xref: /dpdk/drivers/crypto/virtio/virtio_pci.c (revision 25500d4b8076e9b84c0d69108c64418470d1f65c)
1*25500d4bSJay Zhou /* SPDX-License-Identifier: BSD-3-Clause
2*25500d4bSJay Zhou  * Copyright(c) 2018 HUAWEI TECHNOLOGIES CO., LTD.
3*25500d4bSJay Zhou  */
4*25500d4bSJay Zhou 
5*25500d4bSJay Zhou #include <stdint.h>
6*25500d4bSJay Zhou 
7*25500d4bSJay Zhou #ifdef RTE_EXEC_ENV_LINUXAPP
8*25500d4bSJay Zhou  #include <dirent.h>
9*25500d4bSJay Zhou  #include <fcntl.h>
10*25500d4bSJay Zhou #endif
11*25500d4bSJay Zhou 
12*25500d4bSJay Zhou #include <rte_io.h>
13*25500d4bSJay Zhou #include <rte_bus.h>
14*25500d4bSJay Zhou 
15*25500d4bSJay Zhou #include "virtio_pci.h"
16*25500d4bSJay Zhou #include "virtqueue.h"
17*25500d4bSJay Zhou 
18*25500d4bSJay Zhou /*
19*25500d4bSJay Zhou  * Following macros are derived from linux/pci_regs.h, however,
20*25500d4bSJay Zhou  * we can't simply include that header here, as there is no such
21*25500d4bSJay Zhou  * file for non-Linux platform.
22*25500d4bSJay Zhou  */
23*25500d4bSJay Zhou #define PCI_CAPABILITY_LIST	0x34
24*25500d4bSJay Zhou #define PCI_CAP_ID_VNDR		0x09
25*25500d4bSJay Zhou #define PCI_CAP_ID_MSIX		0x11
26*25500d4bSJay Zhou 
27*25500d4bSJay Zhou /*
28*25500d4bSJay Zhou  * The remaining space is defined by each driver as the per-driver
29*25500d4bSJay Zhou  * configuration space.
30*25500d4bSJay Zhou  */
31*25500d4bSJay Zhou #define VIRTIO_PCI_CONFIG(hw) \
32*25500d4bSJay Zhou 		(((hw)->use_msix == VIRTIO_MSIX_ENABLED) ? 24 : 20)
33*25500d4bSJay Zhou 
34*25500d4bSJay Zhou struct virtio_hw_internal virtio_hw_internal[RTE_MAX_VIRTIO_CRYPTO];
35*25500d4bSJay Zhou 
36*25500d4bSJay Zhou static inline int
37*25500d4bSJay Zhou check_vq_phys_addr_ok(struct virtqueue *vq)
38*25500d4bSJay Zhou {
39*25500d4bSJay Zhou 	/* Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit,
40*25500d4bSJay Zhou 	 * and only accepts 32 bit page frame number.
41*25500d4bSJay Zhou 	 * Check if the allocated physical memory exceeds 16TB.
42*25500d4bSJay Zhou 	 */
43*25500d4bSJay Zhou 	if ((vq->vq_ring_mem + vq->vq_ring_size - 1) >>
44*25500d4bSJay Zhou 			(VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) {
45*25500d4bSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("vring address shouldn't be above 16TB!");
46*25500d4bSJay Zhou 		return 0;
47*25500d4bSJay Zhou 	}
48*25500d4bSJay Zhou 
49*25500d4bSJay Zhou 	return 1;
50*25500d4bSJay Zhou }
51*25500d4bSJay Zhou 
52*25500d4bSJay Zhou static inline void
53*25500d4bSJay Zhou io_write64_twopart(uint64_t val, uint32_t *lo, uint32_t *hi)
54*25500d4bSJay Zhou {
55*25500d4bSJay Zhou 	rte_write32(val & ((1ULL << 32) - 1), lo);
56*25500d4bSJay Zhou 	rte_write32(val >> 32,		     hi);
57*25500d4bSJay Zhou }
58*25500d4bSJay Zhou 
59*25500d4bSJay Zhou static void
60*25500d4bSJay Zhou modern_read_dev_config(struct virtio_crypto_hw *hw, size_t offset,
61*25500d4bSJay Zhou 		       void *dst, int length)
62*25500d4bSJay Zhou {
63*25500d4bSJay Zhou 	int i;
64*25500d4bSJay Zhou 	uint8_t *p;
65*25500d4bSJay Zhou 	uint8_t old_gen, new_gen;
66*25500d4bSJay Zhou 
67*25500d4bSJay Zhou 	do {
68*25500d4bSJay Zhou 		old_gen = rte_read8(&hw->common_cfg->config_generation);
69*25500d4bSJay Zhou 
70*25500d4bSJay Zhou 		p = dst;
71*25500d4bSJay Zhou 		for (i = 0;  i < length; i++)
72*25500d4bSJay Zhou 			*p++ = rte_read8((uint8_t *)hw->dev_cfg + offset + i);
73*25500d4bSJay Zhou 
74*25500d4bSJay Zhou 		new_gen = rte_read8(&hw->common_cfg->config_generation);
75*25500d4bSJay Zhou 	} while (old_gen != new_gen);
76*25500d4bSJay Zhou }
77*25500d4bSJay Zhou 
78*25500d4bSJay Zhou static void
79*25500d4bSJay Zhou modern_write_dev_config(struct virtio_crypto_hw *hw, size_t offset,
80*25500d4bSJay Zhou 			const void *src, int length)
81*25500d4bSJay Zhou {
82*25500d4bSJay Zhou 	int i;
83*25500d4bSJay Zhou 	const uint8_t *p = src;
84*25500d4bSJay Zhou 
85*25500d4bSJay Zhou 	for (i = 0;  i < length; i++)
86*25500d4bSJay Zhou 		rte_write8((*p++), (((uint8_t *)hw->dev_cfg) + offset + i));
87*25500d4bSJay Zhou }
88*25500d4bSJay Zhou 
89*25500d4bSJay Zhou static uint64_t
90*25500d4bSJay Zhou modern_get_features(struct virtio_crypto_hw *hw)
91*25500d4bSJay Zhou {
92*25500d4bSJay Zhou 	uint32_t features_lo, features_hi;
93*25500d4bSJay Zhou 
94*25500d4bSJay Zhou 	rte_write32(0, &hw->common_cfg->device_feature_select);
95*25500d4bSJay Zhou 	features_lo = rte_read32(&hw->common_cfg->device_feature);
96*25500d4bSJay Zhou 
97*25500d4bSJay Zhou 	rte_write32(1, &hw->common_cfg->device_feature_select);
98*25500d4bSJay Zhou 	features_hi = rte_read32(&hw->common_cfg->device_feature);
99*25500d4bSJay Zhou 
100*25500d4bSJay Zhou 	return ((uint64_t)features_hi << 32) | features_lo;
101*25500d4bSJay Zhou }
102*25500d4bSJay Zhou 
103*25500d4bSJay Zhou static void
104*25500d4bSJay Zhou modern_set_features(struct virtio_crypto_hw *hw, uint64_t features)
105*25500d4bSJay Zhou {
106*25500d4bSJay Zhou 	rte_write32(0, &hw->common_cfg->guest_feature_select);
107*25500d4bSJay Zhou 	rte_write32(features & ((1ULL << 32) - 1),
108*25500d4bSJay Zhou 		    &hw->common_cfg->guest_feature);
109*25500d4bSJay Zhou 
110*25500d4bSJay Zhou 	rte_write32(1, &hw->common_cfg->guest_feature_select);
111*25500d4bSJay Zhou 	rte_write32(features >> 32,
112*25500d4bSJay Zhou 		    &hw->common_cfg->guest_feature);
113*25500d4bSJay Zhou }
114*25500d4bSJay Zhou 
115*25500d4bSJay Zhou static uint8_t
116*25500d4bSJay Zhou modern_get_status(struct virtio_crypto_hw *hw)
117*25500d4bSJay Zhou {
118*25500d4bSJay Zhou 	return rte_read8(&hw->common_cfg->device_status);
119*25500d4bSJay Zhou }
120*25500d4bSJay Zhou 
121*25500d4bSJay Zhou static void
122*25500d4bSJay Zhou modern_set_status(struct virtio_crypto_hw *hw, uint8_t status)
123*25500d4bSJay Zhou {
124*25500d4bSJay Zhou 	rte_write8(status, &hw->common_cfg->device_status);
125*25500d4bSJay Zhou }
126*25500d4bSJay Zhou 
127*25500d4bSJay Zhou static void
128*25500d4bSJay Zhou modern_reset(struct virtio_crypto_hw *hw)
129*25500d4bSJay Zhou {
130*25500d4bSJay Zhou 	modern_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
131*25500d4bSJay Zhou 	modern_get_status(hw);
132*25500d4bSJay Zhou }
133*25500d4bSJay Zhou 
134*25500d4bSJay Zhou static uint8_t
135*25500d4bSJay Zhou modern_get_isr(struct virtio_crypto_hw *hw)
136*25500d4bSJay Zhou {
137*25500d4bSJay Zhou 	return rte_read8(hw->isr);
138*25500d4bSJay Zhou }
139*25500d4bSJay Zhou 
140*25500d4bSJay Zhou static uint16_t
141*25500d4bSJay Zhou modern_set_config_irq(struct virtio_crypto_hw *hw, uint16_t vec)
142*25500d4bSJay Zhou {
143*25500d4bSJay Zhou 	rte_write16(vec, &hw->common_cfg->msix_config);
144*25500d4bSJay Zhou 	return rte_read16(&hw->common_cfg->msix_config);
145*25500d4bSJay Zhou }
146*25500d4bSJay Zhou 
147*25500d4bSJay Zhou static uint16_t
148*25500d4bSJay Zhou modern_set_queue_irq(struct virtio_crypto_hw *hw, struct virtqueue *vq,
149*25500d4bSJay Zhou 		uint16_t vec)
150*25500d4bSJay Zhou {
151*25500d4bSJay Zhou 	rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
152*25500d4bSJay Zhou 	rte_write16(vec, &hw->common_cfg->queue_msix_vector);
153*25500d4bSJay Zhou 	return rte_read16(&hw->common_cfg->queue_msix_vector);
154*25500d4bSJay Zhou }
155*25500d4bSJay Zhou 
156*25500d4bSJay Zhou static uint16_t
157*25500d4bSJay Zhou modern_get_queue_num(struct virtio_crypto_hw *hw, uint16_t queue_id)
158*25500d4bSJay Zhou {
159*25500d4bSJay Zhou 	rte_write16(queue_id, &hw->common_cfg->queue_select);
160*25500d4bSJay Zhou 	return rte_read16(&hw->common_cfg->queue_size);
161*25500d4bSJay Zhou }
162*25500d4bSJay Zhou 
163*25500d4bSJay Zhou static int
164*25500d4bSJay Zhou modern_setup_queue(struct virtio_crypto_hw *hw, struct virtqueue *vq)
165*25500d4bSJay Zhou {
166*25500d4bSJay Zhou 	uint64_t desc_addr, avail_addr, used_addr;
167*25500d4bSJay Zhou 	uint16_t notify_off;
168*25500d4bSJay Zhou 
169*25500d4bSJay Zhou 	if (!check_vq_phys_addr_ok(vq))
170*25500d4bSJay Zhou 		return -1;
171*25500d4bSJay Zhou 
172*25500d4bSJay Zhou 	desc_addr = vq->vq_ring_mem;
173*25500d4bSJay Zhou 	avail_addr = desc_addr + vq->vq_nentries * sizeof(struct vring_desc);
174*25500d4bSJay Zhou 	used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct vring_avail,
175*25500d4bSJay Zhou 							 ring[vq->vq_nentries]),
176*25500d4bSJay Zhou 				   VIRTIO_PCI_VRING_ALIGN);
177*25500d4bSJay Zhou 
178*25500d4bSJay Zhou 	rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
179*25500d4bSJay Zhou 
180*25500d4bSJay Zhou 	io_write64_twopart(desc_addr, &hw->common_cfg->queue_desc_lo,
181*25500d4bSJay Zhou 				      &hw->common_cfg->queue_desc_hi);
182*25500d4bSJay Zhou 	io_write64_twopart(avail_addr, &hw->common_cfg->queue_avail_lo,
183*25500d4bSJay Zhou 				       &hw->common_cfg->queue_avail_hi);
184*25500d4bSJay Zhou 	io_write64_twopart(used_addr, &hw->common_cfg->queue_used_lo,
185*25500d4bSJay Zhou 				      &hw->common_cfg->queue_used_hi);
186*25500d4bSJay Zhou 
187*25500d4bSJay Zhou 	notify_off = rte_read16(&hw->common_cfg->queue_notify_off);
188*25500d4bSJay Zhou 	vq->notify_addr = (void *)((uint8_t *)hw->notify_base +
189*25500d4bSJay Zhou 				notify_off * hw->notify_off_multiplier);
190*25500d4bSJay Zhou 
191*25500d4bSJay Zhou 	rte_write16(1, &hw->common_cfg->queue_enable);
192*25500d4bSJay Zhou 
193*25500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("queue %u addresses:", vq->vq_queue_index);
194*25500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("\t desc_addr: %" PRIx64, desc_addr);
195*25500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("\t aval_addr: %" PRIx64, avail_addr);
196*25500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("\t used_addr: %" PRIx64, used_addr);
197*25500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("\t notify addr: %p (notify offset: %u)",
198*25500d4bSJay Zhou 		vq->notify_addr, notify_off);
199*25500d4bSJay Zhou 
200*25500d4bSJay Zhou 	return 0;
201*25500d4bSJay Zhou }
202*25500d4bSJay Zhou 
203*25500d4bSJay Zhou static void
204*25500d4bSJay Zhou modern_del_queue(struct virtio_crypto_hw *hw, struct virtqueue *vq)
205*25500d4bSJay Zhou {
206*25500d4bSJay Zhou 	rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
207*25500d4bSJay Zhou 
208*25500d4bSJay Zhou 	io_write64_twopart(0, &hw->common_cfg->queue_desc_lo,
209*25500d4bSJay Zhou 				  &hw->common_cfg->queue_desc_hi);
210*25500d4bSJay Zhou 	io_write64_twopart(0, &hw->common_cfg->queue_avail_lo,
211*25500d4bSJay Zhou 				  &hw->common_cfg->queue_avail_hi);
212*25500d4bSJay Zhou 	io_write64_twopart(0, &hw->common_cfg->queue_used_lo,
213*25500d4bSJay Zhou 				  &hw->common_cfg->queue_used_hi);
214*25500d4bSJay Zhou 
215*25500d4bSJay Zhou 	rte_write16(0, &hw->common_cfg->queue_enable);
216*25500d4bSJay Zhou }
217*25500d4bSJay Zhou 
218*25500d4bSJay Zhou static void
219*25500d4bSJay Zhou modern_notify_queue(struct virtio_crypto_hw *hw __rte_unused,
220*25500d4bSJay Zhou 		struct virtqueue *vq)
221*25500d4bSJay Zhou {
222*25500d4bSJay Zhou 	rte_write16(vq->vq_queue_index, vq->notify_addr);
223*25500d4bSJay Zhou }
224*25500d4bSJay Zhou 
225*25500d4bSJay Zhou const struct virtio_pci_ops virtio_crypto_modern_ops = {
226*25500d4bSJay Zhou 	.read_dev_cfg	= modern_read_dev_config,
227*25500d4bSJay Zhou 	.write_dev_cfg	= modern_write_dev_config,
228*25500d4bSJay Zhou 	.reset		= modern_reset,
229*25500d4bSJay Zhou 	.get_status	= modern_get_status,
230*25500d4bSJay Zhou 	.set_status	= modern_set_status,
231*25500d4bSJay Zhou 	.get_features	= modern_get_features,
232*25500d4bSJay Zhou 	.set_features	= modern_set_features,
233*25500d4bSJay Zhou 	.get_isr	= modern_get_isr,
234*25500d4bSJay Zhou 	.set_config_irq	= modern_set_config_irq,
235*25500d4bSJay Zhou 	.set_queue_irq  = modern_set_queue_irq,
236*25500d4bSJay Zhou 	.get_queue_num	= modern_get_queue_num,
237*25500d4bSJay Zhou 	.setup_queue	= modern_setup_queue,
238*25500d4bSJay Zhou 	.del_queue	= modern_del_queue,
239*25500d4bSJay Zhou 	.notify_queue	= modern_notify_queue,
240*25500d4bSJay Zhou };
241*25500d4bSJay Zhou 
242*25500d4bSJay Zhou void
243*25500d4bSJay Zhou vtpci_read_cryptodev_config(struct virtio_crypto_hw *hw, size_t offset,
244*25500d4bSJay Zhou 		void *dst, int length)
245*25500d4bSJay Zhou {
246*25500d4bSJay Zhou 	VTPCI_OPS(hw)->read_dev_cfg(hw, offset, dst, length);
247*25500d4bSJay Zhou }
248*25500d4bSJay Zhou 
249*25500d4bSJay Zhou void
250*25500d4bSJay Zhou vtpci_write_cryptodev_config(struct virtio_crypto_hw *hw, size_t offset,
251*25500d4bSJay Zhou 		const void *src, int length)
252*25500d4bSJay Zhou {
253*25500d4bSJay Zhou 	VTPCI_OPS(hw)->write_dev_cfg(hw, offset, src, length);
254*25500d4bSJay Zhou }
255*25500d4bSJay Zhou 
256*25500d4bSJay Zhou uint64_t
257*25500d4bSJay Zhou vtpci_cryptodev_negotiate_features(struct virtio_crypto_hw *hw,
258*25500d4bSJay Zhou 		uint64_t host_features)
259*25500d4bSJay Zhou {
260*25500d4bSJay Zhou 	uint64_t features;
261*25500d4bSJay Zhou 
262*25500d4bSJay Zhou 	/*
263*25500d4bSJay Zhou 	 * Limit negotiated features to what the driver, virtqueue, and
264*25500d4bSJay Zhou 	 * host all support.
265*25500d4bSJay Zhou 	 */
266*25500d4bSJay Zhou 	features = host_features & hw->guest_features;
267*25500d4bSJay Zhou 	VTPCI_OPS(hw)->set_features(hw, features);
268*25500d4bSJay Zhou 
269*25500d4bSJay Zhou 	return features;
270*25500d4bSJay Zhou }
271*25500d4bSJay Zhou 
272*25500d4bSJay Zhou void
273*25500d4bSJay Zhou vtpci_cryptodev_reset(struct virtio_crypto_hw *hw)
274*25500d4bSJay Zhou {
275*25500d4bSJay Zhou 	VTPCI_OPS(hw)->set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
276*25500d4bSJay Zhou 	/* flush status write */
277*25500d4bSJay Zhou 	VTPCI_OPS(hw)->get_status(hw);
278*25500d4bSJay Zhou }
279*25500d4bSJay Zhou 
280*25500d4bSJay Zhou void
281*25500d4bSJay Zhou vtpci_cryptodev_reinit_complete(struct virtio_crypto_hw *hw)
282*25500d4bSJay Zhou {
283*25500d4bSJay Zhou 	vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK);
284*25500d4bSJay Zhou }
285*25500d4bSJay Zhou 
286*25500d4bSJay Zhou void
287*25500d4bSJay Zhou vtpci_cryptodev_set_status(struct virtio_crypto_hw *hw, uint8_t status)
288*25500d4bSJay Zhou {
289*25500d4bSJay Zhou 	if (status != VIRTIO_CONFIG_STATUS_RESET)
290*25500d4bSJay Zhou 		status |= VTPCI_OPS(hw)->get_status(hw);
291*25500d4bSJay Zhou 
292*25500d4bSJay Zhou 	VTPCI_OPS(hw)->set_status(hw, status);
293*25500d4bSJay Zhou }
294*25500d4bSJay Zhou 
295*25500d4bSJay Zhou uint8_t
296*25500d4bSJay Zhou vtpci_cryptodev_get_status(struct virtio_crypto_hw *hw)
297*25500d4bSJay Zhou {
298*25500d4bSJay Zhou 	return VTPCI_OPS(hw)->get_status(hw);
299*25500d4bSJay Zhou }
300*25500d4bSJay Zhou 
301*25500d4bSJay Zhou uint8_t
302*25500d4bSJay Zhou vtpci_cryptodev_isr(struct virtio_crypto_hw *hw)
303*25500d4bSJay Zhou {
304*25500d4bSJay Zhou 	return VTPCI_OPS(hw)->get_isr(hw);
305*25500d4bSJay Zhou }
306*25500d4bSJay Zhou 
307*25500d4bSJay Zhou static void *
308*25500d4bSJay Zhou get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap)
309*25500d4bSJay Zhou {
310*25500d4bSJay Zhou 	uint8_t  bar    = cap->bar;
311*25500d4bSJay Zhou 	uint32_t length = cap->length;
312*25500d4bSJay Zhou 	uint32_t offset = cap->offset;
313*25500d4bSJay Zhou 	uint8_t *base;
314*25500d4bSJay Zhou 
315*25500d4bSJay Zhou 	if (bar >= PCI_MAX_RESOURCE) {
316*25500d4bSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("invalid bar: %u", bar);
317*25500d4bSJay Zhou 		return NULL;
318*25500d4bSJay Zhou 	}
319*25500d4bSJay Zhou 
320*25500d4bSJay Zhou 	if (offset + length < offset) {
321*25500d4bSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("offset(%u) + length(%u) overflows",
322*25500d4bSJay Zhou 			offset, length);
323*25500d4bSJay Zhou 		return NULL;
324*25500d4bSJay Zhou 	}
325*25500d4bSJay Zhou 
326*25500d4bSJay Zhou 	if (offset + length > dev->mem_resource[bar].len) {
327*25500d4bSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR(
328*25500d4bSJay Zhou 			"invalid cap: overflows bar space: %u > %" PRIu64,
329*25500d4bSJay Zhou 			offset + length, dev->mem_resource[bar].len);
330*25500d4bSJay Zhou 		return NULL;
331*25500d4bSJay Zhou 	}
332*25500d4bSJay Zhou 
333*25500d4bSJay Zhou 	base = dev->mem_resource[bar].addr;
334*25500d4bSJay Zhou 	if (base == NULL) {
335*25500d4bSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_ERR("bar %u base addr is NULL", bar);
336*25500d4bSJay Zhou 		return NULL;
337*25500d4bSJay Zhou 	}
338*25500d4bSJay Zhou 
339*25500d4bSJay Zhou 	return base + offset;
340*25500d4bSJay Zhou }
341*25500d4bSJay Zhou 
342*25500d4bSJay Zhou #define PCI_MSIX_ENABLE 0x8000
343*25500d4bSJay Zhou 
344*25500d4bSJay Zhou static int
345*25500d4bSJay Zhou virtio_read_caps(struct rte_pci_device *dev, struct virtio_crypto_hw *hw)
346*25500d4bSJay Zhou {
347*25500d4bSJay Zhou 	uint8_t pos;
348*25500d4bSJay Zhou 	struct virtio_pci_cap cap;
349*25500d4bSJay Zhou 	int ret;
350*25500d4bSJay Zhou 
351*25500d4bSJay Zhou 	if (rte_pci_map_device(dev)) {
352*25500d4bSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_DBG("failed to map pci device!");
353*25500d4bSJay Zhou 		return -1;
354*25500d4bSJay Zhou 	}
355*25500d4bSJay Zhou 
356*25500d4bSJay Zhou 	ret = rte_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST);
357*25500d4bSJay Zhou 	if (ret < 0) {
358*25500d4bSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_DBG("failed to read pci capability list");
359*25500d4bSJay Zhou 		return -1;
360*25500d4bSJay Zhou 	}
361*25500d4bSJay Zhou 
362*25500d4bSJay Zhou 	while (pos) {
363*25500d4bSJay Zhou 		ret = rte_pci_read_config(dev, &cap, sizeof(cap), pos);
364*25500d4bSJay Zhou 		if (ret < 0) {
365*25500d4bSJay Zhou 			VIRTIO_CRYPTO_INIT_LOG_ERR(
366*25500d4bSJay Zhou 				"failed to read pci cap at pos: %x", pos);
367*25500d4bSJay Zhou 			break;
368*25500d4bSJay Zhou 		}
369*25500d4bSJay Zhou 
370*25500d4bSJay Zhou 		if (cap.cap_vndr == PCI_CAP_ID_MSIX) {
371*25500d4bSJay Zhou 			/* Transitional devices would also have this capability,
372*25500d4bSJay Zhou 			 * that's why we also check if msix is enabled.
373*25500d4bSJay Zhou 			 * 1st byte is cap ID; 2nd byte is the position of next
374*25500d4bSJay Zhou 			 * cap; next two bytes are the flags.
375*25500d4bSJay Zhou 			 */
376*25500d4bSJay Zhou 			uint16_t flags = ((uint16_t *)&cap)[1];
377*25500d4bSJay Zhou 
378*25500d4bSJay Zhou 			if (flags & PCI_MSIX_ENABLE)
379*25500d4bSJay Zhou 				hw->use_msix = VIRTIO_MSIX_ENABLED;
380*25500d4bSJay Zhou 			else
381*25500d4bSJay Zhou 				hw->use_msix = VIRTIO_MSIX_DISABLED;
382*25500d4bSJay Zhou 		}
383*25500d4bSJay Zhou 
384*25500d4bSJay Zhou 		if (cap.cap_vndr != PCI_CAP_ID_VNDR) {
385*25500d4bSJay Zhou 			VIRTIO_CRYPTO_INIT_LOG_DBG(
386*25500d4bSJay Zhou 				"[%2x] skipping non VNDR cap id: %02x",
387*25500d4bSJay Zhou 				pos, cap.cap_vndr);
388*25500d4bSJay Zhou 			goto next;
389*25500d4bSJay Zhou 		}
390*25500d4bSJay Zhou 
391*25500d4bSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_DBG(
392*25500d4bSJay Zhou 			"[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u",
393*25500d4bSJay Zhou 			pos, cap.cfg_type, cap.bar, cap.offset, cap.length);
394*25500d4bSJay Zhou 
395*25500d4bSJay Zhou 		switch (cap.cfg_type) {
396*25500d4bSJay Zhou 		case VIRTIO_PCI_CAP_COMMON_CFG:
397*25500d4bSJay Zhou 			hw->common_cfg = get_cfg_addr(dev, &cap);
398*25500d4bSJay Zhou 			break;
399*25500d4bSJay Zhou 		case VIRTIO_PCI_CAP_NOTIFY_CFG:
400*25500d4bSJay Zhou 			rte_pci_read_config(dev, &hw->notify_off_multiplier,
401*25500d4bSJay Zhou 					4, pos + sizeof(cap));
402*25500d4bSJay Zhou 			hw->notify_base = get_cfg_addr(dev, &cap);
403*25500d4bSJay Zhou 			break;
404*25500d4bSJay Zhou 		case VIRTIO_PCI_CAP_DEVICE_CFG:
405*25500d4bSJay Zhou 			hw->dev_cfg = get_cfg_addr(dev, &cap);
406*25500d4bSJay Zhou 			break;
407*25500d4bSJay Zhou 		case VIRTIO_PCI_CAP_ISR_CFG:
408*25500d4bSJay Zhou 			hw->isr = get_cfg_addr(dev, &cap);
409*25500d4bSJay Zhou 			break;
410*25500d4bSJay Zhou 		}
411*25500d4bSJay Zhou 
412*25500d4bSJay Zhou next:
413*25500d4bSJay Zhou 		pos = cap.cap_next;
414*25500d4bSJay Zhou 	}
415*25500d4bSJay Zhou 
416*25500d4bSJay Zhou 	if (hw->common_cfg == NULL || hw->notify_base == NULL ||
417*25500d4bSJay Zhou 	    hw->dev_cfg == NULL    || hw->isr == NULL) {
418*25500d4bSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_INFO("no modern virtio pci device found.");
419*25500d4bSJay Zhou 		return -1;
420*25500d4bSJay Zhou 	}
421*25500d4bSJay Zhou 
422*25500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_INFO("found modern virtio pci device.");
423*25500d4bSJay Zhou 
424*25500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("common cfg mapped at: %p", hw->common_cfg);
425*25500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("device cfg mapped at: %p", hw->dev_cfg);
426*25500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("isr cfg mapped at: %p", hw->isr);
427*25500d4bSJay Zhou 	VIRTIO_CRYPTO_INIT_LOG_DBG("notify base: %p, notify off multiplier: %u",
428*25500d4bSJay Zhou 		hw->notify_base, hw->notify_off_multiplier);
429*25500d4bSJay Zhou 
430*25500d4bSJay Zhou 	return 0;
431*25500d4bSJay Zhou }
432*25500d4bSJay Zhou 
433*25500d4bSJay Zhou /*
434*25500d4bSJay Zhou  * Return -1:
435*25500d4bSJay Zhou  *   if there is error mapping with VFIO/UIO.
436*25500d4bSJay Zhou  *   if port map error when driver type is KDRV_NONE.
437*25500d4bSJay Zhou  *   if whitelisted but driver type is KDRV_UNKNOWN.
438*25500d4bSJay Zhou  * Return 1 if kernel driver is managing the device.
439*25500d4bSJay Zhou  * Return 0 on success.
440*25500d4bSJay Zhou  */
441*25500d4bSJay Zhou int
442*25500d4bSJay Zhou vtpci_cryptodev_init(struct rte_pci_device *dev, struct virtio_crypto_hw *hw)
443*25500d4bSJay Zhou {
444*25500d4bSJay Zhou 	/*
445*25500d4bSJay Zhou 	 * Try if we can succeed reading virtio pci caps, which exists
446*25500d4bSJay Zhou 	 * only on modern pci device. If failed, we fallback to legacy
447*25500d4bSJay Zhou 	 * virtio handling.
448*25500d4bSJay Zhou 	 */
449*25500d4bSJay Zhou 	if (virtio_read_caps(dev, hw) == 0) {
450*25500d4bSJay Zhou 		VIRTIO_CRYPTO_INIT_LOG_INFO("modern virtio pci detected.");
451*25500d4bSJay Zhou 		virtio_hw_internal[hw->dev_id].vtpci_ops =
452*25500d4bSJay Zhou 					&virtio_crypto_modern_ops;
453*25500d4bSJay Zhou 		hw->modern = 1;
454*25500d4bSJay Zhou 		return 0;
455*25500d4bSJay Zhou 	}
456*25500d4bSJay Zhou 
457*25500d4bSJay Zhou 	/*
458*25500d4bSJay Zhou 	 * virtio crypto conforms to virtio 1.0 and doesn't support
459*25500d4bSJay Zhou 	 * legacy mode
460*25500d4bSJay Zhou 	 */
461*25500d4bSJay Zhou 	return -1;
462*25500d4bSJay Zhou }
463