]> Git Repo - linux.git/commitdiff
PCI: endpoint: Remove "core_init_notifier" flag
authorManivannan Sadhasivam <[email protected]>
Wed, 27 Mar 2024 09:13:37 +0000 (14:43 +0530)
committerKrzysztof Wilczyński <[email protected]>
Wed, 10 Apr 2024 17:52:42 +0000 (17:52 +0000)
"core_init_notifier" flag is set by the glue drivers requiring refclk from
the host to complete the DWC core initialization. Also, those drivers will
send a notification to the EPF drivers once the initialization is fully
completed using the pci_epc_init_notify() API. Only then, the EPF drivers
will start functioning.

For the rest of the drivers generating refclk locally, EPF drivers will
start functioning post binding with them. EPF drivers rely on the
'core_init_notifier' flag to differentiate between the drivers.
Unfortunately, this creates two different flows for the EPF drivers.

So to avoid that, let's get rid of the "core_init_notifier" flag and follow
a single initialization flow for the EPF drivers. This is done by calling
the dw_pcie_ep_init_notify() from all glue drivers after the completion of
dw_pcie_ep_init_registers() API. This will allow all the glue drivers to
send the notification to the EPF drivers once the initialization is fully
completed.

Only difference here is that, the drivers requiring refclk from host will
send the notification once refclk is received, while others will send it
during probe time itself.

But this also requires the EPC core driver to deliver the notification
after EPF driver bind. Because, the glue driver can send the notification
before the EPF drivers bind() and in those cases the EPF drivers will miss
the event. To accommodate this, EPC core is now caching the state of the
EPC initialization in 'init_complete' flag and pci-ep-cfs driver sends the
notification to EPF drivers based on that after each EPF driver bind.

Link: https://lore.kernel.org/linux-pci/[email protected]
Tested-by: Niklas Cassel <[email protected]>
Signed-off-by: Manivannan Sadhasivam <[email protected]>
Signed-off-by: Krzysztof Wilczyński <[email protected]>
Reviewed-by: Frank Li <[email protected]>
Reviewed-by: Niklas Cassel <[email protected]>
19 files changed:
drivers/pci/controller/cadence/pcie-cadence-ep.c
drivers/pci/controller/dwc/pci-dra7xx.c
drivers/pci/controller/dwc/pci-imx6.c
drivers/pci/controller/dwc/pci-keystone.c
drivers/pci/controller/dwc/pci-layerscape-ep.c
drivers/pci/controller/dwc/pcie-artpec6.c
drivers/pci/controller/dwc/pcie-designware-ep.c
drivers/pci/controller/dwc/pcie-designware-plat.c
drivers/pci/controller/dwc/pcie-keembay.c
drivers/pci/controller/dwc/pcie-qcom-ep.c
drivers/pci/controller/dwc/pcie-rcar-gen4.c
drivers/pci/controller/dwc/pcie-tegra194.c
drivers/pci/controller/dwc/pcie-uniphier-ep.c
drivers/pci/controller/pcie-rcar-ep.c
drivers/pci/controller/pcie-rockchip-ep.c
drivers/pci/endpoint/functions/pci-epf-test.c
drivers/pci/endpoint/pci-ep-cfs.c
drivers/pci/endpoint/pci-epc-core.c
include/linux/pci-epc.h

index 81c50dc64da96f4c7182e9fc3b19a22d6d04ea0d..55c42ca2b7775d422f4efc21c07a46495ee9729b 100644 (file)
@@ -746,6 +746,8 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
 
        spin_lock_init(&ep->lock);
 
+       pci_epc_init_notify(epc);
+
        return 0;
 
  free_epc_mem:
index 395042b29ffc8be9ebcb9912f9b01ac1f5060062..d2d17d37d3e0b5adfd30c9c348a0be29b795bff8 100644 (file)
@@ -474,6 +474,8 @@ static int dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx,
                return ret;
        }
 
+       dw_pcie_ep_init_notify(ep);
+
        return 0;
 }
 
index 8d28ecc381bc4d936e4a27736de3266c48ceb97a..917c69edee1d54199cdf19106af61d9578359159 100644 (file)
@@ -1131,6 +1131,8 @@ static int imx6_add_pcie_ep(struct imx6_pcie *imx6_pcie,
                return ret;
        }
 
