xref: /dpdk/drivers/crypto/virtio/virtio_cryptodev.c (revision 1af8b0b2747fe6c6267fa7bedb602e569742362e)
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>
101f37cb2bSDavid Marchand #include <bus_pci_driver.h>
1125500d4bSJay Zhou #include <rte_cryptodev.h>
12af668035SAkhil Goyal #include <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,
43bdce2564SAkhil Goyal 		struct rte_cryptodev_sym_session *session);
446f0175ffSJay Zhou 
4525500d4bSJay Zhou /*
4625500d4bSJay Zhou  * The set of PCI devices this driver supports
4725500d4bSJay Zhou  */
4825500d4bSJay Zhou static const struct rte_pci_id pci_id_virtio_crypto_map[] = {
4925500d4bSJay Zhou 	{ RTE_PCI_DEVICE(VIRTIO_CRYPTO_PCI_VENDORID,
5025500d4bSJay Zhou 				VIRTIO_CRYPTO_PCI_DEVICEID) },
5125500d4bSJay Zhou 	{ .vendor_id = 0, /* sentinel */ },
5225500d4bSJay Zhou };
538769079aSJay Zhou 
545889e1ffSJay Zhou static const struct rte_cryptodev_capabilities virtio_capabilities[] = {
555889e1ffSJay Zhou 	VIRTIO_SYM_CAPABILITIES,
565889e1ffSJay Zhou 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
575889e1ffSJay Zhou };
585889e1ffSJay Zhou 
598769079aSJay Zhou uint8_t cryptodev_virtio_driver_id;
608769079aSJay Zhou 
61b7fa78c7SJay Zhou #define NUM_ENTRY_SYM_CREATE_SESSION 4
62b7fa78c7SJay Zhou 
63b7fa78c7SJay Zhou static int
64b7fa78c7SJay Zhou virtio_crypto_send_command(struct virtqueue *vq,
65b7fa78c7SJay Zhou 		struct virtio_crypto_op_ctrl_req *ctrl, uint8_t *cipher_key,
66b7fa78c7SJay Zhou 		uint8_t *auth_key, struct virtio_crypto_session *session)
67b7fa78c7SJay Zhou {
68b7fa78c7SJay Zhou 	uint8_t idx = 0;
69b7fa78c7SJay Zhou 	uint8_t needed = 1;
70b7fa78c7SJay Zhou 	uint32_t head = 0;
71b7fa78c7SJay Zhou 	uint32_t len_cipher_key = 0;
72b7fa78c7SJay Zhou 	uint32_t len_auth_key = 0;
73b7fa78c7SJay Zhou 	uint32_t len_ctrl_req = sizeof(struct virtio_crypto_op_ctrl_req);
74b7fa78c7SJay Zhou 	uint32_t len_session_input = sizeof(struct virtio_crypto_session_input);
75b7fa78c7SJay Zhou 	uint32_t len_total = 0;
76b7fa78c7SJay Zhou 	uint32_t input_offset = 0;
77b7fa78c7SJay Zhou 	void *virt_addr_started = NULL;
78b7fa78c7SJay Zhou 	phys_addr_t phys_addr_started;
79b7fa78c7SJay Zhou 	struct vring_desc *desc;
80b7fa78c7SJay Zhou 	uint32_t desc_offset;
81b7fa78c7SJay Zhou 	struct virtio_crypto_session_input *input;
82b7fa78c7SJay Zhou 	int ret;
83b7fa78c7SJay Zhou 
84b7fa78c7SJay Zhou 	PMD_INIT_FUNC_TRACE();
85b7fa78c7SJay Zhou 
86b7fa78c7SJay Zhou 	if (session == NULL) {
87b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("session is NULL.");
88b7fa78c7SJay Zhou 		return -EINVAL;
89b7fa78c7SJay Zhou 	}
90b7fa78c7SJay Zhou 	/* cipher only is supported, it is available if auth_key is NULL */
91b7fa78c7SJay Zhou 	if (!cipher_key) {
92b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("cipher key is NULL.");
93b7fa78c7SJay Zhou 		return -EINVAL;
94b7fa78c7SJay Zhou 	}
95b7fa78c7SJay Zhou 
96b7fa78c7SJay Zhou 	head = vq->vq_desc_head_idx;
97b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_desc_head_idx = %d, vq = %p",
98b7fa78c7SJay Zhou 					head, vq);
99b7fa78c7SJay Zhou 
100b7fa78c7SJay Zhou 	if (vq->vq_free_cnt < needed) {
101b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Not enough entry");
102b7fa78c7SJay Zhou 		return -ENOSPC;
103b7fa78c7SJay Zhou 	}
104b7fa78c7SJay Zhou 
105b7fa78c7SJay Zhou 	/* calculate the length of cipher key */
106b7fa78c7SJay Zhou 	if (cipher_key) {
107b7fa78c7SJay Zhou 		switch (ctrl->u.sym_create_session.op_type) {
108b7fa78c7SJay Zhou 		case VIRTIO_CRYPTO_SYM_OP_CIPHER:
109b7fa78c7SJay Zhou 			len_cipher_key
110b7fa78c7SJay Zhou 				= ctrl->u.sym_create_session.u.cipher
111b7fa78c7SJay Zhou 							.para.keylen;
112b7fa78c7SJay Zhou 			break;
113b7fa78c7SJay Zhou 		case VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING:
114b7fa78c7SJay Zhou 			len_cipher_key
115b7fa78c7SJay Zhou 				= ctrl->u.sym_create_session.u.chain
116b7fa78c7SJay Zhou 					.para.cipher_param.keylen;
117b7fa78c7SJay Zhou 			break;
118b7fa78c7SJay Zhou 		default:
119b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR("invalid op type");
120b7fa78c7SJay Zhou 			return -EINVAL;
121b7fa78c7SJay Zhou 		}
122b7fa78c7SJay Zhou 	}
123b7fa78c7SJay Zhou 
124b7fa78c7SJay Zhou 	/* calculate the length of auth key */
125b7fa78c7SJay Zhou 	if (auth_key) {
126b7fa78c7SJay Zhou 		len_auth_key =
127b7fa78c7SJay Zhou 			ctrl->u.sym_create_session.u.chain.para.u.mac_param
128b7fa78c7SJay Zhou 				.auth_key_len;
129b7fa78c7SJay Zhou 	}
130b7fa78c7SJay Zhou 
131b7fa78c7SJay Zhou 	/*
132b7fa78c7SJay Zhou 	 * malloc memory to store indirect vring_desc entries, including
133b7fa78c7SJay Zhou 	 * ctrl request, cipher key, auth key, session input and desc vring
134b7fa78c7SJay Zhou 	 */
135b7fa78c7SJay Zhou 	desc_offset = len_ctrl_req + len_cipher_key + len_auth_key
136b7fa78c7SJay Zhou 		+ len_session_input;
137b7fa78c7SJay Zhou 	virt_addr_started = rte_malloc(NULL,
138b7fa78c7SJay Zhou 		desc_offset + NUM_ENTRY_SYM_CREATE_SESSION
139b7fa78c7SJay Zhou 			* sizeof(struct vring_desc), RTE_CACHE_LINE_SIZE);
140b7fa78c7SJay Zhou 	if (virt_addr_started == NULL) {
141b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("not enough heap memory");
142b7fa78c7SJay Zhou 		return -ENOSPC;
143b7fa78c7SJay Zhou 	}
144b7fa78c7SJay Zhou 	phys_addr_started = rte_malloc_virt2iova(virt_addr_started);
145b7fa78c7SJay Zhou 
146b7fa78c7SJay Zhou 	/* address to store indirect vring desc entries */
147b7fa78c7SJay Zhou 	desc = (struct vring_desc *)
148b7fa78c7SJay Zhou 		((uint8_t *)virt_addr_started + desc_offset);
149b7fa78c7SJay Zhou 
150b7fa78c7SJay Zhou 	/*  ctrl req part */
151b7fa78c7SJay Zhou 	memcpy(virt_addr_started, ctrl, len_ctrl_req);
152b7fa78c7SJay Zhou 	desc[idx].addr = phys_addr_started;
153b7fa78c7SJay Zhou 	desc[idx].len = len_ctrl_req;
154b7fa78c7SJay Zhou 	desc[idx].flags = VRING_DESC_F_NEXT;
155b7fa78c7SJay Zhou 	desc[idx].next = idx + 1;
156b7fa78c7SJay Zhou 	idx++;
157b7fa78c7SJay Zhou 	len_total += len_ctrl_req;
158b7fa78c7SJay Zhou 	input_offset += len_ctrl_req;
159b7fa78c7SJay Zhou 
160b7fa78c7SJay Zhou 	/* cipher key part */
161b7fa78c7SJay Zhou 	if (len_cipher_key > 0) {
162b7fa78c7SJay Zhou 		memcpy((uint8_t *)virt_addr_started + len_total,
163b7fa78c7SJay Zhou 			cipher_key, len_cipher_key);
164b7fa78c7SJay Zhou 
165b7fa78c7SJay Zhou 		desc[idx].addr = phys_addr_started + len_total;
166b7fa78c7SJay Zhou 		desc[idx].len = len_cipher_key;
167b7fa78c7SJay Zhou 		desc[idx].flags = VRING_DESC_F_NEXT;
168b7fa78c7SJay Zhou 		desc[idx].next = idx + 1;
169b7fa78c7SJay Zhou 		idx++;
170b7fa78c7SJay Zhou 		len_total += len_cipher_key;
171b7fa78c7SJay Zhou 		input_offset += len_cipher_key;
172b7fa78c7SJay Zhou 	}
173b7fa78c7SJay Zhou 
174b7fa78c7SJay Zhou 	/* auth key part */
175b7fa78c7SJay Zhou 	if (len_auth_key > 0) {
176b7fa78c7SJay Zhou 		memcpy((uint8_t *)virt_addr_started + len_total,
177b7fa78c7SJay Zhou 			auth_key, len_auth_key);
178b7fa78c7SJay Zhou 
179b7fa78c7SJay Zhou 		desc[idx].addr = phys_addr_started + len_total;
180b7fa78c7SJay Zhou 		desc[idx].len = len_auth_key;
181b7fa78c7SJay Zhou 		desc[idx].flags = VRING_DESC_F_NEXT;
182b7fa78c7SJay Zhou 		desc[idx].next = idx + 1;
183b7fa78c7SJay Zhou 		idx++;
184b7fa78c7SJay Zhou 		len_total += len_auth_key;
185b7fa78c7SJay Zhou 		input_offset += len_auth_key;
186b7fa78c7SJay Zhou 	}
187b7fa78c7SJay Zhou 
188b7fa78c7SJay Zhou 	/* input part */
189b7fa78c7SJay Zhou 	input = (struct virtio_crypto_session_input *)
190b7fa78c7SJay Zhou 		((uint8_t *)virt_addr_started + input_offset);
191b7fa78c7SJay Zhou 	input->status = VIRTIO_CRYPTO_ERR;
192b7fa78c7SJay Zhou 	input->session_id = ~0ULL;
193b7fa78c7SJay Zhou 	desc[idx].addr = phys_addr_started + len_total;
194b7fa78c7SJay Zhou 	desc[idx].len = len_session_input;
195b7fa78c7SJay Zhou 	desc[idx].flags = VRING_DESC_F_WRITE;
196b7fa78c7SJay Zhou 	idx++;
197b7fa78c7SJay Zhou 
198b7fa78c7SJay Zhou 	/* use a single desc entry */
199b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].addr = phys_addr_started + desc_offset;
200b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].len = idx * sizeof(struct vring_desc);
201b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].flags = VRING_DESC_F_INDIRECT;
202b7fa78c7SJay Zhou 	vq->vq_free_cnt--;
203b7fa78c7SJay Zhou 
204b7fa78c7SJay Zhou 	vq->vq_desc_head_idx = vq->vq_ring.desc[head].next;
205b7fa78c7SJay Zhou 
206b7fa78c7SJay Zhou 	vq_update_avail_ring(vq, head);
207b7fa78c7SJay Zhou 	vq_update_avail_idx(vq);
208b7fa78c7SJay Zhou 
209b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_queue_index = %d",
210b7fa78c7SJay Zhou 					vq->vq_queue_index);
211b7fa78c7SJay Zhou 
212b7fa78c7SJay Zhou 	virtqueue_notify(vq);
213b7fa78c7SJay Zhou 
214b7fa78c7SJay Zhou 	rte_rmb();
215b7fa78c7SJay Zhou 	while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) {
216b7fa78c7SJay Zhou 		rte_rmb();
217b7fa78c7SJay Zhou 		usleep(100);
218b7fa78c7SJay Zhou 	}
219b7fa78c7SJay Zhou 
220b7fa78c7SJay Zhou 	while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) {
221b7fa78c7SJay Zhou 		uint32_t idx, desc_idx, used_idx;
222b7fa78c7SJay Zhou 		struct vring_used_elem *uep;
223b7fa78c7SJay Zhou 
224b7fa78c7SJay Zhou 		used_idx = (uint32_t)(vq->vq_used_cons_idx
225b7fa78c7SJay Zhou 				& (vq->vq_nentries - 1));
226b7fa78c7SJay Zhou 		uep = &vq->vq_ring.used->ring[used_idx];
227b7fa78c7SJay Zhou 		idx = (uint32_t) uep->id;
228b7fa78c7SJay Zhou 		desc_idx = idx;
229b7fa78c7SJay Zhou 
230b7fa78c7SJay Zhou 		while (vq->vq_ring.desc[desc_idx].flags & VRING_DESC_F_NEXT) {
231b7fa78c7SJay Zhou 			desc_idx = vq->vq_ring.desc[desc_idx].next;
232b7fa78c7SJay Zhou 			vq->vq_free_cnt++;
233b7fa78c7SJay Zhou 		}
234b7fa78c7SJay Zhou 
235b7fa78c7SJay Zhou 		vq->vq_ring.desc[desc_idx].next = vq->vq_desc_head_idx;
236b7fa78c7SJay Zhou 		vq->vq_desc_head_idx = idx;
237b7fa78c7SJay Zhou 
238b7fa78c7SJay Zhou 		vq->vq_used_cons_idx++;
239b7fa78c7SJay Zhou 		vq->vq_free_cnt++;
240b7fa78c7SJay Zhou 	}
241b7fa78c7SJay Zhou 
242*1af8b0b2SDavid Marchand 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_free_cnt=%d", vq->vq_free_cnt);
243*1af8b0b2SDavid Marchand 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_desc_head_idx=%d", vq->vq_desc_head_idx);
244b7fa78c7SJay Zhou 
245b7fa78c7SJay Zhou 	/* get the result */
246b7fa78c7SJay Zhou 	if (input->status != VIRTIO_CRYPTO_OK) {
247b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Something wrong on backend! "
248b7fa78c7SJay Zhou 				"status=%u, session_id=%" PRIu64 "",
249b7fa78c7SJay Zhou 				input->status, input->session_id);
250b7fa78c7SJay Zhou 		rte_free(virt_addr_started);
251b7fa78c7SJay Zhou 		ret = -1;
252b7fa78c7SJay Zhou 	} else {
253b7fa78c7SJay Zhou 		session->session_id = input->session_id;
254b7fa78c7SJay Zhou 
255b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_INFO("Create session successfully, "
256b7fa78c7SJay Zhou 				"session_id=%" PRIu64 "", input->session_id);
257b7fa78c7SJay Zhou 		rte_free(virt_addr_started);
258b7fa78c7SJay Zhou 		ret = 0;
259b7fa78c7SJay Zhou 	}
260b7fa78c7SJay Zhou 
261b7fa78c7SJay Zhou 	return ret;
262b7fa78c7SJay Zhou }
263b7fa78c7SJay Zhou 
2646f0175ffSJay Zhou void
2656f0175ffSJay Zhou virtio_crypto_queue_release(struct virtqueue *vq)
2666f0175ffSJay Zhou {
2676f0175ffSJay Zhou 	struct virtio_crypto_hw *hw;
2686f0175ffSJay Zhou 
2696f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
2706f0175ffSJay Zhou 
2716f0175ffSJay Zhou 	if (vq) {
2726f0175ffSJay Zhou 		hw = vq->hw;
2736f0175ffSJay Zhou 		/* Select and deactivate the queue */
2746f0175ffSJay Zhou 		VTPCI_OPS(hw)->del_queue(hw, vq);
2756f0175ffSJay Zhou 
2766f0175ffSJay Zhou 		rte_memzone_free(vq->mz);
2776f0175ffSJay Zhou 		rte_mempool_free(vq->mpool);
2786f0175ffSJay Zhou 		rte_free(vq);
2796f0175ffSJay Zhou 	}
2806f0175ffSJay Zhou }
2816f0175ffSJay Zhou 
2826f0175ffSJay Zhou #define MPOOL_MAX_NAME_SZ 32
2836f0175ffSJay Zhou 
2846f0175ffSJay Zhou int
2856f0175ffSJay Zhou virtio_crypto_queue_setup(struct rte_cryptodev *dev,
2866f0175ffSJay Zhou 		int queue_type,
2876f0175ffSJay Zhou 		uint16_t vtpci_queue_idx,
2886f0175ffSJay Zhou 		uint16_t nb_desc,
2896f0175ffSJay Zhou 		int socket_id,
2906f0175ffSJay Zhou 		struct virtqueue **pvq)
2916f0175ffSJay Zhou {
2926f0175ffSJay Zhou 	char vq_name[VIRTQUEUE_MAX_NAME_SZ];
2936f0175ffSJay Zhou 	char mpool_name[MPOOL_MAX_NAME_SZ];
2946f0175ffSJay Zhou 	const struct rte_memzone *mz;
2956f0175ffSJay Zhou 	unsigned int vq_size, size;
2966f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
2976f0175ffSJay Zhou 	struct virtqueue *vq = NULL;
2986f0175ffSJay Zhou 	uint32_t i = 0;
2996f0175ffSJay Zhou 	uint32_t j;
3006f0175ffSJay Zhou 
3016f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
3026f0175ffSJay Zhou 
3036f0175ffSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("setting up queue: %u", vtpci_queue_idx);
3046f0175ffSJay Zhou 
3056f0175ffSJay Zhou 	/*
3066f0175ffSJay Zhou 	 * Read the virtqueue size from the Queue Size field
3076f0175ffSJay Zhou 	 * Always power of 2 and if 0 virtqueue does not exist
3086f0175ffSJay Zhou 	 */
3096f0175ffSJay Zhou 	vq_size = VTPCI_OPS(hw)->get_queue_num(hw, vtpci_queue_idx);
3106f0175ffSJay Zhou 	if (vq_size == 0) {
3116f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue does not exist");
3126f0175ffSJay Zhou 		return -EINVAL;
3136f0175ffSJay Zhou 	}
3146f0175ffSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq_size: %u", vq_size);
3156f0175ffSJay Zhou 
3166f0175ffSJay Zhou 	if (!rte_is_power_of_2(vq_size)) {
3176f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue size is not powerof 2");
3186f0175ffSJay Zhou 		return -EINVAL;
3196f0175ffSJay Zhou 	}
3206f0175ffSJay Zhou 
3216f0175ffSJay Zhou 	if (queue_type == VTCRYPTO_DATAQ) {
3226f0175ffSJay Zhou 		snprintf(vq_name, sizeof(vq_name), "dev%d_dataqueue%d",
3236f0175ffSJay Zhou 				dev->data->dev_id, vtpci_queue_idx);
3246f0175ffSJay Zhou 		snprintf(mpool_name, sizeof(mpool_name),
3256f0175ffSJay Zhou 				"dev%d_dataqueue%d_mpool",
3266f0175ffSJay Zhou 				dev->data->dev_id, vtpci_queue_idx);
3276f0175ffSJay Zhou 	} else if (queue_type == VTCRYPTO_CTRLQ) {
3286f0175ffSJay Zhou 		snprintf(vq_name, sizeof(vq_name), "dev%d_controlqueue",
3296f0175ffSJay Zhou 				dev->data->dev_id);
3306f0175ffSJay Zhou 		snprintf(mpool_name, sizeof(mpool_name),
3316f0175ffSJay Zhou 				"dev%d_controlqueue_mpool",
3326f0175ffSJay Zhou 				dev->data->dev_id);
3336f0175ffSJay Zhou 	}
3346f0175ffSJay Zhou 	size = RTE_ALIGN_CEIL(sizeof(*vq) +
3356f0175ffSJay Zhou 				vq_size * sizeof(struct vq_desc_extra),
3366f0175ffSJay Zhou 				RTE_CACHE_LINE_SIZE);
3376f0175ffSJay Zhou 	vq = rte_zmalloc_socket(vq_name, size, RTE_CACHE_LINE_SIZE,
3386f0175ffSJay Zhou 				socket_id);
3396f0175ffSJay Zhou 	if (vq == NULL) {
3406f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("Can not allocate virtqueue");
3416f0175ffSJay Zhou 		return -ENOMEM;
3426f0175ffSJay Zhou 	}
3436f0175ffSJay Zhou 
3446f0175ffSJay Zhou 	if (queue_type == VTCRYPTO_DATAQ) {
3456f0175ffSJay Zhou 		/* pre-allocate a mempool and use it in the data plane to
3466f0175ffSJay Zhou 		 * improve performance
3476f0175ffSJay Zhou 		 */
3486f0175ffSJay Zhou 		vq->mpool = rte_mempool_lookup(mpool_name);
3496f0175ffSJay Zhou 		if (vq->mpool == NULL)
3506f0175ffSJay Zhou 			vq->mpool = rte_mempool_create(mpool_name,
3516f0175ffSJay Zhou 					vq_size,
3526f0175ffSJay Zhou 					sizeof(struct virtio_crypto_op_cookie),
3536f0175ffSJay Zhou 					RTE_CACHE_LINE_SIZE, 0,
3546f0175ffSJay Zhou 					NULL, NULL, NULL, NULL, socket_id,
3556f0175ffSJay Zhou 					0);
3566f0175ffSJay Zhou 		if (!vq->mpool) {
3576f0175ffSJay Zhou 			VIRTIO_CRYPTO_DRV_LOG_ERR("Virtio Crypto PMD "
3586f0175ffSJay Zhou 					"Cannot create mempool");
3596f0175ffSJay Zhou 			goto mpool_create_err;
3606f0175ffSJay Zhou 		}
3616f0175ffSJay Zhou 		for (i = 0; i < vq_size; i++) {
3626f0175ffSJay Zhou 			vq->vq_descx[i].cookie =
3636f0175ffSJay Zhou 				rte_zmalloc("crypto PMD op cookie pointer",
3646f0175ffSJay Zhou 					sizeof(struct virtio_crypto_op_cookie),
3656f0175ffSJay Zhou 					RTE_CACHE_LINE_SIZE);
3666f0175ffSJay Zhou 			if (vq->vq_descx[i].cookie == NULL) {
3676f0175ffSJay Zhou 				VIRTIO_CRYPTO_DRV_LOG_ERR("Failed to "
3686f0175ffSJay Zhou 						"alloc mem for cookie");
3696f0175ffSJay Zhou 				goto cookie_alloc_err;
3706f0175ffSJay Zhou 			}
3716f0175ffSJay Zhou 		}
3726f0175ffSJay Zhou 	}
3736f0175ffSJay Zhou 
3746f0175ffSJay Zhou 	vq->hw = hw;
3756f0175ffSJay Zhou 	vq->dev_id = dev->data->dev_id;
3766f0175ffSJay Zhou 	vq->vq_queue_index = vtpci_queue_idx;
3776f0175ffSJay Zhou 	vq->vq_nentries = vq_size;
3786f0175ffSJay Zhou 
3796f0175ffSJay Zhou 	/*
3806f0175ffSJay Zhou 	 * Using part of the vring entries is permitted, but the maximum
3816f0175ffSJay Zhou 	 * is vq_size
3826f0175ffSJay Zhou 	 */
3836f0175ffSJay Zhou 	if (nb_desc == 0 || nb_desc > vq_size)
3846f0175ffSJay Zhou 		nb_desc = vq_size;
3856f0175ffSJay Zhou 	vq->vq_free_cnt = nb_desc;
3866f0175ffSJay Zhou 
3876f0175ffSJay Zhou 	/*
3886f0175ffSJay Zhou 	 * Reserve a memzone for vring elements
3896f0175ffSJay Zhou 	 */
3906f0175ffSJay Zhou 	size = vring_size(vq_size, VIRTIO_PCI_VRING_ALIGN);
3916f0175ffSJay Zhou 	vq->vq_ring_size = RTE_ALIGN_CEIL(size, VIRTIO_PCI_VRING_ALIGN);
3926f0175ffSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("%s vring_size: %d, rounded_vring_size: %d",
3936f0175ffSJay Zhou 			(queue_type == VTCRYPTO_DATAQ) ? "dataq" : "ctrlq",
3946f0175ffSJay Zhou 			size, vq->vq_ring_size);
3956f0175ffSJay Zhou 
3966f0175ffSJay Zhou 	mz = rte_memzone_reserve_aligned(vq_name, vq->vq_ring_size,
3976f0175ffSJay Zhou 			socket_id, 0, VIRTIO_PCI_VRING_ALIGN);
3986f0175ffSJay Zhou 	if (mz == NULL) {
3996f0175ffSJay Zhou 		if (rte_errno == EEXIST)
4006f0175ffSJay Zhou 			mz = rte_memzone_lookup(vq_name);
4016f0175ffSJay Zhou 		if (mz == NULL) {
4026f0175ffSJay Zhou 			VIRTIO_CRYPTO_INIT_LOG_ERR("not enough memory");
4036f0175ffSJay Zhou 			goto mz_reserve_err;
4046f0175ffSJay Zhou 		}
4056f0175ffSJay Zhou 	}
4066f0175ffSJay Zhou 
4076f0175ffSJay Zhou 	/*
4086f0175ffSJay Zhou 	 * Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit,
4096f0175ffSJay Zhou 	 * and only accepts 32 bit page frame number.
4106f0175ffSJay Zhou 	 * Check if the allocated physical memory exceeds 16TB.
4116f0175ffSJay Zhou 	 */
41272f82c43SThomas Monjalon 	if ((mz->iova + vq->vq_ring_size - 1)
4136f0175ffSJay Zhou 				>> (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) {
4146f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("vring address shouldn't be "
4156f0175ffSJay Zhou 					"above 16TB!");
4166f0175ffSJay Zhou 		goto vring_addr_err;
4176f0175ffSJay Zhou 	}
4186f0175ffSJay Zhou 
4196f0175ffSJay Zhou 	memset(mz->addr, 0, sizeof(mz->len));
4206f0175ffSJay Zhou 	vq->mz = mz;
42172f82c43SThomas Monjalon 	vq->vq_ring_mem = mz->iova;
4226f0175ffSJay Zhou 	vq->vq_ring_virt_mem = mz->addr;
4236f0175ffSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_ring_mem(physical): 0x%"PRIx64,
42472f82c43SThomas Monjalon 					(uint64_t)mz->iova);
4256f0175ffSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_ring_virt_mem: 0x%"PRIx64,
4266f0175ffSJay Zhou 					(uint64_t)(uintptr_t)mz->addr);
4276f0175ffSJay Zhou 
4286f0175ffSJay Zhou 	*pvq = vq;
4296f0175ffSJay Zhou 
4306f0175ffSJay Zhou 	return 0;
4316f0175ffSJay Zhou 
4326f0175ffSJay Zhou vring_addr_err:
4336f0175ffSJay Zhou 	rte_memzone_free(mz);
4346f0175ffSJay Zhou mz_reserve_err:
4356f0175ffSJay Zhou cookie_alloc_err:
4366f0175ffSJay Zhou 	rte_mempool_free(vq->mpool);
4376f0175ffSJay Zhou 	if (i != 0) {
4386f0175ffSJay Zhou 		for (j = 0; j < i; j++)
4396f0175ffSJay Zhou 			rte_free(vq->vq_descx[j].cookie);
4406f0175ffSJay Zhou 	}
4416f0175ffSJay Zhou mpool_create_err:
4426f0175ffSJay Zhou 	rte_free(vq);
4436f0175ffSJay Zhou 	return -ENOMEM;
4446f0175ffSJay Zhou }
4456f0175ffSJay Zhou 
4466f0175ffSJay Zhou static int
4476f0175ffSJay Zhou virtio_crypto_ctrlq_setup(struct rte_cryptodev *dev, uint16_t queue_idx)
4486f0175ffSJay Zhou {
4496f0175ffSJay Zhou 	int ret;
4506f0175ffSJay Zhou 	struct virtqueue *vq;
4516f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
4526f0175ffSJay Zhou 
4536f0175ffSJay Zhou 	/* if virtio device has started, do not touch the virtqueues */
4546f0175ffSJay Zhou 	if (dev->data->dev_started)
4556f0175ffSJay Zhou 		return 0;
4566f0175ffSJay Zhou 
4576f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
4586f0175ffSJay Zhou 
4596f0175ffSJay Zhou 	ret = virtio_crypto_queue_setup(dev, VTCRYPTO_CTRLQ, queue_idx,
4606f0175ffSJay Zhou 			0, SOCKET_ID_ANY, &vq);
4616f0175ffSJay Zhou 	if (ret < 0) {
4626f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("control vq initialization failed");
4636f0175ffSJay Zhou 		return ret;
4646f0175ffSJay Zhou 	}
4656f0175ffSJay Zhou 
4666f0175ffSJay Zhou 	hw->cvq = vq;
4676f0175ffSJay Zhou 
4686f0175ffSJay Zhou 	return 0;
4696f0175ffSJay Zhou }
4706f0175ffSJay Zhou 
4716f0175ffSJay Zhou static void
4726f0175ffSJay Zhou virtio_crypto_free_queues(struct rte_cryptodev *dev)
4736f0175ffSJay Zhou {
4746f0175ffSJay Zhou 	unsigned int i;
4756f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
4766f0175ffSJay Zhou 
4776f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
4786f0175ffSJay Zhou 
4796f0175ffSJay Zhou 	/* control queue release */
4806f0175ffSJay Zhou 	virtio_crypto_queue_release(hw->cvq);
4816f0175ffSJay Zhou 
4826f0175ffSJay Zhou 	/* data queue release */
4836f0175ffSJay Zhou 	for (i = 0; i < hw->max_dataqueues; i++)
4846f0175ffSJay Zhou 		virtio_crypto_queue_release(dev->data->queue_pairs[i]);
4856f0175ffSJay Zhou }
4866f0175ffSJay Zhou 
4876f0175ffSJay Zhou static int
4886f0175ffSJay Zhou virtio_crypto_dev_close(struct rte_cryptodev *dev __rte_unused)
4896f0175ffSJay Zhou {
4906f0175ffSJay Zhou 	return 0;
4916f0175ffSJay Zhou }
4926f0175ffSJay Zhou 
49325500d4bSJay Zhou /*
49425500d4bSJay Zhou  * dev_ops for virtio, bare necessities for basic operation
49525500d4bSJay Zhou  */
49625500d4bSJay Zhou static struct rte_cryptodev_ops virtio_crypto_dev_ops = {
49725500d4bSJay Zhou 	/* Device related operations */
4986f0175ffSJay Zhou 	.dev_configure			 = virtio_crypto_dev_configure,
4996f0175ffSJay Zhou 	.dev_start			 = virtio_crypto_dev_start,
5006f0175ffSJay Zhou 	.dev_stop			 = virtio_crypto_dev_stop,
5016f0175ffSJay Zhou 	.dev_close			 = virtio_crypto_dev_close,
5026f0175ffSJay Zhou 	.dev_infos_get			 = virtio_crypto_dev_info_get,
50325500d4bSJay Zhou 
504efd3ac6bSJay Zhou 	.stats_get			 = virtio_crypto_dev_stats_get,
505efd3ac6bSJay Zhou 	.stats_reset			 = virtio_crypto_dev_stats_reset,
50625500d4bSJay Zhou 
5076f0175ffSJay Zhou 	.queue_pair_setup                = virtio_crypto_qp_setup,
5086f0175ffSJay Zhou 	.queue_pair_release              = virtio_crypto_qp_release,
50925500d4bSJay Zhou 
51025500d4bSJay Zhou 	/* Crypto related operations */
511012c5076SPablo de Lara 	.sym_session_get_size		= virtio_crypto_sym_get_session_private_size,
512012c5076SPablo de Lara 	.sym_session_configure		= virtio_crypto_sym_configure_session,
513012c5076SPablo de Lara 	.sym_session_clear		= virtio_crypto_sym_clear_session
51425500d4bSJay Zhou };
51525500d4bSJay Zhou 
516efd3ac6bSJay Zhou static void
517efd3ac6bSJay Zhou virtio_crypto_update_stats(struct rte_cryptodev *dev,
518efd3ac6bSJay Zhou 		struct rte_cryptodev_stats *stats)
519efd3ac6bSJay Zhou {
520efd3ac6bSJay Zhou 	unsigned int i;
521efd3ac6bSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
522efd3ac6bSJay Zhou 
523efd3ac6bSJay Zhou 	PMD_INIT_FUNC_TRACE();
524efd3ac6bSJay Zhou 
525efd3ac6bSJay Zhou 	if (stats == NULL) {
526efd3ac6bSJay Zhou 		VIRTIO_CRYPTO_DRV_LOG_ERR("invalid pointer");
527efd3ac6bSJay Zhou 		return;
528efd3ac6bSJay Zhou 	}
529efd3ac6bSJay Zhou 
530efd3ac6bSJay Zhou 	for (i = 0; i < hw->max_dataqueues; i++) {
531efd3ac6bSJay Zhou 		const struct virtqueue *data_queue
532efd3ac6bSJay Zhou 			= dev->data->queue_pairs[i];
533efd3ac6bSJay Zhou 		if (data_queue == NULL)
534efd3ac6bSJay Zhou 			continue;
535efd3ac6bSJay Zhou 
536efd3ac6bSJay Zhou 		stats->enqueued_count += data_queue->packets_sent_total;
537efd3ac6bSJay Zhou 		stats->enqueue_err_count += data_queue->packets_sent_failed;
538efd3ac6bSJay Zhou 
539efd3ac6bSJay Zhou 		stats->dequeued_count += data_queue->packets_received_total;
540efd3ac6bSJay Zhou 		stats->dequeue_err_count
541efd3ac6bSJay Zhou 			+= data_queue->packets_received_failed;
542efd3ac6bSJay Zhou 	}
543efd3ac6bSJay Zhou }
544efd3ac6bSJay Zhou 
545efd3ac6bSJay Zhou static void
546efd3ac6bSJay Zhou virtio_crypto_dev_stats_get(struct rte_cryptodev *dev,
547efd3ac6bSJay Zhou 		struct rte_cryptodev_stats *stats)
548efd3ac6bSJay Zhou {
549efd3ac6bSJay Zhou 	PMD_INIT_FUNC_TRACE();
550efd3ac6bSJay Zhou 
551efd3ac6bSJay Zhou 	virtio_crypto_update_stats(dev, stats);
552efd3ac6bSJay Zhou }
553efd3ac6bSJay Zhou 
554efd3ac6bSJay Zhou static void
555efd3ac6bSJay Zhou virtio_crypto_dev_stats_reset(struct rte_cryptodev *dev)
556efd3ac6bSJay Zhou {
557efd3ac6bSJay Zhou 	unsigned int i;
558efd3ac6bSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
559efd3ac6bSJay Zhou 
560efd3ac6bSJay Zhou 	PMD_INIT_FUNC_TRACE();
561efd3ac6bSJay Zhou 
562efd3ac6bSJay Zhou 	for (i = 0; i < hw->max_dataqueues; i++) {
563efd3ac6bSJay Zhou 		struct virtqueue *data_queue = dev->data->queue_pairs[i];
564efd3ac6bSJay Zhou 		if (data_queue == NULL)
565efd3ac6bSJay Zhou 			continue;
566efd3ac6bSJay Zhou 
567efd3ac6bSJay Zhou 		data_queue->packets_sent_total = 0;
568efd3ac6bSJay Zhou 		data_queue->packets_sent_failed = 0;
569efd3ac6bSJay Zhou 
570efd3ac6bSJay Zhou 		data_queue->packets_received_total = 0;
571efd3ac6bSJay Zhou 		data_queue->packets_received_failed = 0;
572efd3ac6bSJay Zhou 	}
573efd3ac6bSJay Zhou }
574efd3ac6bSJay Zhou 
57525500d4bSJay Zhou static int
5766f0175ffSJay Zhou virtio_crypto_qp_setup(struct rte_cryptodev *dev, uint16_t queue_pair_id,
5776f0175ffSJay Zhou 		const struct rte_cryptodev_qp_conf *qp_conf,
578725d2a7fSFan Zhang 		int socket_id)
5796f0175ffSJay Zhou {
5806f0175ffSJay Zhou 	int ret;
5816f0175ffSJay Zhou 	struct virtqueue *vq;
5826f0175ffSJay Zhou 
5836f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
5846f0175ffSJay Zhou 
5856f0175ffSJay Zhou 	/* if virtio dev is started, do not touch the virtqueues */
5866f0175ffSJay Zhou 	if (dev->data->dev_started)
5876f0175ffSJay Zhou 		return 0;
5886f0175ffSJay Zhou 
5896f0175ffSJay Zhou 	ret = virtio_crypto_queue_setup(dev, VTCRYPTO_DATAQ, queue_pair_id,
5906f0175ffSJay Zhou 			qp_conf->nb_descriptors, socket_id, &vq);
5916f0175ffSJay Zhou 	if (ret < 0) {
5926f0175ffSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR(
593f665790aSDavid Marchand 			"virtio crypto data queue initialization failed");
5946f0175ffSJay Zhou 		return ret;
5956f0175ffSJay Zhou 	}
5966f0175ffSJay Zhou 
5976f0175ffSJay Zhou 	dev->data->queue_pairs[queue_pair_id] = vq;
5986f0175ffSJay Zhou 
5996f0175ffSJay Zhou 	return 0;
6006f0175ffSJay Zhou }
6016f0175ffSJay Zhou 
6026f0175ffSJay Zhou static int
6036f0175ffSJay Zhou virtio_crypto_qp_release(struct rte_cryptodev *dev, uint16_t queue_pair_id)
6046f0175ffSJay Zhou {
6056f0175ffSJay Zhou 	struct virtqueue *vq
6066f0175ffSJay Zhou 		= (struct virtqueue *)dev->data->queue_pairs[queue_pair_id];
6076f0175ffSJay Zhou 
6086f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
6096f0175ffSJay Zhou 
6106f0175ffSJay Zhou 	if (vq == NULL) {
6116f0175ffSJay Zhou 		VIRTIO_CRYPTO_DRV_LOG_DBG("vq already freed");
6126f0175ffSJay Zhou 		return 0;
6136f0175ffSJay Zhou 	}
6146f0175ffSJay Zhou 
6156f0175ffSJay Zhou 	virtio_crypto_queue_release(vq);
6166f0175ffSJay Zhou 	return 0;
6176f0175ffSJay Zhou }
6186f0175ffSJay Zhou 
6196f0175ffSJay Zhou static int
62025500d4bSJay Zhou virtio_negotiate_features(struct virtio_crypto_hw *hw, uint64_t req_features)
62125500d4bSJay Zhou {
62225500d4bSJay Zhou 	uint64_t host_features;
62325500d4bSJay Zhou 
62425500d4bSJay Zhou 	PMD_INIT_FUNC_TRACE();
62525500d4bSJay Zhou 
62625500d4bSJay Zhou 	/* Prepare guest_features: feature that driver wants to support */
62725500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("guest_features before negotiate = %" PRIx64,
62825500d4bSJay Zhou 		req_features);
62925500d4bSJay Zhou 
63025500d4bSJay Zhou 	/* Read device(host) feature bits */
63125500d4bSJay Zhou 	host_features = VTPCI_OPS(hw)->get_features(hw);
63225500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("host_features before negotiate = %" PRIx64,
63325500d4bSJay Zhou 		host_features);
63425500d4bSJay Zhou 
63525500d4bSJay Zhou 	/*
63625500d4bSJay Zhou 	 * Negotiate features: Subset of device feature bits are written back
63725500d4bSJay Zhou 	 * guest feature bits.
63825500d4bSJay Zhou 	 */
63925500d4bSJay Zhou 	hw->guest_features = req_features;
64025500d4bSJay Zhou 	hw->guest_features = vtpci_cryptodev_negotiate_features(hw,
64125500d4bSJay Zhou 							host_features);
64225500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("features after negotiate = %" PRIx64,
64325500d4bSJay Zhou 		hw->guest_features);
64425500d4bSJay Zhou 
64525500d4bSJay Zhou 	if (hw->modern) {
64625500d4bSJay Zhou 		if (!vtpci_with_feature(hw, VIRTIO_F_VERSION_1)) {
64725500d4bSJay Zhou 			VIRTIO_CRYPTO_INIT_LOG_ERR(
64825500d4bSJay Zhou 				"VIRTIO_F_VERSION_1 features is not enabled.");
64925500d4bSJay Zhou 			return -1;
65025500d4bSJay Zhou 		}
65125500d4bSJay Zhou 		vtpci_cryptodev_set_status(hw,
65225500d4bSJay Zhou 			VIRTIO_CONFIG_STATUS_FEATURES_OK);
65325500d4bSJay Zhou 		if (!(vtpci_cryptodev_get_status(hw) &
65425500d4bSJay Zhou 			VIRTIO_CONFIG_STATUS_FEATURES_OK)) {
65525500d4bSJay Zhou 			VIRTIO_CRYPTO_INIT_LOG_ERR("failed to set FEATURES_OK "
65625500d4bSJay Zhou 						"status!");
65725500d4bSJay Zhou 			return -1;
65825500d4bSJay Zhou 		}
65925500d4bSJay Zhou 	}
66025500d4bSJay Zhou 
66125500d4bSJay Zhou 	hw->req_guest_features = req_features;
66225500d4bSJay Zhou 
66325500d4bSJay Zhou 	return 0;
66425500d4bSJay Zhou }
66525500d4bSJay Zhou 
66625500d4bSJay Zhou /* reset device and renegotiate features if needed */
66725500d4bSJay Zhou static int
66825500d4bSJay Zhou virtio_crypto_init_device(struct rte_cryptodev *cryptodev,
66925500d4bSJay Zhou 	uint64_t req_features)
67025500d4bSJay Zhou {
67125500d4bSJay Zhou 	struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
67225500d4bSJay Zhou 	struct virtio_crypto_config local_config;
67325500d4bSJay Zhou 	struct virtio_crypto_config *config = &local_config;
67425500d4bSJay Zhou 
67525500d4bSJay Zhou 	PMD_INIT_FUNC_TRACE();
67625500d4bSJay Zhou 
67725500d4bSJay Zhou 	/* Reset the device although not necessary at startup */
67825500d4bSJay Zhou 	vtpci_cryptodev_reset(hw);
67925500d4bSJay Zhou 
68025500d4bSJay Zhou 	/* Tell the host we've noticed this device. */
68125500d4bSJay Zhou 	vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_ACK);
68225500d4bSJay Zhou 
68325500d4bSJay Zhou 	/* Tell the host we've known how to drive the device. */
68425500d4bSJay Zhou 	vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER);
68525500d4bSJay Zhou 	if (virtio_negotiate_features(hw, req_features) < 0)
68625500d4bSJay Zhou 		return -1;
68725500d4bSJay Zhou 
68825500d4bSJay Zhou 	/* Get status of the device */
68925500d4bSJay Zhou 	vtpci_read_cryptodev_config(hw,
69025500d4bSJay Zhou 		offsetof(struct virtio_crypto_config, status),
69125500d4bSJay Zhou 		&config->status, sizeof(config->status));
69225500d4bSJay Zhou 	if (config->status != VIRTIO_CRYPTO_S_HW_READY) {
69325500d4bSJay Zhou 		VIRTIO_CRYPTO_DRV_LOG_ERR("accelerator hardware is "
69425500d4bSJay Zhou 				"not ready");
69525500d4bSJay Zhou 		return -1;
69625500d4bSJay Zhou 	}
69725500d4bSJay Zhou 
69825500d4bSJay Zhou 	/* Get number of data queues */
69925500d4bSJay Zhou 	vtpci_read_cryptodev_config(hw,
70025500d4bSJay Zhou 		offsetof(struct virtio_crypto_config, max_dataqueues),
70125500d4bSJay Zhou 		&config->max_dataqueues,
70225500d4bSJay Zhou 		sizeof(config->max_dataqueues));
70325500d4bSJay Zhou 	hw->max_dataqueues = config->max_dataqueues;
70425500d4bSJay Zhou 
70525500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("hw->max_dataqueues=%d",
70625500d4bSJay Zhou 		hw->max_dataqueues);
70725500d4bSJay Zhou 
70825500d4bSJay Zhou 	return 0;
70925500d4bSJay Zhou }
71025500d4bSJay Zhou 
71125500d4bSJay Zhou /*
71225500d4bSJay Zhou  * This function is based on probe() function
71325500d4bSJay Zhou  * It returns 0 on success.
71425500d4bSJay Zhou  */
71525500d4bSJay Zhou static int
71625500d4bSJay Zhou crypto_virtio_create(const char *name, struct rte_pci_device *pci_dev,
71725500d4bSJay Zhou 		struct rte_cryptodev_pmd_init_params *init_params)
71825500d4bSJay Zhou {
71925500d4bSJay Zhou 	struct rte_cryptodev *cryptodev;
72025500d4bSJay Zhou 	struct virtio_crypto_hw *hw;
72125500d4bSJay Zhou 
72225500d4bSJay Zhou 	PMD_INIT_FUNC_TRACE();
72325500d4bSJay Zhou 
72425500d4bSJay Zhou 	cryptodev = rte_cryptodev_pmd_create(name, &pci_dev->device,
72525500d4bSJay Zhou 					init_params);
72625500d4bSJay Zhou 	if (cryptodev == NULL)
72725500d4bSJay Zhou 		return -ENODEV;
72825500d4bSJay Zhou 
72925500d4bSJay Zhou 	cryptodev->driver_id = cryptodev_virtio_driver_id;
73025500d4bSJay Zhou 	cryptodev->dev_ops = &virtio_crypto_dev_ops;
73125500d4bSJay Zhou 
73225500d4bSJay Zhou 	cryptodev->enqueue_burst = virtio_crypto_pkt_tx_burst;
73325500d4bSJay Zhou 	cryptodev->dequeue_burst = virtio_crypto_pkt_rx_burst;
73425500d4bSJay Zhou 
73525500d4bSJay Zhou 	cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
736b7aa3b5bSJay Zhou 		RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
737b7aa3b5bSJay Zhou 		RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT;
73825500d4bSJay Zhou 
73925500d4bSJay Zhou 	hw = cryptodev->data->dev_private;
74025500d4bSJay Zhou 	hw->dev_id = cryptodev->data->dev_id;
7415889e1ffSJay Zhou 	hw->virtio_dev_capabilities = virtio_capabilities;
74225500d4bSJay Zhou 
74325500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("dev %d vendorID=0x%x deviceID=0x%x",
74425500d4bSJay Zhou 		cryptodev->data->dev_id, pci_dev->id.vendor_id,
74525500d4bSJay Zhou 		pci_dev->id.device_id);
74625500d4bSJay Zhou 
74725500d4bSJay Zhou 	/* pci device init */
74825500d4bSJay Zhou 	if (vtpci_cryptodev_init(pci_dev, hw))
74925500d4bSJay Zhou 		return -1;
75025500d4bSJay Zhou 
75125500d4bSJay Zhou 	if (virtio_crypto_init_device(cryptodev,
75225500d4bSJay Zhou 			VIRTIO_CRYPTO_PMD_GUEST_FEATURES) < 0)
75325500d4bSJay Zhou 		return -1;
75425500d4bSJay Zhou 
755d54c72ecSAkhil Goyal 	rte_cryptodev_pmd_probing_finish(cryptodev);
756d54c72ecSAkhil Goyal 
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;
9532a440d6aSAkhil Goyal 	session = CRYPTODEV_GET_SYM_SESS_PRIV(sess);
954b7fa78c7SJay Zhou 
955b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_SESSION_LOG_INFO("vq->vq_desc_head_idx = %d, "
956b7fa78c7SJay Zhou 			"vq = %p", vq->vq_desc_head_idx, vq);
957b7fa78c7SJay Zhou 
958b7fa78c7SJay Zhou 	if (vq->vq_free_cnt < needed) {
959b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
960b7fa78c7SJay Zhou 				"vq->vq_free_cnt = %d is less than %d, "
961b7fa78c7SJay Zhou 				"not enough", vq->vq_free_cnt, needed);
962b7fa78c7SJay Zhou 		return;
963b7fa78c7SJay Zhou 	}
964b7fa78c7SJay Zhou 
965b7fa78c7SJay Zhou 	/*
966b7fa78c7SJay Zhou 	 * malloc memory to store information of ctrl request op,
967b7fa78c7SJay Zhou 	 * returned status and desc vring
968b7fa78c7SJay Zhou 	 */
969b7fa78c7SJay Zhou 	malloc_virt_addr = rte_malloc(NULL, len_op_ctrl_req + len_inhdr
970b7fa78c7SJay Zhou 		+ NUM_ENTRY_SYM_CLEAR_SESSION
971b7fa78c7SJay Zhou 		* sizeof(struct vring_desc), RTE_CACHE_LINE_SIZE);
972b7fa78c7SJay Zhou 	if (malloc_virt_addr == NULL) {
973b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("not enough heap room");
974b7fa78c7SJay Zhou 		return;
975b7fa78c7SJay Zhou 	}
976b7fa78c7SJay Zhou 	malloc_phys_addr = rte_malloc_virt2iova(malloc_virt_addr);
977b7fa78c7SJay Zhou 
978b7fa78c7SJay Zhou 	/* assign ctrl request op part */
979b7fa78c7SJay Zhou 	ctrl = (struct virtio_crypto_op_ctrl_req *)malloc_virt_addr;
980b7fa78c7SJay Zhou 	ctrl->header.opcode = VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION;
981b7fa78c7SJay Zhou 	/* default data virtqueue is 0 */
982b7fa78c7SJay Zhou 	ctrl->header.queue_id = 0;
983b7fa78c7SJay Zhou 	ctrl->u.destroy_session.session_id = session->session_id;
984b7fa78c7SJay Zhou 
985b7fa78c7SJay Zhou 	/* status part */
986b7fa78c7SJay Zhou 	status = &(((struct virtio_crypto_inhdr *)
987b7fa78c7SJay Zhou 		((uint8_t *)malloc_virt_addr + len_op_ctrl_req))->status);
988b7fa78c7SJay Zhou 	*status = VIRTIO_CRYPTO_ERR;
989b7fa78c7SJay Zhou 
990b7fa78c7SJay Zhou 	/* indirect desc vring part */
991b7fa78c7SJay Zhou 	desc = (struct vring_desc *)((uint8_t *)malloc_virt_addr
992b7fa78c7SJay Zhou 		+ desc_offset);
993b7fa78c7SJay Zhou 
994b7fa78c7SJay Zhou 	/* ctrl request part */
995b7fa78c7SJay Zhou 	desc[0].addr = malloc_phys_addr;
996b7fa78c7SJay Zhou 	desc[0].len = len_op_ctrl_req;
997b7fa78c7SJay Zhou 	desc[0].flags = VRING_DESC_F_NEXT;
998b7fa78c7SJay Zhou 	desc[0].next = 1;
999b7fa78c7SJay Zhou 
1000b7fa78c7SJay Zhou 	/* status part */
1001b7fa78c7SJay Zhou 	desc[1].addr = malloc_phys_addr + len_op_ctrl_req;
1002b7fa78c7SJay Zhou 	desc[1].len = len_inhdr;
1003b7fa78c7SJay Zhou 	desc[1].flags = VRING_DESC_F_WRITE;
1004b7fa78c7SJay Zhou 
1005b7fa78c7SJay Zhou 	/* use only a single desc entry */
1006b7fa78c7SJay Zhou 	head = vq->vq_desc_head_idx;
1007b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].flags = VRING_DESC_F_INDIRECT;
1008b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].addr = malloc_phys_addr + desc_offset;
1009b7fa78c7SJay Zhou 	vq->vq_ring.desc[head].len
1010b7fa78c7SJay Zhou 		= NUM_ENTRY_SYM_CLEAR_SESSION
1011b7fa78c7SJay Zhou 		* sizeof(struct vring_desc);
1012b7fa78c7SJay Zhou 	vq->vq_free_cnt -= needed;
1013b7fa78c7SJay Zhou 
1014b7fa78c7SJay Zhou 	vq->vq_desc_head_idx = vq->vq_ring.desc[head].next;
1015b7fa78c7SJay Zhou 
1016b7fa78c7SJay Zhou 	vq_update_avail_ring(vq, head);
1017b7fa78c7SJay Zhou 	vq_update_avail_idx(vq);
1018b7fa78c7SJay Zhou 
1019b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_queue_index = %d",
1020b7fa78c7SJay Zhou 					vq->vq_queue_index);
1021b7fa78c7SJay Zhou 
1022b7fa78c7SJay Zhou 	virtqueue_notify(vq);
1023b7fa78c7SJay Zhou 
1024b7fa78c7SJay Zhou 	rte_rmb();
1025b7fa78c7SJay Zhou 	while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) {
1026b7fa78c7SJay Zhou 		rte_rmb();
1027b7fa78c7SJay Zhou 		usleep(100);
1028b7fa78c7SJay Zhou 	}
1029b7fa78c7SJay Zhou 
1030b7fa78c7SJay Zhou 	while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) {
1031b7fa78c7SJay Zhou 		uint32_t idx, desc_idx, used_idx;
1032b7fa78c7SJay Zhou 		struct vring_used_elem *uep;
1033b7fa78c7SJay Zhou 
1034b7fa78c7SJay Zhou 		used_idx = (uint32_t)(vq->vq_used_cons_idx
1035b7fa78c7SJay Zhou 				& (vq->vq_nentries - 1));
1036b7fa78c7SJay Zhou 		uep = &vq->vq_ring.used->ring[used_idx];
1037b7fa78c7SJay Zhou 		idx = (uint32_t) uep->id;
1038b7fa78c7SJay Zhou 		desc_idx = idx;
1039b7fa78c7SJay Zhou 		while (vq->vq_ring.desc[desc_idx].flags
1040b7fa78c7SJay Zhou 				& VRING_DESC_F_NEXT) {
1041b7fa78c7SJay Zhou 			desc_idx = vq->vq_ring.desc[desc_idx].next;
1042b7fa78c7SJay Zhou 			vq->vq_free_cnt++;
1043b7fa78c7SJay Zhou 		}
1044b7fa78c7SJay Zhou 
1045b7fa78c7SJay Zhou 		vq->vq_ring.desc[desc_idx].next = vq->vq_desc_head_idx;
1046b7fa78c7SJay Zhou 		vq->vq_desc_head_idx = idx;
1047b7fa78c7SJay Zhou 		vq->vq_used_cons_idx++;
1048b7fa78c7SJay Zhou 		vq->vq_free_cnt++;
1049b7fa78c7SJay Zhou 	}
1050b7fa78c7SJay Zhou 
1051b7fa78c7SJay Zhou 	if (*status != VIRTIO_CRYPTO_OK) {
1052b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Close session failed "
1053b7fa78c7SJay Zhou 				"status=%"PRIu32", session_id=%"PRIu64"",
1054b7fa78c7SJay Zhou 				*status, session->session_id);
1055b7fa78c7SJay Zhou 		rte_free(malloc_virt_addr);
1056b7fa78c7SJay Zhou 		return;
1057b7fa78c7SJay Zhou 	}
1058b7fa78c7SJay Zhou 
1059*1af8b0b2SDavid Marchand 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_free_cnt=%d", vq->vq_free_cnt);
1060*1af8b0b2SDavid Marchand 	VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_desc_head_idx=%d", vq->vq_desc_head_idx);
1061b7fa78c7SJay Zhou 
1062b7fa78c7SJay Zhou 	VIRTIO_CRYPTO_SESSION_LOG_INFO("Close session %"PRIu64" successfully ",
1063b7fa78c7SJay Zhou 			session->session_id);
1064b7fa78c7SJay Zhou 
1065b7fa78c7SJay Zhou 	rte_free(malloc_virt_addr);
1066b7fa78c7SJay Zhou }
1067b7fa78c7SJay Zhou 
1068b7fa78c7SJay Zhou static struct rte_crypto_cipher_xform *
1069b7fa78c7SJay Zhou virtio_crypto_get_cipher_xform(struct rte_crypto_sym_xform *xform)
1070b7fa78c7SJay Zhou {
1071b7fa78c7SJay Zhou 	do {
1072b7fa78c7SJay Zhou 		if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
1073b7fa78c7SJay Zhou 			return &xform->cipher;
1074b7fa78c7SJay Zhou 
1075b7fa78c7SJay Zhou 		xform = xform->next;
1076b7fa78c7SJay Zhou 	} while (xform);
1077b7fa78c7SJay Zhou 
1078b7fa78c7SJay Zhou 	return NULL;
1079b7fa78c7SJay Zhou }
1080b7fa78c7SJay Zhou 
1081b7fa78c7SJay Zhou static struct rte_crypto_auth_xform *
1082b7fa78c7SJay Zhou virtio_crypto_get_auth_xform(struct rte_crypto_sym_xform *xform)
1083b7fa78c7SJay Zhou {
1084b7fa78c7SJay Zhou 	do {
1085b7fa78c7SJay Zhou 		if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
1086b7fa78c7SJay Zhou 			return &xform->auth;
1087b7fa78c7SJay Zhou 
1088b7fa78c7SJay Zhou 		xform = xform->next;
1089b7fa78c7SJay Zhou 	} while (xform);
1090b7fa78c7SJay Zhou 
1091b7fa78c7SJay Zhou 	return NULL;
1092b7fa78c7SJay Zhou }
1093b7fa78c7SJay Zhou 
1094b7fa78c7SJay Zhou /** Get xform chain order */
1095b7fa78c7SJay Zhou static int
1096b7fa78c7SJay Zhou virtio_crypto_get_chain_order(struct rte_crypto_sym_xform *xform)
1097b7fa78c7SJay Zhou {
1098b7fa78c7SJay Zhou 	if (xform == NULL)
1099b7fa78c7SJay Zhou 		return -1;
1100b7fa78c7SJay Zhou 
1101b7fa78c7SJay Zhou 	/* Cipher Only */
1102b7fa78c7SJay Zhou 	if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
1103b7fa78c7SJay Zhou 			xform->next == NULL)
1104b7fa78c7SJay Zhou 		return VIRTIO_CRYPTO_CMD_CIPHER;
1105b7fa78c7SJay Zhou 
1106b7fa78c7SJay Zhou 	/* Authentication Only */
1107b7fa78c7SJay Zhou 	if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
1108b7fa78c7SJay Zhou 			xform->next == NULL)
1109b7fa78c7SJay Zhou 		return VIRTIO_CRYPTO_CMD_AUTH;
1110b7fa78c7SJay Zhou 
1111b7fa78c7SJay Zhou 	/* Authenticate then Cipher */
1112b7fa78c7SJay Zhou 	if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
1113b7fa78c7SJay Zhou 			xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
1114b7fa78c7SJay Zhou 		return VIRTIO_CRYPTO_CMD_HASH_CIPHER;
1115b7fa78c7SJay Zhou 
1116b7fa78c7SJay Zhou 	/* Cipher then Authenticate */
1117b7fa78c7SJay Zhou 	if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
1118b7fa78c7SJay Zhou 			xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH)
1119b7fa78c7SJay Zhou 		return VIRTIO_CRYPTO_CMD_CIPHER_HASH;
1120b7fa78c7SJay Zhou 
1121b7fa78c7SJay Zhou 	return -1;
1122b7fa78c7SJay Zhou }
1123b7fa78c7SJay Zhou 
1124b7fa78c7SJay Zhou static int
1125b7fa78c7SJay Zhou virtio_crypto_sym_pad_cipher_param(
1126b7fa78c7SJay Zhou 		struct virtio_crypto_cipher_session_para *para,
1127b7fa78c7SJay Zhou 		struct rte_crypto_cipher_xform *cipher_xform)
1128b7fa78c7SJay Zhou {
1129b7fa78c7SJay Zhou 	switch (cipher_xform->algo) {
11305889e1ffSJay Zhou 	case RTE_CRYPTO_CIPHER_AES_CBC:
11315889e1ffSJay Zhou 		para->algo = VIRTIO_CRYPTO_CIPHER_AES_CBC;
11325889e1ffSJay Zhou 		break;
1133b7fa78c7SJay Zhou 	default:
1134b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Crypto: Unsupported "
1135b7fa78c7SJay Zhou 				"Cipher alg %u", cipher_xform->algo);
1136b7fa78c7SJay Zhou 		return -1;
1137b7fa78c7SJay Zhou 	}
1138b7fa78c7SJay Zhou 
1139b7fa78c7SJay Zhou 	para->keylen = cipher_xform->key.length;
1140b7fa78c7SJay Zhou 	switch (cipher_xform->op) {
1141b7fa78c7SJay Zhou 	case RTE_CRYPTO_CIPHER_OP_ENCRYPT:
1142b7fa78c7SJay Zhou 		para->op = VIRTIO_CRYPTO_OP_ENCRYPT;
1143b7fa78c7SJay Zhou 		break;
1144b7fa78c7SJay Zhou 	case RTE_CRYPTO_CIPHER_OP_DECRYPT:
1145b7fa78c7SJay Zhou 		para->op = VIRTIO_CRYPTO_OP_DECRYPT;
1146b7fa78c7SJay Zhou 		break;
1147b7fa78c7SJay Zhou 	default:
1148b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Unsupported cipher operation "
1149b7fa78c7SJay Zhou 					"parameter");
1150b7fa78c7SJay Zhou 		return -1;
1151b7fa78c7SJay Zhou 	}
1152b7fa78c7SJay Zhou 
1153b7fa78c7SJay Zhou 	return 0;
1154b7fa78c7SJay Zhou }
1155b7fa78c7SJay Zhou 
1156b7fa78c7SJay Zhou static int
1157b7fa78c7SJay Zhou virtio_crypto_sym_pad_auth_param(
1158b7fa78c7SJay Zhou 		struct virtio_crypto_op_ctrl_req *ctrl,
1159b7fa78c7SJay Zhou 		struct rte_crypto_auth_xform *auth_xform)
1160b7fa78c7SJay Zhou {
1161b7fa78c7SJay Zhou 	uint32_t *algo;
1162b7fa78c7SJay Zhou 	struct virtio_crypto_alg_chain_session_para *para =
1163b7fa78c7SJay Zhou 		&(ctrl->u.sym_create_session.u.chain.para);
1164b7fa78c7SJay Zhou 
1165b7fa78c7SJay Zhou 	switch (ctrl->u.sym_create_session.u.chain.para.hash_mode) {
1166b7fa78c7SJay Zhou 	case VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN:
1167b7fa78c7SJay Zhou 		algo = &(para->u.hash_param.algo);
1168b7fa78c7SJay Zhou 		break;
1169b7fa78c7SJay Zhou 	case VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH:
1170b7fa78c7SJay Zhou 		algo = &(para->u.mac_param.algo);
1171b7fa78c7SJay Zhou 		break;
1172b7fa78c7SJay Zhou 	default:
1173b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Unsupported hash mode %u "
1174b7fa78c7SJay Zhou 			"specified",
1175b7fa78c7SJay Zhou 			ctrl->u.sym_create_session.u.chain.para.hash_mode);
1176b7fa78c7SJay Zhou 		return -1;
1177b7fa78c7SJay Zhou 	}
1178b7fa78c7SJay Zhou 
1179b7fa78c7SJay Zhou 	switch (auth_xform->algo) {
11808144eadaSJay Zhou 	case RTE_CRYPTO_AUTH_SHA1_HMAC:
11818144eadaSJay Zhou 		*algo = VIRTIO_CRYPTO_MAC_HMAC_SHA1;
11828144eadaSJay Zhou 		break;
1183b7fa78c7SJay Zhou 	default:
1184b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
1185b7fa78c7SJay Zhou 			"Crypto: Undefined Hash algo %u specified",
1186b7fa78c7SJay Zhou 			auth_xform->algo);
1187b7fa78c7SJay Zhou 		return -1;
1188b7fa78c7SJay Zhou 	}
1189b7fa78c7SJay Zhou 
1190b7fa78c7SJay Zhou 	return 0;
1191b7fa78c7SJay Zhou }
1192b7fa78c7SJay Zhou 
1193b7fa78c7SJay Zhou static int
1194b7fa78c7SJay Zhou virtio_crypto_sym_pad_op_ctrl_req(
1195b7fa78c7SJay Zhou 		struct virtio_crypto_op_ctrl_req *ctrl,
1196b7fa78c7SJay Zhou 		struct rte_crypto_sym_xform *xform, bool is_chainned,
1197186b14d6SFan Zhang 		uint8_t *cipher_key_data, uint8_t *auth_key_data,
1198b7fa78c7SJay Zhou 		struct virtio_crypto_session *session)
1199b7fa78c7SJay Zhou {
1200b7fa78c7SJay Zhou 	int ret;
1201b7fa78c7SJay Zhou 	struct rte_crypto_auth_xform *auth_xform = NULL;
1202b7fa78c7SJay Zhou 	struct rte_crypto_cipher_xform *cipher_xform = NULL;
1203b7fa78c7SJay Zhou 
1204b7fa78c7SJay Zhou 	/* Get cipher xform from crypto xform chain */
1205b7fa78c7SJay Zhou 	cipher_xform = virtio_crypto_get_cipher_xform(xform);
1206b7fa78c7SJay Zhou 	if (cipher_xform) {
1207186b14d6SFan Zhang 		if (cipher_xform->key.length > VIRTIO_CRYPTO_MAX_KEY_SIZE) {
1208186b14d6SFan Zhang 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1209186b14d6SFan Zhang 				"cipher key size cannot be longer than %u",
1210186b14d6SFan Zhang 				VIRTIO_CRYPTO_MAX_KEY_SIZE);
1211186b14d6SFan Zhang 			return -1;
1212186b14d6SFan Zhang 		}
1213b063e843SFan Zhang 		if (cipher_xform->iv.length > VIRTIO_CRYPTO_MAX_IV_SIZE) {
1214b063e843SFan Zhang 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1215b063e843SFan Zhang 				"cipher IV size cannot be longer than %u",
1216b063e843SFan Zhang 				VIRTIO_CRYPTO_MAX_IV_SIZE);
1217b063e843SFan Zhang 			return -1;
1218b063e843SFan Zhang 		}
1219b7fa78c7SJay Zhou 		if (is_chainned)
1220b7fa78c7SJay Zhou 			ret = virtio_crypto_sym_pad_cipher_param(
1221b7fa78c7SJay Zhou 				&ctrl->u.sym_create_session.u.chain.para
1222b7fa78c7SJay Zhou 						.cipher_param, cipher_xform);
1223b7fa78c7SJay Zhou 		else
1224b7fa78c7SJay Zhou 			ret = virtio_crypto_sym_pad_cipher_param(
1225b7fa78c7SJay Zhou 				&ctrl->u.sym_create_session.u.cipher.para,
1226b7fa78c7SJay Zhou 				cipher_xform);
1227b7fa78c7SJay Zhou 
1228b7fa78c7SJay Zhou 		if (ret < 0) {
1229b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1230b7fa78c7SJay Zhou 				"pad cipher parameter failed");
1231b7fa78c7SJay Zhou 			return -1;
1232b7fa78c7SJay Zhou 		}
1233b7fa78c7SJay Zhou 
1234186b14d6SFan Zhang 		memcpy(cipher_key_data, cipher_xform->key.data,
1235186b14d6SFan Zhang 				cipher_xform->key.length);
1236b7fa78c7SJay Zhou 
1237b7fa78c7SJay Zhou 		session->iv.offset = cipher_xform->iv.offset;
1238b7fa78c7SJay Zhou 		session->iv.length = cipher_xform->iv.length;
1239b7fa78c7SJay Zhou 	}
1240b7fa78c7SJay Zhou 
1241b7fa78c7SJay Zhou 	/* Get auth xform from crypto xform chain */
1242b7fa78c7SJay Zhou 	auth_xform = virtio_crypto_get_auth_xform(xform);
1243b7fa78c7SJay Zhou 	if (auth_xform) {
1244b7fa78c7SJay Zhou 		/* FIXME: support VIRTIO_CRYPTO_SYM_HASH_MODE_NESTED */
1245b7fa78c7SJay Zhou 		struct virtio_crypto_alg_chain_session_para *para =
1246b7fa78c7SJay Zhou 			&(ctrl->u.sym_create_session.u.chain.para);
1247b7fa78c7SJay Zhou 		if (auth_xform->key.length) {
1248186b14d6SFan Zhang 			if (auth_xform->key.length >
1249186b14d6SFan Zhang 					VIRTIO_CRYPTO_MAX_KEY_SIZE) {
1250186b14d6SFan Zhang 				VIRTIO_CRYPTO_SESSION_LOG_ERR(
1251186b14d6SFan Zhang 				"auth key size cannot be longer than %u",
1252186b14d6SFan Zhang 					VIRTIO_CRYPTO_MAX_KEY_SIZE);
1253186b14d6SFan Zhang 				return -1;
1254186b14d6SFan Zhang 			}
1255b7fa78c7SJay Zhou 			para->hash_mode = VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH;
1256b7fa78c7SJay Zhou 			para->u.mac_param.auth_key_len =
1257b7fa78c7SJay Zhou 				(uint32_t)auth_xform->key.length;
1258b7fa78c7SJay Zhou 			para->u.mac_param.hash_result_len =
1259b7fa78c7SJay Zhou 				auth_xform->digest_length;
1260186b14d6SFan Zhang 			memcpy(auth_key_data, auth_xform->key.data,
1261186b14d6SFan Zhang 					auth_xform->key.length);
1262b7fa78c7SJay Zhou 		} else {
1263b7fa78c7SJay Zhou 			para->hash_mode	= VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN;
1264b7fa78c7SJay Zhou 			para->u.hash_param.hash_result_len =
1265b7fa78c7SJay Zhou 				auth_xform->digest_length;
1266b7fa78c7SJay Zhou 		}
1267b7fa78c7SJay Zhou 
1268b7fa78c7SJay Zhou 		ret = virtio_crypto_sym_pad_auth_param(ctrl, auth_xform);
1269b7fa78c7SJay Zhou 		if (ret < 0) {
1270b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR("pad auth parameter "
1271b7fa78c7SJay Zhou 						"failed");
1272b7fa78c7SJay Zhou 			return -1;
1273b7fa78c7SJay Zhou 		}
1274b7fa78c7SJay Zhou 	}
1275b7fa78c7SJay Zhou 
1276b7fa78c7SJay Zhou 	return 0;
1277b7fa78c7SJay Zhou }
1278b7fa78c7SJay Zhou 
1279b7fa78c7SJay Zhou static int
1280b7fa78c7SJay Zhou virtio_crypto_check_sym_configure_session_paras(
1281b7fa78c7SJay Zhou 		struct rte_cryptodev *dev,
1282b7fa78c7SJay Zhou 		struct rte_crypto_sym_xform *xform,
1283bdce2564SAkhil Goyal 		struct rte_cryptodev_sym_session *sym_sess)
1284b7fa78c7SJay Zhou {
1285bdce2564SAkhil Goyal 	if (unlikely(xform == NULL) || unlikely(sym_sess == NULL)) {
1286b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("NULL pointer");
1287b7fa78c7SJay Zhou 		return -1;
1288b7fa78c7SJay Zhou 	}
1289b7fa78c7SJay Zhou 
1290b7fa78c7SJay Zhou 	if (virtio_crypto_check_sym_session_paras(dev) < 0)
1291b7fa78c7SJay Zhou 		return -1;
1292b7fa78c7SJay Zhou 
1293b7fa78c7SJay Zhou 	return 0;
1294b7fa78c7SJay Zhou }
1295b7fa78c7SJay Zhou 
1296b7fa78c7SJay Zhou static int
1297b7fa78c7SJay Zhou virtio_crypto_sym_configure_session(
1298b7fa78c7SJay Zhou 		struct rte_cryptodev *dev,
1299b7fa78c7SJay Zhou 		struct rte_crypto_sym_xform *xform,
1300bdce2564SAkhil Goyal 		struct rte_cryptodev_sym_session *sess)
1301b7fa78c7SJay Zhou {
1302b7fa78c7SJay Zhou 	int ret;
1303b7fa78c7SJay Zhou 	struct virtio_crypto_session *session;
1304b7fa78c7SJay Zhou 	struct virtio_crypto_op_ctrl_req *ctrl_req;
1305b7fa78c7SJay Zhou 	enum virtio_crypto_cmd_id cmd_id;
1306186b14d6SFan Zhang 	uint8_t cipher_key_data[VIRTIO_CRYPTO_MAX_KEY_SIZE] = {0};
1307186b14d6SFan Zhang 	uint8_t auth_key_data[VIRTIO_CRYPTO_MAX_KEY_SIZE] = {0};
1308b7fa78c7SJay Zhou 	struct virtio_crypto_hw *hw;
1309b7fa78c7SJay Zhou 	struct virtqueue *control_vq;
1310b7fa78c7SJay Zhou 
1311b7fa78c7SJay Zhou 	PMD_INIT_FUNC_TRACE();
1312b7fa78c7SJay Zhou 
1313b7fa78c7SJay Zhou 	ret = virtio_crypto_check_sym_configure_session_paras(dev, xform,
1314bdce2564SAkhil Goyal 			sess);
1315b7fa78c7SJay Zhou 	if (ret < 0) {
1316b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR("Invalid parameters");
1317b7fa78c7SJay Zhou 		return ret;
1318b7fa78c7SJay Zhou 	}
13192a440d6aSAkhil Goyal 	session = CRYPTODEV_GET_SYM_SESS_PRIV(sess);
1320b7fa78c7SJay Zhou 	memset(session, 0, sizeof(struct virtio_crypto_session));
1321b7fa78c7SJay Zhou 	ctrl_req = &session->ctrl;
1322b7fa78c7SJay Zhou 	ctrl_req->header.opcode = VIRTIO_CRYPTO_CIPHER_CREATE_SESSION;
1323b7fa78c7SJay Zhou 	/* FIXME: support multiqueue */
1324b7fa78c7SJay Zhou 	ctrl_req->header.queue_id = 0;
1325b7fa78c7SJay Zhou 
1326b7fa78c7SJay Zhou 	hw = dev->data->dev_private;
1327b7fa78c7SJay Zhou 	control_vq = hw->cvq;
1328b7fa78c7SJay Zhou 
1329b7fa78c7SJay Zhou 	cmd_id = virtio_crypto_get_chain_order(xform);
1330b7fa78c7SJay Zhou 	if (cmd_id == VIRTIO_CRYPTO_CMD_CIPHER_HASH)
1331b7fa78c7SJay Zhou 		ctrl_req->u.sym_create_session.u.chain.para.alg_chain_order
1332b7fa78c7SJay Zhou 			= VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH;
1333b7fa78c7SJay Zhou 	if (cmd_id == VIRTIO_CRYPTO_CMD_HASH_CIPHER)
1334b7fa78c7SJay Zhou 		ctrl_req->u.sym_create_session.u.chain.para.alg_chain_order
1335b7fa78c7SJay Zhou 			= VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER;
1336b7fa78c7SJay Zhou 
1337b7fa78c7SJay Zhou 	switch (cmd_id) {
1338b7fa78c7SJay Zhou 	case VIRTIO_CRYPTO_CMD_CIPHER_HASH:
1339b7fa78c7SJay Zhou 	case VIRTIO_CRYPTO_CMD_HASH_CIPHER:
1340b7fa78c7SJay Zhou 		ctrl_req->u.sym_create_session.op_type
1341b7fa78c7SJay Zhou 			= VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING;
1342b7fa78c7SJay Zhou 
1343b7fa78c7SJay Zhou 		ret = virtio_crypto_sym_pad_op_ctrl_req(ctrl_req,
1344186b14d6SFan Zhang 			xform, true, cipher_key_data, auth_key_data, session);
1345b7fa78c7SJay Zhou 		if (ret < 0) {
1346b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1347b7fa78c7SJay Zhou 				"padding sym op ctrl req failed");
1348b7fa78c7SJay Zhou 			goto error_out;
1349b7fa78c7SJay Zhou 		}
1350b7fa78c7SJay Zhou 		ret = virtio_crypto_send_command(control_vq, ctrl_req,
1351b7fa78c7SJay Zhou 			cipher_key_data, auth_key_data, session);
1352b7fa78c7SJay Zhou 		if (ret < 0) {
1353b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1354b7fa78c7SJay Zhou 				"create session failed: %d", ret);
1355b7fa78c7SJay Zhou 			goto error_out;
1356b7fa78c7SJay Zhou 		}
1357b7fa78c7SJay Zhou 		break;
1358b7fa78c7SJay Zhou 	case VIRTIO_CRYPTO_CMD_CIPHER:
1359b7fa78c7SJay Zhou 		ctrl_req->u.sym_create_session.op_type
1360b7fa78c7SJay Zhou 			= VIRTIO_CRYPTO_SYM_OP_CIPHER;
1361b7fa78c7SJay Zhou 		ret = virtio_crypto_sym_pad_op_ctrl_req(ctrl_req, xform,
1362186b14d6SFan Zhang 			false, cipher_key_data, auth_key_data, session);
1363b7fa78c7SJay Zhou 		if (ret < 0) {
1364b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1365b7fa78c7SJay Zhou 				"padding sym op ctrl req failed");
1366b7fa78c7SJay Zhou 			goto error_out;
1367b7fa78c7SJay Zhou 		}
1368b7fa78c7SJay Zhou 		ret = virtio_crypto_send_command(control_vq, ctrl_req,
1369b7fa78c7SJay Zhou 			cipher_key_data, NULL, session);
1370b7fa78c7SJay Zhou 		if (ret < 0) {
1371b7fa78c7SJay Zhou 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
1372b7fa78c7SJay Zhou 				"create session failed: %d", ret);
1373b7fa78c7SJay Zhou 			goto error_out;
1374b7fa78c7SJay Zhou 		}
1375b7fa78c7SJay Zhou 		break;
1376b7fa78c7SJay Zhou 	default:
1377b7fa78c7SJay Zhou 		VIRTIO_CRYPTO_SESSION_LOG_ERR(
1378b7fa78c7SJay Zhou 			"Unsupported operation chain order parameter");
1379b7fa78c7SJay Zhou 		goto error_out;
1380b7fa78c7SJay Zhou 	}
1381b7fa78c7SJay Zhou 	return 0;
1382b7fa78c7SJay Zhou 
1383b7fa78c7SJay Zhou error_out:
1384b7fa78c7SJay Zhou 	return -1;
1385b7fa78c7SJay Zhou }
1386b7fa78c7SJay Zhou 
13876f0175ffSJay Zhou static void
13886f0175ffSJay Zhou virtio_crypto_dev_info_get(struct rte_cryptodev *dev,
13896f0175ffSJay Zhou 		struct rte_cryptodev_info *info)
13906f0175ffSJay Zhou {
13916f0175ffSJay Zhou 	struct virtio_crypto_hw *hw = dev->data->dev_private;
13926f0175ffSJay Zhou 
13936f0175ffSJay Zhou 	PMD_INIT_FUNC_TRACE();
13946f0175ffSJay Zhou 
13956f0175ffSJay Zhou 	if (info != NULL) {
13966f0175ffSJay Zhou 		info->driver_id = cryptodev_virtio_driver_id;
13976f0175ffSJay Zhou 		info->feature_flags = dev->feature_flags;
13986f0175ffSJay Zhou 		info->max_nb_queue_pairs = hw->max_dataqueues;
1399e1fc5b76SPablo de Lara 		/* No limit of number of sessions */
1400e1fc5b76SPablo de Lara 		info->sym.max_nb_sessions = 0;
14015889e1ffSJay Zhou 		info->capabilities = hw->virtio_dev_capabilities;
14026f0175ffSJay Zhou 	}
14036f0175ffSJay Zhou }
14046f0175ffSJay Zhou 
14056f0175ffSJay Zhou static int
14068769079aSJay Zhou crypto_virtio_pci_probe(
14078769079aSJay Zhou 	struct rte_pci_driver *pci_drv __rte_unused,
140825500d4bSJay Zhou 	struct rte_pci_device *pci_dev)
14098769079aSJay Zhou {
141025500d4bSJay Zhou 	struct rte_cryptodev_pmd_init_params init_params = {
141125500d4bSJay Zhou 		.name = "",
1412933f42eaSXiao Wang 		.socket_id = pci_dev->device.numa_node,
1413e1fc5b76SPablo de Lara 		.private_data_size = sizeof(struct virtio_crypto_hw)
141425500d4bSJay Zhou 	};
141525500d4bSJay Zhou 	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
141625500d4bSJay Zhou 
141725500d4bSJay Zhou 	VIRTIO_CRYPTO_DRV_LOG_DBG("Found Crypto device at %02x:%02x.%x",
141825500d4bSJay Zhou 			pci_dev->addr.bus,
141925500d4bSJay Zhou 			pci_dev->addr.devid,
142025500d4bSJay Zhou 			pci_dev->addr.function);
142125500d4bSJay Zhou 
142225500d4bSJay Zhou 	rte_pci_device_name(&pci_dev->addr, name, sizeof(name));
142325500d4bSJay Zhou 
142425500d4bSJay Zhou 	return crypto_virtio_create(name, pci_dev, &init_params);
14258769079aSJay Zhou }
14268769079aSJay Zhou 
14278769079aSJay Zhou static int
14288769079aSJay Zhou crypto_virtio_pci_remove(
14298769079aSJay Zhou 	struct rte_pci_device *pci_dev __rte_unused)
14308769079aSJay Zhou {
143125500d4bSJay Zhou 	struct rte_cryptodev *cryptodev;
143225500d4bSJay Zhou 	char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
143325500d4bSJay Zhou 
143425500d4bSJay Zhou 	if (pci_dev == NULL)
143525500d4bSJay Zhou 		return -EINVAL;
143625500d4bSJay Zhou 
143725500d4bSJay Zhou 	rte_pci_device_name(&pci_dev->addr, cryptodev_name,
143825500d4bSJay Zhou 			sizeof(cryptodev_name));
143925500d4bSJay Zhou 
144025500d4bSJay Zhou 	cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
144125500d4bSJay Zhou 	if (cryptodev == NULL)
144225500d4bSJay Zhou 		return -ENODEV;
144325500d4bSJay Zhou 
14446f0175ffSJay Zhou 	return virtio_crypto_dev_uninit(cryptodev);
14458769079aSJay Zhou }
14468769079aSJay Zhou 
14478769079aSJay Zhou static struct rte_pci_driver rte_virtio_crypto_driver = {
144825500d4bSJay Zhou 	.id_table = pci_id_virtio_crypto_map,
144925500d4bSJay Zhou 	.drv_flags = 0,
14508769079aSJay Zhou 	.probe = crypto_virtio_pci_probe,
14518769079aSJay Zhou 	.remove = crypto_virtio_pci_remove
14528769079aSJay Zhou };
14538769079aSJay Zhou 
14548769079aSJay Zhou static struct cryptodev_driver virtio_crypto_drv;
14558769079aSJay Zhou 
14568769079aSJay Zhou RTE_PMD_REGISTER_PCI(CRYPTODEV_NAME_VIRTIO_PMD, rte_virtio_crypto_driver);
14578769079aSJay Zhou RTE_PMD_REGISTER_CRYPTO_DRIVER(virtio_crypto_drv,
14588769079aSJay Zhou 	rte_virtio_crypto_driver.driver,
14598769079aSJay Zhou 	cryptodev_virtio_driver_id);
1460eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(virtio_crypto_logtype_init, init, NOTICE);
1461eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(virtio_crypto_logtype_session, session, NOTICE);
1462eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(virtio_crypto_logtype_rx, rx, NOTICE);
1463eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(virtio_crypto_logtype_tx, tx, NOTICE);
1464eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(virtio_crypto_logtype_driver, driver, NOTICE);
1465