162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci * Marvell OcteonTX CPT driver
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2019 Marvell International Ltd.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify
762306a36Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as
862306a36Sopenharmony_ci * published by the Free Software Foundation.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#ifndef __OTX_CPTVF_REQUEST_MANAGER_H
1262306a36Sopenharmony_ci#define __OTX_CPTVF_REQUEST_MANAGER_H
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/types.h>
1562306a36Sopenharmony_ci#include <linux/crypto.h>
1662306a36Sopenharmony_ci#include <linux/pci.h>
1762306a36Sopenharmony_ci#include "otx_cpt_hw_types.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/*
2062306a36Sopenharmony_ci * Maximum total number of SG buffers is 100, we divide it equally
2162306a36Sopenharmony_ci * between input and output
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ci#define OTX_CPT_MAX_SG_IN_CNT		50
2462306a36Sopenharmony_ci#define OTX_CPT_MAX_SG_OUT_CNT		50
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/* DMA mode direct or SG */
2762306a36Sopenharmony_ci#define OTX_CPT_DMA_DIRECT_DIRECT	0
2862306a36Sopenharmony_ci#define OTX_CPT_DMA_GATHER_SCATTER	1
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* Context source CPTR or DPTR */
3162306a36Sopenharmony_ci#define OTX_CPT_FROM_CPTR		0
3262306a36Sopenharmony_ci#define OTX_CPT_FROM_DPTR		1
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* CPT instruction queue alignment */
3562306a36Sopenharmony_ci#define OTX_CPT_INST_Q_ALIGNMENT	128
3662306a36Sopenharmony_ci#define OTX_CPT_MAX_REQ_SIZE		65535
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/* Default command timeout in seconds */
3962306a36Sopenharmony_ci#define OTX_CPT_COMMAND_TIMEOUT		4
4062306a36Sopenharmony_ci#define OTX_CPT_TIMER_HOLD		0x03F
4162306a36Sopenharmony_ci#define OTX_CPT_COUNT_HOLD		32
4262306a36Sopenharmony_ci#define OTX_CPT_TIME_IN_RESET_COUNT     5
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/* Minimum and maximum values for interrupt coalescing */
4562306a36Sopenharmony_ci#define OTX_CPT_COALESC_MIN_TIME_WAIT	0x0
4662306a36Sopenharmony_ci#define OTX_CPT_COALESC_MAX_TIME_WAIT	((1<<16)-1)
4762306a36Sopenharmony_ci#define OTX_CPT_COALESC_MIN_NUM_WAIT	0x0
4862306a36Sopenharmony_ci#define OTX_CPT_COALESC_MAX_NUM_WAIT	((1<<20)-1)
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ciunion otx_cpt_opcode_info {
5162306a36Sopenharmony_ci	u16 flags;
5262306a36Sopenharmony_ci	struct {
5362306a36Sopenharmony_ci		u8 major;
5462306a36Sopenharmony_ci		u8 minor;
5562306a36Sopenharmony_ci	} s;
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistruct otx_cptvf_request {
5962306a36Sopenharmony_ci	u32 param1;
6062306a36Sopenharmony_ci	u32 param2;
6162306a36Sopenharmony_ci	u16 dlen;
6262306a36Sopenharmony_ci	union otx_cpt_opcode_info opcode;
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistruct otx_cpt_buf_ptr {
6662306a36Sopenharmony_ci	u8 *vptr;
6762306a36Sopenharmony_ci	dma_addr_t dma_addr;
6862306a36Sopenharmony_ci	u16 size;
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ciunion otx_cpt_ctrl_info {
7262306a36Sopenharmony_ci	u32 flags;
7362306a36Sopenharmony_ci	struct {
7462306a36Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
7562306a36Sopenharmony_ci		u32 reserved0:26;
7662306a36Sopenharmony_ci		u32 grp:3;	/* Group bits */
7762306a36Sopenharmony_ci		u32 dma_mode:2;	/* DMA mode */
7862306a36Sopenharmony_ci		u32 se_req:1;	/* To SE core */
7962306a36Sopenharmony_ci#else
8062306a36Sopenharmony_ci		u32 se_req:1;	/* To SE core */
8162306a36Sopenharmony_ci		u32 dma_mode:2;	/* DMA mode */
8262306a36Sopenharmony_ci		u32 grp:3;	/* Group bits */
8362306a36Sopenharmony_ci		u32 reserved0:26;
8462306a36Sopenharmony_ci#endif
8562306a36Sopenharmony_ci	} s;
8662306a36Sopenharmony_ci};
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/*
8962306a36Sopenharmony_ci * CPT_INST_S software command definitions
9062306a36Sopenharmony_ci * Words EI (0-3)
9162306a36Sopenharmony_ci */
9262306a36Sopenharmony_ciunion otx_cpt_iq_cmd_word0 {
9362306a36Sopenharmony_ci	u64 u64;
9462306a36Sopenharmony_ci	struct {
9562306a36Sopenharmony_ci		__be16 opcode;
9662306a36Sopenharmony_ci		__be16 param1;
9762306a36Sopenharmony_ci		__be16 param2;
9862306a36Sopenharmony_ci		__be16 dlen;
9962306a36Sopenharmony_ci	} s;
10062306a36Sopenharmony_ci};
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ciunion otx_cpt_iq_cmd_word3 {
10362306a36Sopenharmony_ci	u64 u64;
10462306a36Sopenharmony_ci	struct {
10562306a36Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
10662306a36Sopenharmony_ci		u64 grp:3;
10762306a36Sopenharmony_ci		u64 cptr:61;
10862306a36Sopenharmony_ci#else
10962306a36Sopenharmony_ci		u64 cptr:61;
11062306a36Sopenharmony_ci		u64 grp:3;
11162306a36Sopenharmony_ci#endif
11262306a36Sopenharmony_ci	} s;
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistruct otx_cpt_iq_cmd {
11662306a36Sopenharmony_ci	union otx_cpt_iq_cmd_word0 cmd;
11762306a36Sopenharmony_ci	u64 dptr;
11862306a36Sopenharmony_ci	u64 rptr;
11962306a36Sopenharmony_ci	union otx_cpt_iq_cmd_word3 cptr;
12062306a36Sopenharmony_ci};
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistruct otx_cpt_sglist_component {
12362306a36Sopenharmony_ci	union {
12462306a36Sopenharmony_ci		u64 len;
12562306a36Sopenharmony_ci		struct {
12662306a36Sopenharmony_ci			__be16 len0;
12762306a36Sopenharmony_ci			__be16 len1;
12862306a36Sopenharmony_ci			__be16 len2;
12962306a36Sopenharmony_ci			__be16 len3;
13062306a36Sopenharmony_ci		} s;
13162306a36Sopenharmony_ci	} u;
13262306a36Sopenharmony_ci	__be64 ptr0;
13362306a36Sopenharmony_ci	__be64 ptr1;
13462306a36Sopenharmony_ci	__be64 ptr2;
13562306a36Sopenharmony_ci	__be64 ptr3;
13662306a36Sopenharmony_ci};
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistruct otx_cpt_pending_entry {
13962306a36Sopenharmony_ci	u64 *completion_addr;	/* Completion address */
14062306a36Sopenharmony_ci	struct otx_cpt_info_buffer *info;
14162306a36Sopenharmony_ci	/* Kernel async request callback */
14262306a36Sopenharmony_ci	void (*callback)(int status, void *arg1, void *arg2);
14362306a36Sopenharmony_ci	struct crypto_async_request *areq; /* Async request callback arg */
14462306a36Sopenharmony_ci	u8 resume_sender;	/* Notify sender to resume sending requests */
14562306a36Sopenharmony_ci	u8 busy;		/* Entry status (free/busy) */
14662306a36Sopenharmony_ci};
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistruct otx_cpt_pending_queue {
14962306a36Sopenharmony_ci	struct otx_cpt_pending_entry *head;	/* Head of the queue */
15062306a36Sopenharmony_ci	u32 front;			/* Process work from here */
15162306a36Sopenharmony_ci	u32 rear;			/* Append new work here */
15262306a36Sopenharmony_ci	u32 pending_count;		/* Pending requests count */
15362306a36Sopenharmony_ci	u32 qlen;			/* Queue length */
15462306a36Sopenharmony_ci	spinlock_t lock;		/* Queue lock */
15562306a36Sopenharmony_ci};
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistruct otx_cpt_req_info {
15862306a36Sopenharmony_ci	/* Kernel async request callback */
15962306a36Sopenharmony_ci	void (*callback)(int status, void *arg1, void *arg2);
16062306a36Sopenharmony_ci	struct crypto_async_request *areq; /* Async request callback arg */
16162306a36Sopenharmony_ci	struct otx_cptvf_request req;/* Request information (core specific) */
16262306a36Sopenharmony_ci	union otx_cpt_ctrl_info ctrl;/* User control information */
16362306a36Sopenharmony_ci	struct otx_cpt_buf_ptr in[OTX_CPT_MAX_SG_IN_CNT];
16462306a36Sopenharmony_ci	struct otx_cpt_buf_ptr out[OTX_CPT_MAX_SG_OUT_CNT];
16562306a36Sopenharmony_ci	u8 *iv_out;     /* IV to send back */
16662306a36Sopenharmony_ci	u16 rlen;	/* Output length */
16762306a36Sopenharmony_ci	u8 incnt;	/* Number of input buffers */
16862306a36Sopenharmony_ci	u8 outcnt;	/* Number of output buffers */
16962306a36Sopenharmony_ci	u8 req_type;	/* Type of request */
17062306a36Sopenharmony_ci	u8 is_enc;	/* Is a request an encryption request */
17162306a36Sopenharmony_ci	u8 is_trunc_hmac;/* Is truncated hmac used */
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistruct otx_cpt_info_buffer {
17562306a36Sopenharmony_ci	struct otx_cpt_pending_entry *pentry;
17662306a36Sopenharmony_ci	struct otx_cpt_req_info *req;
17762306a36Sopenharmony_ci	struct pci_dev *pdev;
17862306a36Sopenharmony_ci	u64 *completion_addr;
17962306a36Sopenharmony_ci	u8 *out_buffer;
18062306a36Sopenharmony_ci	u8 *in_buffer;
18162306a36Sopenharmony_ci	dma_addr_t dptr_baddr;
18262306a36Sopenharmony_ci	dma_addr_t rptr_baddr;
18362306a36Sopenharmony_ci	dma_addr_t comp_baddr;
18462306a36Sopenharmony_ci	unsigned long time_in;
18562306a36Sopenharmony_ci	u32 dlen;
18662306a36Sopenharmony_ci	u32 dma_len;
18762306a36Sopenharmony_ci	u8 extra_time;
18862306a36Sopenharmony_ci};
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic inline void do_request_cleanup(struct pci_dev *pdev,
19162306a36Sopenharmony_ci				      struct otx_cpt_info_buffer *info)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	struct otx_cpt_req_info *req;
19462306a36Sopenharmony_ci	int i;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	if (info->dptr_baddr)
19762306a36Sopenharmony_ci		dma_unmap_single(&pdev->dev, info->dptr_baddr,
19862306a36Sopenharmony_ci				 info->dma_len, DMA_BIDIRECTIONAL);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	if (info->req) {
20162306a36Sopenharmony_ci		req = info->req;
20262306a36Sopenharmony_ci		for (i = 0; i < req->outcnt; i++) {
20362306a36Sopenharmony_ci			if (req->out[i].dma_addr)
20462306a36Sopenharmony_ci				dma_unmap_single(&pdev->dev,
20562306a36Sopenharmony_ci						 req->out[i].dma_addr,
20662306a36Sopenharmony_ci						 req->out[i].size,
20762306a36Sopenharmony_ci						 DMA_BIDIRECTIONAL);
20862306a36Sopenharmony_ci		}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci		for (i = 0; i < req->incnt; i++) {
21162306a36Sopenharmony_ci			if (req->in[i].dma_addr)
21262306a36Sopenharmony_ci				dma_unmap_single(&pdev->dev,
21362306a36Sopenharmony_ci						 req->in[i].dma_addr,
21462306a36Sopenharmony_ci						 req->in[i].size,
21562306a36Sopenharmony_ci						 DMA_BIDIRECTIONAL);
21662306a36Sopenharmony_ci		}
21762306a36Sopenharmony_ci	}
21862306a36Sopenharmony_ci	kfree_sensitive(info);
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistruct otx_cptvf_wqe;
22262306a36Sopenharmony_civoid otx_cpt_dump_sg_list(struct pci_dev *pdev, struct otx_cpt_req_info *req);
22362306a36Sopenharmony_civoid otx_cpt_post_process(struct otx_cptvf_wqe *wqe);
22462306a36Sopenharmony_ciint otx_cpt_do_request(struct pci_dev *pdev, struct otx_cpt_req_info *req,
22562306a36Sopenharmony_ci		       int cpu_num);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci#endif /* __OTX_CPTVF_REQUEST_MANAGER_H */
228