18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci * Marvell OcteonTX CPT driver
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2019 Marvell International Ltd.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify
78c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as
88c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#ifndef __OTX_CPTVF_REQUEST_MANAGER_H
128c2ecf20Sopenharmony_ci#define __OTX_CPTVF_REQUEST_MANAGER_H
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/types.h>
158c2ecf20Sopenharmony_ci#include <linux/crypto.h>
168c2ecf20Sopenharmony_ci#include <linux/pci.h>
178c2ecf20Sopenharmony_ci#include "otx_cpt_hw_types.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*
208c2ecf20Sopenharmony_ci * Maximum total number of SG buffers is 100, we divide it equally
218c2ecf20Sopenharmony_ci * between input and output
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_ci#define OTX_CPT_MAX_SG_IN_CNT		50
248c2ecf20Sopenharmony_ci#define OTX_CPT_MAX_SG_OUT_CNT		50
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/* DMA mode direct or SG */
278c2ecf20Sopenharmony_ci#define OTX_CPT_DMA_DIRECT_DIRECT	0
288c2ecf20Sopenharmony_ci#define OTX_CPT_DMA_GATHER_SCATTER	1
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/* Context source CPTR or DPTR */
318c2ecf20Sopenharmony_ci#define OTX_CPT_FROM_CPTR		0
328c2ecf20Sopenharmony_ci#define OTX_CPT_FROM_DPTR		1
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/* CPT instruction queue alignment */
358c2ecf20Sopenharmony_ci#define OTX_CPT_INST_Q_ALIGNMENT	128
368c2ecf20Sopenharmony_ci#define OTX_CPT_MAX_REQ_SIZE		65535
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/* Default command timeout in seconds */
398c2ecf20Sopenharmony_ci#define OTX_CPT_COMMAND_TIMEOUT		4
408c2ecf20Sopenharmony_ci#define OTX_CPT_TIMER_HOLD		0x03F
418c2ecf20Sopenharmony_ci#define OTX_CPT_COUNT_HOLD		32
428c2ecf20Sopenharmony_ci#define OTX_CPT_TIME_IN_RESET_COUNT     5
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/* Minimum and maximum values for interrupt coalescing */
458c2ecf20Sopenharmony_ci#define OTX_CPT_COALESC_MIN_TIME_WAIT	0x0
468c2ecf20Sopenharmony_ci#define OTX_CPT_COALESC_MAX_TIME_WAIT	((1<<16)-1)
478c2ecf20Sopenharmony_ci#define OTX_CPT_COALESC_MIN_NUM_WAIT	0x0
488c2ecf20Sopenharmony_ci#define OTX_CPT_COALESC_MAX_NUM_WAIT	((1<<20)-1)
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ciunion otx_cpt_opcode_info {
518c2ecf20Sopenharmony_ci	u16 flags;
528c2ecf20Sopenharmony_ci	struct {
538c2ecf20Sopenharmony_ci		u8 major;
548c2ecf20Sopenharmony_ci		u8 minor;
558c2ecf20Sopenharmony_ci	} s;
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistruct otx_cptvf_request {
598c2ecf20Sopenharmony_ci	u32 param1;
608c2ecf20Sopenharmony_ci	u32 param2;
618c2ecf20Sopenharmony_ci	u16 dlen;
628c2ecf20Sopenharmony_ci	union otx_cpt_opcode_info opcode;
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistruct otx_cpt_buf_ptr {
668c2ecf20Sopenharmony_ci	u8 *vptr;
678c2ecf20Sopenharmony_ci	dma_addr_t dma_addr;
688c2ecf20Sopenharmony_ci	u16 size;
698c2ecf20Sopenharmony_ci};
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ciunion otx_cpt_ctrl_info {
728c2ecf20Sopenharmony_ci	u32 flags;
738c2ecf20Sopenharmony_ci	struct {
748c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
758c2ecf20Sopenharmony_ci		u32 reserved0:26;
768c2ecf20Sopenharmony_ci		u32 grp:3;	/* Group bits */
778c2ecf20Sopenharmony_ci		u32 dma_mode:2;	/* DMA mode */
788c2ecf20Sopenharmony_ci		u32 se_req:1;	/* To SE core */
798c2ecf20Sopenharmony_ci#else
808c2ecf20Sopenharmony_ci		u32 se_req:1;	/* To SE core */
818c2ecf20Sopenharmony_ci		u32 dma_mode:2;	/* DMA mode */
828c2ecf20Sopenharmony_ci		u32 grp:3;	/* Group bits */
838c2ecf20Sopenharmony_ci		u32 reserved0:26;
848c2ecf20Sopenharmony_ci#endif
858c2ecf20Sopenharmony_ci	} s;
868c2ecf20Sopenharmony_ci};
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/*
898c2ecf20Sopenharmony_ci * CPT_INST_S software command definitions
908c2ecf20Sopenharmony_ci * Words EI (0-3)
918c2ecf20Sopenharmony_ci */
928c2ecf20Sopenharmony_ciunion otx_cpt_iq_cmd_word0 {
938c2ecf20Sopenharmony_ci	u64 u64;
948c2ecf20Sopenharmony_ci	struct {
958c2ecf20Sopenharmony_ci		__be16 opcode;
968c2ecf20Sopenharmony_ci		__be16 param1;
978c2ecf20Sopenharmony_ci		__be16 param2;
988c2ecf20Sopenharmony_ci		__be16 dlen;
998c2ecf20Sopenharmony_ci	} s;
1008c2ecf20Sopenharmony_ci};
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ciunion otx_cpt_iq_cmd_word3 {
1038c2ecf20Sopenharmony_ci	u64 u64;
1048c2ecf20Sopenharmony_ci	struct {
1058c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
1068c2ecf20Sopenharmony_ci		u64 grp:3;
1078c2ecf20Sopenharmony_ci		u64 cptr:61;
1088c2ecf20Sopenharmony_ci#else
1098c2ecf20Sopenharmony_ci		u64 cptr:61;
1108c2ecf20Sopenharmony_ci		u64 grp:3;
1118c2ecf20Sopenharmony_ci#endif
1128c2ecf20Sopenharmony_ci	} s;
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistruct otx_cpt_iq_cmd {
1168c2ecf20Sopenharmony_ci	union otx_cpt_iq_cmd_word0 cmd;
1178c2ecf20Sopenharmony_ci	u64 dptr;
1188c2ecf20Sopenharmony_ci	u64 rptr;
1198c2ecf20Sopenharmony_ci	union otx_cpt_iq_cmd_word3 cptr;
1208c2ecf20Sopenharmony_ci};
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistruct otx_cpt_sglist_component {
1238c2ecf20Sopenharmony_ci	union {
1248c2ecf20Sopenharmony_ci		u64 len;
1258c2ecf20Sopenharmony_ci		struct {
1268c2ecf20Sopenharmony_ci			__be16 len0;
1278c2ecf20Sopenharmony_ci			__be16 len1;
1288c2ecf20Sopenharmony_ci			__be16 len2;
1298c2ecf20Sopenharmony_ci			__be16 len3;
1308c2ecf20Sopenharmony_ci		} s;
1318c2ecf20Sopenharmony_ci	} u;
1328c2ecf20Sopenharmony_ci	__be64 ptr0;
1338c2ecf20Sopenharmony_ci	__be64 ptr1;
1348c2ecf20Sopenharmony_ci	__be64 ptr2;
1358c2ecf20Sopenharmony_ci	__be64 ptr3;
1368c2ecf20Sopenharmony_ci};
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistruct otx_cpt_pending_entry {
1398c2ecf20Sopenharmony_ci	u64 *completion_addr;	/* Completion address */
1408c2ecf20Sopenharmony_ci	struct otx_cpt_info_buffer *info;
1418c2ecf20Sopenharmony_ci	/* Kernel async request callback */
1428c2ecf20Sopenharmony_ci	void (*callback)(int status, void *arg1, void *arg2);
1438c2ecf20Sopenharmony_ci	struct crypto_async_request *areq; /* Async request callback arg */
1448c2ecf20Sopenharmony_ci	u8 resume_sender;	/* Notify sender to resume sending requests */
1458c2ecf20Sopenharmony_ci	u8 busy;		/* Entry status (free/busy) */
1468c2ecf20Sopenharmony_ci};
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistruct otx_cpt_pending_queue {
1498c2ecf20Sopenharmony_ci	struct otx_cpt_pending_entry *head;	/* Head of the queue */
1508c2ecf20Sopenharmony_ci	u32 front;			/* Process work from here */
1518c2ecf20Sopenharmony_ci	u32 rear;			/* Append new work here */
1528c2ecf20Sopenharmony_ci	u32 pending_count;		/* Pending requests count */
1538c2ecf20Sopenharmony_ci	u32 qlen;			/* Queue length */
1548c2ecf20Sopenharmony_ci	spinlock_t lock;		/* Queue lock */
1558c2ecf20Sopenharmony_ci};
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistruct otx_cpt_req_info {
1588c2ecf20Sopenharmony_ci	/* Kernel async request callback */
1598c2ecf20Sopenharmony_ci	void (*callback)(int status, void *arg1, void *arg2);
1608c2ecf20Sopenharmony_ci	struct crypto_async_request *areq; /* Async request callback arg */
1618c2ecf20Sopenharmony_ci	struct otx_cptvf_request req;/* Request information (core specific) */
1628c2ecf20Sopenharmony_ci	union otx_cpt_ctrl_info ctrl;/* User control information */
1638c2ecf20Sopenharmony_ci	struct otx_cpt_buf_ptr in[OTX_CPT_MAX_SG_IN_CNT];
1648c2ecf20Sopenharmony_ci	struct otx_cpt_buf_ptr out[OTX_CPT_MAX_SG_OUT_CNT];
1658c2ecf20Sopenharmony_ci	u8 *iv_out;     /* IV to send back */
1668c2ecf20Sopenharmony_ci	u16 rlen;	/* Output length */
1678c2ecf20Sopenharmony_ci	u8 incnt;	/* Number of input buffers */
1688c2ecf20Sopenharmony_ci	u8 outcnt;	/* Number of output buffers */
1698c2ecf20Sopenharmony_ci	u8 req_type;	/* Type of request */
1708c2ecf20Sopenharmony_ci	u8 is_enc;	/* Is a request an encryption request */
1718c2ecf20Sopenharmony_ci	u8 is_trunc_hmac;/* Is truncated hmac used */
1728c2ecf20Sopenharmony_ci};
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistruct otx_cpt_info_buffer {
1758c2ecf20Sopenharmony_ci	struct otx_cpt_pending_entry *pentry;
1768c2ecf20Sopenharmony_ci	struct otx_cpt_req_info *req;
1778c2ecf20Sopenharmony_ci	struct pci_dev *pdev;
1788c2ecf20Sopenharmony_ci	u64 *completion_addr;
1798c2ecf20Sopenharmony_ci	u8 *out_buffer;
1808c2ecf20Sopenharmony_ci	u8 *in_buffer;
1818c2ecf20Sopenharmony_ci	dma_addr_t dptr_baddr;
1828c2ecf20Sopenharmony_ci	dma_addr_t rptr_baddr;
1838c2ecf20Sopenharmony_ci	dma_addr_t comp_baddr;
1848c2ecf20Sopenharmony_ci	unsigned long time_in;
1858c2ecf20Sopenharmony_ci	u32 dlen;
1868c2ecf20Sopenharmony_ci	u32 dma_len;
1878c2ecf20Sopenharmony_ci	u8 extra_time;
1888c2ecf20Sopenharmony_ci};
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic inline void do_request_cleanup(struct pci_dev *pdev,
1918c2ecf20Sopenharmony_ci				      struct otx_cpt_info_buffer *info)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	struct otx_cpt_req_info *req;
1948c2ecf20Sopenharmony_ci	int i;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	if (info->dptr_baddr)
1978c2ecf20Sopenharmony_ci		dma_unmap_single(&pdev->dev, info->dptr_baddr,
1988c2ecf20Sopenharmony_ci				 info->dma_len, DMA_BIDIRECTIONAL);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	if (info->req) {
2018c2ecf20Sopenharmony_ci		req = info->req;
2028c2ecf20Sopenharmony_ci		for (i = 0; i < req->outcnt; i++) {
2038c2ecf20Sopenharmony_ci			if (req->out[i].dma_addr)
2048c2ecf20Sopenharmony_ci				dma_unmap_single(&pdev->dev,
2058c2ecf20Sopenharmony_ci						 req->out[i].dma_addr,
2068c2ecf20Sopenharmony_ci						 req->out[i].size,
2078c2ecf20Sopenharmony_ci						 DMA_BIDIRECTIONAL);
2088c2ecf20Sopenharmony_ci		}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci		for (i = 0; i < req->incnt; i++) {
2118c2ecf20Sopenharmony_ci			if (req->in[i].dma_addr)
2128c2ecf20Sopenharmony_ci				dma_unmap_single(&pdev->dev,
2138c2ecf20Sopenharmony_ci						 req->in[i].dma_addr,
2148c2ecf20Sopenharmony_ci						 req->in[i].size,
2158c2ecf20Sopenharmony_ci						 DMA_BIDIRECTIONAL);
2168c2ecf20Sopenharmony_ci		}
2178c2ecf20Sopenharmony_ci	}
2188c2ecf20Sopenharmony_ci	kfree_sensitive(info);
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistruct otx_cptvf_wqe;
2228c2ecf20Sopenharmony_civoid otx_cpt_dump_sg_list(struct pci_dev *pdev, struct otx_cpt_req_info *req);
2238c2ecf20Sopenharmony_civoid otx_cpt_post_process(struct otx_cptvf_wqe *wqe);
2248c2ecf20Sopenharmony_ciint otx_cpt_do_request(struct pci_dev *pdev, struct otx_cpt_req_info *req,
2258c2ecf20Sopenharmony_ci		       int cpu_num);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci#endif /* __OTX_CPTVF_REQUEST_MANAGER_H */
228