1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606  * Copyright(c) 2018 HUAWEI TECHNOLOGIES CO., LTD.
3d30ea906Sjfb8856606  */
4d30ea906Sjfb8856606 #include <stdbool.h>
5d30ea906Sjfb8856606 #include <unistd.h>
6d30ea906Sjfb8856606 
7d30ea906Sjfb8856606 #include <rte_common.h>
8d30ea906Sjfb8856606 #include <rte_errno.h>
9d30ea906Sjfb8856606 #include <rte_pci.h>
10d30ea906Sjfb8856606 #include <rte_bus_pci.h>
11d30ea906Sjfb8856606 #include <rte_cryptodev.h>
12d30ea906Sjfb8856606 #include <rte_cryptodev_pmd.h>
13d30ea906Sjfb8856606 #include <rte_eal.h>
14d30ea906Sjfb8856606 
15d30ea906Sjfb8856606 #include "virtio_cryptodev.h"
16d30ea906Sjfb8856606 #include "virtqueue.h"
17d30ea906Sjfb8856606 #include "virtio_crypto_algs.h"
18d30ea906Sjfb8856606 #include "virtio_crypto_capabilities.h"
19d30ea906Sjfb8856606 
20d30ea906Sjfb8856606 static int virtio_crypto_dev_configure(struct rte_cryptodev *dev,
21d30ea906Sjfb8856606 		struct rte_cryptodev_config *config);
22d30ea906Sjfb8856606 static int virtio_crypto_dev_start(struct rte_cryptodev *dev);
23d30ea906Sjfb8856606 static void virtio_crypto_dev_stop(struct rte_cryptodev *dev);
24d30ea906Sjfb8856606 static int virtio_crypto_dev_close(struct rte_cryptodev *dev);
25d30ea906Sjfb8856606 static void virtio_crypto_dev_info_get(struct rte_cryptodev *dev,
26d30ea906Sjfb8856606 		struct rte_cryptodev_info *dev_info);
27d30ea906Sjfb8856606 static void virtio_crypto_dev_stats_get(struct rte_cryptodev *dev,
28d30ea906Sjfb8856606 		struct rte_cryptodev_stats *stats);
29d30ea906Sjfb8856606 static void virtio_crypto_dev_stats_reset(struct rte_cryptodev *dev);
30d30ea906Sjfb8856606 static int virtio_crypto_qp_setup(struct rte_cryptodev *dev,
31d30ea906Sjfb8856606 		uint16_t queue_pair_id,
32d30ea906Sjfb8856606 		const struct rte_cryptodev_qp_conf *qp_conf,
334418919fSjohnjiang 		int socket_id);
34d30ea906Sjfb8856606 static int virtio_crypto_qp_release(struct rte_cryptodev *dev,
35d30ea906Sjfb8856606 		uint16_t queue_pair_id);
36d30ea906Sjfb8856606 static void virtio_crypto_dev_free_mbufs(struct rte_cryptodev *dev);
37d30ea906Sjfb8856606 static unsigned int virtio_crypto_sym_get_session_private_size(
38d30ea906Sjfb8856606 		struct rte_cryptodev *dev);
39d30ea906Sjfb8856606 static void virtio_crypto_sym_clear_session(struct rte_cryptodev *dev,
40d30ea906Sjfb8856606 		struct rte_cryptodev_sym_session *sess);
41d30ea906Sjfb8856606 static int virtio_crypto_sym_configure_session(struct rte_cryptodev *dev,
42d30ea906Sjfb8856606 		struct rte_crypto_sym_xform *xform,
43d30ea906Sjfb8856606 		struct rte_cryptodev_sym_session *session,
44d30ea906Sjfb8856606 		struct rte_mempool *mp);
45d30ea906Sjfb8856606 
46d30ea906Sjfb8856606 /*
47d30ea906Sjfb8856606  * The set of PCI devices this driver supports
48d30ea906Sjfb8856606  */
49d30ea906Sjfb8856606 static const struct rte_pci_id pci_id_virtio_crypto_map[] = {
50d30ea906Sjfb8856606 	{ RTE_PCI_DEVICE(VIRTIO_CRYPTO_PCI_VENDORID,
51d30ea906Sjfb8856606 				VIRTIO_CRYPTO_PCI_DEVICEID) },
52d30ea906Sjfb8856606 	{ .vendor_id = 0, /* sentinel */ },
53d30ea906Sjfb8856606 };
54d30ea906Sjfb8856606 
55d30ea906Sjfb8856606 static const struct rte_cryptodev_capabilities virtio_capabilities[] = {
56d30ea906Sjfb8856606 	VIRTIO_SYM_CAPABILITIES,
57d30ea906Sjfb8856606 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
58d30ea906Sjfb8856606 };
59d30ea906Sjfb8856606 
60d30ea906Sjfb8856606 uint8_t cryptodev_virtio_driver_id;
61d30ea906Sjfb8856606 
62d30ea906Sjfb8856606 #define NUM_ENTRY_SYM_CREATE_SESSION 4
63d30ea906Sjfb8856606 
64d30ea906Sjfb8856606 static int
virtio_crypto_send_command(struct virtqueue * vq,struct virtio_crypto_op_ctrl_req * ctrl,uint8_t * cipher_key,uint8_t * auth_key,struct virtio_crypto_session * session)65d30ea906Sjfb8856606 virtio_crypto_send_command(struct virtqueue *vq,
66d30ea906Sjfb8856606 		struct virtio_crypto_op_ctrl_req *ctrl, uint8_t *cipher_key,
67d30ea906Sjfb8856606 		uint8_t *auth_key, struct virtio_crypto_session *session)
68d30ea906Sjfb8856606 {
69d30ea906Sjfb8856606 	uint8_t idx = 0;
70d30ea906Sjfb8856606 	uint8_t needed = 1;
71d30ea906Sjfb8856606 	uint32_t head = 0;
72d30ea906Sjfb8856606 	uint32_t len_cipher_key = 0;
73d30ea906Sjfb8856606 	uint32_t len_auth_key = 0;
74d30ea906Sjfb8856606 	uint32_t len_ctrl_req = sizeof(struct virtio_crypto_op_ctrl_req);
75d30ea906Sjfb8856606 	uint32_t len_session_input = sizeof(struct virtio_crypto_session_input);
76d30ea906Sjfb8856606 	uint32_t len_total = 0;
77d30ea906Sjfb8856606 	uint32_t input_offset = 0;
78d30ea906Sjfb8856606 	void *virt_addr_started = NULL;
79d30ea906Sjfb8856606 	phys_addr_t phys_addr_started;
80d30ea906Sjfb8856606 	struct vring_desc *desc;
81d30ea906Sjfb8856606 	uint32_t desc_offset;
82d30ea906Sjfb8856606 	struct virtio_crypto_session_input *input;
83d30ea906Sjfb8856606 	int ret;
84d30ea906Sjfb8856606 
85d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
86d30ea906Sjfb8856606 
87d30ea906Sjfb8856606 	if (session == NULL) {
88d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("session is NULL.");
89d30ea906Sjfb8856606 		return -EINVAL;
90d30ea906Sjfb8856606 	}
91d30ea906Sjfb8856606 	/* cipher only is supported, it is available if auth_key is NULL */
92d30ea906Sjfb8856606 	if (!cipher_key) {
93d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("cipher key is NULL.");
94d30ea906Sjfb8856606 		return -EINVAL;
95d30ea906Sjfb8856606 	}
96d30ea906Sjfb8856606 
97d30ea906Sjfb8856606 	head = vq->vq_desc_head_idx;
98d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_desc_head_idx = %d, vq = %p",
99d30ea906Sjfb8856606 					head, vq);
100d30ea906Sjfb8856606 
101d30ea906Sjfb8856606 	if (vq->vq_free_cnt < needed) {
102d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Not enough entry");
103d30ea906Sjfb8856606 		return -ENOSPC;
104d30ea906Sjfb8856606 	}
105d30ea906Sjfb8856606 
106d30ea906Sjfb8856606 	/* calculate the length of cipher key */
107d30ea906Sjfb8856606 	if (cipher_key) {
108d30ea906Sjfb8856606 		switch (ctrl->u.sym_create_session.op_type) {
109d30ea906Sjfb8856606 		case VIRTIO_CRYPTO_SYM_OP_CIPHER:
110d30ea906Sjfb8856606 			len_cipher_key
111d30ea906Sjfb8856606 				= ctrl->u.sym_create_session.u.cipher
112d30ea906Sjfb8856606 							.para.keylen;
113d30ea906Sjfb8856606 			break;
114d30ea906Sjfb8856606 		case VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING:
115d30ea906Sjfb8856606 			len_cipher_key
116d30ea906Sjfb8856606 				= ctrl->u.sym_create_session.u.chain
117d30ea906Sjfb8856606 					.para.cipher_param.keylen;
118d30ea906Sjfb8856606 			break;
119d30ea906Sjfb8856606 		default:
120d30ea906Sjfb8856606 			VIRTIO_CRYPTO_SESSION_LOG_ERR("invalid op type");
121d30ea906Sjfb8856606 			return -EINVAL;
122d30ea906Sjfb8856606 		}
123d30ea906Sjfb8856606 	}
124d30ea906Sjfb8856606 
125d30ea906Sjfb8856606 	/* calculate the length of auth key */
126d30ea906Sjfb8856606 	if (auth_key) {
127d30ea906Sjfb8856606 		len_auth_key =
128d30ea906Sjfb8856606 			ctrl->u.sym_create_session.u.chain.para.u.mac_param
129d30ea906Sjfb8856606 				.auth_key_len;
130d30ea906Sjfb8856606 	}
131d30ea906Sjfb8856606 
132d30ea906Sjfb8856606 	/*
133d30ea906Sjfb8856606 	 * malloc memory to store indirect vring_desc entries, including
134d30ea906Sjfb8856606 	 * ctrl request, cipher key, auth key, session input and desc vring
135d30ea906Sjfb8856606 	 */
136d30ea906Sjfb8856606 	desc_offset = len_ctrl_req + len_cipher_key + len_auth_key
137d30ea906Sjfb8856606 		+ len_session_input;
138d30ea906Sjfb8856606 	virt_addr_started = rte_malloc(NULL,
139d30ea906Sjfb8856606 		desc_offset + NUM_ENTRY_SYM_CREATE_SESSION
140d30ea906Sjfb8856606 			* sizeof(struct vring_desc), RTE_CACHE_LINE_SIZE);
141d30ea906Sjfb8856606 	if (virt_addr_started == NULL) {
142d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("not enough heap memory");
143d30ea906Sjfb8856606 		return -ENOSPC;
144d30ea906Sjfb8856606 	}
145d30ea906Sjfb8856606 	phys_addr_started = rte_malloc_virt2iova(virt_addr_started);
146d30ea906Sjfb8856606 
147d30ea906Sjfb8856606 	/* address to store indirect vring desc entries */
148d30ea906Sjfb8856606 	desc = (struct vring_desc *)
149d30ea906Sjfb8856606 		((uint8_t *)virt_addr_started + desc_offset);
150d30ea906Sjfb8856606 
151d30ea906Sjfb8856606 	/*  ctrl req part */
152d30ea906Sjfb8856606 	memcpy(virt_addr_started, ctrl, len_ctrl_req);
153d30ea906Sjfb8856606 	desc[idx].addr = phys_addr_started;
154d30ea906Sjfb8856606 	desc[idx].len = len_ctrl_req;
155d30ea906Sjfb8856606 	desc[idx].flags = VRING_DESC_F_NEXT;
156d30ea906Sjfb8856606 	desc[idx].next = idx + 1;
157d30ea906Sjfb8856606 	idx++;
158d30ea906Sjfb8856606 	len_total += len_ctrl_req;
159d30ea906Sjfb8856606 	input_offset += len_ctrl_req;
160d30ea906Sjfb8856606 
161d30ea906Sjfb8856606 	/* cipher key part */
162d30ea906Sjfb8856606 	if (len_cipher_key > 0) {
163d30ea906Sjfb8856606 		memcpy((uint8_t *)virt_addr_started + len_total,
164d30ea906Sjfb8856606 			cipher_key, len_cipher_key);
165d30ea906Sjfb8856606 
166d30ea906Sjfb8856606 		desc[idx].addr = phys_addr_started + len_total;
167d30ea906Sjfb8856606 		desc[idx].len = len_cipher_key;
168d30ea906Sjfb8856606 		desc[idx].flags = VRING_DESC_F_NEXT;
169d30ea906Sjfb8856606 		desc[idx].next = idx + 1;
170d30ea906Sjfb8856606 		idx++;
171d30ea906Sjfb8856606 		len_total += len_cipher_key;
172d30ea906Sjfb8856606 		input_offset += len_cipher_key;
173d30ea906Sjfb8856606 	}
174d30ea906Sjfb8856606 
175d30ea906Sjfb8856606 	/* auth key part */
176d30ea906Sjfb8856606 	if (len_auth_key > 0) {
177d30ea906Sjfb8856606 		memcpy((uint8_t *)virt_addr_started + len_total,
178d30ea906Sjfb8856606 			auth_key, len_auth_key);
179d30ea906Sjfb8856606 
180d30ea906Sjfb8856606 		desc[idx].addr = phys_addr_started + len_total;
181d30ea906Sjfb8856606 		desc[idx].len = len_auth_key;
182d30ea906Sjfb8856606 		desc[idx].flags = VRING_DESC_F_NEXT;
183d30ea906Sjfb8856606 		desc[idx].next = idx + 1;
184d30ea906Sjfb8856606 		idx++;
185d30ea906Sjfb8856606 		len_total += len_auth_key;
186d30ea906Sjfb8856606 		input_offset += len_auth_key;
187d30ea906Sjfb8856606 	}
188d30ea906Sjfb8856606 
189d30ea906Sjfb8856606 	/* input part */
190d30ea906Sjfb8856606 	input = (struct virtio_crypto_session_input *)
191d30ea906Sjfb8856606 		((uint8_t *)virt_addr_started + input_offset);
192d30ea906Sjfb8856606 	input->status = VIRTIO_CRYPTO_ERR;
193d30ea906Sjfb8856606 	input->session_id = ~0ULL;
194d30ea906Sjfb8856606 	desc[idx].addr = phys_addr_started + len_total;
195d30ea906Sjfb8856606 	desc[idx].len = len_session_input;
196d30ea906Sjfb8856606 	desc[idx].flags = VRING_DESC_F_WRITE;
197d30ea906Sjfb8856606 	idx++;
198d30ea906Sjfb8856606 
199d30ea906Sjfb8856606 	/* use a single desc entry */
200d30ea906Sjfb8856606 	vq->vq_ring.desc[head].addr = phys_addr_started + desc_offset;
201d30ea906Sjfb8856606 	vq->vq_ring.desc[head].len = idx * sizeof(struct vring_desc);
202d30ea906Sjfb8856606 	vq->vq_ring.desc[head].flags = VRING_DESC_F_INDIRECT;
203d30ea906Sjfb8856606 	vq->vq_free_cnt--;
204d30ea906Sjfb8856606 
205d30ea906Sjfb8856606 	vq->vq_desc_head_idx = vq->vq_ring.desc[head].next;
206d30ea906Sjfb8856606 
207d30ea906Sjfb8856606 	vq_update_avail_ring(vq, head);
208d30ea906Sjfb8856606 	vq_update_avail_idx(vq);
209d30ea906Sjfb8856606 
210d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_queue_index = %d",
211d30ea906Sjfb8856606 					vq->vq_queue_index);
212d30ea906Sjfb8856606 
213d30ea906Sjfb8856606 	virtqueue_notify(vq);
214d30ea906Sjfb8856606 
215d30ea906Sjfb8856606 	rte_rmb();
216d30ea906Sjfb8856606 	while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) {
217d30ea906Sjfb8856606 		rte_rmb();
218d30ea906Sjfb8856606 		usleep(100);
219d30ea906Sjfb8856606 	}
220d30ea906Sjfb8856606 
221d30ea906Sjfb8856606 	while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) {
222d30ea906Sjfb8856606 		uint32_t idx, desc_idx, used_idx;
223d30ea906Sjfb8856606 		struct vring_used_elem *uep;
224d30ea906Sjfb8856606 
225d30ea906Sjfb8856606 		used_idx = (uint32_t)(vq->vq_used_cons_idx
226d30ea906Sjfb8856606 				& (vq->vq_nentries - 1));
227d30ea906Sjfb8856606 		uep = &vq->vq_ring.used->ring[used_idx];
228d30ea906Sjfb8856606 		idx = (uint32_t) uep->id;
229d30ea906Sjfb8856606 		desc_idx = idx;
230d30ea906Sjfb8856606 
231d30ea906Sjfb8856606 		while (vq->vq_ring.desc[desc_idx].flags & VRING_DESC_F_NEXT) {
232d30ea906Sjfb8856606 			desc_idx = vq->vq_ring.desc[desc_idx].next;
233d30ea906Sjfb8856606 			vq->vq_free_cnt++;
234d30ea906Sjfb8856606 		}
235d30ea906Sjfb8856606 
236d30ea906Sjfb8856606 		vq->vq_ring.desc[desc_idx].next = vq->vq_desc_head_idx;
237d30ea906Sjfb8856606 		vq->vq_desc_head_idx = idx;
238d30ea906Sjfb8856606 
239d30ea906Sjfb8856606 		vq->vq_used_cons_idx++;
240d30ea906Sjfb8856606 		vq->vq_free_cnt++;
241d30ea906Sjfb8856606 	}
242d30ea906Sjfb8856606 
243d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_free_cnt=%d\n"
244d30ea906Sjfb8856606 			"vq->vq_desc_head_idx=%d",
245d30ea906Sjfb8856606 			vq->vq_free_cnt, vq->vq_desc_head_idx);
246d30ea906Sjfb8856606 
247d30ea906Sjfb8856606 	/* get the result */
248d30ea906Sjfb8856606 	if (input->status != VIRTIO_CRYPTO_OK) {
249d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Something wrong on backend! "
250d30ea906Sjfb8856606 				"status=%u, session_id=%" PRIu64 "",
251d30ea906Sjfb8856606 				input->status, input->session_id);
252d30ea906Sjfb8856606 		rte_free(virt_addr_started);
253d30ea906Sjfb8856606 		ret = -1;
254d30ea906Sjfb8856606 	} else {
255d30ea906Sjfb8856606 		session->session_id = input->session_id;
256d30ea906Sjfb8856606 
257d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_INFO("Create session successfully, "
258d30ea906Sjfb8856606 				"session_id=%" PRIu64 "", input->session_id);
259d30ea906Sjfb8856606 		rte_free(virt_addr_started);
260d30ea906Sjfb8856606 		ret = 0;
261d30ea906Sjfb8856606 	}
262d30ea906Sjfb8856606 
263d30ea906Sjfb8856606 	return ret;
264d30ea906Sjfb8856606 }
265d30ea906Sjfb8856606 
266d30ea906Sjfb8856606 void
virtio_crypto_queue_release(struct virtqueue * vq)267d30ea906Sjfb8856606 virtio_crypto_queue_release(struct virtqueue *vq)
268d30ea906Sjfb8856606 {
269d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw;
270d30ea906Sjfb8856606 
271d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
272d30ea906Sjfb8856606 
273d30ea906Sjfb8856606 	if (vq) {
274d30ea906Sjfb8856606 		hw = vq->hw;
275d30ea906Sjfb8856606 		/* Select and deactivate the queue */
276d30ea906Sjfb8856606 		VTPCI_OPS(hw)->del_queue(hw, vq);
277d30ea906Sjfb8856606 
278d30ea906Sjfb8856606 		rte_memzone_free(vq->mz);
279d30ea906Sjfb8856606 		rte_mempool_free(vq->mpool);
280d30ea906Sjfb8856606 		rte_free(vq);
281d30ea906Sjfb8856606 	}
282d30ea906Sjfb8856606 }
283d30ea906Sjfb8856606 
284d30ea906Sjfb8856606 #define MPOOL_MAX_NAME_SZ 32
285d30ea906Sjfb8856606 
286d30ea906Sjfb8856606 int
virtio_crypto_queue_setup(struct rte_cryptodev * dev,int queue_type,uint16_t vtpci_queue_idx,uint16_t nb_desc,int socket_id,struct virtqueue ** pvq)287d30ea906Sjfb8856606 virtio_crypto_queue_setup(struct rte_cryptodev *dev,
288d30ea906Sjfb8856606 		int queue_type,
289d30ea906Sjfb8856606 		uint16_t vtpci_queue_idx,
290d30ea906Sjfb8856606 		uint16_t nb_desc,
291d30ea906Sjfb8856606 		int socket_id,
292d30ea906Sjfb8856606 		struct virtqueue **pvq)
293d30ea906Sjfb8856606 {
294d30ea906Sjfb8856606 	char vq_name[VIRTQUEUE_MAX_NAME_SZ];
295d30ea906Sjfb8856606 	char mpool_name[MPOOL_MAX_NAME_SZ];
296d30ea906Sjfb8856606 	const struct rte_memzone *mz;
297d30ea906Sjfb8856606 	unsigned int vq_size, size;
298d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = dev->data->dev_private;
299d30ea906Sjfb8856606 	struct virtqueue *vq = NULL;
300d30ea906Sjfb8856606 	uint32_t i = 0;
301d30ea906Sjfb8856606 	uint32_t j;
302d30ea906Sjfb8856606 
303d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
304d30ea906Sjfb8856606 
305d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("setting up queue: %u", vtpci_queue_idx);
306d30ea906Sjfb8856606 
307d30ea906Sjfb8856606 	/*
308d30ea906Sjfb8856606 	 * Read the virtqueue size from the Queue Size field
309d30ea906Sjfb8856606 	 * Always power of 2 and if 0 virtqueue does not exist
310d30ea906Sjfb8856606 	 */
311d30ea906Sjfb8856606 	vq_size = VTPCI_OPS(hw)->get_queue_num(hw, vtpci_queue_idx);
312d30ea906Sjfb8856606 	if (vq_size == 0) {
313d30ea906Sjfb8856606 		VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue does not exist");
314d30ea906Sjfb8856606 		return -EINVAL;
315d30ea906Sjfb8856606 	}
316d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq_size: %u", vq_size);
317d30ea906Sjfb8856606 
318d30ea906Sjfb8856606 	if (!rte_is_power_of_2(vq_size)) {
319d30ea906Sjfb8856606 		VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue size is not powerof 2");
320d30ea906Sjfb8856606 		return -EINVAL;
321d30ea906Sjfb8856606 	}
322d30ea906Sjfb8856606 
323d30ea906Sjfb8856606 	if (queue_type == VTCRYPTO_DATAQ) {
324d30ea906Sjfb8856606 		snprintf(vq_name, sizeof(vq_name), "dev%d_dataqueue%d",
325d30ea906Sjfb8856606 				dev->data->dev_id, vtpci_queue_idx);
326d30ea906Sjfb8856606 		snprintf(mpool_name, sizeof(mpool_name),
327d30ea906Sjfb8856606 				"dev%d_dataqueue%d_mpool",
328d30ea906Sjfb8856606 				dev->data->dev_id, vtpci_queue_idx);
329d30ea906Sjfb8856606 	} else if (queue_type == VTCRYPTO_CTRLQ) {
330d30ea906Sjfb8856606 		snprintf(vq_name, sizeof(vq_name), "dev%d_controlqueue",
331d30ea906Sjfb8856606 				dev->data->dev_id);
332d30ea906Sjfb8856606 		snprintf(mpool_name, sizeof(mpool_name),
333d30ea906Sjfb8856606 				"dev%d_controlqueue_mpool",
334d30ea906Sjfb8856606 				dev->data->dev_id);
335d30ea906Sjfb8856606 	}
336d30ea906Sjfb8856606 	size = RTE_ALIGN_CEIL(sizeof(*vq) +
337d30ea906Sjfb8856606 				vq_size * sizeof(struct vq_desc_extra),
338d30ea906Sjfb8856606 				RTE_CACHE_LINE_SIZE);
339d30ea906Sjfb8856606 	vq = rte_zmalloc_socket(vq_name, size, RTE_CACHE_LINE_SIZE,
340d30ea906Sjfb8856606 				socket_id);
341d30ea906Sjfb8856606 	if (vq == NULL) {
342d30ea906Sjfb8856606 		VIRTIO_CRYPTO_INIT_LOG_ERR("Can not allocate virtqueue");
343d30ea906Sjfb8856606 		return -ENOMEM;
344d30ea906Sjfb8856606 	}
345d30ea906Sjfb8856606 
346d30ea906Sjfb8856606 	if (queue_type == VTCRYPTO_DATAQ) {
347d30ea906Sjfb8856606 		/* pre-allocate a mempool and use it in the data plane to
348d30ea906Sjfb8856606 		 * improve performance
349d30ea906Sjfb8856606 		 */
350d30ea906Sjfb8856606 		vq->mpool = rte_mempool_lookup(mpool_name);
351d30ea906Sjfb8856606 		if (vq->mpool == NULL)
352d30ea906Sjfb8856606 			vq->mpool = rte_mempool_create(mpool_name,
353d30ea906Sjfb8856606 					vq_size,
354d30ea906Sjfb8856606 					sizeof(struct virtio_crypto_op_cookie),
355d30ea906Sjfb8856606 					RTE_CACHE_LINE_SIZE, 0,
356d30ea906Sjfb8856606 					NULL, NULL, NULL, NULL, socket_id,
357d30ea906Sjfb8856606 					0);
358d30ea906Sjfb8856606 		if (!vq->mpool) {
359d30ea906Sjfb8856606 			VIRTIO_CRYPTO_DRV_LOG_ERR("Virtio Crypto PMD "
360d30ea906Sjfb8856606 					"Cannot create mempool");
361d30ea906Sjfb8856606 			goto mpool_create_err;
362d30ea906Sjfb8856606 		}
363d30ea906Sjfb8856606 		for (i = 0; i < vq_size; i++) {
364d30ea906Sjfb8856606 			vq->vq_descx[i].cookie =
365d30ea906Sjfb8856606 				rte_zmalloc("crypto PMD op cookie pointer",
366d30ea906Sjfb8856606 					sizeof(struct virtio_crypto_op_cookie),
367d30ea906Sjfb8856606 					RTE_CACHE_LINE_SIZE);
368d30ea906Sjfb8856606 			if (vq->vq_descx[i].cookie == NULL) {
369d30ea906Sjfb8856606 				VIRTIO_CRYPTO_DRV_LOG_ERR("Failed to "
370d30ea906Sjfb8856606 						"alloc mem for cookie");
371d30ea906Sjfb8856606 				goto cookie_alloc_err;
372d30ea906Sjfb8856606 			}
373d30ea906Sjfb8856606 		}
374d30ea906Sjfb8856606 	}
375d30ea906Sjfb8856606 
376d30ea906Sjfb8856606 	vq->hw = hw;
377d30ea906Sjfb8856606 	vq->dev_id = dev->data->dev_id;
378d30ea906Sjfb8856606 	vq->vq_queue_index = vtpci_queue_idx;
379d30ea906Sjfb8856606 	vq->vq_nentries = vq_size;
380d30ea906Sjfb8856606 
381d30ea906Sjfb8856606 	/*
382d30ea906Sjfb8856606 	 * Using part of the vring entries is permitted, but the maximum
383d30ea906Sjfb8856606 	 * is vq_size
384d30ea906Sjfb8856606 	 */
385d30ea906Sjfb8856606 	if (nb_desc == 0 || nb_desc > vq_size)
386d30ea906Sjfb8856606 		nb_desc = vq_size;
387d30ea906Sjfb8856606 	vq->vq_free_cnt = nb_desc;
388d30ea906Sjfb8856606 
389d30ea906Sjfb8856606 	/*
390d30ea906Sjfb8856606 	 * Reserve a memzone for vring elements
391d30ea906Sjfb8856606 	 */
392d30ea906Sjfb8856606 	size = vring_size(vq_size, VIRTIO_PCI_VRING_ALIGN);
393d30ea906Sjfb8856606 	vq->vq_ring_size = RTE_ALIGN_CEIL(size, VIRTIO_PCI_VRING_ALIGN);
394d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("%s vring_size: %d, rounded_vring_size: %d",
395d30ea906Sjfb8856606 			(queue_type == VTCRYPTO_DATAQ) ? "dataq" : "ctrlq",
396d30ea906Sjfb8856606 			size, vq->vq_ring_size);
397d30ea906Sjfb8856606 
398d30ea906Sjfb8856606 	mz = rte_memzone_reserve_aligned(vq_name, vq->vq_ring_size,
399d30ea906Sjfb8856606 			socket_id, 0, VIRTIO_PCI_VRING_ALIGN);
400d30ea906Sjfb8856606 	if (mz == NULL) {
401d30ea906Sjfb8856606 		if (rte_errno == EEXIST)
402d30ea906Sjfb8856606 			mz = rte_memzone_lookup(vq_name);
403d30ea906Sjfb8856606 		if (mz == NULL) {
404d30ea906Sjfb8856606 			VIRTIO_CRYPTO_INIT_LOG_ERR("not enough memory");
405d30ea906Sjfb8856606 			goto mz_reserve_err;
406d30ea906Sjfb8856606 		}
407d30ea906Sjfb8856606 	}
408d30ea906Sjfb8856606 
409d30ea906Sjfb8856606 	/*
410d30ea906Sjfb8856606 	 * Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit,
411d30ea906Sjfb8856606 	 * and only accepts 32 bit page frame number.
412d30ea906Sjfb8856606 	 * Check if the allocated physical memory exceeds 16TB.
413d30ea906Sjfb8856606 	 */
414*2d9fd380Sjfb8856606 	if ((mz->iova + vq->vq_ring_size - 1)
415d30ea906Sjfb8856606 				>> (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) {
416d30ea906Sjfb8856606 		VIRTIO_CRYPTO_INIT_LOG_ERR("vring address shouldn't be "
417d30ea906Sjfb8856606 					"above 16TB!");
418d30ea906Sjfb8856606 		goto vring_addr_err;
419d30ea906Sjfb8856606 	}
420d30ea906Sjfb8856606 
421d30ea906Sjfb8856606 	memset(mz->addr, 0, sizeof(mz->len));
422d30ea906Sjfb8856606 	vq->mz = mz;
423*2d9fd380Sjfb8856606 	vq->vq_ring_mem = mz->iova;
424d30ea906Sjfb8856606 	vq->vq_ring_virt_mem = mz->addr;
425d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_ring_mem(physical): 0x%"PRIx64,
426*2d9fd380Sjfb8856606 					(uint64_t)mz->iova);
427d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_ring_virt_mem: 0x%"PRIx64,
428d30ea906Sjfb8856606 					(uint64_t)(uintptr_t)mz->addr);
429d30ea906Sjfb8856606 
430d30ea906Sjfb8856606 	*pvq = vq;
431d30ea906Sjfb8856606 
432d30ea906Sjfb8856606 	return 0;
433d30ea906Sjfb8856606 
434d30ea906Sjfb8856606 vring_addr_err:
435d30ea906Sjfb8856606 	rte_memzone_free(mz);
436d30ea906Sjfb8856606 mz_reserve_err:
437d30ea906Sjfb8856606 cookie_alloc_err:
438d30ea906Sjfb8856606 	rte_mempool_free(vq->mpool);
439d30ea906Sjfb8856606 	if (i != 0) {
440d30ea906Sjfb8856606 		for (j = 0; j < i; j++)
441d30ea906Sjfb8856606 			rte_free(vq->vq_descx[j].cookie);
442d30ea906Sjfb8856606 	}
443d30ea906Sjfb8856606 mpool_create_err:
444d30ea906Sjfb8856606 	rte_free(vq);
445d30ea906Sjfb8856606 	return -ENOMEM;
446d30ea906Sjfb8856606 }
447d30ea906Sjfb8856606 
448d30ea906Sjfb8856606 static int
virtio_crypto_ctrlq_setup(struct rte_cryptodev * dev,uint16_t queue_idx)449d30ea906Sjfb8856606 virtio_crypto_ctrlq_setup(struct rte_cryptodev *dev, uint16_t queue_idx)
450d30ea906Sjfb8856606 {
451d30ea906Sjfb8856606 	int ret;
452d30ea906Sjfb8856606 	struct virtqueue *vq;
453d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = dev->data->dev_private;
454d30ea906Sjfb8856606 
455d30ea906Sjfb8856606 	/* if virtio device has started, do not touch the virtqueues */
456d30ea906Sjfb8856606 	if (dev->data->dev_started)
457d30ea906Sjfb8856606 		return 0;
458d30ea906Sjfb8856606 
459d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
460d30ea906Sjfb8856606 
461d30ea906Sjfb8856606 	ret = virtio_crypto_queue_setup(dev, VTCRYPTO_CTRLQ, queue_idx,
462d30ea906Sjfb8856606 			0, SOCKET_ID_ANY, &vq);
463d30ea906Sjfb8856606 	if (ret < 0) {
464d30ea906Sjfb8856606 		VIRTIO_CRYPTO_INIT_LOG_ERR("control vq initialization failed");
465d30ea906Sjfb8856606 		return ret;
466d30ea906Sjfb8856606 	}
467d30ea906Sjfb8856606 
468d30ea906Sjfb8856606 	hw->cvq = vq;
469d30ea906Sjfb8856606 
470d30ea906Sjfb8856606 	return 0;
471d30ea906Sjfb8856606 }
472d30ea906Sjfb8856606 
473d30ea906Sjfb8856606 static void
virtio_crypto_free_queues(struct rte_cryptodev * dev)474d30ea906Sjfb8856606 virtio_crypto_free_queues(struct rte_cryptodev *dev)
475d30ea906Sjfb8856606 {
476d30ea906Sjfb8856606 	unsigned int i;
477d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = dev->data->dev_private;
478d30ea906Sjfb8856606 
479d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
480d30ea906Sjfb8856606 
481d30ea906Sjfb8856606 	/* control queue release */
482d30ea906Sjfb8856606 	virtio_crypto_queue_release(hw->cvq);
483d30ea906Sjfb8856606 
484d30ea906Sjfb8856606 	/* data queue release */
485d30ea906Sjfb8856606 	for (i = 0; i < hw->max_dataqueues; i++)
486d30ea906Sjfb8856606 		virtio_crypto_queue_release(dev->data->queue_pairs[i]);
487d30ea906Sjfb8856606 }
488d30ea906Sjfb8856606 
489d30ea906Sjfb8856606 static int
virtio_crypto_dev_close(struct rte_cryptodev * dev __rte_unused)490d30ea906Sjfb8856606 virtio_crypto_dev_close(struct rte_cryptodev *dev __rte_unused)
491d30ea906Sjfb8856606 {
492d30ea906Sjfb8856606 	return 0;
493d30ea906Sjfb8856606 }
494d30ea906Sjfb8856606 
495d30ea906Sjfb8856606 /*
496d30ea906Sjfb8856606  * dev_ops for virtio, bare necessities for basic operation
497d30ea906Sjfb8856606  */
498d30ea906Sjfb8856606 static struct rte_cryptodev_ops virtio_crypto_dev_ops = {
499d30ea906Sjfb8856606 	/* Device related operations */
500d30ea906Sjfb8856606 	.dev_configure			 = virtio_crypto_dev_configure,
501d30ea906Sjfb8856606 	.dev_start			 = virtio_crypto_dev_start,
502d30ea906Sjfb8856606 	.dev_stop			 = virtio_crypto_dev_stop,
503d30ea906Sjfb8856606 	.dev_close			 = virtio_crypto_dev_close,
504d30ea906Sjfb8856606 	.dev_infos_get			 = virtio_crypto_dev_info_get,
505d30ea906Sjfb8856606 
506d30ea906Sjfb8856606 	.stats_get			 = virtio_crypto_dev_stats_get,
507d30ea906Sjfb8856606 	.stats_reset			 = virtio_crypto_dev_stats_reset,
508d30ea906Sjfb8856606 
509d30ea906Sjfb8856606 	.queue_pair_setup                = virtio_crypto_qp_setup,
510d30ea906Sjfb8856606 	.queue_pair_release              = virtio_crypto_qp_release,
511d30ea906Sjfb8856606 
512d30ea906Sjfb8856606 	/* Crypto related operations */
513d30ea906Sjfb8856606 	.sym_session_get_size		= virtio_crypto_sym_get_session_private_size,
514d30ea906Sjfb8856606 	.sym_session_configure		= virtio_crypto_sym_configure_session,
515d30ea906Sjfb8856606 	.sym_session_clear		= virtio_crypto_sym_clear_session
516d30ea906Sjfb8856606 };
517d30ea906Sjfb8856606 
518d30ea906Sjfb8856606 static void
virtio_crypto_update_stats(struct rte_cryptodev * dev,struct rte_cryptodev_stats * stats)519d30ea906Sjfb8856606 virtio_crypto_update_stats(struct rte_cryptodev *dev,
520d30ea906Sjfb8856606 		struct rte_cryptodev_stats *stats)
521d30ea906Sjfb8856606 {
522d30ea906Sjfb8856606 	unsigned int i;
523d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = dev->data->dev_private;
524d30ea906Sjfb8856606 
525d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
526d30ea906Sjfb8856606 
527d30ea906Sjfb8856606 	if (stats == NULL) {
528d30ea906Sjfb8856606 		VIRTIO_CRYPTO_DRV_LOG_ERR("invalid pointer");
529d30ea906Sjfb8856606 		return;
530d30ea906Sjfb8856606 	}
531d30ea906Sjfb8856606 
532d30ea906Sjfb8856606 	for (i = 0; i < hw->max_dataqueues; i++) {
533d30ea906Sjfb8856606 		const struct virtqueue *data_queue
534d30ea906Sjfb8856606 			= dev->data->queue_pairs[i];
535d30ea906Sjfb8856606 		if (data_queue == NULL)
536d30ea906Sjfb8856606 			continue;
537d30ea906Sjfb8856606 
538d30ea906Sjfb8856606 		stats->enqueued_count += data_queue->packets_sent_total;
539d30ea906Sjfb8856606 		stats->enqueue_err_count += data_queue->packets_sent_failed;
540d30ea906Sjfb8856606 
541d30ea906Sjfb8856606 		stats->dequeued_count += data_queue->packets_received_total;
542d30ea906Sjfb8856606 		stats->dequeue_err_count
543d30ea906Sjfb8856606 			+= data_queue->packets_received_failed;
544d30ea906Sjfb8856606 	}
545d30ea906Sjfb8856606 }
546d30ea906Sjfb8856606 
547d30ea906Sjfb8856606 static void
virtio_crypto_dev_stats_get(struct rte_cryptodev * dev,struct rte_cryptodev_stats * stats)548d30ea906Sjfb8856606 virtio_crypto_dev_stats_get(struct rte_cryptodev *dev,
549d30ea906Sjfb8856606 		struct rte_cryptodev_stats *stats)
550d30ea906Sjfb8856606 {
551d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
552d30ea906Sjfb8856606 
553d30ea906Sjfb8856606 	virtio_crypto_update_stats(dev, stats);
554d30ea906Sjfb8856606 }
555d30ea906Sjfb8856606 
556d30ea906Sjfb8856606 static void
virtio_crypto_dev_stats_reset(struct rte_cryptodev * dev)557d30ea906Sjfb8856606 virtio_crypto_dev_stats_reset(struct rte_cryptodev *dev)
558d30ea906Sjfb8856606 {
559d30ea906Sjfb8856606 	unsigned int i;
560d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = dev->data->dev_private;
561d30ea906Sjfb8856606 
562d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
563d30ea906Sjfb8856606 
564d30ea906Sjfb8856606 	for (i = 0; i < hw->max_dataqueues; i++) {
565d30ea906Sjfb8856606 		struct virtqueue *data_queue = dev->data->queue_pairs[i];
566d30ea906Sjfb8856606 		if (data_queue == NULL)
567d30ea906Sjfb8856606 			continue;
568d30ea906Sjfb8856606 
569d30ea906Sjfb8856606 		data_queue->packets_sent_total = 0;
570d30ea906Sjfb8856606 		data_queue->packets_sent_failed = 0;
571d30ea906Sjfb8856606 
572d30ea906Sjfb8856606 		data_queue->packets_received_total = 0;
573d30ea906Sjfb8856606 		data_queue->packets_received_failed = 0;
574d30ea906Sjfb8856606 	}
575d30ea906Sjfb8856606 }
576d30ea906Sjfb8856606 
577d30ea906Sjfb8856606 static int
virtio_crypto_qp_setup(struct rte_cryptodev * dev,uint16_t queue_pair_id,const struct rte_cryptodev_qp_conf * qp_conf,int socket_id)578d30ea906Sjfb8856606 virtio_crypto_qp_setup(struct rte_cryptodev *dev, uint16_t queue_pair_id,
579d30ea906Sjfb8856606 		const struct rte_cryptodev_qp_conf *qp_conf,
5804418919fSjohnjiang 		int socket_id)
581d30ea906Sjfb8856606 {
582d30ea906Sjfb8856606 	int ret;
583d30ea906Sjfb8856606 	struct virtqueue *vq;
584d30ea906Sjfb8856606 
585d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
586d30ea906Sjfb8856606 
587d30ea906Sjfb8856606 	/* if virtio dev is started, do not touch the virtqueues */
588d30ea906Sjfb8856606 	if (dev->data->dev_started)
589d30ea906Sjfb8856606 		return 0;
590d30ea906Sjfb8856606 
591d30ea906Sjfb8856606 	ret = virtio_crypto_queue_setup(dev, VTCRYPTO_DATAQ, queue_pair_id,
592d30ea906Sjfb8856606 			qp_conf->nb_descriptors, socket_id, &vq);
593d30ea906Sjfb8856606 	if (ret < 0) {
594d30ea906Sjfb8856606 		VIRTIO_CRYPTO_INIT_LOG_ERR(
595d30ea906Sjfb8856606 			"virtio crypto data queue initialization failed\n");
596d30ea906Sjfb8856606 		return ret;
597d30ea906Sjfb8856606 	}
598d30ea906Sjfb8856606 
599d30ea906Sjfb8856606 	dev->data->queue_pairs[queue_pair_id] = vq;
600d30ea906Sjfb8856606 
601d30ea906Sjfb8856606 	return 0;
602d30ea906Sjfb8856606 }
603d30ea906Sjfb8856606 
604d30ea906Sjfb8856606 static int
virtio_crypto_qp_release(struct rte_cryptodev * dev,uint16_t queue_pair_id)605d30ea906Sjfb8856606 virtio_crypto_qp_release(struct rte_cryptodev *dev, uint16_t queue_pair_id)
606d30ea906Sjfb8856606 {
607d30ea906Sjfb8856606 	struct virtqueue *vq
608d30ea906Sjfb8856606 		= (struct virtqueue *)dev->data->queue_pairs[queue_pair_id];
609d30ea906Sjfb8856606 
610d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
611d30ea906Sjfb8856606 
612d30ea906Sjfb8856606 	if (vq == NULL) {
613d30ea906Sjfb8856606 		VIRTIO_CRYPTO_DRV_LOG_DBG("vq already freed");
614d30ea906Sjfb8856606 		return 0;
615d30ea906Sjfb8856606 	}
616d30ea906Sjfb8856606 
617d30ea906Sjfb8856606 	virtio_crypto_queue_release(vq);
618d30ea906Sjfb8856606 	return 0;
619d30ea906Sjfb8856606 }
620d30ea906Sjfb8856606 
621d30ea906Sjfb8856606 static int
virtio_negotiate_features(struct virtio_crypto_hw * hw,uint64_t req_features)622d30ea906Sjfb8856606 virtio_negotiate_features(struct virtio_crypto_hw *hw, uint64_t req_features)
623d30ea906Sjfb8856606 {
624d30ea906Sjfb8856606 	uint64_t host_features;
625d30ea906Sjfb8856606 
626d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
627d30ea906Sjfb8856606 
628d30ea906Sjfb8856606 	/* Prepare guest_features: feature that driver wants to support */
629d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("guest_features before negotiate = %" PRIx64,
630d30ea906Sjfb8856606 		req_features);
631d30ea906Sjfb8856606 
632d30ea906Sjfb8856606 	/* Read device(host) feature bits */
633d30ea906Sjfb8856606 	host_features = VTPCI_OPS(hw)->get_features(hw);
634d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("host_features before negotiate = %" PRIx64,
635d30ea906Sjfb8856606 		host_features);
636d30ea906Sjfb8856606 
637d30ea906Sjfb8856606 	/*
638d30ea906Sjfb8856606 	 * Negotiate features: Subset of device feature bits are written back
639d30ea906Sjfb8856606 	 * guest feature bits.
640d30ea906Sjfb8856606 	 */
641d30ea906Sjfb8856606 	hw->guest_features = req_features;
642d30ea906Sjfb8856606 	hw->guest_features = vtpci_cryptodev_negotiate_features(hw,
643d30ea906Sjfb8856606 							host_features);
644d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("features after negotiate = %" PRIx64,
645d30ea906Sjfb8856606 		hw->guest_features);
646d30ea906Sjfb8856606 
647d30ea906Sjfb8856606 	if (hw->modern) {
648d30ea906Sjfb8856606 		if (!vtpci_with_feature(hw, VIRTIO_F_VERSION_1)) {
649d30ea906Sjfb8856606 			VIRTIO_CRYPTO_INIT_LOG_ERR(
650d30ea906Sjfb8856606 				"VIRTIO_F_VERSION_1 features is not enabled.");
651d30ea906Sjfb8856606 			return -1;
652d30ea906Sjfb8856606 		}
653d30ea906Sjfb8856606 		vtpci_cryptodev_set_status(hw,
654d30ea906Sjfb8856606 			VIRTIO_CONFIG_STATUS_FEATURES_OK);
655d30ea906Sjfb8856606 		if (!(vtpci_cryptodev_get_status(hw) &
656d30ea906Sjfb8856606 			VIRTIO_CONFIG_STATUS_FEATURES_OK)) {
657d30ea906Sjfb8856606 			VIRTIO_CRYPTO_INIT_LOG_ERR("failed to set FEATURES_OK "
658d30ea906Sjfb8856606 						"status!");
659d30ea906Sjfb8856606 			return -1;
660d30ea906Sjfb8856606 		}
661d30ea906Sjfb8856606 	}
662d30ea906Sjfb8856606 
663d30ea906Sjfb8856606 	hw->req_guest_features = req_features;
664d30ea906Sjfb8856606 
665d30ea906Sjfb8856606 	return 0;
666d30ea906Sjfb8856606 }
667d30ea906Sjfb8856606 
668d30ea906Sjfb8856606 /* reset device and renegotiate features if needed */
669d30ea906Sjfb8856606 static int
virtio_crypto_init_device(struct rte_cryptodev * cryptodev,uint64_t req_features)670d30ea906Sjfb8856606 virtio_crypto_init_device(struct rte_cryptodev *cryptodev,
671d30ea906Sjfb8856606 	uint64_t req_features)
672d30ea906Sjfb8856606 {
673d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
674d30ea906Sjfb8856606 	struct virtio_crypto_config local_config;
675d30ea906Sjfb8856606 	struct virtio_crypto_config *config = &local_config;
676d30ea906Sjfb8856606 
677d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
678d30ea906Sjfb8856606 
679d30ea906Sjfb8856606 	/* Reset the device although not necessary at startup */
680d30ea906Sjfb8856606 	vtpci_cryptodev_reset(hw);
681d30ea906Sjfb8856606 
682d30ea906Sjfb8856606 	/* Tell the host we've noticed this device. */
683d30ea906Sjfb8856606 	vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_ACK);
684d30ea906Sjfb8856606 
685d30ea906Sjfb8856606 	/* Tell the host we've known how to drive the device. */
686d30ea906Sjfb8856606 	vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER);
687d30ea906Sjfb8856606 	if (virtio_negotiate_features(hw, req_features) < 0)
688d30ea906Sjfb8856606 		return -1;
689d30ea906Sjfb8856606 
690d30ea906Sjfb8856606 	/* Get status of the device */
691d30ea906Sjfb8856606 	vtpci_read_cryptodev_config(hw,
692d30ea906Sjfb8856606 		offsetof(struct virtio_crypto_config, status),
693d30ea906Sjfb8856606 		&config->status, sizeof(config->status));
694d30ea906Sjfb8856606 	if (config->status != VIRTIO_CRYPTO_S_HW_READY) {
695d30ea906Sjfb8856606 		VIRTIO_CRYPTO_DRV_LOG_ERR("accelerator hardware is "
696d30ea906Sjfb8856606 				"not ready");
697d30ea906Sjfb8856606 		return -1;
698d30ea906Sjfb8856606 	}
699d30ea906Sjfb8856606 
700d30ea906Sjfb8856606 	/* Get number of data queues */
701d30ea906Sjfb8856606 	vtpci_read_cryptodev_config(hw,
702d30ea906Sjfb8856606 		offsetof(struct virtio_crypto_config, max_dataqueues),
703d30ea906Sjfb8856606 		&config->max_dataqueues,
704d30ea906Sjfb8856606 		sizeof(config->max_dataqueues));
705d30ea906Sjfb8856606 	hw->max_dataqueues = config->max_dataqueues;
706d30ea906Sjfb8856606 
707d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("hw->max_dataqueues=%d",
708d30ea906Sjfb8856606 		hw->max_dataqueues);
709d30ea906Sjfb8856606 
710d30ea906Sjfb8856606 	return 0;
711d30ea906Sjfb8856606 }
712d30ea906Sjfb8856606 
713d30ea906Sjfb8856606 /*
714d30ea906Sjfb8856606  * This function is based on probe() function
715d30ea906Sjfb8856606  * It returns 0 on success.
716d30ea906Sjfb8856606  */
717d30ea906Sjfb8856606 static int
crypto_virtio_create(const char * name,struct rte_pci_device * pci_dev,struct rte_cryptodev_pmd_init_params * init_params)718d30ea906Sjfb8856606 crypto_virtio_create(const char *name, struct rte_pci_device *pci_dev,
719d30ea906Sjfb8856606 		struct rte_cryptodev_pmd_init_params *init_params)
720d30ea906Sjfb8856606 {
721d30ea906Sjfb8856606 	struct rte_cryptodev *cryptodev;
722d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw;
723d30ea906Sjfb8856606 
724d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
725d30ea906Sjfb8856606 
726d30ea906Sjfb8856606 	cryptodev = rte_cryptodev_pmd_create(name, &pci_dev->device,
727d30ea906Sjfb8856606 					init_params);
728d30ea906Sjfb8856606 	if (cryptodev == NULL)
729d30ea906Sjfb8856606 		return -ENODEV;
730d30ea906Sjfb8856606 
731d30ea906Sjfb8856606 	cryptodev->driver_id = cryptodev_virtio_driver_id;
732d30ea906Sjfb8856606 	cryptodev->dev_ops = &virtio_crypto_dev_ops;
733d30ea906Sjfb8856606 
734d30ea906Sjfb8856606 	cryptodev->enqueue_burst = virtio_crypto_pkt_tx_burst;
735d30ea906Sjfb8856606 	cryptodev->dequeue_burst = virtio_crypto_pkt_rx_burst;
736d30ea906Sjfb8856606 
737d30ea906Sjfb8856606 	cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
738*2d9fd380Sjfb8856606 		RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
739*2d9fd380Sjfb8856606 		RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT;
740d30ea906Sjfb8856606 
741d30ea906Sjfb8856606 	hw = cryptodev->data->dev_private;
742d30ea906Sjfb8856606 	hw->dev_id = cryptodev->data->dev_id;
743d30ea906Sjfb8856606 	hw->virtio_dev_capabilities = virtio_capabilities;
744d30ea906Sjfb8856606 
745d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("dev %d vendorID=0x%x deviceID=0x%x",
746d30ea906Sjfb8856606 		cryptodev->data->dev_id, pci_dev->id.vendor_id,
747d30ea906Sjfb8856606 		pci_dev->id.device_id);
748d30ea906Sjfb8856606 
749d30ea906Sjfb8856606 	/* pci device init */
750d30ea906Sjfb8856606 	if (vtpci_cryptodev_init(pci_dev, hw))
751d30ea906Sjfb8856606 		return -1;
752d30ea906Sjfb8856606 
753d30ea906Sjfb8856606 	if (virtio_crypto_init_device(cryptodev,
754d30ea906Sjfb8856606 			VIRTIO_CRYPTO_PMD_GUEST_FEATURES) < 0)
755d30ea906Sjfb8856606 		return -1;
756d30ea906Sjfb8856606 
757d30ea906Sjfb8856606 	return 0;
758d30ea906Sjfb8856606 }
759d30ea906Sjfb8856606 
760d30ea906Sjfb8856606 static int
virtio_crypto_dev_uninit(struct rte_cryptodev * cryptodev)761d30ea906Sjfb8856606 virtio_crypto_dev_uninit(struct rte_cryptodev *cryptodev)
762d30ea906Sjfb8856606 {
763d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
764d30ea906Sjfb8856606 
765d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
766d30ea906Sjfb8856606 
767d30ea906Sjfb8856606 	if (rte_eal_process_type() == RTE_PROC_SECONDARY)
768d30ea906Sjfb8856606 		return -EPERM;
769d30ea906Sjfb8856606 
770d30ea906Sjfb8856606 	if (cryptodev->data->dev_started) {
771d30ea906Sjfb8856606 		virtio_crypto_dev_stop(cryptodev);
772d30ea906Sjfb8856606 		virtio_crypto_dev_close(cryptodev);
773d30ea906Sjfb8856606 	}
774d30ea906Sjfb8856606 
775d30ea906Sjfb8856606 	cryptodev->dev_ops = NULL;
776d30ea906Sjfb8856606 	cryptodev->enqueue_burst = NULL;
777d30ea906Sjfb8856606 	cryptodev->dequeue_burst = NULL;
778d30ea906Sjfb8856606 
779d30ea906Sjfb8856606 	/* release control queue */
780d30ea906Sjfb8856606 	virtio_crypto_queue_release(hw->cvq);
781d30ea906Sjfb8856606 
782d30ea906Sjfb8856606 	rte_free(cryptodev->data);
783d30ea906Sjfb8856606 	cryptodev->data = NULL;
784d30ea906Sjfb8856606 
785d30ea906Sjfb8856606 	VIRTIO_CRYPTO_DRV_LOG_INFO("dev_uninit completed");
786d30ea906Sjfb8856606 
787d30ea906Sjfb8856606 	return 0;
788d30ea906Sjfb8856606 }
789d30ea906Sjfb8856606 
790d30ea906Sjfb8856606 static int
virtio_crypto_dev_configure(struct rte_cryptodev * cryptodev,struct rte_cryptodev_config * config __rte_unused)791d30ea906Sjfb8856606 virtio_crypto_dev_configure(struct rte_cryptodev *cryptodev,
792d30ea906Sjfb8856606 	struct rte_cryptodev_config *config __rte_unused)
793d30ea906Sjfb8856606 {
794d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
795d30ea906Sjfb8856606 
796d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
797d30ea906Sjfb8856606 
798d30ea906Sjfb8856606 	if (virtio_crypto_init_device(cryptodev,
799d30ea906Sjfb8856606 			VIRTIO_CRYPTO_PMD_GUEST_FEATURES) < 0)
800d30ea906Sjfb8856606 		return -1;
801d30ea906Sjfb8856606 
802d30ea906Sjfb8856606 	/* setup control queue
803d30ea906Sjfb8856606 	 * [0, 1, ... ,(config->max_dataqueues - 1)] are data queues
804d30ea906Sjfb8856606 	 * config->max_dataqueues is the control queue
805d30ea906Sjfb8856606 	 */
806d30ea906Sjfb8856606 	if (virtio_crypto_ctrlq_setup(cryptodev, hw->max_dataqueues) < 0) {
807d30ea906Sjfb8856606 		VIRTIO_CRYPTO_INIT_LOG_ERR("control queue setup error");
808d30ea906Sjfb8856606 		return -1;
809d30ea906Sjfb8856606 	}
810d30ea906Sjfb8856606 	virtio_crypto_ctrlq_start(cryptodev);
811d30ea906Sjfb8856606 
812d30ea906Sjfb8856606 	return 0;
813d30ea906Sjfb8856606 }
814d30ea906Sjfb8856606 
815d30ea906Sjfb8856606 static void
virtio_crypto_dev_stop(struct rte_cryptodev * dev)816d30ea906Sjfb8856606 virtio_crypto_dev_stop(struct rte_cryptodev *dev)
817d30ea906Sjfb8856606 {
818d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = dev->data->dev_private;
819d30ea906Sjfb8856606 
820d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
821d30ea906Sjfb8856606 	VIRTIO_CRYPTO_DRV_LOG_DBG("virtio_dev_stop");
822d30ea906Sjfb8856606 
823d30ea906Sjfb8856606 	vtpci_cryptodev_reset(hw);
824d30ea906Sjfb8856606 
825d30ea906Sjfb8856606 	virtio_crypto_dev_free_mbufs(dev);
826d30ea906Sjfb8856606 	virtio_crypto_free_queues(dev);
827d30ea906Sjfb8856606 
828d30ea906Sjfb8856606 	dev->data->dev_started = 0;
829d30ea906Sjfb8856606 }
830d30ea906Sjfb8856606 
831d30ea906Sjfb8856606 static int
virtio_crypto_dev_start(struct rte_cryptodev * dev)832d30ea906Sjfb8856606 virtio_crypto_dev_start(struct rte_cryptodev *dev)
833d30ea906Sjfb8856606 {
834d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = dev->data->dev_private;
835d30ea906Sjfb8856606 
836d30ea906Sjfb8856606 	if (dev->data->dev_started)
837d30ea906Sjfb8856606 		return 0;
838d30ea906Sjfb8856606 
839d30ea906Sjfb8856606 	/* Do final configuration before queue engine starts */
840d30ea906Sjfb8856606 	virtio_crypto_dataq_start(dev);
841d30ea906Sjfb8856606 	vtpci_cryptodev_reinit_complete(hw);
842d30ea906Sjfb8856606 
843d30ea906Sjfb8856606 	dev->data->dev_started = 1;
844d30ea906Sjfb8856606 
845d30ea906Sjfb8856606 	return 0;
846d30ea906Sjfb8856606 }
847d30ea906Sjfb8856606 
848d30ea906Sjfb8856606 static void
virtio_crypto_dev_free_mbufs(struct rte_cryptodev * dev)849d30ea906Sjfb8856606 virtio_crypto_dev_free_mbufs(struct rte_cryptodev *dev)
850d30ea906Sjfb8856606 {
851d30ea906Sjfb8856606 	uint32_t i;
852d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = dev->data->dev_private;
853d30ea906Sjfb8856606 
854d30ea906Sjfb8856606 	for (i = 0; i < hw->max_dataqueues; i++) {
855d30ea906Sjfb8856606 		VIRTIO_CRYPTO_INIT_LOG_DBG("Before freeing dataq[%d] used "
856d30ea906Sjfb8856606 			"and unused buf", i);
857d30ea906Sjfb8856606 		VIRTQUEUE_DUMP((struct virtqueue *)
858d30ea906Sjfb8856606 			dev->data->queue_pairs[i]);
859d30ea906Sjfb8856606 
860d30ea906Sjfb8856606 		VIRTIO_CRYPTO_INIT_LOG_DBG("queue_pairs[%d]=%p",
861d30ea906Sjfb8856606 				i, dev->data->queue_pairs[i]);
862d30ea906Sjfb8856606 
863d30ea906Sjfb8856606 		virtqueue_detatch_unused(dev->data->queue_pairs[i]);
864d30ea906Sjfb8856606 
865d30ea906Sjfb8856606 		VIRTIO_CRYPTO_INIT_LOG_DBG("After freeing dataq[%d] used and "
866d30ea906Sjfb8856606 					"unused buf", i);
867d30ea906Sjfb8856606 		VIRTQUEUE_DUMP(
868d30ea906Sjfb8856606 			(struct virtqueue *)dev->data->queue_pairs[i]);
869d30ea906Sjfb8856606 	}
870d30ea906Sjfb8856606 }
871d30ea906Sjfb8856606 
872d30ea906Sjfb8856606 static unsigned int
virtio_crypto_sym_get_session_private_size(struct rte_cryptodev * dev __rte_unused)873d30ea906Sjfb8856606 virtio_crypto_sym_get_session_private_size(
874d30ea906Sjfb8856606 		struct rte_cryptodev *dev __rte_unused)
875d30ea906Sjfb8856606 {
876d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
877d30ea906Sjfb8856606 
878d30ea906Sjfb8856606 	return RTE_ALIGN_CEIL(sizeof(struct virtio_crypto_session), 16);
879d30ea906Sjfb8856606 }
880d30ea906Sjfb8856606 
881d30ea906Sjfb8856606 static int
virtio_crypto_check_sym_session_paras(struct rte_cryptodev * dev)882d30ea906Sjfb8856606 virtio_crypto_check_sym_session_paras(
883d30ea906Sjfb8856606 		struct rte_cryptodev *dev)
884d30ea906Sjfb8856606 {
885d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw;
886d30ea906Sjfb8856606 
887d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
888d30ea906Sjfb8856606 
889d30ea906Sjfb8856606 	if (unlikely(dev == NULL)) {
890d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("dev is NULL");
891d30ea906Sjfb8856606 		return -1;
892d30ea906Sjfb8856606 	}
893d30ea906Sjfb8856606 	if (unlikely(dev->data == NULL)) {
894d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("dev->data is NULL");
895d30ea906Sjfb8856606 		return -1;
896d30ea906Sjfb8856606 	}
897d30ea906Sjfb8856606 	hw = dev->data->dev_private;
898d30ea906Sjfb8856606 	if (unlikely(hw == NULL)) {
899d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("hw is NULL");
900d30ea906Sjfb8856606 		return -1;
901d30ea906Sjfb8856606 	}
902d30ea906Sjfb8856606 	if (unlikely(hw->cvq == NULL)) {
903d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("vq is NULL");
904d30ea906Sjfb8856606 		return -1;
905d30ea906Sjfb8856606 	}
906d30ea906Sjfb8856606 
907d30ea906Sjfb8856606 	return 0;
908d30ea906Sjfb8856606 }
909d30ea906Sjfb8856606 
910d30ea906Sjfb8856606 static int
virtio_crypto_check_sym_clear_session_paras(struct rte_cryptodev * dev,struct rte_cryptodev_sym_session * sess)911d30ea906Sjfb8856606 virtio_crypto_check_sym_clear_session_paras(
912d30ea906Sjfb8856606 		struct rte_cryptodev *dev,
913d30ea906Sjfb8856606 		struct rte_cryptodev_sym_session *sess)
914d30ea906Sjfb8856606 {
915d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
916d30ea906Sjfb8856606 
917d30ea906Sjfb8856606 	if (sess == NULL) {
918d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("sym_session is NULL");
919d30ea906Sjfb8856606 		return -1;
920d30ea906Sjfb8856606 	}
921d30ea906Sjfb8856606 
922d30ea906Sjfb8856606 	return virtio_crypto_check_sym_session_paras(dev);
923d30ea906Sjfb8856606 }
924d30ea906Sjfb8856606 
925d30ea906Sjfb8856606 #define NUM_ENTRY_SYM_CLEAR_SESSION 2
926d30ea906Sjfb8856606 
927d30ea906Sjfb8856606 static void
virtio_crypto_sym_clear_session(struct rte_cryptodev * dev,struct rte_cryptodev_sym_session * sess)928d30ea906Sjfb8856606 virtio_crypto_sym_clear_session(
929d30ea906Sjfb8856606 		struct rte_cryptodev *dev,
930d30ea906Sjfb8856606 		struct rte_cryptodev_sym_session *sess)
931d30ea906Sjfb8856606 {
932d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw;
933d30ea906Sjfb8856606 	struct virtqueue *vq;
934d30ea906Sjfb8856606 	struct virtio_crypto_session *session;
935d30ea906Sjfb8856606 	struct virtio_crypto_op_ctrl_req *ctrl;
936d30ea906Sjfb8856606 	struct vring_desc *desc;
937d30ea906Sjfb8856606 	uint8_t *status;
938d30ea906Sjfb8856606 	uint8_t needed = 1;
939d30ea906Sjfb8856606 	uint32_t head;
940d30ea906Sjfb8856606 	uint8_t *malloc_virt_addr;
941d30ea906Sjfb8856606 	uint64_t malloc_phys_addr;
942d30ea906Sjfb8856606 	uint8_t len_inhdr = sizeof(struct virtio_crypto_inhdr);
943d30ea906Sjfb8856606 	uint32_t len_op_ctrl_req = sizeof(struct virtio_crypto_op_ctrl_req);
944d30ea906Sjfb8856606 	uint32_t desc_offset = len_op_ctrl_req + len_inhdr;
945d30ea906Sjfb8856606 
946d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
947d30ea906Sjfb8856606 
948d30ea906Sjfb8856606 	if (virtio_crypto_check_sym_clear_session_paras(dev, sess) < 0)
949d30ea906Sjfb8856606 		return;
950d30ea906Sjfb8856606 
951d30ea906Sjfb8856606 	hw = dev->data->dev_private;
952d30ea906Sjfb8856606 	vq = hw->cvq;
953d30ea906Sjfb8856606 	session = (struct virtio_crypto_session *)get_sym_session_private_data(
954d30ea906Sjfb8856606 		sess, cryptodev_virtio_driver_id);
955d30ea906Sjfb8856606 	if (session == NULL) {
956d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Invalid session parameter");
957d30ea906Sjfb8856606 		return;
958d30ea906Sjfb8856606 	}
959d30ea906Sjfb8856606 
960d30ea906Sjfb8856606 	VIRTIO_CRYPTO_SESSION_LOG_INFO("vq->vq_desc_head_idx = %d, "
961d30ea906Sjfb8856606 			"vq = %p", vq->vq_desc_head_idx, vq);
962d30ea906Sjfb8856606 
963d30ea906Sjfb8856606 	if (vq->vq_free_cnt < needed) {
964d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
965d30ea906Sjfb8856606 				"vq->vq_free_cnt = %d is less than %d, "
966d30ea906Sjfb8856606 				"not enough", vq->vq_free_cnt, needed);
967d30ea906Sjfb8856606 		return;
968d30ea906Sjfb8856606 	}
969d30ea906Sjfb8856606 
970d30ea906Sjfb8856606 	/*
971d30ea906Sjfb8856606 	 * malloc memory to store information of ctrl request op,
972d30ea906Sjfb8856606 	 * returned status and desc vring
973d30ea906Sjfb8856606 	 */
974d30ea906Sjfb8856606 	malloc_virt_addr = rte_malloc(NULL, len_op_ctrl_req + len_inhdr
975d30ea906Sjfb8856606 		+ NUM_ENTRY_SYM_CLEAR_SESSION
976d30ea906Sjfb8856606 		* sizeof(struct vring_desc), RTE_CACHE_LINE_SIZE);
977d30ea906Sjfb8856606 	if (malloc_virt_addr == NULL) {
978d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("not enough heap room");
979d30ea906Sjfb8856606 		return;
980d30ea906Sjfb8856606 	}
981d30ea906Sjfb8856606 	malloc_phys_addr = rte_malloc_virt2iova(malloc_virt_addr);
982d30ea906Sjfb8856606 
983d30ea906Sjfb8856606 	/* assign ctrl request op part */
984d30ea906Sjfb8856606 	ctrl = (struct virtio_crypto_op_ctrl_req *)malloc_virt_addr;
985d30ea906Sjfb8856606 	ctrl->header.opcode = VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION;
986d30ea906Sjfb8856606 	/* default data virtqueue is 0 */
987d30ea906Sjfb8856606 	ctrl->header.queue_id = 0;
988d30ea906Sjfb8856606 	ctrl->u.destroy_session.session_id = session->session_id;
989d30ea906Sjfb8856606 
990d30ea906Sjfb8856606 	/* status part */
991d30ea906Sjfb8856606 	status = &(((struct virtio_crypto_inhdr *)
992d30ea906Sjfb8856606 		((uint8_t *)malloc_virt_addr + len_op_ctrl_req))->status);
993d30ea906Sjfb8856606 	*status = VIRTIO_CRYPTO_ERR;
994d30ea906Sjfb8856606 
995d30ea906Sjfb8856606 	/* indirect desc vring part */
996d30ea906Sjfb8856606 	desc = (struct vring_desc *)((uint8_t *)malloc_virt_addr
997d30ea906Sjfb8856606 		+ desc_offset);
998d30ea906Sjfb8856606 
999d30ea906Sjfb8856606 	/* ctrl request part */
1000d30ea906Sjfb8856606 	desc[0].addr = malloc_phys_addr;
1001d30ea906Sjfb8856606 	desc[0].len = len_op_ctrl_req;
1002d30ea906Sjfb8856606 	desc[0].flags = VRING_DESC_F_NEXT;
1003d30ea906Sjfb8856606 	desc[0].next = 1;
1004d30ea906Sjfb8856606 
1005d30ea906Sjfb8856606 	/* status part */
1006d30ea906Sjfb8856606 	desc[1].addr = malloc_phys_addr + len_op_ctrl_req;
1007d30ea906Sjfb8856606 	desc[1].len = len_inhdr;
1008d30ea906Sjfb8856606 	desc[1].flags = VRING_DESC_F_WRITE;
1009d30ea906Sjfb8856606 
1010d30ea906Sjfb8856606 	/* use only a single desc entry */
1011d30ea906Sjfb8856606 	head = vq->vq_desc_head_idx;
1012d30ea906Sjfb8856606 	vq->vq_ring.desc[head].flags = VRING_DESC_F_INDIRECT;
1013d30ea906Sjfb8856606 	vq->vq_ring.desc[head].addr = malloc_phys_addr + desc_offset;
1014d30ea906Sjfb8856606 	vq->vq_ring.desc[head].len
1015d30ea906Sjfb8856606 		= NUM_ENTRY_SYM_CLEAR_SESSION
1016d30ea906Sjfb8856606 		* sizeof(struct vring_desc);
1017d30ea906Sjfb8856606 	vq->vq_free_cnt -= needed;
1018d30ea906Sjfb8856606 
1019d30ea906Sjfb8856606 	vq->vq_desc_head_idx = vq->vq_ring.desc[head].next;
1020d30ea906Sjfb8856606 
1021d30ea906Sjfb8856606 	vq_update_avail_ring(vq, head);
1022d30ea906Sjfb8856606 	vq_update_avail_idx(vq);
1023d30ea906Sjfb8856606 
1024d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_queue_index = %d",
1025d30ea906Sjfb8856606 					vq->vq_queue_index);
1026d30ea906Sjfb8856606 
1027d30ea906Sjfb8856606 	virtqueue_notify(vq);
1028d30ea906Sjfb8856606 
1029d30ea906Sjfb8856606 	rte_rmb();
1030d30ea906Sjfb8856606 	while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) {
1031d30ea906Sjfb8856606 		rte_rmb();
1032d30ea906Sjfb8856606 		usleep(100);
1033d30ea906Sjfb8856606 	}
1034d30ea906Sjfb8856606 
1035d30ea906Sjfb8856606 	while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) {
1036d30ea906Sjfb8856606 		uint32_t idx, desc_idx, used_idx;
1037d30ea906Sjfb8856606 		struct vring_used_elem *uep;
1038d30ea906Sjfb8856606 
1039d30ea906Sjfb8856606 		used_idx = (uint32_t)(vq->vq_used_cons_idx
1040d30ea906Sjfb8856606 				& (vq->vq_nentries - 1));
1041d30ea906Sjfb8856606 		uep = &vq->vq_ring.used->ring[used_idx];
1042d30ea906Sjfb8856606 		idx = (uint32_t) uep->id;
1043d30ea906Sjfb8856606 		desc_idx = idx;
1044d30ea906Sjfb8856606 		while (vq->vq_ring.desc[desc_idx].flags
1045d30ea906Sjfb8856606 				& VRING_DESC_F_NEXT) {
1046d30ea906Sjfb8856606 			desc_idx = vq->vq_ring.desc[desc_idx].next;
1047d30ea906Sjfb8856606 			vq->vq_free_cnt++;
1048d30ea906Sjfb8856606 		}
1049d30ea906Sjfb8856606 
1050d30ea906Sjfb8856606 		vq->vq_ring.desc[desc_idx].next = vq->vq_desc_head_idx;
1051d30ea906Sjfb8856606 		vq->vq_desc_head_idx = idx;
1052d30ea906Sjfb8856606 		vq->vq_used_cons_idx++;
1053d30ea906Sjfb8856606 		vq->vq_free_cnt++;
1054d30ea906Sjfb8856606 	}
1055d30ea906Sjfb8856606 
1056d30ea906Sjfb8856606 	if (*status != VIRTIO_CRYPTO_OK) {
1057d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Close session failed "
1058d30ea906Sjfb8856606 				"status=%"PRIu32", session_id=%"PRIu64"",
1059d30ea906Sjfb8856606 				*status, session->session_id);
1060d30ea906Sjfb8856606 		rte_free(malloc_virt_addr);
1061d30ea906Sjfb8856606 		return;
1062d30ea906Sjfb8856606 	}
1063d30ea906Sjfb8856606 
1064d30ea906Sjfb8856606 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_free_cnt=%d\n"
1065d30ea906Sjfb8856606 			"vq->vq_desc_head_idx=%d",
1066d30ea906Sjfb8856606 			vq->vq_free_cnt, vq->vq_desc_head_idx);
1067d30ea906Sjfb8856606 
1068d30ea906Sjfb8856606 	VIRTIO_CRYPTO_SESSION_LOG_INFO("Close session %"PRIu64" successfully ",
1069d30ea906Sjfb8856606 			session->session_id);
1070d30ea906Sjfb8856606 
1071d30ea906Sjfb8856606 	memset(session, 0, sizeof(struct virtio_crypto_session));
1072d30ea906Sjfb8856606 	struct rte_mempool *sess_mp = rte_mempool_from_obj(session);
1073d30ea906Sjfb8856606 	set_sym_session_private_data(sess, cryptodev_virtio_driver_id, NULL);
1074d30ea906Sjfb8856606 	rte_mempool_put(sess_mp, session);
1075d30ea906Sjfb8856606 	rte_free(malloc_virt_addr);
1076d30ea906Sjfb8856606 }
1077d30ea906Sjfb8856606 
1078d30ea906Sjfb8856606 static struct rte_crypto_cipher_xform *
virtio_crypto_get_cipher_xform(struct rte_crypto_sym_xform * xform)1079d30ea906Sjfb8856606 virtio_crypto_get_cipher_xform(struct rte_crypto_sym_xform *xform)
1080d30ea906Sjfb8856606 {
1081d30ea906Sjfb8856606 	do {
1082d30ea906Sjfb8856606 		if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
1083d30ea906Sjfb8856606 			return &xform->cipher;
1084d30ea906Sjfb8856606 
1085d30ea906Sjfb8856606 		xform = xform->next;
1086d30ea906Sjfb8856606 	} while (xform);
1087d30ea906Sjfb8856606 
1088d30ea906Sjfb8856606 	return NULL;
1089d30ea906Sjfb8856606 }
1090d30ea906Sjfb8856606 
1091d30ea906Sjfb8856606 static struct rte_crypto_auth_xform *
virtio_crypto_get_auth_xform(struct rte_crypto_sym_xform * xform)1092d30ea906Sjfb8856606 virtio_crypto_get_auth_xform(struct rte_crypto_sym_xform *xform)
1093d30ea906Sjfb8856606 {
1094d30ea906Sjfb8856606 	do {
1095d30ea906Sjfb8856606 		if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
1096d30ea906Sjfb8856606 			return &xform->auth;
1097d30ea906Sjfb8856606 
1098d30ea906Sjfb8856606 		xform = xform->next;
1099d30ea906Sjfb8856606 	} while (xform);
1100d30ea906Sjfb8856606 
1101d30ea906Sjfb8856606 	return NULL;
1102d30ea906Sjfb8856606 }
1103d30ea906Sjfb8856606 
1104d30ea906Sjfb8856606 /** Get xform chain order */
1105d30ea906Sjfb8856606 static int
virtio_crypto_get_chain_order(struct rte_crypto_sym_xform * xform)1106d30ea906Sjfb8856606 virtio_crypto_get_chain_order(struct rte_crypto_sym_xform *xform)
1107d30ea906Sjfb8856606 {
1108d30ea906Sjfb8856606 	if (xform == NULL)
1109d30ea906Sjfb8856606 		return -1;
1110d30ea906Sjfb8856606 
1111d30ea906Sjfb8856606 	/* Cipher Only */
1112d30ea906Sjfb8856606 	if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
1113d30ea906Sjfb8856606 			xform->next == NULL)
1114d30ea906Sjfb8856606 		return VIRTIO_CRYPTO_CMD_CIPHER;
1115d30ea906Sjfb8856606 
1116d30ea906Sjfb8856606 	/* Authentication Only */
1117d30ea906Sjfb8856606 	if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
1118d30ea906Sjfb8856606 			xform->next == NULL)
1119d30ea906Sjfb8856606 		return VIRTIO_CRYPTO_CMD_AUTH;
1120d30ea906Sjfb8856606 
1121d30ea906Sjfb8856606 	/* Authenticate then Cipher */
1122d30ea906Sjfb8856606 	if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
1123d30ea906Sjfb8856606 			xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
1124d30ea906Sjfb8856606 		return VIRTIO_CRYPTO_CMD_HASH_CIPHER;
1125d30ea906Sjfb8856606 
1126d30ea906Sjfb8856606 	/* Cipher then Authenticate */
1127d30ea906Sjfb8856606 	if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
1128d30ea906Sjfb8856606 			xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH)
1129d30ea906Sjfb8856606 		return VIRTIO_CRYPTO_CMD_CIPHER_HASH;
1130d30ea906Sjfb8856606 
1131d30ea906Sjfb8856606 	return -1;
1132d30ea906Sjfb8856606 }
1133d30ea906Sjfb8856606 
1134d30ea906Sjfb8856606 static int
virtio_crypto_sym_pad_cipher_param(struct virtio_crypto_cipher_session_para * para,struct rte_crypto_cipher_xform * cipher_xform)1135d30ea906Sjfb8856606 virtio_crypto_sym_pad_cipher_param(
1136d30ea906Sjfb8856606 		struct virtio_crypto_cipher_session_para *para,
1137d30ea906Sjfb8856606 		struct rte_crypto_cipher_xform *cipher_xform)
1138d30ea906Sjfb8856606 {
1139d30ea906Sjfb8856606 	switch (cipher_xform->algo) {
1140d30ea906Sjfb8856606 	case RTE_CRYPTO_CIPHER_AES_CBC:
1141d30ea906Sjfb8856606 		para->algo = VIRTIO_CRYPTO_CIPHER_AES_CBC;
1142d30ea906Sjfb8856606 		break;
1143d30ea906Sjfb8856606 	default:
1144d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Crypto: Unsupported "
1145d30ea906Sjfb8856606 				"Cipher alg %u", cipher_xform->algo);
1146d30ea906Sjfb8856606 		return -1;
1147d30ea906Sjfb8856606 	}
1148d30ea906Sjfb8856606 
1149d30ea906Sjfb8856606 	para->keylen = cipher_xform->key.length;
1150d30ea906Sjfb8856606 	switch (cipher_xform->op) {
1151d30ea906Sjfb8856606 	case RTE_CRYPTO_CIPHER_OP_ENCRYPT:
1152d30ea906Sjfb8856606 		para->op = VIRTIO_CRYPTO_OP_ENCRYPT;
1153d30ea906Sjfb8856606 		break;
1154d30ea906Sjfb8856606 	case RTE_CRYPTO_CIPHER_OP_DECRYPT:
1155d30ea906Sjfb8856606 		para->op = VIRTIO_CRYPTO_OP_DECRYPT;
1156d30ea906Sjfb8856606 		break;
1157d30ea906Sjfb8856606 	default:
1158d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Unsupported cipher operation "
1159d30ea906Sjfb8856606 					"parameter");
1160d30ea906Sjfb8856606 		return -1;
1161d30ea906Sjfb8856606 	}
1162d30ea906Sjfb8856606 
1163d30ea906Sjfb8856606 	return 0;
1164d30ea906Sjfb8856606 }
1165d30ea906Sjfb8856606 
1166d30ea906Sjfb8856606 static int
virtio_crypto_sym_pad_auth_param(struct virtio_crypto_op_ctrl_req * ctrl,struct rte_crypto_auth_xform * auth_xform)1167d30ea906Sjfb8856606 virtio_crypto_sym_pad_auth_param(
1168d30ea906Sjfb8856606 		struct virtio_crypto_op_ctrl_req *ctrl,
1169d30ea906Sjfb8856606 		struct rte_crypto_auth_xform *auth_xform)
1170d30ea906Sjfb8856606 {
1171d30ea906Sjfb8856606 	uint32_t *algo;
1172d30ea906Sjfb8856606 	struct virtio_crypto_alg_chain_session_para *para =
1173d30ea906Sjfb8856606 		&(ctrl->u.sym_create_session.u.chain.para);
1174d30ea906Sjfb8856606 
1175d30ea906Sjfb8856606 	switch (ctrl->u.sym_create_session.u.chain.para.hash_mode) {
1176d30ea906Sjfb8856606 	case VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN:
1177d30ea906Sjfb8856606 		algo = &(para->u.hash_param.algo);
1178d30ea906Sjfb8856606 		break;
1179d30ea906Sjfb8856606 	case VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH:
1180d30ea906Sjfb8856606 		algo = &(para->u.mac_param.algo);
1181d30ea906Sjfb8856606 		break;
1182d30ea906Sjfb8856606 	default:
1183d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Unsupported hash mode %u "
1184d30ea906Sjfb8856606 			"specified",
1185d30ea906Sjfb8856606 			ctrl->u.sym_create_session.u.chain.para.hash_mode);
1186d30ea906Sjfb8856606 		return -1;
1187d30ea906Sjfb8856606 	}
1188d30ea906Sjfb8856606 
1189d30ea906Sjfb8856606 	switch (auth_xform->algo) {
1190d30ea906Sjfb8856606 	case RTE_CRYPTO_AUTH_SHA1_HMAC:
1191d30ea906Sjfb8856606 		*algo = VIRTIO_CRYPTO_MAC_HMAC_SHA1;
1192d30ea906Sjfb8856606 		break;
1193d30ea906Sjfb8856606 	default:
1194d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
1195d30ea906Sjfb8856606 			"Crypto: Undefined Hash algo %u specified",
1196d30ea906Sjfb8856606 			auth_xform->algo);
1197d30ea906Sjfb8856606 		return -1;
1198d30ea906Sjfb8856606 	}
1199d30ea906Sjfb8856606 
1200d30ea906Sjfb8856606 	return 0;
1201d30ea906Sjfb8856606 }
1202d30ea906Sjfb8856606 
1203d30ea906Sjfb8856606 static int
virtio_crypto_sym_pad_op_ctrl_req(struct virtio_crypto_op_ctrl_req * ctrl,struct rte_crypto_sym_xform * xform,bool is_chainned,uint8_t * cipher_key_data,uint8_t * auth_key_data,struct virtio_crypto_session * session)1204d30ea906Sjfb8856606 virtio_crypto_sym_pad_op_ctrl_req(
1205d30ea906Sjfb8856606 		struct virtio_crypto_op_ctrl_req *ctrl,
1206d30ea906Sjfb8856606 		struct rte_crypto_sym_xform *xform, bool is_chainned,
12074418919fSjohnjiang 		uint8_t *cipher_key_data, uint8_t *auth_key_data,
1208d30ea906Sjfb8856606 		struct virtio_crypto_session *session)
1209d30ea906Sjfb8856606 {
1210d30ea906Sjfb8856606 	int ret;
1211d30ea906Sjfb8856606 	struct rte_crypto_auth_xform *auth_xform = NULL;
1212d30ea906Sjfb8856606 	struct rte_crypto_cipher_xform *cipher_xform = NULL;
1213d30ea906Sjfb8856606 
1214d30ea906Sjfb8856606 	/* Get cipher xform from crypto xform chain */
1215d30ea906Sjfb8856606 	cipher_xform = virtio_crypto_get_cipher_xform(xform);
1216d30ea906Sjfb8856606 	if (cipher_xform) {
12174418919fSjohnjiang 		if (cipher_xform->key.length > VIRTIO_CRYPTO_MAX_KEY_SIZE) {
12184418919fSjohnjiang 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
12194418919fSjohnjiang 				"cipher key size cannot be longer than %u",
12204418919fSjohnjiang 				VIRTIO_CRYPTO_MAX_KEY_SIZE);
12214418919fSjohnjiang 			return -1;
12224418919fSjohnjiang 		}
1223d30ea906Sjfb8856606 		if (cipher_xform->iv.length > VIRTIO_CRYPTO_MAX_IV_SIZE) {
1224d30ea906Sjfb8856606 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1225d30ea906Sjfb8856606 				"cipher IV size cannot be longer than %u",
1226d30ea906Sjfb8856606 				VIRTIO_CRYPTO_MAX_IV_SIZE);
1227d30ea906Sjfb8856606 			return -1;
1228d30ea906Sjfb8856606 		}
1229d30ea906Sjfb8856606 		if (is_chainned)
1230d30ea906Sjfb8856606 			ret = virtio_crypto_sym_pad_cipher_param(
1231d30ea906Sjfb8856606 				&ctrl->u.sym_create_session.u.chain.para
1232d30ea906Sjfb8856606 						.cipher_param, cipher_xform);
1233d30ea906Sjfb8856606 		else
1234d30ea906Sjfb8856606 			ret = virtio_crypto_sym_pad_cipher_param(
1235d30ea906Sjfb8856606 				&ctrl->u.sym_create_session.u.cipher.para,
1236d30ea906Sjfb8856606 				cipher_xform);
1237d30ea906Sjfb8856606 
1238d30ea906Sjfb8856606 		if (ret < 0) {
1239d30ea906Sjfb8856606 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1240d30ea906Sjfb8856606 				"pad cipher parameter failed");
1241d30ea906Sjfb8856606 			return -1;
1242d30ea906Sjfb8856606 		}
1243d30ea906Sjfb8856606 
12444418919fSjohnjiang 		memcpy(cipher_key_data, cipher_xform->key.data,
12454418919fSjohnjiang 				cipher_xform->key.length);
1246d30ea906Sjfb8856606 
1247d30ea906Sjfb8856606 		session->iv.offset = cipher_xform->iv.offset;
1248d30ea906Sjfb8856606 		session->iv.length = cipher_xform->iv.length;
1249d30ea906Sjfb8856606 	}
1250d30ea906Sjfb8856606 
1251d30ea906Sjfb8856606 	/* Get auth xform from crypto xform chain */
1252d30ea906Sjfb8856606 	auth_xform = virtio_crypto_get_auth_xform(xform);
1253d30ea906Sjfb8856606 	if (auth_xform) {
1254d30ea906Sjfb8856606 		/* FIXME: support VIRTIO_CRYPTO_SYM_HASH_MODE_NESTED */
1255d30ea906Sjfb8856606 		struct virtio_crypto_alg_chain_session_para *para =
1256d30ea906Sjfb8856606 			&(ctrl->u.sym_create_session.u.chain.para);
1257d30ea906Sjfb8856606 		if (auth_xform->key.length) {
12584418919fSjohnjiang 			if (auth_xform->key.length >
12594418919fSjohnjiang 					VIRTIO_CRYPTO_MAX_KEY_SIZE) {
12604418919fSjohnjiang 				VIRTIO_CRYPTO_SESSION_LOG_ERR(
12614418919fSjohnjiang 				"auth key size cannot be longer than %u",
12624418919fSjohnjiang 					VIRTIO_CRYPTO_MAX_KEY_SIZE);
12634418919fSjohnjiang 				return -1;
12644418919fSjohnjiang 			}
1265d30ea906Sjfb8856606 			para->hash_mode = VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH;
1266d30ea906Sjfb8856606 			para->u.mac_param.auth_key_len =
1267d30ea906Sjfb8856606 				(uint32_t)auth_xform->key.length;
1268d30ea906Sjfb8856606 			para->u.mac_param.hash_result_len =
1269d30ea906Sjfb8856606 				auth_xform->digest_length;
12704418919fSjohnjiang 			memcpy(auth_key_data, auth_xform->key.data,
12714418919fSjohnjiang 					auth_xform->key.length);
1272d30ea906Sjfb8856606 		} else {
1273d30ea906Sjfb8856606 			para->hash_mode	= VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN;
1274d30ea906Sjfb8856606 			para->u.hash_param.hash_result_len =
1275d30ea906Sjfb8856606 				auth_xform->digest_length;
1276d30ea906Sjfb8856606 		}
1277d30ea906Sjfb8856606 
1278d30ea906Sjfb8856606 		ret = virtio_crypto_sym_pad_auth_param(ctrl, auth_xform);
1279d30ea906Sjfb8856606 		if (ret < 0) {
1280d30ea906Sjfb8856606 			VIRTIO_CRYPTO_SESSION_LOG_ERR("pad auth parameter "
1281d30ea906Sjfb8856606 						"failed");
1282d30ea906Sjfb8856606 			return -1;
1283d30ea906Sjfb8856606 		}
1284d30ea906Sjfb8856606 	}
1285d30ea906Sjfb8856606 
1286d30ea906Sjfb8856606 	return 0;
1287d30ea906Sjfb8856606 }
1288d30ea906Sjfb8856606 
1289d30ea906Sjfb8856606 static int
virtio_crypto_check_sym_configure_session_paras(struct rte_cryptodev * dev,struct rte_crypto_sym_xform * xform,struct rte_cryptodev_sym_session * sym_sess,struct rte_mempool * mempool)1290d30ea906Sjfb8856606 virtio_crypto_check_sym_configure_session_paras(
1291d30ea906Sjfb8856606 		struct rte_cryptodev *dev,
1292d30ea906Sjfb8856606 		struct rte_crypto_sym_xform *xform,
1293d30ea906Sjfb8856606 		struct rte_cryptodev_sym_session *sym_sess,
1294d30ea906Sjfb8856606 		struct rte_mempool *mempool)
1295d30ea906Sjfb8856606 {
1296d30ea906Sjfb8856606 	if (unlikely(xform == NULL) || unlikely(sym_sess == NULL) ||
1297d30ea906Sjfb8856606 		unlikely(mempool == NULL)) {
1298d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("NULL pointer");
1299d30ea906Sjfb8856606 		return -1;
1300d30ea906Sjfb8856606 	}
1301d30ea906Sjfb8856606 
1302d30ea906Sjfb8856606 	if (virtio_crypto_check_sym_session_paras(dev) < 0)
1303d30ea906Sjfb8856606 		return -1;
1304d30ea906Sjfb8856606 
1305d30ea906Sjfb8856606 	return 0;
1306d30ea906Sjfb8856606 }
1307d30ea906Sjfb8856606 
1308d30ea906Sjfb8856606 static int
virtio_crypto_sym_configure_session(struct rte_cryptodev * dev,struct rte_crypto_sym_xform * xform,struct rte_cryptodev_sym_session * sess,struct rte_mempool * mempool)1309d30ea906Sjfb8856606 virtio_crypto_sym_configure_session(
1310d30ea906Sjfb8856606 		struct rte_cryptodev *dev,
1311d30ea906Sjfb8856606 		struct rte_crypto_sym_xform *xform,
1312d30ea906Sjfb8856606 		struct rte_cryptodev_sym_session *sess,
1313d30ea906Sjfb8856606 		struct rte_mempool *mempool)
1314d30ea906Sjfb8856606 {
1315d30ea906Sjfb8856606 	int ret;
1316d30ea906Sjfb8856606 	struct virtio_crypto_session crypto_sess;
1317d30ea906Sjfb8856606 	void *session_private = &crypto_sess;
1318d30ea906Sjfb8856606 	struct virtio_crypto_session *session;
1319d30ea906Sjfb8856606 	struct virtio_crypto_op_ctrl_req *ctrl_req;
1320d30ea906Sjfb8856606 	enum virtio_crypto_cmd_id cmd_id;
13214418919fSjohnjiang 	uint8_t cipher_key_data[VIRTIO_CRYPTO_MAX_KEY_SIZE] = {0};
13224418919fSjohnjiang 	uint8_t auth_key_data[VIRTIO_CRYPTO_MAX_KEY_SIZE] = {0};
1323d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw;
1324d30ea906Sjfb8856606 	struct virtqueue *control_vq;
1325d30ea906Sjfb8856606 
1326d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
1327d30ea906Sjfb8856606 
1328d30ea906Sjfb8856606 	ret = virtio_crypto_check_sym_configure_session_paras(dev, xform,
1329d30ea906Sjfb8856606 			sess, mempool);
1330d30ea906Sjfb8856606 	if (ret < 0) {
1331d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Invalid parameters");
1332d30ea906Sjfb8856606 		return ret;
1333d30ea906Sjfb8856606 	}
1334d30ea906Sjfb8856606 
1335d30ea906Sjfb8856606 	if (rte_mempool_get(mempool, &session_private)) {
1336d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
1337d30ea906Sjfb8856606 			"Couldn't get object from session mempool");
1338d30ea906Sjfb8856606 		return -ENOMEM;
1339d30ea906Sjfb8856606 	}
1340d30ea906Sjfb8856606 
1341d30ea906Sjfb8856606 	session = (struct virtio_crypto_session *)session_private;
1342d30ea906Sjfb8856606 	memset(session, 0, sizeof(struct virtio_crypto_session));
1343d30ea906Sjfb8856606 	ctrl_req = &session->ctrl;
1344d30ea906Sjfb8856606 	ctrl_req->header.opcode = VIRTIO_CRYPTO_CIPHER_CREATE_SESSION;
1345d30ea906Sjfb8856606 	/* FIXME: support multiqueue */
1346d30ea906Sjfb8856606 	ctrl_req->header.queue_id = 0;
1347d30ea906Sjfb8856606 
1348d30ea906Sjfb8856606 	hw = dev->data->dev_private;
1349d30ea906Sjfb8856606 	control_vq = hw->cvq;
1350d30ea906Sjfb8856606 
1351d30ea906Sjfb8856606 	cmd_id = virtio_crypto_get_chain_order(xform);
1352d30ea906Sjfb8856606 	if (cmd_id == VIRTIO_CRYPTO_CMD_CIPHER_HASH)
1353d30ea906Sjfb8856606 		ctrl_req->u.sym_create_session.u.chain.para.alg_chain_order
1354d30ea906Sjfb8856606 			= VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH;
1355d30ea906Sjfb8856606 	if (cmd_id == VIRTIO_CRYPTO_CMD_HASH_CIPHER)
1356d30ea906Sjfb8856606 		ctrl_req->u.sym_create_session.u.chain.para.alg_chain_order
1357d30ea906Sjfb8856606 			= VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER;
1358d30ea906Sjfb8856606 
1359d30ea906Sjfb8856606 	switch (cmd_id) {
1360d30ea906Sjfb8856606 	case VIRTIO_CRYPTO_CMD_CIPHER_HASH:
1361d30ea906Sjfb8856606 	case VIRTIO_CRYPTO_CMD_HASH_CIPHER:
1362d30ea906Sjfb8856606 		ctrl_req->u.sym_create_session.op_type
1363d30ea906Sjfb8856606 			= VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING;
1364d30ea906Sjfb8856606 
1365d30ea906Sjfb8856606 		ret = virtio_crypto_sym_pad_op_ctrl_req(ctrl_req,
13664418919fSjohnjiang 			xform, true, cipher_key_data, auth_key_data, session);
1367d30ea906Sjfb8856606 		if (ret < 0) {
1368d30ea906Sjfb8856606 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1369d30ea906Sjfb8856606 				"padding sym op ctrl req failed");
1370d30ea906Sjfb8856606 			goto error_out;
1371d30ea906Sjfb8856606 		}
1372d30ea906Sjfb8856606 		ret = virtio_crypto_send_command(control_vq, ctrl_req,
1373d30ea906Sjfb8856606 			cipher_key_data, auth_key_data, session);
1374d30ea906Sjfb8856606 		if (ret < 0) {
1375d30ea906Sjfb8856606 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1376d30ea906Sjfb8856606 				"create session failed: %d", ret);
1377d30ea906Sjfb8856606 			goto error_out;
1378d30ea906Sjfb8856606 		}
1379d30ea906Sjfb8856606 		break;
1380d30ea906Sjfb8856606 	case VIRTIO_CRYPTO_CMD_CIPHER:
1381d30ea906Sjfb8856606 		ctrl_req->u.sym_create_session.op_type
1382d30ea906Sjfb8856606 			= VIRTIO_CRYPTO_SYM_OP_CIPHER;
1383d30ea906Sjfb8856606 		ret = virtio_crypto_sym_pad_op_ctrl_req(ctrl_req, xform,
13844418919fSjohnjiang 			false, cipher_key_data, auth_key_data, session);
1385d30ea906Sjfb8856606 		if (ret < 0) {
1386d30ea906Sjfb8856606 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1387d30ea906Sjfb8856606 				"padding sym op ctrl req failed");
1388d30ea906Sjfb8856606 			goto error_out;
1389d30ea906Sjfb8856606 		}
1390d30ea906Sjfb8856606 		ret = virtio_crypto_send_command(control_vq, ctrl_req,
1391d30ea906Sjfb8856606 			cipher_key_data, NULL, session);
1392d30ea906Sjfb8856606 		if (ret < 0) {
1393d30ea906Sjfb8856606 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1394d30ea906Sjfb8856606 				"create session failed: %d", ret);
1395d30ea906Sjfb8856606 			goto error_out;
1396d30ea906Sjfb8856606 		}
1397d30ea906Sjfb8856606 		break;
1398d30ea906Sjfb8856606 	default:
1399d30ea906Sjfb8856606 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
1400d30ea906Sjfb8856606 			"Unsupported operation chain order parameter");
1401d30ea906Sjfb8856606 		goto error_out;
1402d30ea906Sjfb8856606 	}
1403d30ea906Sjfb8856606 
1404d30ea906Sjfb8856606 	set_sym_session_private_data(sess, dev->driver_id,
1405d30ea906Sjfb8856606 		session_private);
1406d30ea906Sjfb8856606 
1407d30ea906Sjfb8856606 	return 0;
1408d30ea906Sjfb8856606 
1409d30ea906Sjfb8856606 error_out:
1410d30ea906Sjfb8856606 	return -1;
1411d30ea906Sjfb8856606 }
1412d30ea906Sjfb8856606 
1413d30ea906Sjfb8856606 static void
virtio_crypto_dev_info_get(struct rte_cryptodev * dev,struct rte_cryptodev_info * info)1414d30ea906Sjfb8856606 virtio_crypto_dev_info_get(struct rte_cryptodev *dev,
1415d30ea906Sjfb8856606 		struct rte_cryptodev_info *info)
1416d30ea906Sjfb8856606 {
1417d30ea906Sjfb8856606 	struct virtio_crypto_hw *hw = dev->data->dev_private;
1418d30ea906Sjfb8856606 
1419d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
1420d30ea906Sjfb8856606 
1421d30ea906Sjfb8856606 	if (info != NULL) {
1422d30ea906Sjfb8856606 		info->driver_id = cryptodev_virtio_driver_id;
1423d30ea906Sjfb8856606 		info->feature_flags = dev->feature_flags;
1424d30ea906Sjfb8856606 		info->max_nb_queue_pairs = hw->max_dataqueues;
1425d30ea906Sjfb8856606 		/* No limit of number of sessions */
1426d30ea906Sjfb8856606 		info->sym.max_nb_sessions = 0;
1427d30ea906Sjfb8856606 		info->capabilities = hw->virtio_dev_capabilities;
1428d30ea906Sjfb8856606 	}
1429d30ea906Sjfb8856606 }
1430d30ea906Sjfb8856606 
1431d30ea906Sjfb8856606 static int
crypto_virtio_pci_probe(struct rte_pci_driver * pci_drv __rte_unused,struct rte_pci_device * pci_dev)1432d30ea906Sjfb8856606 crypto_virtio_pci_probe(
1433d30ea906Sjfb8856606 	struct rte_pci_driver *pci_drv __rte_unused,
1434d30ea906Sjfb8856606 	struct rte_pci_device *pci_dev)
1435d30ea906Sjfb8856606 {
1436d30ea906Sjfb8856606 	struct rte_cryptodev_pmd_init_params init_params = {
1437d30ea906Sjfb8856606 		.name = "",
14384418919fSjohnjiang 		.socket_id = pci_dev->device.numa_node,
1439d30ea906Sjfb8856606 		.private_data_size = sizeof(struct virtio_crypto_hw)
1440d30ea906Sjfb8856606 	};
1441d30ea906Sjfb8856606 	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
1442d30ea906Sjfb8856606 
1443d30ea906Sjfb8856606 	VIRTIO_CRYPTO_DRV_LOG_DBG("Found Crypto device at %02x:%02x.%x",
1444d30ea906Sjfb8856606 			pci_dev->addr.bus,
1445d30ea906Sjfb8856606 			pci_dev->addr.devid,
1446d30ea906Sjfb8856606 			pci_dev->addr.function);
1447d30ea906Sjfb8856606 
1448d30ea906Sjfb8856606 	rte_pci_device_name(&pci_dev->addr, name, sizeof(name));
1449d30ea906Sjfb8856606 
1450d30ea906Sjfb8856606 	return crypto_virtio_create(name, pci_dev, &init_params);
1451d30ea906Sjfb8856606 }
1452d30ea906Sjfb8856606 
1453d30ea906Sjfb8856606 static int
crypto_virtio_pci_remove(struct rte_pci_device * pci_dev __rte_unused)1454d30ea906Sjfb8856606 crypto_virtio_pci_remove(
1455d30ea906Sjfb8856606 	struct rte_pci_device *pci_dev __rte_unused)
1456d30ea906Sjfb8856606 {
1457d30ea906Sjfb8856606 	struct rte_cryptodev *cryptodev;
1458d30ea906Sjfb8856606 	char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
1459d30ea906Sjfb8856606 
1460d30ea906Sjfb8856606 	if (pci_dev == NULL)
1461d30ea906Sjfb8856606 		return -EINVAL;
1462d30ea906Sjfb8856606 
1463d30ea906Sjfb8856606 	rte_pci_device_name(&pci_dev->addr, cryptodev_name,
1464d30ea906Sjfb8856606 			sizeof(cryptodev_name));
1465d30ea906Sjfb8856606 
1466d30ea906Sjfb8856606 	cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
1467d30ea906Sjfb8856606 	if (cryptodev == NULL)
1468d30ea906Sjfb8856606 		return -ENODEV;
1469d30ea906Sjfb8856606 
1470d30ea906Sjfb8856606 	return virtio_crypto_dev_uninit(cryptodev);
1471d30ea906Sjfb8856606 }
1472d30ea906Sjfb8856606 
1473d30ea906Sjfb8856606 static struct rte_pci_driver rte_virtio_crypto_driver = {
1474d30ea906Sjfb8856606 	.id_table = pci_id_virtio_crypto_map,
1475d30ea906Sjfb8856606 	.drv_flags = 0,
1476d30ea906Sjfb8856606 	.probe = crypto_virtio_pci_probe,
1477d30ea906Sjfb8856606 	.remove = crypto_virtio_pci_remove
1478d30ea906Sjfb8856606 };
1479d30ea906Sjfb8856606 
1480d30ea906Sjfb8856606 static struct cryptodev_driver virtio_crypto_drv;
1481d30ea906Sjfb8856606 
1482d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI(CRYPTODEV_NAME_VIRTIO_PMD, rte_virtio_crypto_driver);
1483d30ea906Sjfb8856606 RTE_PMD_REGISTER_CRYPTO_DRIVER(virtio_crypto_drv,
1484d30ea906Sjfb8856606 	rte_virtio_crypto_driver.driver,
1485d30ea906Sjfb8856606 	cryptodev_virtio_driver_id);
1486*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(virtio_crypto_logtype_init, pmd.crypto.virtio.init, NOTICE);
1487*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(virtio_crypto_logtype_session, pmd.crypto.virtio.session,
1488*2d9fd380Sjfb8856606 		 NOTICE);
1489*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(virtio_crypto_logtype_rx, pmd.crypto.virtio.rx, NOTICE);
1490*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(virtio_crypto_logtype_tx, pmd.crypto.virtio.tx, NOTICE);
1491*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(virtio_crypto_logtype_driver, pmd.crypto.virtio.driver,
1492*2d9fd380Sjfb8856606 		 NOTICE);
1493