+       dw_pcie_ep_init_notify(ep);
+
        /* Start LTSSM. */
        imx6_pcie_ltssm_enable(dev);
 
index 81ebac520650a5db28f6a9fae9595b099fc61ef4..d3a7d14ee685a1d63c5b0ba13b540c54293d13e7 100644 (file)
@@ -1293,6 +1293,8 @@ static int ks_pcie_probe(struct platform_device *pdev)
                        goto err_ep_init;
                }
 
+               dw_pcie_ep_init_notify(&pci->ep);
+
                break;
        default:
                dev_err(dev, "INVALID device type %d\n", mode);
index 9eb2233e3d7f4b8b41bb1c626a81a00a17487470..7dde6d5fa4d858d2b817796ee90da7f971cbe7ac 100644 (file)
@@ -286,6 +286,8 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)
                return ret;
        }
 
+       dw_pcie_ep_init_notify(&pci->ep);
+
        return ls_pcie_ep_interrupt_init(pcie, pdev);
 }
 
index a6095561db4a690cde72b9edbc54ced5d3223677..a4630b92489bf4033bf2d636bb235b64b3537dff 100644 (file)
@@ -452,6 +452,8 @@ static int artpec6_pcie_probe(struct platform_device *pdev)
                        return ret;
                }
 
+               dw_pcie_ep_init_notify(&pci->ep);
+
                break;
        default:
                dev_err(dev, "INVALID device type %d\n", artpec6_pcie->mode);
index 2063cf2049e5c317fe7aba18ec40b61157c06641..47391d7d3a7343b20d7f1dc1e80e02de4e16c1f8 100644 (file)
@@ -632,6 +632,7 @@ void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep)
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
        dw_pcie_edma_remove(pci);
+       ep->epc->init_complete = false;
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_cleanup);
 
index ca9b22e654cd21a621e0b4308f0e130ab4eb619e..8490c5d6ff9f92aa084e5fb497124df296769341 100644 (file)
@@ -154,6 +154,8 @@ static int dw_plat_pcie_probe(struct platform_device *pdev)
                        dw_pcie_ep_deinit(&pci->ep);
                }
 
+               dw_pcie_ep_init_notify(&pci->ep);
+
                break;
        default:
                dev_err(dev, "INVALID device type %d\n", dw_plat_pcie->mode);
index b2556dbcffb53a1632914b4b0510ece0d2371094..98bbc83182b45ce5f23446f58c8cd0a9e05a5847 100644 (file)
@@ -442,6 +442,8 @@ static int keembay_pcie_probe(struct platform_device *pdev)
                        return ret;
                }
 
+               dw_pcie_ep_init_notify(&pci->ep);
+
                break;
        default:
                dev_err(dev, "Invalid device type %d\n", pcie->mode);
index 3697b4a944ccfad8d6bffd5918037b19bbe598a8..2fb8c15e7a9116a1f6715f9cece1bcb3cf3c694f 100644 (file)
@@ -775,7 +775,6 @@ static void qcom_pcie_ep_init_debugfs(struct qcom_pcie_ep *pcie_ep)
 
 static const struct pci_epc_features qcom_pcie_epc_features = {
        .linkup_notifier = true,
-       .core_init_notifier = true,
        .msi_capable = true,
        .msix_capable = false,
        .align = SZ_4K,
index e155a905fb4f6b18ae03cf221da3781792c36206..cfeccc2f9ee1d15bf664a9585cfafdd8a894d41f 100644 (file)
@@ -437,6 +437,8 @@ static int rcar_gen4_add_dw_pcie_ep(struct rcar_gen4_pcie *rcar)
                rcar_gen4_pcie_ep_deinit(rcar);
        }
 
+       dw_pcie_ep_init_notify(ep);
+
        return ret;
 }
 
