hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/thunderbolt/eeprom.c
....@@ -1,11 +1,13 @@
11 // SPDX-License-Identifier: GPL-2.0
22 /*
3
- * Thunderbolt Cactus Ridge driver - eeprom access
3
+ * Thunderbolt driver - eeprom access
44 *
55 * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
6
+ * Copyright (C) 2018, Intel Corporation
67 */
78
89 #include <linux/crc32.h>
10
+#include <linux/delay.h>
911 #include <linux/property.h>
1012 #include <linux/slab.h>
1113 #include "tb.h"
....@@ -130,12 +132,51 @@
130132 }
131133
132134 /**
135
+ * tb_eeprom_get_drom_offset - get drom offset within eeprom
136
+ */
137
+static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset)
138
+{
139
+ struct tb_cap_plug_events cap;
140
+ int res;
141
+
142
+ if (!sw->cap_plug_events) {
143
+ tb_sw_warn(sw, "no TB_CAP_PLUG_EVENTS, cannot read eeprom\n");
144
+ return -ENODEV;
145
+ }
146
+ res = tb_sw_read(sw, &cap, TB_CFG_SWITCH, sw->cap_plug_events,
147
+ sizeof(cap) / 4);
148
+ if (res)
149
+ return res;
150
+
151
+ if (!cap.eeprom_ctl.present || cap.eeprom_ctl.not_present) {
152
+ tb_sw_warn(sw, "no NVM\n");
153
+ return -ENODEV;
154
+ }
155
+
156
+ if (cap.drom_offset > 0xffff) {
157
+ tb_sw_warn(sw, "drom offset is larger than 0xffff: %#x\n",
158
+ cap.drom_offset);
159
+ return -ENXIO;
160
+ }
161
+ *offset = cap.drom_offset;
162
+ return 0;
163
+}
164
+
165
+/**
133166 * tb_eeprom_read_n - read count bytes from offset into val
134167 */
135168 static int tb_eeprom_read_n(struct tb_switch *sw, u16 offset, u8 *val,
136169 size_t count)
137170 {
171
+ u16 drom_offset;
138172 int i, res;
173
+
174
+ res = tb_eeprom_get_drom_offset(sw, &drom_offset);
175
+ if (res)
176
+ return res;
177
+
178
+ offset += drom_offset;
179
+
139180 res = tb_eeprom_active(sw, true);
140181 if (res)
141182 return res;
....@@ -207,7 +248,7 @@
207248
208249 struct tb_drom_entry_generic {
209250 struct tb_drom_entry_header header;
210
- u8 data[0];
251
+ u8 data[];
211252 } __packed;
212253
213254 struct tb_drom_entry_port {
....@@ -238,36 +279,6 @@
238279
239280
240281 /**
241
- * tb_eeprom_get_drom_offset - get drom offset within eeprom
242
- */
243
-static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset)
244
-{
245
- struct tb_cap_plug_events cap;
246
- int res;
247
- if (!sw->cap_plug_events) {
248
- tb_sw_warn(sw, "no TB_CAP_PLUG_EVENTS, cannot read eeprom\n");
249
- return -ENOSYS;
250
- }
251
- res = tb_sw_read(sw, &cap, TB_CFG_SWITCH, sw->cap_plug_events,
252
- sizeof(cap) / 4);
253
- if (res)
254
- return res;
255
-
256
- if (!cap.eeprom_ctl.present || cap.eeprom_ctl.not_present) {
257
- tb_sw_warn(sw, "no NVM\n");
258
- return -ENOSYS;
259
- }
260
-
261
- if (cap.drom_offset > 0xffff) {
262
- tb_sw_warn(sw, "drom offset is larger than 0xffff: %#x\n",
263
- cap.drom_offset);
264
- return -ENXIO;
265
- }
266
- *offset = cap.drom_offset;
267
- return 0;
268
-}
269
-
270
-/**
271282 * tb_drom_read_uid_only - read uid directly from drom
272283 *
273284 * Does not use the cached copy in sw->drom. Used during resume to check switch
....@@ -276,17 +287,11 @@
276287 int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid)
277288 {
278289 u8 data[9];
279
- u16 drom_offset;
280290 u8 crc;
281
- int res = tb_eeprom_get_drom_offset(sw, &drom_offset);
282
- if (res)
283
- return res;
284
-
285
- if (drom_offset == 0)
286
- return -ENODEV;
291
+ int res;
287292
288293 /* read uid */
289
- res = tb_eeprom_read_n(sw, drom_offset, data, 9);
294
+ res = tb_eeprom_read_n(sw, 0, data, 9);
290295 if (res)
291296 return res;
292297
....@@ -385,8 +390,8 @@
385390 struct tb_drom_entry_header *entry = (void *) (sw->drom + pos);
386391 if (pos + 1 == drom_size || pos + entry->len > drom_size
387392 || !entry->len) {
388
- tb_sw_warn(sw, "drom buffer overrun, aborting\n");
389
- return -EIO;
393
+ tb_sw_warn(sw, "DROM buffer overrun\n");
394
+ return -EILSEQ;
390395 }
391396
392397 switch (entry->type) {
....@@ -413,7 +418,7 @@
413418 struct device *dev = &sw->tb->nhi->pdev->dev;
414419 int len, res;
415420
416
- len = device_property_read_u8_array(dev, "ThunderboltDROM", NULL, 0);
421
+ len = device_property_count_u8(dev, "ThunderboltDROM");
417422 if (len < 0 || len < sizeof(struct tb_drom_header))
418423 return -EINVAL;
419424
....@@ -483,16 +488,47 @@
483488 return ret;
484489 }
485490
491
+static int usb4_copy_host_drom(struct tb_switch *sw, u16 *size)
492
+{
493
+ int ret;
494
+
495
+ ret = usb4_switch_drom_read(sw, 14, size, sizeof(*size));
496
+ if (ret)
497
+ return ret;
498
+
499
+ /* Size includes CRC8 + UID + CRC32 */
500
+ *size += 1 + 8 + 4;
501
+ sw->drom = kzalloc(*size, GFP_KERNEL);
502
+ if (!sw->drom)
503
+ return -ENOMEM;
504
+
505
+ ret = usb4_switch_drom_read(sw, 0, sw->drom, *size);
506
+ if (ret) {
507
+ kfree(sw->drom);
508
+ sw->drom = NULL;
509
+ }
510
+
511
+ return ret;
512
+}
513
+
514
+static int tb_drom_read_n(struct tb_switch *sw, u16 offset, u8 *val,
515
+ size_t count)
516
+{
517
+ if (tb_switch_is_usb4(sw))
518
+ return usb4_switch_drom_read(sw, offset, val, count);
519
+ return tb_eeprom_read_n(sw, offset, val, count);
520
+}
521
+
486522 /**
487523 * tb_drom_read - copy drom to sw->drom and parse it
488524 */
489525 int tb_drom_read(struct tb_switch *sw)
490526 {
491
- u16 drom_offset;
492527 u16 size;
493528 u32 crc;
494529 struct tb_drom_header *header;
495
- int res;
530
+ int res, retries = 1;
531
+
496532 if (sw->drom)
497533 return 0;
498534
....@@ -509,38 +545,31 @@
509545 goto parse;
510546
511547 /*
512
- * The root switch contains only a dummy drom (header only,
513
- * no entries). Hardcode the configuration here.
548
+ * USB4 hosts may support reading DROM through router
549
+ * operations.
514550 */
515
- tb_drom_read_uid_only(sw, &sw->uid);
516
-
517
- sw->ports[1].link_nr = 0;
518
- sw->ports[2].link_nr = 1;
519
- sw->ports[1].dual_link_port = &sw->ports[2];
520
- sw->ports[2].dual_link_port = &sw->ports[1];
521
-
522
- sw->ports[3].link_nr = 0;
523
- sw->ports[4].link_nr = 1;
524
- sw->ports[3].dual_link_port = &sw->ports[4];
525
- sw->ports[4].dual_link_port = &sw->ports[3];
526
-
527
- /* Port 5 is inaccessible on this gen 1 controller */
528
- if (sw->config.device_id == PCI_DEVICE_ID_INTEL_LIGHT_RIDGE)
529
- sw->ports[5].disabled = true;
551
+ if (tb_switch_is_usb4(sw)) {
552
+ usb4_switch_read_uid(sw, &sw->uid);
553
+ if (!usb4_copy_host_drom(sw, &size))
554
+ goto parse;
555
+ } else {
556
+ /*
557
+ * The root switch contains only a dummy drom
558
+ * (header only, no entries). Hardcode the
559
+ * configuration here.
560
+ */
561
+ tb_drom_read_uid_only(sw, &sw->uid);
562
+ }
530563
531564 return 0;
532565 }
533566
534
- res = tb_eeprom_get_drom_offset(sw, &drom_offset);
535
- if (res)
536
- return res;
537
-
538
- res = tb_eeprom_read_n(sw, drom_offset + 14, (u8 *) &size, 2);
567
+ res = tb_drom_read_n(sw, 14, (u8 *) &size, 2);
539568 if (res)
540569 return res;
541570 size &= 0x3ff;
542571 size += TB_DROM_DATA_START;
543
- tb_sw_info(sw, "reading drom (length: %#x)\n", size);
572
+ tb_sw_dbg(sw, "reading drom (length: %#x)\n", size);
544573 if (size < sizeof(*header)) {
545574 tb_sw_warn(sw, "drom too small, aborting\n");
546575 return -EIO;
....@@ -549,7 +578,7 @@
549578 sw->drom = kzalloc(size, GFP_KERNEL);
550579 if (!sw->drom)
551580 return -ENOMEM;
552
- res = tb_eeprom_read_n(sw, drom_offset, sw->drom, size);
581
+ res = tb_drom_read_n(sw, 0, sw->drom, size);
553582 if (res)
554583 goto err;
555584
....@@ -572,6 +601,7 @@
572601 sw->uid = header->uid;
573602 sw->vendor = header->vendor_id;
574603 sw->device = header->model_id;
604
+ tb_check_quirks(sw);
575605
576606 crc = tb_crc32(sw->drom + TB_DROM_DATA_START, header->data_len);
577607 if (crc != header->data_crc32) {
....@@ -584,7 +614,17 @@
584614 tb_sw_warn(sw, "drom device_rom_revision %#x unknown\n",
585615 header->device_rom_revision);
586616
587
- return tb_drom_parse_entries(sw);
617
+ res = tb_drom_parse_entries(sw);
618
+ /* If the DROM parsing fails, wait a moment and retry once */
619
+ if (res == -EILSEQ && retries--) {
620
+ tb_sw_warn(sw, "parsing DROM failed, retrying\n");
621
+ msleep(100);
622
+ res = tb_drom_read_n(sw, 0, sw->drom, size);
623
+ if (!res)
624
+ goto parse;
625
+ }
626
+
627
+ return res;
588628 err:
589629 kfree(sw->drom);
590630 sw->drom = NULL;