diff mbox series

[net-next,3/3] octeontx2-af: Handle CPT function level reset

Message ID 20210113152007.30293-4-schalla@marvell.com
State New
Headers show
Series None | expand

Commit Message

Srujana Challa Jan. 13, 2021, 3:20 p.m. UTC
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(+)

Comments

Saeed Mahameed Jan. 15, 2021, midnight UTC | #1
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 mbox series

Patch

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 */