RE: [PATCH v4 5/7] PCI: cadence: Add support to configure virtual functions

2021-04-06 Thread Tom Joseph


> -Original Message-
> From: Kishon Vijay Abraham I 
> Sent: 10 March 2021 16:10
> 
> Now that support for SR-IOV is added in PCIe endpoint core, add support
> to configure virtual functions in the Cadence PCIe EP driver.
> 
> Signed-off-by: Kishon Vijay Abraham I 
> ---
>  .../pci/controller/cadence/pcie-cadence-ep.c  | 207 --
>  drivers/pci/controller/cadence/pcie-cadence.h |   7 +
>  2 files changed, 197 insertions(+), 17 deletions(-)
> 
Acked-by: Tom Joseph 


[PATCH v4 5/7] PCI: cadence: Add support to configure virtual functions

2021-03-10 Thread Kishon Vijay Abraham I
Now that support for SR-IOV is added in PCIe endpoint core, add support
to configure virtual functions in the Cadence PCIe EP driver.

Signed-off-by: Kishon Vijay Abraham I 
---
 .../pci/controller/cadence/pcie-cadence-ep.c  | 207 --
 drivers/pci/controller/cadence/pcie-cadence.h |   7 +
 2 files changed, 197 insertions(+), 17 deletions(-)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c 
b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index 912a15be8bfd..0bbff57c5787 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -20,7 +20,18 @@ static int cdns_pcie_ep_write_header(struct pci_epc *epc, u8 
fn, u8 vfn,
 struct pci_epf_header *hdr)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+   u32 cap = CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET;
struct cdns_pcie *pcie = &ep->pcie;
+   u32 reg;
+
+   if (vfn > 1) {
+   dev_dbg(&epc->dev, "Only Virtual Function #1 has deviceID\n");
+   return 0;
+   } else if (vfn == 1) {
+   reg = cap + PCI_SRIOV_VF_DID;
+   cdns_pcie_ep_fn_writew(pcie, fn, reg, hdr->deviceid);
+   return 0;
+   }
 
cdns_pcie_ep_fn_writew(pcie, fn, PCI_DEVICE_ID, hdr->deviceid);
cdns_pcie_ep_fn_writeb(pcie, fn, PCI_REVISION_ID, hdr->revid);
@@ -51,12 +62,14 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn, 
u8 vfn,
struct pci_epf_bar *epf_bar)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+   u32 cap = CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET;
struct cdns_pcie_epf *epf = &ep->epf[fn];
struct cdns_pcie *pcie = &ep->pcie;
dma_addr_t bar_phys = epf_bar->phys_addr;
enum pci_barno bar = epf_bar->barno;
int flags = epf_bar->flags;
u32 addr0, addr1, reg, cfg, b, aperture, ctrl;
+   u32 first_vf_offset, stride;
u64 sz;
 
/* BAR size is 2^(aperture + 7) */
@@ -92,19 +105,39 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 
fn, u8 vfn,
 
addr0 = lower_32_bits(bar_phys);
addr1 = upper_32_bits(bar_phys);
+
+   if (vfn == 1) {
+   if (bar < BAR_4) {
+   reg = CDNS_PCIE_LM_EP_VFUNC_BAR_CFG0(fn);
+   b = bar;
+   } else {
+   reg = CDNS_PCIE_LM_EP_VFUNC_BAR_CFG1(fn);
+   b = bar - BAR_4;
+   }
+   } else {
+   if (bar < BAR_4) {
+   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn);
+   b = bar;
+   } else {
+   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG1(fn);
+   b = bar - BAR_4;
+   }
+   }
+
+   if (vfn > 0) {
+   first_vf_offset = cdns_pcie_ep_fn_readw(pcie, fn, cap +
+   PCI_SRIOV_VF_OFFSET);
+   stride = cdns_pcie_ep_fn_readw(pcie, fn, cap +
+  PCI_SRIOV_VF_STRIDE);
+   fn = fn + first_vf_offset + ((vfn - 1) * stride);
+   epf = &epf->epf[vfn - 1];
+   }
+
cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar),
 addr0);
cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar),
 addr1);
 
-   if (bar < BAR_4) {
-   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn);
-   b = bar;
-   } else {
-   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG1(fn);
-   b = bar - BAR_4;
-   }
-
cfg = cdns_pcie_readl(pcie, reg);
cfg &= ~(CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b) |
 CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b));
@@ -121,17 +154,38 @@ static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, 
u8 fn, u8 vfn,
   struct pci_epf_bar *epf_bar)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+   u32 cap = CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET;
struct cdns_pcie_epf *epf = &ep->epf[fn];
struct cdns_pcie *pcie = &ep->pcie;
enum pci_barno bar = epf_bar->barno;
+   u32 first_vf_offset, stride;
u32 reg, cfg, b, ctrl;
 
-   if (bar < BAR_4) {
-   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn);
-   b = bar;
+   if (vfn == 1) {
+   if (bar < BAR_4) {
+   reg = CDNS_PCIE_LM_EP_VFUNC_BAR_CFG0(fn);
+   b = bar;
+   } else {
+   reg = CDNS_PCIE_LM_EP_VFUNC_BAR_CFG1(fn);
+   b = bar - BAR_4;
+   }
} else {
-   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG1(fn);
-   b = bar - BAR_4;
+   if (bar < BAR_4) {
+   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn);