]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Revert "PCI: qcom: Enumerate endpoints based on Link up event in 'global_irq' interrupt"
authorNiklas Cassel <cassel@kernel.org>
Mon, 22 Dec 2025 06:42:12 +0000 (07:42 +0100)
committerManivannan Sadhasivam <mani@kernel.org>
Mon, 22 Dec 2025 17:01:31 +0000 (22:31 +0530)
This reverts commit 4581403f67929d02c197cb187c4e1e811c9e762a.

While this fake hotplugging was a nice idea, it has shown that this feature
does not handle PCIe switches correctly:
pci_bus 0004:43: busn_res: can not insert [bus 43-41] under [bus 42-41] (conflicts with (null) [bus 42-41])
pci_bus 0004:43: busn_res: [bus 43-41] end is updated to 43
pci_bus 0004:43: busn_res: can not insert [bus 43] under [bus 42-41] (conflicts with (null) [bus 42-41])
pci 0004:42:00.0: devices behind bridge are unusable because [bus 43] cannot be assigned for them
pci_bus 0004:44: busn_res: can not insert [bus 44-41] under [bus 42-41] (conflicts with (null) [bus 42-41])
pci_bus 0004:44: busn_res: [bus 44-41] end is updated to 44
pci_bus 0004:44: busn_res: can not insert [bus 44] under [bus 42-41] (conflicts with (null) [bus 42-41])
pci 0004:42:02.0: devices behind bridge are unusable because [bus 44] cannot be assigned for them
pci_bus 0004:45: busn_res: can not insert [bus 45-41] under [bus 42-41] (conflicts with (null) [bus 42-41])
pci_bus 0004:45: busn_res: [bus 45-41] end is updated to 45
pci_bus 0004:45: busn_res: can not insert [bus 45] under [bus 42-41] (conflicts with (null) [bus 42-41])
pci 0004:42:06.0: devices behind bridge are unusable because [bus 45] cannot be assigned for them
pci_bus 0004:46: busn_res: can not insert [bus 46-41] under [bus 42-41] (conflicts with (null) [bus 42-41])
pci_bus 0004:46: busn_res: [bus 46-41] end is updated to 46
pci_bus 0004:46: busn_res: can not insert [bus 46] under [bus 42-41] (conflicts with (null) [bus 42-41])
pci 0004:42:0e.0: devices behind bridge are unusable because [bus 46] cannot be assigned for them
pci_bus 0004:42: busn_res: [bus 42-41] end is updated to 46
pci_bus 0004:42: busn_res: can not insert [bus 42-46] under [bus 41] (conflicts with (null) [bus 41])
pci 0004:41:00.0: devices behind bridge are unusable because [bus 42-46] cannot be assigned for them
pcieport 0004:40:00.0: bridge has subordinate 41 but max busn 46

During the initial scan, PCI core doesn't see the switch and since the Root
Port is not hot plug capable, the secondary bus number gets assigned as the
subordinate bus number. This means, the PCI core assumes that only one bus
will appear behind the Root Port since the Root Port is not hot plug
capable.

This works perfectly fine for PCIe endpoints connected to the Root Port,
since they don't extend the bus. However, if a PCIe switch is connected,
then there is a problem when the downstream busses starts showing up and
the PCI core doesn't extend the subordinate bus number and bridge resources
after initial scan during boot.

The long term plan is to migrate this driver to the upcoming pwrctrl APIs
that are supposed to handle this problem elegantly.

Suggested-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Tested-by: Shawn Lin <shawn.lin@rock-chips.com>
Acked-by: Shawn Lin <shawn.lin@rock-chips.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20251222064207.3246632-13-cassel@kernel.org
drivers/pci/controller/dwc/pcie-qcom.c

index c5fcb87972e91ef122ce1a8f32db2a89bd0f03db..13e6c334e10d21b9ebfe5f82de0aff3bce6191e3 100644 (file)
@@ -55,9 +55,6 @@
 #define PARF_AXI_MSTR_WR_ADDR_HALT_V2          0x1a8
 #define PARF_Q2A_FLUSH                         0x1ac
 #define PARF_LTSSM                             0x1b0
