Adds APIs to write CPT CTX through microcode op(SET_CTX/WRITE_SA).
Signed-off-by: Srujana Challa <schalla@marvell.com>
Acked-by: Jerin Jacob <jerinj@marvell.com>
struct {
uint64_t cptr : 46;
uint64_t inval : 1;
- uint64_t res : 1;
- uint64_t pf_func : 16;
} s;
};
}
int
-roc_cpt_lf_ctx_flush(struct roc_cpt_lf *lf, uint64_t cptr)
+roc_cpt_lf_ctx_flush(struct roc_cpt_lf *lf, void *cptr, bool inval)
{
union cpt_lf_ctx_flush reg;
return -ENOTSUP;
reg.u = 0;
- reg.s.pf_func = lf->pf_func;
- reg.s.inval = 1;
- reg.s.cptr = cptr;
+ reg.s.inval = inval;
+ reg.s.cptr = (uintptr_t)cptr >> 7;
plt_write64(reg.u, lf->rbase + CPT_LF_CTX_FLUSH);
return 0;
}
+int
+roc_cpt_lf_ctx_reload(struct roc_cpt_lf *lf, void *cptr)
+{
+ union cpt_lf_ctx_reload reg;
+
+ if (lf == NULL) {
+ plt_err("Could not trigger CTX reload");
+ return -ENOTSUP;
+ }
+
+ reg.u = 0;
+ reg.s.cptr = (uintptr_t)cptr >> 7;
+
+ plt_write64(reg.u, lf->rbase + CPT_LF_CTX_RELOAD);
+
+ return 0;
+}
+
void
cpt_lf_fini(struct roc_cpt_lf *lf)
{
return 0;
}
+
+int
+roc_cpt_ctx_write(struct roc_cpt_lf *lf, void *sa_dptr, void *sa_cptr,
+ uint16_t sa_len)
+{
+ uintptr_t lmt_base = lf->lmt_base;
+ uint64_t lmt_arg, io_addr;
+ struct cpt_inst_s *inst;
+ union cpt_res_s *res;
+ uint16_t lmt_id;
+ uint64_t *dptr;
+ int i;
+
+ ROC_LMT_CPT_BASE_ID_GET(lmt_base, lmt_id);
+ inst = (struct cpt_inst_s *)lmt_base;
+
+ memset(inst, 0, sizeof(struct cpt_inst_s));
+
+ res = plt_zmalloc(sizeof(*res), ROC_CPT_RES_ALIGN);
+ if (res == NULL) {
+ plt_err("Couldn't allocate memory for result address");
+ return -ENOMEM;
+ }
+ dptr = plt_zmalloc(sa_len, 0);
+ if (!dptr) {
+ plt_err("Couldn't allocate memory for SA dptr");
+ plt_free(res);
+ return -ENOMEM;
+ }
+ for (i = 0; i < (sa_len / 8); i++)
+ dptr[i] = plt_cpu_to_be_64(((uint64_t *)sa_dptr)[i]);
+
+ /* Fill CPT_INST_S for WRITE_SA microcode op */
+ res->cn10k.compcode = CPT_COMP_NOT_DONE;
+ inst->res_addr = (uint64_t)res;
+ inst->dptr = (uint64_t)dptr;
+ inst->w4.s.param2 = sa_len >> 3;
+ inst->w4.s.dlen = sa_len;
+ inst->w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_WRITE_SA;
+ inst->w4.s.opcode_minor = ROC_IE_OT_MINOR_OP_WRITE_SA;
+ inst->w7.s.cptr = (uint64_t)sa_cptr;
+ inst->w7.s.ctx_val = 1;
+ inst->w7.s.egrp = ROC_CPT_DFLT_ENG_GRP_SE_IE;
+
+ lmt_arg = ROC_CN10K_CPT_LMT_ARG | (uint64_t)lmt_id;
+ io_addr = lf->io_addr | ROC_CN10K_CPT_INST_DW_M1 << 4;
+
+ roc_lmt_submit_steorl(lmt_arg, io_addr);
+ plt_wmb();
+
+ /* Wait until CPT instruction completes */
+ while (res->cn10k.compcode == CPT_COMP_NOT_DONE)
+ plt_delay_ms(1);
+
+ plt_free(res);
+
+ return 0;
+}
(((ROC_CPT_CCM_ICV_LEN - 2) / 2) << 3) | (ROC_CPT_CCM_MSG_LEN - 1))
#define ROC_CPT_CCM_SALT_LEN 3
+#define ROC_CPT_RES_ALIGN 16
+
enum {
ROC_CPT_REVISION_ID_83XX = 0,
ROC_CPT_REVISION_ID_96XX_B0 = 1,
void __roc_api roc_cpt_dev_clear(struct roc_cpt *roc_cpt);
int __roc_api roc_cpt_lf_init(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf);
void __roc_api roc_cpt_lf_fini(struct roc_cpt_lf *lf);
-int __roc_api roc_cpt_lf_ctx_flush(struct roc_cpt_lf *lf, uint64_t cptr);
+int __roc_api roc_cpt_lf_ctx_flush(struct roc_cpt_lf *lf, void *cptr,
+ bool inval);
+int __roc_api roc_cpt_lf_ctx_reload(struct roc_cpt_lf *lf, void *cptr);
int __roc_api roc_cpt_inline_ipsec_cfg(struct dev *dev, uint8_t slot,
struct roc_nix *nix);
int __roc_api roc_cpt_inline_ipsec_inb_cfg(struct roc_cpt *roc_cpt,
struct roc_cpt_lmtline *lmtline, int lf_id);
void __roc_api roc_cpt_parse_hdr_dump(const struct cpt_parse_hdr_s *cpth);
+int __roc_api roc_cpt_ctx_write(struct roc_cpt_lf *lf, void *sa_dptr,
+ void *sa_cptr, uint16_t sa_len);
#endif /* _ROC_CPT_H_ */
#define ROC_IE_OT_MAJOR_OP_PROCESS_OUTBOUND_IPSEC 0x28UL
#define ROC_IE_OT_MAJOR_OP_PROCESS_INBOUND_IPSEC 0x29UL
+#define ROC_IE_OT_MAJOR_OP_WRITE_SA 0x01UL
+#define ROC_IE_OT_MINOR_OP_WRITE_SA 0x09UL
+
+#define ROC_IE_OT_CTX_ILEN 2
+
enum roc_ie_ot_ucc_ipsec {
ROC_IE_OT_UCC_SUCCESS = 0x00,
ROC_IE_OT_UCC_ERR_SA_INVAL = 0xb0,
struct nix *nix = roc_nix_to_nix_priv(roc_nix);
struct roc_nix_ipsec_cfg cfg;
size_t inb_sa_sz;
- int rc;
+ int rc, i;
+ void *sa;
/* CN9K SA size is different */
if (roc_model_is_cn9k())
plt_err("Failed to allocate memory for Inbound SA");
return -ENOMEM;
}
+ if (roc_model_is_cn10k()) {
+ for (i = 0; i < ipsec_in_max_spi; i++) {
+ sa = ((uint8_t *)nix->inb_sa_base) + (i * inb_sa_sz);
+ roc_nix_inl_inb_sa_init(sa);
+ }
+ }
memset(&cfg, 0, sizeof(cfg));
cfg.sa_size = inb_sa_sz;
void *sa_base;
size_t sa_sz;
int i, j, rc;
+ void *sa;
if (idev == NULL)
return -ENOTSUP;
plt_err("Outbound SA base alloc failed");
goto lf_fini;
}
+ if (roc_model_is_cn10k()) {
+ for (i = 0; i < roc_nix->ipsec_out_max_sa; i++) {
+ sa = ((uint8_t *)sa_base) + (i * sa_sz);
+ roc_nix_inl_outb_sa_init(sa);
+ }
+ }
nix->outb_sa_base = sa_base;
nix->outb_sa_sz = sa_sz;
{
struct nix *nix = roc_nix_to_nix_priv(roc_nix);
struct roc_cpt_lf *outb_lf = nix->cpt_lf_base;
+ struct idev_cfg *idev = idev_get_cfg();
+ struct nix_inl_dev *inl_dev = NULL;
union cpt_lf_ctx_reload reload;
union cpt_lf_ctx_flush flush;
uintptr_t rbase;
return 0;
}
- if (!inb && !outb_lf)
- return -EINVAL;
+ if (inb && nix->inb_inl_dev) {
+ outb_lf = NULL;
+ if (idev)
+ inl_dev = idev->nix_inl_dev;
+ if (inl_dev)
+ outb_lf = &inl_dev->cpt_lf;
+ }
- /* Performing op via outbound lf is enough
- * when inline dev is not in use.
- */
- if (outb_lf && !nix->inb_inl_dev) {
+ if (outb_lf) {
rbase = outb_lf->rbase;
flush.u = 0;
}
return 0;
}
+ plt_err("Could not get CPT LF for SA sync");
+ return -ENOTSUP;
+}
+int
+roc_nix_inl_ctx_write(struct roc_nix *roc_nix, void *sa_dptr, void *sa_cptr,
+ bool inb, uint16_t sa_len)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct roc_cpt_lf *outb_lf = nix->cpt_lf_base;
+ struct idev_cfg *idev = idev_get_cfg();
+ struct nix_inl_dev *inl_dev = NULL;
+ union cpt_lf_ctx_flush flush;
+ uintptr_t rbase;
+ int rc;
+
+ /* Nothing much to do on cn9k */
+ if (roc_model_is_cn9k()) {
+ plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
+ return 0;
+ }
+
+ if (inb && nix->inb_inl_dev) {
+ outb_lf = NULL;
+ if (idev)
+ inl_dev = idev->nix_inl_dev;
+ if (inl_dev && inl_dev->attach_cptlf)
+ outb_lf = &inl_dev->cpt_lf;
+ }
+
+ if (outb_lf) {
+ rbase = outb_lf->rbase;
+ flush.u = 0;
+
+ rc = roc_cpt_ctx_write(outb_lf, sa_dptr, sa_cptr, sa_len);
+ if (rc)
+ return rc;
+ /* Trigger CTX flush to write dirty data back to DRAM */
+ flush.s.cptr = ((uintptr_t)sa_cptr) >> 7;
+ plt_write64(flush.u, rbase + CPT_LF_CTX_FLUSH);
+
+ return 0;
+ }
+ plt_nix_dbg("Could not get CPT LF for CTX write");
return -ENOTSUP;
}
+void
+roc_nix_inl_inb_sa_init(struct roc_ot_ipsec_inb_sa *sa)
+{
+ size_t offset;
+
+ memset(sa, 0, sizeof(struct roc_ot_ipsec_inb_sa));
+
+ offset = offsetof(struct roc_ot_ipsec_inb_sa, ctx);
+ sa->w0.s.hw_ctx_off = offset / ROC_CTX_UNIT_8B;
+ sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
+ sa->w0.s.ctx_size = ROC_IE_OT_CTX_ILEN;
+ sa->w0.s.aop_valid = 1;
+}
+
+void
+roc_nix_inl_outb_sa_init(struct roc_ot_ipsec_outb_sa *sa)
+{
+ size_t offset;
+
+ memset(sa, 0, sizeof(struct roc_ot_ipsec_outb_sa));
+
+ offset = offsetof(struct roc_ot_ipsec_outb_sa, ctx);
+ sa->w0.s.ctx_push_size = (offset / ROC_CTX_UNIT_8B);
+ sa->w0.s.ctx_size = ROC_IE_OT_CTX_ILEN;
+ sa->w0.s.aop_valid = 1;
+}
+
void
roc_nix_inl_dev_lock(void)
{
int __roc_api roc_nix_inl_sa_sync(struct roc_nix *roc_nix, void *sa, bool inb,
enum roc_nix_inl_sa_sync_op op);
+int __roc_api roc_nix_inl_ctx_write(struct roc_nix *roc_nix, void *sa_dptr,
+ void *sa_cptr, bool inb, uint16_t sa_len);
+void __roc_api roc_nix_inl_inb_sa_init(struct roc_ot_ipsec_inb_sa *sa);
+void __roc_api roc_nix_inl_outb_sa_init(struct roc_ot_ipsec_outb_sa *sa);
#endif /* _ROC_NIX_INL_H_ */
struct nix_lf_alloc_rsp *rsp;
struct nix_lf_alloc_req *req;
size_t inb_sa_sz;
- int rc = -ENOSPC;
+ int i, rc = -ENOSPC;
+ void *sa;
/* Alloc NIX LF needed for single RQ */
req = mbox_alloc_msg_nix_lf_alloc(mbox);
goto unregister_irqs;
}
+ if (roc_model_is_cn10k()) {
+ for (i = 0; i < ipsec_in_max_spi; i++) {
+ sa = ((uint8_t *)inl_dev->inb_sa_base) +
+ (i * inb_sa_sz);
+ roc_nix_inl_inb_sa_init(sa);
+ }
+ }
/* Setup device specific inb SA table */
rc = nix_inl_nix_ipsec_cfg(inl_dev, true);
if (rc) {
roc_cpt_iq_disable;
roc_cpt_iq_enable;
roc_cpt_lf_ctx_flush;
+ roc_cpt_lf_ctx_reload;
roc_cpt_lf_init;
roc_cpt_lf_fini;
roc_cpt_lfs_print;
roc_cpt_lmtline_init;
roc_cpt_parse_hdr_dump;
roc_cpt_rxc_time_cfg;
+ roc_cpt_ctx_write;
roc_error_msg_get;
roc_hash_sha1_gen;
roc_hash_sha256_gen;
roc_nix_inl_outb_sso_pffunc_get;
roc_nix_inl_outb_is_enabled;
roc_nix_inl_sa_sync;
+ roc_nix_inl_ctx_write;
+ roc_nix_inl_inb_sa_init;
+ roc_nix_inl_outb_sa_init;
roc_nix_is_lbk;
roc_nix_is_pf;
roc_nix_is_sdp;