| From 4084401b33e57fbb2e4bb6443a211b02b133f8d3 Mon Sep 17 00:00:00 2001 |
| From: Subbaraya Sundeep <sbhatta@marvell.com> |
| Date: Mon, 4 Nov 2019 12:27:44 +0530 |
| Subject: [PATCH] PCI: Do not use bus number zero from EA capability |
| |
| commit 73884a7082f466ce6686bb8dd7e6571dd42313b4 upstream. |
| |
| As per PCIe r5.0, sec 7.8.5.2, fixed bus numbers of a bridge must be zero |
| when no function that uses EA is located behind it. Hence, if EA supplies |
| bus numbers of zero, assign bus numbers normally. A secondary bus can |
| never have a bus number of zero, so setting a bridge's Secondary Bus Number |
| to zero makes downstream devices unreachable. |
| |
| [bhelgaas: retain bool return value so "zero is invalid" logic is local] |
| Fixes: 2dbce5901179 ("PCI: Assign bus numbers present in EA capability for bridges") |
| Link: https://lore.kernel.org/r/1572850664-9861-1-git-send-email-sundeep.lkml@gmail.com |
| Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com> |
| Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> |
| Cc: stable@vger.kernel.org # v5.2+ |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c |
| index 0e8e2c186f50..1910b3394d2c 100644 |
| --- a/drivers/pci/probe.c |
| +++ b/drivers/pci/probe.c |
| @@ -1094,14 +1094,15 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, |
| * @sec: updated with secondary bus number from EA |
| * @sub: updated with subordinate bus number from EA |
| * |
| - * If @dev is a bridge with EA capability, update @sec and @sub with |
| - * fixed bus numbers from the capability and return true. Otherwise, |
| - * return false. |
| + * If @dev is a bridge with EA capability that specifies valid secondary |
| + * and subordinate bus numbers, return true with the bus numbers in @sec |
| + * and @sub. Otherwise return false. |
| */ |
| static bool pci_ea_fixed_busnrs(struct pci_dev *dev, u8 *sec, u8 *sub) |
| { |
| int ea, offset; |
| u32 dw; |
| + u8 ea_sec, ea_sub; |
| |
| if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) |
| return false; |
| @@ -1113,8 +1114,13 @@ static bool pci_ea_fixed_busnrs(struct pci_dev *dev, u8 *sec, u8 *sub) |
| |
| offset = ea + PCI_EA_FIRST_ENT; |
| pci_read_config_dword(dev, offset, &dw); |
| - *sec = dw & PCI_EA_SEC_BUS_MASK; |
| - *sub = (dw & PCI_EA_SUB_BUS_MASK) >> PCI_EA_SUB_BUS_SHIFT; |
| + ea_sec = dw & PCI_EA_SEC_BUS_MASK; |
| + ea_sub = (dw & PCI_EA_SUB_BUS_MASK) >> PCI_EA_SUB_BUS_SHIFT; |
| + if (ea_sec == 0 || ea_sub < ea_sec) |
| + return false; |
| + |
| + *sec = ea_sec; |
| + *sub = ea_sub; |
| return true; |
| } |
| |
| -- |
| 2.7.4 |
| |