xref: /dpdk/drivers/crypto/virtio/virtio_cryptodev.c (revision 72f82c4324fb633d51a6a0f0e237f560d96cb1d7)
18769079aSJay Zhou /* SPDX-License-Identifier: BSD-3-Clause
28769079aSJay Zhou  * Copyright(c) 2018 HUAWEI TECHNOLOGIES CO., LTD.
38769079aSJay Zhou  */
4b7fa78c7SJay Zhou #include <stdbool.h>
5b7fa78c7SJay Zhou #include <unistd.h>
6b7fa78c7SJay Zhou 
7b7fa78c7SJay Zhou #include <rte_common.h>
86f0175ffSJay Zhou #include <rte_errno.h>
98769079aSJay Zhou #include <rte_pci.h>
108769079aSJay Zhou #include <rte_bus_pci.h>
1125500d4bSJay Zhou #include <rte_cryptodev.h>
128769079aSJay Zhou #include <rte_cryptodev_pmd.h>
1325500d4bSJay Zhou #include <rte_eal.h>
148769079aSJay Zhou 
158769079aSJay Zhou #include "virtio_cryptodev.h"
1625500d4bSJay Zhou #include "virtqueue.h"
17b7fa78c7SJay Zhou #include "virtio_crypto_algs.h"
185889e1ffSJay Zhou #include "virtio_crypto_capabilities.h"
1925500d4bSJay Zhou 
206f0175ffSJay Zhou static int virtio_crypto_dev_configure(struct rte_cryptodev *dev,
216f0175ffSJay Zhou 		struct rte_cryptodev_config *config);
226f0175ffSJay Zhou static int virtio_crypto_dev_start(struct rte_cryptodev *dev);
236f0175ffSJay Zhou static void virtio_crypto_dev_stop(struct rte_cryptodev *dev);
246f0175ffSJay Zhou static int virtio_crypto_dev_close(struct rte_cryptodev *dev);
256f0175ffSJay Zhou static void virtio_crypto_dev_info_get(struct rte_cryptodev *dev,
266f0175ffSJay Zhou 		struct rte_cryptodev_info *dev_info);
27efd3ac6bSJay Zhou static void virtio_crypto_dev_stats_get(struct rte_cryptodev *dev,
28efd3ac6bSJay Zhou 		struct rte_cryptodev_stats *stats);
29efd3ac6bSJay Zhou static void virtio_crypto_dev_stats_reset(struct rte_cryptodev *dev);
306f0175ffSJay Zhou static int virtio_crypto_qp_setup(struct rte_cryptodev *dev,
316f0175ffSJay Zhou 		uint16_t queue_pair_id,
326f0175ffSJay Zhou 		const struct rte_cryptodev_qp_conf *qp_conf,
33725d2a7fSFan Zhang 		int socket_id);
346f0175ffSJay Zhou static int virtio_crypto_qp_release(struct rte_cryptodev *dev,
356f0175ffSJay Zhou 		uint16_t queue_pair_id);
366f0175ffSJay Zhou static void virtio_crypto_dev_free_mbufs(struct rte_cryptodev *dev);
37b7fa78c7SJay Zhou static unsigned int virtio_crypto_sym_get_session_private_size(
38b7fa78c7SJay Zhou 		struct rte_cryptodev *dev);
39b7fa78c7SJay Zhou static void virtio_crypto_sym_clear_session(struct rte_cryptodev *dev,
40b7fa78c7SJay Zhou 		struct rte_cryptodev_sym_session *sess);
41b7fa78c7SJay Zhou static int virtio_crypto_sym_configure_session(struct rte_cryptodev *dev,
42b7fa78c7SJay Zhou 		struct rte_crypto_sym_xform *xform,
43b7fa78c7SJay Zhou 		struct rte_cryptodev_sym_session *session,
44b7fa78c7SJay Zhou 		struct rte_mempool *mp);
456f0175ffSJay Zhou 
4625500d4bSJay Zhou /*
4725500d4bSJay Zhou  * The set of PCI devices this driver supports
4825500d4bSJay Zhou  */
4925500d4bSJay Zhou static const struct rte_pci_id pci_id_virtio_crypto_map[] = {
5025500d4bSJay Zhou 	{ RTE_PCI_DEVICE(VIRTIO_CRYPTO_PCI_VENDORID,
5125500d4bSJay Zhou 				VIRTIO_CRYPTO_PCI_DEVICEID) },
5225500d4bSJay Zhou 	{ .vendor_id = 0, /* sentinel */ },
5325500d4bSJay Zhou };
548769079aSJay Zhou 
555889e1ffSJay Zhou static const struct rte_cryptodev_capabilities virtio_capabilities[] = {
565889e1ffSJay Zhou 	VIRTIO_SYM_CAPABILITIES,
575889e1ffSJay Zhou 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
585889e1ffSJay Zhou };
595889e1ffSJay Zhou 
608769079aSJay Zhou uint8_t cryptodev_virtio_driver_id;
618769079aSJay Zhou 
62b7fa78c7SJay Zhou #define NUM_ENTRY_SYM_CREATE_SESSION 4
63b7fa78c7SJay Zhou 
64b7fa78c7SJay Zhou static int
65b7fa78c7SJay Zhou virtio_crypto_send_command(struct virtqueue *vq,
66b7fa78c7SJay Zhou 		struct virtio_crypto_op_ctrl_req *ctrl, uint8_t *cipher_key,
67b7fa78c7SJay Zhou 		uint8_t *auth_key, struct virtio_crypto_session *session)
68b7fa78c7SJay Zhou {
69b7fa78c7SJay Zhou 	uint8_t idx = 0;
70b7fa78c7SJay Zhou 	uint8_t needed = 1;
71b7fa78c7SJay Zhou 	uint32_t head = 0;
72b7fa78c7SJay Zhou 	uint32_t len_cipher_key = 0;
73b7fa78c7SJay Zhou 	uint32_t len_auth_key = 0;
74b7fa78c7SJay Zhou 	uint32_t len_ctrl_req = sizeof(struct virtio_crypto_op_ctrl_req);
75b7fa78c7SJay Zhou 	uint32_t len_session_input = sizeof(struct virtio_crypto_session_input);
76b7fa78c7SJay Zhou 	uint32_t len_total = 0;
77b7fa78c7SJay Zhou 	uint32_t input_offset = 0;
78b7fa78c7SJay Zhou 	void *virt_addr_started = NULL;
79b7fa78c7SJay Zhou 	phys_addr_t phys_addr_started;
80b7fa78c7SJay Zhou 	struct vring_desc *desc;
81b7fa78c7SJay Zhou 	uint32_t desc_offset;
82b7fa78c7SJay Zhou 	struct virtio_crypto_session_input *input;
83b7fa78c7SJay Zhou 	int ret;
84b7fa78c7SJay Zhou 
85b7fa78c7SJay Zhou 	PMD_INIT_FUNC_TRACE();
86b7fa78c7SJay Zhou 
87b7fa78c7SJay Zhou 	if (session == NULL) {
88b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("session is NULL.");
89b7fa78c7SJay Zhou 		return -EINVAL;
90b7fa78c7SJay Zhou 	}
91b7fa78c7SJay Zhou 	/* cipher only is supported, it is available if auth_key is NULL */
92b7fa78c7SJay Zhou 	if (!cipher_key) {
93b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("cipher key is NULL.");
94b7fa78c7SJay Zhou 		return -EINVAL;
95b7fa78c7SJay Zhou 	}
96b7fa78c7SJay Zhou 
97b7fa78c7SJay Zhou 	head = vq->vq_desc_head_idx;
98b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_desc_head_idx = %d, vq = %p",
99b7fa78c7SJay Zhou 					head, vq);
100b7fa78c7SJay Zhou 
101b7fa78c7SJay Zhou 	if (vq->vq_free_cnt < needed) {
102b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Not enough entry");
103b7fa78c7SJay Zhou 		return -ENOSPC;
104b7fa78c7SJay Zhou 	}
105b7fa78c7SJay Zhou 
106b7fa78c7SJay Zhou 	/* calculate the length of cipher key */
107b7fa78c7SJay Zhou 	if (cipher_key) {
108b7fa78c7SJay Zhou 		switch (ctrl->u.sym_create_session.op_type) {
109b7fa78c7SJay Zhou 		case VIRTIO_CRYPTO_SYM_OP_CIPHER:
110b7fa78c7SJay Zhou 			len_cipher_key
111b7fa78c7SJay Zhou 				= ctrl->u.sym_create_session.u.cipher
112b7fa78c7SJay Zhou 							.para.keylen;
113b7fa78c7SJay Zhou 			break;
114b7fa78c7SJay Zhou 		case VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING:
115b7fa78c7SJay Zhou 			len_cipher_key
116b7fa78c7SJay Zhou 				= ctrl->u.sym_create_session.u.chain
117b7fa78c7SJay Zhou 					.para.cipher_param.keylen;
118b7fa78c7SJay Zhou 			break;
119b7fa78c7SJay Zhou 		default:
120b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR("invalid op type");
121b7fa78c7SJay Zhou 			return -EINVAL;
122b7fa78c7SJay Zhou 		}
123b7fa78c7SJay Zhou 	}
124b7fa78c7SJay Zhou 
125b7fa78c7SJay Zhou 	/* calculate the length of auth key */
126b7fa78c7SJay Zhou 	if (auth_key) {
127b7fa78c7SJay Zhou 		len_auth_key =
128b7fa78c7SJay Zhou 			ctrl->u.sym_create_session.u.chain.para.u.mac_param
129b7fa78c7SJay Zhou 				.auth_key_len;
130b7fa78c7SJay Zhou 	}
131b7fa78c7SJay Zhou 
132b7fa78c7SJay Zhou 	/*
133b7fa78c7SJay Zhou 	 * malloc memory to store indirect vring_desc entries, including
134b7fa78c7SJay Zhou 	 * ctrl request, cipher key, auth key, session input and desc vring
135b7fa78c7SJay Zhou 	 */
136b7fa78c7SJay Zhou 	desc_offset = len_ctrl_req + len_cipher_key + len_auth_key
137b7fa78c7SJay Zhou 		+ len_session_input;
138b7fa78c7SJay Zhou 	virt_addr_started = rte_malloc(NULL,
139b7fa78c7SJay Zhou 		desc_offset + NUM_ENTRY_SYM_CREATE_SESSION
140b7fa78c7SJay Zhou 			* sizeof(struct vring_desc), RTE_CACHE_LINE_SIZE);
141b7fa78c7SJay Zhou 	if (virt_addr_started == NULL) {
142b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("not enough heap memory");
143b7fa78c7SJay Zhou 		return -ENOSPC;
144b7fa78c7SJay Zhou 	}
145b7fa78c7SJay Zhou 	phys_addr_started = rte_malloc_virt2iova(virt_addr_started);
146b7fa78c7SJay Zhou 
147b7fa78c7SJay Zhou 	/* address to store indirect vring desc entries */
148b7fa78c7SJay Zhou 	desc = (struct vring_desc *)
149b7fa78c7SJay Zhou 		((uint8_t *)virt_addr_started + desc_offset);
150b7fa78c7SJay Zhou 
151b7fa78c7SJay Zhou 	/*  ctrl req part */
152b7fa78c7SJay Zhou 	memcpy(virt_addr_started, ctrl, len_ctrl_req);
153b7fa78c7SJay Zhou 	desc[idx].addr = phys_addr_started;
154b7fa78c7SJay Zhou 	desc[idx].len = len_ctrl_req;
155b7fa78c7SJay Zhou 	desc[idx].flags = VRING_DESC_F_NEXT;
156b7fa78c7SJay Zhou 	desc[idx].next = idx + 1;
157b7fa78c7SJay Zhou 	idx++;
158b7fa78c7SJay Zhou 	len_total += len_ctrl_req;
159b7fa78c7SJay Zhou 	input_offset += len_ctrl_req;
160b7fa78c7SJay Zhou 
161b7fa78c7SJay Zhou 	/* cipher key part */
162b7fa78c7SJay Zhou 	if (len_cipher_key > 0) {
163b7fa78c7SJay Zhou 		memcpy((uint8_t *)virt_addr_started + len_total,
164b7fa78c7SJay Zhou 			cipher_key, len_cipher_key);
165b7fa78c7SJay Zhou 
166b7fa78c7SJay Zhou 		desc[idx].addr = phys_addr_started + len_total;
167b7fa78c7SJay Zhou 		desc[idx].len = len_cipher_key;
168b7fa78c7SJay Zhou 		desc[idx].flags = VRING_DESC_F_NEXT;
169b7fa78c7SJay Zhou 		desc[idx].next = idx + 1;
170b7fa78c7SJay Zhou 		idx++;
171b7fa78c7SJay Zhou 		len_total += len_cipher_key;
172b7fa78c7SJay Zhou 		input_offset += len_cipher_key;
173b7fa78c7SJay Zhou 	}
174b7fa78c7SJay Zhou 
175b7fa78c7SJay Zhou 	/* auth key part */
176b7fa78c7SJay Zhou 	if (len_auth_key > 0) {
177b7fa78c7SJay Zhou 		memcpy((uint8_t *)virt_addr_started + len_total,
178b7fa78c7SJay Zhou 			auth_key, len_auth_key);
179b7fa78c7SJay Zhou 
180b7fa78c7SJay Zhou 		desc[idx].addr = phys_addr_started + len_total;
181b7fa78c7SJay Zhou 		desc[idx].len = len_auth_key;
182b7fa78c7SJay Zhou 		desc[idx].flags = VRING_DESC_F_NEXT;
183b7fa78c7SJay Zhou 		desc[idx].next = idx + 1;
184b7fa78c7SJay Zhou 		idx++;
185b7fa78c7SJay Zhou 		len_total += len_auth_key;
186b7fa78c7SJay Zhou 		input_offset += len_auth_key;
187b7fa78c7SJay Zhou 	}
188b7fa78c7SJay Zhou 
189b7fa78c7SJay Zhou 	/* input part */
190b7fa78c7SJay Zhou 	input = (struct virtio_crypto_session_input *)
191b7fa78c7SJay Zhou 		((uint8_t *)virt_addr_started + input_offset);
192b7fa78c7SJay Zhou 	input->status = VIRTIO_CRYPTO_ERR;
193b7fa78c7SJay Zhou 	input->session_id = ~0ULL;
194b7fa78c7SJay Zhou 	desc[idx].addr = phys_addr_started + len_total;
195b7fa78c7SJay Zhou 	desc[idx].len = len_session_input;
196b7fa78c7SJay Zhou 	desc[idx].flags = VRING_DESC_F_WRITE;
197b7fa78c7SJay Zhou 	idx++;
198b7fa78c7SJay Zhou 
199b7fa78c7SJay Zhou 	/* use a single desc entry */
200b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].addr = phys_addr_started + desc_offset;
201b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].len = idx * sizeof(struct vring_desc);
202b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].flags = VRING_DESC_F_INDIRECT;
203b7fa78c7SJay Zhou 	vq->vq_free_cnt--;
204b7fa78c7SJay Zhou 
205b7fa78c7SJay Zhou 	vq->vq_desc_head_idx = vq->vq_ring.desc[head].next;
206b7fa78c7SJay Zhou 
207b7fa78c7SJay Zhou 	vq_update_avail_ring(vq, head);
208b7fa78c7SJay Zhou 	vq_update_avail_idx(vq);
209b7fa78c7SJay Zhou 
210b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_queue_index = %d",
211b7fa78c7SJay Zhou 					vq->vq_queue_index);
212b7fa78c7SJay Zhou 
213b7fa78c7SJay Zhou 	virtqueue_notify(vq);
214b7fa78c7SJay Zhou 
215b7fa78c7SJay Zhou 	rte_rmb();
216b7fa78c7SJay Zhou 	while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) {
217b7fa78c7SJay Zhou 		rte_rmb();
218b7fa78c7SJay Zhou 		usleep(100);
219b7fa78c7SJay Zhou 	}
220b7fa78c7SJay Zhou 
221b7fa78c7SJay Zhou 	while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) {
222b7fa78c7SJay Zhou 		uint32_t idx, desc_idx, used_idx;
223b7fa78c7SJay Zhou 		struct vring_used_elem *uep;
224b7fa78c7SJay Zhou 
225b7fa78c7SJay Zhou 		used_idx = (uint32_t)(vq->vq_used_cons_idx
226b7fa78c7SJay Zhou 				& (vq->vq_nentries - 1));
227b7fa78c7SJay Zhou 		uep = &vq->vq_ring.used->ring[used_idx];
228b7fa78c7SJay Zhou 		idx = (uint32_t) uep->id;
229b7fa78c7SJay Zhou 		desc_idx = idx;
230b7fa78c7SJay Zhou 
231b7fa78c7SJay Zhou 		while (vq->vq_ring.desc[desc_idx].flags & VRING_DESC_F_NEXT) {
232b7fa78c7SJay Zhou 			desc_idx = vq->vq_ring.desc[desc_idx].next;
233b7fa78c7SJay Zhou 			vq->vq_free_cnt++;
234b7fa78c7SJay Zhou 		}
235b7fa78c7SJay Zhou 
236b7fa78c7SJay Zhou 		vq->vq_ring.desc[desc_idx].next = vq->vq_desc_head_idx;
237b7fa78c7SJay Zhou 		vq->vq_desc_head_idx = idx;
238b7fa78c7SJay Zhou 
239b7fa78c7SJay Zhou 		vq->vq_used_cons_idx++;
240b7fa78c7SJay Zhou 		vq->vq_free_cnt++;
241b7fa78c7SJay Zhou 	}
242b7fa78c7SJay Zhou 
243b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_free_cnt=%d\n"
244b7fa78c7SJay Zhou 			"vq->vq_desc_head_idx=%d",
245b7fa78c7SJay Zhou 			vq->vq_free_cnt, vq->vq_desc_head_idx);
246b7fa78c7SJay Zhou 
247b7fa78c7SJay Zhou 	/* get the result */
248b7fa78c7SJay Zhou 	if (input->status != VIRTIO_CRYPTO_OK) {
249b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Something wrong on backend! "
250b7fa78c7SJay Zhou 				"status=%u, session_id=%" PRIu64 "",
251b7fa78c7SJay Zhou 				input->status, input->session_id);
252b7fa78c7SJay Zhou 		rte_free(virt_addr_started);
253b7fa78c7SJay Zhou 		ret = -1;
254b7fa78c7SJay Zhou 	} else {
255b7fa78c7SJay Zhou 		session->session_id = input->session_id;
256b7fa78c7SJay Zhou 
257b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_INFO("Create session successfully, "
258b7fa78c7SJay Zhou 				"session_id=%" PRIu64 "", input->session_id);
259b7fa78c7SJay Zhou 		rte_free(virt_addr_started);
260b7fa78c7SJay Zhou 		ret = 0;
261b7fa78c7SJay Zhou 	}
262b7fa78c7SJay Zhou 
263b7fa78c7SJay Zhou 	return ret;
264b7fa78c7SJay Zhou }
265b7fa78c7SJay Zhou 
2666f0175ffSJay Zhou void
2676f0175ffSJay Zhou virtio_crypto_queue_release(struct virtqueue *vq)
2686f0175ffSJay Zhou {
2696f0175ffSJay Zhou 	struct virtio_crypto_hw *hw;
2706f0175ffSJay Zhou 
2716f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
2726f0175ffSJay Zhou 
2736f0175ffSJay Zhou 	if (vq) {
2746f0175ffSJay Zhou 		hw = vq->hw;
2756f0175ffSJay Zhou 		/* Select and deactivate the queue */
2766f0175ffSJay Zhou 		VTPCI_OPS(hw)->del_queue(hw, vq);
2776f0175ffSJay Zhou 
2786f0175ffSJay Zhou 		rte_memzone_free(vq->mz);
2796f0175ffSJay Zhou 		rte_mempool_free(vq->mpool);
2806f0175ffSJay Zhou 		rte_free(vq);
2816f0175ffSJay Zhou 	}
2826f0175ffSJay Zhou }
2836f0175ffSJay Zhou 
2846f0175ffSJay Zhou #define MPOOL_MAX_NAME_SZ 32
2856f0175ffSJay Zhou 
2866f0175ffSJay Zhou int
2876f0175ffSJay Zhou virtio_crypto_queue_setup(struct rte_cryptodev *dev,
2886f0175ffSJay Zhou 		int queue_type,
2896f0175ffSJay Zhou 		uint16_t vtpci_queue_idx,
2906f0175ffSJay Zhou 		uint16_t nb_desc,
2916f0175ffSJay Zhou 		int socket_id,
2926f0175ffSJay Zhou 		struct virtqueue **pvq)
2936f0175ffSJay Zhou {
2946f0175ffSJay Zhou 	char vq_name[VIRTQUEUE_MAX_NAME_SZ];
2956f0175ffSJay Zhou 	char mpool_name[MPOOL_MAX_NAME_SZ];
2966f0175ffSJay Zhou 	const struct rte_memzone *mz;
2976f0175ffSJay Zhou 	unsigned int vq_size, size;
2986f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
2996f0175ffSJay Zhou 	struct virtqueue *vq = NULL;
3006f0175ffSJay Zhou 	uint32_t i = 0;
3016f0175ffSJay Zhou 	uint32_t j;
3026f0175ffSJay Zhou 
3036f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
3046f0175ffSJay Zhou 
3056f0175ffSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("setting up queue: %u", vtpci_queue_idx);
3066f0175ffSJay Zhou 
3076f0175ffSJay Zhou 	/*
3086f0175ffSJay Zhou 	 * Read the virtqueue size from the Queue Size field
3096f0175ffSJay Zhou 	 * Always power of 2 and if 0 virtqueue does not exist
3106f0175ffSJay Zhou 	 */
3116f0175ffSJay Zhou 	vq_size = VTPCI_OPS(hw)->get_queue_num(hw, vtpci_queue_idx);
3126f0175ffSJay Zhou 	if (vq_size == 0) {
3136f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue does not exist");
3146f0175ffSJay Zhou 		return -EINVAL;
3156f0175ffSJay Zhou 	}
3166f0175ffSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq_size: %u", vq_size);
3176f0175ffSJay Zhou 
3186f0175ffSJay Zhou 	if (!rte_is_power_of_2(vq_size)) {
3196f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue size is not powerof 2");
3206f0175ffSJay Zhou 		return -EINVAL;
3216f0175ffSJay Zhou 	}
3226f0175ffSJay Zhou 
3236f0175ffSJay Zhou 	if (queue_type == VTCRYPTO_DATAQ) {
3246f0175ffSJay Zhou 		snprintf(vq_name, sizeof(vq_name), "dev%d_dataqueue%d",
3256f0175ffSJay Zhou 				dev->data->dev_id, vtpci_queue_idx);
3266f0175ffSJay Zhou 		snprintf(mpool_name, sizeof(mpool_name),
3276f0175ffSJay Zhou 				"dev%d_dataqueue%d_mpool",
3286f0175ffSJay Zhou 				dev->data->dev_id, vtpci_queue_idx);
3296f0175ffSJay Zhou 	} else if (queue_type == VTCRYPTO_CTRLQ) {
3306f0175ffSJay Zhou 		snprintf(vq_name, sizeof(vq_name), "dev%d_controlqueue",
3316f0175ffSJay Zhou 				dev->data->dev_id);
3326f0175ffSJay Zhou 		snprintf(mpool_name, sizeof(mpool_name),
3336f0175ffSJay Zhou 				"dev%d_controlqueue_mpool",
3346f0175ffSJay Zhou 				dev->data->dev_id);
3356f0175ffSJay Zhou 	}
3366f0175ffSJay Zhou 	size = RTE_ALIGN_CEIL(sizeof(*vq) +
3376f0175ffSJay Zhou 				vq_size * sizeof(struct vq_desc_extra),
3386f0175ffSJay Zhou 				RTE_CACHE_LINE_SIZE);
3396f0175ffSJay Zhou 	vq = rte_zmalloc_socket(vq_name, size, RTE_CACHE_LINE_SIZE,
3406f0175ffSJay Zhou 				socket_id);
3416f0175ffSJay Zhou 	if (vq == NULL) {
3426f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("Can not allocate virtqueue");
3436f0175ffSJay Zhou 		return -ENOMEM;
3446f0175ffSJay Zhou 	}
3456f0175ffSJay Zhou 
3466f0175ffSJay Zhou 	if (queue_type == VTCRYPTO_DATAQ) {
3476f0175ffSJay Zhou 		/* pre-allocate a mempool and use it in the data plane to
3486f0175ffSJay Zhou 		 * improve performance
3496f0175ffSJay Zhou 		 */
3506f0175ffSJay Zhou 		vq->mpool = rte_mempool_lookup(mpool_name);
3516f0175ffSJay Zhou 		if (vq->mpool == NULL)
3526f0175ffSJay Zhou 			vq->mpool = rte_mempool_create(mpool_name,
3536f0175ffSJay Zhou 					vq_size,
3546f0175ffSJay Zhou 					sizeof(struct virtio_crypto_op_cookie),
3556f0175ffSJay Zhou 					RTE_CACHE_LINE_SIZE, 0,
3566f0175ffSJay Zhou 					NULL, NULL, NULL, NULL, socket_id,
3576f0175ffSJay Zhou 					0);
3586f0175ffSJay Zhou 		if (!vq->mpool) {
3596f0175ffSJay Zhou 			VIRTIO_CRYPTO_DRV_LOG_ERR("Virtio Crypto PMD "
3606f0175ffSJay Zhou 					"Cannot create mempool");
3616f0175ffSJay Zhou 			goto mpool_create_err;
3626f0175ffSJay Zhou 		}
3636f0175ffSJay Zhou 		for (i = 0; i < vq_size; i++) {
3646f0175ffSJay Zhou 			vq->vq_descx[i].cookie =
3656f0175ffSJay Zhou 				rte_zmalloc("crypto PMD op cookie pointer",
3666f0175ffSJay Zhou 					sizeof(struct virtio_crypto_op_cookie),
3676f0175ffSJay Zhou 					RTE_CACHE_LINE_SIZE);
3686f0175ffSJay Zhou 			if (vq->vq_descx[i].cookie == NULL) {
3696f0175ffSJay Zhou 				VIRTIO_CRYPTO_DRV_LOG_ERR("Failed to "
3706f0175ffSJay Zhou 						"alloc mem for cookie");
3716f0175ffSJay Zhou 				goto cookie_alloc_err;
3726f0175ffSJay Zhou 			}
3736f0175ffSJay Zhou 		}
3746f0175ffSJay Zhou 	}
3756f0175ffSJay Zhou 
3766f0175ffSJay Zhou 	vq->hw = hw;
3776f0175ffSJay Zhou 	vq->dev_id = dev->data->dev_id;
3786f0175ffSJay Zhou 	vq->vq_queue_index = vtpci_queue_idx;
3796f0175ffSJay Zhou 	vq->vq_nentries = vq_size;
3806f0175ffSJay Zhou 
3816f0175ffSJay Zhou 	/*
3826f0175ffSJay Zhou 	 * Using part of the vring entries is permitted, but the maximum
3836f0175ffSJay Zhou 	 * is vq_size
3846f0175ffSJay Zhou 	 */
3856f0175ffSJay Zhou 	if (nb_desc == 0 || nb_desc > vq_size)
3866f0175ffSJay Zhou 		nb_desc = vq_size;
3876f0175ffSJay Zhou 	vq->vq_free_cnt = nb_desc;
3886f0175ffSJay Zhou 
3896f0175ffSJay Zhou 	/*
3906f0175ffSJay Zhou 	 * Reserve a memzone for vring elements
3916f0175ffSJay Zhou 	 */
3926f0175ffSJay Zhou 	size = vring_size(vq_size, VIRTIO_PCI_VRING_ALIGN);
3936f0175ffSJay Zhou 	vq->vq_ring_size = RTE_ALIGN_CEIL(size, VIRTIO_PCI_VRING_ALIGN);
3946f0175ffSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("%s vring_size: %d, rounded_vring_size: %d",
3956f0175ffSJay Zhou 			(queue_type == VTCRYPTO_DATAQ) ? "dataq" : "ctrlq",
3966f0175ffSJay Zhou 			size, vq->vq_ring_size);
3976f0175ffSJay Zhou 
3986f0175ffSJay Zhou 	mz = rte_memzone_reserve_aligned(vq_name, vq->vq_ring_size,
3996f0175ffSJay Zhou 			socket_id, 0, VIRTIO_PCI_VRING_ALIGN);
4006f0175ffSJay Zhou 	if (mz == NULL) {
4016f0175ffSJay Zhou 		if (rte_errno == EEXIST)
4026f0175ffSJay Zhou 			mz = rte_memzone_lookup(vq_name);
4036f0175ffSJay Zhou 		if (mz == NULL) {
4046f0175ffSJay Zhou 			VIRTIO_CRYPTO_INIT_LOG_ERR("not enough memory");
4056f0175ffSJay Zhou 			goto mz_reserve_err;
4066f0175ffSJay Zhou 		}
4076f0175ffSJay Zhou 	}
4086f0175ffSJay Zhou 
4096f0175ffSJay Zhou 	/*
4106f0175ffSJay Zhou 	 * Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit,
4116f0175ffSJay Zhou 	 * and only accepts 32 bit page frame number.
4126f0175ffSJay Zhou 	 * Check if the allocated physical memory exceeds 16TB.
4136f0175ffSJay Zhou 	 */
414*72f82c43SThomas Monjalon 	if ((mz->iova + vq->vq_ring_size - 1)
4156f0175ffSJay Zhou 				>> (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) {
4166f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("vring address shouldn't be "
4176f0175ffSJay Zhou 					"above 16TB!");
4186f0175ffSJay Zhou 		goto vring_addr_err;
4196f0175ffSJay Zhou 	}
4206f0175ffSJay Zhou 
4216f0175ffSJay Zhou 	memset(mz->addr, 0, sizeof(mz->len));
4226f0175ffSJay Zhou 	vq->mz = mz;
423*72f82c43SThomas Monjalon 	vq->vq_ring_mem = mz->iova;
4246f0175ffSJay Zhou 	vq->vq_ring_virt_mem = mz->addr;
4256f0175ffSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_ring_mem(physical): 0x%"PRIx64,
426*72f82c43SThomas Monjalon 					(uint64_t)mz->iova);
4276f0175ffSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_ring_virt_mem: 0x%"PRIx64,
4286f0175ffSJay Zhou 					(uint64_t)(uintptr_t)mz->addr);
4296f0175ffSJay Zhou 
4306f0175ffSJay Zhou 	*pvq = vq;
4316f0175ffSJay Zhou 
4326f0175ffSJay Zhou 	return 0;
4336f0175ffSJay Zhou 
4346f0175ffSJay Zhou vring_addr_err:
4356f0175ffSJay Zhou 	rte_memzone_free(mz);
4366f0175ffSJay Zhou mz_reserve_err:
4376f0175ffSJay Zhou cookie_alloc_err:
4386f0175ffSJay Zhou 	rte_mempool_free(vq->mpool);
4396f0175ffSJay Zhou 	if (i != 0) {
4406f0175ffSJay Zhou 		for (j = 0; j < i; j++)
4416f0175ffSJay Zhou 			rte_free(vq->vq_descx[j].cookie);
4426f0175ffSJay Zhou 	}
4436f0175ffSJay Zhou mpool_create_err:
4446f0175ffSJay Zhou 	rte_free(vq);
4456f0175ffSJay Zhou 	return -ENOMEM;
4466f0175ffSJay Zhou }
4476f0175ffSJay Zhou 
4486f0175ffSJay Zhou static int
4496f0175ffSJay Zhou virtio_crypto_ctrlq_setup(struct rte_cryptodev *dev, uint16_t queue_idx)
4506f0175ffSJay Zhou {
4516f0175ffSJay Zhou 	int ret;
4526f0175ffSJay Zhou 	struct virtqueue *vq;
4536f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
4546f0175ffSJay Zhou 
4556f0175ffSJay Zhou 	/* if virtio device has started, do not touch the virtqueues */
4566f0175ffSJay Zhou 	if (dev->data->dev_started)
4576f0175ffSJay Zhou 		return 0;
4586f0175ffSJay Zhou 
4596f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
4606f0175ffSJay Zhou 
4616f0175ffSJay Zhou 	ret = virtio_crypto_queue_setup(dev, VTCRYPTO_CTRLQ, queue_idx,
4626f0175ffSJay Zhou 			0, SOCKET_ID_ANY, &vq);
4636f0175ffSJay Zhou 	if (ret < 0) {
4646f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("control vq initialization failed");
4656f0175ffSJay Zhou 		return ret;
4666f0175ffSJay Zhou 	}
4676f0175ffSJay Zhou 
4686f0175ffSJay Zhou 	hw->cvq = vq;
4696f0175ffSJay Zhou 
4706f0175ffSJay Zhou 	return 0;
4716f0175ffSJay Zhou }
4726f0175ffSJay Zhou 
4736f0175ffSJay Zhou static void
4746f0175ffSJay Zhou virtio_crypto_free_queues(struct rte_cryptodev *dev)
4756f0175ffSJay Zhou {
4766f0175ffSJay Zhou 	unsigned int i;
4776f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
4786f0175ffSJay Zhou 
4796f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
4806f0175ffSJay Zhou 
4816f0175ffSJay Zhou 	/* control queue release */
4826f0175ffSJay Zhou 	virtio_crypto_queue_release(hw->cvq);
4836f0175ffSJay Zhou 
4846f0175ffSJay Zhou 	/* data queue release */
4856f0175ffSJay Zhou 	for (i = 0; i < hw->max_dataqueues; i++)
4866f0175ffSJay Zhou 		virtio_crypto_queue_release(dev->data->queue_pairs[i]);
4876f0175ffSJay Zhou }
4886f0175ffSJay Zhou 
4896f0175ffSJay Zhou static int
4906f0175ffSJay Zhou virtio_crypto_dev_close(struct rte_cryptodev *dev __rte_unused)
4916f0175ffSJay Zhou {
4926f0175ffSJay Zhou 	return 0;
4936f0175ffSJay Zhou }
4946f0175ffSJay Zhou 
49525500d4bSJay Zhou /*
49625500d4bSJay Zhou  * dev_ops for virtio, bare necessities for basic operation
49725500d4bSJay Zhou  */
49825500d4bSJay Zhou static struct rte_cryptodev_ops virtio_crypto_dev_ops = {
49925500d4bSJay Zhou 	/* Device related operations */
5006f0175ffSJay Zhou 	.dev_configure			 = virtio_crypto_dev_configure,
5016f0175ffSJay Zhou 	.dev_start			 = virtio_crypto_dev_start,
5026f0175ffSJay Zhou 	.dev_stop			 = virtio_crypto_dev_stop,
5036f0175ffSJay Zhou 	.dev_close			 = virtio_crypto_dev_close,
5046f0175ffSJay Zhou 	.dev_infos_get			 = virtio_crypto_dev_info_get,
50525500d4bSJay Zhou 
506efd3ac6bSJay Zhou 	.stats_get			 = virtio_crypto_dev_stats_get,
507efd3ac6bSJay Zhou 	.stats_reset			 = virtio_crypto_dev_stats_reset,
50825500d4bSJay Zhou 
5096f0175ffSJay Zhou 	.queue_pair_setup                = virtio_crypto_qp_setup,
5106f0175ffSJay Zhou 	.queue_pair_release              = virtio_crypto_qp_release,
51125500d4bSJay Zhou 
51225500d4bSJay Zhou 	/* Crypto related operations */
513012c5076SPablo de Lara 	.sym_session_get_size		= virtio_crypto_sym_get_session_private_size,
514012c5076SPablo de Lara 	.sym_session_configure		= virtio_crypto_sym_configure_session,
515012c5076SPablo de Lara 	.sym_session_clear		= virtio_crypto_sym_clear_session
51625500d4bSJay Zhou };
51725500d4bSJay Zhou 
518efd3ac6bSJay Zhou static void
519efd3ac6bSJay Zhou virtio_crypto_update_stats(struct rte_cryptodev *dev,
520efd3ac6bSJay Zhou 		struct rte_cryptodev_stats *stats)
521efd3ac6bSJay Zhou {
522efd3ac6bSJay Zhou 	unsigned int i;
523efd3ac6bSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
524efd3ac6bSJay Zhou 
525efd3ac6bSJay Zhou 	PMD_INIT_FUNC_TRACE();
526efd3ac6bSJay Zhou 
527efd3ac6bSJay Zhou 	if (stats == NULL) {
528efd3ac6bSJay Zhou 		VIRTIO_CRYPTO_DRV_LOG_ERR("invalid pointer");
529efd3ac6bSJay Zhou 		return;
530efd3ac6bSJay Zhou 	}
531efd3ac6bSJay Zhou 
532efd3ac6bSJay Zhou 	for (i = 0; i < hw->max_dataqueues; i++) {
533efd3ac6bSJay Zhou 		const struct virtqueue *data_queue
534efd3ac6bSJay Zhou 			= dev->data->queue_pairs[i];
535efd3ac6bSJay Zhou 		if (data_queue == NULL)
536efd3ac6bSJay Zhou 			continue;
537efd3ac6bSJay Zhou 
538efd3ac6bSJay Zhou 		stats->enqueued_count += data_queue->packets_sent_total;
539efd3ac6bSJay Zhou 		stats->enqueue_err_count += data_queue->packets_sent_failed;
540efd3ac6bSJay Zhou 
541efd3ac6bSJay Zhou 		stats->dequeued_count += data_queue->packets_received_total;
542efd3ac6bSJay Zhou 		stats->dequeue_err_count
543efd3ac6bSJay Zhou 			+= data_queue->packets_received_failed;
544efd3ac6bSJay Zhou 	}
545efd3ac6bSJay Zhou }
546efd3ac6bSJay Zhou 
547efd3ac6bSJay Zhou static void
548efd3ac6bSJay Zhou virtio_crypto_dev_stats_get(struct rte_cryptodev *dev,
549efd3ac6bSJay Zhou 		struct rte_cryptodev_stats *stats)
550efd3ac6bSJay Zhou {
551efd3ac6bSJay Zhou 	PMD_INIT_FUNC_TRACE();
552efd3ac6bSJay Zhou 
553efd3ac6bSJay Zhou 	virtio_crypto_update_stats(dev, stats);
554efd3ac6bSJay Zhou }
555efd3ac6bSJay Zhou 
556efd3ac6bSJay Zhou static void
557efd3ac6bSJay Zhou virtio_crypto_dev_stats_reset(struct rte_cryptodev *dev)
558efd3ac6bSJay Zhou {
559efd3ac6bSJay Zhou 	unsigned int i;
560efd3ac6bSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
561efd3ac6bSJay Zhou 
562efd3ac6bSJay Zhou 	PMD_INIT_FUNC_TRACE();
563efd3ac6bSJay Zhou 
564efd3ac6bSJay Zhou 	for (i = 0; i < hw->max_dataqueues; i++) {
565efd3ac6bSJay Zhou 		struct virtqueue *data_queue = dev->data->queue_pairs[i];
566efd3ac6bSJay Zhou 		if (data_queue == NULL)
567efd3ac6bSJay Zhou 			continue;
568efd3ac6bSJay Zhou 
569efd3ac6bSJay Zhou 		data_queue->packets_sent_total = 0;
570efd3ac6bSJay Zhou 		data_queue->packets_sent_failed = 0;
571efd3ac6bSJay Zhou 
572efd3ac6bSJay Zhou 		data_queue->packets_received_total = 0;
573efd3ac6bSJay Zhou 		data_queue->packets_received_failed = 0;
574efd3ac6bSJay Zhou 	}
575efd3ac6bSJay Zhou }
576efd3ac6bSJay Zhou 
57725500d4bSJay Zhou static int
5786f0175ffSJay Zhou virtio_crypto_qp_setup(struct rte_cryptodev *dev, uint16_t queue_pair_id,
5796f0175ffSJay Zhou 		const struct rte_cryptodev_qp_conf *qp_conf,
580725d2a7fSFan Zhang 		int socket_id)
5816f0175ffSJay Zhou {
5826f0175ffSJay Zhou 	int ret;
5836f0175ffSJay Zhou 	struct virtqueue *vq;
5846f0175ffSJay Zhou 
5856f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
5866f0175ffSJay Zhou 
5876f0175ffSJay Zhou 	/* if virtio dev is started, do not touch the virtqueues */
5886f0175ffSJay Zhou 	if (dev->data->dev_started)
5896f0175ffSJay Zhou 		return 0;
5906f0175ffSJay Zhou 
5916f0175ffSJay Zhou 	ret = virtio_crypto_queue_setup(dev, VTCRYPTO_DATAQ, queue_pair_id,
5926f0175ffSJay Zhou 			qp_conf->nb_descriptors, socket_id, &vq);
5936f0175ffSJay Zhou 	if (ret < 0) {
5946f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR(
5956f0175ffSJay Zhou 			"virtio crypto data queue initialization failed\n");
5966f0175ffSJay Zhou 		return ret;
5976f0175ffSJay Zhou 	}
5986f0175ffSJay Zhou 
5996f0175ffSJay Zhou 	dev->data->queue_pairs[queue_pair_id] = vq;
6006f0175ffSJay Zhou 
6016f0175ffSJay Zhou 	return 0;
6026f0175ffSJay Zhou }
6036f0175ffSJay Zhou 
6046f0175ffSJay Zhou static int
6056f0175ffSJay Zhou virtio_crypto_qp_release(struct rte_cryptodev *dev, uint16_t queue_pair_id)
6066f0175ffSJay Zhou {
6076f0175ffSJay Zhou 	struct virtqueue *vq
6086f0175ffSJay Zhou 		= (struct virtqueue *)dev->data->queue_pairs[queue_pair_id];
6096f0175ffSJay Zhou 
6106f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
6116f0175ffSJay Zhou 
6126f0175ffSJay Zhou 	if (vq == NULL) {
6136f0175ffSJay Zhou 		VIRTIO_CRYPTO_DRV_LOG_DBG("vq already freed");
6146f0175ffSJay Zhou 		return 0;
6156f0175ffSJay Zhou 	}
6166f0175ffSJay Zhou 
6176f0175ffSJay Zhou 	virtio_crypto_queue_release(vq);
6186f0175ffSJay Zhou 	return 0;
6196f0175ffSJay Zhou }
6206f0175ffSJay Zhou 
6216f0175ffSJay Zhou static int
62225500d4bSJay Zhou virtio_negotiate_features(struct virtio_crypto_hw *hw, uint64_t req_features)
62325500d4bSJay Zhou {
62425500d4bSJay Zhou 	uint64_t host_features;
62525500d4bSJay Zhou 
62625500d4bSJay Zhou 	PMD_INIT_FUNC_TRACE();
62725500d4bSJay Zhou 
62825500d4bSJay Zhou 	/* Prepare guest_features: feature that driver wants to support */
62925500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("guest_features before negotiate = %" PRIx64,
63025500d4bSJay Zhou 		req_features);
63125500d4bSJay Zhou 
63225500d4bSJay Zhou 	/* Read device(host) feature bits */
63325500d4bSJay Zhou 	host_features = VTPCI_OPS(hw)->get_features(hw);
63425500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("host_features before negotiate = %" PRIx64,
63525500d4bSJay Zhou 		host_features);
63625500d4bSJay Zhou 
63725500d4bSJay Zhou 	/*
63825500d4bSJay Zhou 	 * Negotiate features: Subset of device feature bits are written back
63925500d4bSJay Zhou 	 * guest feature bits.
64025500d4bSJay Zhou 	 */
64125500d4bSJay Zhou 	hw->guest_features = req_features;
64225500d4bSJay Zhou 	hw->guest_features = vtpci_cryptodev_negotiate_features(hw,
64325500d4bSJay Zhou 							host_features);
64425500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("features after negotiate = %" PRIx64,
64525500d4bSJay Zhou 		hw->guest_features);
64625500d4bSJay Zhou 
64725500d4bSJay Zhou 	if (hw->modern) {
64825500d4bSJay Zhou 		if (!vtpci_with_feature(hw, VIRTIO_F_VERSION_1)) {
64925500d4bSJay Zhou 			VIRTIO_CRYPTO_INIT_LOG_ERR(
65025500d4bSJay Zhou 				"VIRTIO_F_VERSION_1 features is not enabled.");
65125500d4bSJay Zhou 			return -1;
65225500d4bSJay Zhou 		}
65325500d4bSJay Zhou 		vtpci_cryptodev_set_status(hw,
65425500d4bSJay Zhou 			VIRTIO_CONFIG_STATUS_FEATURES_OK);
65525500d4bSJay Zhou 		if (!(vtpci_cryptodev_get_status(hw) &
65625500d4bSJay Zhou 			VIRTIO_CONFIG_STATUS_FEATURES_OK)) {
65725500d4bSJay Zhou 			VIRTIO_CRYPTO_INIT_LOG_ERR("failed to set FEATURES_OK "
65825500d4bSJay Zhou 						"status!");
65925500d4bSJay Zhou 			return -1;
66025500d4bSJay Zhou 		}
66125500d4bSJay Zhou 	}
66225500d4bSJay Zhou 
66325500d4bSJay Zhou 	hw->req_guest_features = req_features;
66425500d4bSJay Zhou 
66525500d4bSJay Zhou 	return 0;
66625500d4bSJay Zhou }
66725500d4bSJay Zhou 
66825500d4bSJay Zhou /* reset device and renegotiate features if needed */
66925500d4bSJay Zhou static int
67025500d4bSJay Zhou virtio_crypto_init_device(struct rte_cryptodev *cryptodev,
67125500d4bSJay Zhou 	uint64_t req_features)
67225500d4bSJay Zhou {
67325500d4bSJay Zhou 	struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
67425500d4bSJay Zhou 	struct virtio_crypto_config local_config;
67525500d4bSJay Zhou 	struct virtio_crypto_config *config = &local_config;
67625500d4bSJay Zhou 
67725500d4bSJay Zhou 	PMD_INIT_FUNC_TRACE();
67825500d4bSJay Zhou 
67925500d4bSJay Zhou 	/* Reset the device although not necessary at startup */
68025500d4bSJay Zhou 	vtpci_cryptodev_reset(hw);
68125500d4bSJay Zhou 
68225500d4bSJay Zhou 	/* Tell the host we've noticed this device. */
68325500d4bSJay Zhou 	vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_ACK);
68425500d4bSJay Zhou 
68525500d4bSJay Zhou 	/* Tell the host we've known how to drive the device. */
68625500d4bSJay Zhou 	vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER);
68725500d4bSJay Zhou 	if (virtio_negotiate_features(hw, req_features) < 0)
68825500d4bSJay Zhou 		return -1;
68925500d4bSJay Zhou 
69025500d4bSJay Zhou 	/* Get status of the device */
69125500d4bSJay Zhou 	vtpci_read_cryptodev_config(hw,
69225500d4bSJay Zhou 		offsetof(struct virtio_crypto_config, status),
69325500d4bSJay Zhou 		&config->status, sizeof(config->status));
69425500d4bSJay Zhou 	if (config->status != VIRTIO_CRYPTO_S_HW_READY) {
69525500d4bSJay Zhou 		VIRTIO_CRYPTO_DRV_LOG_ERR("accelerator hardware is "
69625500d4bSJay Zhou 				"not ready");
69725500d4bSJay Zhou 		return -1;
69825500d4bSJay Zhou 	}
69925500d4bSJay Zhou 
70025500d4bSJay Zhou 	/* Get number of data queues */
70125500d4bSJay Zhou 	vtpci_read_cryptodev_config(hw,
70225500d4bSJay Zhou 		offsetof(struct virtio_crypto_config, max_dataqueues),
70325500d4bSJay Zhou 		&config->max_dataqueues,
70425500d4bSJay Zhou 		sizeof(config->max_dataqueues));
70525500d4bSJay Zhou 	hw->max_dataqueues = config->max_dataqueues;
70625500d4bSJay Zhou 
70725500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("hw->max_dataqueues=%d",
70825500d4bSJay Zhou 		hw->max_dataqueues);
70925500d4bSJay Zhou 
71025500d4bSJay Zhou 	return 0;
71125500d4bSJay Zhou }
71225500d4bSJay Zhou 
71325500d4bSJay Zhou /*
71425500d4bSJay Zhou  * This function is based on probe() function
71525500d4bSJay Zhou  * It returns 0 on success.
71625500d4bSJay Zhou  */
71725500d4bSJay Zhou static int
71825500d4bSJay Zhou crypto_virtio_create(const char *name, struct rte_pci_device *pci_dev,
71925500d4bSJay Zhou 		struct rte_cryptodev_pmd_init_params *init_params)
72025500d4bSJay Zhou {
72125500d4bSJay Zhou 	struct rte_cryptodev *cryptodev;
72225500d4bSJay Zhou 	struct virtio_crypto_hw *hw;
72325500d4bSJay Zhou 
72425500d4bSJay Zhou 	PMD_INIT_FUNC_TRACE();
72525500d4bSJay Zhou 
72625500d4bSJay Zhou 	cryptodev = rte_cryptodev_pmd_create(name, &pci_dev->device,
72725500d4bSJay Zhou 					init_params);
72825500d4bSJay Zhou 	if (cryptodev == NULL)
72925500d4bSJay Zhou 		return -ENODEV;
73025500d4bSJay Zhou 
73125500d4bSJay Zhou 	cryptodev->driver_id = cryptodev_virtio_driver_id;
73225500d4bSJay Zhou 	cryptodev->dev_ops = &virtio_crypto_dev_ops;
73325500d4bSJay Zhou 
73425500d4bSJay Zhou 	cryptodev->enqueue_burst = virtio_crypto_pkt_tx_burst;
73525500d4bSJay Zhou 	cryptodev->dequeue_burst = virtio_crypto_pkt_rx_burst;
73625500d4bSJay Zhou 
73725500d4bSJay Zhou 	cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
738b7aa3b5bSJay Zhou 		RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
739b7aa3b5bSJay Zhou 		RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT;
74025500d4bSJay Zhou 
74125500d4bSJay Zhou 	hw = cryptodev->data->dev_private;
74225500d4bSJay Zhou 	hw->dev_id = cryptodev->data->dev_id;
7435889e1ffSJay Zhou 	hw->virtio_dev_capabilities = virtio_capabilities;
74425500d4bSJay Zhou 
74525500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("dev %d vendorID=0x%x deviceID=0x%x",
74625500d4bSJay Zhou 		cryptodev->data->dev_id, pci_dev->id.vendor_id,
74725500d4bSJay Zhou 		pci_dev->id.device_id);
74825500d4bSJay Zhou 
74925500d4bSJay Zhou 	/* pci device init */
75025500d4bSJay Zhou 	if (vtpci_cryptodev_init(pci_dev, hw))
75125500d4bSJay Zhou 		return -1;
75225500d4bSJay Zhou 
75325500d4bSJay Zhou 	if (virtio_crypto_init_device(cryptodev,
75425500d4bSJay Zhou 			VIRTIO_CRYPTO_PMD_GUEST_FEATURES) < 0)
75525500d4bSJay Zhou 		return -1;
75625500d4bSJay Zhou 
75725500d4bSJay Zhou 	return 0;
75825500d4bSJay Zhou }
75925500d4bSJay Zhou 
7608769079aSJay Zhou static int
7616f0175ffSJay Zhou virtio_crypto_dev_uninit(struct rte_cryptodev *cryptodev)
7626f0175ffSJay Zhou {
7636f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
7646f0175ffSJay Zhou 
7656f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
7666f0175ffSJay Zhou 
7676f0175ffSJay Zhou 	if (rte_eal_process_type() == RTE_PROC_SECONDARY)
7686f0175ffSJay Zhou 		return -EPERM;
7696f0175ffSJay Zhou 
7706f0175ffSJay Zhou 	if (cryptodev->data->dev_started) {
7716f0175ffSJay Zhou 		virtio_crypto_dev_stop(cryptodev);
7726f0175ffSJay Zhou 		virtio_crypto_dev_close(cryptodev);
7736f0175ffSJay Zhou 	}
7746f0175ffSJay Zhou 
7756f0175ffSJay Zhou 	cryptodev->dev_ops = NULL;
7766f0175ffSJay Zhou 	cryptodev->enqueue_burst = NULL;
7776f0175ffSJay Zhou 	cryptodev->dequeue_burst = NULL;
7786f0175ffSJay Zhou 
7796f0175ffSJay Zhou 	/* release control queue */
7806f0175ffSJay Zhou 	virtio_crypto_queue_release(hw->cvq);
7816f0175ffSJay Zhou 
7826f0175ffSJay Zhou 	rte_free(cryptodev->data);
7836f0175ffSJay Zhou 	cryptodev->data = NULL;
7846f0175ffSJay Zhou 
7856f0175ffSJay Zhou 	VIRTIO_CRYPTO_DRV_LOG_INFO("dev_uninit completed");
7866f0175ffSJay Zhou 
7876f0175ffSJay Zhou 	return 0;
7886f0175ffSJay Zhou }
7896f0175ffSJay Zhou 
7906f0175ffSJay Zhou static int
7916f0175ffSJay Zhou virtio_crypto_dev_configure(struct rte_cryptodev *cryptodev,
7926f0175ffSJay Zhou 	struct rte_cryptodev_config *config __rte_unused)
7936f0175ffSJay Zhou {
7946f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
7956f0175ffSJay Zhou 
7966f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
7976f0175ffSJay Zhou 
7986f0175ffSJay Zhou 	if (virtio_crypto_init_device(cryptodev,
7996f0175ffSJay Zhou 			VIRTIO_CRYPTO_PMD_GUEST_FEATURES) < 0)
8006f0175ffSJay Zhou 		return -1;
8016f0175ffSJay Zhou 
8026f0175ffSJay Zhou 	/* setup control queue
8036f0175ffSJay Zhou 	 * [0, 1, ... ,(config->max_dataqueues - 1)] are data queues
8046f0175ffSJay Zhou 	 * config->max_dataqueues is the control queue
8056f0175ffSJay Zhou 	 */
8066f0175ffSJay Zhou 	if (virtio_crypto_ctrlq_setup(cryptodev, hw->max_dataqueues) < 0) {
8076f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("control queue setup error");
8086f0175ffSJay Zhou 		return -1;
8096f0175ffSJay Zhou 	}
8106f0175ffSJay Zhou 	virtio_crypto_ctrlq_start(cryptodev);
8116f0175ffSJay Zhou 
8126f0175ffSJay Zhou 	return 0;
8136f0175ffSJay Zhou }
8146f0175ffSJay Zhou 
8156f0175ffSJay Zhou static void
8166f0175ffSJay Zhou virtio_crypto_dev_stop(struct rte_cryptodev *dev)
8176f0175ffSJay Zhou {
8186f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
8196f0175ffSJay Zhou 
8206f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
8216f0175ffSJay Zhou 	VIRTIO_CRYPTO_DRV_LOG_DBG("virtio_dev_stop");
8226f0175ffSJay Zhou 
8236f0175ffSJay Zhou 	vtpci_cryptodev_reset(hw);
8246f0175ffSJay Zhou 
8256f0175ffSJay Zhou 	virtio_crypto_dev_free_mbufs(dev);
8266f0175ffSJay Zhou 	virtio_crypto_free_queues(dev);
8276f0175ffSJay Zhou 
8286f0175ffSJay Zhou 	dev->data->dev_started = 0;
8296f0175ffSJay Zhou }
8306f0175ffSJay Zhou 
8316f0175ffSJay Zhou static int
8326f0175ffSJay Zhou virtio_crypto_dev_start(struct rte_cryptodev *dev)
8336f0175ffSJay Zhou {
8346f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
8356f0175ffSJay Zhou 
8366f0175ffSJay Zhou 	if (dev->data->dev_started)
8376f0175ffSJay Zhou 		return 0;
8386f0175ffSJay Zhou 
8396f0175ffSJay Zhou 	/* Do final configuration before queue engine starts */
8406f0175ffSJay Zhou 	virtio_crypto_dataq_start(dev);
8416f0175ffSJay Zhou 	vtpci_cryptodev_reinit_complete(hw);
8426f0175ffSJay Zhou 
8436f0175ffSJay Zhou 	dev->data->dev_started = 1;
8446f0175ffSJay Zhou 
8456f0175ffSJay Zhou 	return 0;
8466f0175ffSJay Zhou }
8476f0175ffSJay Zhou 
8486f0175ffSJay Zhou static void
8496f0175ffSJay Zhou virtio_crypto_dev_free_mbufs(struct rte_cryptodev *dev)
8506f0175ffSJay Zhou {
8516f0175ffSJay Zhou 	uint32_t i;
8526f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
8536f0175ffSJay Zhou 
8546f0175ffSJay Zhou 	for (i = 0; i < hw->max_dataqueues; i++) {
8556f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_DBG("Before freeing dataq[%d] used "
8566f0175ffSJay Zhou 			"and unused buf", i);
8576f0175ffSJay Zhou 		VIRTQUEUE_DUMP((struct virtqueue *)
8586f0175ffSJay Zhou 			dev->data->queue_pairs[i]);
8596f0175ffSJay Zhou 
8606f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_DBG("queue_pairs[%d]=%p",
8616f0175ffSJay Zhou 				i, dev->data->queue_pairs[i]);
8626f0175ffSJay Zhou 
8636f0175ffSJay Zhou 		virtqueue_detatch_unused(dev->data->queue_pairs[i]);
8646f0175ffSJay Zhou 
8656f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_DBG("After freeing dataq[%d] used and "
8666f0175ffSJay Zhou 					"unused buf", i);
8676f0175ffSJay Zhou 		VIRTQUEUE_DUMP(
8686f0175ffSJay Zhou 			(struct virtqueue *)dev->data->queue_pairs[i]);
8696f0175ffSJay Zhou 	}
8706f0175ffSJay Zhou }
8716f0175ffSJay Zhou 
872b7fa78c7SJay Zhou static unsigned int
873b7fa78c7SJay Zhou virtio_crypto_sym_get_session_private_size(
874b7fa78c7SJay Zhou 		struct rte_cryptodev *dev __rte_unused)
875b7fa78c7SJay Zhou {
876b7fa78c7SJay Zhou 	PMD_INIT_FUNC_TRACE();
877b7fa78c7SJay Zhou 
878b7fa78c7SJay Zhou 	return RTE_ALIGN_CEIL(sizeof(struct virtio_crypto_session), 16);
879b7fa78c7SJay Zhou }
880b7fa78c7SJay Zhou 
881b7fa78c7SJay Zhou static int
882b7fa78c7SJay Zhou virtio_crypto_check_sym_session_paras(
883b7fa78c7SJay Zhou 		struct rte_cryptodev *dev)
884b7fa78c7SJay Zhou {
885b7fa78c7SJay Zhou 	struct virtio_crypto_hw *hw;
886b7fa78c7SJay Zhou 
887b7fa78c7SJay Zhou 	PMD_INIT_FUNC_TRACE();
888b7fa78c7SJay Zhou 
889b7fa78c7SJay Zhou 	if (unlikely(dev == NULL)) {
890b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("dev is NULL");
891b7fa78c7SJay Zhou 		return -1;
892b7fa78c7SJay Zhou 	}
893b7fa78c7SJay Zhou 	if (unlikely(dev->data == NULL)) {
894b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("dev->data is NULL");
895b7fa78c7SJay Zhou 		return -1;
896b7fa78c7SJay Zhou 	}
897b7fa78c7SJay Zhou 	hw = dev->data->dev_private;
898b7fa78c7SJay Zhou 	if (unlikely(hw == NULL)) {
899b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("hw is NULL");
900b7fa78c7SJay Zhou 		return -1;
901b7fa78c7SJay Zhou 	}
902b7fa78c7SJay Zhou 	if (unlikely(hw->cvq == NULL)) {
903b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("vq is NULL");
904b7fa78c7SJay Zhou 		return -1;
905b7fa78c7SJay Zhou 	}
906b7fa78c7SJay Zhou 
907b7fa78c7SJay Zhou 	return 0;
908b7fa78c7SJay Zhou }
909b7fa78c7SJay Zhou 
910b7fa78c7SJay Zhou static int
911b7fa78c7SJay Zhou virtio_crypto_check_sym_clear_session_paras(
912b7fa78c7SJay Zhou 		struct rte_cryptodev *dev,
913b7fa78c7SJay Zhou 		struct rte_cryptodev_sym_session *sess)
914b7fa78c7SJay Zhou {
915b7fa78c7SJay Zhou 	PMD_INIT_FUNC_TRACE();
916b7fa78c7SJay Zhou 
917b7fa78c7SJay Zhou 	if (sess == NULL) {
918b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("sym_session is NULL");
919b7fa78c7SJay Zhou 		return -1;
920b7fa78c7SJay Zhou 	}
921b7fa78c7SJay Zhou 
922b7fa78c7SJay Zhou 	return virtio_crypto_check_sym_session_paras(dev);
923b7fa78c7SJay Zhou }
924b7fa78c7SJay Zhou 
925b7fa78c7SJay Zhou #define NUM_ENTRY_SYM_CLEAR_SESSION 2
926b7fa78c7SJay Zhou 
927b7fa78c7SJay Zhou static void
928b7fa78c7SJay Zhou virtio_crypto_sym_clear_session(
929b7fa78c7SJay Zhou 		struct rte_cryptodev *dev,
930b7fa78c7SJay Zhou 		struct rte_cryptodev_sym_session *sess)
931b7fa78c7SJay Zhou {
932b7fa78c7SJay Zhou 	struct virtio_crypto_hw *hw;
933b7fa78c7SJay Zhou 	struct virtqueue *vq;
934b7fa78c7SJay Zhou 	struct virtio_crypto_session *session;
935b7fa78c7SJay Zhou 	struct virtio_crypto_op_ctrl_req *ctrl;
936b7fa78c7SJay Zhou 	struct vring_desc *desc;
937b7fa78c7SJay Zhou 	uint8_t *status;
938b7fa78c7SJay Zhou 	uint8_t needed = 1;
939b7fa78c7SJay Zhou 	uint32_t head;
940b7fa78c7SJay Zhou 	uint8_t *malloc_virt_addr;
941b7fa78c7SJay Zhou 	uint64_t malloc_phys_addr;
942b7fa78c7SJay Zhou 	uint8_t len_inhdr = sizeof(struct virtio_crypto_inhdr);
943b7fa78c7SJay Zhou 	uint32_t len_op_ctrl_req = sizeof(struct virtio_crypto_op_ctrl_req);
944b7fa78c7SJay Zhou 	uint32_t desc_offset = len_op_ctrl_req + len_inhdr;
945b7fa78c7SJay Zhou 
946b7fa78c7SJay Zhou 	PMD_INIT_FUNC_TRACE();
947b7fa78c7SJay Zhou 
948b7fa78c7SJay Zhou 	if (virtio_crypto_check_sym_clear_session_paras(dev, sess) < 0)
949b7fa78c7SJay Zhou 		return;
950b7fa78c7SJay Zhou 
951b7fa78c7SJay Zhou 	hw = dev->data->dev_private;
952b7fa78c7SJay Zhou 	vq = hw->cvq;
953012c5076SPablo de Lara 	session = (struct virtio_crypto_session *)get_sym_session_private_data(
954b7fa78c7SJay Zhou 		sess, cryptodev_virtio_driver_id);
955b7fa78c7SJay Zhou 	if (session == NULL) {
956b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Invalid session parameter");
957b7fa78c7SJay Zhou 		return;
958b7fa78c7SJay Zhou 	}
959b7fa78c7SJay Zhou 
960b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_SESSION_LOG_INFO("vq->vq_desc_head_idx = %d, "
961b7fa78c7SJay Zhou 			"vq = %p", vq->vq_desc_head_idx, vq);
962b7fa78c7SJay Zhou 
963b7fa78c7SJay Zhou 	if (vq->vq_free_cnt < needed) {
964b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
965b7fa78c7SJay Zhou 				"vq->vq_free_cnt = %d is less than %d, "
966b7fa78c7SJay Zhou 				"not enough", vq->vq_free_cnt, needed);
967b7fa78c7SJay Zhou 		return;
968b7fa78c7SJay Zhou 	}
969b7fa78c7SJay Zhou 
970b7fa78c7SJay Zhou 	/*
971b7fa78c7SJay Zhou 	 * malloc memory to store information of ctrl request op,
972b7fa78c7SJay Zhou 	 * returned status and desc vring
973b7fa78c7SJay Zhou 	 */
974b7fa78c7SJay Zhou 	malloc_virt_addr = rte_malloc(NULL, len_op_ctrl_req + len_inhdr
975b7fa78c7SJay Zhou 		+ NUM_ENTRY_SYM_CLEAR_SESSION
976b7fa78c7SJay Zhou 		* sizeof(struct vring_desc), RTE_CACHE_LINE_SIZE);
977b7fa78c7SJay Zhou 	if (malloc_virt_addr == NULL) {
978b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("not enough heap room");
979b7fa78c7SJay Zhou 		return;
980b7fa78c7SJay Zhou 	}
981b7fa78c7SJay Zhou 	malloc_phys_addr = rte_malloc_virt2iova(malloc_virt_addr);
982b7fa78c7SJay Zhou 
983b7fa78c7SJay Zhou 	/* assign ctrl request op part */
984b7fa78c7SJay Zhou 	ctrl = (struct virtio_crypto_op_ctrl_req *)malloc_virt_addr;
985b7fa78c7SJay Zhou 	ctrl->header.opcode = VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION;
986b7fa78c7SJay Zhou 	/* default data virtqueue is 0 */
987b7fa78c7SJay Zhou 	ctrl->header.queue_id = 0;
988b7fa78c7SJay Zhou 	ctrl->u.destroy_session.session_id = session->session_id;
989b7fa78c7SJay Zhou 
990b7fa78c7SJay Zhou 	/* status part */
991b7fa78c7SJay Zhou 	status = &(((struct virtio_crypto_inhdr *)
992b7fa78c7SJay Zhou 		((uint8_t *)malloc_virt_addr + len_op_ctrl_req))->status);
993b7fa78c7SJay Zhou 	*status = VIRTIO_CRYPTO_ERR;
994b7fa78c7SJay Zhou 
995b7fa78c7SJay Zhou 	/* indirect desc vring part */
996b7fa78c7SJay Zhou 	desc = (struct vring_desc *)((uint8_t *)malloc_virt_addr
997b7fa78c7SJay Zhou 		+ desc_offset);
998b7fa78c7SJay Zhou 
999b7fa78c7SJay Zhou 	/* ctrl request part */
1000b7fa78c7SJay Zhou 	desc[0].addr = malloc_phys_addr;
1001b7fa78c7SJay Zhou 	desc[0].len = len_op_ctrl_req;
1002b7fa78c7SJay Zhou 	desc[0].flags = VRING_DESC_F_NEXT;
1003b7fa78c7SJay Zhou 	desc[0].next = 1;
1004b7fa78c7SJay Zhou 
1005b7fa78c7SJay Zhou 	/* status part */
1006b7fa78c7SJay Zhou 	desc[1].addr = malloc_phys_addr + len_op_ctrl_req;
1007b7fa78c7SJay Zhou 	desc[1].len = len_inhdr;
1008b7fa78c7SJay Zhou 	desc[1].flags = VRING_DESC_F_WRITE;
1009b7fa78c7SJay Zhou 
1010b7fa78c7SJay Zhou 	/* use only a single desc entry */
1011b7fa78c7SJay Zhou 	head = vq->vq_desc_head_idx;
1012b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].flags = VRING_DESC_F_INDIRECT;
1013b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].addr = malloc_phys_addr + desc_offset;
1014b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].len
1015b7fa78c7SJay Zhou 		= NUM_ENTRY_SYM_CLEAR_SESSION
1016b7fa78c7SJay Zhou 		* sizeof(struct vring_desc);
1017b7fa78c7SJay Zhou 	vq->vq_free_cnt -= needed;
1018b7fa78c7SJay Zhou 
1019b7fa78c7SJay Zhou 	vq->vq_desc_head_idx = vq->vq_ring.desc[head].next;
1020b7fa78c7SJay Zhou 
1021b7fa78c7SJay Zhou 	vq_update_avail_ring(vq, head);
1022b7fa78c7SJay Zhou 	vq_update_avail_idx(vq);
1023b7fa78c7SJay Zhou 
1024b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_queue_index = %d",
1025b7fa78c7SJay Zhou 					vq->vq_queue_index);
1026b7fa78c7SJay Zhou 
1027b7fa78c7SJay Zhou 	virtqueue_notify(vq);
1028b7fa78c7SJay Zhou 
1029b7fa78c7SJay Zhou 	rte_rmb();
1030b7fa78c7SJay Zhou 	while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) {
1031b7fa78c7SJay Zhou 		rte_rmb();
1032b7fa78c7SJay Zhou 		usleep(100);
1033b7fa78c7SJay Zhou 	}
1034b7fa78c7SJay Zhou 
1035b7fa78c7SJay Zhou 	while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) {
1036b7fa78c7SJay Zhou 		uint32_t idx, desc_idx, used_idx;
1037b7fa78c7SJay Zhou 		struct vring_used_elem *uep;
1038b7fa78c7SJay Zhou 
1039b7fa78c7SJay Zhou 		used_idx = (uint32_t)(vq->vq_used_cons_idx
1040b7fa78c7SJay Zhou 				& (vq->vq_nentries - 1));
1041b7fa78c7SJay Zhou 		uep = &vq->vq_ring.used->ring[used_idx];
1042b7fa78c7SJay Zhou 		idx = (uint32_t) uep->id;
1043b7fa78c7SJay Zhou 		desc_idx = idx;
1044b7fa78c7SJay Zhou 		while (vq->vq_ring.desc[desc_idx].flags
1045b7fa78c7SJay Zhou 				& VRING_DESC_F_NEXT) {
1046b7fa78c7SJay Zhou 			desc_idx = vq->vq_ring.desc[desc_idx].next;
1047b7fa78c7SJay Zhou 			vq->vq_free_cnt++;
1048b7fa78c7SJay Zhou 		}
1049b7fa78c7SJay Zhou 
1050b7fa78c7SJay Zhou 		vq->vq_ring.desc[desc_idx].next = vq->vq_desc_head_idx;
1051b7fa78c7SJay Zhou 		vq->vq_desc_head_idx = idx;
1052b7fa78c7SJay Zhou 		vq->vq_used_cons_idx++;
1053b7fa78c7SJay Zhou 		vq->vq_free_cnt++;
1054b7fa78c7SJay Zhou 	}
1055b7fa78c7SJay Zhou 
1056b7fa78c7SJay Zhou 	if (*status != VIRTIO_CRYPTO_OK) {
1057b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Close session failed "
1058b7fa78c7SJay Zhou 				"status=%"PRIu32", session_id=%"PRIu64"",
1059b7fa78c7SJay Zhou 				*status, session->session_id);
1060b7fa78c7SJay Zhou 		rte_free(malloc_virt_addr);
1061b7fa78c7SJay Zhou 		return;
1062b7fa78c7SJay Zhou 	}
1063b7fa78c7SJay Zhou 
1064b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_free_cnt=%d\n"
1065b7fa78c7SJay Zhou 			"vq->vq_desc_head_idx=%d",
1066b7fa78c7SJay Zhou 			vq->vq_free_cnt, vq->vq_desc_head_idx);
1067b7fa78c7SJay Zhou 
1068b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_SESSION_LOG_INFO("Close session %"PRIu64" successfully ",
1069b7fa78c7SJay Zhou 			session->session_id);
1070b7fa78c7SJay Zhou 
10714487cfa1SPablo de Lara 	memset(session, 0, sizeof(struct virtio_crypto_session));
10724487cfa1SPablo de Lara 	struct rte_mempool *sess_mp = rte_mempool_from_obj(session);
10734487cfa1SPablo de Lara 	set_sym_session_private_data(sess, cryptodev_virtio_driver_id, NULL);
10744487cfa1SPablo de Lara 	rte_mempool_put(sess_mp, session);
1075b7fa78c7SJay Zhou 	rte_free(malloc_virt_addr);
1076b7fa78c7SJay Zhou }
1077b7fa78c7SJay Zhou 
1078b7fa78c7SJay Zhou static struct rte_crypto_cipher_xform *
1079b7fa78c7SJay Zhou virtio_crypto_get_cipher_xform(struct rte_crypto_sym_xform *xform)
1080b7fa78c7SJay Zhou {
1081b7fa78c7SJay Zhou 	do {
1082b7fa78c7SJay Zhou 		if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
1083b7fa78c7SJay Zhou 			return &xform->cipher;
1084b7fa78c7SJay Zhou 
1085b7fa78c7SJay Zhou 		xform = xform->next;
1086b7fa78c7SJay Zhou 	} while (xform);
1087b7fa78c7SJay Zhou 
1088b7fa78c7SJay Zhou 	return NULL;
1089b7fa78c7SJay Zhou }
1090b7fa78c7SJay Zhou 
1091b7fa78c7SJay Zhou static struct rte_crypto_auth_xform *
1092b7fa78c7SJay Zhou virtio_crypto_get_auth_xform(struct rte_crypto_sym_xform *xform)
1093b7fa78c7SJay Zhou {
1094b7fa78c7SJay Zhou 	do {
1095b7fa78c7SJay Zhou 		if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
1096b7fa78c7SJay Zhou 			return &xform->auth;
1097b7fa78c7SJay Zhou 
1098b7fa78c7SJay Zhou 		xform = xform->next;
1099b7fa78c7SJay Zhou 	} while (xform);
1100b7fa78c7SJay Zhou 
1101b7fa78c7SJay Zhou 	return NULL;
1102b7fa78c7SJay Zhou }
1103b7fa78c7SJay Zhou 
1104b7fa78c7SJay Zhou /** Get xform chain order */
1105b7fa78c7SJay Zhou static int
1106b7fa78c7SJay Zhou virtio_crypto_get_chain_order(struct rte_crypto_sym_xform *xform)
1107b7fa78c7SJay Zhou {
1108b7fa78c7SJay Zhou 	if (xform == NULL)
1109b7fa78c7SJay Zhou 		return -1;
1110b7fa78c7SJay Zhou 
1111b7fa78c7SJay Zhou 	/* Cipher Only */
1112b7fa78c7SJay Zhou 	if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
1113b7fa78c7SJay Zhou 			xform->next == NULL)
1114b7fa78c7SJay Zhou 		return VIRTIO_CRYPTO_CMD_CIPHER;
1115b7fa78c7SJay Zhou 
1116b7fa78c7SJay Zhou 	/* Authentication Only */
1117b7fa78c7SJay Zhou 	if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
1118b7fa78c7SJay Zhou 			xform->next == NULL)
1119b7fa78c7SJay Zhou 		return VIRTIO_CRYPTO_CMD_AUTH;
1120b7fa78c7SJay Zhou 
1121b7fa78c7SJay Zhou 	/* Authenticate then Cipher */
1122b7fa78c7SJay Zhou 	if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
1123b7fa78c7SJay Zhou 			xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
1124b7fa78c7SJay Zhou 		return VIRTIO_CRYPTO_CMD_HASH_CIPHER;
1125b7fa78c7SJay Zhou 
1126b7fa78c7SJay Zhou 	/* Cipher then Authenticate */
1127b7fa78c7SJay Zhou 	if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
1128b7fa78c7SJay Zhou 			xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH)
1129b7fa78c7SJay Zhou 		return VIRTIO_CRYPTO_CMD_CIPHER_HASH;
1130b7fa78c7SJay Zhou 
1131b7fa78c7SJay Zhou 	return -1;
1132b7fa78c7SJay Zhou }
1133b7fa78c7SJay Zhou 
1134b7fa78c7SJay Zhou static int
1135b7fa78c7SJay Zhou virtio_crypto_sym_pad_cipher_param(
1136b7fa78c7SJay Zhou 		struct virtio_crypto_cipher_session_para *para,
1137b7fa78c7SJay Zhou 		struct rte_crypto_cipher_xform *cipher_xform)
1138b7fa78c7SJay Zhou {
1139b7fa78c7SJay Zhou 	switch (cipher_xform->algo) {
11405889e1ffSJay Zhou 	case RTE_CRYPTO_CIPHER_AES_CBC:
11415889e1ffSJay Zhou 		para->algo = VIRTIO_CRYPTO_CIPHER_AES_CBC;
11425889e1ffSJay Zhou 		break;
1143b7fa78c7SJay Zhou 	default:
1144b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Crypto: Unsupported "
1145b7fa78c7SJay Zhou 				"Cipher alg %u", cipher_xform->algo);
1146b7fa78c7SJay Zhou 		return -1;
1147b7fa78c7SJay Zhou 	}
1148b7fa78c7SJay Zhou 
1149b7fa78c7SJay Zhou 	para->keylen = cipher_xform->key.length;
1150b7fa78c7SJay Zhou 	switch (cipher_xform->op) {
1151b7fa78c7SJay Zhou 	case RTE_CRYPTO_CIPHER_OP_ENCRYPT:
1152b7fa78c7SJay Zhou 		para->op = VIRTIO_CRYPTO_OP_ENCRYPT;
1153b7fa78c7SJay Zhou 		break;
1154b7fa78c7SJay Zhou 	case RTE_CRYPTO_CIPHER_OP_DECRYPT:
1155b7fa78c7SJay Zhou 		para->op = VIRTIO_CRYPTO_OP_DECRYPT;
1156b7fa78c7SJay Zhou 		break;
1157b7fa78c7SJay Zhou 	default:
1158b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Unsupported cipher operation "
1159b7fa78c7SJay Zhou 					"parameter");
1160b7fa78c7SJay Zhou 		return -1;
1161b7fa78c7SJay Zhou 	}
1162b7fa78c7SJay Zhou 
1163b7fa78c7SJay Zhou 	return 0;
1164b7fa78c7SJay Zhou }
1165b7fa78c7SJay Zhou 
1166b7fa78c7SJay Zhou static int
1167b7fa78c7SJay Zhou virtio_crypto_sym_pad_auth_param(
1168b7fa78c7SJay Zhou 		struct virtio_crypto_op_ctrl_req *ctrl,
1169b7fa78c7SJay Zhou 		struct rte_crypto_auth_xform *auth_xform)
1170b7fa78c7SJay Zhou {
1171b7fa78c7SJay Zhou 	uint32_t *algo;
1172b7fa78c7SJay Zhou 	struct virtio_crypto_alg_chain_session_para *para =
1173b7fa78c7SJay Zhou 		&(ctrl->u.sym_create_session.u.chain.para);
1174b7fa78c7SJay Zhou 
1175b7fa78c7SJay Zhou 	switch (ctrl->u.sym_create_session.u.chain.para.hash_mode) {
1176b7fa78c7SJay Zhou 	case VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN:
1177b7fa78c7SJay Zhou 		algo = &(para->u.hash_param.algo);
1178b7fa78c7SJay Zhou 		break;
1179b7fa78c7SJay Zhou 	case VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH:
1180b7fa78c7SJay Zhou 		algo = &(para->u.mac_param.algo);
1181b7fa78c7SJay Zhou 		break;
1182b7fa78c7SJay Zhou 	default:
1183b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Unsupported hash mode %u "
1184b7fa78c7SJay Zhou 			"specified",
1185b7fa78c7SJay Zhou 			ctrl->u.sym_create_session.u.chain.para.hash_mode);
1186b7fa78c7SJay Zhou 		return -1;
1187b7fa78c7SJay Zhou 	}
1188b7fa78c7SJay Zhou 
1189b7fa78c7SJay Zhou 	switch (auth_xform->algo) {
11908144eadaSJay Zhou 	case RTE_CRYPTO_AUTH_SHA1_HMAC:
11918144eadaSJay Zhou 		*algo = VIRTIO_CRYPTO_MAC_HMAC_SHA1;
11928144eadaSJay Zhou 		break;
1193b7fa78c7SJay Zhou 	default:
1194b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
1195b7fa78c7SJay Zhou 			"Crypto: Undefined Hash algo %u specified",
1196b7fa78c7SJay Zhou 			auth_xform->algo);
1197b7fa78c7SJay Zhou 		return -1;
1198b7fa78c7SJay Zhou 	}
1199b7fa78c7SJay Zhou 
1200b7fa78c7SJay Zhou 	return 0;
1201b7fa78c7SJay Zhou }
1202b7fa78c7SJay Zhou 
1203b7fa78c7SJay Zhou static int
1204b7fa78c7SJay Zhou virtio_crypto_sym_pad_op_ctrl_req(
1205b7fa78c7SJay Zhou 		struct virtio_crypto_op_ctrl_req *ctrl,
1206b7fa78c7SJay Zhou 		struct rte_crypto_sym_xform *xform, bool is_chainned,
1207186b14d6SFan Zhang 		uint8_t *cipher_key_data, uint8_t *auth_key_data,
1208b7fa78c7SJay Zhou 		struct virtio_crypto_session *session)
1209b7fa78c7SJay Zhou {
1210b7fa78c7SJay Zhou 	int ret;
1211b7fa78c7SJay Zhou 	struct rte_crypto_auth_xform *auth_xform = NULL;
1212b7fa78c7SJay Zhou 	struct rte_crypto_cipher_xform *cipher_xform = NULL;
1213b7fa78c7SJay Zhou 
1214b7fa78c7SJay Zhou 	/* Get cipher xform from crypto xform chain */
1215b7fa78c7SJay Zhou 	cipher_xform = virtio_crypto_get_cipher_xform(xform);
1216b7fa78c7SJay Zhou 	if (cipher_xform) {
1217186b14d6SFan Zhang 		if (cipher_xform->key.length > VIRTIO_CRYPTO_MAX_KEY_SIZE) {
1218186b14d6SFan Zhang 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1219186b14d6SFan Zhang 				"cipher key size cannot be longer than %u",
1220186b14d6SFan Zhang 				VIRTIO_CRYPTO_MAX_KEY_SIZE);
1221186b14d6SFan Zhang 			return -1;
1222186b14d6SFan Zhang 		}
1223b063e843SFan Zhang 		if (cipher_xform->iv.length > VIRTIO_CRYPTO_MAX_IV_SIZE) {
1224b063e843SFan Zhang 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1225b063e843SFan Zhang 				"cipher IV size cannot be longer than %u",
1226b063e843SFan Zhang 				VIRTIO_CRYPTO_MAX_IV_SIZE);
1227b063e843SFan Zhang 			return -1;
1228b063e843SFan Zhang 		}
1229b7fa78c7SJay Zhou 		if (is_chainned)
1230b7fa78c7SJay Zhou 			ret = virtio_crypto_sym_pad_cipher_param(
1231b7fa78c7SJay Zhou 				&ctrl->u.sym_create_session.u.chain.para
1232b7fa78c7SJay Zhou 						.cipher_param, cipher_xform);
1233b7fa78c7SJay Zhou 		else
1234b7fa78c7SJay Zhou 			ret = virtio_crypto_sym_pad_cipher_param(
1235b7fa78c7SJay Zhou 				&ctrl->u.sym_create_session.u.cipher.para,
1236b7fa78c7SJay Zhou 				cipher_xform);
1237b7fa78c7SJay Zhou 
1238b7fa78c7SJay Zhou 		if (ret < 0) {
1239b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1240b7fa78c7SJay Zhou 				"pad cipher parameter failed");
1241b7fa78c7SJay Zhou 			return -1;
1242b7fa78c7SJay Zhou 		}
1243b7fa78c7SJay Zhou 
1244186b14d6SFan Zhang 		memcpy(cipher_key_data, cipher_xform->key.data,
1245186b14d6SFan Zhang 				cipher_xform->key.length);
1246b7fa78c7SJay Zhou 
1247b7fa78c7SJay Zhou 		session->iv.offset = cipher_xform->iv.offset;
1248b7fa78c7SJay Zhou 		session->iv.length = cipher_xform->iv.length;
1249b7fa78c7SJay Zhou 	}
1250b7fa78c7SJay Zhou 
1251b7fa78c7SJay Zhou 	/* Get auth xform from crypto xform chain */
1252b7fa78c7SJay Zhou 	auth_xform = virtio_crypto_get_auth_xform(xform);
1253b7fa78c7SJay Zhou 	if (auth_xform) {
1254b7fa78c7SJay Zhou 		/* FIXME: support VIRTIO_CRYPTO_SYM_HASH_MODE_NESTED */
1255b7fa78c7SJay Zhou 		struct virtio_crypto_alg_chain_session_para *para =
1256b7fa78c7SJay Zhou 			&(ctrl->u.sym_create_session.u.chain.para);
1257b7fa78c7SJay Zhou 		if (auth_xform->key.length) {
1258186b14d6SFan Zhang 			if (auth_xform->key.length >
1259186b14d6SFan Zhang 					VIRTIO_CRYPTO_MAX_KEY_SIZE) {
1260186b14d6SFan Zhang 				VIRTIO_CRYPTO_SESSION_LOG_ERR(
1261186b14d6SFan Zhang 				"auth key size cannot be longer than %u",
1262186b14d6SFan Zhang 					VIRTIO_CRYPTO_MAX_KEY_SIZE);
1263186b14d6SFan Zhang 				return -1;
1264186b14d6SFan Zhang 			}
1265b7fa78c7SJay Zhou 			para->hash_mode = VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH;
1266b7fa78c7SJay Zhou 			para->u.mac_param.auth_key_len =
1267b7fa78c7SJay Zhou 				(uint32_t)auth_xform->key.length;
1268b7fa78c7SJay Zhou 			para->u.mac_param.hash_result_len =
1269b7fa78c7SJay Zhou 				auth_xform->digest_length;
1270186b14d6SFan Zhang 			memcpy(auth_key_data, auth_xform->key.data,
1271186b14d6SFan Zhang 					auth_xform->key.length);
1272b7fa78c7SJay Zhou 		} else {
1273b7fa78c7SJay Zhou 			para->hash_mode	= VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN;
1274b7fa78c7SJay Zhou 			para->u.hash_param.hash_result_len =
1275b7fa78c7SJay Zhou 				auth_xform->digest_length;
1276b7fa78c7SJay Zhou 		}
1277b7fa78c7SJay Zhou 
1278b7fa78c7SJay Zhou 		ret = virtio_crypto_sym_pad_auth_param(ctrl, auth_xform);
1279b7fa78c7SJay Zhou 		if (ret < 0) {
1280b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR("pad auth parameter "
1281b7fa78c7SJay Zhou 						"failed");
1282b7fa78c7SJay Zhou 			return -1;
1283b7fa78c7SJay Zhou 		}
1284b7fa78c7SJay Zhou 	}
1285b7fa78c7SJay Zhou 
1286b7fa78c7SJay Zhou 	return 0;
1287b7fa78c7SJay Zhou }
1288b7fa78c7SJay Zhou 
1289b7fa78c7SJay Zhou static int
1290b7fa78c7SJay Zhou virtio_crypto_check_sym_configure_session_paras(
1291b7fa78c7SJay Zhou 		struct rte_cryptodev *dev,
1292b7fa78c7SJay Zhou 		struct rte_crypto_sym_xform *xform,
1293b7fa78c7SJay Zhou 		struct rte_cryptodev_sym_session *sym_sess,
1294b7fa78c7SJay Zhou 		struct rte_mempool *mempool)
1295b7fa78c7SJay Zhou {
1296b7fa78c7SJay Zhou 	if (unlikely(xform == NULL) || unlikely(sym_sess == NULL) ||
1297b7fa78c7SJay Zhou 		unlikely(mempool == NULL)) {
1298b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("NULL pointer");
1299b7fa78c7SJay Zhou 		return -1;
1300b7fa78c7SJay Zhou 	}
1301b7fa78c7SJay Zhou 
1302b7fa78c7SJay Zhou 	if (virtio_crypto_check_sym_session_paras(dev) < 0)
1303b7fa78c7SJay Zhou 		return -1;
1304b7fa78c7SJay Zhou 
1305b7fa78c7SJay Zhou 	return 0;
1306b7fa78c7SJay Zhou }
1307b7fa78c7SJay Zhou 
1308b7fa78c7SJay Zhou static int
1309b7fa78c7SJay Zhou virtio_crypto_sym_configure_session(
1310b7fa78c7SJay Zhou 		struct rte_cryptodev *dev,
1311b7fa78c7SJay Zhou 		struct rte_crypto_sym_xform *xform,
1312b7fa78c7SJay Zhou 		struct rte_cryptodev_sym_session *sess,
1313b7fa78c7SJay Zhou 		struct rte_mempool *mempool)
1314b7fa78c7SJay Zhou {
1315b7fa78c7SJay Zhou 	int ret;
1316b7fa78c7SJay Zhou 	struct virtio_crypto_session crypto_sess;
1317b7fa78c7SJay Zhou 	void *session_private = &crypto_sess;
1318b7fa78c7SJay Zhou 	struct virtio_crypto_session *session;
1319b7fa78c7SJay Zhou 	struct virtio_crypto_op_ctrl_req *ctrl_req;
1320b7fa78c7SJay Zhou 	enum virtio_crypto_cmd_id cmd_id;
1321186b14d6SFan Zhang 	uint8_t cipher_key_data[VIRTIO_CRYPTO_MAX_KEY_SIZE] = {0};
1322186b14d6SFan Zhang 	uint8_t auth_key_data[VIRTIO_CRYPTO_MAX_KEY_SIZE] = {0};
1323b7fa78c7SJay Zhou 	struct virtio_crypto_hw *hw;
1324b7fa78c7SJay Zhou 	struct virtqueue *control_vq;
1325b7fa78c7SJay Zhou 
1326b7fa78c7SJay Zhou 	PMD_INIT_FUNC_TRACE();
1327b7fa78c7SJay Zhou 
1328b7fa78c7SJay Zhou 	ret = virtio_crypto_check_sym_configure_session_paras(dev, xform,
1329b7fa78c7SJay Zhou 			sess, mempool);
1330b7fa78c7SJay Zhou 	if (ret < 0) {
1331b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Invalid parameters");
1332b7fa78c7SJay Zhou 		return ret;
1333b7fa78c7SJay Zhou 	}
1334b7fa78c7SJay Zhou 
1335b7fa78c7SJay Zhou 	if (rte_mempool_get(mempool, &session_private)) {
1336b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
1337b7fa78c7SJay Zhou 			"Couldn't get object from session mempool");
1338b7fa78c7SJay Zhou 		return -ENOMEM;
1339b7fa78c7SJay Zhou 	}
1340b7fa78c7SJay Zhou 
1341b7fa78c7SJay Zhou 	session = (struct virtio_crypto_session *)session_private;
1342b7fa78c7SJay Zhou 	memset(session, 0, sizeof(struct virtio_crypto_session));
1343b7fa78c7SJay Zhou 	ctrl_req = &session->ctrl;
1344b7fa78c7SJay Zhou 	ctrl_req->header.opcode = VIRTIO_CRYPTO_CIPHER_CREATE_SESSION;
1345b7fa78c7SJay Zhou 	/* FIXME: support multiqueue */
1346b7fa78c7SJay Zhou 	ctrl_req->header.queue_id = 0;
1347b7fa78c7SJay Zhou 
1348b7fa78c7SJay Zhou 	hw = dev->data->dev_private;
1349b7fa78c7SJay Zhou 	control_vq = hw->cvq;
1350b7fa78c7SJay Zhou 
1351b7fa78c7SJay Zhou 	cmd_id = virtio_crypto_get_chain_order(xform);
1352b7fa78c7SJay Zhou 	if (cmd_id == VIRTIO_CRYPTO_CMD_CIPHER_HASH)
1353b7fa78c7SJay Zhou 		ctrl_req->u.sym_create_session.u.chain.para.alg_chain_order
1354b7fa78c7SJay Zhou 			= VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH;
1355b7fa78c7SJay Zhou 	if (cmd_id == VIRTIO_CRYPTO_CMD_HASH_CIPHER)
1356b7fa78c7SJay Zhou 		ctrl_req->u.sym_create_session.u.chain.para.alg_chain_order
1357b7fa78c7SJay Zhou 			= VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER;
1358b7fa78c7SJay Zhou 
1359b7fa78c7SJay Zhou 	switch (cmd_id) {
1360b7fa78c7SJay Zhou 	case VIRTIO_CRYPTO_CMD_CIPHER_HASH:
1361b7fa78c7SJay Zhou 	case VIRTIO_CRYPTO_CMD_HASH_CIPHER:
1362b7fa78c7SJay Zhou 		ctrl_req->u.sym_create_session.op_type
1363b7fa78c7SJay Zhou 			= VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING;
1364b7fa78c7SJay Zhou 
1365b7fa78c7SJay Zhou 		ret = virtio_crypto_sym_pad_op_ctrl_req(ctrl_req,
1366186b14d6SFan Zhang 			xform, true, cipher_key_data, auth_key_data, session);
1367b7fa78c7SJay Zhou 		if (ret < 0) {
1368b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1369b7fa78c7SJay Zhou 				"padding sym op ctrl req failed");
1370b7fa78c7SJay Zhou 			goto error_out;
1371b7fa78c7SJay Zhou 		}
1372b7fa78c7SJay Zhou 		ret = virtio_crypto_send_command(control_vq, ctrl_req,
1373b7fa78c7SJay Zhou 			cipher_key_data, auth_key_data, session);
1374b7fa78c7SJay Zhou 		if (ret < 0) {
1375b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1376b7fa78c7SJay Zhou 				"create session failed: %d", ret);
1377b7fa78c7SJay Zhou 			goto error_out;
1378b7fa78c7SJay Zhou 		}
1379b7fa78c7SJay Zhou 		break;
1380b7fa78c7SJay Zhou 	case VIRTIO_CRYPTO_CMD_CIPHER:
1381b7fa78c7SJay Zhou 		ctrl_req->u.sym_create_session.op_type
1382b7fa78c7SJay Zhou 			= VIRTIO_CRYPTO_SYM_OP_CIPHER;
1383b7fa78c7SJay Zhou 		ret = virtio_crypto_sym_pad_op_ctrl_req(ctrl_req, xform,
1384186b14d6SFan Zhang 			false, cipher_key_data, auth_key_data, session);
1385b7fa78c7SJay Zhou 		if (ret < 0) {
1386b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1387b7fa78c7SJay Zhou 				"padding sym op ctrl req failed");
1388b7fa78c7SJay Zhou 			goto error_out;
1389b7fa78c7SJay Zhou 		}
1390b7fa78c7SJay Zhou 		ret = virtio_crypto_send_command(control_vq, ctrl_req,
1391b7fa78c7SJay Zhou 			cipher_key_data, NULL, session);
1392b7fa78c7SJay Zhou 		if (ret < 0) {
1393b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1394b7fa78c7SJay Zhou 				"create session failed: %d", ret);
1395b7fa78c7SJay Zhou 			goto error_out;
1396b7fa78c7SJay Zhou 		}
1397b7fa78c7SJay Zhou 		break;
1398b7fa78c7SJay Zhou 	default:
1399b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
1400b7fa78c7SJay Zhou 			"Unsupported operation chain order parameter");
1401b7fa78c7SJay Zhou 		goto error_out;
1402b7fa78c7SJay Zhou 	}
1403b7fa78c7SJay Zhou 
1404012c5076SPablo de Lara 	set_sym_session_private_data(sess, dev->driver_id,
1405b7fa78c7SJay Zhou 		session_private);
1406b7fa78c7SJay Zhou 
1407b7fa78c7SJay Zhou 	return 0;
1408b7fa78c7SJay Zhou 
1409b7fa78c7SJay Zhou error_out:
1410b7fa78c7SJay Zhou 	return -1;
1411b7fa78c7SJay Zhou }
1412b7fa78c7SJay Zhou 
14136f0175ffSJay Zhou static void
14146f0175ffSJay Zhou virtio_crypto_dev_info_get(struct rte_cryptodev *dev,
14156f0175ffSJay Zhou 		struct rte_cryptodev_info *info)
14166f0175ffSJay Zhou {
14176f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
14186f0175ffSJay Zhou 
14196f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
14206f0175ffSJay Zhou 
14216f0175ffSJay Zhou 	if (info != NULL) {
14226f0175ffSJay Zhou 		info->driver_id = cryptodev_virtio_driver_id;
14236f0175ffSJay Zhou 		info->feature_flags = dev->feature_flags;
14246f0175ffSJay Zhou 		info->max_nb_queue_pairs = hw->max_dataqueues;
1425e1fc5b76SPablo de Lara 		/* No limit of number of sessions */
1426e1fc5b76SPablo de Lara 		info->sym.max_nb_sessions = 0;
14275889e1ffSJay Zhou 		info->capabilities = hw->virtio_dev_capabilities;
14286f0175ffSJay Zhou 	}
14296f0175ffSJay Zhou }
14306f0175ffSJay Zhou 
14316f0175ffSJay Zhou static int
14328769079aSJay Zhou crypto_virtio_pci_probe(
14338769079aSJay Zhou 	struct rte_pci_driver *pci_drv __rte_unused,
143425500d4bSJay Zhou 	struct rte_pci_device *pci_dev)
14358769079aSJay Zhou {
143625500d4bSJay Zhou 	struct rte_cryptodev_pmd_init_params init_params = {
143725500d4bSJay Zhou 		.name = "",
1438933f42eaSXiao Wang 		.socket_id = pci_dev->device.numa_node,
1439e1fc5b76SPablo de Lara 		.private_data_size = sizeof(struct virtio_crypto_hw)
144025500d4bSJay Zhou 	};
144125500d4bSJay Zhou 	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
144225500d4bSJay Zhou 
144325500d4bSJay Zhou 	VIRTIO_CRYPTO_DRV_LOG_DBG("Found Crypto device at %02x:%02x.%x",
144425500d4bSJay Zhou 			pci_dev->addr.bus,
144525500d4bSJay Zhou 			pci_dev->addr.devid,
144625500d4bSJay Zhou 			pci_dev->addr.function);
144725500d4bSJay Zhou 
144825500d4bSJay Zhou 	rte_pci_device_name(&pci_dev->addr, name, sizeof(name));
144925500d4bSJay Zhou 
145025500d4bSJay Zhou 	return crypto_virtio_create(name, pci_dev, &init_params);
14518769079aSJay Zhou }
14528769079aSJay Zhou 
14538769079aSJay Zhou static int
14548769079aSJay Zhou crypto_virtio_pci_remove(
14558769079aSJay Zhou 	struct rte_pci_device *pci_dev __rte_unused)
14568769079aSJay Zhou {
145725500d4bSJay Zhou 	struct rte_cryptodev *cryptodev;
145825500d4bSJay Zhou 	char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
145925500d4bSJay Zhou 
146025500d4bSJay Zhou 	if (pci_dev == NULL)
146125500d4bSJay Zhou 		return -EINVAL;
146225500d4bSJay Zhou 
146325500d4bSJay Zhou 	rte_pci_device_name(&pci_dev->addr, cryptodev_name,
146425500d4bSJay Zhou 			sizeof(cryptodev_name));
146525500d4bSJay Zhou 
146625500d4bSJay Zhou 	cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
146725500d4bSJay Zhou 	if (cryptodev == NULL)
146825500d4bSJay Zhou 		return -ENODEV;
146925500d4bSJay Zhou 
14706f0175ffSJay Zhou 	return virtio_crypto_dev_uninit(cryptodev);
14718769079aSJay Zhou }
14728769079aSJay Zhou 
14738769079aSJay Zhou static struct rte_pci_driver rte_virtio_crypto_driver = {
147425500d4bSJay Zhou 	.id_table = pci_id_virtio_crypto_map,
147525500d4bSJay Zhou 	.drv_flags = 0,
14768769079aSJay Zhou 	.probe = crypto_virtio_pci_probe,
14778769079aSJay Zhou 	.remove = crypto_virtio_pci_remove
14788769079aSJay Zhou };
14798769079aSJay Zhou 
14808769079aSJay Zhou static struct cryptodev_driver virtio_crypto_drv;
14818769079aSJay Zhou 
14828769079aSJay Zhou RTE_PMD_REGISTER_PCI(CRYPTODEV_NAME_VIRTIO_PMD, rte_virtio_crypto_driver);
14838769079aSJay Zhou RTE_PMD_REGISTER_CRYPTO_DRIVER(virtio_crypto_drv,
14848769079aSJay Zhou 	rte_virtio_crypto_driver.driver,
14858769079aSJay Zhou 	cryptodev_virtio_driver_id);
14869c99878aSJerin Jacob RTE_LOG_REGISTER(virtio_crypto_logtype_init, pmd.crypto.virtio.init, NOTICE);
14879c99878aSJerin Jacob RTE_LOG_REGISTER(virtio_crypto_logtype_session, pmd.crypto.virtio.session,
14889c99878aSJerin Jacob 		 NOTICE);
14899c99878aSJerin Jacob RTE_LOG_REGISTER(virtio_crypto_logtype_rx, pmd.crypto.virtio.rx, NOTICE);
14909c99878aSJerin Jacob RTE_LOG_REGISTER(virtio_crypto_logtype_tx, pmd.crypto.virtio.tx, NOTICE);
14919c99878aSJerin Jacob RTE_LOG_REGISTER(virtio_crypto_logtype_driver, pmd.crypto.virtio.driver,
14929c99878aSJerin Jacob 		 NOTICE);
1493