index db043f579fbe4f0ea2ee3c7d9542b1940f9c0ed5..ddc23602eca7312cd51741181ce4a6d0552f56ba 100644 (file)
@@ -2006,7 +2006,6 @@ static int tegra_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
 
 static const struct pci_epc_features tegra_pcie_epc_features = {
        .linkup_notifier = true,
-       .core_init_notifier = true,
        .msi_capable = false,
        .msix_capable = false,
        .bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M,
index 0e5e7344de48488e9b8abfa124ba04d74b83d31b..a2b844268e2857d6bfdd50783d6ad31c224bc601 100644 (file)
@@ -410,6 +410,8 @@ static int uniphier_pcie_ep_probe(struct platform_device *pdev)
                return ret;
        }
 
+       dw_pcie_ep_init_notify(&priv->pci.ep);
+
        return 0;
 }
 
index 05967c6c0b426ad4c8269000cbe61c47d7228992..047e2cef5afcd54117c7c880fe9788771f5308a2 100644 (file)
@@ -542,6 +542,8 @@ static int rcar_pcie_ep_probe(struct platform_device *pdev)
                goto err_pm_put;
        }
 
+       pci_epc_init_notify(epc);
+
        return 0;
 
 err_pm_put:
index c9046e97a1d27fe2bd93d8b60e7f354bedabcba8..8613df8184df06df6ee772e7271877a4a6f8d48e 100644 (file)
@@ -609,6 +609,8 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
        rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE,
                            PCIE_CLIENT_CONFIG);
 
+       pci_epc_init_notify(epc);
+
        return 0;
 err_epc_mem_exit:
        pci_epc_mem_exit(epc);
index cd4ffb39dcdc6137a3569ac420c90fc09cce7983..212fc303fb631104e07d81c537016e9e00c3a048 100644 (file)
@@ -753,6 +753,7 @@ static int pci_epf_test_core_init(struct pci_epf *epf)
        const struct pci_epc_features *epc_features;
        struct pci_epc *epc = epf->epc;
        struct device *dev = &epf->dev;
+       bool linkup_notifier = false;
        bool msix_capable = false;
        bool msi_capable = true;
        int ret;
@@ -795,6 +796,10 @@ static int pci_epf_test_core_init(struct pci_epf *epf)
                }
        }
 
+       linkup_notifier = epc_features->linkup_notifier;
+       if (!linkup_notifier)
+               queue_work(kpcitest_workqueue, &epf_test->cmd_handler.work);
+
        return 0;
 }
 
@@ -890,8 +895,6 @@ static int pci_epf_test_bind(struct pci_epf *epf)
        const struct pci_epc_features *epc_features;
        enum pci_barno test_reg_bar = BAR_0;
        struct pci_epc *epc = epf->epc;
-       bool linkup_notifier = false;
-       bool core_init_notifier = false;
 
        if (WARN_ON_ONCE(!epc))
                return -EINVAL;
@@ -902,8 +905,6 @@ static int pci_epf_test_bind(struct pci_epf *epf)
                return -EOPNOTSUPP;
        }
 
-       linkup_notifier = epc_features->linkup_notifier;
-       core_init_notifier = epc_features->core_init_notifier;
        test_reg_bar = pci_epc_get_first_free_bar(epc_features);
        if (test_reg_bar < 0)
                return -EINVAL;
@@ -916,21 +917,12 @@ static int pci_epf_test_bind(struct pci_epf *epf)
        if (ret)
                return ret;
 
-       if (!core_init_notifier) {
-               ret = pci_epf_test_core_init(epf);
-               if (ret)
-                       return ret;
-       }
-
        epf_test->dma_supported = true;
 
        ret = pci_epf_test_init_dma_chan(epf_test);
        if (ret)
                epf_test->dma_supported = false;
 
-       if (!linkup_notifier && !core_init_notifier)
-               queue_work(kpcitest_workqueue, &epf_test->cmd_handler.work);
-
        return 0;
 }
 
index 0ea64e24ed616b4132a1cfa9d9e1ee136b8f2b06..3b21e28f9b59118a272ec38a1901570cc3a95a2b 100644 (file)
@@ -64,6 +64,9 @@ static int pci_secondary_epc_epf_link(struct config_item *epf_item,
                return ret;
        }
 
+       /* Send any pending EPC initialization complete to the EPF driver */
+       pci_epc_notify_pending_init(epc, epf);
+
        return 0;
 }
 
