Commit 7a590bd6 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'octeontx2-af-miscellaneous-changes-for-cpt'

Srujana Challa says:

====================
octeontx2-af: Miscellaneous changes for CPT

This patchset consists of miscellaneous changes for CPT.
- Adds a new mailbox to reset the requested CPT LF.
- Modify FLR sequence as per HW team suggested.
- Adds support to recover CPT engines when they gets fault.
- Updates CPT inbound inline IPsec configuration mailbox,
  as per new generation of the OcteonTX2 chips.
- Adds a new mailbox to return CPT FLT Interrupt info.
====================

Link: https://lore.kernel.org/r/20230118120354.1017961-1-schalla@marvell.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents c7ef8221 b814cc90
...@@ -195,6 +195,9 @@ M(CPT_STATS, 0xA05, cpt_sts, cpt_sts_req, cpt_sts_rsp) \ ...@@ -195,6 +195,9 @@ M(CPT_STATS, 0xA05, cpt_sts, cpt_sts_req, cpt_sts_rsp) \
M(CPT_RXC_TIME_CFG, 0xA06, cpt_rxc_time_cfg, cpt_rxc_time_cfg_req, \ M(CPT_RXC_TIME_CFG, 0xA06, cpt_rxc_time_cfg, cpt_rxc_time_cfg_req, \
msg_rsp) \ msg_rsp) \
M(CPT_CTX_CACHE_SYNC, 0xA07, cpt_ctx_cache_sync, msg_req, msg_rsp) \ M(CPT_CTX_CACHE_SYNC, 0xA07, cpt_ctx_cache_sync, msg_req, msg_rsp) \
M(CPT_LF_RESET, 0xA08, cpt_lf_reset, cpt_lf_rst_req, msg_rsp) \
M(CPT_FLT_ENG_INFO, 0xA09, cpt_flt_eng_info, cpt_flt_eng_info_req, \
cpt_flt_eng_info_rsp) \
/* SDP mbox IDs (range 0x1000 - 0x11FF) */ \ /* SDP mbox IDs (range 0x1000 - 0x11FF) */ \
M(SET_SDP_CHAN_INFO, 0x1000, set_sdp_chan_info, sdp_chan_info_msg, msg_rsp) \ M(SET_SDP_CHAN_INFO, 0x1000, set_sdp_chan_info, sdp_chan_info_msg, msg_rsp) \
M(GET_SDP_CHAN_INFO, 0x1001, get_sdp_chan_info, msg_req, sdp_get_chan_info_msg) \ M(GET_SDP_CHAN_INFO, 0x1001, get_sdp_chan_info, msg_req, sdp_get_chan_info_msg) \
...@@ -1613,6 +1616,8 @@ struct cpt_lf_alloc_req_msg { ...@@ -1613,6 +1616,8 @@ struct cpt_lf_alloc_req_msg {
u16 sso_pf_func; u16 sso_pf_func;
u16 eng_grpmsk; u16 eng_grpmsk;
int blkaddr; int blkaddr;
u8 ctx_ilen_valid : 1;
u8 ctx_ilen : 7;
}; };
#define CPT_INLINE_INBOUND 0 #define CPT_INLINE_INBOUND 0
...@@ -1696,6 +1701,28 @@ struct cpt_inst_lmtst_req { ...@@ -1696,6 +1701,28 @@ struct cpt_inst_lmtst_req {
u64 rsvd; u64 rsvd;
}; };
/* Mailbox message format to request for CPT LF reset */
struct cpt_lf_rst_req {
struct mbox_msghdr hdr;
u32 slot;
u32 rsvd;
};
/* Mailbox message format to request for CPT faulted engines */
struct cpt_flt_eng_info_req {
struct mbox_msghdr hdr;
int blkaddr;
bool reset;
u32 rsvd;
};
struct cpt_flt_eng_info_rsp {
struct mbox_msghdr hdr;
u64 flt_eng_map[CPT_10K_AF_INT_VEC_RVU];
u64 rcvrd_eng_map[CPT_10K_AF_INT_VEC_RVU];
u64 rsvd;
};
struct sdp_node_info { struct sdp_node_info {
/* Node to which this PF belons to */ /* Node to which this PF belons to */
u8 node_id; u8 node_id;
......
...@@ -1164,8 +1164,16 @@ static int rvu_setup_hw_resources(struct rvu *rvu) ...@@ -1164,8 +1164,16 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
goto nix_err; goto nix_err;
} }
err = rvu_cpt_init(rvu);
if (err) {
dev_err(rvu->dev, "%s: Failed to initialize cpt\n", __func__);
goto mcs_err;
}
return 0; return 0;
mcs_err:
rvu_mcs_exit(rvu);
nix_err: nix_err:
rvu_nix_freemem(rvu); rvu_nix_freemem(rvu);
npa_err: npa_err:
......
...@@ -108,6 +108,8 @@ struct rvu_block { ...@@ -108,6 +108,8 @@ struct rvu_block {
u64 lfreset_reg; u64 lfreset_reg;
unsigned char name[NAME_SIZE]; unsigned char name[NAME_SIZE];
struct rvu *rvu; struct rvu *rvu;
u64 cpt_flt_eng_map[3];
u64 cpt_rcvrd_eng_map[3];
}; };
struct nix_mcast { struct nix_mcast {
...@@ -459,6 +461,7 @@ struct rvu { ...@@ -459,6 +461,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];
...@@ -510,6 +513,7 @@ struct rvu { ...@@ -510,6 +513,7 @@ struct rvu {
struct ptp *ptp; struct ptp *ptp;
int mcs_blk_cnt; int mcs_blk_cnt;
int cpt_pf_num;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
struct rvu_debugfs rvu_dbg; struct rvu_debugfs rvu_dbg;
...@@ -524,6 +528,8 @@ struct rvu { ...@@ -524,6 +528,8 @@ struct rvu {
struct list_head mcs_intrq_head; struct list_head mcs_intrq_head;
/* mcs interrupt queue lock */ /* mcs interrupt queue lock */
spinlock_t mcs_intrq_lock; spinlock_t mcs_intrq_lock;
/* CPT interrupt lock */
spinlock_t cpt_intr_lock;
}; };
static inline void rvu_write64(struct rvu *rvu, u64 block, u64 offset, u64 val) static inline void rvu_write64(struct rvu *rvu, u64 block, u64 offset, u64 val)
...@@ -546,6 +552,17 @@ static inline u64 rvupf_read64(struct rvu *rvu, u64 offset) ...@@ -546,6 +552,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)
{ {
...@@ -865,6 +882,7 @@ void rvu_cpt_unregister_interrupts(struct rvu *rvu); ...@@ -865,6 +882,7 @@ void rvu_cpt_unregister_interrupts(struct rvu *rvu);
int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf,
int slot); int slot);
int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc); int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc);
int rvu_cpt_init(struct rvu *rvu);
/* CN10K RVU */ /* CN10K RVU */
int rvu_set_channels_base(struct rvu *rvu); int rvu_set_channels_base(struct rvu *rvu);
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#define PCI_DEVID_OTX2_CPT10K_PF 0xA0F2 #define PCI_DEVID_OTX2_CPT10K_PF 0xA0F2
/* Length of initial context fetch in 128 byte words */ /* Length of initial context fetch in 128 byte words */
#define CPT_CTX_ILEN 2ULL #define CPT_CTX_ILEN 1ULL
#define cpt_get_eng_sts(e_min, e_max, rsp, etype) \ #define cpt_get_eng_sts(e_min, e_max, rsp, etype) \
({ \ ({ \
...@@ -37,34 +37,68 @@ ...@@ -37,34 +37,68 @@
(_rsp)->free_sts_##etype = free_sts; \ (_rsp)->free_sts_##etype = free_sts; \
}) })
static irqreturn_t rvu_cpt_af_flt_intr_handler(int irq, void *ptr) static irqreturn_t cpt_af_flt_intr_handler(int vec, void *ptr)
{ {
struct rvu_block *block = ptr; struct rvu_block *block = ptr;
struct rvu *rvu = block->rvu; struct rvu *rvu = block->rvu;
int blkaddr = block->addr; int blkaddr = block->addr;
u64 reg0, reg1, reg2; u64 reg, val;
int i, eng;
reg0 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(0)); u8 grp;
reg1 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(1));
if (!is_rvu_otx2(rvu)) { reg = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(vec));
reg2 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(2)); dev_err_ratelimited(rvu->dev, "Received CPTAF FLT%d irq : 0x%llx", vec, reg);
dev_err_ratelimited(rvu->dev,
"Received CPTAF FLT irq : 0x%llx, 0x%llx, 0x%llx", i = -1;
reg0, reg1, reg2); while ((i = find_next_bit((unsigned long *)&reg, 64, i + 1)) < 64) {
} else { switch (vec) {
dev_err_ratelimited(rvu->dev, case 0:
"Received CPTAF FLT irq : 0x%llx, 0x%llx", eng = i;
reg0, reg1); break;
case 1:
eng = i + 64;
break;
case 2:
eng = i + 128;
break;
} }
grp = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_CTL2(eng)) & 0xFF;
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(0), reg0); /* Disable and enable the engine which triggers fault */
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(1), reg1); rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL2(eng), 0x0);
if (!is_rvu_otx2(rvu)) val = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_CTL(eng));
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(2), reg2); rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL(eng), val & ~1ULL);
rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL2(eng), grp);
rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL(eng), val | 1ULL);
spin_lock(&rvu->cpt_intr_lock);
block->cpt_flt_eng_map[vec] |= BIT_ULL(i);
val = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_STS(eng));
val = val & 0x3;
if (val == 0x1 || val == 0x2)
block->cpt_rcvrd_eng_map[vec] |= BIT_ULL(i);
spin_unlock(&rvu->cpt_intr_lock);
}
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(vec), reg);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t rvu_cpt_af_flt0_intr_handler(int irq, void *ptr)
{
return cpt_af_flt_intr_handler(CPT_AF_INT_VEC_FLT0, ptr);
}
static irqreturn_t rvu_cpt_af_flt1_intr_handler(int irq, void *ptr)
{
return cpt_af_flt_intr_handler(CPT_AF_INT_VEC_FLT1, ptr);
}
static irqreturn_t rvu_cpt_af_flt2_intr_handler(int irq, void *ptr)
{
return cpt_af_flt_intr_handler(CPT_10K_AF_INT_VEC_FLT2, ptr);
}
static irqreturn_t rvu_cpt_af_rvu_intr_handler(int irq, void *ptr) static irqreturn_t rvu_cpt_af_rvu_intr_handler(int irq, void *ptr)
{ {
struct rvu_block *block = ptr; struct rvu_block *block = ptr;
...@@ -119,8 +153,10 @@ static void cpt_10k_unregister_interrupts(struct rvu_block *block, int off) ...@@ -119,8 +153,10 @@ static void cpt_10k_unregister_interrupts(struct rvu_block *block, int off)
int i; int i;
/* Disable all CPT AF interrupts */ /* Disable all CPT AF interrupts */
for (i = 0; i < CPT_10K_AF_INT_VEC_RVU; i++) rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(0), ~0ULL);
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(i), 0x1); rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(1), ~0ULL);
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(2), 0xFFFF);
rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1); rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1);
rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1); rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1);
...@@ -151,7 +187,7 @@ static void cpt_unregister_interrupts(struct rvu *rvu, int blkaddr) ...@@ -151,7 +187,7 @@ static void cpt_unregister_interrupts(struct rvu *rvu, int blkaddr)
/* Disable all CPT AF interrupts */ /* Disable all CPT AF interrupts */
for (i = 0; i < CPT_AF_INT_VEC_RVU; i++) for (i = 0; i < CPT_AF_INT_VEC_RVU; i++)
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(i), 0x1); rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(i), ~0ULL);
rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1); rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1);
rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1); rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1);
...@@ -172,16 +208,31 @@ static int cpt_10k_register_interrupts(struct rvu_block *block, int off) ...@@ -172,16 +208,31 @@ static int cpt_10k_register_interrupts(struct rvu_block *block, int off)
{ {
struct rvu *rvu = block->rvu; struct rvu *rvu = block->rvu;
int blkaddr = block->addr; int blkaddr = block->addr;
irq_handler_t flt_fn;
int i, ret; int i, ret;
for (i = CPT_10K_AF_INT_VEC_FLT0; i < CPT_10K_AF_INT_VEC_RVU; i++) { for (i = CPT_10K_AF_INT_VEC_FLT0; i < CPT_10K_AF_INT_VEC_RVU; i++) {
sprintf(&rvu->irq_name[(off + i) * NAME_SIZE], "CPTAF FLT%d", i); sprintf(&rvu->irq_name[(off + i) * NAME_SIZE], "CPTAF FLT%d", i);
switch (i) {
case CPT_10K_AF_INT_VEC_FLT0:
flt_fn = rvu_cpt_af_flt0_intr_handler;
break;
case CPT_10K_AF_INT_VEC_FLT1:
flt_fn = rvu_cpt_af_flt1_intr_handler;
break;
case CPT_10K_AF_INT_VEC_FLT2:
flt_fn = rvu_cpt_af_flt2_intr_handler;
break;
}
ret = rvu_cpt_do_register_interrupt(block, off + i, ret = rvu_cpt_do_register_interrupt(block, off + i,
rvu_cpt_af_flt_intr_handler, flt_fn, &rvu->irq_name[(off + i) * NAME_SIZE]);
&rvu->irq_name[(off + i) * NAME_SIZE]);
if (ret) if (ret)
goto err; goto err;
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0x1); if (i == CPT_10K_AF_INT_VEC_FLT2)
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0xFFFF);
else
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), ~0ULL);
} }
ret = rvu_cpt_do_register_interrupt(block, off + CPT_10K_AF_INT_VEC_RVU, ret = rvu_cpt_do_register_interrupt(block, off + CPT_10K_AF_INT_VEC_RVU,
...@@ -208,8 +259,8 @@ static int cpt_register_interrupts(struct rvu *rvu, int blkaddr) ...@@ -208,8 +259,8 @@ static int cpt_register_interrupts(struct rvu *rvu, int blkaddr)
{ {
struct rvu_hwinfo *hw = rvu->hw; struct rvu_hwinfo *hw = rvu->hw;
struct rvu_block *block; struct rvu_block *block;
irq_handler_t flt_fn;
int i, offs, ret = 0; int i, offs, ret = 0;
char irq_name[16];
if (!is_block_implemented(rvu->hw, blkaddr)) if (!is_block_implemented(rvu->hw, blkaddr))
return 0; return 0;
...@@ -226,13 +277,20 @@ static int cpt_register_interrupts(struct rvu *rvu, int blkaddr) ...@@ -226,13 +277,20 @@ static int cpt_register_interrupts(struct rvu *rvu, int blkaddr)
return cpt_10k_register_interrupts(block, offs); return cpt_10k_register_interrupts(block, offs);
for (i = CPT_AF_INT_VEC_FLT0; i < CPT_AF_INT_VEC_RVU; i++) { for (i = CPT_AF_INT_VEC_FLT0; i < CPT_AF_INT_VEC_RVU; i++) {
snprintf(irq_name, sizeof(irq_name), "CPTAF FLT%d", i); sprintf(&rvu->irq_name[(offs + i) * NAME_SIZE], "CPTAF FLT%d", i);
switch (i) {
case CPT_AF_INT_VEC_FLT0:
flt_fn = rvu_cpt_af_flt0_intr_handler;
break;
case CPT_AF_INT_VEC_FLT1:
flt_fn = rvu_cpt_af_flt1_intr_handler;
break;
}
ret = rvu_cpt_do_register_interrupt(block, offs + i, ret = rvu_cpt_do_register_interrupt(block, offs + i,
rvu_cpt_af_flt_intr_handler, flt_fn, &rvu->irq_name[(offs + i) * NAME_SIZE]);
irq_name);
if (ret) if (ret)
goto err; goto err;
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0x1); rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), ~0ULL);
} }
ret = rvu_cpt_do_register_interrupt(block, offs + CPT_AF_INT_VEC_RVU, ret = rvu_cpt_do_register_interrupt(block, offs + CPT_AF_INT_VEC_RVU,
...@@ -290,7 +348,7 @@ static int get_cpt_pf_num(struct rvu *rvu) ...@@ -290,7 +348,7 @@ static int get_cpt_pf_num(struct rvu *rvu)
static bool is_cpt_pf(struct rvu *rvu, u16 pcifunc) static bool is_cpt_pf(struct rvu *rvu, u16 pcifunc)
{ {
int cpt_pf_num = get_cpt_pf_num(rvu); int cpt_pf_num = rvu->cpt_pf_num;
if (rvu_get_pf(pcifunc) != cpt_pf_num) if (rvu_get_pf(pcifunc) != cpt_pf_num)
return false; return false;
...@@ -302,7 +360,7 @@ static bool is_cpt_pf(struct rvu *rvu, u16 pcifunc) ...@@ -302,7 +360,7 @@ static bool is_cpt_pf(struct rvu *rvu, u16 pcifunc)
static bool is_cpt_vf(struct rvu *rvu, u16 pcifunc) static bool is_cpt_vf(struct rvu *rvu, u16 pcifunc)
{ {
int cpt_pf_num = get_cpt_pf_num(rvu); int cpt_pf_num = rvu->cpt_pf_num;
if (rvu_get_pf(pcifunc) != cpt_pf_num) if (rvu_get_pf(pcifunc) != cpt_pf_num)
return false; return false;
...@@ -371,8 +429,12 @@ int rvu_mbox_handler_cpt_lf_alloc(struct rvu *rvu, ...@@ -371,8 +429,12 @@ int rvu_mbox_handler_cpt_lf_alloc(struct rvu *rvu,
/* Set CPT LF group and priority */ /* Set CPT LF group and priority */
val = (u64)req->eng_grpmsk << 48 | 1; val = (u64)req->eng_grpmsk << 48 | 1;
if (!is_rvu_otx2(rvu)) if (!is_rvu_otx2(rvu)) {
if (req->ctx_ilen_valid)
val |= (req->ctx_ilen << 17);
else
val |= (CPT_CTX_ILEN << 17); val |= (CPT_CTX_ILEN << 17);
}
rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val); rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val);
...@@ -762,10 +824,21 @@ int rvu_mbox_handler_cpt_sts(struct rvu *rvu, struct cpt_sts_req *req, ...@@ -762,10 +824,21 @@ int rvu_mbox_handler_cpt_sts(struct rvu *rvu, struct cpt_sts_req *req,
#define RXC_ZOMBIE_COUNT GENMASK_ULL(60, 48) #define RXC_ZOMBIE_COUNT GENMASK_ULL(60, 48)
static void cpt_rxc_time_cfg(struct rvu *rvu, struct cpt_rxc_time_cfg_req *req, static void cpt_rxc_time_cfg(struct rvu *rvu, struct cpt_rxc_time_cfg_req *req,
int blkaddr) int blkaddr, struct cpt_rxc_time_cfg_req *save)
{ {
u64 dfrg_reg; u64 dfrg_reg;
if (save) {
/* Save older config */
dfrg_reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_DFRG);
save->zombie_thres = FIELD_GET(RXC_ZOMBIE_THRES, dfrg_reg);
save->zombie_limit = FIELD_GET(RXC_ZOMBIE_LIMIT, dfrg_reg);
save->active_thres = FIELD_GET(RXC_ACTIVE_THRES, dfrg_reg);
save->active_limit = FIELD_GET(RXC_ACTIVE_LIMIT, dfrg_reg);
save->step = rvu_read64(rvu, blkaddr, CPT_AF_RXC_TIME_CFG);
}
dfrg_reg = FIELD_PREP(RXC_ZOMBIE_THRES, req->zombie_thres); dfrg_reg = FIELD_PREP(RXC_ZOMBIE_THRES, req->zombie_thres);
dfrg_reg |= FIELD_PREP(RXC_ZOMBIE_LIMIT, req->zombie_limit); dfrg_reg |= FIELD_PREP(RXC_ZOMBIE_LIMIT, req->zombie_limit);
dfrg_reg |= FIELD_PREP(RXC_ACTIVE_THRES, req->active_thres); dfrg_reg |= FIELD_PREP(RXC_ACTIVE_THRES, req->active_thres);
...@@ -790,7 +863,7 @@ int rvu_mbox_handler_cpt_rxc_time_cfg(struct rvu *rvu, ...@@ -790,7 +863,7 @@ int rvu_mbox_handler_cpt_rxc_time_cfg(struct rvu *rvu,
!is_cpt_vf(rvu, req->hdr.pcifunc)) !is_cpt_vf(rvu, req->hdr.pcifunc))
return CPT_AF_ERR_ACCESS_DENIED; return CPT_AF_ERR_ACCESS_DENIED;
cpt_rxc_time_cfg(rvu, req, blkaddr); cpt_rxc_time_cfg(rvu, req, blkaddr, NULL);
return 0; return 0;
} }
...@@ -801,9 +874,67 @@ int rvu_mbox_handler_cpt_ctx_cache_sync(struct rvu *rvu, struct msg_req *req, ...@@ -801,9 +874,67 @@ int rvu_mbox_handler_cpt_ctx_cache_sync(struct rvu *rvu, struct msg_req *req,
return rvu_cpt_ctx_flush(rvu, req->hdr.pcifunc); return rvu_cpt_ctx_flush(rvu, req->hdr.pcifunc);
} }
int rvu_mbox_handler_cpt_lf_reset(struct rvu *rvu, struct cpt_lf_rst_req *req,
struct msg_rsp *rsp)
{
u16 pcifunc = req->hdr.pcifunc;
struct rvu_block *block;
int cptlf, blkaddr, ret;
u16 actual_slot;
u64 ctl, ctl2;
blkaddr = rvu_get_blkaddr_from_slot(rvu, BLKTYPE_CPT, pcifunc,
req->slot, &actual_slot);
if (blkaddr < 0)
return CPT_AF_ERR_LF_INVALID;
block = &rvu->hw->block[blkaddr];
cptlf = rvu_get_lf(rvu, block, pcifunc, actual_slot);
if (cptlf < 0)
return CPT_AF_ERR_LF_INVALID;
ctl = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf));
ctl2 = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf));
ret = rvu_lf_reset(rvu, block, cptlf);
if (ret)
dev_err(rvu->dev, "Failed to reset blkaddr %d LF%d\n",
block->addr, cptlf);
rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), ctl);
rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), ctl2);
return 0;
}
int rvu_mbox_handler_cpt_flt_eng_info(struct rvu *rvu, struct cpt_flt_eng_info_req *req,
struct cpt_flt_eng_info_rsp *rsp)
{
struct rvu_block *block;
unsigned long flags;
int blkaddr, vec;
blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
if (blkaddr < 0)
return blkaddr;
block = &rvu->hw->block[blkaddr];
for (vec = 0; vec < CPT_10K_AF_INT_VEC_RVU; vec++) {
spin_lock_irqsave(&rvu->cpt_intr_lock, flags);
rsp->flt_eng_map[vec] = block->cpt_flt_eng_map[vec];
rsp->rcvrd_eng_map[vec] = block->cpt_rcvrd_eng_map[vec];
if (req->reset) {
block->cpt_flt_eng_map[vec] = 0x0;
block->cpt_rcvrd_eng_map[vec] = 0x0;
}
spin_unlock_irqrestore(&rvu->cpt_intr_lock, flags);
}
return 0;
}
static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr) static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr)
{ {
struct cpt_rxc_time_cfg_req req; struct cpt_rxc_time_cfg_req req, prev;
int timeout = 2000; int timeout = 2000;
u64 reg; u64 reg;
...@@ -819,7 +950,7 @@ static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr) ...@@ -819,7 +950,7 @@ static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr)
req.active_thres = 1; req.active_thres = 1;
req.active_limit = 1; req.active_limit = 1;
cpt_rxc_time_cfg(rvu, &req, blkaddr); cpt_rxc_time_cfg(rvu, &req, blkaddr, &prev);
do { do {
reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ACTIVE_STS); reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ACTIVE_STS);
...@@ -845,70 +976,68 @@ static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr) ...@@ -845,70 +976,68 @@ static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr)
if (timeout == 0) if (timeout == 0)
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");
/* Restore config */
cpt_rxc_time_cfg(rvu, &prev, blkaddr, NULL);
} }
#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)
...@@ -918,18 +1047,15 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int s ...@@ -918,18 +1047,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;
} }
...@@ -940,7 +1066,7 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int s ...@@ -940,7 +1066,7 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int s
static int cpt_inline_inb_lf_cmd_send(struct rvu *rvu, int blkaddr, static int cpt_inline_inb_lf_cmd_send(struct rvu *rvu, int blkaddr,
int nix_blkaddr) int nix_blkaddr)
{ {
int cpt_pf_num = get_cpt_pf_num(rvu); int cpt_pf_num = rvu->cpt_pf_num;
struct cpt_inst_lmtst_req *req; struct cpt_inst_lmtst_req *req;
dma_addr_t res_daddr; dma_addr_t res_daddr;
int timeout = 3000; int timeout = 3000;
...@@ -1064,7 +1190,7 @@ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc) ...@@ -1064,7 +1190,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));
...@@ -1077,10 +1203,19 @@ int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc) ...@@ -1077,10 +1203,19 @@ 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);
return 0; return 0;
} }
int rvu_cpt_init(struct rvu *rvu)
{
/* Retrieve CPT PF number */
rvu->cpt_pf_num = get_cpt_pf_num(rvu);
spin_lock_init(&rvu->cpt_intr_lock);
return 0;
}
...@@ -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