Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Lukas Wunner and committed by
Bjorn Helgaas
19bf4d4f aae20bb6

+44 -4
+28 -1
drivers/pci/quirks.c
··· 3185 3185 DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, PCI_ANY_ID, 3186 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 + */ 3193 + static 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 + } 3200 + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE, 3201 + quirk_thunderbolt_hotplug_msi); 3202 + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE, 3203 + quirk_thunderbolt_hotplug_msi); 3204 + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK, 3205 + quirk_thunderbolt_hotplug_msi); 3206 + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, 3207 + quirk_thunderbolt_hotplug_msi); 3208 + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE, 3209 + quirk_thunderbolt_hotplug_msi); 3210 + 3188 3211 #ifdef CONFIG_ACPI 3189 3212 /* 3190 3213 * Apple: Shutdown Cactus Ridge Thunderbolt controller. ··· 3290 3267 if (!nhi) 3291 3268 goto out; 3292 3269 if (nhi->vendor != PCI_VENDOR_ID_INTEL 3293 - || (nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && 3270 + || (nhi->device != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE && 3271 + nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && 3294 3272 nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI) 3295 3273 || nhi->subsystem_vendor != 0x2222 3296 3274 || nhi->subsystem_device != 0x1111) ··· 3302 3278 pci_dev_put(nhi); 3303 3279 pci_dev_put(sibling); 3304 3280 } 3281 + DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 3282 + PCI_DEVICE_ID_INTEL_LIGHT_RIDGE, 3283 + quirk_apple_wait_for_thunderbolt); 3305 3284 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 3306 3285 PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, 3307 3286 quirk_apple_wait_for_thunderbolt);
+5
drivers/thunderbolt/eeprom.c
··· 388 388 sw->ports[4].link_nr = 1; 389 389 sw->ports[3].dual_link_port = &sw->ports[4]; 390 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 396 return 0; 392 397 } 393 398
+9 -2
drivers/thunderbolt/nhi.c
··· 37 37 */ 38 38 static 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 42 int bit = ring_interrupt_index(ring) & 31; 42 43 int mask = 1 << bit; 43 44 u32 old, new; ··· 565 564 /* cannot fail - table is allocated bin pcim_iomap_regions */ 566 565 nhi->iobase = pcim_iomap_table(pdev)[0]; 567 566 nhi->hop_count = ioread32(nhi->iobase + REG_HOP_COUNT) & 0x3ff; 568 - if (nhi->hop_count != 12) 567 + if (nhi->hop_count != 12 && nhi->hop_count != 32) 569 568 dev_warn(&pdev->dev, "unexpected hop count: %d\n", 570 569 nhi->hop_count); 571 570 INIT_WORK(&nhi->interrupt_work, nhi_interrupt_work); ··· 636 635 * We have to specify class, the TB bridges use the same device and 637 636 * vendor (sub)id on gen 1 and gen 2 controllers. 638 637 */ 638 + { 639 + .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0, 640 + .vendor = PCI_VENDOR_ID_INTEL, 641 + .device = PCI_DEVICE_ID_INTEL_LIGHT_RIDGE, 642 + .subvendor = 0x2222, .subdevice = 0x1111, 643 + }, 639 644 { 640 645 .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0, 641 646 .vendor = PCI_VENDOR_ID_INTEL,
+2 -1
drivers/thunderbolt/switch.c
··· 370 370 tb_sw_warn(sw, "unknown switch vendor id %#x\n", 371 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 375 sw->config.device_id != PCI_DEVICE_ID_INTEL_PORT_RIDGE) 375 376 tb_sw_warn(sw, "unsupported switch device id %#x\n", 376 377 sw->config.device_id);