[PATCH v2 07/15] soc: octeontx2: Scan blocks for LFs provisioned to PF/VF

2018-09-04 Thread sunil . kovvuri
From: Sunil Goutham 

Scan all RVU blocks to find any 'LF to RVU PF/VF' mapping done by
low level firmware. If found any, mark them as used in respective
block's LF bitmap and also save mapped PF/VF's PF_FUNC info.

This is done to avoid reattaching a block LF to a different RVU PF/VF.

Signed-off-by: Sunil Goutham 
---
 drivers/soc/marvell/octeontx2/rvu.c| 148 -
 drivers/soc/marvell/octeontx2/rvu.h|  16 
 drivers/soc/marvell/octeontx2/rvu_struct.h |  18 
 3 files changed, 180 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/marvell/octeontx2/rvu.c 
b/drivers/soc/marvell/octeontx2/rvu.c
index 25f79bf..9539ab9 100644
--- a/drivers/soc/marvell/octeontx2/rvu.c
+++ b/drivers/soc/marvell/octeontx2/rvu.c
@@ -22,6 +22,8 @@
 #define DRV_STRING  "Marvell OcteonTX2 RVU Admin Function Driver"
 #define DRV_VERSION"1.0"
 
+static int rvu_get_hwvf(struct rvu *rvu, int pcifunc);
+
 /* Supported devices */
 static const struct pci_device_id rvu_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_RVU_AF) },
@@ -66,6 +68,91 @@ int rvu_alloc_bitmap(struct rsrc_bmap *rsrc)
return 0;
 }
 
+static void rvu_update_rsrc_map(struct rvu *rvu, struct rvu_pfvf *pfvf,
+   struct rvu_block *block, u16 pcifunc,
+   u16 lf, bool attach)
+{
+   int devnum, num_lfs = 0;
+   bool is_pf;
+   u64 reg;
+
+   if (lf >= block->lf.max) {
+   dev_err(>pdev->dev,
+   "%s: FATAL: LF %d is >= %s's max lfs i.e %d\n",
+   __func__, lf, block->name, block->lf.max);
+   return;
+   }
+
+   /* Check if this is for a RVU PF or VF */
+   if (pcifunc & RVU_PFVF_FUNC_MASK) {
+   is_pf = false;
+   devnum = rvu_get_hwvf(rvu, pcifunc);
+   } else {
+   is_pf = true;
+   devnum = rvu_get_pf(pcifunc);
+   }
+
+   block->fn_map[lf] = attach ? pcifunc : 0;
+
+   switch (block->type) {
+   case BLKTYPE_NPA:
+   pfvf->npalf = attach ? true : false;
+   num_lfs = pfvf->npalf;
+   break;
+   case BLKTYPE_NIX:
+   pfvf->nixlf = attach ? true : false;
+   num_lfs = pfvf->nixlf;
+   break;
+   case BLKTYPE_SSO:
+   attach ? pfvf->sso++ : pfvf->sso--;
+   num_lfs = pfvf->sso;
+   break;
+   case BLKTYPE_SSOW:
+   attach ? pfvf->ssow++ : pfvf->ssow--;
+   num_lfs = pfvf->ssow;
+   break;
+   case BLKTYPE_TIM:
+   attach ? pfvf->timlfs++ : pfvf->timlfs--;
+   num_lfs = pfvf->timlfs;
+   break;
+   case BLKTYPE_CPT:
+   attach ? pfvf->cptlfs++ : pfvf->cptlfs--;
+   num_lfs = pfvf->cptlfs;
+   break;
+   }
+
+   reg = is_pf ? block->pf_lfcnt_reg : block->vf_lfcnt_reg;
+   rvu_write64(rvu, BLKADDR_RVUM, reg | (devnum << 16), num_lfs);
+}
+
+inline int rvu_get_pf(u16 pcifunc)
+{
+   return (pcifunc >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK;
+}
+
+static int rvu_get_hwvf(struct rvu *rvu, int pcifunc)
+{
+   int pf, func;
+   u64 cfg;
+
+   pf = rvu_get_pf(pcifunc);
+   func = pcifunc & RVU_PFVF_FUNC_MASK;
+
+   /* Get first HWVF attached to this PF */
+   cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf));
+
+   return ((cfg & 0xFFF) + func - 1);
+}
+
+struct rvu_pfvf *rvu_get_pfvf(struct rvu *rvu, int pcifunc)
+{
+   /* Check if it is a PF or VF */
+   if (pcifunc & RVU_PFVF_FUNC_MASK)
+   return >hwvf[rvu_get_hwvf(rvu, pcifunc)];
+   else
+   return >pf[rvu_get_pf(pcifunc)];
+}
+
 static void rvu_check_block_implemented(struct rvu *rvu)
 {
struct rvu_hwinfo *hw = rvu->hw;
@@ -107,6 +194,28 @@ static void rvu_reset_all_blocks(struct rvu *rvu)
rvu_block_reset(rvu, BLKADDR_NDC2, NDC_AF_BLK_RST);
 }
 
