xref: /openbmc/linux/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
18ec8015aSSrujana Challa // SPDX-License-Identifier: GPL-2.0-only
28ec8015aSSrujana Challa /* Copyright (C) 2020 Marvell. */
38ec8015aSSrujana Challa 
48ec8015aSSrujana Challa #include "otx2_cptvf.h"
58ec8015aSSrujana Challa #include "otx2_cpt_common.h"
68ec8015aSSrujana Challa 
78ec8015aSSrujana Challa /* SG list header size in bytes */
88ec8015aSSrujana Challa #define SG_LIST_HDR_SIZE	8
98ec8015aSSrujana Challa 
108ec8015aSSrujana Challa /* Default timeout when waiting for free pending entry in us */
118ec8015aSSrujana Challa #define CPT_PENTRY_TIMEOUT	1000
128ec8015aSSrujana Challa #define CPT_PENTRY_STEP		50
138ec8015aSSrujana Challa 
148ec8015aSSrujana Challa /* Default threshold for stopping and resuming sender requests */
158ec8015aSSrujana Challa #define CPT_IQ_STOP_MARGIN	128
168ec8015aSSrujana Challa #define CPT_IQ_RESUME_MARGIN	512
178ec8015aSSrujana Challa 
188ec8015aSSrujana Challa /* Default command timeout in seconds */
198ec8015aSSrujana Challa #define CPT_COMMAND_TIMEOUT	4
208ec8015aSSrujana Challa #define CPT_TIME_IN_RESET_COUNT 5
218ec8015aSSrujana Challa 
otx2_cpt_dump_sg_list(struct pci_dev * pdev,struct otx2_cpt_req_info * req)228ec8015aSSrujana Challa static void otx2_cpt_dump_sg_list(struct pci_dev *pdev,
238ec8015aSSrujana Challa 				  struct otx2_cpt_req_info *req)
248ec8015aSSrujana Challa {
258ec8015aSSrujana Challa 	int i;
268ec8015aSSrujana Challa 
278ec8015aSSrujana Challa 	pr_debug("Gather list size %d\n", req->in_cnt);
288ec8015aSSrujana Challa 	for (i = 0; i < req->in_cnt; i++) {
298ec8015aSSrujana Challa 		pr_debug("Buffer %d size %d, vptr 0x%p, dmaptr 0x%p\n", i,
308ec8015aSSrujana Challa 			 req->in[i].size, req->in[i].vptr,
318ec8015aSSrujana Challa 			 (void *) req->in[i].dma_addr);
328ec8015aSSrujana Challa 		pr_debug("Buffer hexdump (%d bytes)\n",
338ec8015aSSrujana Challa 			 req->in[i].size);
348ec8015aSSrujana Challa 		print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1,
358ec8015aSSrujana Challa 				     req->in[i].vptr, req->in[i].size, false);
368ec8015aSSrujana Challa 	}
378ec8015aSSrujana Challa 	pr_debug("Scatter list size %d\n", req->out_cnt);
388ec8015aSSrujana Challa 	for (i = 0; i < req->out_cnt; i++) {
398ec8015aSSrujana Challa 		pr_debug("Buffer %d size %d, vptr 0x%p, dmaptr 0x%p\n", i,
408ec8015aSSrujana Challa 			 req->out[i].size, req->out[i].vptr,
418ec8015aSSrujana Challa 			 (void *) req->out[i].dma_addr);
428ec8015aSSrujana Challa 		pr_debug("Buffer hexdump (%d bytes)\n", req->out[i].size);
438ec8015aSSrujana Challa 		print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1,
448ec8015aSSrujana Challa 				     req->out[i].vptr, req->out[i].size, false);
458ec8015aSSrujana Challa 	}
468ec8015aSSrujana Challa }
478ec8015aSSrujana Challa 
get_free_pending_entry(struct otx2_cpt_pending_queue * q,int qlen)488ec8015aSSrujana Challa static inline struct otx2_cpt_pending_entry *get_free_pending_entry(
498ec8015aSSrujana Challa 					struct otx2_cpt_pending_queue *q,
508ec8015aSSrujana Challa 					int qlen)
518ec8015aSSrujana Challa {
528ec8015aSSrujana Challa 	struct otx2_cpt_pending_entry *ent = NULL;
538ec8015aSSrujana Challa 
548ec8015aSSrujana Challa 	ent = &q->head[q->rear];
558ec8015aSSrujana Challa 	if (unlikely(ent->busy))
568ec8015aSSrujana Challa 		return NULL;
578ec8015aSSrujana Challa 
588ec8015aSSrujana Challa 	q->rear++;
598ec8015aSSrujana Challa 	if (unlikely(q->rear == qlen))
608ec8015aSSrujana Challa 		q->rear = 0;
618ec8015aSSrujana Challa 
628ec8015aSSrujana Challa 	return ent;
638ec8015aSSrujana Challa }
648ec8015aSSrujana Challa 
modulo_inc(u32 index,u32 length,u32 inc)658ec8015aSSrujana Challa static inline u32 modulo_inc(u32 index, u32 length, u32 inc)
668ec8015aSSrujana Challa {
678ec8015aSSrujana Challa 	if (WARN_ON(inc > length))
688ec8015aSSrujana Challa 		inc = length;
698ec8015aSSrujana Challa 
708ec8015aSSrujana Challa 	index += inc;
718ec8015aSSrujana Challa 	if (unlikely(index >= length))
728ec8015aSSrujana Challa 		index -= length;
738ec8015aSSrujana Challa 
748ec8015aSSrujana Challa 	return index;
758ec8015aSSrujana Challa }
768ec8015aSSrujana Challa 
free_pentry(struct otx2_cpt_pending_entry * pentry)778ec8015aSSrujana Challa static inline void free_pentry(struct otx2_cpt_pending_entry *pentry)
788ec8015aSSrujana Challa {
798ec8015aSSrujana Challa 	pentry->completion_addr = NULL;
808ec8015aSSrujana Challa 	pentry->info = NULL;
818ec8015aSSrujana Challa 	pentry->callback = NULL;
828ec8015aSSrujana Challa 	pentry->areq = NULL;
838ec8015aSSrujana Challa 	pentry->resume_sender = false;
848ec8015aSSrujana Challa 	pentry->busy = false;
858ec8015aSSrujana Challa }
868ec8015aSSrujana Challa 
setup_sgio_components(struct pci_dev * pdev,struct otx2_cpt_buf_ptr * list,int buf_count,u8 * buffer)878ec8015aSSrujana Challa static inline int setup_sgio_components(struct pci_dev *pdev,
888ec8015aSSrujana Challa 					struct otx2_cpt_buf_ptr *list,
898ec8015aSSrujana Challa 					int buf_count, u8 *buffer)
908ec8015aSSrujana Challa {
918ec8015aSSrujana Challa 	struct otx2_cpt_sglist_component *sg_ptr = NULL;
928ec8015aSSrujana Challa 	int ret = 0, i, j;
938ec8015aSSrujana Challa 	int components;
948ec8015aSSrujana Challa 
958ec8015aSSrujana Challa 	if (unlikely(!list)) {
968ec8015aSSrujana Challa 		dev_err(&pdev->dev, "Input list pointer is NULL\n");
978ec8015aSSrujana Challa 		return -EFAULT;
988ec8015aSSrujana Challa 	}
998ec8015aSSrujana Challa 
1008ec8015aSSrujana Challa 	for (i = 0; i < buf_count; i++) {
1018ec8015aSSrujana Challa 		if (unlikely(!list[i].vptr))
1028ec8015aSSrujana Challa 			continue;
1038ec8015aSSrujana Challa 		list[i].dma_addr = dma_map_single(&pdev->dev, list[i].vptr,
1048ec8015aSSrujana Challa 						  list[i].size,
1058ec8015aSSrujana Challa 						  DMA_BIDIRECTIONAL);
1068ec8015aSSrujana Challa 		if (unlikely(dma_mapping_error(&pdev->dev, list[i].dma_addr))) {
1078ec8015aSSrujana Challa 			dev_err(&pdev->dev, "Dma mapping failed\n");
1088ec8015aSSrujana Challa 			ret = -EIO;
1098ec8015aSSrujana Challa 			goto sg_cleanup;
1108ec8015aSSrujana Challa 		}
1118ec8015aSSrujana Challa 	}
1128ec8015aSSrujana Challa 	components = buf_count / 4;
1138ec8015aSSrujana Challa 	sg_ptr = (struct otx2_cpt_sglist_component *)buffer;
1148ec8015aSSrujana Challa 	for (i = 0; i < components; i++) {
1158ec8015aSSrujana Challa 		sg_ptr->len0 = cpu_to_be16(list[i * 4 + 0].size);
1168ec8015aSSrujana Challa 		sg_ptr->len1 = cpu_to_be16(list[i * 4 + 1].size);
1178ec8015aSSrujana Challa 		sg_ptr->len2 = cpu_to_be16(list[i * 4 + 2].size);
1188ec8015aSSrujana Challa 		sg_ptr->len3 = cpu_to_be16(list[i * 4 + 3].size);
1198ec8015aSSrujana Challa 		sg_ptr->ptr0 = cpu_to_be64(list[i * 4 + 0].dma_addr);
1208ec8015aSSrujana Challa 		sg_ptr->ptr1 = cpu_to_be64(list[i * 4 + 1].dma_addr);
1218ec8015aSSrujana Challa 		sg_ptr->ptr2 = cpu_to_be64(list[i * 4 + 2].dma_addr);
1228ec8015aSSrujana Challa 		sg_ptr->ptr3 = cpu_to_be64(list[i * 4 + 3].dma_addr);
1238ec8015aSSrujana Challa 		sg_ptr++;
1248ec8015aSSrujana Challa 	}
1258ec8015aSSrujana Challa 	components = buf_count % 4;
1268ec8015aSSrujana Challa 
1278ec8015aSSrujana Challa 	switch (components) {
1288ec8015aSSrujana Challa 	case 3:
1298ec8015aSSrujana Challa 		sg_ptr->len2 = cpu_to_be16(list[i * 4 + 2].size);
1308ec8015aSSrujana Challa 		sg_ptr->ptr2 = cpu_to_be64(list[i * 4 + 2].dma_addr);
1318ec8015aSSrujana Challa 		fallthrough;
1328ec8015aSSrujana Challa 	case 2:
1338ec8015aSSrujana Challa 		sg_ptr->len1 = cpu_to_be16(list[i * 4 + 1].size);
1348ec8015aSSrujana Challa 		sg_ptr->ptr1 = cpu_to_be64(list[i * 4 + 1].dma_addr);
1358ec8015aSSrujana Challa 		fallthrough;
1368ec8015aSSrujana Challa 	case 1:
1378ec8015aSSrujana Challa 		sg_ptr->len0 = cpu_to_be16(list[i * 4 + 0].size);
1388ec8015aSSrujana Challa 		sg_ptr->ptr0 = cpu_to_be64(list[i * 4 + 0].dma_addr);
1398ec8015aSSrujana Challa 		break;
1408ec8015aSSrujana Challa 	default:
1418ec8015aSSrujana Challa 		break;
1428ec8015aSSrujana Challa 	}
1438ec8015aSSrujana Challa 	return ret;
1448ec8015aSSrujana Challa 
1458ec8015aSSrujana Challa sg_cleanup:
1468ec8015aSSrujana Challa 	for (j = 0; j < i; j++) {
1478ec8015aSSrujana Challa 		if (list[j].dma_addr) {
1488ec8015aSSrujana Challa 			dma_unmap_single(&pdev->dev, list[j].dma_addr,
1498ec8015aSSrujana Challa 					 list[j].size, DMA_BIDIRECTIONAL);
1508ec8015aSSrujana Challa 		}
1518ec8015aSSrujana Challa 
1528ec8015aSSrujana Challa 		list[j].dma_addr = 0;
1538ec8015aSSrujana Challa 	}
1548ec8015aSSrujana Challa 	return ret;
1558ec8015aSSrujana Challa }
1568ec8015aSSrujana Challa 
info_create(struct pci_dev * pdev,struct otx2_cpt_req_info * req,gfp_t gfp)1578ec8015aSSrujana Challa static inline struct otx2_cpt_inst_info *info_create(struct pci_dev *pdev,
1588ec8015aSSrujana Challa 					      struct otx2_cpt_req_info *req,
1598ec8015aSSrujana Challa 					      gfp_t gfp)
1608ec8015aSSrujana Challa {
1618ec8015aSSrujana Challa 	int align = OTX2_CPT_DMA_MINALIGN;
1628ec8015aSSrujana Challa 	struct otx2_cpt_inst_info *info;
1638ec8015aSSrujana Challa 	u32 dlen, align_dlen, info_len;
1648ec8015aSSrujana Challa 	u16 g_sz_bytes, s_sz_bytes;
1658ec8015aSSrujana Challa 	u32 total_mem_len;
1668ec8015aSSrujana Challa 
1678ec8015aSSrujana Challa 	if (unlikely(req->in_cnt > OTX2_CPT_MAX_SG_IN_CNT ||
1688ec8015aSSrujana Challa 		     req->out_cnt > OTX2_CPT_MAX_SG_OUT_CNT)) {
1698ec8015aSSrujana Challa 		dev_err(&pdev->dev, "Error too many sg components\n");
1708ec8015aSSrujana Challa 		return NULL;
1718ec8015aSSrujana Challa 	}
1728ec8015aSSrujana Challa 
1738ec8015aSSrujana Challa 	g_sz_bytes = ((req->in_cnt + 3) / 4) *
1748ec8015aSSrujana Challa 		      sizeof(struct otx2_cpt_sglist_component);
1758ec8015aSSrujana Challa 	s_sz_bytes = ((req->out_cnt + 3) / 4) *
1768ec8015aSSrujana Challa 		      sizeof(struct otx2_cpt_sglist_component);
1778ec8015aSSrujana Challa 
1788ec8015aSSrujana Challa 	dlen = g_sz_bytes + s_sz_bytes + SG_LIST_HDR_SIZE;
1798ec8015aSSrujana Challa 	align_dlen = ALIGN(dlen, align);
1808ec8015aSSrujana Challa 	info_len = ALIGN(sizeof(*info), align);
1818ec8015aSSrujana Challa 	total_mem_len = align_dlen + info_len + sizeof(union otx2_cpt_res_s);
1828ec8015aSSrujana Challa 
1838ec8015aSSrujana Challa 	info = kzalloc(total_mem_len, gfp);
1848ec8015aSSrujana Challa 	if (unlikely(!info))
1858ec8015aSSrujana Challa 		return NULL;
1868ec8015aSSrujana Challa 
1878ec8015aSSrujana Challa 	info->dlen = dlen;
1888ec8015aSSrujana Challa 	info->in_buffer = (u8 *)info + info_len;
1898ec8015aSSrujana Challa 
1908ec8015aSSrujana Challa 	((u16 *)info->in_buffer)[0] = req->out_cnt;
1918ec8015aSSrujana Challa 	((u16 *)info->in_buffer)[1] = req->in_cnt;
1928ec8015aSSrujana Challa 	((u16 *)info->in_buffer)[2] = 0;
1938ec8015aSSrujana Challa 	((u16 *)info->in_buffer)[3] = 0;
1948ec8015aSSrujana Challa 	cpu_to_be64s((u64 *)info->in_buffer);
1958ec8015aSSrujana Challa 
1968ec8015aSSrujana Challa 	/* Setup gather (input) components */
1978ec8015aSSrujana Challa 	if (setup_sgio_components(pdev, req->in, req->in_cnt,
1988ec8015aSSrujana Challa 				  &info->in_buffer[8])) {
1998ec8015aSSrujana Challa 		dev_err(&pdev->dev, "Failed to setup gather list\n");
2008ec8015aSSrujana Challa 		goto destroy_info;
2018ec8015aSSrujana Challa 	}
2028ec8015aSSrujana Challa 
2038ec8015aSSrujana Challa 	if (setup_sgio_components(pdev, req->out, req->out_cnt,
2048ec8015aSSrujana Challa 				  &info->in_buffer[8 + g_sz_bytes])) {
2058ec8015aSSrujana Challa 		dev_err(&pdev->dev, "Failed to setup scatter list\n");
2068ec8015aSSrujana Challa 		goto destroy_info;
2078ec8015aSSrujana Challa 	}
2088ec8015aSSrujana Challa 
2098ec8015aSSrujana Challa 	info->dma_len = total_mem_len - info_len;
2108ec8015aSSrujana Challa 	info->dptr_baddr = dma_map_single(&pdev->dev, info->in_buffer,
2118ec8015aSSrujana Challa 					  info->dma_len, DMA_BIDIRECTIONAL);
2128ec8015aSSrujana Challa 	if (unlikely(dma_mapping_error(&pdev->dev, info->dptr_baddr))) {
2138ec8015aSSrujana Challa 		dev_err(&pdev->dev, "DMA Mapping failed for cpt req\n");
2148ec8015aSSrujana Challa 		goto destroy_info;
2158ec8015aSSrujana Challa 	}
2168ec8015aSSrujana Challa 	/*
2178ec8015aSSrujana Challa 	 * Get buffer for union otx2_cpt_res_s response
2188ec8015aSSrujana Challa 	 * structure and its physical address
2198ec8015aSSrujana Challa 	 */
2208ec8015aSSrujana Challa 	info->completion_addr = info->in_buffer + align_dlen;
2218ec8015aSSrujana Challa 	info->comp_baddr = info->dptr_baddr + align_dlen;
2228ec8015aSSrujana Challa 
2238ec8015aSSrujana Challa 	return info;
2248ec8015aSSrujana Challa 
2258ec8015aSSrujana Challa destroy_info:
2268ec8015aSSrujana Challa 	otx2_cpt_info_destroy(pdev, info);
2278ec8015aSSrujana Challa 	return NULL;
2288ec8015aSSrujana Challa }
2298ec8015aSSrujana Challa 
process_request(struct pci_dev * pdev,struct otx2_cpt_req_info * req,struct otx2_cpt_pending_queue * pqueue,struct otx2_cptlf_info * lf)2308ec8015aSSrujana Challa static int process_request(struct pci_dev *pdev, struct otx2_cpt_req_info *req,
2318ec8015aSSrujana Challa 			   struct otx2_cpt_pending_queue *pqueue,
2328ec8015aSSrujana Challa 			   struct otx2_cptlf_info *lf)
2338ec8015aSSrujana Challa {
2348ec8015aSSrujana Challa 	struct otx2_cptvf_request *cpt_req = &req->req;
2358ec8015aSSrujana Challa 	struct otx2_cpt_pending_entry *pentry = NULL;
2368ec8015aSSrujana Challa 	union otx2_cpt_ctrl_info *ctrl = &req->ctrl;
2378ec8015aSSrujana Challa 	struct otx2_cpt_inst_info *info = NULL;
2388ec8015aSSrujana Challa 	union otx2_cpt_res_s *result = NULL;
2398ec8015aSSrujana Challa 	struct otx2_cpt_iq_command iq_cmd;
2408ec8015aSSrujana Challa 	union otx2_cpt_inst_s cptinst;
2418ec8015aSSrujana Challa 	int retry, ret = 0;
2428ec8015aSSrujana Challa 	u8 resume_sender;
2438ec8015aSSrujana Challa 	gfp_t gfp;
2448ec8015aSSrujana Challa 
2458ec8015aSSrujana Challa 	gfp = (req->areq->flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL :
2468ec8015aSSrujana Challa 							      GFP_ATOMIC;
2478ec8015aSSrujana Challa 	if (unlikely(!otx2_cptlf_started(lf->lfs)))
2488ec8015aSSrujana Challa 		return -ENODEV;
2498ec8015aSSrujana Challa 
2508ec8015aSSrujana Challa 	info = info_create(pdev, req, gfp);
2518ec8015aSSrujana Challa 	if (unlikely(!info)) {
2528ec8015aSSrujana Challa 		dev_err(&pdev->dev, "Setting up cpt inst info failed");
2538ec8015aSSrujana Challa 		return -ENOMEM;
2548ec8015aSSrujana Challa 	}
2558ec8015aSSrujana Challa 	cpt_req->dlen = info->dlen;
2568ec8015aSSrujana Challa 
2578ec8015aSSrujana Challa 	result = info->completion_addr;
2588ec8015aSSrujana Challa 	result->s.compcode = OTX2_CPT_COMPLETION_CODE_INIT;
2598ec8015aSSrujana Challa 
2608ec8015aSSrujana Challa 	spin_lock_bh(&pqueue->lock);
2618ec8015aSSrujana Challa 	pentry = get_free_pending_entry(pqueue, pqueue->qlen);
2628ec8015aSSrujana Challa 	retry = CPT_PENTRY_TIMEOUT / CPT_PENTRY_STEP;
2638ec8015aSSrujana Challa 	while (unlikely(!pentry) && retry--) {
2648ec8015aSSrujana Challa 		spin_unlock_bh(&pqueue->lock);
2658ec8015aSSrujana Challa 		udelay(CPT_PENTRY_STEP);
2668ec8015aSSrujana Challa 		spin_lock_bh(&pqueue->lock);
2678ec8015aSSrujana Challa 		pentry = get_free_pending_entry(pqueue, pqueue->qlen);
2688ec8015aSSrujana Challa 	}
2698ec8015aSSrujana Challa 
2708ec8015aSSrujana Challa 	if (unlikely(!pentry)) {
2718ec8015aSSrujana Challa 		ret = -ENOSPC;
2728ec8015aSSrujana Challa 		goto destroy_info;
2738ec8015aSSrujana Challa 	}
2748ec8015aSSrujana Challa 
2758ec8015aSSrujana Challa 	/*
2768ec8015aSSrujana Challa 	 * Check if we are close to filling in entire pending queue,
2778ec8015aSSrujana Challa 	 * if so then tell the sender to stop/sleep by returning -EBUSY
2788ec8015aSSrujana Challa 	 * We do it only for context which can sleep (GFP_KERNEL)
2798ec8015aSSrujana Challa 	 */
2808ec8015aSSrujana Challa 	if (gfp == GFP_KERNEL &&
2818ec8015aSSrujana Challa 	    pqueue->pending_count > (pqueue->qlen - CPT_IQ_STOP_MARGIN)) {
2828ec8015aSSrujana Challa 		pentry->resume_sender = true;
2838ec8015aSSrujana Challa 	} else
2848ec8015aSSrujana Challa 		pentry->resume_sender = false;
2858ec8015aSSrujana Challa 	resume_sender = pentry->resume_sender;
2868ec8015aSSrujana Challa 	pqueue->pending_count++;
2878ec8015aSSrujana Challa 
2888ec8015aSSrujana Challa 	pentry->completion_addr = info->completion_addr;
2898ec8015aSSrujana Challa 	pentry->info = info;
2908ec8015aSSrujana Challa 	pentry->callback = req->callback;
2918ec8015aSSrujana Challa 	pentry->areq = req->areq;
2928ec8015aSSrujana Challa 	pentry->busy = true;
2938ec8015aSSrujana Challa 	info->pentry = pentry;
2948ec8015aSSrujana Challa 	info->time_in = jiffies;
2958ec8015aSSrujana Challa 	info->req = req;
2968ec8015aSSrujana Challa 
2978ec8015aSSrujana Challa 	/* Fill in the command */
2988ec8015aSSrujana Challa 	iq_cmd.cmd.u = 0;
2998ec8015aSSrujana Challa 	iq_cmd.cmd.s.opcode = cpu_to_be16(cpt_req->opcode.flags);
3008ec8015aSSrujana Challa 	iq_cmd.cmd.s.param1 = cpu_to_be16(cpt_req->param1);
3018ec8015aSSrujana Challa 	iq_cmd.cmd.s.param2 = cpu_to_be16(cpt_req->param2);
3028ec8015aSSrujana Challa 	iq_cmd.cmd.s.dlen   = cpu_to_be16(cpt_req->dlen);
3038ec8015aSSrujana Challa 
3048ec8015aSSrujana Challa 	/* 64-bit swap for microcode data reads, not needed for addresses*/
3058ec8015aSSrujana Challa 	cpu_to_be64s(&iq_cmd.cmd.u);
3068ec8015aSSrujana Challa 	iq_cmd.dptr = info->dptr_baddr;
3078ec8015aSSrujana Challa 	iq_cmd.rptr = 0;
3088ec8015aSSrujana Challa 	iq_cmd.cptr.u = 0;
3098ec8015aSSrujana Challa 	iq_cmd.cptr.s.grp = ctrl->s.grp;
3108ec8015aSSrujana Challa 
3118ec8015aSSrujana Challa 	/* Fill in the CPT_INST_S type command for HW interpretation */
3128ec8015aSSrujana Challa 	otx2_cpt_fill_inst(&cptinst, &iq_cmd, info->comp_baddr);
3138ec8015aSSrujana Challa 
3148ec8015aSSrujana Challa 	/* Print debug info if enabled */
3158ec8015aSSrujana Challa 	otx2_cpt_dump_sg_list(pdev, req);
3168ec8015aSSrujana Challa 	pr_debug("Cpt_inst_s hexdump (%d bytes)\n", OTX2_CPT_INST_SIZE);
3178ec8015aSSrujana Challa 	print_hex_dump_debug("", 0, 16, 1, &cptinst, OTX2_CPT_INST_SIZE, false);
3188ec8015aSSrujana Challa 	pr_debug("Dptr hexdump (%d bytes)\n", cpt_req->dlen);
3198ec8015aSSrujana Challa 	print_hex_dump_debug("", 0, 16, 1, info->in_buffer,
3208ec8015aSSrujana Challa 			     cpt_req->dlen, false);
3218ec8015aSSrujana Challa 
3228ec8015aSSrujana Challa 	/* Send CPT command */
323*40a645f7SSrujana Challa 	lf->lfs->ops->send_cmd(&cptinst, 1, lf);
3248ec8015aSSrujana Challa 
3258ec8015aSSrujana Challa 	/*
3268ec8015aSSrujana Challa 	 * We allocate and prepare pending queue entry in critical section
3278ec8015aSSrujana Challa 	 * together with submitting CPT instruction to CPT instruction queue
3288ec8015aSSrujana Challa 	 * to make sure that order of CPT requests is the same in both
3298ec8015aSSrujana Challa 	 * pending and instruction queues
3308ec8015aSSrujana Challa 	 */
3318ec8015aSSrujana Challa 	spin_unlock_bh(&pqueue->lock);
3328ec8015aSSrujana Challa 
3338ec8015aSSrujana Challa 	ret = resume_sender ? -EBUSY : -EINPROGRESS;
3348ec8015aSSrujana Challa 	return ret;
3358ec8015aSSrujana Challa 
3368ec8015aSSrujana Challa destroy_info:
3378ec8015aSSrujana Challa 	spin_unlock_bh(&pqueue->lock);
3388ec8015aSSrujana Challa 	otx2_cpt_info_destroy(pdev, info);
3398ec8015aSSrujana Challa 	return ret;
3408ec8015aSSrujana Challa }
3418ec8015aSSrujana Challa 
otx2_cpt_do_request(struct pci_dev * pdev,struct otx2_cpt_req_info * req,int cpu_num)3428ec8015aSSrujana Challa int otx2_cpt_do_request(struct pci_dev *pdev, struct otx2_cpt_req_info *req,
3438ec8015aSSrujana Challa 			int cpu_num)
3448ec8015aSSrujana Challa {
3458ec8015aSSrujana Challa 	struct otx2_cptvf_dev *cptvf = pci_get_drvdata(pdev);
3468ec8015aSSrujana Challa 	struct otx2_cptlfs_info *lfs = &cptvf->lfs;
3478ec8015aSSrujana Challa 
3488ec8015aSSrujana Challa 	return process_request(lfs->pdev, req, &lfs->lf[cpu_num].pqueue,
3498ec8015aSSrujana Challa 			       &lfs->lf[cpu_num]);
3508ec8015aSSrujana Challa }
3518ec8015aSSrujana Challa 
cpt_process_ccode(struct otx2_cptlfs_info * lfs,union otx2_cpt_res_s * cpt_status,struct otx2_cpt_inst_info * info,u32 * res_code)352*40a645f7SSrujana Challa static int cpt_process_ccode(struct otx2_cptlfs_info *lfs,
3538ec8015aSSrujana Challa 			     union otx2_cpt_res_s *cpt_status,
3548ec8015aSSrujana Challa 			     struct otx2_cpt_inst_info *info,
3558ec8015aSSrujana Challa 			     u32 *res_code)
3568ec8015aSSrujana Challa {
357*40a645f7SSrujana Challa 	u8 uc_ccode = lfs->ops->cpt_get_uc_compcode(cpt_status);
358*40a645f7SSrujana Challa 	u8 ccode = lfs->ops->cpt_get_compcode(cpt_status);
359*40a645f7SSrujana Challa 	struct pci_dev *pdev = lfs->pdev;
3608ec8015aSSrujana Challa 
3618ec8015aSSrujana Challa 	switch (ccode) {
3628ec8015aSSrujana Challa 	case OTX2_CPT_COMP_E_FAULT:
3638ec8015aSSrujana Challa 		dev_err(&pdev->dev,
3648ec8015aSSrujana Challa 			"Request failed with DMA fault\n");
3658ec8015aSSrujana Challa 		otx2_cpt_dump_sg_list(pdev, info->req);
3668ec8015aSSrujana Challa 		break;
3678ec8015aSSrujana Challa 
3688ec8015aSSrujana Challa 	case OTX2_CPT_COMP_E_HWERR:
3698ec8015aSSrujana Challa 		dev_err(&pdev->dev,
3708ec8015aSSrujana Challa 			"Request failed with hardware error\n");
3718ec8015aSSrujana Challa 		otx2_cpt_dump_sg_list(pdev, info->req);
3728ec8015aSSrujana Challa 		break;
3738ec8015aSSrujana Challa 
3748ec8015aSSrujana Challa 	case OTX2_CPT_COMP_E_INSTERR:
3758ec8015aSSrujana Challa 		dev_err(&pdev->dev,
3768ec8015aSSrujana Challa 			"Request failed with instruction error\n");
3778ec8015aSSrujana Challa 		otx2_cpt_dump_sg_list(pdev, info->req);
3788ec8015aSSrujana Challa 		break;
3798ec8015aSSrujana Challa 
3808ec8015aSSrujana Challa 	case OTX2_CPT_COMP_E_NOTDONE:
3818ec8015aSSrujana Challa 		/* check for timeout */
3828ec8015aSSrujana Challa 		if (time_after_eq(jiffies, info->time_in +
3838ec8015aSSrujana Challa 				  CPT_COMMAND_TIMEOUT * HZ))
3848ec8015aSSrujana Challa 			dev_warn(&pdev->dev,
3858ec8015aSSrujana Challa 				 "Request timed out 0x%p", info->req);
3868ec8015aSSrujana Challa 		else if (info->extra_time < CPT_TIME_IN_RESET_COUNT) {
3878ec8015aSSrujana Challa 			info->time_in = jiffies;
3888ec8015aSSrujana Challa 			info->extra_time++;
3898ec8015aSSrujana Challa 		}
3908ec8015aSSrujana Challa 		return 1;
3918ec8015aSSrujana Challa 
3928ec8015aSSrujana Challa 	case OTX2_CPT_COMP_E_GOOD:
393*40a645f7SSrujana Challa 	case OTX2_CPT_COMP_E_WARN:
3948ec8015aSSrujana Challa 		/*
3958ec8015aSSrujana Challa 		 * Check microcode completion code, it is only valid
3968ec8015aSSrujana Challa 		 * when completion code is CPT_COMP_E::GOOD
3978ec8015aSSrujana Challa 		 */
3988ec8015aSSrujana Challa 		if (uc_ccode != OTX2_CPT_UCC_SUCCESS) {
3998ec8015aSSrujana Challa 			/*
4008ec8015aSSrujana Challa 			 * If requested hmac is truncated and ucode returns
4018ec8015aSSrujana Challa 			 * s/g write length error then we report success
4028ec8015aSSrujana Challa 			 * because ucode writes as many bytes of calculated
4038ec8015aSSrujana Challa 			 * hmac as available in gather buffer and reports
4048ec8015aSSrujana Challa 			 * s/g write length error if number of bytes in gather
4058ec8015aSSrujana Challa 			 * buffer is less than full hmac size.
4068ec8015aSSrujana Challa 			 */
4078ec8015aSSrujana Challa 			if (info->req->is_trunc_hmac &&
4088ec8015aSSrujana Challa 			    uc_ccode == OTX2_CPT_UCC_SG_WRITE_LENGTH) {
4098ec8015aSSrujana Challa 				*res_code = 0;
4108ec8015aSSrujana Challa 				break;
4118ec8015aSSrujana Challa 			}
4128ec8015aSSrujana Challa 
4138ec8015aSSrujana Challa 			dev_err(&pdev->dev,
4148ec8015aSSrujana Challa 				"Request failed with software error code 0x%x\n",
4158ec8015aSSrujana Challa 				cpt_status->s.uc_compcode);
4168ec8015aSSrujana Challa 			otx2_cpt_dump_sg_list(pdev, info->req);
4178ec8015aSSrujana Challa 			break;
4188ec8015aSSrujana Challa 		}
4198ec8015aSSrujana Challa 		/* Request has been processed with success */
4208ec8015aSSrujana Challa 		*res_code = 0;
4218ec8015aSSrujana Challa 		break;
4228ec8015aSSrujana Challa 
4238ec8015aSSrujana Challa 	default:
4248ec8015aSSrujana Challa 		dev_err(&pdev->dev,
4258ec8015aSSrujana Challa 			"Request returned invalid status %d\n", ccode);
4268ec8015aSSrujana Challa 		break;
4278ec8015aSSrujana Challa 	}
4288ec8015aSSrujana Challa 	return 0;
4298ec8015aSSrujana Challa }
4308ec8015aSSrujana Challa 
process_pending_queue(struct otx2_cptlfs_info * lfs,struct otx2_cpt_pending_queue * pqueue)431*40a645f7SSrujana Challa static inline void process_pending_queue(struct otx2_cptlfs_info *lfs,
4328ec8015aSSrujana Challa 					 struct otx2_cpt_pending_queue *pqueue)
4338ec8015aSSrujana Challa {
4348ec8015aSSrujana Challa 	struct otx2_cpt_pending_entry *resume_pentry = NULL;
4358ec8015aSSrujana Challa 	void (*callback)(int status, void *arg, void *req);
4368ec8015aSSrujana Challa 	struct otx2_cpt_pending_entry *pentry = NULL;
4378ec8015aSSrujana Challa 	union otx2_cpt_res_s *cpt_status = NULL;
4388ec8015aSSrujana Challa 	struct otx2_cpt_inst_info *info = NULL;
4398ec8015aSSrujana Challa 	struct otx2_cpt_req_info *req = NULL;
4408ec8015aSSrujana Challa 	struct crypto_async_request *areq;
441*40a645f7SSrujana Challa 	struct pci_dev *pdev = lfs->pdev;
4428ec8015aSSrujana Challa 	u32 res_code, resume_index;
4438ec8015aSSrujana Challa 
4448ec8015aSSrujana Challa 	while (1) {
4458ec8015aSSrujana Challa 		spin_lock_bh(&pqueue->lock);
4468ec8015aSSrujana Challa 		pentry = &pqueue->head[pqueue->front];
4478ec8015aSSrujana Challa 
4488ec8015aSSrujana Challa 		if (WARN_ON(!pentry)) {
4498ec8015aSSrujana Challa 			spin_unlock_bh(&pqueue->lock);
4508ec8015aSSrujana Challa 			break;
4518ec8015aSSrujana Challa 		}
4528ec8015aSSrujana Challa 
4538ec8015aSSrujana Challa 		res_code = -EINVAL;
4548ec8015aSSrujana Challa 		if (unlikely(!pentry->busy)) {
4558ec8015aSSrujana Challa 			spin_unlock_bh(&pqueue->lock);
4568ec8015aSSrujana Challa 			break;
4578ec8015aSSrujana Challa 		}
4588ec8015aSSrujana Challa 
4598ec8015aSSrujana Challa 		if (unlikely(!pentry->callback)) {
4608ec8015aSSrujana Challa 			dev_err(&pdev->dev, "Callback NULL\n");
4618ec8015aSSrujana Challa 			goto process_pentry;
4628ec8015aSSrujana Challa 		}
4638ec8015aSSrujana Challa 
4648ec8015aSSrujana Challa 		info = pentry->info;
4658ec8015aSSrujana Challa 		if (unlikely(!info)) {
4668ec8015aSSrujana Challa 			dev_err(&pdev->dev, "Pending entry post arg NULL\n");
4678ec8015aSSrujana Challa 			goto process_pentry;
4688ec8015aSSrujana Challa 		}
4698ec8015aSSrujana Challa 
4708ec8015aSSrujana Challa 		req = info->req;
4718ec8015aSSrujana Challa 		if (unlikely(!req)) {
4728ec8015aSSrujana Challa 			dev_err(&pdev->dev, "Request NULL\n");
4738ec8015aSSrujana Challa 			goto process_pentry;
4748ec8015aSSrujana Challa 		}
4758ec8015aSSrujana Challa 
4768ec8015aSSrujana Challa 		cpt_status = pentry->completion_addr;
4778ec8015aSSrujana Challa 		if (unlikely(!cpt_status)) {
4788ec8015aSSrujana Challa 			dev_err(&pdev->dev, "Completion address NULL\n");
4798ec8015aSSrujana Challa 			goto process_pentry;
4808ec8015aSSrujana Challa 		}
4818ec8015aSSrujana Challa 
482*40a645f7SSrujana Challa 		if (cpt_process_ccode(lfs, cpt_status, info, &res_code)) {
4838ec8015aSSrujana Challa 			spin_unlock_bh(&pqueue->lock);
4848ec8015aSSrujana Challa 			return;
4858ec8015aSSrujana Challa 		}
4868ec8015aSSrujana Challa 		info->pdev = pdev;
4878ec8015aSSrujana Challa 
4888ec8015aSSrujana Challa process_pentry:
4898ec8015aSSrujana Challa 		/*
4908ec8015aSSrujana Challa 		 * Check if we should inform sending side to resume
4918ec8015aSSrujana Challa 		 * We do it CPT_IQ_RESUME_MARGIN elements in advance before
4928ec8015aSSrujana Challa 		 * pending queue becomes empty
4938ec8015aSSrujana Challa 		 */
4948ec8015aSSrujana Challa 		resume_index = modulo_inc(pqueue->front, pqueue->qlen,
4958ec8015aSSrujana Challa 					  CPT_IQ_RESUME_MARGIN);
4968ec8015aSSrujana Challa 		resume_pentry = &pqueue->head[resume_index];
4978ec8015aSSrujana Challa 		if (resume_pentry &&
4988ec8015aSSrujana Challa 		    resume_pentry->resume_sender) {
4998ec8015aSSrujana Challa 			resume_pentry->resume_sender = false;
5008ec8015aSSrujana Challa 			callback = resume_pentry->callback;
5018ec8015aSSrujana Challa 			areq = resume_pentry->areq;
5028ec8015aSSrujana Challa 
5038ec8015aSSrujana Challa 			if (callback) {
5048ec8015aSSrujana Challa 				spin_unlock_bh(&pqueue->lock);
5058ec8015aSSrujana Challa 
5068ec8015aSSrujana Challa 				/*
5078ec8015aSSrujana Challa 				 * EINPROGRESS is an indication for sending
5088ec8015aSSrujana Challa 				 * side that it can resume sending requests
5098ec8015aSSrujana Challa 				 */
5108ec8015aSSrujana Challa 				callback(-EINPROGRESS, areq, info);
5118ec8015aSSrujana Challa 				spin_lock_bh(&pqueue->lock);
5128ec8015aSSrujana Challa 			}
5138ec8015aSSrujana Challa 		}
5148ec8015aSSrujana Challa 
5158ec8015aSSrujana Challa 		callback = pentry->callback;
5168ec8015aSSrujana Challa 		areq = pentry->areq;
5178ec8015aSSrujana Challa 		free_pentry(pentry);
5188ec8015aSSrujana Challa 
5198ec8015aSSrujana Challa 		pqueue->pending_count--;
5208ec8015aSSrujana Challa 		pqueue->front = modulo_inc(pqueue->front, pqueue->qlen, 1);
5218ec8015aSSrujana Challa 		spin_unlock_bh(&pqueue->lock);
5228ec8015aSSrujana Challa 
5238ec8015aSSrujana Challa 		/*
5248ec8015aSSrujana Challa 		 * Call callback after current pending entry has been
5258ec8015aSSrujana Challa 		 * processed, we don't do it if the callback pointer is
5268ec8015aSSrujana Challa 		 * invalid.
5278ec8015aSSrujana Challa 		 */
5288ec8015aSSrujana Challa 		if (callback)
5298ec8015aSSrujana Challa 			callback(res_code, areq, info);
5308ec8015aSSrujana Challa 	}
5318ec8015aSSrujana Challa }
5328ec8015aSSrujana Challa 
otx2_cpt_post_process(struct otx2_cptlf_wqe * wqe)5338ec8015aSSrujana Challa void otx2_cpt_post_process(struct otx2_cptlf_wqe *wqe)
5348ec8015aSSrujana Challa {
535*40a645f7SSrujana Challa 	process_pending_queue(wqe->lfs,
5368ec8015aSSrujana Challa 			      &wqe->lfs->lf[wqe->lf_num].pqueue);
5378ec8015aSSrujana Challa }
5386f03f0e8SSrujana Challa 
otx2_cpt_get_kcrypto_eng_grp_num(struct pci_dev * pdev)5396f03f0e8SSrujana Challa int otx2_cpt_get_kcrypto_eng_grp_num(struct pci_dev *pdev)
5406f03f0e8SSrujana Challa {
5416f03f0e8SSrujana Challa 	struct otx2_cptvf_dev *cptvf = pci_get_drvdata(pdev);
5426f03f0e8SSrujana Challa 
5436f03f0e8SSrujana Challa 	return cptvf->lfs.kcrypto_eng_grp_num;
5446f03f0e8SSrujana Challa }
545