aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Wunner <lukas@wunner.de>2016-03-20 08:57:20 -0400
committerBjorn Helgaas <bhelgaas@google.com>2016-04-08 12:13:40 -0400
commit19bf4d4f909d644110cb587545dc385044ac90a4 (patch)
treefcf7e36fc22edf2914f39ec9bd183687c75914c6
parentaae20bb6b45e0666c63506053c40f71c0c34cba0 (diff)
thunderbolt: Support 1st gen Light Ridge controller
Add support for the 1st gen Light Ridge controller, which is built into these systems: iMac12,1 2011 21.5" iMac12,2 2011 27" Macmini5,1 2011 i5 2.3 GHz Macmini5,2 2011 i5 2.5 GHz Macmini5,3 2011 i7 2.0 GHz MacBookPro8,1 2011 13" MacBookPro8,2 2011 15" MacBookPro8,3 2011 17" MacBookPro9,1 2012 15" MacBookPro9,2 2012 13" Light Ridge (CV82524) was the very first copper Thunderbolt controller, introduced 2010 alongside its fiber-optic cousin Light Peak (CVL2510). Consequently the chip suffers from some teething troubles: - MSI is broken for hotplug signaling on the downstream bridges: The chip just never sends an interrupt. It requests 32 MSIs for each of its six bridges and the pcieport driver only allocates one per bridge. However I've verified that even if 32 MSIs are allocated there's no interrupt on hotplug. The only option is thus to disable MSI, which is also what OS X does. Apparently all Thunderbolt chips up to revision 1 of Cactus Ridge 4C are plagued by this issue so quirk those as well. - The chip supports a maximum hop_count of 32, unlike its successors which support only 12. Fixup ring_interrupt_active() to cope with values >= 32. - Another peculiarity is that the chip supports a maximum of 13 ports whereas its successors support 12. However the additional port (#5) seems to be unusable as reading its TB_CFG_PORT config space results in TB_CFG_ERROR_INVALID_CONFIG_SPACE. Add a quirk to mark the port disabled on the root switch, assuming that's necessary on all Macs using this chip. Tested-by: Lukas Wunner <lukas@wunner.de> [MacBookPro9,1] Tested-by: William Brown <william@blackhats.net.au> [MacBookPro8,2] Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Andreas Noever <andreas.noever@gmail.com>
-rw-r--r--drivers/pci/quirks.c29
-rw-r--r--drivers/thunderbolt/eeprom.c5
-rw-r--r--drivers/thunderbolt/nhi.c11
-rw-r--r--drivers/thunderbolt/switch.c3
4 files changed, 44 insertions, 4 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index b584ddf83555..b1ff270622dd 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3185,6 +3185,29 @@ static void quirk_no_pm_reset(struct pci_dev *dev)
3185DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, PCI_ANY_ID, 3185DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
3186 PCI_CLASS_DISPLAY_VGA, 8, quirk_no_pm_reset); 3186 PCI_CLASS_DISPLAY_VGA, 8, quirk_no_pm_reset);
3187 3187
3188/*
3189 * Thunderbolt controllers with broken MSI hotplug signaling:
3190 * Entire 1st generation (Light Ridge, Eagle Ridge, Light Peak) and part
3191 * of the 2nd generation (Cactus Ridge 4C up to revision 1, Port Ridge).
3192 */
3193static void quirk_thunderbolt_hotplug_msi(struct pci_dev *pdev)
3194{
3195 if (pdev->is_hotplug_bridge &&
3196 (pdev->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C ||
3197 pdev->revision <= 1))
3198 pdev->no_msi = 1;
3199}
3200DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
3201 quirk_thunderbolt_hotplug_msi);
3202DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE,
3203 quirk_thunderbolt_hotplug_msi);
3204DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK,
3205 quirk_thunderbolt_hotplug_msi);
3206DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
3207 quirk_thunderbolt_hotplug_msi);
3208DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
3209 quirk_thunderbolt_hotplug_msi);
3210
3188#ifdef CONFIG_ACPI 3211#ifdef CONFIG_ACPI
3189/* 3212/*
3190 * Apple: Shutdown Cactus Ridge Thunderbolt controller. 3213 * Apple: Shutdown Cactus Ridge Thunderbolt controller.
@@ -3267,7 +3290,8 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
3267 if (!nhi) 3290 if (!nhi)
3268 goto out; 3291 goto out;
3269 if (nhi->vendor != PCI_VENDOR_ID_INTEL 3292 if (nhi->vendor != PCI_VENDOR_ID_INTEL
3270 || (nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && 3293 || (nhi->device != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE &&
3294 nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
3271 nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI) 3295 nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI)
3272 || nhi->subsystem_vendor != 0x2222 3296 || nhi->subsystem_vendor != 0x2222
3273 || nhi->subsystem_device != 0x1111) 3297 || nhi->subsystem_device != 0x1111)
@@ -3279,6 +3303,9 @@ out:
3279 pci_dev_put(sibling); 3303 pci_dev_put(sibling);
3280} 3304}
3281DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 3305DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
3306 PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
3307 quirk_apple_wait_for_thunderbolt);
3308DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
3282 PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, 3309 PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
3283 quirk_apple_wait_for_thunderbolt); 3310 quirk_apple_wait_for_thunderbolt);
3284DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 3311DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 47e56e861d61..0c052e25c5bc 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -388,6 +388,11 @@ int tb_drom_read(struct tb_switch *sw)
388 sw->ports[4].link_nr = 1; 388 sw->ports[4].link_nr = 1;
389 sw->ports[3].dual_link_port = &sw->ports[4]; 389 sw->ports[3].dual_link_port = &sw->ports[4];
390 sw->ports[4].dual_link_port = &sw->ports[3]; 390 sw->ports[4].dual_link_port = &sw->ports[3];
391
392 /* Port 5 is inaccessible on this gen 1 controller */
393 if (sw->config.device_id == PCI_DEVICE_ID_INTEL_LIGHT_RIDGE)
394 sw->ports[5].disabled = true;
395
391 return 0; 396 return 0;
392 } 397 }
393 398
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index 36be23babb89..9c15344b657a 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -37,7 +37,8 @@ static int ring_interrupt_index(struct tb_ring *ring)
37 */ 37 */
38static void ring_interrupt_active(struct tb_ring *ring, bool active) 38static void ring_interrupt_active(struct tb_ring *ring, bool active)
39{ 39{
40 int reg = REG_RING_INTERRUPT_BASE + ring_interrupt_index(ring) / 32; 40 int reg = REG_RING_INTERRUPT_BASE +
41 ring_interrupt_index(ring) / 32 * 4;
41 int bit = ring_interrupt_index(ring) & 31; 42 int bit = ring_interrupt_index(ring) & 31;
42 int mask = 1 << bit; 43 int mask = 1 << bit;
43 u32 old, new; 44 u32 old, new;
@@ -564,7 +565,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
564 /* cannot fail - table is allocated bin pcim_iomap_regions */ 565 /* cannot fail - table is allocated bin pcim_iomap_regions */
565 nhi->iobase = pcim_iomap_table(pdev)[0]; 566 nhi->iobase = pcim_iomap_table(pdev)[0];
566 nhi->hop_count = ioread32(nhi->iobase + REG_HOP_COUNT) & 0x3ff; 567 nhi->hop_count = ioread32(nhi->iobase + REG_HOP_COUNT) & 0x3ff;
567 if (nhi->hop_count != 12) 568 if (nhi->hop_count != 12 && nhi->hop_count != 32)
568 dev_warn(&pdev->dev, "unexpected hop count: %d\n", 569 dev_warn(&pdev->dev, "unexpected hop count: %d\n",
569 nhi->hop_count); 570 nhi->hop_count);
570 INIT_WORK(&nhi->interrupt_work, nhi_interrupt_work); 571 INIT_WORK(&nhi->interrupt_work, nhi_interrupt_work);
@@ -638,6 +639,12 @@ static struct pci_device_id nhi_ids[] = {
638 { 639 {
639 .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0, 640 .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
640 .vendor = PCI_VENDOR_ID_INTEL, 641 .vendor = PCI_VENDOR_ID_INTEL,
642 .device = PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
643 .subvendor = 0x2222, .subdevice = 0x1111,
644 },
645 {
646 .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
647 .vendor = PCI_VENDOR_ID_INTEL,
641 .device = PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, 648 .device = PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
642 .subvendor = 0x2222, .subdevice = 0x1111, 649 .subvendor = 0x2222, .subdevice = 0x1111,
643 }, 650 },
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index c6270f0bd5c5..1e116f53d6dd 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -370,7 +370,8 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route)
370 tb_sw_warn(sw, "unknown switch vendor id %#x\n", 370 tb_sw_warn(sw, "unknown switch vendor id %#x\n",
371 sw->config.vendor_id); 371 sw->config.vendor_id);
372 372
373 if (sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && 373 if (sw->config.device_id != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE &&
374 sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
374 sw->config.device_id != PCI_DEVICE_ID_INTEL_PORT_RIDGE) 375 sw->config.device_id != PCI_DEVICE_ID_INTEL_PORT_RIDGE)
375 tb_sw_warn(sw, "unsupported switch device id %#x\n", 376 tb_sw_warn(sw, "unsupported switch device id %#x\n",
376 sw->config.device_id); 377 sw->config.device_id);