Gen 1 and 2 chips use the same ID for NHI, bridges and switch.
Gen 3 chips and onward use a distinct ID for the NHI.
No functional change intended.
Cc: Andreas Noever <[email protected]>
Signed-off-by: Lukas Wunner <[email protected]>
Acked-by: Bjorn Helgaas <[email protected]>
---
drivers/pci/quirks.c | 16 ++++++++++------
drivers/thunderbolt/nhi.c | 8 +++++---
drivers/thunderbolt/switch.c | 9 +++++----
include/linux/pci_ids.h | 18 ++++++++++++++++++
4 files changed, 38 insertions(+), 13 deletions(-)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 8e67802..b584ddf 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3232,7 +3232,8 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev)
acpi_execute_simple_method(SXIO, NULL, 0);
acpi_execute_simple_method(SXLV, NULL, 0);
}
-DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL, 0x1547,
+DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
quirk_apple_poweroff_thunderbolt);
/*
@@ -3266,9 +3267,10 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
if (!nhi)
goto out;
if (nhi->vendor != PCI_VENDOR_ID_INTEL
- || (nhi->device != 0x1547 && nhi->device != 0x156c)
- || nhi->subsystem_vendor != 0x2222
- || nhi->subsystem_device != 0x1111)
+ || (nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
+ nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI)
+ || nhi->subsystem_vendor != 0x2222
+ || nhi->subsystem_device != 0x1111)
goto out;
dev_info(&dev->dev, "quirk: waiting for thunderbolt to reestablish PCI tunnels...\n");
device_pm_wait_for_dev(&dev->dev, &nhi->dev);
@@ -3276,9 +3278,11 @@ out:
pci_dev_put(nhi);
pci_dev_put(sibling);
}
-DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x1547,
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
quirk_apple_wait_for_thunderbolt);
-DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x156d,
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE,
quirk_apple_wait_for_thunderbolt);
#endif
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index 20a41f7..36be23b 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -633,16 +633,18 @@ static const struct dev_pm_ops nhi_pm_ops = {
static struct pci_device_id nhi_ids[] = {
/*
* We have to specify class, the TB bridges use the same device and
- * vendor (sub)id.
+ * vendor (sub)id on gen 1 and gen 2 controllers.
*/
{
.class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
- .vendor = PCI_VENDOR_ID_INTEL, .device = 0x1547,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
.subvendor = 0x2222, .subdevice = 0x1111,
},
{
.class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
- .vendor = PCI_VENDOR_ID_INTEL, .device = 0x156c,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI,
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
},
{ 0,}
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index aeb9829..db73ffe 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -293,9 +293,9 @@ static int tb_plug_events_active(struct tb_switch *sw, bool active)
if (active) {
data = data & 0xFFFFFF83;
switch (sw->config.device_id) {
- case 0x1513:
- case 0x151a:
- case 0x1549:
+ case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE:
+ case PCI_DEVICE_ID_INTEL_EAGLE_RIDGE:
+ case PCI_DEVICE_ID_INTEL_PORT_RIDGE:
break;
default:
data |= 4;
@@ -370,7 +370,8 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route)
tb_sw_warn(sw, "unknown switch vendor id %#x\n",
sw->config.vendor_id);
- if (sw->config.device_id != 0x1547 && sw->config.device_id != 0x1549)
+ if (sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
+ sw->config.device_id != PCI_DEVICE_ID_INTEL_PORT_RIDGE)
tb_sw_warn(sw, "unsupported switch device id %#x\n",
sw->config.device_id);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 247da8c..c58752f 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2604,6 +2604,24 @@
#define PCI_DEVICE_ID_INTEL_82441 0x1237
#define PCI_DEVICE_ID_INTEL_82380FB 0x124b
#define PCI_DEVICE_ID_INTEL_82439 0x1250
+#define PCI_DEVICE_ID_INTEL_LIGHT_RIDGE 0x1513 /* Tbt 1 Gen 1 */
+#define PCI_DEVICE_ID_INTEL_EAGLE_RIDGE 0x151a
+#define PCI_DEVICE_ID_INTEL_LIGHT_PEAK 0x151b
+#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C 0x1547 /* Tbt 1 Gen 2 */
+#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C 0x1548
+#define PCI_DEVICE_ID_INTEL_PORT_RIDGE 0x1549
+#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI 0x1566 /* Tbt 1 Gen 3 */
+#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE 0x1567
+#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI 0x1568
+#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE 0x1569
+#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI 0x156a /* Thunderbolt 2 */
+#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE 0x156b
+#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI 0x156c
+#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE 0x156d
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI 0x1575 /* Thunderbolt 3 */
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE 0x1576
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI 0x1577
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE 0x1578
#define PCI_DEVICE_ID_INTEL_80960_RP 0x1960
#define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21
#define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30
--
2.8.0.rc3
Fix typo in tb_cfg_print_error() message.
Fix bytecount in struct tb_drom_entry_port comment.
Replace magic number in tb_switch_alloc().
Rename tb_sw_set_unpplugged() and TB_CAL_IECS.
^ ^
Cc: Andreas Noever <[email protected]>
Signed-off-by: Lukas Wunner <[email protected]>
---
drivers/thunderbolt/ctl.c | 2 +-
drivers/thunderbolt/eeprom.c | 2 +-
drivers/thunderbolt/switch.c | 10 +++++-----
drivers/thunderbolt/tb.c | 2 +-
drivers/thunderbolt/tb.h | 2 +-
drivers/thunderbolt/tb_regs.h | 2 +-
6 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c
index 799634b..1146ff4 100644
--- a/drivers/thunderbolt/ctl.c
+++ b/drivers/thunderbolt/ctl.c
@@ -249,7 +249,7 @@ static void tb_cfg_print_error(struct tb_ctl *ctl,
* cfg_read/cfg_write.
*/
tb_ctl_WARN(ctl,
- "CFG_ERROR(%llx:%x): Invalid config space of offset\n",
+ "CFG_ERROR(%llx:%x): Invalid config space or offset\n",
res->response_route, res->response_port);
return;
case TB_CFG_ERROR_NO_SUCH_PORT:
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 0dde34e..47e56e8 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -221,7 +221,7 @@ struct tb_drom_entry_port {
u8 micro1:4;
u8 micro3;
- /* BYTES 5-6, TODO: verify (find hardware that has these set) */
+ /* BYTES 6-7, TODO: verify (find hardware that has these set) */
u8 peer_port_rid:4;
u8 unknown3:3;
bool has_peer_port:1;
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index db73ffe..c6270f0 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -350,7 +350,7 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route)
return NULL;
sw->tb = tb;
- if (tb_cfg_read(tb->ctl, &sw->config, route, 0, 2, 0, 5))
+ if (tb_cfg_read(tb->ctl, &sw->config, route, 0, TB_CFG_SWITCH, 0, 5))
goto err;
tb_info(tb,
"initializing Switch at %#llx (depth: %d, up port: %d)\n",
@@ -426,9 +426,9 @@ err:
}
/**
- * tb_sw_set_unpplugged() - set is_unplugged on switch and downstream switches
+ * tb_sw_set_unplugged() - set is_unplugged on switch and downstream switches
*/
-void tb_sw_set_unpplugged(struct tb_switch *sw)
+void tb_sw_set_unplugged(struct tb_switch *sw)
{
int i;
if (sw == sw->tb->root_switch) {
@@ -442,7 +442,7 @@ void tb_sw_set_unpplugged(struct tb_switch *sw)
sw->is_unplugged = true;
for (i = 0; i <= sw->config.max_port_number; i++) {
if (!tb_is_upstream_port(&sw->ports[i]) && sw->ports[i].remote)
- tb_sw_set_unpplugged(sw->ports[i].remote->sw);
+ tb_sw_set_unplugged(sw->ports[i].remote->sw);
}
}
@@ -484,7 +484,7 @@ int tb_switch_resume(struct tb_switch *sw)
|| tb_switch_resume(port->remote->sw)) {
tb_port_warn(port,
"lost during suspend, disconnecting\n");
- tb_sw_set_unpplugged(port->remote->sw);
+ tb_sw_set_unplugged(port->remote->sw);
}
}
return 0;
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index d2c3fe3..24b6d30 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -246,7 +246,7 @@ static void tb_handle_hotplug(struct work_struct *work)
if (ev->unplug) {
if (port->remote) {
tb_port_info(port, "unplugged\n");
- tb_sw_set_unpplugged(port->remote->sw);
+ tb_sw_set_unplugged(port->remote->sw);
tb_free_invalid_tunnels(tb);
tb_switch_free(port->remote->sw);
port->remote = NULL;
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 8b0d7cf..61d57ba 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -226,7 +226,7 @@ void tb_switch_free(struct tb_switch *sw);
void tb_switch_suspend(struct tb_switch *sw);
int tb_switch_resume(struct tb_switch *sw);
int tb_switch_reset(struct tb *tb, u64 route);
-void tb_sw_set_unpplugged(struct tb_switch *sw);
+void tb_sw_set_unplugged(struct tb_switch *sw);
struct tb_switch *get_switch_at_route(struct tb_switch *sw, u64 route);
int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged);
diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h
index 6577af7..1e2a4a8 100644
--- a/drivers/thunderbolt/tb_regs.h
+++ b/drivers/thunderbolt/tb_regs.h
@@ -30,7 +30,7 @@ enum tb_cap {
TB_CAP_I2C = 0x0005,
TB_CAP_PLUG_EVENTS = 0x0105, /* also EEPROM */
TB_CAP_TIME2 = 0x0305,
- TB_CAL_IECS = 0x0405,
+ TB_CAP_IECS = 0x0405,
TB_CAP_LINK_CONTROLLER = 0x0605, /* also IECS */
};
--
2.8.0.rc3
Built into:
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.
Cc: Andreas Noever <[email protected]>
Tested-by: Lukas Wunner <[email protected]> [MacBookPro9,1]
Tested-by: William Brown <[email protected]> [MacBookPro8,2]
Signed-off-by: Lukas Wunner <[email protected]>
---
drivers/pci/quirks.c | 29 ++++++++++++++++++++++++++++-
drivers/thunderbolt/eeprom.c | 5 +++++
drivers/thunderbolt/nhi.c | 11 +++++++++--
drivers/thunderbolt/switch.c | 3 ++-
4 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index b584ddf..b1ff270 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)
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
PCI_CLASS_DISPLAY_VGA, 8, quirk_no_pm_reset);
+/*
+ * Thunderbolt controllers with broken MSI hotplug signaling:
+ * Entire 1st generation (Light Ridge, Eagle Ridge, Light Peak) and part
+ * of the 2nd generation (Cactus Ridge 4C up to revision 1, Port Ridge).
+ */
+static void quirk_thunderbolt_hotplug_msi(struct pci_dev *pdev)
+{
+ if (pdev->is_hotplug_bridge &&
+ (pdev->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C ||
+ pdev->revision <= 1))
+ pdev->no_msi = 1;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
+ quirk_thunderbolt_hotplug_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE,
+ quirk_thunderbolt_hotplug_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK,
+ quirk_thunderbolt_hotplug_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
+ quirk_thunderbolt_hotplug_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
+ quirk_thunderbolt_hotplug_msi);
+
#ifdef CONFIG_ACPI
/*
* Apple: Shutdown Cactus Ridge Thunderbolt controller.
@@ -3267,7 +3290,8 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
if (!nhi)
goto out;
if (nhi->vendor != PCI_VENDOR_ID_INTEL
- || (nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
+ || (nhi->device != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE &&
+ nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI)
|| nhi->subsystem_vendor != 0x2222
|| nhi->subsystem_device != 0x1111)
@@ -3279,6 +3303,9 @@ out:
pci_dev_put(sibling);
}
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
+ quirk_apple_wait_for_thunderbolt);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
quirk_apple_wait_for_thunderbolt);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 47e56e8..0c052e2 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -388,6 +388,11 @@ int tb_drom_read(struct tb_switch *sw)
sw->ports[4].link_nr = 1;
sw->ports[3].dual_link_port = &sw->ports[4];
sw->ports[4].dual_link_port = &sw->ports[3];
+
+ /* Port 5 is inaccessible on this gen 1 controller */
+ if (sw->config.device_id == PCI_DEVICE_ID_INTEL_LIGHT_RIDGE)
+ sw->ports[5].disabled = true;
+
return 0;
}
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index 36be23b..9c15344 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -37,7 +37,8 @@ static int ring_interrupt_index(struct tb_ring *ring)
*/
static void ring_interrupt_active(struct tb_ring *ring, bool active)
{
- int reg = REG_RING_INTERRUPT_BASE + ring_interrupt_index(ring) / 32;
+ int reg = REG_RING_INTERRUPT_BASE +
+ ring_interrupt_index(ring) / 32 * 4;
int bit = ring_interrupt_index(ring) & 31;
int mask = 1 << bit;
u32 old, new;
@@ -564,7 +565,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* cannot fail - table is allocated bin pcim_iomap_regions */
nhi->iobase = pcim_iomap_table(pdev)[0];
nhi->hop_count = ioread32(nhi->iobase + REG_HOP_COUNT) & 0x3ff;
- if (nhi->hop_count != 12)
+ if (nhi->hop_count != 12 && nhi->hop_count != 32)
dev_warn(&pdev->dev, "unexpected hop count: %d\n",
nhi->hop_count);
INIT_WORK(&nhi->interrupt_work, nhi_interrupt_work);
@@ -638,6 +639,12 @@ static struct pci_device_id nhi_ids[] = {
{
.class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
.vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
+ .subvendor = 0x2222, .subdevice = 0x1111,
+ },
+ {
+ .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
.subvendor = 0x2222, .subdevice = 0x1111,
},
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index c6270f0..1e116f5 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)
tb_sw_warn(sw, "unknown switch vendor id %#x\n",
sw->config.vendor_id);
- if (sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
+ if (sw->config.device_id != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE &&
+ sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
sw->config.device_id != PCI_DEVICE_ID_INTEL_PORT_RIDGE)
tb_sw_warn(sw, "unsupported switch device id %#x\n",
sw->config.device_id);
--
2.8.0.rc3
On Sun, Mar 20, 2016 at 1:57 PM, Lukas Wunner <[email protected]> wrote:
> Built into:
> 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.
>
> Cc: Andreas Noever <[email protected]>
> Tested-by: Lukas Wunner <[email protected]> [MacBookPro9,1]
> Tested-by: William Brown <[email protected]> [MacBookPro8,2]
> Signed-off-by: Lukas Wunner <[email protected]>
> ---
> drivers/pci/quirks.c | 29 ++++++++++++++++++++++++++++-
> drivers/thunderbolt/eeprom.c | 5 +++++
> drivers/thunderbolt/nhi.c | 11 +++++++++--
> drivers/thunderbolt/switch.c | 3 ++-
> 4 files changed, 44 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index b584ddf..b1ff270 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)
> DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
> PCI_CLASS_DISPLAY_VGA, 8, quirk_no_pm_reset);
>
> +/*
> + * Thunderbolt controllers with broken MSI hotplug signaling:
> + * Entire 1st generation (Light Ridge, Eagle Ridge, Light Peak) and part
> + * of the 2nd generation (Cactus Ridge 4C up to revision 1, Port Ridge).
> + */
> +static void quirk_thunderbolt_hotplug_msi(struct pci_dev *pdev)
> +{
> + if (pdev->is_hotplug_bridge &&
> + (pdev->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C ||
> + pdev->revision <= 1))
> + pdev->no_msi = 1;
> +}
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
> + quirk_thunderbolt_hotplug_msi);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE,
> + quirk_thunderbolt_hotplug_msi);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK,
> + quirk_thunderbolt_hotplug_msi);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
> + quirk_thunderbolt_hotplug_msi);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
> + quirk_thunderbolt_hotplug_msi);
> +
> #ifdef CONFIG_ACPI
> /*
> * Apple: Shutdown Cactus Ridge Thunderbolt controller.
> @@ -3267,7 +3290,8 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
> if (!nhi)
> goto out;
> if (nhi->vendor != PCI_VENDOR_ID_INTEL
> - || (nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
> + || (nhi->device != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE &&
> + nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
> nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI)
> || nhi->subsystem_vendor != 0x2222
> || nhi->subsystem_device != 0x1111)
> @@ -3279,6 +3303,9 @@ out:
> pci_dev_put(sibling);
> }
> DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
> + PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
> + quirk_apple_wait_for_thunderbolt);
> +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
> PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
> quirk_apple_wait_for_thunderbolt);
> DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
> diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
> index 47e56e8..0c052e2 100644
> --- a/drivers/thunderbolt/eeprom.c
> +++ b/drivers/thunderbolt/eeprom.c
> @@ -388,6 +388,11 @@ int tb_drom_read(struct tb_switch *sw)
> sw->ports[4].link_nr = 1;
> sw->ports[3].dual_link_port = &sw->ports[4];
> sw->ports[4].dual_link_port = &sw->ports[3];
> +
> + /* Port 5 is inaccessible on this gen 1 controller */
> + if (sw->config.device_id == PCI_DEVICE_ID_INTEL_LIGHT_RIDGE)
> + sw->ports[5].disabled = true;
> +
> return 0;
> }
>
> diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
> index 36be23b..9c15344 100644
> --- a/drivers/thunderbolt/nhi.c
> +++ b/drivers/thunderbolt/nhi.c
> @@ -37,7 +37,8 @@ static int ring_interrupt_index(struct tb_ring *ring)
> */
> static void ring_interrupt_active(struct tb_ring *ring, bool active)
> {
> - int reg = REG_RING_INTERRUPT_BASE + ring_interrupt_index(ring) / 32;
> + int reg = REG_RING_INTERRUPT_BASE +
> + ring_interrupt_index(ring) / 32 * 4;
> int bit = ring_interrupt_index(ring) & 31;
> int mask = 1 << bit;
> u32 old, new;
> @@ -564,7 +565,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> /* cannot fail - table is allocated bin pcim_iomap_regions */
> nhi->iobase = pcim_iomap_table(pdev)[0];
> nhi->hop_count = ioread32(nhi->iobase + REG_HOP_COUNT) & 0x3ff;
> - if (nhi->hop_count != 12)
> + if (nhi->hop_count != 12 && nhi->hop_count != 32)
> dev_warn(&pdev->dev, "unexpected hop count: %d\n",
> nhi->hop_count);
> INIT_WORK(&nhi->interrupt_work, nhi_interrupt_work);
> @@ -638,6 +639,12 @@ static struct pci_device_id nhi_ids[] = {
> {
> .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
> .vendor = PCI_VENDOR_ID_INTEL,
> + .device = PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
> + .subvendor = 0x2222, .subdevice = 0x1111,
> + },
> + {
> + .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
> + .vendor = PCI_VENDOR_ID_INTEL,
> .device = PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
> .subvendor = 0x2222, .subdevice = 0x1111,
> },
> diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
> index c6270f0..1e116f5 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)
> tb_sw_warn(sw, "unknown switch vendor id %#x\n",
> sw->config.vendor_id);
>
> - if (sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
> + if (sw->config.device_id != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE &&
> + sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
> sw->config.device_id != PCI_DEVICE_ID_INTEL_PORT_RIDGE)
> tb_sw_warn(sw, "unsupported switch device id %#x\n",
> sw->config.device_id);
> --
> 2.8.0.rc3
>
Acked-by: Andreas Noever <[email protected]>
(Whole series)
Nice Work!
[+cc Greg]
On Sun, Mar 20, 2016 at 01:57:20PM +0100, Lukas Wunner wrote:
> Gen 1 and 2 chips use the same ID for NHI, bridges and switch.
> Gen 3 chips and onward use a distinct ID for the NHI.
>
> No functional change intended.
>
> Cc: Andreas Noever <[email protected]>
> Signed-off-by: Lukas Wunner <[email protected]>
> Acked-by: Bjorn Helgaas <[email protected]>
All three patches applied with Andreas' ack to pci/thunderbolt for v4.7,
thanks!
> ---
> drivers/pci/quirks.c | 16 ++++++++++------
> drivers/thunderbolt/nhi.c | 8 +++++---
> drivers/thunderbolt/switch.c | 9 +++++----
> include/linux/pci_ids.h | 18 ++++++++++++++++++
> 4 files changed, 38 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index 8e67802..b584ddf 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -3232,7 +3232,8 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev)
> acpi_execute_simple_method(SXIO, NULL, 0);
> acpi_execute_simple_method(SXLV, NULL, 0);
> }
> -DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL, 0x1547,
> +DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL,
> + PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
> quirk_apple_poweroff_thunderbolt);
>
> /*
> @@ -3266,9 +3267,10 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
> if (!nhi)
> goto out;
> if (nhi->vendor != PCI_VENDOR_ID_INTEL
> - || (nhi->device != 0x1547 && nhi->device != 0x156c)
> - || nhi->subsystem_vendor != 0x2222
> - || nhi->subsystem_device != 0x1111)
> + || (nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
> + nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI)
> + || nhi->subsystem_vendor != 0x2222
> + || nhi->subsystem_device != 0x1111)
> goto out;
> dev_info(&dev->dev, "quirk: waiting for thunderbolt to reestablish PCI tunnels...\n");
> device_pm_wait_for_dev(&dev->dev, &nhi->dev);
> @@ -3276,9 +3278,11 @@ out:
> pci_dev_put(nhi);
> pci_dev_put(sibling);
> }
> -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x1547,
> +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
> + PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
> quirk_apple_wait_for_thunderbolt);
> -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x156d,
> +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
> + PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE,
> quirk_apple_wait_for_thunderbolt);
> #endif
>
> diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
> index 20a41f7..36be23b 100644
> --- a/drivers/thunderbolt/nhi.c
> +++ b/drivers/thunderbolt/nhi.c
> @@ -633,16 +633,18 @@ static const struct dev_pm_ops nhi_pm_ops = {
> static struct pci_device_id nhi_ids[] = {
> /*
> * We have to specify class, the TB bridges use the same device and
> - * vendor (sub)id.
> + * vendor (sub)id on gen 1 and gen 2 controllers.
> */
> {
> .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
> - .vendor = PCI_VENDOR_ID_INTEL, .device = 0x1547,
> + .vendor = PCI_VENDOR_ID_INTEL,
> + .device = PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
> .subvendor = 0x2222, .subdevice = 0x1111,
> },
> {
> .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
> - .vendor = PCI_VENDOR_ID_INTEL, .device = 0x156c,
> + .vendor = PCI_VENDOR_ID_INTEL,
> + .device = PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI,
> .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
> },
> { 0,}
> diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
> index aeb9829..db73ffe 100644
> --- a/drivers/thunderbolt/switch.c
> +++ b/drivers/thunderbolt/switch.c
> @@ -293,9 +293,9 @@ static int tb_plug_events_active(struct tb_switch *sw, bool active)
> if (active) {
> data = data & 0xFFFFFF83;
> switch (sw->config.device_id) {
> - case 0x1513:
> - case 0x151a:
> - case 0x1549:
> + case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE:
> + case PCI_DEVICE_ID_INTEL_EAGLE_RIDGE:
> + case PCI_DEVICE_ID_INTEL_PORT_RIDGE:
> break;
> default:
> data |= 4;
> @@ -370,7 +370,8 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route)
> tb_sw_warn(sw, "unknown switch vendor id %#x\n",
> sw->config.vendor_id);
>
> - if (sw->config.device_id != 0x1547 && sw->config.device_id != 0x1549)
> + if (sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
> + sw->config.device_id != PCI_DEVICE_ID_INTEL_PORT_RIDGE)
> tb_sw_warn(sw, "unsupported switch device id %#x\n",
> sw->config.device_id);
>
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index 247da8c..c58752f 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -2604,6 +2604,24 @@
> #define PCI_DEVICE_ID_INTEL_82441 0x1237
> #define PCI_DEVICE_ID_INTEL_82380FB 0x124b
> #define PCI_DEVICE_ID_INTEL_82439 0x1250
> +#define PCI_DEVICE_ID_INTEL_LIGHT_RIDGE 0x1513 /* Tbt 1 Gen 1 */
> +#define PCI_DEVICE_ID_INTEL_EAGLE_RIDGE 0x151a
> +#define PCI_DEVICE_ID_INTEL_LIGHT_PEAK 0x151b
> +#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C 0x1547 /* Tbt 1 Gen 2 */
> +#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C 0x1548
> +#define PCI_DEVICE_ID_INTEL_PORT_RIDGE 0x1549
> +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI 0x1566 /* Tbt 1 Gen 3 */
> +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE 0x1567
> +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI 0x1568
> +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE 0x1569
> +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI 0x156a /* Thunderbolt 2 */
> +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE 0x156b
> +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI 0x156c
> +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE 0x156d
> +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI 0x1575 /* Thunderbolt 3 */
> +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE 0x1576
> +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI 0x1577
> +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE 0x1578
> #define PCI_DEVICE_ID_INTEL_80960_RP 0x1960
> #define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21
> #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30
> --
> 2.8.0.rc3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html