+static void rvu_scan_block(struct rvu *rvu, struct rvu_block *block)
+{
+   struct rvu_pfvf *pfvf;
+   u64 cfg;
+   int lf;
+
+   for (lf = 0; lf < block->lf.max; lf++) {
+   cfg = rvu_read64(rvu, block->addr,
+block->lfcfg_reg | (lf << block->lfshift));
+   if (!(cfg & BIT_ULL(63)))
+   continue;
+
+   /* Set this resource as being used */
+   __set_bit(lf, block->lf.bmap);
+
+   /* Get, to whom this LF is attached */
+   pfvf = rvu_get_pfvf(rvu, (cfg >> 8) & 0x);
+   rvu_update_rsrc_map(rvu, pfvf, block,
+   (cfg >> 8) & 0x, lf, true);
+   }
+}
+
 static void rvu_free_hw_resources(struct rvu *rvu)
 {
struct rvu_hwinfo *hw = rvu->hw;
@@ -124,7 +233,7 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
 {
struct rvu_hwinfo *hw = 

[PATCH v2 07/15] soc: octeontx2: Scan blocks for LFs provisioned to PF/VF

2018-09-04 Thread sunil . kovvuri
From: Sunil Goutham 

Scan all RVU blocks to find any 'LF to RVU PF/VF' mapping done by
low level firmware. If found any, mark them as used in respective
block's LF bitmap and also save mapped PF/VF's PF_FUNC info.

This is done to avoid reattaching a block LF to a different RVU PF/VF.

Signed-off-by: Sunil Goutham 
---
 drivers/soc/marvell/octeontx2/rvu.c| 148 -
 drivers/soc/marvell/octeontx2/rvu.h|  16 
 drivers/soc/marvell/octeontx2/rvu_struct.h |  18 
 3 files changed, 180 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/marvell/octeontx2/rvu.c 
b/drivers/soc/marvell/octeontx2/rvu.c
index 25f79bf..9539ab9 100644
--- a/drivers/soc/marvell/octeontx2/rvu.c
+++ b/drivers/soc/marvell/octeontx2/rvu.c
@@ -22,6 +22,8 @@
 #define DRV_STRING  "Marvell OcteonTX2 RVU Admin Function Driver"
 #define DRV_VERSION"1.0"
 
+static int rvu_get_hwvf(struct rvu *rvu, int pcifunc);
+
 /* Supported devices */
 static const struct pci_device_id rvu_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_RVU_AF) },
@@ -66,6 +68,91 @@ int rvu_alloc_bitmap(struct rsrc_bmap *rsrc)
return 0;
 }
 
