Commit 1286c50a authored by Srujana Challa's avatar Srujana Challa Committed by David S. Miller

octeontx2-af: modify FLR sequence for CPT

On OcteonTX2 platform CPT instruction enqueue is only
possible via LMTST operations.
The existing FLR sequence mentioned in HRM requires
a dummy LMTST to CPT but LMTST can't be submitted from
AF driver. So, HW team provided a new sequence to avoid
dummy LMTST. This patch adds code for the same.
Signed-off-by: default avatarSrujana Challa <schalla@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f58cf765
...@@ -459,6 +459,7 @@ struct rvu { ...@@ -459,6 +459,7 @@ struct rvu {
struct rvu_pfvf *pf; struct rvu_pfvf *pf;
struct rvu_pfvf *hwvf; struct rvu_pfvf *hwvf;
struct mutex rsrc_lock; /* Serialize resource alloc/free */ struct mutex rsrc_lock; /* Serialize resource alloc/free */
struct mutex alias_lock; /* Serialize bar2 alias access */
int vfs; /* Number of VFs attached to RVU */ int vfs; /* Number of VFs attached to RVU */
int nix_blkaddr[MAX_NIX_BLKS]; int nix_blkaddr[MAX_NIX_BLKS];
...@@ -546,6 +547,17 @@ static inline u64 rvupf_read64(struct rvu *rvu, u64 offset) ...@@ -546,6 +547,17 @@ static inline u64 rvupf_read64(struct rvu *rvu, u64 offset)
return readq(rvu->pfreg_base + offset); return readq(rvu->pfreg_base + offset);
} }
static inline void rvu_bar2_sel_write64(struct rvu *rvu, u64 block, u64 offset, u64 val)
{
/* HW requires read back of RVU_AF_BAR2_SEL register to make sure completion of
* write operation.
*/
rvu_write64(rvu, block, offset, val);
rvu_read64(rvu, block, offset);
/* Barrier to ensure read completes before accessing LF registers */
mb();
}
/* Silicon revisions */ /* Silicon revisions */
static inline bool is_rvu_pre_96xx_C0(struct rvu *rvu) static inline bool is_rvu_pre_96xx_C0(struct rvu *rvu)
{ {
......
...@@ -930,68 +930,63 @@ static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr) ...@@ -930,68 +930,63 @@ static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr)
dev_warn(rvu->dev, "Poll for RXC zombie count hits hard loop counter\n"); dev_warn(rvu->dev, "Poll for RXC zombie count hits hard loop counter\n");
} }
#define INPROG_INFLIGHT(reg) ((reg) & 0x1FF) #define INFLIGHT GENMASK_ULL(8, 0)
#define INPROG_GRB_PARTIAL(reg) ((reg) & BIT_ULL(31)) #define GRB_CNT GENMASK_ULL(39, 32)
#define INPROG_GRB(reg) (((reg) >> 32) & 0xFF) #define GWB_CNT GENMASK_ULL(47, 40)
#define INPROG_GWB(reg) (((reg) >> 40) & 0xFF) #define XQ_XOR GENMASK_ULL(63, 63)
#define DQPTR GENMASK_ULL(19, 0)
#define NQPTR GENMASK_ULL(51, 32)
static void cpt_lf_disable_iqueue(struct rvu *rvu, int blkaddr, int slot) static void cpt_lf_disable_iqueue(struct rvu *rvu, int blkaddr, int slot)
{ {
int i = 0, hard_lp_ctr = 100000; int timeout = 1000000;
u64 inprog, grp_ptr; u64 inprog, inst_ptr;
u16 nq_ptr, dq_ptr; u64 qsize, pending;
int i = 0;
/* Disable instructions enqueuing */ /* Disable instructions enqueuing */
rvu_write64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_CTL), 0x0); 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, inprog = rvu_read64(rvu, blkaddr,
CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG));
inprog &= ~BIT_ULL(16); inprog |= BIT_ULL(16);
rvu_write64(rvu, blkaddr, rvu_write64(rvu, blkaddr,
CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), inprog); CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), inprog);
/* Wait for CPT queue to become execution-quiescent */ qsize = rvu_read64(rvu, blkaddr,
CPT_AF_BAR2_ALIASX(slot, CPT_LF_Q_SIZE)) & 0x7FFF;
do { do {
inprog = rvu_read64(rvu, blkaddr, inst_ptr = rvu_read64(rvu, blkaddr,
CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); CPT_AF_BAR2_ALIASX(slot, CPT_LF_Q_INST_PTR));
if (INPROG_GRB_PARTIAL(inprog)) { pending = (FIELD_GET(XQ_XOR, inst_ptr) * qsize * 40) +
i = 0; FIELD_GET(NQPTR, inst_ptr) -
hard_lp_ctr--; FIELD_GET(DQPTR, inst_ptr);
} else { udelay(1);
i++; timeout--;
} } while ((pending != 0) && (timeout != 0));
grp_ptr = rvu_read64(rvu, blkaddr,
CPT_AF_BAR2_ALIASX(slot,
CPT_LF_Q_GRP_PTR));
nq_ptr = (grp_ptr >> 32) & 0x7FFF;
dq_ptr = grp_ptr & 0x7FFF;
} while (hard_lp_ctr && (i < 10) && (nq_ptr != dq_ptr));
if (hard_lp_ctr == 0) if (timeout == 0)
dev_warn(rvu->dev, "CPT FLR hits hard loop counter\n"); dev_warn(rvu->dev, "TIMEOUT: CPT poll on pending instructions\n");
i = 0; timeout = 1000000;
hard_lp_ctr = 100000; /* Wait for CPT queue to become execution-quiescent */
do { do {
inprog = rvu_read64(rvu, blkaddr, inprog = rvu_read64(rvu, blkaddr,
CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG));
if ((INPROG_INFLIGHT(inprog) == 0) && if ((FIELD_GET(INFLIGHT, inprog) == 0) &&
(INPROG_GWB(inprog) < 40) && (FIELD_GET(GRB_CNT, inprog) == 0)) {
((INPROG_GRB(inprog) == 0) ||
(INPROG_GRB((inprog)) == 40))) {
i++; i++;
} else { } else {
i = 0; i = 0;
hard_lp_ctr--; timeout--;
} }
} while (hard_lp_ctr && (i < 10)); } while ((timeout != 0) && (i < 10));
if (hard_lp_ctr == 0) if (timeout == 0)
dev_warn(rvu->dev, "CPT FLR hits hard loop counter\n"); dev_warn(rvu->dev, "TIMEOUT: CPT poll on inflight count\n");
/* Wait for 2 us to flush all queue writes to memory */
udelay(2);
} }
int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int slot) int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int slot)
...@@ -1001,18 +996,15 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int s ...@@ -1001,18 +996,15 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int s
if (is_cpt_pf(rvu, pcifunc) || is_cpt_vf(rvu, pcifunc)) if (is_cpt_pf(rvu, pcifunc) || is_cpt_vf(rvu, pcifunc))
cpt_rxc_teardown(rvu, blkaddr); cpt_rxc_teardown(rvu, blkaddr);
mutex_lock(&rvu->alias_lock);
/* Enable BAR2 ALIAS for this pcifunc. */ /* Enable BAR2 ALIAS for this pcifunc. */
reg = BIT_ULL(16) | pcifunc; reg = BIT_ULL(16) | pcifunc;
rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg); rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg);
cpt_lf_disable_iqueue(rvu, blkaddr, slot); cpt_lf_disable_iqueue(rvu, blkaddr, slot);
/* Set group drop to help clear out hardware */ rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0);
reg = rvu_read64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); mutex_unlock(&rvu->alias_lock);
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; return 0;
} }
...@@ -1147,7 +1139,7 @@ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc) ...@@ -1147,7 +1139,7 @@ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc)
/* Enable BAR2 ALIAS for this pcifunc. */ /* Enable BAR2 ALIAS for this pcifunc. */
reg = BIT_ULL(16) | pcifunc; reg = BIT_ULL(16) | pcifunc;
rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg); rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg);
for (i = 0; i < max_ctx_entries; i++) { for (i = 0; i < max_ctx_entries; i++) {
cam_data = rvu_read64(rvu, blkaddr, CPT_AF_CTX_CAM_DATA(i)); cam_data = rvu_read64(rvu, blkaddr, CPT_AF_CTX_CAM_DATA(i));
...@@ -1160,7 +1152,7 @@ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc) ...@@ -1160,7 +1152,7 @@ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc)
reg); reg);
} }
} }
rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0); rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0);
unlock: unlock:
mutex_unlock(&rvu->rsrc_lock); mutex_unlock(&rvu->rsrc_lock);
......
...@@ -545,6 +545,8 @@ ...@@ -545,6 +545,8 @@
#define CPT_LF_CTL 0x10 #define CPT_LF_CTL 0x10
#define CPT_LF_INPROG 0x40 #define CPT_LF_INPROG 0x40
#define CPT_LF_Q_SIZE 0x100
#define CPT_LF_Q_INST_PTR 0x110
#define CPT_LF_Q_GRP_PTR 0x120 #define CPT_LF_Q_GRP_PTR 0x120
#define CPT_LF_CTX_FLUSH 0x510 #define CPT_LF_CTX_FLUSH 0x510
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment