Path: blob/master/drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h
26285 views
/* SPDX-License-Identifier: GPL-2.0-only1* Copyright (C) 2020 Marvell.2*/34#ifndef __OTX2_CPT_REQMGR_H5#define __OTX2_CPT_REQMGR_H67#include "otx2_cpt_common.h"89/* Completion code size and initial value */10#define OTX2_CPT_COMPLETION_CODE_SIZE 811#define OTX2_CPT_COMPLETION_CODE_INIT OTX2_CPT_COMP_E_NOTDONE12/*13* Maximum total number of SG buffers is 100, we divide it equally14* between input and output15*/16#define OTX2_CPT_MAX_SG_IN_CNT 5017#define OTX2_CPT_MAX_SG_OUT_CNT 501819/* DMA mode direct or SG */20#define OTX2_CPT_DMA_MODE_DIRECT 021#define OTX2_CPT_DMA_MODE_SG 12223/* Context source CPTR or DPTR */24#define OTX2_CPT_FROM_CPTR 025#define OTX2_CPT_FROM_DPTR 12627#define OTX2_CPT_MAX_REQ_SIZE 655352829#define SG_COMPS_MAX 430#define SGV2_COMPS_MAX 33132#define SG_COMP_3 333#define SG_COMP_2 234#define SG_COMP_1 13536#define OTX2_CPT_DPTR_RPTR_ALIGN 837#define OTX2_CPT_RES_ADDR_ALIGN 323839union otx2_cpt_opcode {40u16 flags;41struct {42u8 major;43u8 minor;44} s;45};4647struct otx2_cptvf_request {48u32 param1;49u32 param2;50u16 dlen;51union otx2_cpt_opcode opcode;52dma_addr_t cptr_dma;53void *cptr;54};5556/*57* CPT_INST_S software command definitions58* Words EI (0-3)59*/60union otx2_cpt_iq_cmd_word0 {61u64 u;62struct {63__be16 opcode;64__be16 param1;65__be16 param2;66__be16 dlen;67} s;68};6970union otx2_cpt_iq_cmd_word3 {71u64 u;72struct {73u64 cptr:61;74u64 grp:3;75} s;76};7778struct otx2_cpt_iq_command {79union otx2_cpt_iq_cmd_word0 cmd;80u64 dptr;81u64 rptr;82union otx2_cpt_iq_cmd_word3 cptr;83};8485struct otx2_cpt_pending_entry {86void *completion_addr; /* Completion address */87void *info;88/* Kernel async request callback */89void (*callback)(int status, void *arg1, void *arg2);90struct crypto_async_request *areq; /* Async request callback arg */91u8 resume_sender; /* Notify sender to resume sending requests */92u8 busy; /* Entry status (free/busy) */93};9495struct otx2_cpt_pending_queue {96struct otx2_cpt_pending_entry *head; /* Head of the queue */97u32 front; /* Process work from here */98u32 rear; /* Append new work here */99u32 pending_count; /* Pending requests count */100u32 qlen; /* Queue length */101spinlock_t lock; /* Queue lock */102};103104struct otx2_cpt_buf_ptr {105u8 *vptr;106dma_addr_t dma_addr;107u16 size;108};109110union otx2_cpt_ctrl_info {111u32 flags;112struct {113#if defined(__BIG_ENDIAN_BITFIELD)114u32 reserved_6_31:26;115u32 grp:3; /* Group bits */116u32 dma_mode:2; /* DMA mode */117u32 se_req:1; /* To SE core */118#else119u32 se_req:1; /* To SE core */120u32 dma_mode:2; /* DMA mode */121u32 grp:3; /* Group bits */122u32 reserved_6_31:26;123#endif124} s;125};126127struct otx2_cpt_req_info {128/* Kernel async request callback */129void (*callback)(int status, void *arg1, void *arg2);130struct crypto_async_request *areq; /* Async request callback arg */131struct otx2_cptvf_request req;/* Request information (core specific) */132union otx2_cpt_ctrl_info ctrl;/* User control information */133struct otx2_cpt_buf_ptr in[OTX2_CPT_MAX_SG_IN_CNT];134struct otx2_cpt_buf_ptr out[OTX2_CPT_MAX_SG_OUT_CNT];135u8 *iv_out; /* IV to send back */136u16 rlen; /* Output length */137u8 in_cnt; /* Number of input buffers */138u8 out_cnt; /* Number of output buffers */139u8 req_type; /* Type of request */140u8 is_enc; /* Is a request an encryption request */141u8 is_trunc_hmac;/* Is truncated hmac used */142};143144struct otx2_cpt_inst_info {145struct otx2_cpt_pending_entry *pentry;146struct otx2_cpt_req_info *req;147struct pci_dev *pdev;148void *completion_addr;149u8 *out_buffer;150u8 *in_buffer;151dma_addr_t dptr_baddr;152dma_addr_t rptr_baddr;153dma_addr_t comp_baddr;154unsigned long time_in;155u32 dlen;156u32 dma_len;157u64 gthr_sz;158u64 sctr_sz;159u8 extra_time;160};161162struct otx2_cpt_sglist_component {163__be16 len0;164__be16 len1;165__be16 len2;166__be16 len3;167__be64 ptr0;168__be64 ptr1;169__be64 ptr2;170__be64 ptr3;171};172173struct cn10kb_cpt_sglist_component {174u16 len0;175u16 len1;176u16 len2;177u16 valid_segs;178u64 ptr0;179u64 ptr1;180u64 ptr2;181};182183static inline void otx2_cpt_info_destroy(struct pci_dev *pdev,184struct otx2_cpt_inst_info *info)185{186struct otx2_cpt_req_info *req;187int i;188189if (info->dptr_baddr)190dma_unmap_single(&pdev->dev, info->dptr_baddr,191info->dma_len, DMA_BIDIRECTIONAL);192193if (info->req) {194req = info->req;195for (i = 0; i < req->out_cnt; i++) {196if (req->out[i].dma_addr)197dma_unmap_single(&pdev->dev,198req->out[i].dma_addr,199req->out[i].size,200DMA_BIDIRECTIONAL);201}202203for (i = 0; i < req->in_cnt; i++) {204if (req->in[i].dma_addr)205dma_unmap_single(&pdev->dev,206req->in[i].dma_addr,207req->in[i].size,208DMA_BIDIRECTIONAL);209}210}211kfree(info);212}213214static inline int setup_sgio_components(struct pci_dev *pdev,215struct otx2_cpt_buf_ptr *list,216int buf_count, u8 *buffer)217{218struct otx2_cpt_sglist_component *sg_ptr;219int components;220int i, j;221222if (unlikely(!list)) {223dev_err(&pdev->dev, "Input list pointer is NULL\n");224return -EINVAL;225}226227for (i = 0; i < buf_count; i++) {228if (unlikely(!list[i].vptr))229continue;230list[i].dma_addr = dma_map_single(&pdev->dev, list[i].vptr,231list[i].size,232DMA_BIDIRECTIONAL);233if (unlikely(dma_mapping_error(&pdev->dev, list[i].dma_addr))) {234dev_err(&pdev->dev, "Dma mapping failed\n");235goto sg_cleanup;236}237}238components = buf_count / SG_COMPS_MAX;239sg_ptr = (struct otx2_cpt_sglist_component *)buffer;240for (i = 0; i < components; i++) {241sg_ptr->len0 = cpu_to_be16(list[i * SG_COMPS_MAX + 0].size);242sg_ptr->len1 = cpu_to_be16(list[i * SG_COMPS_MAX + 1].size);243sg_ptr->len2 = cpu_to_be16(list[i * SG_COMPS_MAX + 2].size);244sg_ptr->len3 = cpu_to_be16(list[i * SG_COMPS_MAX + 3].size);245sg_ptr->ptr0 = cpu_to_be64(list[i * SG_COMPS_MAX + 0].dma_addr);246sg_ptr->ptr1 = cpu_to_be64(list[i * SG_COMPS_MAX + 1].dma_addr);247sg_ptr->ptr2 = cpu_to_be64(list[i * SG_COMPS_MAX + 2].dma_addr);248sg_ptr->ptr3 = cpu_to_be64(list[i * SG_COMPS_MAX + 3].dma_addr);249sg_ptr++;250}251components = buf_count % SG_COMPS_MAX;252253switch (components) {254case SG_COMP_3:255sg_ptr->len2 = cpu_to_be16(list[i * SG_COMPS_MAX + 2].size);256sg_ptr->ptr2 = cpu_to_be64(list[i * SG_COMPS_MAX + 2].dma_addr);257fallthrough;258case SG_COMP_2:259sg_ptr->len1 = cpu_to_be16(list[i * SG_COMPS_MAX + 1].size);260sg_ptr->ptr1 = cpu_to_be64(list[i * SG_COMPS_MAX + 1].dma_addr);261fallthrough;262case SG_COMP_1:263sg_ptr->len0 = cpu_to_be16(list[i * SG_COMPS_MAX + 0].size);264sg_ptr->ptr0 = cpu_to_be64(list[i * SG_COMPS_MAX + 0].dma_addr);265break;266default:267break;268}269return 0;270271sg_cleanup:272for (j = 0; j < i; j++) {273if (list[j].dma_addr) {274dma_unmap_single(&pdev->dev, list[j].dma_addr,275list[j].size, DMA_BIDIRECTIONAL);276}277278list[j].dma_addr = 0;279}280return -EIO;281}282283static inline int sgv2io_components_setup(struct pci_dev *pdev,284struct otx2_cpt_buf_ptr *list,285int buf_count, u8 *buffer)286{287struct cn10kb_cpt_sglist_component *sg_ptr;288int components;289int i, j;290291if (unlikely(!list)) {292dev_err(&pdev->dev, "Input list pointer is NULL\n");293return -EFAULT;294}295296for (i = 0; i < buf_count; i++) {297if (unlikely(!list[i].vptr))298continue;299list[i].dma_addr = dma_map_single(&pdev->dev, list[i].vptr,300list[i].size,301DMA_BIDIRECTIONAL);302if (unlikely(dma_mapping_error(&pdev->dev, list[i].dma_addr))) {303dev_err(&pdev->dev, "Dma mapping failed\n");304goto sg_cleanup;305}306}307components = buf_count / SGV2_COMPS_MAX;308sg_ptr = (struct cn10kb_cpt_sglist_component *)buffer;309for (i = 0; i < components; i++) {310sg_ptr->len0 = list[i * SGV2_COMPS_MAX + 0].size;311sg_ptr->len1 = list[i * SGV2_COMPS_MAX + 1].size;312sg_ptr->len2 = list[i * SGV2_COMPS_MAX + 2].size;313sg_ptr->ptr0 = list[i * SGV2_COMPS_MAX + 0].dma_addr;314sg_ptr->ptr1 = list[i * SGV2_COMPS_MAX + 1].dma_addr;315sg_ptr->ptr2 = list[i * SGV2_COMPS_MAX + 2].dma_addr;316sg_ptr->valid_segs = SGV2_COMPS_MAX;317sg_ptr++;318}319components = buf_count % SGV2_COMPS_MAX;320321sg_ptr->valid_segs = components;322switch (components) {323case SG_COMP_2:324sg_ptr->len1 = list[i * SGV2_COMPS_MAX + 1].size;325sg_ptr->ptr1 = list[i * SGV2_COMPS_MAX + 1].dma_addr;326fallthrough;327case SG_COMP_1:328sg_ptr->len0 = list[i * SGV2_COMPS_MAX + 0].size;329sg_ptr->ptr0 = list[i * SGV2_COMPS_MAX + 0].dma_addr;330break;331default:332break;333}334return 0;335336sg_cleanup:337for (j = 0; j < i; j++) {338if (list[j].dma_addr) {339dma_unmap_single(&pdev->dev, list[j].dma_addr,340list[j].size, DMA_BIDIRECTIONAL);341}342343list[j].dma_addr = 0;344}345return -EIO;346}347348static inline struct otx2_cpt_inst_info *349cn10k_sgv2_info_create(struct pci_dev *pdev, struct otx2_cpt_req_info *req,350gfp_t gfp)351{352u32 dlen = 0, g_len, s_len, sg_len, info_len;353struct otx2_cpt_inst_info *info;354u32 total_mem_len;355int i;356357/* Allocate memory to meet below alignment requirement:358* ------------------------------------359* | struct otx2_cpt_inst_info |360* | (No alignment required) |361* | --------------------------------|362* | | padding for ARCH_DMA_MINALIGN |363* | | alignment |364* |------------------------------------|365* | SG List Gather/Input memory |366* | Length = multiple of 32Bytes |367* | Alignment = 8Byte |368* |---------------------------------- |369* | SG List Scatter/Output memory |370* | Length = multiple of 32Bytes |371* | Alignment = 8Byte |372* | -------------------------------|373* | | padding for 32B alignment |374* |------------------------------------|375* | Result response memory |376* | Alignment = 32Byte |377* ------------------------------------378*/379380info_len = sizeof(*info);381382g_len = ((req->in_cnt + 2) / 3) *383sizeof(struct cn10kb_cpt_sglist_component);384s_len = ((req->out_cnt + 2) / 3) *385sizeof(struct cn10kb_cpt_sglist_component);386sg_len = g_len + s_len;387388/* Allocate extra memory for SG and response address alignment */389total_mem_len = ALIGN(info_len, OTX2_CPT_DPTR_RPTR_ALIGN);390total_mem_len += (ARCH_DMA_MINALIGN - 1) &391~(OTX2_CPT_DPTR_RPTR_ALIGN - 1);392total_mem_len += ALIGN(sg_len, OTX2_CPT_RES_ADDR_ALIGN);393total_mem_len += sizeof(union otx2_cpt_res_s);394395info = kzalloc(total_mem_len, gfp);396if (unlikely(!info))397return NULL;398399for (i = 0; i < req->in_cnt; i++)400dlen += req->in[i].size;401402info->dlen = dlen;403info->in_buffer = PTR_ALIGN((u8 *)info + info_len, ARCH_DMA_MINALIGN);404info->out_buffer = info->in_buffer + g_len;405info->gthr_sz = req->in_cnt;406info->sctr_sz = req->out_cnt;407408/* Setup gather (input) components */409if (sgv2io_components_setup(pdev, req->in, req->in_cnt,410info->in_buffer)) {411dev_err(&pdev->dev, "Failed to setup gather list\n");412goto destroy_info;413}414415if (sgv2io_components_setup(pdev, req->out, req->out_cnt,416info->out_buffer)) {417dev_err(&pdev->dev, "Failed to setup scatter list\n");418goto destroy_info;419}420421info->dma_len = total_mem_len - info_len;422info->dptr_baddr = dma_map_single(&pdev->dev, info->in_buffer,423info->dma_len, DMA_BIDIRECTIONAL);424if (unlikely(dma_mapping_error(&pdev->dev, info->dptr_baddr))) {425dev_err(&pdev->dev, "DMA Mapping failed for cpt req\n");426goto destroy_info;427}428info->rptr_baddr = info->dptr_baddr + g_len;429/*430* Get buffer for union otx2_cpt_res_s response431* structure and its physical address432*/433info->completion_addr = PTR_ALIGN((info->in_buffer + sg_len),434OTX2_CPT_RES_ADDR_ALIGN);435info->comp_baddr = ALIGN((info->dptr_baddr + sg_len),436OTX2_CPT_RES_ADDR_ALIGN);437438return info;439440destroy_info:441otx2_cpt_info_destroy(pdev, info);442return NULL;443}444445/* SG list header size in bytes */446#define SG_LIST_HDR_SIZE 8447static inline struct otx2_cpt_inst_info *448otx2_sg_info_create(struct pci_dev *pdev, struct otx2_cpt_req_info *req,449gfp_t gfp)450{451struct otx2_cpt_inst_info *info;452u32 dlen, info_len;453u16 g_len, s_len;454u32 total_mem_len;455456if (unlikely(req->in_cnt > OTX2_CPT_MAX_SG_IN_CNT ||457req->out_cnt > OTX2_CPT_MAX_SG_OUT_CNT)) {458dev_err(&pdev->dev, "Error too many sg components\n");459return NULL;460}461462/* Allocate memory to meet below alignment requirement:463* ------------------------------------464* | struct otx2_cpt_inst_info |465* | (No alignment required) |466* | --------------------------------|467* | | padding for ARCH_DMA_MINALIGN |468* | | alignment |469* |------------------------------------|470* | SG List Header of 8 Byte |471* |------------------------------------|472* | SG List Gather/Input memory |473* | Length = multiple of 32Bytes |474* | Alignment = 8Byte |475* |---------------------------------- |476* | SG List Scatter/Output memory |477* | Length = multiple of 32Bytes |478* | Alignment = 8Byte |479* | -------------------------------|480* | | padding for 32B alignment |481* |------------------------------------|482* | Result response memory |483* | Alignment = 32Byte |484* ------------------------------------485*/486487info_len = sizeof(*info);488489g_len = ((req->in_cnt + 3) / 4) *490sizeof(struct otx2_cpt_sglist_component);491s_len = ((req->out_cnt + 3) / 4) *492sizeof(struct otx2_cpt_sglist_component);493494dlen = g_len + s_len + SG_LIST_HDR_SIZE;495496/* Allocate extra memory for SG and response address alignment */497total_mem_len = ALIGN(info_len, OTX2_CPT_DPTR_RPTR_ALIGN);498total_mem_len += (ARCH_DMA_MINALIGN - 1) &499~(OTX2_CPT_DPTR_RPTR_ALIGN - 1);500total_mem_len += ALIGN(dlen, OTX2_CPT_RES_ADDR_ALIGN);501total_mem_len += sizeof(union otx2_cpt_res_s);502503info = kzalloc(total_mem_len, gfp);504if (unlikely(!info))505return NULL;506507info->dlen = dlen;508info->in_buffer = PTR_ALIGN((u8 *)info + info_len, ARCH_DMA_MINALIGN);509info->out_buffer = info->in_buffer + SG_LIST_HDR_SIZE + g_len;510511((u16 *)info->in_buffer)[0] = req->out_cnt;512((u16 *)info->in_buffer)[1] = req->in_cnt;513((u16 *)info->in_buffer)[2] = 0;514((u16 *)info->in_buffer)[3] = 0;515cpu_to_be64s((u64 *)info->in_buffer);516517/* Setup gather (input) components */518if (setup_sgio_components(pdev, req->in, req->in_cnt,519&info->in_buffer[8])) {520dev_err(&pdev->dev, "Failed to setup gather list\n");521goto destroy_info;522}523524if (setup_sgio_components(pdev, req->out, req->out_cnt,525info->out_buffer)) {526dev_err(&pdev->dev, "Failed to setup scatter list\n");527goto destroy_info;528}529530info->dma_len = total_mem_len - info_len;531info->dptr_baddr = dma_map_single(&pdev->dev, info->in_buffer,532info->dma_len, DMA_BIDIRECTIONAL);533if (unlikely(dma_mapping_error(&pdev->dev, info->dptr_baddr))) {534dev_err(&pdev->dev, "DMA Mapping failed for cpt req\n");535goto destroy_info;536}537/*538* Get buffer for union otx2_cpt_res_s response539* structure and its physical address540*/541info->completion_addr = PTR_ALIGN((info->in_buffer + dlen),542OTX2_CPT_RES_ADDR_ALIGN);543info->comp_baddr = ALIGN((info->dptr_baddr + dlen),544OTX2_CPT_RES_ADDR_ALIGN);545546return info;547548destroy_info:549otx2_cpt_info_destroy(pdev, info);550return NULL;551}552553struct otx2_cptlf_wqe;554int otx2_cpt_do_request(struct pci_dev *pdev, struct otx2_cpt_req_info *req,555int cpu_num);556void otx2_cpt_post_process(struct otx2_cptlf_wqe *wqe);557int otx2_cpt_get_eng_grp_num(struct pci_dev *pdev,558enum otx2_cpt_eng_type);559560#endif /* __OTX2_CPT_REQMGR_H */561562563