summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRay Jui <ray.jui@broadcom.com>2018-06-11 20:21:06 -0400
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2018-07-13 06:56:55 -0400
commitf78e60a29d4ff27531770cf2c6eee89292379209 (patch)
tree10d900903255dc58311052926fe2298624532ac5
parent1e5748c27ad6669ec4a377f44ef40898c28184e5 (diff)
PCI: iproc: Reject unconfigured physical functions from PAXC
PAXC is an emulated PCIe root complex internally in various Broadcom based SoCs. PAXC internally connects to the embedded network processor within these SoCs, with the embedeed network processor exposed as an endpoint device. The number of physical functions from the embedded network processor that can be accessed depends on the firmware configuration. Unfortunately, due to an ASIC bug, unconfigured physical functions cannot be properly hidden from the root complex during enumerattion. As a result, config write access to these unconfigured physical functions during enumeration will cause a bus lock up on the embedded network processor. Fortunately, these unconfigured physical functions contain a very specific, staled PCIe device ID 0x168e. By making use of this device ID, one is able to terminate the enumeration early in the vendor/device ID config read. Signed-off-by: Ray Jui <ray.jui@broadcom.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Scott Branden <scott.branden@broadcom.com> Reviewed-by: Oza Pawandeep <poza@codeaurora.org>
-rw-r--r--drivers/pci/controller/pcie-iproc.c26
-rw-r--r--drivers/pci/controller/pcie-iproc.h5
2 files changed, 30 insertions, 1 deletions
diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
index 0804aa284b87..59be1e02ba65 100644
--- a/drivers/pci/controller/pcie-iproc.c
+++ b/drivers/pci/controller/pcie-iproc.c
@@ -582,6 +582,25 @@ static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
582 if (size <= 2) 582 if (size <= 2)
583 *val = (data >> (8 * (where & 3))) & ((1 << (size * 8)) - 1); 583 *val = (data >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
584 584
585 /*
586 * For PAXC and PAXCv2, the total number of PFs that one can enumerate
587 * depends on the firmware configuration. Unfortunately, due to an ASIC
588 * bug, unconfigured PFs cannot be properly hidden from the root
589 * complex. As a result, write access to these PFs will cause bus lock
590 * up on the embedded processor
591 *
592 * Since all unconfigured PFs are left with an incorrect, staled device
593 * ID of 0x168e (PCI_DEVICE_ID_NX2_57810), we try to catch those access
594 * early here and reject them all
595 */
596#define DEVICE_ID_MASK 0xffff0000
597#define DEVICE_ID_SHIFT 16
598 if (pcie->rej_unconfig_pf &&
599 (where & CFG_ADDR_REG_NUM_MASK) == PCI_VENDOR_ID)
600 if ((*val & DEVICE_ID_MASK) ==
601 (PCI_DEVICE_ID_NX2_57810 << DEVICE_ID_SHIFT))
602 return PCIBIOS_FUNC_NOT_SUPPORTED;
603
585 return PCIBIOS_SUCCESSFUL; 604 return PCIBIOS_SUCCESSFUL;
586} 605}
587 606
@@ -681,7 +700,7 @@ static int iproc_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
681 struct iproc_pcie *pcie = iproc_data(bus); 700 struct iproc_pcie *pcie = iproc_data(bus);
682 701
683 iproc_pcie_apb_err_disable(bus, true); 702 iproc_pcie_apb_err_disable(bus, true);
684 if (pcie->type == IPROC_PCIE_PAXB_V2) 703 if (pcie->iproc_cfg_read)
685 ret = iproc_pcie_config_read(bus, devfn, where, size, val); 704 ret = iproc_pcie_config_read(bus, devfn, where, size, val);
686 else 705 else
687 ret = pci_generic_config_read32(bus, devfn, where, size, val); 706 ret = pci_generic_config_read32(bus, devfn, where, size, val);
@@ -1336,6 +1355,7 @@ static int iproc_pcie_rev_init(struct iproc_pcie *pcie)
1336 break; 1355 break;
1337 case IPROC_PCIE_PAXB: 1356 case IPROC_PCIE_PAXB:
1338 regs = iproc_pcie_reg_paxb; 1357 regs = iproc_pcie_reg_paxb;
1358 pcie->iproc_cfg_read = true;
1339 pcie->has_apb_err_disable = true; 1359 pcie->has_apb_err_disable = true;
1340 if (pcie->need_ob_cfg) { 1360 if (pcie->need_ob_cfg) {
1341 pcie->ob_map = paxb_ob_map; 1361 pcie->ob_map = paxb_ob_map;
@@ -1358,10 +1378,14 @@ static int iproc_pcie_rev_init(struct iproc_pcie *pcie)
1358 case IPROC_PCIE_PAXC: 1378 case IPROC_PCIE_PAXC:
1359 regs = iproc_pcie_reg_paxc; 1379 regs = iproc_pcie_reg_paxc;
1360 pcie->ep_is_internal = true; 1380 pcie->ep_is_internal = true;
1381 pcie->iproc_cfg_read = true;
1382 pcie->rej_unconfig_pf = true;
1361 break; 1383 break;
1362 case IPROC_PCIE_PAXC_V2: 1384 case IPROC_PCIE_PAXC_V2:
1363 regs = iproc_pcie_reg_paxc_v2; 1385 regs = iproc_pcie_reg_paxc_v2;
1364 pcie->ep_is_internal = true; 1386 pcie->ep_is_internal = true;
1387 pcie->iproc_cfg_read = true;
1388 pcie->rej_unconfig_pf = true;
1365 pcie->need_msi_steer = true; 1389 pcie->need_msi_steer = true;
1366 break; 1390 break;
1367 default: 1391 default:
diff --git a/drivers/pci/controller/pcie-iproc.h b/drivers/pci/controller/pcie-iproc.h
index 9d5cfeea3046..4f03ea539805 100644
--- a/drivers/pci/controller/pcie-iproc.h
+++ b/drivers/pci/controller/pcie-iproc.h
@@ -58,6 +58,9 @@ struct iproc_msi;
58 * @phy: optional PHY device that controls the Serdes 58 * @phy: optional PHY device that controls the Serdes
59 * @map_irq: function callback to map interrupts 59 * @map_irq: function callback to map interrupts
60 * @ep_is_internal: indicates an internal emulated endpoint device is connected 60 * @ep_is_internal: indicates an internal emulated endpoint device is connected
61 * @iproc_cfg_read: indicates the iProc config read function should be used
62 * @rej_unconfig_pf: indicates the root complex needs to detect and reject
63 * enumeration against unconfigured physical functions emulated in the ASIC
61 * @has_apb_err_disable: indicates the controller can be configured to prevent 64 * @has_apb_err_disable: indicates the controller can be configured to prevent
62 * unsupported request from being forwarded as an APB bus error 65 * unsupported request from being forwarded as an APB bus error
63 * @fix_paxc_cap: indicates the controller has corrupted capability list in its 66 * @fix_paxc_cap: indicates the controller has corrupted capability list in its
@@ -86,6 +89,8 @@ struct iproc_pcie {
86 struct phy *phy; 89 struct phy *phy;
87 int (*map_irq)(const struct pci_dev *, u8, u8); 90 int (*map_irq)(const struct pci_dev *, u8, u8);
88 bool ep_is_internal; 91 bool ep_is_internal;
92 bool iproc_cfg_read;
93 bool rej_unconfig_pf;
89 bool has_apb_err_disable; 94 bool has_apb_err_disable;
90 bool fix_paxc_cap; 95 bool fix_paxc_cap;
91 96