diff options
author | Philippe Bergheaud <felix@linux.vnet.ibm.com> | 2016-07-01 13:32:52 +0200 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2016-07-08 22:23:57 +1000 |
commit | 3b3dcd61fa4e3604d8f1bdfd8471fca7b7c012e4 (patch) | |
tree | b6affe5c87b114c797f21c04faa97daa56428dbb /drivers/misc/cxl/pci.c | |
parent | e00878be3f414a99234b3c9613e2fcab7497cd4b (diff) |
cxl: Ignore CAPI adapters misplaced in switched slots
One should not attempt to switch a PHB into CAPI mode if there is
a switch between the PHB and the adapter. This patch modifies the
cxl driver to ignore CAPI adapters misplaced in switched slots.
Signed-off-by: Philippe Bergheaud <felix@linux.vnet.ibm.com>
Reviewed-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
Acked-by: Ian Munsie <imunsie@au1.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'drivers/misc/cxl/pci.c')
-rw-r--r-- | drivers/misc/cxl/pci.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index b7f2e96c1528..3a5f9801640d 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -1402,6 +1402,30 @@ static void cxl_pci_remove_adapter(struct cxl *adapter) device_unregister(&adapter->dev); } +#define CXL_MAX_PCIEX_PARENT 2 + +static int cxl_slot_is_switched(struct pci_dev *dev) +{ + struct device_node *np; + int depth = 0; + const __be32 *prop; + + if (!(np = pci_device_to_OF_node(dev))) { + pr_err("cxl: np = NULL\n"); + return -ENODEV; + } + of_node_get(np); + while (np) { + np = of_get_next_parent(np); + prop = of_get_property(np, "device_type", NULL); + if (!prop || strcmp((char *)prop, "pciex")) + break; + depth++; + } + of_node_put(np); + return (depth > CXL_MAX_PCIEX_PARENT); +} + static int cxl_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct cxl *adapter; @@ -1413,6 +1437,11 @@ static int cxl_probe(struct pci_dev *dev, const struct pci_device_id *id) return -ENODEV; } + if (cxl_slot_is_switched(dev)) { + dev_info(&dev->dev, "Ignoring card on incompatible PCI slot\n"); + return -ENODEV; + } + if (cxl_verbose) dump_cxl_config_space(dev); |