+static void rvu_update_rsrc_map(struct rvu *rvu, struct rvu_pfvf *pfvf,
+   struct rvu_block *block, u16 pcifunc,
+   u16 lf, bool attach)
+{
+   int devnum, num_lfs = 0;
+   bool is_pf;
+   u64 reg;
+
+   if (lf >= block->lf.max) {
+   dev_err(>pdev->dev,
+   "%s: FATAL: LF %d is >= %s's max lfs i.e %d\n",
+   __func__, lf, block->name, block->lf.max);
+   return;
+   }
+
+   /* Check if this is for a RVU PF or VF */
+   if (pcifunc & RVU_PFVF_FUNC_MASK) {
+   is_pf = false;
+   devnum = rvu_get_hwvf(rvu, pcifunc);
+   } else {
+   is_pf = true;
+   devnum = rvu_get_pf(pcifunc);
+   }
+
+   block->fn_map[lf] = attach ? pcifunc : 0;
+
+   switch (block->type) {
+   case BLKTYPE_NPA:
+   pfvf->npalf = attach ? true : false;
+   num_lfs = pfvf->npalf;
+   break;
+   case BLKTYPE_NIX:
+   pfvf->nixlf = attach ? true : false;
+   num_lfs = pfvf->nixlf;
+   break;
+   case BLKTYPE_SSO:
+   attach ? pfvf->sso++ : pfvf->sso--;
+   num_lfs = pfvf->sso;
+   break;
+   case BLKTYPE_SSOW:
+   attach ? pfvf->ssow++ : pfvf->ssow--;
+   num_lfs = pfvf->ssow;
+   break;
+   case BLKTYPE_TIM:
+   attach ? pfvf->timlfs++ : pfvf->timlfs--;
+   num_lfs = pfvf->timlfs;
+   break;
+   case BLKTYPE_CPT:
+   attach ? pfvf->cptlfs++ : pfvf->cptlfs--;
+   num_lfs = pfvf->cptlfs;
+   break;
+   }
+
+   reg = is_pf ? block->pf_lfcnt_reg : block->vf_lfcnt_reg;
+   rvu_write64(rvu, BLKADDR_RVUM, reg | (devnum << 16), num_lfs);
+}
+
+inline int rvu_get_pf(u16 pcifunc)
+{
+   return (pcifunc >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK;
+}
+
+static int rvu_get_hwvf(struct rvu *rvu, int pcifunc)
+{
+   int pf, func;
+   u64 cfg;
+
+   pf = rvu_get_pf(pcifunc);
+   func = pcifunc & RVU_PFVF_FUNC_MASK;
+
+   /* Get first HWVF attached to this PF */
+   cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf));
+
+   return ((cfg & 0xFFF) + func - 1);
+}
+
+struct rvu_pfvf *rvu_get_pfvf(struct rvu *rvu, int pcifunc)
+{
+   /* Check if it is a PF or VF */
+   if (pcifunc & RVU_PFVF_FUNC_MASK)
+   return >hwvf[rvu_get_hwvf(rvu, pcifunc)];
+   else
+   return >pf[rvu_get_pf(pcifunc)];
+}
+
 static void rvu_check_block_implemented(struct rvu *rvu)
 {
struct rvu_hwinfo *hw = rvu->hw;
@@ -107,6 +194,28 @@ static void rvu_reset_all_blocks(struct rvu *rvu)
rvu_block_reset(rvu, BLKADDR_NDC2, NDC_AF_BLK_RST);
 }
 
+static void rvu_scan_block(struct rvu *rvu, struct rvu_block *block)
+{
+   struct rvu_pfvf *pfvf;
+   u64 cfg;
+   int lf;
+
+   for (lf = 0; lf < block->lf.max; lf++) {
+   cfg = rvu_read64(rvu, block->addr,
+block->lfcfg_reg | (lf << block->lfshift));
+   if (!(cfg & BIT_ULL(63)))
+   continue;
+
+   /* Set this resource as being used */
+   __set_bit(lf, block->lf.bmap);
+
+   /* Get, to whom this LF is attached */
+   pfvf = rvu_get_pfvf(rvu, (cfg >> 8) & 0x);
+   rvu_update_rsrc_map(rvu, pfvf, block,
+   (cfg >> 8) & 0x, lf, true);
+   }
+}
+
 static void rvu_free_hw_resources(struct rvu *rvu)
 {
struct rvu_hwinfo *hw = rvu->hw;
@@ -124,7 +233,7 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
 {
struct rvu_hwinfo *hw =