Message ID | 20210113152007.30293-4-schalla@marvell.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Support for OcteonTX2 98xx CPT block. | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Link |
netdev/fixes_present | success | Link |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | warning | 1 maintainers not CCed: lcherian@marvell.com |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Link |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | success | Errors and warnings before: 0 this patch: 0 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | Link |
netdev/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 111 lines checked |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 3 this patch: 3 |
netdev/header_inline | success | Link |
netdev/stable | success | Stable not CCed |
On Wed, 2021-01-13 at 20:50 +0530, Srujana Challa wrote: > When FLR is initiated for a VF (PCI function level reset), > the parent PF gets a interrupt. PF then sends a message to > admin function (AF), which then cleans up all resources > attached to that VF. This patch adds support to handle > CPT FLR. > > Signed-off-by: Narayana Prasad Raju Atherya <pathreya@marvell.com> > Signed-off-by: Suheil Chandran <schandran@marvell.com> > Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com> > Signed-off-by: Srujana Challa <schalla@marvell.com> > --- > .../net/ethernet/marvell/octeontx2/af/rvu.c | 3 + > .../net/ethernet/marvell/octeontx2/af/rvu.h | 2 + > .../ethernet/marvell/octeontx2/af/rvu_cpt.c | 74 > +++++++++++++++++++ > .../ethernet/marvell/octeontx2/af/rvu_reg.h | 8 ++ > 4 files changed, 87 insertions(+) > > diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c > b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c > index e8fd712860a1..0d538b39462d 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c > +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c > @@ -2150,6 +2150,9 @@ static void rvu_blklf_teardown(struct rvu *rvu, > u16 pcifunc, u8 blkaddr) > rvu_nix_lf_teardown(rvu, pcifunc, block->addr, > lf); > else if (block->addr == BLKADDR_NPA) > rvu_npa_lf_teardown(rvu, pcifunc, lf); > + else if ((block->addr == BLKADDR_CPT0) || > + (block->addr == BLKADDR_CPT1)) > + rvu_cpt_lf_teardown(rvu, pcifunc, lf, slot); > > err = rvu_lf_reset(rvu, block, lf); > if (err) { > diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h > b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h > index b1a6ecfd563e..6f64a13e752a 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h > +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h > @@ -601,6 +601,8 @@ void npc_enable_mcam_entry(struct rvu *rvu, > struct npc_mcam *mcam, > void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam, > int blkaddr, u16 src, struct mcam_entry > *entry, > u8 *intf, u8 *ena); > +/* CPT APIs */ > +int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int lf, int > slot); > > #ifdef CONFIG_DEBUG_FS > void rvu_dbg_init(struct rvu *rvu); > diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c > b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c > index b6de4b95a72a..ea435d7da975 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c > +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c > @@ -240,3 +240,77 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct > rvu *rvu, > > return 0; > } > + > +static void cpt_lf_disable_iqueue(struct rvu *rvu, int blkaddr, int > slot) > +{ > + u64 inprog, grp_ptr; > + int i = 0; > + > + /* Disable instructions enqueuing */ > + rvu_write64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_CTL), > 0x0); > + > + /* Disable executions in the LF's queue */ > + inprog = rvu_read64(rvu, blkaddr, > + CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); > + inprog &= ~BIT_ULL(16); > + rvu_write64(rvu, blkaddr, > + CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), inprog); > + > + /* Wait for CPT queue to become execution-quiescent */ > + do { > + inprog = rvu_read64(rvu, blkaddr, > + CPT_AF_BAR2_ALIASX(slot, > CPT_LF_INPROG)); > + /* Check for partial entries (GRB_PARTIAL) */ > + if (inprog & BIT_ULL(31)) > + i = 0; > + else > + i++; > + > + grp_ptr = rvu_read64(rvu, blkaddr, > + CPT_AF_BAR2_ALIASX(slot, > + CPT_LF_Q_GRP_PT > R)); > + } while ((i < 10) && (((grp_ptr >> 32) & 0x7FFF) != > + (grp_ptr & 0x7FFF))); > What prevents an infinite loop if the HW locks up and you get stuck on a partial entry ? Also it would be nice if you'd wrap this in a nice macro with an informative name: (grp_ptr >> 32) & 0x7FFF) != (grp_ptr & 0x7FFF)) > + i = 0; > + do { > + inprog = rvu_read64(rvu, blkaddr, > + CPT_AF_BAR2_ALIASX(slot, > CPT_LF_INPROG)); > + /* GWB writes groups of 40. So below formula is used > for > + * knowing that no more instructions will be scheduled > + * (INFLIGHT == 0) && (GWB < 40) && (GRB == 0 OR 40) > + */ So why not replace the comment with macros that wrap the below conditions and the code will become self explanatory.. > + if (((inprog & 0x1FF) == 0) && > + (((inprog >> 40) & 0xFF) < 40) && > + ((((inprog >> 32) & 0xFF) == 0) || > + (((inprog >> 32) & 0xFF) == 40))) > + i++; > + else > + i = 0; > + } while (i < 10); > +} > + >
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index e8fd712860a1..0d538b39462d 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -2150,6 +2150,9 @@ static void rvu_blklf_teardown(struct rvu *rvu, u16 pcifunc, u8 blkaddr) rvu_nix_lf_teardown(rvu, pcifunc, block->addr, lf); else if (block->addr == BLKADDR_NPA) rvu_npa_lf_teardown(rvu, pcifunc, lf); + else if ((block->addr == BLKADDR_CPT0) || + (block->addr == BLKADDR_CPT1)) + rvu_cpt_lf_teardown(rvu, pcifunc, lf, slot); err = rvu_lf_reset(rvu, block, lf); if (err) { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index b1a6ecfd563e..6f64a13e752a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -601,6 +601,8 @@ void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam, void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr, u16 src, struct mcam_entry *entry, u8 *intf, u8 *ena); +/* CPT APIs */ +int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int lf, int slot); #ifdef CONFIG_DEBUG_FS void rvu_dbg_init(struct rvu *rvu); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c index b6de4b95a72a..ea435d7da975 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c @@ -240,3 +240,77 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu, return 0; } + +static void cpt_lf_disable_iqueue(struct rvu *rvu, int blkaddr, int slot) +{ + u64 inprog, grp_ptr; + int i = 0; + + /* Disable instructions enqueuing */ + rvu_write64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_CTL), 0x0); + + /* Disable executions in the LF's queue */ + inprog = rvu_read64(rvu, blkaddr, + CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); + inprog &= ~BIT_ULL(16); + rvu_write64(rvu, blkaddr, + CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), inprog); + + /* Wait for CPT queue to become execution-quiescent */ + do { + inprog = rvu_read64(rvu, blkaddr, + CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); + /* Check for partial entries (GRB_PARTIAL) */ + if (inprog & BIT_ULL(31)) + i = 0; + else + i++; + + grp_ptr = rvu_read64(rvu, blkaddr, + CPT_AF_BAR2_ALIASX(slot, + CPT_LF_Q_GRP_PTR)); + } while ((i < 10) && (((grp_ptr >> 32) & 0x7FFF) != + (grp_ptr & 0x7FFF))); + + i = 0; + do { + inprog = rvu_read64(rvu, blkaddr, + CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); + /* GWB writes groups of 40. So below formula is used for + * knowing that no more instructions will be scheduled + * (INFLIGHT == 0) && (GWB < 40) && (GRB == 0 OR 40) + */ + if (((inprog & 0x1FF) == 0) && + (((inprog >> 40) & 0xFF) < 40) && + ((((inprog >> 32) & 0xFF) == 0) || + (((inprog >> 32) & 0xFF) == 40))) + i++; + else + i = 0; + } while (i < 10); +} + +int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int lf, int slot) +{ + int blkaddr; + u64 reg; + + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_CPT, pcifunc); + if (blkaddr != BLKADDR_CPT0 && blkaddr != BLKADDR_CPT1) + return -EINVAL; + + /* Enable BAR2 ALIAS for this pcifunc. */ + reg = BIT_ULL(16) | pcifunc; + rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg); + + cpt_lf_disable_iqueue(rvu, blkaddr, slot); + + /* Set group drop to help clear out hardware */ + reg = rvu_read64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); + reg |= BIT_ULL(17); + rvu_write64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), reg); + + rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0); + + return 0; +} diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h index 0fb2aa909a23..79a6dcf0e3c0 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h @@ -484,9 +484,17 @@ #define CPT_AF_RAS_INT_ENA_W1S (0x47030) #define CPT_AF_RAS_INT_ENA_W1C (0x47038) +#define AF_BAR2_ALIASX(a, b) (0x9100000ull | (a) << 12 | (b)) +#define CPT_AF_BAR2_SEL 0x9000000 +#define CPT_AF_BAR2_ALIASX(a, b) AF_BAR2_ALIASX(a, b) + #define CPT_AF_LF_CTL2_SHIFT 3 #define CPT_AF_LF_SSO_PF_FUNC_SHIFT 32 +#define CPT_LF_CTL 0x10 +#define CPT_LF_INPROG 0x40 +#define CPT_LF_Q_GRP_PTR 0x120 + #define NPC_AF_BLK_RST (0x00040) /* NPC */