-#define PARF_INT_ALL_STATUS                    0x224
-#define PARF_INT_ALL_CLEAR                     0x228
-#define PARF_INT_ALL_MASK                      0x22c
 #define PARF_SID_OFFSET                                0x234
 #define PARF_BDF_TRANSLATE_CFG                 0x24c
 #define PARF_DBI_BASE_ADDR_V2                  0x350
 /* PARF_LTSSM register fields */
 #define LTSSM_EN                               BIT(8)
 
-/* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */
-#define PARF_INT_ALL_LINK_UP                   BIT(13)
-
 /* PARF_NO_SNOOP_OVERRIDE register fields */
 #define WR_NO_SNOOP_OVERRIDE_EN                        BIT(1)
 #define RD_NO_SNOOP_OVERRIDE_EN                        BIT(3)
@@ -1635,32 +1629,6 @@ static void qcom_pcie_init_debugfs(struct qcom_pcie *pcie)
                                    qcom_pcie_link_transition_count);
 }
 
-static irqreturn_t qcom_pcie_global_irq_thread(int irq, void *data)
-{
-       struct qcom_pcie *pcie = data;
-       struct dw_pcie_rp *pp = &pcie->pci->pp;
-       struct device *dev = pcie->pci->dev;
-       u32 status = readl_relaxed(pcie->parf + PARF_INT_ALL_STATUS);
-
-       writel_relaxed(status, pcie->parf + PARF_INT_ALL_CLEAR);
-
-       if (FIELD_GET(PARF_INT_ALL_LINK_UP, status)) {
-               msleep(PCIE_RESET_CONFIG_WAIT_MS);
-               dev_dbg(dev, "Received Link up event. Starting enumeration!\n");
-               /* Rescan the bus to enumerate endpoint devices */
-               pci_lock_rescan_remove();
-               pci_rescan_bus(pp->bridge->bus);
-               pci_unlock_rescan_remove();
-
-               qcom_pcie_icc_opp_update(pcie);
-       } else {
-               dev_WARN_ONCE(dev, 1, "Received unknown event. INT_STATUS: 0x%08x\n",
-                             status);
-       }
-
-       return IRQ_HANDLED;
-}
-
 static void qcom_pci_free_msi(void *ptr)
 {
        struct dw_pcie_rp *pp = (struct dw_pcie_rp *)ptr;
@@ -1805,8 +1773,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
        struct dw_pcie_rp *pp;
        struct resource *res;
        struct dw_pcie *pci;
-       int ret, irq;
-       char *name;
+       int ret;
 
        pcie_cfg = of_device_get_match_data(dev);
        if (!pcie_cfg) {
@@ -1963,27 +1930,6 @@ static int qcom_pcie_probe(struct platform_device *pdev)
                goto err_phy_exit;
        }
 
-       name = devm_kasprintf(dev, GFP_KERNEL, "qcom_pcie_global_irq%d",
-                             pci_domain_nr(pp->bridge->bus));
-       if (!name) {
-               ret = -ENOMEM;
-               goto err_host_deinit;
-       }
-
-       irq = platform_get_irq_byname_optional(pdev, "global");
-       if (irq > 0) {
-               ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
-                                               qcom_pcie_global_irq_thread,
-                                               IRQF_ONESHOT, name, pcie);
-               if (ret) {
-                       dev_err_probe(&pdev->dev, ret,
-                                     "Failed to request Global IRQ\n");
-                       goto err_host_deinit;
-               }
-
-               writel_relaxed(PARF_INT_ALL_LINK_UP, pcie->parf + PARF_INT_ALL_MASK);
-       }
-
        qcom_pcie_icc_opp_update(pcie);
 
        if (pcie->mhi)
@@ -1991,8 +1937,6 @@ static int qcom_pcie_probe(struct platform_device *pdev)
 
        return 0;
 
-err_host_deinit:
-       dw_pcie_host_deinit(pp);
 err_phy_exit:
        list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
                phy_exit(port->phy);