PCI: cadence: Clear the ARI Capability Next Function Number of the last function
authorJasko-EXT Wojciech <wojciech.jasko-EXT@continental-corporation.com>
Sat, 2 Dec 2023 08:50:15 +0000 (14:20 +0530)
committerKrzysztof Wilczyński <kwilczynski@kernel.org>
Sun, 10 Mar 2024 18:33:16 +0000 (18:33 +0000)
Next Function Number field in ARI Capability Register for last function
must be zero by default as per the PCIe specification, indicating there
is no next higher number function but that's not happening in our case,
so this patch clears the Next Function Number field for last function
used.

[kwilczynski: white spaces update for one define]
Link: https://lore.kernel.org/linux-pci/20231202085015.3048516-1-s-vadapalli@ti.com
Signed-off-by: Jasko-EXT Wojciech <wojciech.jasko-EXT@continental-corporation.com>
Signed-off-by: Achal Verma <a-verma1@ti.com>
Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>
drivers/pci/controller/cadence/pcie-cadence-ep.c
drivers/pci/controller/cadence/pcie-cadence.h

index 2d0a8d78bffb525f45e7939561f5427e82e6062e..81c50dc64da96f4c7182e9fc3b19a22d6d04ea0d 100644 (file)
@@ -565,7 +565,8 @@ static int cdns_pcie_ep_start(struct pci_epc *epc)
        struct cdns_pcie *pcie = &ep->pcie;
        struct device *dev = pcie->dev;
        int max_epfs = sizeof(epc->function_num_map) * 8;
-       int ret, value, epf;
+       int ret, epf, last_fn;
+       u32 reg, value;
 
        /*
         * BIT(0) is hardwired to 1, hence function 0 is always enabled
@@ -573,6 +574,17 @@ static int cdns_pcie_ep_start(struct pci_epc *epc)
         */
        cdns_pcie_writel(pcie, CDNS_PCIE_LM_EP_FUNC_CFG, epc->function_num_map);
 
+       /*
+        * Next function field in ARI_CAP_AND_CTR register for last function
+        * should be 0.
+        * Clearing Next Function Number field for the last function used.
+        */
+       last_fn = find_last_bit(&epc->function_num_map, BITS_PER_LONG);
+       reg     = CDNS_PCIE_CORE_PF_I_ARI_CAP_AND_CTRL(last_fn);
+       value  = cdns_pcie_readl(pcie, reg);
+       value &= ~CDNS_PCIE_ARI_CAP_NFN_MASK;
+       cdns_pcie_writel(pcie, reg, value);
+
        if (ep->quirk_disable_flr) {
                for (epf = 0; epf < max_epfs; epf++) {
                        if (!(epc->function_num_map & BIT(epf)))
index 03b96798f858cbad49485cb83016aeef95866d1a..7a66a2f815dcea38c78b1f172f54d7cdd5deb5ad 100644 (file)
 #define CDNS_PCIE_EP_FUNC_DEV_CAP_OFFSET       0xc0
 #define CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET     0x200
 
+/*
+ * Endpoint PF Registers
+ */
+#define CDNS_PCIE_CORE_PF_I_ARI_CAP_AND_CTRL(fn)       (0x144 + (fn) * 0x1000)
+#define CDNS_PCIE_ARI_CAP_NFN_MASK                     GENMASK(15, 8)
+
 /*
  * Root Port Registers (PCI configuration space for the root port function)
  */