@@ -125,6 +128,9 @@ static int pci_primary_epc_epf_link(struct config_item *epf_item,
                return ret;
        }
 
+       /* Send any pending EPC initialization complete to the EPF driver */
+       pci_epc_notify_pending_init(epc, epf);
+
        return 0;
 }
 
@@ -230,6 +236,9 @@ static int pci_epc_epf_link(struct config_item *epc_item,
                return ret;
        }
 
+       /* Send any pending EPC initialization complete to the EPF driver */
+       pci_epc_notify_pending_init(epc, epf);
+
        return 0;
 }
 
index da3fc0795b0b620c06c39fe9304eb84857c6c0ca..47d27ec7439d94acca83e4beb427bf1c82d64320 100644 (file)
@@ -748,10 +748,32 @@ void pci_epc_init_notify(struct pci_epc *epc)
                        epf->event_ops->core_init(epf);
                mutex_unlock(&epf->lock);
        }
+       epc->init_complete = true;
        mutex_unlock(&epc->list_lock);
 }
 EXPORT_SYMBOL_GPL(pci_epc_init_notify);
 
+/**
+ * pci_epc_notify_pending_init() - Notify the pending EPC device initialization
+ *                                 complete to the EPF device
+ * @epc: the EPC device whose core initialization is pending to be notified
+ * @epf: the EPF device to be notified
+ *
+ * Invoke to notify the pending EPC device initialization complete to the EPF
+ * device. This is used to deliver the notification if the EPC initialization
+ * got completed before the EPF driver bind.
+ */
+void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf)
+{
+       if (epc->init_complete) {
+               mutex_lock(&epf->lock);
+               if (epf->event_ops && epf->event_ops->core_init)
+                       epf->event_ops->core_init(epf);
+               mutex_unlock(&epf->lock);
+       }
+}
+EXPORT_SYMBOL_GPL(pci_epc_notify_pending_init);
+
 /**
  * pci_epc_bme_notify() - Notify the EPF device that the EPC device has received
  *                       the BME event from the Root complex
index cc2f70d061c83b551af24c866312147a09cdf820..acc5f96161fe1263a0b219c8b67b4fd40347a690 100644 (file)
@@ -128,6 +128,8 @@ struct pci_epc_mem {
  * @group: configfs group representing the PCI EPC device
  * @lock: mutex to protect pci_epc ops
  * @function_num_map: bitmap to manage physical function number
+ * @init_complete: flag to indicate whether the EPC initialization is complete
+ *                 or not
  */
 struct pci_epc {
        struct device                   dev;
@@ -143,6 +145,7 @@ struct pci_epc {
        /* mutex to protect against concurrent access of EP controller */
        struct mutex                    lock;
        unsigned long                   function_num_map;
+       bool                            init_complete;
 };
 
 /**
@@ -179,8 +182,6 @@ struct pci_epc_bar_desc {
 /**
  * struct pci_epc_features - features supported by a EPC device per function
  * @linkup_notifier: indicate if the EPC device can notify EPF driver on link up
- * @core_init_notifier: indicate cores that can notify about their availability
- *                     for initialization
  * @msi_capable: indicate if the endpoint function has MSI capability
  * @msix_capable: indicate if the endpoint function has MSI-X capability
  * @bar: array specifying the hardware description for each BAR
@@ -188,7 +189,6 @@ struct pci_epc_bar_desc {
  */
 struct pci_epc_features {
        unsigned int    linkup_notifier : 1;
-       unsigned int    core_init_notifier : 1;
        unsigned int    msi_capable : 1;
        unsigned int    msix_capable : 1;
        struct  pci_epc_bar_desc bar[PCI_STD_NUM_BARS];
@@ -225,6 +225,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf,
 void pci_epc_linkup(struct pci_epc *epc);
 void pci_epc_linkdown(struct pci_epc *epc);
 void pci_epc_init_notify(struct pci_epc *epc);
+void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf);
 void pci_epc_bme_notify(struct pci_epc *epc);
 void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
                        enum pci_epc_interface_type type);
This page took 0.094666 seconds and 4 git commands to generate.