Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2016 Intel Corporation
3 : : */
4 : :
5 : : #include <stdint.h>
6 : : #include <string.h>
7 : : #include <stdio.h>
8 : : #include <stdlib.h>
9 : : #include <errno.h>
10 : : #include <unistd.h>
11 : :
12 : : #include <ethdev_driver.h>
13 : : #include <rte_memcpy.h>
14 : : #include <rte_string_fns.h>
15 : : #include <rte_memzone.h>
16 : : #include <rte_malloc.h>
17 : : #include <rte_branch_prediction.h>
18 : : #include <rte_ether.h>
19 : : #include <rte_ip.h>
20 : : #include <rte_arp.h>
21 : : #include <rte_common.h>
22 : : #include <rte_errno.h>
23 : : #include <rte_cpuflags.h>
24 : : #include <rte_vect.h>
25 : : #include <rte_memory.h>
26 : : #include <rte_eal_paging.h>
27 : : #include <rte_eal.h>
28 : : #include <dev_driver.h>
29 : : #include <rte_cycles.h>
30 : : #include <rte_kvargs.h>
31 : :
32 : : #include "virtio_ethdev.h"
33 : : #include "virtio.h"
34 : : #include "virtio_logs.h"
35 : : #include "virtqueue.h"
36 : : #include "virtio_cvq.h"
37 : : #include "virtio_rxtx.h"
38 : : #include "virtio_rxtx_simple.h"
39 : : #include "virtio_user/virtio_user_dev.h"
40 : :
41 : : static int virtio_dev_configure(struct rte_eth_dev *dev);
42 : : static int virtio_dev_start(struct rte_eth_dev *dev);
43 : : static int virtio_dev_promiscuous_enable(struct rte_eth_dev *dev);
44 : : static int virtio_dev_promiscuous_disable(struct rte_eth_dev *dev);
45 : : static int virtio_dev_allmulticast_enable(struct rte_eth_dev *dev);
46 : : static int virtio_dev_allmulticast_disable(struct rte_eth_dev *dev);
47 : : static uint32_t virtio_dev_speed_capa_get(uint32_t speed);
48 : : static int virtio_dev_devargs_parse(struct rte_devargs *devargs,
49 : : uint32_t *speed,
50 : : int *vectorized);
51 : : static int virtio_dev_info_get(struct rte_eth_dev *dev,
52 : : struct rte_eth_dev_info *dev_info);
53 : : static int virtio_dev_link_update(struct rte_eth_dev *dev,
54 : : int wait_to_complete);
55 : : static int virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
56 : : static int virtio_dev_rss_hash_update(struct rte_eth_dev *dev,
57 : : struct rte_eth_rss_conf *rss_conf);
58 : : static int virtio_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
59 : : struct rte_eth_rss_conf *rss_conf);
60 : : static int virtio_dev_rss_reta_update(struct rte_eth_dev *dev,
61 : : struct rte_eth_rss_reta_entry64 *reta_conf,
62 : : uint16_t reta_size);
63 : : static int virtio_dev_rss_reta_query(struct rte_eth_dev *dev,
64 : : struct rte_eth_rss_reta_entry64 *reta_conf,
65 : : uint16_t reta_size);
66 : :
67 : : static void virtio_set_hwaddr(struct virtio_hw *hw);
68 : : static void virtio_get_hwaddr(struct virtio_hw *hw);
69 : :
70 : : static int virtio_dev_stats_get(struct rte_eth_dev *dev,
71 : : struct rte_eth_stats *stats,
72 : : struct eth_queue_stats *qstats);
73 : : static int virtio_dev_xstats_get(struct rte_eth_dev *dev,
74 : : struct rte_eth_xstat *xstats, unsigned n);
75 : : static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
76 : : struct rte_eth_xstat_name *xstats_names,
77 : : unsigned limit);
78 : : static int virtio_dev_stats_reset(struct rte_eth_dev *dev);
79 : : static void virtio_dev_free_mbufs(struct rte_eth_dev *dev);
80 : : static int virtio_vlan_filter_set(struct rte_eth_dev *dev,
81 : : uint16_t vlan_id, int on);
82 : : static int virtio_mac_addr_add(struct rte_eth_dev *dev,
83 : : struct rte_ether_addr *mac_addr,
84 : : uint32_t index, uint32_t vmdq);
85 : : static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index);
86 : : static int virtio_mac_addr_set(struct rte_eth_dev *dev,
87 : : struct rte_ether_addr *mac_addr);
88 : :
89 : : static int virtio_intr_disable(struct rte_eth_dev *dev);
90 : : static int virtio_get_monitor_addr(void *rx_queue,
91 : : struct rte_power_monitor_cond *pmc);
92 : :
93 : : static int virtio_dev_queue_stats_mapping_set(
94 : : struct rte_eth_dev *eth_dev,
95 : : uint16_t queue_id,
96 : : uint8_t stat_idx,
97 : : uint8_t is_rx);
98 : :
99 : : static void virtio_notify_peers(struct rte_eth_dev *dev);
100 : : static void virtio_ack_link_announce(struct rte_eth_dev *dev);
101 : :
102 : : static int virtio_rx_burst_mode_get(struct rte_eth_dev *dev,
103 : : __rte_unused uint16_t queue_id, struct rte_eth_burst_mode *mode);
104 : : static int virtio_tx_burst_mode_get(struct rte_eth_dev *dev,
105 : : __rte_unused uint16_t queue_id, struct rte_eth_burst_mode *mode);
106 : :
107 : : struct rte_virtio_xstats_name_off {
108 : : char name[RTE_ETH_XSTATS_NAME_SIZE];
109 : : unsigned offset;
110 : : };
111 : :
112 : : /* [rt]x_qX_ is prepended to the name string here */
113 : : static const struct rte_virtio_xstats_name_off rte_virtio_rxq_stat_strings[] = {
114 : : {"good_packets", offsetof(struct virtnet_rx, stats.packets)},
115 : : {"good_bytes", offsetof(struct virtnet_rx, stats.bytes)},
116 : : {"errors", offsetof(struct virtnet_rx, stats.errors)},
117 : : {"multicast_packets", offsetof(struct virtnet_rx, stats.multicast)},
118 : : {"broadcast_packets", offsetof(struct virtnet_rx, stats.broadcast)},
119 : : {"undersize_packets", offsetof(struct virtnet_rx, stats.size_bins[0])},
120 : : {"size_64_packets", offsetof(struct virtnet_rx, stats.size_bins[1])},
121 : : {"size_65_127_packets", offsetof(struct virtnet_rx, stats.size_bins[2])},
122 : : {"size_128_255_packets", offsetof(struct virtnet_rx, stats.size_bins[3])},
123 : : {"size_256_511_packets", offsetof(struct virtnet_rx, stats.size_bins[4])},
124 : : {"size_512_1023_packets", offsetof(struct virtnet_rx, stats.size_bins[5])},
125 : : {"size_1024_1518_packets", offsetof(struct virtnet_rx, stats.size_bins[6])},
126 : : {"size_1519_max_packets", offsetof(struct virtnet_rx, stats.size_bins[7])},
127 : : };
128 : :
129 : : /* [rt]x_qX_ is prepended to the name string here */
130 : : static const struct rte_virtio_xstats_name_off rte_virtio_txq_stat_strings[] = {
131 : : {"good_packets", offsetof(struct virtnet_tx, stats.packets)},
132 : : {"good_bytes", offsetof(struct virtnet_tx, stats.bytes)},
133 : : {"multicast_packets", offsetof(struct virtnet_tx, stats.multicast)},
134 : : {"broadcast_packets", offsetof(struct virtnet_tx, stats.broadcast)},
135 : : {"undersize_packets", offsetof(struct virtnet_tx, stats.size_bins[0])},
136 : : {"size_64_packets", offsetof(struct virtnet_tx, stats.size_bins[1])},
137 : : {"size_65_127_packets", offsetof(struct virtnet_tx, stats.size_bins[2])},
138 : : {"size_128_255_packets", offsetof(struct virtnet_tx, stats.size_bins[3])},
139 : : {"size_256_511_packets", offsetof(struct virtnet_tx, stats.size_bins[4])},
140 : : {"size_512_1023_packets", offsetof(struct virtnet_tx, stats.size_bins[5])},
141 : : {"size_1024_1518_packets", offsetof(struct virtnet_tx, stats.size_bins[6])},
142 : : {"size_1519_max_packets", offsetof(struct virtnet_tx, stats.size_bins[7])},
143 : : };
144 : :
145 : : #define VIRTIO_NB_RXQ_XSTATS (sizeof(rte_virtio_rxq_stat_strings) / \
146 : : sizeof(rte_virtio_rxq_stat_strings[0]))
147 : : #define VIRTIO_NB_TXQ_XSTATS (sizeof(rte_virtio_txq_stat_strings) / \
148 : : sizeof(rte_virtio_txq_stat_strings[0]))
149 : :
150 : : struct virtio_hw_internal virtio_hw_internal[RTE_MAX_ETHPORTS];
151 : :
152 : : static int
153 : 0 : virtio_set_multiple_queues_rss(struct rte_eth_dev *dev, uint16_t nb_queues)
154 : : {
155 : 0 : struct virtio_hw *hw = dev->data->dev_private;
156 : : struct virtio_pmd_ctrl ctrl;
157 : : struct virtio_net_ctrl_rss rss;
158 : : int dlen, ret;
159 : :
160 : 0 : rss.hash_types = hw->rss_hash_types & VIRTIO_NET_HASH_TYPE_MASK;
161 : : RTE_BUILD_BUG_ON(!RTE_IS_POWER_OF_2(VIRTIO_NET_RSS_RETA_SIZE));
162 : 0 : rss.indirection_table_mask = VIRTIO_NET_RSS_RETA_SIZE - 1;
163 : 0 : rss.unclassified_queue = 0;
164 : 0 : memcpy(rss.indirection_table, hw->rss_reta, VIRTIO_NET_RSS_RETA_SIZE * sizeof(uint16_t));
165 : 0 : rss.max_tx_vq = nb_queues;
166 : 0 : rss.hash_key_length = VIRTIO_NET_RSS_KEY_SIZE;
167 : 0 : memcpy(rss.hash_key_data, hw->rss_key, VIRTIO_NET_RSS_KEY_SIZE);
168 : :
169 : 0 : ctrl.hdr.class = VIRTIO_NET_CTRL_MQ;
170 : 0 : ctrl.hdr.cmd = VIRTIO_NET_CTRL_MQ_RSS_CONFIG;
171 : : memcpy(ctrl.data, &rss, sizeof(rss));
172 : :
173 : 0 : dlen = sizeof(rss);
174 : :
175 : 0 : ret = virtio_send_command(hw->cvq, &ctrl, &dlen, 1);
176 [ # # ]: 0 : if (ret) {
177 : 0 : PMD_INIT_LOG(ERR, "RSS multiqueue configured but send command failed");
178 : 0 : return -EINVAL;
179 : : }
180 : :
181 : : return 0;
182 : : }
183 : :
184 : : static int
185 : 0 : virtio_set_multiple_queues_auto(struct rte_eth_dev *dev, uint16_t nb_queues)
186 : : {
187 : 0 : struct virtio_hw *hw = dev->data->dev_private;
188 : : struct virtio_pmd_ctrl ctrl;
189 : : int dlen;
190 : : int ret;
191 : :
192 : 0 : ctrl.hdr.class = VIRTIO_NET_CTRL_MQ;
193 : 0 : ctrl.hdr.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET;
194 : : memcpy(ctrl.data, &nb_queues, sizeof(uint16_t));
195 : :
196 : 0 : dlen = sizeof(uint16_t);
197 : :
198 : 0 : ret = virtio_send_command(hw->cvq, &ctrl, &dlen, 1);
199 [ # # ]: 0 : if (ret) {
200 : 0 : PMD_INIT_LOG(ERR, "Multiqueue configured but send command "
201 : : "failed, this is too late now...");
202 : 0 : return -EINVAL;
203 : : }
204 : :
205 : : return 0;
206 : : }
207 : :
208 : : static int
209 : 0 : virtio_set_multiple_queues(struct rte_eth_dev *dev, uint16_t nb_queues)
210 : : {
211 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
212 : :
213 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_RSS))
214 : 0 : return virtio_set_multiple_queues_rss(dev, nb_queues);
215 : : else
216 : 0 : return virtio_set_multiple_queues_auto(dev, nb_queues);
217 : : }
218 : :
219 : : static uint16_t
220 : : virtio_get_nr_vq(struct virtio_hw *hw)
221 : : {
222 : 0 : uint16_t nr_vq = hw->max_queue_pairs * 2;
223 : :
224 [ # # # # : 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VQ))
# # ]
225 : 0 : nr_vq += 1;
226 : :
227 : : return nr_vq;
228 : : }
229 : :
230 : : static void
231 : 0 : virtio_control_queue_notify(struct virtqueue *vq, __rte_unused void *cookie)
232 : : {
233 : : virtqueue_notify(vq);
234 : 0 : }
235 : :
236 : : static int
237 : 0 : virtio_init_queue(struct rte_eth_dev *dev, uint16_t queue_idx)
238 : : {
239 : : char vq_name[VIRTQUEUE_MAX_NAME_SZ];
240 : : unsigned int vq_size;
241 : 0 : struct virtio_hw *hw = dev->data->dev_private;
242 : : struct virtqueue *vq;
243 [ # # ]: 0 : int queue_type = virtio_get_queue_type(hw, queue_idx);
244 : : int ret;
245 : 0 : int numa_node = dev->device->numa_node;
246 : :
247 : 0 : PMD_INIT_LOG(INFO, "setting up queue: %u on NUMA node %d",
248 : : queue_idx, numa_node);
249 : :
250 : : /*
251 : : * Read the virtqueue size from the Queue Size field
252 : : * Always power of 2 and if 0 virtqueue does not exist
253 : : */
254 : 0 : vq_size = VIRTIO_OPS(hw)->get_queue_num(hw, queue_idx);
255 : 0 : PMD_INIT_LOG(DEBUG, "vq_size: %u", vq_size);
256 [ # # ]: 0 : if (vq_size == 0) {
257 : 0 : PMD_INIT_LOG(ERR, "virtqueue does not exist");
258 : 0 : return -EINVAL;
259 : : }
260 : :
261 [ # # ]: 0 : if (!virtio_with_packed_queue(hw) && !rte_is_power_of_2(vq_size)) {
262 : 0 : PMD_INIT_LOG(ERR, "split virtqueue size is not power of 2");
263 : 0 : return -EINVAL;
264 : : }
265 : :
266 : 0 : snprintf(vq_name, sizeof(vq_name), "port%d_vq%d", dev->data->port_id, queue_idx);
267 : :
268 : 0 : vq = virtqueue_alloc(hw, queue_idx, vq_size, queue_type, numa_node, vq_name);
269 [ # # ]: 0 : if (!vq) {
270 : 0 : PMD_INIT_LOG(ERR, "virtqueue init failed");
271 : 0 : return -ENOMEM;
272 : : }
273 : :
274 : 0 : hw->vqs[queue_idx] = vq;
275 : :
276 [ # # ]: 0 : if (queue_type == VTNET_CQ) {
277 : 0 : hw->cvq = &vq->cq;
278 : 0 : vq->cq.notify_queue = &virtio_control_queue_notify;
279 : : }
280 : :
281 [ # # ]: 0 : if (VIRTIO_OPS(hw)->setup_queue(hw, vq) < 0) {
282 : 0 : PMD_INIT_LOG(ERR, "setup_queue failed");
283 : : ret = -EINVAL;
284 : 0 : goto clean_vq;
285 : : }
286 : :
287 : : return 0;
288 : :
289 : : clean_vq:
290 [ # # ]: 0 : if (queue_type == VTNET_CQ)
291 : 0 : hw->cvq = NULL;
292 : 0 : virtqueue_free(vq);
293 : 0 : hw->vqs[queue_idx] = NULL;
294 : :
295 : 0 : return ret;
296 : : }
297 : :
298 : : static void
299 [ # # ]: 0 : virtio_free_queues(struct virtio_hw *hw)
300 : : {
301 : : uint16_t nr_vq = virtio_get_nr_vq(hw);
302 : : struct virtqueue *vq;
303 : : uint16_t i;
304 : :
305 [ # # ]: 0 : if (hw->vqs == NULL)
306 : : return;
307 : :
308 [ # # ]: 0 : for (i = 0; i < nr_vq; i++) {
309 : 0 : vq = hw->vqs[i];
310 [ # # ]: 0 : if (!vq)
311 : 0 : continue;
312 : 0 : virtqueue_free(vq);
313 : 0 : hw->vqs[i] = NULL;
314 : : }
315 : :
316 : 0 : rte_free(hw->vqs);
317 : 0 : hw->vqs = NULL;
318 : : }
319 : :
320 : : static int
321 : 0 : virtio_alloc_queues(struct rte_eth_dev *dev)
322 : : {
323 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
324 : : uint16_t nr_vq = virtio_get_nr_vq(hw);
325 : : uint16_t i;
326 : : int ret;
327 : :
328 : 0 : hw->vqs = rte_zmalloc(NULL, sizeof(struct virtqueue *) * nr_vq, 0);
329 [ # # ]: 0 : if (!hw->vqs) {
330 : 0 : PMD_INIT_LOG(ERR, "failed to allocate vqs");
331 : 0 : return -ENOMEM;
332 : : }
333 : :
334 [ # # ]: 0 : for (i = 0; i < nr_vq; i++) {
335 : 0 : ret = virtio_init_queue(dev, i);
336 [ # # ]: 0 : if (ret < 0) {
337 : 0 : virtio_free_queues(hw);
338 : 0 : return ret;
339 : : }
340 : : }
341 : :
342 : : return 0;
343 : : }
344 : :
345 : : static void virtio_queues_unbind_intr(struct rte_eth_dev *dev);
346 : :
347 : : static void
348 : : virtio_free_rss(struct virtio_hw *hw)
349 : : {
350 : 0 : rte_free(hw->rss_key);
351 : 0 : hw->rss_key = NULL;
352 : :
353 : 0 : rte_free(hw->rss_reta);
354 : 0 : hw->rss_reta = NULL;
355 : : }
356 : :
357 : : int
358 : 0 : virtio_dev_close(struct rte_eth_dev *dev)
359 : : {
360 : 0 : struct virtio_hw *hw = dev->data->dev_private;
361 : : struct rte_eth_intr_conf *intr_conf = &dev->data->dev_conf.intr_conf;
362 : :
363 : 0 : PMD_INIT_LOG(DEBUG, "virtio_dev_close");
364 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
365 : : return 0;
366 : :
367 [ # # ]: 0 : if (!hw->opened)
368 : : return 0;
369 : 0 : hw->opened = 0;
370 : :
371 : : /* reset the NIC */
372 [ # # ]: 0 : if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
373 : 0 : VIRTIO_OPS(hw)->set_config_irq(hw, VIRTIO_MSI_NO_VECTOR);
374 [ # # ]: 0 : if (intr_conf->rxq)
375 : 0 : virtio_queues_unbind_intr(dev);
376 : :
377 [ # # ]: 0 : if (intr_conf->lsc || intr_conf->rxq) {
378 : 0 : virtio_intr_disable(dev);
379 : 0 : rte_intr_efd_disable(dev->intr_handle);
380 : 0 : rte_intr_vec_list_free(dev->intr_handle);
381 : : }
382 : :
383 : 0 : virtio_reset(hw);
384 : 0 : virtio_dev_free_mbufs(dev);
385 : 0 : virtio_free_queues(hw);
386 : : virtio_free_rss(hw);
387 : :
388 : 0 : return VIRTIO_OPS(hw)->dev_close(hw);
389 : : }
390 : :
391 : : static int
392 : 0 : virtio_dev_promiscuous_enable(struct rte_eth_dev *dev)
393 : : {
394 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
395 : : struct virtio_pmd_ctrl ctrl;
396 : : int dlen[1];
397 : : int ret;
398 : :
399 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) {
400 : 0 : PMD_INIT_LOG(INFO, "host does not support rx control");
401 : 0 : return -ENOTSUP;
402 : : }
403 : :
404 : 0 : ctrl.hdr.class = VIRTIO_NET_CTRL_RX;
405 : 0 : ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_PROMISC;
406 : 0 : ctrl.data[0] = 1;
407 : 0 : dlen[0] = 1;
408 : :
409 : 0 : ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1);
410 [ # # ]: 0 : if (ret) {
411 : 0 : PMD_INIT_LOG(ERR, "Failed to enable promisc");
412 : 0 : return -EAGAIN;
413 : : }
414 : :
415 : : return 0;
416 : : }
417 : :
418 : : static int
419 : 0 : virtio_dev_promiscuous_disable(struct rte_eth_dev *dev)
420 : : {
421 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
422 : : struct virtio_pmd_ctrl ctrl;
423 : : int dlen[1];
424 : : int ret;
425 : :
426 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) {
427 : 0 : PMD_INIT_LOG(INFO, "host does not support rx control");
428 : 0 : return -ENOTSUP;
429 : : }
430 : :
431 : 0 : ctrl.hdr.class = VIRTIO_NET_CTRL_RX;
432 : 0 : ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_PROMISC;
433 : 0 : ctrl.data[0] = 0;
434 : 0 : dlen[0] = 1;
435 : :
436 : 0 : ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1);
437 [ # # ]: 0 : if (ret) {
438 : 0 : PMD_INIT_LOG(ERR, "Failed to disable promisc");
439 : 0 : return -EAGAIN;
440 : : }
441 : :
442 : : return 0;
443 : : }
444 : :
445 : : static int
446 : 0 : virtio_dev_allmulticast_enable(struct rte_eth_dev *dev)
447 : : {
448 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
449 : : struct virtio_pmd_ctrl ctrl;
450 : : int dlen[1];
451 : : int ret;
452 : :
453 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) {
454 : 0 : PMD_INIT_LOG(INFO, "host does not support rx control");
455 : 0 : return -ENOTSUP;
456 : : }
457 : :
458 : 0 : ctrl.hdr.class = VIRTIO_NET_CTRL_RX;
459 : 0 : ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_ALLMULTI;
460 : 0 : ctrl.data[0] = 1;
461 : 0 : dlen[0] = 1;
462 : :
463 : 0 : ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1);
464 [ # # ]: 0 : if (ret) {
465 : 0 : PMD_INIT_LOG(ERR, "Failed to enable allmulticast");
466 : 0 : return -EAGAIN;
467 : : }
468 : :
469 : : return 0;
470 : : }
471 : :
472 : : static int
473 : 0 : virtio_dev_allmulticast_disable(struct rte_eth_dev *dev)
474 : : {
475 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
476 : : struct virtio_pmd_ctrl ctrl;
477 : : int dlen[1];
478 : : int ret;
479 : :
480 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) {
481 : 0 : PMD_INIT_LOG(INFO, "host does not support rx control");
482 : 0 : return -ENOTSUP;
483 : : }
484 : :
485 : 0 : ctrl.hdr.class = VIRTIO_NET_CTRL_RX;
486 : 0 : ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_ALLMULTI;
487 : 0 : ctrl.data[0] = 0;
488 : 0 : dlen[0] = 1;
489 : :
490 : 0 : ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1);
491 [ # # ]: 0 : if (ret) {
492 : 0 : PMD_INIT_LOG(ERR, "Failed to disable allmulticast");
493 : 0 : return -EAGAIN;
494 : : }
495 : :
496 : : return 0;
497 : : }
498 : :
499 : : uint16_t
500 [ # # ]: 0 : virtio_rx_mem_pool_buf_size(struct rte_mempool *mp)
501 : : {
502 : 0 : return rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM;
503 : : }
504 : :
505 : : bool
506 : 0 : virtio_rx_check_scatter(uint16_t max_rx_pkt_len, uint16_t rx_buf_size,
507 : : bool rx_scatter_enabled, const char **error)
508 : : {
509 [ # # ]: 0 : if (!rx_scatter_enabled && max_rx_pkt_len > rx_buf_size) {
510 : 0 : *error = "Rx scatter is disabled and RxQ mbuf pool object size is too small";
511 : 0 : return false;
512 : : }
513 : :
514 : : return true;
515 : : }
516 : :
517 : : static bool
518 : 0 : virtio_check_scatter_on_all_rx_queues(struct rte_eth_dev *dev,
519 : : uint16_t frame_size)
520 : : {
521 : 0 : struct virtio_hw *hw = dev->data->dev_private;
522 : : struct virtnet_rx *rxvq;
523 : : struct virtqueue *vq;
524 : : unsigned int qidx;
525 : : uint16_t buf_size;
526 : : const char *error;
527 : :
528 [ # # ]: 0 : if (hw->vqs == NULL)
529 : : return true;
530 : :
531 [ # # ]: 0 : for (qidx = 0; qidx < hw->max_queue_pairs; qidx++) {
532 : 0 : vq = hw->vqs[2 * qidx + VTNET_SQ_RQ_QUEUE_IDX];
533 [ # # ]: 0 : if (vq == NULL)
534 : 0 : continue;
535 : :
536 : : rxvq = &vq->rxq;
537 [ # # ]: 0 : if (rxvq->mpool == NULL)
538 : 0 : continue;
539 : 0 : buf_size = virtio_rx_mem_pool_buf_size(rxvq->mpool);
540 : :
541 [ # # ]: 0 : if (!virtio_rx_check_scatter(frame_size, buf_size,
542 : 0 : hw->rx_ol_scatter, &error)) {
543 : 0 : PMD_INIT_LOG(ERR, "MTU check for RxQ %u failed: %s",
544 : : qidx, error);
545 : 0 : return false;
546 : : }
547 : : }
548 : :
549 : : return true;
550 : : }
551 : :
552 : : #define VLAN_TAG_LEN 4 /* 802.3ac tag (not DMA'd) */
553 : : static int
554 : 0 : virtio_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
555 : : {
556 : 0 : struct virtio_hw *hw = dev->data->dev_private;
557 : 0 : uint32_t ether_hdr_len = RTE_ETHER_HDR_LEN + VLAN_TAG_LEN +
558 : 0 : hw->vtnet_hdr_size;
559 : 0 : uint32_t frame_size = mtu + ether_hdr_len;
560 : 0 : uint32_t max_frame_size = hw->max_mtu + ether_hdr_len;
561 : :
562 : 0 : max_frame_size = RTE_MIN(max_frame_size, VIRTIO_MAX_RX_PKTLEN);
563 : :
564 [ # # ]: 0 : if (mtu < RTE_ETHER_MIN_MTU || frame_size > max_frame_size) {
565 : 0 : PMD_INIT_LOG(ERR, "MTU should be between %d and %d",
566 : : RTE_ETHER_MIN_MTU, max_frame_size - ether_hdr_len);
567 : 0 : return -EINVAL;
568 : : }
569 : :
570 [ # # ]: 0 : if (!virtio_check_scatter_on_all_rx_queues(dev, frame_size)) {
571 : 0 : PMD_INIT_LOG(ERR, "MTU vs Rx scatter and Rx buffers check failed");
572 : 0 : return -EINVAL;
573 : : }
574 : :
575 : 0 : hw->max_rx_pkt_len = frame_size;
576 : :
577 : 0 : return 0;
578 : : }
579 : :
580 : : static int
581 : 0 : virtio_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
582 : : {
583 : 0 : struct virtio_hw *hw = dev->data->dev_private;
584 : 0 : struct virtnet_rx *rxvq = dev->data->rx_queues[queue_id];
585 [ # # ]: 0 : struct virtqueue *vq = virtnet_rxq_to_vq(rxvq);
586 : :
587 : : virtqueue_enable_intr(vq);
588 [ # # ]: 0 : virtio_mb(hw->weak_barriers);
589 : 0 : return 0;
590 : : }
591 : :
592 : : static int
593 : 0 : virtio_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
594 : : {
595 : 0 : struct virtnet_rx *rxvq = dev->data->rx_queues[queue_id];
596 [ # # ]: 0 : struct virtqueue *vq = virtnet_rxq_to_vq(rxvq);
597 : :
598 : : virtqueue_disable_intr(vq);
599 : 0 : return 0;
600 : : }
601 : :
602 : : static int
603 : 0 : virtio_dev_priv_dump(struct rte_eth_dev *dev, FILE *f)
604 : : {
605 : 0 : struct virtio_hw *hw = dev->data->dev_private;
606 : :
607 : 0 : fprintf(f, "guest_features: 0x%" PRIx64 "\n", hw->guest_features);
608 : 0 : fprintf(f, "vtnet_hdr_size: %u\n", hw->vtnet_hdr_size);
609 : 0 : fprintf(f, "use_vec: rx-%u tx-%u\n", hw->use_vec_rx, hw->use_vec_tx);
610 : 0 : fprintf(f, "use_inorder: rx-%u tx-%u\n", hw->use_inorder_rx, hw->use_inorder_tx);
611 : 0 : fprintf(f, "intr_lsc: %u\n", hw->intr_lsc);
612 : 0 : fprintf(f, "max_mtu: %u\n", hw->max_mtu);
613 : 0 : fprintf(f, "max_rx_pkt_len: %zu\n", hw->max_rx_pkt_len);
614 : 0 : fprintf(f, "max_queue_pairs: %u\n", hw->max_queue_pairs);
615 : 0 : fprintf(f, "req_guest_features: 0x%" PRIx64 "\n", hw->req_guest_features);
616 : :
617 : 0 : return 0;
618 : : }
619 : :
620 : : static void
621 : 0 : virtio_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
622 : : struct rte_eth_rxq_info *qinfo)
623 : : {
624 : 0 : uint16_t vq_idx = 2 * rx_queue_id + VTNET_SQ_RQ_QUEUE_IDX;
625 : 0 : struct virtio_hw *hw = dev->data->dev_private;
626 : 0 : struct virtqueue *vq = hw->vqs[vq_idx];
627 : :
628 : 0 : qinfo->nb_desc = vq->vq_nentries;
629 : 0 : }
630 : :
631 : : static void
632 : 0 : virtio_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
633 : : struct rte_eth_txq_info *qinfo)
634 : : {
635 : 0 : uint16_t vq_idx = 2 * tx_queue_id + VTNET_SQ_TQ_QUEUE_IDX;
636 : 0 : struct virtio_hw *hw = dev->data->dev_private;
637 : 0 : struct virtqueue *vq = hw->vqs[vq_idx];
638 : :
639 : 0 : qinfo->nb_desc = vq->vq_nentries;
640 : 0 : }
641 : :
642 : : /*
643 : : * dev_ops for virtio, bare necessities for basic operation
644 : : */
645 : : static const struct eth_dev_ops virtio_eth_dev_ops = {
646 : : .dev_configure = virtio_dev_configure,
647 : : .dev_start = virtio_dev_start,
648 : : .dev_stop = virtio_dev_stop,
649 : : .dev_close = virtio_dev_close,
650 : : .promiscuous_enable = virtio_dev_promiscuous_enable,
651 : : .promiscuous_disable = virtio_dev_promiscuous_disable,
652 : : .allmulticast_enable = virtio_dev_allmulticast_enable,
653 : : .allmulticast_disable = virtio_dev_allmulticast_disable,
654 : : .mtu_set = virtio_mtu_set,
655 : : .dev_infos_get = virtio_dev_info_get,
656 : : .rxq_info_get = virtio_rxq_info_get,
657 : : .txq_info_get = virtio_txq_info_get,
658 : : .stats_get = virtio_dev_stats_get,
659 : : .xstats_get = virtio_dev_xstats_get,
660 : : .xstats_get_names = virtio_dev_xstats_get_names,
661 : : .stats_reset = virtio_dev_stats_reset,
662 : : .xstats_reset = virtio_dev_stats_reset,
663 : : .link_update = virtio_dev_link_update,
664 : : .vlan_offload_set = virtio_dev_vlan_offload_set,
665 : : .rx_queue_setup = virtio_dev_rx_queue_setup,
666 : : .rx_queue_intr_enable = virtio_dev_rx_queue_intr_enable,
667 : : .rx_queue_intr_disable = virtio_dev_rx_queue_intr_disable,
668 : : .tx_queue_setup = virtio_dev_tx_queue_setup,
669 : : .rx_burst_mode_get = virtio_rx_burst_mode_get,
670 : : .tx_burst_mode_get = virtio_tx_burst_mode_get,
671 : : .rss_hash_update = virtio_dev_rss_hash_update,
672 : : .rss_hash_conf_get = virtio_dev_rss_hash_conf_get,
673 : : .reta_update = virtio_dev_rss_reta_update,
674 : : .reta_query = virtio_dev_rss_reta_query,
675 : : /* collect stats per queue */
676 : : .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set,
677 : : .vlan_filter_set = virtio_vlan_filter_set,
678 : : .mac_addr_add = virtio_mac_addr_add,
679 : : .mac_addr_remove = virtio_mac_addr_remove,
680 : : .mac_addr_set = virtio_mac_addr_set,
681 : : .get_monitor_addr = virtio_get_monitor_addr,
682 : : .eth_dev_priv_dump = virtio_dev_priv_dump,
683 : : };
684 : :
685 : : /*
686 : : * dev_ops for virtio-user in secondary processes, as we just have
687 : : * some limited supports currently.
688 : : */
689 : : const struct eth_dev_ops virtio_user_secondary_eth_dev_ops = {
690 : : .dev_infos_get = virtio_dev_info_get,
691 : : .stats_get = virtio_dev_stats_get,
692 : : .xstats_get = virtio_dev_xstats_get,
693 : : .xstats_get_names = virtio_dev_xstats_get_names,
694 : : .stats_reset = virtio_dev_stats_reset,
695 : : .xstats_reset = virtio_dev_stats_reset,
696 : : /* collect stats per queue */
697 : : .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set,
698 : : };
699 : :
700 : : static void
701 : 0 : virtio_update_stats(struct rte_eth_dev *dev, struct rte_eth_stats *stats,
702 : : struct eth_queue_stats *qstats)
703 : : {
704 : : unsigned i;
705 : :
706 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
707 : 0 : const struct virtnet_tx *txvq = dev->data->tx_queues[i];
708 [ # # ]: 0 : if (txvq == NULL)
709 : 0 : continue;
710 : :
711 : 0 : stats->opackets += txvq->stats.packets;
712 : 0 : stats->obytes += txvq->stats.bytes;
713 : :
714 [ # # ]: 0 : if (qstats != NULL && i < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
715 : 0 : qstats->q_opackets[i] = txvq->stats.packets;
716 : 0 : qstats->q_obytes[i] = txvq->stats.bytes;
717 : : }
718 : : }
719 : :
720 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
721 : 0 : const struct virtnet_rx *rxvq = dev->data->rx_queues[i];
722 [ # # ]: 0 : if (rxvq == NULL)
723 : 0 : continue;
724 : :
725 : 0 : stats->ipackets += rxvq->stats.packets;
726 : 0 : stats->ibytes += rxvq->stats.bytes;
727 : 0 : stats->ierrors += rxvq->stats.errors;
728 : :
729 [ # # ]: 0 : if (qstats != NULL && i < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
730 : 0 : qstats->q_ipackets[i] = rxvq->stats.packets;
731 : 0 : qstats->q_ibytes[i] = rxvq->stats.bytes;
732 : : }
733 : : }
734 : :
735 : 0 : stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed;
736 : 0 : }
737 : :
738 : 0 : static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
739 : : struct rte_eth_xstat_name *xstats_names,
740 : : __rte_unused unsigned limit)
741 : : {
742 : : unsigned i;
743 : : unsigned count = 0;
744 : : unsigned t;
745 : :
746 : 0 : unsigned nstats = dev->data->nb_tx_queues * VIRTIO_NB_TXQ_XSTATS +
747 : 0 : dev->data->nb_rx_queues * VIRTIO_NB_RXQ_XSTATS;
748 : :
749 [ # # ]: 0 : if (xstats_names != NULL) {
750 : : /* Note: limit checked in rte_eth_xstats_names() */
751 : :
752 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
753 : 0 : struct virtnet_rx *rxvq = dev->data->rx_queues[i];
754 [ # # ]: 0 : if (rxvq == NULL)
755 : 0 : continue;
756 [ # # ]: 0 : for (t = 0; t < VIRTIO_NB_RXQ_XSTATS; t++) {
757 : 0 : snprintf(xstats_names[count].name,
758 : : sizeof(xstats_names[count].name),
759 : : "rx_q%u_%s", i,
760 : 0 : rte_virtio_rxq_stat_strings[t].name);
761 : 0 : count++;
762 : : }
763 : : }
764 : :
765 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
766 : 0 : struct virtnet_tx *txvq = dev->data->tx_queues[i];
767 [ # # ]: 0 : if (txvq == NULL)
768 : 0 : continue;
769 [ # # ]: 0 : for (t = 0; t < VIRTIO_NB_TXQ_XSTATS; t++) {
770 : 0 : snprintf(xstats_names[count].name,
771 : : sizeof(xstats_names[count].name),
772 : : "tx_q%u_%s", i,
773 : 0 : rte_virtio_txq_stat_strings[t].name);
774 : 0 : count++;
775 : : }
776 : : }
777 : 0 : return count;
778 : : }
779 : 0 : return nstats;
780 : : }
781 : :
782 : : static int
783 : 0 : virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
784 : : unsigned n)
785 : : {
786 : : unsigned i;
787 : : unsigned count = 0;
788 : :
789 : 0 : unsigned nstats = dev->data->nb_tx_queues * VIRTIO_NB_TXQ_XSTATS +
790 : 0 : dev->data->nb_rx_queues * VIRTIO_NB_RXQ_XSTATS;
791 : :
792 [ # # ]: 0 : if (n < nstats)
793 : 0 : return nstats;
794 : :
795 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
796 : 0 : struct virtnet_rx *rxvq = dev->data->rx_queues[i];
797 : :
798 [ # # ]: 0 : if (rxvq == NULL)
799 : 0 : continue;
800 : :
801 : : unsigned t;
802 : :
803 [ # # ]: 0 : for (t = 0; t < VIRTIO_NB_RXQ_XSTATS; t++) {
804 : 0 : xstats[count].value = *(uint64_t *)(((char *)rxvq) +
805 : 0 : rte_virtio_rxq_stat_strings[t].offset);
806 : 0 : xstats[count].id = count;
807 : 0 : count++;
808 : : }
809 : : }
810 : :
811 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
812 : 0 : struct virtnet_tx *txvq = dev->data->tx_queues[i];
813 : :
814 [ # # ]: 0 : if (txvq == NULL)
815 : 0 : continue;
816 : :
817 : : unsigned t;
818 : :
819 [ # # ]: 0 : for (t = 0; t < VIRTIO_NB_TXQ_XSTATS; t++) {
820 : 0 : xstats[count].value = *(uint64_t *)(((char *)txvq) +
821 : 0 : rte_virtio_txq_stat_strings[t].offset);
822 : 0 : xstats[count].id = count;
823 : 0 : count++;
824 : : }
825 : : }
826 : :
827 : 0 : return count;
828 : : }
829 : :
830 : : static int
831 : 0 : virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats,
832 : : struct eth_queue_stats *qstats)
833 : : {
834 : 0 : virtio_update_stats(dev, stats, qstats);
835 : :
836 : 0 : return 0;
837 : : }
838 : :
839 : : static int
840 : 0 : virtio_dev_stats_reset(struct rte_eth_dev *dev)
841 : : {
842 : : unsigned int i;
843 : :
844 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
845 : 0 : struct virtnet_tx *txvq = dev->data->tx_queues[i];
846 [ # # ]: 0 : if (txvq == NULL)
847 : 0 : continue;
848 : :
849 : 0 : txvq->stats.packets = 0;
850 : 0 : txvq->stats.bytes = 0;
851 : 0 : txvq->stats.multicast = 0;
852 : 0 : txvq->stats.broadcast = 0;
853 : 0 : memset(txvq->stats.size_bins, 0,
854 : : sizeof(txvq->stats.size_bins[0]) * 8);
855 : : }
856 : :
857 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
858 : 0 : struct virtnet_rx *rxvq = dev->data->rx_queues[i];
859 [ # # ]: 0 : if (rxvq == NULL)
860 : 0 : continue;
861 : :
862 : 0 : rxvq->stats.packets = 0;
863 : 0 : rxvq->stats.bytes = 0;
864 : 0 : rxvq->stats.errors = 0;
865 : 0 : rxvq->stats.multicast = 0;
866 : 0 : rxvq->stats.broadcast = 0;
867 : 0 : memset(rxvq->stats.size_bins, 0,
868 : : sizeof(rxvq->stats.size_bins[0]) * 8);
869 : : }
870 : :
871 : 0 : return 0;
872 : : }
873 : :
874 : : static void
875 : : virtio_set_hwaddr(struct virtio_hw *hw)
876 : : {
877 : 0 : virtio_write_dev_config(hw,
878 : : offsetof(struct virtio_net_config, mac),
879 : : &hw->mac_addr, RTE_ETHER_ADDR_LEN);
880 : 0 : }
881 : :
882 : : static void
883 [ # # ]: 0 : virtio_get_hwaddr(struct virtio_hw *hw)
884 : : {
885 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_MAC)) {
886 : 0 : virtio_read_dev_config(hw,
887 : : offsetof(struct virtio_net_config, mac),
888 : 0 : &hw->mac_addr, RTE_ETHER_ADDR_LEN);
889 : : } else {
890 : 0 : rte_eth_random_addr(&hw->mac_addr[0]);
891 : : virtio_set_hwaddr(hw);
892 : : }
893 : 0 : }
894 : :
895 : : static int
896 [ # # ]: 0 : virtio_mac_table_set(struct virtio_hw *hw,
897 : : const struct virtio_net_ctrl_mac *uc,
898 : : const struct virtio_net_ctrl_mac *mc)
899 : : {
900 : : struct virtio_pmd_ctrl ctrl;
901 : : int err, len[2];
902 : :
903 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_CTRL_MAC_ADDR)) {
904 : 0 : PMD_DRV_LOG(INFO, "host does not support mac table");
905 : 0 : return -1;
906 : : }
907 : :
908 : 0 : ctrl.hdr.class = VIRTIO_NET_CTRL_MAC;
909 : 0 : ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_TABLE_SET;
910 : :
911 : 0 : len[0] = uc->entries * RTE_ETHER_ADDR_LEN + sizeof(uc->entries);
912 : 0 : memcpy(ctrl.data, uc, len[0]);
913 : :
914 : 0 : len[1] = mc->entries * RTE_ETHER_ADDR_LEN + sizeof(mc->entries);
915 : 0 : memcpy(ctrl.data + len[0], mc, len[1]);
916 : :
917 : 0 : err = virtio_send_command(hw->cvq, &ctrl, len, 2);
918 [ # # ]: 0 : if (err != 0)
919 : 0 : PMD_DRV_LOG(NOTICE, "mac table set failed: %d", err);
920 : : return err;
921 : : }
922 : :
923 : : static int
924 : 0 : virtio_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
925 : : uint32_t index, uint32_t vmdq __rte_unused)
926 : : {
927 : 0 : struct virtio_hw *hw = dev->data->dev_private;
928 : 0 : const struct rte_ether_addr *addrs = dev->data->mac_addrs;
929 : : unsigned int i;
930 : : struct virtio_net_ctrl_mac *uc, *mc;
931 : :
932 [ # # ]: 0 : if (index >= VIRTIO_MAX_MAC_ADDRS) {
933 : 0 : PMD_DRV_LOG(ERR, "mac address index %u out of range", index);
934 : 0 : return -EINVAL;
935 : : }
936 : :
937 : 0 : uc = alloca(VIRTIO_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN +
938 : : sizeof(uc->entries));
939 : 0 : uc->entries = 0;
940 : 0 : mc = alloca(VIRTIO_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN +
941 : : sizeof(mc->entries));
942 : 0 : mc->entries = 0;
943 : :
944 [ # # ]: 0 : for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) {
945 : : const struct rte_ether_addr *addr
946 [ # # ]: 0 : = (i == index) ? mac_addr : addrs + i;
947 : : struct virtio_net_ctrl_mac *tbl
948 [ # # ]: 0 : = rte_is_multicast_ether_addr(addr) ? mc : uc;
949 : :
950 [ # # ]: 0 : if (rte_is_zero_ether_addr(addr))
951 : : break;
952 : 0 : memcpy(&tbl->macs[tbl->entries++], addr, RTE_ETHER_ADDR_LEN);
953 : : }
954 : :
955 : 0 : return virtio_mac_table_set(hw, uc, mc);
956 : : }
957 : :
958 : : static void
959 : 0 : virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
960 : : {
961 : 0 : struct virtio_hw *hw = dev->data->dev_private;
962 : 0 : struct rte_ether_addr *addrs = dev->data->mac_addrs;
963 : : struct virtio_net_ctrl_mac *uc, *mc;
964 : : unsigned int i;
965 : :
966 [ # # ]: 0 : if (index >= VIRTIO_MAX_MAC_ADDRS) {
967 : 0 : PMD_DRV_LOG(ERR, "mac address index %u out of range", index);
968 : 0 : return;
969 : : }
970 : :
971 : 0 : uc = alloca(VIRTIO_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN +
972 : : sizeof(uc->entries));
973 : 0 : uc->entries = 0;
974 : 0 : mc = alloca(VIRTIO_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN +
975 : : sizeof(mc->entries));
976 : 0 : mc->entries = 0;
977 : :
978 [ # # ]: 0 : for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) {
979 : : struct virtio_net_ctrl_mac *tbl;
980 : :
981 [ # # # # ]: 0 : if (i == index || rte_is_zero_ether_addr(addrs + i))
982 : 0 : continue;
983 : :
984 [ # # ]: 0 : tbl = rte_is_multicast_ether_addr(addrs + i) ? mc : uc;
985 : 0 : memcpy(&tbl->macs[tbl->entries++], addrs + i,
986 : : RTE_ETHER_ADDR_LEN);
987 : : }
988 : :
989 : 0 : virtio_mac_table_set(hw, uc, mc);
990 : : }
991 : :
992 : : static int
993 : 0 : virtio_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
994 : : {
995 : 0 : struct virtio_hw *hw = dev->data->dev_private;
996 : :
997 [ # # ]: 0 : memcpy(hw->mac_addr, mac_addr, RTE_ETHER_ADDR_LEN);
998 : :
999 : : /* Use atomic update if available */
1000 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_CTRL_MAC_ADDR)) {
1001 : : struct virtio_pmd_ctrl ctrl;
1002 : 0 : int len = RTE_ETHER_ADDR_LEN;
1003 : :
1004 : 0 : ctrl.hdr.class = VIRTIO_NET_CTRL_MAC;
1005 : 0 : ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET;
1006 : :
1007 : : memcpy(ctrl.data, mac_addr, RTE_ETHER_ADDR_LEN);
1008 : 0 : return virtio_send_command(hw->cvq, &ctrl, &len, 1);
1009 : : }
1010 : :
1011 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_MAC))
1012 : : return -ENOTSUP;
1013 : :
1014 : : virtio_set_hwaddr(hw);
1015 : 0 : return 0;
1016 : : }
1017 : :
1018 : : #define CLB_VAL_IDX 0
1019 : : #define CLB_MSK_IDX 1
1020 : : #define CLB_MATCH_IDX 2
1021 : : static int
1022 : 0 : virtio_monitor_callback(const uint64_t value,
1023 : : const uint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ])
1024 : : {
1025 : 0 : const uint64_t m = opaque[CLB_MSK_IDX];
1026 : 0 : const uint64_t v = opaque[CLB_VAL_IDX];
1027 : 0 : const uint64_t c = opaque[CLB_MATCH_IDX];
1028 : :
1029 [ # # ]: 0 : if (c)
1030 [ # # ]: 0 : return (value & m) == v ? -1 : 0;
1031 : : else
1032 [ # # ]: 0 : return (value & m) == v ? 0 : -1;
1033 : : }
1034 : :
1035 : : static int
1036 : 0 : virtio_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)
1037 : : {
1038 : : struct virtnet_rx *rxvq = rx_queue;
1039 : 0 : struct virtqueue *vq = virtnet_rxq_to_vq(rxvq);
1040 : : struct virtio_hw *hw;
1041 : :
1042 [ # # ]: 0 : if (vq == NULL)
1043 : : return -EINVAL;
1044 : :
1045 [ # # ]: 0 : hw = vq->hw;
1046 [ # # ]: 0 : if (virtio_with_packed_queue(hw)) {
1047 : : struct vring_packed_desc *desc;
1048 : 0 : desc = vq->vq_packed.ring.desc;
1049 : 0 : pmc->addr = &desc[vq->vq_used_cons_idx].flags;
1050 [ # # ]: 0 : if (vq->vq_packed.used_wrap_counter)
1051 : 0 : pmc->opaque[CLB_VAL_IDX] =
1052 : : VRING_PACKED_DESC_F_AVAIL_USED;
1053 : : else
1054 : 0 : pmc->opaque[CLB_VAL_IDX] = 0;
1055 : 0 : pmc->opaque[CLB_MSK_IDX] = VRING_PACKED_DESC_F_AVAIL_USED;
1056 : 0 : pmc->opaque[CLB_MATCH_IDX] = 1;
1057 : 0 : pmc->size = sizeof(desc[vq->vq_used_cons_idx].flags);
1058 : : } else {
1059 : 0 : pmc->addr = &vq->vq_split.ring.used->idx;
1060 : 0 : pmc->opaque[CLB_VAL_IDX] = vq->vq_used_cons_idx
1061 : 0 : & (vq->vq_nentries - 1);
1062 : 0 : pmc->opaque[CLB_MSK_IDX] = vq->vq_nentries - 1;
1063 : 0 : pmc->opaque[CLB_MATCH_IDX] = 0;
1064 : 0 : pmc->size = sizeof(vq->vq_split.ring.used->idx);
1065 : : }
1066 : 0 : pmc->fn = virtio_monitor_callback;
1067 : :
1068 : 0 : return 0;
1069 : : }
1070 : :
1071 : : static int
1072 : 0 : virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
1073 : : {
1074 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
1075 : : struct virtio_pmd_ctrl ctrl;
1076 : : int len;
1077 : :
1078 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN))
1079 : : return -ENOTSUP;
1080 : :
1081 : 0 : ctrl.hdr.class = VIRTIO_NET_CTRL_VLAN;
1082 : 0 : ctrl.hdr.cmd = on ? VIRTIO_NET_CTRL_VLAN_ADD : VIRTIO_NET_CTRL_VLAN_DEL;
1083 : : memcpy(ctrl.data, &vlan_id, sizeof(vlan_id));
1084 : 0 : len = sizeof(vlan_id);
1085 : :
1086 : 0 : return virtio_send_command(hw->cvq, &ctrl, &len, 1);
1087 : : }
1088 : :
1089 : : static int
1090 : 0 : virtio_intr_unmask(struct rte_eth_dev *dev)
1091 : : {
1092 : 0 : struct virtio_hw *hw = dev->data->dev_private;
1093 : :
1094 [ # # ]: 0 : if (rte_intr_ack(dev->intr_handle) < 0)
1095 : : return -1;
1096 : :
1097 [ # # ]: 0 : if (VIRTIO_OPS(hw)->intr_detect)
1098 : 0 : VIRTIO_OPS(hw)->intr_detect(hw);
1099 : :
1100 : : return 0;
1101 : : }
1102 : :
1103 : : static int
1104 : 0 : virtio_intr_enable(struct rte_eth_dev *dev)
1105 : : {
1106 : 0 : struct virtio_hw *hw = dev->data->dev_private;
1107 : :
1108 [ # # ]: 0 : if (rte_intr_enable(dev->intr_handle) < 0)
1109 : : return -1;
1110 : :
1111 [ # # ]: 0 : if (VIRTIO_OPS(hw)->intr_detect)
1112 : 0 : VIRTIO_OPS(hw)->intr_detect(hw);
1113 : :
1114 : : return 0;
1115 : : }
1116 : :
1117 : : static int
1118 : 0 : virtio_intr_disable(struct rte_eth_dev *dev)
1119 : : {
1120 : 0 : struct virtio_hw *hw = dev->data->dev_private;
1121 : :
1122 [ # # ]: 0 : if (rte_intr_disable(dev->intr_handle) < 0)
1123 : : return -1;
1124 : :
1125 [ # # ]: 0 : if (VIRTIO_OPS(hw)->intr_detect)
1126 : 0 : VIRTIO_OPS(hw)->intr_detect(hw);
1127 : :
1128 : : return 0;
1129 : : }
1130 : :
1131 : : static int
1132 : 0 : virtio_ethdev_negotiate_features(struct virtio_hw *hw, uint64_t req_features)
1133 : : {
1134 : : uint64_t host_features;
1135 : :
1136 : : /* Prepare guest_features: feature that driver wants to support */
1137 : 0 : PMD_INIT_LOG(DEBUG, "guest_features before negotiate = %" PRIx64,
1138 : : req_features);
1139 : :
1140 : : /* Read device(host) feature bits */
1141 : 0 : host_features = VIRTIO_OPS(hw)->get_features(hw);
1142 : 0 : PMD_INIT_LOG(DEBUG, "host_features before negotiate = %" PRIx64,
1143 : : host_features);
1144 : :
1145 : : /* If supported, ensure MTU value is valid before acknowledging it. */
1146 [ # # ]: 0 : if (host_features & req_features & (1ULL << VIRTIO_NET_F_MTU)) {
1147 : : struct virtio_net_config config;
1148 : :
1149 : 0 : virtio_read_dev_config(hw,
1150 : : offsetof(struct virtio_net_config, mtu),
1151 : : &config.mtu, sizeof(config.mtu));
1152 : :
1153 [ # # ]: 0 : if (config.mtu < RTE_ETHER_MIN_MTU)
1154 : 0 : req_features &= ~(1ULL << VIRTIO_NET_F_MTU);
1155 : : }
1156 : :
1157 : : /*
1158 : : * Negotiate features: Subset of device feature bits are written back
1159 : : * guest feature bits.
1160 : : */
1161 : 0 : hw->guest_features = req_features;
1162 : 0 : hw->guest_features = virtio_negotiate_features(hw, host_features);
1163 : 0 : PMD_INIT_LOG(DEBUG, "features after negotiate = %" PRIx64,
1164 : : hw->guest_features);
1165 : :
1166 [ # # ]: 0 : if (VIRTIO_OPS(hw)->features_ok(hw) < 0)
1167 : : return -1;
1168 : :
1169 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_F_VERSION_1)) {
1170 : 0 : virtio_set_status(hw, VIRTIO_CONFIG_STATUS_FEATURES_OK);
1171 : :
1172 [ # # ]: 0 : if (!(virtio_get_status(hw) & VIRTIO_CONFIG_STATUS_FEATURES_OK)) {
1173 : 0 : PMD_INIT_LOG(ERR, "Failed to set FEATURES_OK status!");
1174 : 0 : return -1;
1175 : : }
1176 : : }
1177 : :
1178 : 0 : hw->req_guest_features = req_features;
1179 : :
1180 : 0 : return 0;
1181 : : }
1182 : :
1183 : : static void
1184 : 0 : virtio_notify_peers(struct rte_eth_dev *dev)
1185 : : {
1186 : 0 : struct virtio_hw *hw = dev->data->dev_private;
1187 : : struct virtnet_rx *rxvq;
1188 : : struct rte_mbuf *rarp_mbuf;
1189 : :
1190 [ # # ]: 0 : if (!dev->data->rx_queues)
1191 : 0 : return;
1192 : :
1193 : 0 : rxvq = dev->data->rx_queues[0];
1194 [ # # ]: 0 : if (!rxvq)
1195 : : return;
1196 : :
1197 : 0 : rarp_mbuf = rte_net_make_rarp_packet(rxvq->mpool,
1198 : 0 : (struct rte_ether_addr *)hw->mac_addr);
1199 [ # # ]: 0 : if (rarp_mbuf == NULL) {
1200 : 0 : PMD_DRV_LOG(ERR, "failed to make RARP packet.");
1201 : 0 : return;
1202 : : }
1203 : :
1204 : 0 : rte_spinlock_lock(&hw->state_lock);
1205 [ # # ]: 0 : if (hw->started == 0) {
1206 : : /* If virtio port just stopped, no need to send RARP */
1207 : 0 : rte_pktmbuf_free(rarp_mbuf);
1208 : 0 : goto out;
1209 : : }
1210 : 0 : hw->started = 0;
1211 : :
1212 : : /*
1213 : : * Prevent the worker threads from touching queues to avoid contention,
1214 : : * 1 ms should be enough for the ongoing Tx function to finish.
1215 : : */
1216 : : rte_delay_ms(1);
1217 : :
1218 : 0 : hw->inject_pkts = &rarp_mbuf;
1219 : 0 : dev->tx_pkt_burst(dev->data->tx_queues[0], &rarp_mbuf, 1);
1220 : 0 : hw->inject_pkts = NULL;
1221 : :
1222 : 0 : hw->started = 1;
1223 : :
1224 : 0 : out:
1225 : : rte_spinlock_unlock(&hw->state_lock);
1226 : : }
1227 : :
1228 : : static void
1229 : 0 : virtio_ack_link_announce(struct rte_eth_dev *dev)
1230 : : {
1231 : 0 : struct virtio_hw *hw = dev->data->dev_private;
1232 : : struct virtio_pmd_ctrl ctrl;
1233 : :
1234 : 0 : ctrl.hdr.class = VIRTIO_NET_CTRL_ANNOUNCE;
1235 : 0 : ctrl.hdr.cmd = VIRTIO_NET_CTRL_ANNOUNCE_ACK;
1236 : :
1237 : 0 : virtio_send_command(hw->cvq, &ctrl, NULL, 0);
1238 : 0 : }
1239 : :
1240 : : /*
1241 : : * Process virtio config changed interrupt. Call the callback
1242 : : * if link state changed, generate gratuitous RARP packet if
1243 : : * the status indicates an ANNOUNCE.
1244 : : */
1245 : : void
1246 : 0 : virtio_interrupt_handler(void *param)
1247 : : {
1248 : : struct rte_eth_dev *dev = param;
1249 : 0 : struct virtio_hw *hw = dev->data->dev_private;
1250 : : uint8_t isr;
1251 : : uint16_t status;
1252 : :
1253 : : /* Read interrupt status which clears interrupt */
1254 : 0 : isr = virtio_get_isr(hw);
1255 : 0 : PMD_DRV_LOG(INFO, "interrupt status = %#x", isr);
1256 : :
1257 [ # # ]: 0 : if (virtio_intr_unmask(dev) < 0)
1258 : 0 : PMD_DRV_LOG(ERR, "interrupt enable failed");
1259 : :
1260 [ # # ]: 0 : if (isr & VIRTIO_ISR_CONFIG) {
1261 [ # # ]: 0 : if (virtio_dev_link_update(dev, 0) == 0)
1262 : 0 : rte_eth_dev_callback_process(dev,
1263 : : RTE_ETH_EVENT_INTR_LSC,
1264 : : NULL);
1265 : :
1266 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_STATUS)) {
1267 : 0 : virtio_read_dev_config(hw,
1268 : : offsetof(struct virtio_net_config, status),
1269 : : &status, sizeof(status));
1270 [ # # ]: 0 : if (status & VIRTIO_NET_S_ANNOUNCE) {
1271 : 0 : virtio_notify_peers(dev);
1272 [ # # ]: 0 : if (hw->cvq)
1273 : 0 : virtio_ack_link_announce(dev);
1274 : : }
1275 : : }
1276 : : }
1277 : 0 : }
1278 : :
1279 : : static const struct {
1280 : : eth_tx_burst_t pkt_burst;
1281 : : const char *info;
1282 : : } virtio_tx_burst_info[] = {
1283 : : { virtio_xmit_pkts, "Scalar"},
1284 : : { virtio_xmit_pkts_packed, "Scalar packed ring"},
1285 : : { virtio_xmit_pkts_inorder, "Scalar in order"},
1286 : : { virtio_xmit_pkts_packed_vec, "Vector packed ring"},
1287 : : };
1288 : :
1289 : : static int
1290 : 0 : virtio_tx_burst_mode_get(struct rte_eth_dev *dev,
1291 : : __rte_unused uint16_t queue_id,
1292 : : struct rte_eth_burst_mode *mode)
1293 : : {
1294 : 0 : eth_tx_burst_t pkt_burst = dev->tx_pkt_burst;
1295 : : size_t i;
1296 : :
1297 [ # # ]: 0 : for (i = 0; i < RTE_DIM(virtio_tx_burst_info); i++) {
1298 [ # # ]: 0 : if (pkt_burst == virtio_tx_burst_info[i].pkt_burst) {
1299 : 0 : snprintf(mode->info, sizeof(mode->info), "%s",
1300 : 0 : virtio_tx_burst_info[i].info);
1301 : 0 : return 0;
1302 : : }
1303 : : }
1304 : :
1305 : : return -EINVAL;
1306 : : }
1307 : :
1308 : : static const struct {
1309 : : eth_rx_burst_t pkt_burst;
1310 : : const char *info;
1311 : : } virtio_rx_burst_info[] = {
1312 : : { virtio_recv_pkts, "Scalar"},
1313 : : { virtio_recv_pkts_packed, "Scalar standard packed ring"},
1314 : : { virtio_recv_pkts_inorder, "Scalar"},
1315 : : { virtio_recv_mergeable_pkts, "Scalar mergeable"},
1316 : : { virtio_recv_mergeable_pkts_packed, "Scalar mergeable packed ring"},
1317 : : #ifdef RTE_ARCH_x86
1318 : : { virtio_recv_pkts_vec, "Vector SSE"},
1319 : : { virtio_recv_pkts_packed_vec, "Vector AVX512 packed ring"},
1320 : : #elif defined(RTE_ARCH_ARM)
1321 : : { virtio_recv_pkts_vec, "Vector NEON"},
1322 : : { virtio_recv_pkts_packed_vec, "Vector NEON packed ring"},
1323 : : #elif defined(RTE_ARCH_PPC_64)
1324 : : { virtio_recv_pkts_vec, "Vector Altivec"},
1325 : : { virtio_recv_pkts_packed_vec, "Vector Altivec packed ring"},
1326 : : #endif
1327 : : };
1328 : :
1329 : : static int
1330 : 0 : virtio_rx_burst_mode_get(struct rte_eth_dev *dev,
1331 : : __rte_unused uint16_t queue_id,
1332 : : struct rte_eth_burst_mode *mode)
1333 : : {
1334 : 0 : eth_tx_burst_t pkt_burst = dev->rx_pkt_burst;
1335 : : size_t i;
1336 : :
1337 [ # # ]: 0 : for (i = 0; i < RTE_DIM(virtio_rx_burst_info); i++) {
1338 [ # # ]: 0 : if (pkt_burst == virtio_rx_burst_info[i].pkt_burst) {
1339 : 0 : snprintf(mode->info, sizeof(mode->info), "%s",
1340 : 0 : virtio_rx_burst_info[i].info);
1341 : 0 : return 0;
1342 : : }
1343 : : }
1344 : :
1345 : : return -EINVAL;
1346 : : }
1347 : :
1348 : : /* set rx and tx handlers according to what is supported */
1349 : : static void
1350 : 0 : set_rxtx_funcs(struct rte_eth_dev *eth_dev)
1351 : : {
1352 : 0 : struct virtio_hw *hw = eth_dev->data->dev_private;
1353 : :
1354 [ # # ]: 0 : eth_dev->tx_pkt_prepare = virtio_xmit_pkts_prepare;
1355 [ # # ]: 0 : if (virtio_with_packed_queue(hw)) {
1356 [ # # ]: 0 : PMD_INIT_LOG(INFO,
1357 : : "virtio: using packed ring %s Tx path on port %u",
1358 : : hw->use_vec_tx ? "vectorized" : "standard",
1359 : : eth_dev->data->port_id);
1360 [ # # ]: 0 : if (hw->use_vec_tx)
1361 : 0 : eth_dev->tx_pkt_burst = virtio_xmit_pkts_packed_vec;
1362 : : else
1363 : 0 : eth_dev->tx_pkt_burst = virtio_xmit_pkts_packed;
1364 : : } else {
1365 [ # # ]: 0 : if (hw->use_inorder_tx) {
1366 : 0 : PMD_INIT_LOG(INFO, "virtio: using inorder Tx path on port %u",
1367 : : eth_dev->data->port_id);
1368 : 0 : eth_dev->tx_pkt_burst = virtio_xmit_pkts_inorder;
1369 : : } else {
1370 : 0 : PMD_INIT_LOG(INFO, "virtio: using standard Tx path on port %u",
1371 : : eth_dev->data->port_id);
1372 : 0 : eth_dev->tx_pkt_burst = virtio_xmit_pkts;
1373 : : }
1374 : : }
1375 : :
1376 [ # # ]: 0 : if (virtio_with_packed_queue(hw)) {
1377 [ # # ]: 0 : if (hw->use_vec_rx) {
1378 : 0 : PMD_INIT_LOG(INFO,
1379 : : "virtio: using packed ring vectorized Rx path on port %u",
1380 : : eth_dev->data->port_id);
1381 : 0 : eth_dev->rx_pkt_burst =
1382 : : &virtio_recv_pkts_packed_vec;
1383 [ # # ]: 0 : } else if (virtio_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
1384 : 0 : PMD_INIT_LOG(INFO,
1385 : : "virtio: using packed ring mergeable buffer Rx path on port %u",
1386 : : eth_dev->data->port_id);
1387 : 0 : eth_dev->rx_pkt_burst =
1388 : : &virtio_recv_mergeable_pkts_packed;
1389 : : } else {
1390 : 0 : PMD_INIT_LOG(INFO,
1391 : : "virtio: using packed ring standard Rx path on port %u",
1392 : : eth_dev->data->port_id);
1393 : 0 : eth_dev->rx_pkt_burst = &virtio_recv_pkts_packed;
1394 : : }
1395 : : } else {
1396 [ # # ]: 0 : if (hw->use_vec_rx) {
1397 : 0 : PMD_INIT_LOG(INFO, "virtio: using vectorized Rx path on port %u",
1398 : : eth_dev->data->port_id);
1399 : 0 : eth_dev->rx_pkt_burst = virtio_recv_pkts_vec;
1400 [ # # ]: 0 : } else if (hw->use_inorder_rx) {
1401 : 0 : PMD_INIT_LOG(INFO,
1402 : : "virtio: using inorder Rx path on port %u",
1403 : : eth_dev->data->port_id);
1404 : 0 : eth_dev->rx_pkt_burst = &virtio_recv_pkts_inorder;
1405 [ # # ]: 0 : } else if (virtio_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
1406 : 0 : PMD_INIT_LOG(INFO,
1407 : : "virtio: using mergeable buffer Rx path on port %u",
1408 : : eth_dev->data->port_id);
1409 : 0 : eth_dev->rx_pkt_burst = &virtio_recv_mergeable_pkts;
1410 : : } else {
1411 : 0 : PMD_INIT_LOG(INFO, "virtio: using standard Rx path on port %u",
1412 : : eth_dev->data->port_id);
1413 : 0 : eth_dev->rx_pkt_burst = &virtio_recv_pkts;
1414 : : }
1415 : : }
1416 : :
1417 : 0 : }
1418 : :
1419 : : /* Only support 1:1 queue/interrupt mapping so far.
1420 : : * TODO: support n:1 queue/interrupt mapping when there are limited number of
1421 : : * interrupt vectors (<N+1).
1422 : : */
1423 : : static int
1424 : 0 : virtio_queues_bind_intr(struct rte_eth_dev *dev)
1425 : : {
1426 : : uint32_t i;
1427 : 0 : struct virtio_hw *hw = dev->data->dev_private;
1428 : :
1429 : 0 : PMD_INIT_LOG(INFO, "queue/interrupt binding");
1430 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; ++i) {
1431 [ # # ]: 0 : if (rte_intr_vec_list_index_set(dev->intr_handle, i,
1432 : 0 : i + 1))
1433 : 0 : return -rte_errno;
1434 [ # # ]: 0 : if (VIRTIO_OPS(hw)->set_queue_irq(hw, hw->vqs[i * 2], i + 1) ==
1435 : : VIRTIO_MSI_NO_VECTOR) {
1436 : 0 : PMD_DRV_LOG(ERR, "failed to set queue vector");
1437 : 0 : return -EBUSY;
1438 : : }
1439 : : }
1440 : :
1441 : : return 0;
1442 : : }
1443 : :
1444 : : static void
1445 : 0 : virtio_queues_unbind_intr(struct rte_eth_dev *dev)
1446 : : {
1447 : : uint32_t i;
1448 : 0 : struct virtio_hw *hw = dev->data->dev_private;
1449 : :
1450 : 0 : PMD_INIT_LOG(INFO, "queue/interrupt unbinding");
1451 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; ++i)
1452 : 0 : VIRTIO_OPS(hw)->set_queue_irq(hw,
1453 : 0 : hw->vqs[i * VTNET_CQ],
1454 : : VIRTIO_MSI_NO_VECTOR);
1455 : 0 : }
1456 : :
1457 : : static int
1458 : 0 : virtio_configure_intr(struct rte_eth_dev *dev)
1459 : : {
1460 : 0 : struct virtio_hw *hw = dev->data->dev_private;
1461 : : int ret;
1462 : :
1463 [ # # ]: 0 : if (!rte_intr_cap_multiple(dev->intr_handle)) {
1464 : 0 : PMD_INIT_LOG(ERR, "Multiple intr vector not supported");
1465 : 0 : return -ENOTSUP;
1466 : : }
1467 : :
1468 : 0 : ret = rte_intr_efd_enable(dev->intr_handle, dev->data->nb_rx_queues);
1469 [ # # ]: 0 : if (ret < 0) {
1470 : 0 : PMD_INIT_LOG(ERR, "Fail to create eventfd");
1471 : 0 : return ret;
1472 : : }
1473 : :
1474 : 0 : ret = rte_intr_vec_list_alloc(dev->intr_handle, "intr_vec",
1475 : 0 : hw->max_queue_pairs);
1476 [ # # ]: 0 : if (ret < 0) {
1477 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate %u rxq vectors",
1478 : : hw->max_queue_pairs);
1479 : 0 : return ret;
1480 : : }
1481 : :
1482 [ # # ]: 0 : if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) {
1483 : : /* Re-register callback to update max_intr */
1484 : 0 : rte_intr_callback_unregister(dev->intr_handle,
1485 : : virtio_interrupt_handler,
1486 : : dev);
1487 : 0 : rte_intr_callback_register(dev->intr_handle,
1488 : : virtio_interrupt_handler,
1489 : : dev);
1490 : : }
1491 : :
1492 : : /* DO NOT try to remove this! This function will enable msix, or QEMU
1493 : : * will encounter SIGSEGV when DRIVER_OK is sent.
1494 : : * And for legacy devices, this should be done before queue/vec binding
1495 : : * to change the config size from 20 to 24, or VIRTIO_MSI_QUEUE_VECTOR
1496 : : * (22) will be ignored.
1497 : : */
1498 [ # # ]: 0 : if (virtio_intr_enable(dev) < 0) {
1499 : 0 : PMD_DRV_LOG(ERR, "interrupt enable failed");
1500 : 0 : return -EINVAL;
1501 : : }
1502 : :
1503 : 0 : ret = virtio_queues_bind_intr(dev);
1504 [ # # ]: 0 : if (ret < 0) {
1505 : 0 : PMD_INIT_LOG(ERR, "Failed to bind queue/interrupt");
1506 : 0 : return ret;
1507 : : }
1508 : :
1509 : : return 0;
1510 : : }
1511 : :
1512 : : static void
1513 : 0 : virtio_get_speed_duplex(struct rte_eth_dev *eth_dev,
1514 : : struct rte_eth_link *link)
1515 : : {
1516 : 0 : struct virtio_hw *hw = eth_dev->data->dev_private;
1517 : : struct virtio_net_config *config;
1518 : : struct virtio_net_config local_config;
1519 : :
1520 : : config = &local_config;
1521 : 0 : virtio_read_dev_config(hw,
1522 : : offsetof(struct virtio_net_config, speed),
1523 : : &config->speed, sizeof(config->speed));
1524 : 0 : virtio_read_dev_config(hw,
1525 : : offsetof(struct virtio_net_config, duplex),
1526 : : &config->duplex, sizeof(config->duplex));
1527 : 0 : hw->speed = config->speed;
1528 : 0 : hw->duplex = config->duplex;
1529 [ # # ]: 0 : if (link != NULL) {
1530 : 0 : link->link_duplex = hw->duplex;
1531 : 0 : link->link_speed = hw->speed;
1532 : : }
1533 : 0 : PMD_INIT_LOG(DEBUG, "link speed = %d, duplex = %d",
1534 : : hw->speed, hw->duplex);
1535 : 0 : }
1536 : :
1537 : : static uint64_t
1538 : 0 : ethdev_to_virtio_rss_offloads(uint64_t ethdev_hash_types)
1539 : : {
1540 : : uint64_t virtio_hash_types = 0;
1541 : :
1542 [ # # ]: 0 : if (ethdev_hash_types & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
1543 : : RTE_ETH_RSS_NONFRAG_IPV4_OTHER))
1544 : : virtio_hash_types |= VIRTIO_NET_HASH_TYPE_IPV4;
1545 : :
1546 [ # # ]: 0 : if (ethdev_hash_types & RTE_ETH_RSS_NONFRAG_IPV4_TCP)
1547 : 0 : virtio_hash_types |= VIRTIO_NET_HASH_TYPE_TCPV4;
1548 : :
1549 [ # # ]: 0 : if (ethdev_hash_types & RTE_ETH_RSS_NONFRAG_IPV4_UDP)
1550 : 0 : virtio_hash_types |= VIRTIO_NET_HASH_TYPE_UDPV4;
1551 : :
1552 [ # # ]: 0 : if (ethdev_hash_types & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
1553 : : RTE_ETH_RSS_NONFRAG_IPV6_OTHER))
1554 : 0 : virtio_hash_types |= VIRTIO_NET_HASH_TYPE_IPV6;
1555 : :
1556 [ # # ]: 0 : if (ethdev_hash_types & RTE_ETH_RSS_NONFRAG_IPV6_TCP)
1557 : 0 : virtio_hash_types |= VIRTIO_NET_HASH_TYPE_TCPV6;
1558 : :
1559 [ # # ]: 0 : if (ethdev_hash_types & RTE_ETH_RSS_NONFRAG_IPV6_UDP)
1560 : 0 : virtio_hash_types |= VIRTIO_NET_HASH_TYPE_UDPV6;
1561 : :
1562 [ # # ]: 0 : if (ethdev_hash_types & RTE_ETH_RSS_IPV6_EX)
1563 : 0 : virtio_hash_types |= VIRTIO_NET_HASH_TYPE_IP_EX;
1564 : :
1565 [ # # ]: 0 : if (ethdev_hash_types & RTE_ETH_RSS_IPV6_TCP_EX)
1566 : 0 : virtio_hash_types |= VIRTIO_NET_HASH_TYPE_TCP_EX;
1567 : :
1568 [ # # ]: 0 : if (ethdev_hash_types & RTE_ETH_RSS_IPV6_UDP_EX)
1569 : 0 : virtio_hash_types |= VIRTIO_NET_HASH_TYPE_UDP_EX;
1570 : :
1571 : 0 : return virtio_hash_types;
1572 : : }
1573 : :
1574 : : static uint64_t
1575 : 0 : virtio_to_ethdev_rss_offloads(uint64_t virtio_hash_types)
1576 : : {
1577 : : uint64_t rss_offloads = 0;
1578 : :
1579 [ # # ]: 0 : if (virtio_hash_types & VIRTIO_NET_HASH_TYPE_IPV4)
1580 : : rss_offloads |= RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
1581 : : RTE_ETH_RSS_NONFRAG_IPV4_OTHER;
1582 : :
1583 [ # # ]: 0 : if (virtio_hash_types & VIRTIO_NET_HASH_TYPE_TCPV4)
1584 : 0 : rss_offloads |= RTE_ETH_RSS_NONFRAG_IPV4_TCP;
1585 : :
1586 [ # # ]: 0 : if (virtio_hash_types & VIRTIO_NET_HASH_TYPE_UDPV4)
1587 : 0 : rss_offloads |= RTE_ETH_RSS_NONFRAG_IPV4_UDP;
1588 : :
1589 [ # # ]: 0 : if (virtio_hash_types & VIRTIO_NET_HASH_TYPE_IPV6)
1590 : 0 : rss_offloads |= RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
1591 : : RTE_ETH_RSS_NONFRAG_IPV6_OTHER;
1592 : :
1593 [ # # ]: 0 : if (virtio_hash_types & VIRTIO_NET_HASH_TYPE_TCPV6)
1594 : 0 : rss_offloads |= RTE_ETH_RSS_NONFRAG_IPV6_TCP;
1595 : :
1596 [ # # ]: 0 : if (virtio_hash_types & VIRTIO_NET_HASH_TYPE_UDPV6)
1597 : 0 : rss_offloads |= RTE_ETH_RSS_NONFRAG_IPV6_UDP;
1598 : :
1599 [ # # ]: 0 : if (virtio_hash_types & VIRTIO_NET_HASH_TYPE_IP_EX)
1600 : 0 : rss_offloads |= RTE_ETH_RSS_IPV6_EX;
1601 : :
1602 [ # # ]: 0 : if (virtio_hash_types & VIRTIO_NET_HASH_TYPE_TCP_EX)
1603 : 0 : rss_offloads |= RTE_ETH_RSS_IPV6_TCP_EX;
1604 : :
1605 [ # # ]: 0 : if (virtio_hash_types & VIRTIO_NET_HASH_TYPE_UDP_EX)
1606 : 0 : rss_offloads |= RTE_ETH_RSS_IPV6_UDP_EX;
1607 : :
1608 : 0 : return rss_offloads;
1609 : : }
1610 : :
1611 : : static int
1612 : 0 : virtio_dev_get_rss_config(struct virtio_hw *hw, uint32_t *rss_hash_types)
1613 : : {
1614 : : struct virtio_net_config local_config;
1615 : : struct virtio_net_config *config = &local_config;
1616 : :
1617 : 0 : virtio_read_dev_config(hw,
1618 : : offsetof(struct virtio_net_config, rss_max_key_size),
1619 : : &config->rss_max_key_size,
1620 : : sizeof(config->rss_max_key_size));
1621 [ # # ]: 0 : if (config->rss_max_key_size < VIRTIO_NET_RSS_KEY_SIZE) {
1622 : 0 : PMD_INIT_LOG(ERR, "Invalid device RSS max key size (%u)",
1623 : : config->rss_max_key_size);
1624 : 0 : return -EINVAL;
1625 : : }
1626 : :
1627 : 0 : virtio_read_dev_config(hw,
1628 : : offsetof(struct virtio_net_config,
1629 : : rss_max_indirection_table_length),
1630 : : &config->rss_max_indirection_table_length,
1631 : : sizeof(config->rss_max_indirection_table_length));
1632 [ # # ]: 0 : if (config->rss_max_indirection_table_length < VIRTIO_NET_RSS_RETA_SIZE) {
1633 : 0 : PMD_INIT_LOG(ERR, "Invalid device RSS max reta size (%u)",
1634 : : config->rss_max_indirection_table_length);
1635 : 0 : return -EINVAL;
1636 : : }
1637 : :
1638 : 0 : virtio_read_dev_config(hw,
1639 : : offsetof(struct virtio_net_config, supported_hash_types),
1640 : : &config->supported_hash_types,
1641 : : sizeof(config->supported_hash_types));
1642 [ # # ]: 0 : if ((config->supported_hash_types & VIRTIO_NET_HASH_TYPE_MASK) == 0) {
1643 : 0 : PMD_INIT_LOG(ERR, "Invalid device RSS hash types (0x%x)",
1644 : : config->supported_hash_types);
1645 : 0 : return -EINVAL;
1646 : : }
1647 : :
1648 : 0 : *rss_hash_types = config->supported_hash_types & VIRTIO_NET_HASH_TYPE_MASK;
1649 : :
1650 : 0 : PMD_INIT_LOG(DEBUG, "Device RSS config:");
1651 : 0 : PMD_INIT_LOG(DEBUG, "\t-Max key size: %u", config->rss_max_key_size);
1652 : 0 : PMD_INIT_LOG(DEBUG, "\t-Max reta size: %u", config->rss_max_indirection_table_length);
1653 : 0 : PMD_INIT_LOG(DEBUG, "\t-Supported hash types: 0x%x", *rss_hash_types);
1654 : :
1655 : 0 : return 0;
1656 : : }
1657 : :
1658 : : static int
1659 : 0 : virtio_dev_rss_hash_update(struct rte_eth_dev *dev,
1660 : : struct rte_eth_rss_conf *rss_conf)
1661 : : {
1662 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
1663 : : char old_rss_key[VIRTIO_NET_RSS_KEY_SIZE];
1664 : : uint32_t old_hash_types;
1665 : : uint16_t nb_queues;
1666 : : int ret;
1667 : :
1668 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_RSS))
1669 : : return -ENOTSUP;
1670 : :
1671 [ # # ]: 0 : if (rss_conf->rss_hf & ~virtio_to_ethdev_rss_offloads(VIRTIO_NET_HASH_TYPE_MASK))
1672 : : return -EINVAL;
1673 : :
1674 : 0 : old_hash_types = hw->rss_hash_types;
1675 : 0 : hw->rss_hash_types = ethdev_to_virtio_rss_offloads(rss_conf->rss_hf);
1676 : :
1677 [ # # # # ]: 0 : if (rss_conf->rss_key && rss_conf->rss_key_len) {
1678 [ # # ]: 0 : if (rss_conf->rss_key_len != VIRTIO_NET_RSS_KEY_SIZE) {
1679 : 0 : PMD_INIT_LOG(ERR, "Driver only supports %u RSS key length",
1680 : : VIRTIO_NET_RSS_KEY_SIZE);
1681 : : ret = -EINVAL;
1682 : 0 : goto restore_types;
1683 : : }
1684 : 0 : memcpy(old_rss_key, hw->rss_key, VIRTIO_NET_RSS_KEY_SIZE);
1685 : : memcpy(hw->rss_key, rss_conf->rss_key, VIRTIO_NET_RSS_KEY_SIZE);
1686 : : }
1687 : :
1688 : 0 : nb_queues = RTE_MAX(dev->data->nb_rx_queues, dev->data->nb_tx_queues);
1689 : 0 : ret = virtio_set_multiple_queues_rss(dev, nb_queues);
1690 [ # # ]: 0 : if (ret < 0) {
1691 : 0 : PMD_INIT_LOG(ERR, "Failed to apply new RSS config to the device");
1692 : 0 : goto restore_key;
1693 : : }
1694 : :
1695 : : return 0;
1696 : : restore_key:
1697 [ # # # # ]: 0 : if (rss_conf->rss_key && rss_conf->rss_key_len)
1698 : 0 : memcpy(hw->rss_key, old_rss_key, VIRTIO_NET_RSS_KEY_SIZE);
1699 : 0 : restore_types:
1700 : 0 : hw->rss_hash_types = old_hash_types;
1701 : :
1702 : 0 : return ret;
1703 : : }
1704 : :
1705 : : static int
1706 : 0 : virtio_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
1707 : : struct rte_eth_rss_conf *rss_conf)
1708 : : {
1709 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
1710 : :
1711 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_RSS))
1712 : : return -ENOTSUP;
1713 : :
1714 [ # # # # ]: 0 : if (rss_conf->rss_key && rss_conf->rss_key_len >= VIRTIO_NET_RSS_KEY_SIZE)
1715 : 0 : memcpy(rss_conf->rss_key, hw->rss_key, VIRTIO_NET_RSS_KEY_SIZE);
1716 : 0 : rss_conf->rss_key_len = VIRTIO_NET_RSS_KEY_SIZE;
1717 : 0 : rss_conf->rss_hf = virtio_to_ethdev_rss_offloads(hw->rss_hash_types);
1718 : :
1719 : 0 : return 0;
1720 : : }
1721 : :
1722 : 0 : static int virtio_dev_rss_reta_update(struct rte_eth_dev *dev,
1723 : : struct rte_eth_rss_reta_entry64 *reta_conf,
1724 : : uint16_t reta_size)
1725 : : {
1726 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
1727 : : uint16_t nb_queues;
1728 : : uint16_t old_reta[VIRTIO_NET_RSS_RETA_SIZE];
1729 : : int idx, pos, i, ret;
1730 : :
1731 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_RSS))
1732 : : return -ENOTSUP;
1733 : :
1734 [ # # ]: 0 : if (reta_size != VIRTIO_NET_RSS_RETA_SIZE)
1735 : : return -EINVAL;
1736 : :
1737 : 0 : memcpy(old_reta, hw->rss_reta, sizeof(old_reta));
1738 : :
1739 [ # # ]: 0 : for (i = 0; i < reta_size; i++) {
1740 : 0 : idx = i / RTE_ETH_RETA_GROUP_SIZE;
1741 : 0 : pos = i % RTE_ETH_RETA_GROUP_SIZE;
1742 : :
1743 [ # # ]: 0 : if (((reta_conf[idx].mask >> pos) & 0x1) == 0)
1744 : 0 : continue;
1745 : :
1746 : 0 : hw->rss_reta[i] = reta_conf[idx].reta[pos];
1747 : : }
1748 : :
1749 : 0 : nb_queues = RTE_MAX(dev->data->nb_rx_queues, dev->data->nb_tx_queues);
1750 : 0 : ret = virtio_set_multiple_queues_rss(dev, nb_queues);
1751 [ # # ]: 0 : if (ret < 0) {
1752 : 0 : PMD_INIT_LOG(ERR, "Failed to apply new RETA to the device");
1753 : 0 : memcpy(hw->rss_reta, old_reta, sizeof(old_reta));
1754 : : }
1755 : :
1756 : 0 : hw->rss_rx_queues = dev->data->nb_rx_queues;
1757 : :
1758 : 0 : return ret;
1759 : : }
1760 : :
1761 : 0 : static int virtio_dev_rss_reta_query(struct rte_eth_dev *dev,
1762 : : struct rte_eth_rss_reta_entry64 *reta_conf,
1763 : : uint16_t reta_size)
1764 : : {
1765 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
1766 : : int idx, i;
1767 : :
1768 [ # # ]: 0 : if (!virtio_with_feature(hw, VIRTIO_NET_F_RSS))
1769 : : return -ENOTSUP;
1770 : :
1771 [ # # ]: 0 : if (reta_size != VIRTIO_NET_RSS_RETA_SIZE)
1772 : : return -EINVAL;
1773 : :
1774 [ # # ]: 0 : for (i = 0; i < reta_size; i++) {
1775 : 0 : idx = i / RTE_ETH_RETA_GROUP_SIZE;
1776 : 0 : reta_conf[idx].reta[i % RTE_ETH_RETA_GROUP_SIZE] = hw->rss_reta[i];
1777 : : }
1778 : :
1779 : : return 0;
1780 : : }
1781 : :
1782 : : /*
1783 : : * As default RSS hash key, it uses the default key of the
1784 : : * Intel IXGBE devices. It can be updated by the application
1785 : : * with any 40B key value.
1786 : : */
1787 : : static uint8_t rss_intel_key[VIRTIO_NET_RSS_KEY_SIZE] = {
1788 : : 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
1789 : : 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
1790 : : 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
1791 : : 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
1792 : : 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA,
1793 : : };
1794 : :
1795 : : static int
1796 : 0 : virtio_dev_rss_init(struct rte_eth_dev *eth_dev)
1797 : : {
1798 : 0 : struct virtio_hw *hw = eth_dev->data->dev_private;
1799 : 0 : uint16_t nb_rx_queues = eth_dev->data->nb_rx_queues;
1800 : : struct rte_eth_rss_conf *rss_conf;
1801 : : int ret, i;
1802 : :
1803 [ # # ]: 0 : if (!nb_rx_queues) {
1804 : 0 : PMD_INIT_LOG(ERR, "Cannot init RSS if no Rx queues");
1805 : 0 : return -EINVAL;
1806 : : }
1807 : :
1808 : : rss_conf = ð_dev->data->dev_conf.rx_adv_conf.rss_conf;
1809 : :
1810 : 0 : ret = virtio_dev_get_rss_config(hw, &hw->rss_hash_types);
1811 [ # # ]: 0 : if (ret)
1812 : : return ret;
1813 : :
1814 [ # # ]: 0 : if (rss_conf->rss_hf) {
1815 : : /* Ensure requested hash types are supported by the device */
1816 [ # # ]: 0 : if (rss_conf->rss_hf & ~virtio_to_ethdev_rss_offloads(hw->rss_hash_types))
1817 : : return -EINVAL;
1818 : :
1819 : 0 : hw->rss_hash_types = ethdev_to_virtio_rss_offloads(rss_conf->rss_hf);
1820 : : }
1821 : :
1822 [ # # ]: 0 : if (!hw->rss_key) {
1823 : : /* Setup default RSS key if not already setup by the user */
1824 : 0 : hw->rss_key = rte_malloc_socket("rss_key",
1825 : : VIRTIO_NET_RSS_KEY_SIZE, 0,
1826 : 0 : eth_dev->device->numa_node);
1827 [ # # ]: 0 : if (!hw->rss_key) {
1828 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate RSS key");
1829 : 0 : return -ENOMEM;
1830 : : }
1831 : : }
1832 : :
1833 [ # # # # ]: 0 : if (rss_conf->rss_key && rss_conf->rss_key_len) {
1834 [ # # ]: 0 : if (rss_conf->rss_key_len != VIRTIO_NET_RSS_KEY_SIZE) {
1835 : 0 : PMD_INIT_LOG(ERR, "Driver only supports %u RSS key length",
1836 : : VIRTIO_NET_RSS_KEY_SIZE);
1837 : 0 : return -EINVAL;
1838 : : }
1839 : 0 : memcpy(hw->rss_key, rss_conf->rss_key, VIRTIO_NET_RSS_KEY_SIZE);
1840 : : } else {
1841 : 0 : memcpy(hw->rss_key, rss_intel_key, VIRTIO_NET_RSS_KEY_SIZE);
1842 : : }
1843 : :
1844 [ # # ]: 0 : if (!hw->rss_reta) {
1845 : : /* Setup default RSS reta if not already setup by the user */
1846 : 0 : hw->rss_reta = rte_zmalloc_socket("rss_reta",
1847 : : VIRTIO_NET_RSS_RETA_SIZE * sizeof(uint16_t), 0,
1848 : 0 : eth_dev->device->numa_node);
1849 [ # # ]: 0 : if (!hw->rss_reta) {
1850 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate RSS reta");
1851 : 0 : return -ENOMEM;
1852 : : }
1853 : :
1854 : 0 : hw->rss_rx_queues = 0;
1855 : : }
1856 : :
1857 : : /* Re-initialize the RSS reta if the number of RX queues has changed */
1858 [ # # ]: 0 : if (hw->rss_rx_queues != nb_rx_queues) {
1859 [ # # ]: 0 : for (i = 0; i < VIRTIO_NET_RSS_RETA_SIZE; i++)
1860 : 0 : hw->rss_reta[i] = i % nb_rx_queues;
1861 : 0 : hw->rss_rx_queues = nb_rx_queues;
1862 : : }
1863 : :
1864 : : return 0;
1865 : : }
1866 : :
1867 : : #define DUPLEX_UNKNOWN 0xff
1868 : : /* reset device and renegotiate features if needed */
1869 : : static int
1870 : 0 : virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features)
1871 : : {
1872 : 0 : struct virtio_hw *hw = eth_dev->data->dev_private;
1873 : : struct virtio_net_config *config;
1874 : : struct virtio_net_config local_config;
1875 : : int ret;
1876 : :
1877 : : /* Reset the device although not necessary at startup */
1878 : 0 : virtio_reset(hw);
1879 : :
1880 [ # # ]: 0 : if (hw->vqs) {
1881 : 0 : virtio_dev_free_mbufs(eth_dev);
1882 : 0 : virtio_free_queues(hw);
1883 : : }
1884 : :
1885 : : /* Tell the host we've noticed this device. */
1886 : 0 : virtio_set_status(hw, VIRTIO_CONFIG_STATUS_ACK);
1887 : :
1888 : : /* Tell the host we've known how to drive the device. */
1889 : 0 : virtio_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER);
1890 [ # # ]: 0 : if (virtio_ethdev_negotiate_features(hw, req_features) < 0)
1891 : : return -EINVAL;
1892 : :
1893 : 0 : hw->weak_barriers = !virtio_with_feature(hw, VIRTIO_F_ORDER_PLATFORM);
1894 : :
1895 : : /* If host does not support both status and MSI-X then disable LSC */
1896 [ # # # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_STATUS) && hw->intr_lsc)
1897 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
1898 : : else
1899 : 0 : eth_dev->data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC;
1900 : :
1901 : : /* Setting up rx_header size for the device */
1902 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_HASH_REPORT))
1903 : 0 : hw->vtnet_hdr_size = sizeof(struct virtio_net_hdr_hash_report);
1904 [ # # # # ]: 0 : else if (virtio_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF) ||
1905 [ # # ]: 0 : virtio_with_feature(hw, VIRTIO_F_VERSION_1) ||
1906 : : virtio_with_packed_queue(hw))
1907 : 0 : hw->vtnet_hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf);
1908 : : else
1909 : 0 : hw->vtnet_hdr_size = sizeof(struct virtio_net_hdr);
1910 : :
1911 : : /* Copy the permanent MAC address to: virtio_hw */
1912 : 0 : virtio_get_hwaddr(hw);
1913 : 0 : rte_ether_addr_copy((struct rte_ether_addr *)hw->mac_addr,
1914 : 0 : ð_dev->data->mac_addrs[0]);
1915 : 0 : PMD_INIT_LOG(DEBUG,
1916 : : "PORT MAC: " RTE_ETHER_ADDR_PRT_FMT,
1917 : : hw->mac_addr[0], hw->mac_addr[1], hw->mac_addr[2],
1918 : : hw->mac_addr[3], hw->mac_addr[4], hw->mac_addr[5]);
1919 : :
1920 [ # # # # ]: 0 : hw->get_speed_via_feat = hw->speed == RTE_ETH_SPEED_NUM_UNKNOWN &&
1921 : : virtio_with_feature(hw, VIRTIO_NET_F_SPEED_DUPLEX);
1922 [ # # ]: 0 : if (hw->get_speed_via_feat)
1923 : 0 : virtio_get_speed_duplex(eth_dev, NULL);
1924 [ # # ]: 0 : if (hw->duplex == DUPLEX_UNKNOWN)
1925 : 0 : hw->duplex = RTE_ETH_LINK_FULL_DUPLEX;
1926 : 0 : PMD_INIT_LOG(DEBUG, "link speed = %d, duplex = %d",
1927 : : hw->speed, hw->duplex);
1928 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VQ)) {
1929 : : config = &local_config;
1930 : :
1931 : 0 : virtio_read_dev_config(hw,
1932 : : offsetof(struct virtio_net_config, mac),
1933 : : &config->mac, sizeof(config->mac));
1934 : :
1935 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_STATUS)) {
1936 : 0 : virtio_read_dev_config(hw,
1937 : : offsetof(struct virtio_net_config, status),
1938 : : &config->status, sizeof(config->status));
1939 : : } else {
1940 : 0 : PMD_INIT_LOG(DEBUG,
1941 : : "VIRTIO_NET_F_STATUS is not supported");
1942 : 0 : config->status = 0;
1943 : : }
1944 : :
1945 [ # # # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_MQ) ||
1946 : : virtio_with_feature(hw, VIRTIO_NET_F_RSS)) {
1947 : 0 : virtio_read_dev_config(hw,
1948 : : offsetof(struct virtio_net_config, max_virtqueue_pairs),
1949 : : &config->max_virtqueue_pairs,
1950 : : sizeof(config->max_virtqueue_pairs));
1951 : : } else {
1952 : 0 : PMD_INIT_LOG(DEBUG,
1953 : : "Neither VIRTIO_NET_F_MQ nor VIRTIO_NET_F_RSS are supported");
1954 : 0 : config->max_virtqueue_pairs = 1;
1955 : : }
1956 : :
1957 [ # # ]: 0 : hw->max_queue_pairs = config->max_virtqueue_pairs;
1958 : :
1959 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_MTU)) {
1960 : 0 : virtio_read_dev_config(hw,
1961 : : offsetof(struct virtio_net_config, mtu),
1962 : : &config->mtu,
1963 : : sizeof(config->mtu));
1964 : :
1965 : : /*
1966 : : * MTU value has already been checked at negotiation
1967 : : * time, but check again in case it has changed since
1968 : : * then, which should not happen.
1969 : : */
1970 [ # # ]: 0 : if (config->mtu < RTE_ETHER_MIN_MTU) {
1971 : 0 : PMD_INIT_LOG(ERR, "invalid max MTU value (%u)",
1972 : : config->mtu);
1973 : 0 : return -EINVAL;
1974 : : }
1975 : :
1976 : 0 : hw->max_mtu = config->mtu;
1977 : : /* Set initial MTU to maximum one supported by vhost */
1978 : 0 : eth_dev->data->mtu = config->mtu;
1979 : :
1980 : : } else {
1981 : 0 : hw->max_mtu = VIRTIO_MAX_RX_PKTLEN - RTE_ETHER_HDR_LEN -
1982 : 0 : VLAN_TAG_LEN - hw->vtnet_hdr_size;
1983 : : }
1984 : :
1985 [ # # ]: 0 : hw->rss_hash_types = 0;
1986 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_RSS)) {
1987 : 0 : ret = virtio_dev_rss_init(eth_dev);
1988 [ # # ]: 0 : if (ret < 0)
1989 : : return ret;
1990 : : }
1991 : :
1992 : 0 : PMD_INIT_LOG(DEBUG, "config->max_virtqueue_pairs=%d",
1993 : : config->max_virtqueue_pairs);
1994 : 0 : PMD_INIT_LOG(DEBUG, "config->status=%d", config->status);
1995 : 0 : PMD_INIT_LOG(DEBUG,
1996 : : "PORT MAC: " RTE_ETHER_ADDR_PRT_FMT,
1997 : : config->mac[0], config->mac[1],
1998 : : config->mac[2], config->mac[3],
1999 : : config->mac[4], config->mac[5]);
2000 : : } else {
2001 : 0 : PMD_INIT_LOG(DEBUG, "config->max_virtqueue_pairs=1");
2002 : 0 : hw->max_queue_pairs = 1;
2003 : 0 : hw->max_mtu = VIRTIO_MAX_RX_PKTLEN - RTE_ETHER_HDR_LEN -
2004 : 0 : VLAN_TAG_LEN - hw->vtnet_hdr_size;
2005 : : }
2006 : :
2007 : 0 : ret = virtio_alloc_queues(eth_dev);
2008 [ # # ]: 0 : if (ret < 0)
2009 : : return ret;
2010 : :
2011 [ # # ]: 0 : if (eth_dev->data->dev_conf.intr_conf.rxq) {
2012 : 0 : ret = virtio_configure_intr(eth_dev);
2013 [ # # ]: 0 : if (ret < 0) {
2014 : 0 : PMD_INIT_LOG(ERR, "failed to configure interrupt");
2015 : 0 : virtio_free_queues(hw);
2016 : 0 : return ret;
2017 : : }
2018 : : }
2019 : :
2020 [ # # ]: 0 : if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
2021 : : /* Enable vector (0) for Link State Interrupt */
2022 [ # # ]: 0 : if (VIRTIO_OPS(hw)->set_config_irq(hw, 0) ==
2023 : : VIRTIO_MSI_NO_VECTOR) {
2024 : 0 : PMD_DRV_LOG(ERR, "failed to set config vector");
2025 : 0 : return -EBUSY;
2026 : : }
2027 : :
2028 : 0 : virtio_reinit_complete(hw);
2029 : :
2030 : 0 : return 0;
2031 : : }
2032 : :
2033 : : /*
2034 : : * This function is based on probe() function in virtio_pci.c
2035 : : * It returns 0 on success.
2036 : : */
2037 : : int
2038 : 0 : eth_virtio_dev_init(struct rte_eth_dev *eth_dev)
2039 : : {
2040 : 0 : struct virtio_hw *hw = eth_dev->data->dev_private;
2041 : 0 : uint32_t speed = RTE_ETH_SPEED_NUM_UNKNOWN;
2042 : 0 : int vectorized = 0;
2043 : : int ret;
2044 : :
2045 : : if (sizeof(struct virtio_net_hdr_hash_report) > RTE_PKTMBUF_HEADROOM) {
2046 : : PMD_INIT_LOG(ERR,
2047 : : "Not sufficient headroom required = %d, avail = %d",
2048 : : (int)sizeof(struct virtio_net_hdr_mrg_rxbuf),
2049 : : RTE_PKTMBUF_HEADROOM);
2050 : :
2051 : : return -1;
2052 : : }
2053 : :
2054 : 0 : eth_dev->dev_ops = &virtio_eth_dev_ops;
2055 : :
2056 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
2057 : 0 : set_rxtx_funcs(eth_dev);
2058 : 0 : return 0;
2059 : : }
2060 : :
2061 : 0 : ret = virtio_dev_devargs_parse(eth_dev->device->devargs, &speed, &vectorized);
2062 [ # # ]: 0 : if (ret < 0)
2063 : : return ret;
2064 : 0 : hw->speed = speed;
2065 : 0 : hw->duplex = DUPLEX_UNKNOWN;
2066 : :
2067 : : /* Allocate memory for storing MAC addresses */
2068 : 0 : eth_dev->data->mac_addrs = rte_zmalloc("virtio",
2069 : : VIRTIO_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN, 0);
2070 [ # # ]: 0 : if (eth_dev->data->mac_addrs == NULL) {
2071 : 0 : PMD_INIT_LOG(ERR,
2072 : : "Failed to allocate %d bytes needed to store MAC addresses",
2073 : : VIRTIO_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN);
2074 : 0 : return -ENOMEM;
2075 : : }
2076 : :
2077 : : rte_spinlock_init(&hw->state_lock);
2078 : :
2079 [ # # ]: 0 : if (vectorized) {
2080 : 0 : hw->use_vec_rx = 1;
2081 : 0 : hw->use_vec_tx = 1;
2082 : : }
2083 : :
2084 : : /* reset device and negotiate default features */
2085 : 0 : ret = virtio_init_device(eth_dev, VIRTIO_PMD_DEFAULT_GUEST_FEATURES);
2086 [ # # ]: 0 : if (ret < 0)
2087 : 0 : goto err_virtio_init;
2088 : :
2089 [ # # ]: 0 : if (vectorized) {
2090 [ # # ]: 0 : if (!virtio_with_packed_queue(hw)) {
2091 : 0 : hw->use_vec_tx = 0;
2092 : : } else {
2093 : : #if !defined(CC_AVX512_SUPPORT) && !defined(RTE_ARCH_ARM)
2094 : : hw->use_vec_rx = 0;
2095 : : hw->use_vec_tx = 0;
2096 : : PMD_DRV_LOG(INFO,
2097 : : "building environment do not support packed ring vectorized");
2098 : : #endif
2099 : : }
2100 : : }
2101 : :
2102 : 0 : hw->opened = 1;
2103 : :
2104 : 0 : return 0;
2105 : :
2106 : : err_virtio_init:
2107 : 0 : rte_free(eth_dev->data->mac_addrs);
2108 : 0 : eth_dev->data->mac_addrs = NULL;
2109 : 0 : return ret;
2110 : : }
2111 : :
2112 : : static uint32_t
2113 : 0 : virtio_dev_speed_capa_get(uint32_t speed)
2114 : : {
2115 [ # # # # : 0 : switch (speed) {
# # # # #
# # ]
2116 : : case RTE_ETH_SPEED_NUM_10G:
2117 : : return RTE_ETH_LINK_SPEED_10G;
2118 : 0 : case RTE_ETH_SPEED_NUM_20G:
2119 : 0 : return RTE_ETH_LINK_SPEED_20G;
2120 : 0 : case RTE_ETH_SPEED_NUM_25G:
2121 : 0 : return RTE_ETH_LINK_SPEED_25G;
2122 : 0 : case RTE_ETH_SPEED_NUM_40G:
2123 : 0 : return RTE_ETH_LINK_SPEED_40G;
2124 : 0 : case RTE_ETH_SPEED_NUM_50G:
2125 : 0 : return RTE_ETH_LINK_SPEED_50G;
2126 : 0 : case RTE_ETH_SPEED_NUM_56G:
2127 : 0 : return RTE_ETH_LINK_SPEED_56G;
2128 : 0 : case RTE_ETH_SPEED_NUM_100G:
2129 : 0 : return RTE_ETH_LINK_SPEED_100G;
2130 : 0 : case RTE_ETH_SPEED_NUM_200G:
2131 : 0 : return RTE_ETH_LINK_SPEED_200G;
2132 : 0 : case RTE_ETH_SPEED_NUM_400G:
2133 : 0 : return RTE_ETH_LINK_SPEED_400G;
2134 : 0 : case RTE_ETH_SPEED_NUM_800G:
2135 : 0 : return RTE_ETH_LINK_SPEED_800G;
2136 : 0 : default:
2137 : 0 : return 0;
2138 : : }
2139 : : }
2140 : :
2141 : 0 : static int vectorized_check_handler(__rte_unused const char *key,
2142 : : const char *value, void *ret_val)
2143 : : {
2144 [ # # ]: 0 : if (value == NULL || ret_val == NULL)
2145 : : return -EINVAL;
2146 : :
2147 [ # # ]: 0 : if (strcmp(value, "1") == 0)
2148 : 0 : *(int *)ret_val = 1;
2149 : : else
2150 : 0 : *(int *)ret_val = 0;
2151 : :
2152 : : return 0;
2153 : : }
2154 : :
2155 : : #define VIRTIO_ARG_SPEED "speed"
2156 : : #define VIRTIO_ARG_VECTORIZED "vectorized"
2157 : :
2158 : : static int
2159 : 0 : link_speed_handler(const char *key __rte_unused,
2160 : : const char *value, void *ret_val)
2161 : : {
2162 : : uint32_t val;
2163 [ # # ]: 0 : if (!value || !ret_val)
2164 : : return -EINVAL;
2165 : 0 : val = strtoul(value, NULL, 0);
2166 : : /* validate input */
2167 [ # # ]: 0 : if (virtio_dev_speed_capa_get(val) == 0)
2168 : : return -EINVAL;
2169 : 0 : *(uint32_t *)ret_val = val;
2170 : :
2171 : 0 : return 0;
2172 : : }
2173 : :
2174 : :
2175 : : static int
2176 : 0 : virtio_dev_devargs_parse(struct rte_devargs *devargs, uint32_t *speed, int *vectorized)
2177 : : {
2178 : : struct rte_kvargs *kvlist;
2179 : : int ret = 0;
2180 : :
2181 [ # # ]: 0 : if (devargs == NULL)
2182 : : return 0;
2183 : :
2184 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
2185 [ # # ]: 0 : if (kvlist == NULL) {
2186 : 0 : PMD_INIT_LOG(ERR, "error when parsing param");
2187 : 0 : return 0;
2188 : : }
2189 : :
2190 [ # # # # ]: 0 : if (speed && rte_kvargs_count(kvlist, VIRTIO_ARG_SPEED) == 1) {
2191 : 0 : ret = rte_kvargs_process(kvlist,
2192 : : VIRTIO_ARG_SPEED,
2193 : : link_speed_handler, speed);
2194 [ # # ]: 0 : if (ret < 0) {
2195 : 0 : PMD_INIT_LOG(ERR, "Failed to parse %s",
2196 : : VIRTIO_ARG_SPEED);
2197 : 0 : goto exit;
2198 : : }
2199 : : }
2200 : :
2201 [ # # # # ]: 0 : if (vectorized &&
2202 : 0 : rte_kvargs_count(kvlist, VIRTIO_ARG_VECTORIZED) == 1) {
2203 : 0 : ret = rte_kvargs_process(kvlist,
2204 : : VIRTIO_ARG_VECTORIZED,
2205 : : vectorized_check_handler, vectorized);
2206 [ # # ]: 0 : if (ret < 0) {
2207 : 0 : PMD_INIT_LOG(ERR, "Failed to parse %s",
2208 : : VIRTIO_ARG_VECTORIZED);
2209 : 0 : goto exit;
2210 : : }
2211 : : }
2212 : :
2213 : 0 : exit:
2214 : 0 : rte_kvargs_free(kvlist);
2215 : 0 : return ret;
2216 : : }
2217 : :
2218 : : static uint8_t
2219 : : rx_offload_enabled(struct virtio_hw *hw)
2220 : : {
2221 [ # # ]: 0 : return virtio_with_feature(hw, VIRTIO_NET_F_GUEST_CSUM) ||
2222 [ # # # # ]: 0 : virtio_with_feature(hw, VIRTIO_NET_F_GUEST_TSO4) ||
2223 : : virtio_with_feature(hw, VIRTIO_NET_F_GUEST_TSO6);
2224 : : }
2225 : :
2226 : : static uint8_t
2227 : : tx_offload_enabled(struct virtio_hw *hw)
2228 : : {
2229 [ # # ]: 0 : return virtio_with_feature(hw, VIRTIO_NET_F_CSUM) ||
2230 [ # # # # ]: 0 : virtio_with_feature(hw, VIRTIO_NET_F_HOST_TSO4) ||
2231 : : virtio_with_feature(hw, VIRTIO_NET_F_HOST_TSO6);
2232 : : }
2233 : :
2234 : : /*
2235 : : * Configure virtio device
2236 : : * It returns 0 on success.
2237 : : */
2238 : : static int
2239 : 0 : virtio_dev_configure(struct rte_eth_dev *dev)
2240 : : {
2241 : 0 : const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
2242 : : const struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode;
2243 : 0 : struct virtio_hw *hw = dev->data->dev_private;
2244 : 0 : uint32_t ether_hdr_len = RTE_ETHER_HDR_LEN + VLAN_TAG_LEN +
2245 : 0 : hw->vtnet_hdr_size;
2246 : 0 : uint64_t rx_offloads = rxmode->offloads;
2247 : 0 : uint64_t tx_offloads = txmode->offloads;
2248 : : uint64_t req_features;
2249 : : int ret;
2250 : :
2251 : 0 : PMD_INIT_LOG(DEBUG, "configure");
2252 : : req_features = VIRTIO_PMD_DEFAULT_GUEST_FEATURES;
2253 : :
2254 [ # # ]: 0 : if (rxmode->mq_mode != RTE_ETH_MQ_RX_NONE && rxmode->mq_mode != RTE_ETH_MQ_RX_RSS) {
2255 : 0 : PMD_DRV_LOG(ERR,
2256 : : "Unsupported Rx multi queue mode %d",
2257 : : rxmode->mq_mode);
2258 : 0 : return -EINVAL;
2259 : : }
2260 : :
2261 [ # # ]: 0 : if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
2262 : 0 : PMD_DRV_LOG(ERR,
2263 : : "Unsupported Tx multi queue mode %d",
2264 : : txmode->mq_mode);
2265 : 0 : return -EINVAL;
2266 : : }
2267 : :
2268 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.rxq) {
2269 : 0 : ret = virtio_init_device(dev, hw->req_guest_features);
2270 [ # # ]: 0 : if (ret < 0)
2271 : : return ret;
2272 : : }
2273 : :
2274 [ # # ]: 0 : if (rxmode->mq_mode == RTE_ETH_MQ_RX_RSS)
2275 : : req_features |= (1ULL << VIRTIO_NET_F_RSS);
2276 : :
2277 [ # # ]: 0 : if (rxmode->mtu > hw->max_mtu)
2278 : 0 : req_features &= ~(1ULL << VIRTIO_NET_F_MTU);
2279 : :
2280 : 0 : hw->max_rx_pkt_len = ether_hdr_len + rxmode->mtu;
2281 : :
2282 [ # # ]: 0 : if (rx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
2283 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM))
2284 : 0 : req_features |= (1ULL << VIRTIO_NET_F_GUEST_CSUM);
2285 : :
2286 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO)
2287 : 0 : req_features |=
2288 : : (1ULL << VIRTIO_NET_F_GUEST_TSO4) |
2289 : : (1ULL << VIRTIO_NET_F_GUEST_TSO6);
2290 : :
2291 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH)
2292 : 0 : req_features |=
2293 : : (1ULL << VIRTIO_NET_F_HASH_REPORT);
2294 : :
2295 [ # # ]: 0 : if (tx_offloads & (RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
2296 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM))
2297 : 0 : req_features |= (1ULL << VIRTIO_NET_F_CSUM);
2298 : :
2299 [ # # ]: 0 : if (tx_offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO)
2300 : 0 : req_features |=
2301 : : (1ULL << VIRTIO_NET_F_HOST_TSO4) |
2302 : : (1ULL << VIRTIO_NET_F_HOST_TSO6);
2303 : :
2304 : : /* if request features changed, reinit the device */
2305 [ # # ]: 0 : if (req_features != hw->req_guest_features) {
2306 : 0 : ret = virtio_init_device(dev, req_features);
2307 [ # # ]: 0 : if (ret < 0)
2308 : : return ret;
2309 : : }
2310 : :
2311 : : /* if queues are not allocated, reinit the device */
2312 [ # # ]: 0 : if (hw->vqs == NULL) {
2313 : 0 : ret = virtio_init_device(dev, hw->req_guest_features);
2314 [ # # ]: 0 : if (ret < 0)
2315 : : return ret;
2316 : : }
2317 : :
2318 [ # # # # ]: 0 : if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) &&
2319 : : !virtio_with_feature(hw, VIRTIO_NET_F_RSS)) {
2320 : 0 : PMD_DRV_LOG(ERR, "RSS support requested but not supported by the device");
2321 : 0 : return -ENOTSUP;
2322 : : }
2323 : :
2324 [ # # ]: 0 : if ((rx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
2325 [ # # ]: 0 : RTE_ETH_RX_OFFLOAD_TCP_CKSUM)) &&
2326 : : !virtio_with_feature(hw, VIRTIO_NET_F_GUEST_CSUM)) {
2327 : 0 : PMD_DRV_LOG(ERR,
2328 : : "rx checksum not available on this host");
2329 : 0 : return -ENOTSUP;
2330 : : }
2331 : :
2332 [ # # # # ]: 0 : if ((rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) &&
2333 [ # # ]: 0 : (!virtio_with_feature(hw, VIRTIO_NET_F_GUEST_TSO4) ||
2334 : : !virtio_with_feature(hw, VIRTIO_NET_F_GUEST_TSO6))) {
2335 : 0 : PMD_DRV_LOG(ERR,
2336 : : "Large Receive Offload not available on this host");
2337 : 0 : return -ENOTSUP;
2338 : : }
2339 : :
2340 : : /* start control queue */
2341 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VQ))
2342 : 0 : virtio_dev_cq_start(dev);
2343 : :
2344 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
2345 : 0 : hw->vlan_strip = 1;
2346 : :
2347 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH)
2348 : 0 : hw->has_hash_report = 1;
2349 : :
2350 : 0 : hw->rx_ol_scatter = (rx_offloads & RTE_ETH_RX_OFFLOAD_SCATTER);
2351 : :
2352 [ # # # # ]: 0 : if ((rx_offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) &&
2353 : : !virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) {
2354 : 0 : PMD_DRV_LOG(ERR,
2355 : : "vlan filtering not available on this host");
2356 : 0 : return -ENOTSUP;
2357 : : }
2358 : :
2359 [ # # ]: 0 : hw->has_tx_offload = tx_offload_enabled(hw);
2360 [ # # ]: 0 : hw->has_rx_offload = rx_offload_enabled(hw);
2361 : :
2362 [ # # ]: 0 : if (virtio_with_packed_queue(hw)) {
2363 : : #if defined(RTE_ARCH_X86_64) && defined(CC_AVX512_SUPPORT)
2364 [ # # # # ]: 0 : if ((hw->use_vec_rx || hw->use_vec_tx) &&
2365 [ # # ]: 0 : (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) ||
2366 [ # # ]: 0 : !virtio_with_feature(hw, VIRTIO_F_IN_ORDER) ||
2367 [ # # ]: 0 : !virtio_with_feature(hw, VIRTIO_F_VERSION_1) ||
2368 : 0 : rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_512)) {
2369 : 0 : PMD_DRV_LOG(INFO,
2370 : : "disabled packed ring vectorized path for requirements not met");
2371 : 0 : hw->use_vec_rx = 0;
2372 : 0 : hw->use_vec_tx = 0;
2373 : : }
2374 : : #elif defined(RTE_ARCH_ARM)
2375 : : if ((hw->use_vec_rx || hw->use_vec_tx) &&
2376 : : (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON) ||
2377 : : !virtio_with_feature(hw, VIRTIO_F_IN_ORDER) ||
2378 : : !virtio_with_feature(hw, VIRTIO_F_VERSION_1) ||
2379 : : rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_128)) {
2380 : : PMD_DRV_LOG(INFO,
2381 : : "disabled packed ring vectorized path for requirements not met");
2382 : : hw->use_vec_rx = 0;
2383 : : hw->use_vec_tx = 0;
2384 : : }
2385 : : #else
2386 : : hw->use_vec_rx = 0;
2387 : : hw->use_vec_tx = 0;
2388 : : #endif
2389 : :
2390 [ # # ]: 0 : if (hw->use_vec_rx) {
2391 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
2392 : 0 : PMD_DRV_LOG(INFO,
2393 : : "disabled packed ring vectorized rx for mrg_rxbuf enabled");
2394 : 0 : hw->use_vec_rx = 0;
2395 : : }
2396 : :
2397 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) {
2398 : 0 : PMD_DRV_LOG(INFO,
2399 : : "disabled packed ring vectorized rx for TCP_LRO enabled");
2400 : 0 : hw->use_vec_rx = 0;
2401 : : }
2402 : :
2403 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH) {
2404 : 0 : PMD_DRV_LOG(INFO,
2405 : : "disabled packed ring vectorized rx for RSS_HASH enabled");
2406 : 0 : hw->use_vec_rx = 0;
2407 : : }
2408 : : }
2409 : : } else {
2410 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_F_IN_ORDER)) {
2411 : 0 : hw->use_inorder_tx = 1;
2412 : 0 : hw->use_inorder_rx = 1;
2413 : 0 : hw->use_vec_rx = 0;
2414 : : }
2415 : :
2416 [ # # ]: 0 : if (hw->use_vec_rx) {
2417 : : #if defined RTE_ARCH_ARM
2418 : : if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) {
2419 : : PMD_DRV_LOG(INFO,
2420 : : "disabled split ring vectorized path for requirement not met");
2421 : : hw->use_vec_rx = 0;
2422 : : }
2423 : : #endif
2424 [ # # ]: 0 : if (virtio_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
2425 : 0 : PMD_DRV_LOG(INFO,
2426 : : "disabled split ring vectorized rx for mrg_rxbuf enabled");
2427 : 0 : hw->use_vec_rx = 0;
2428 : : }
2429 : :
2430 [ # # ]: 0 : if (rx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
2431 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
2432 : : RTE_ETH_RX_OFFLOAD_TCP_LRO |
2433 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP)) {
2434 : 0 : PMD_DRV_LOG(INFO,
2435 : : "disabled split ring vectorized rx for offloading enabled");
2436 : 0 : hw->use_vec_rx = 0;
2437 : : }
2438 : :
2439 [ # # ]: 0 : if (rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_128) {
2440 : 0 : PMD_DRV_LOG(INFO,
2441 : : "disabled split ring vectorized rx, max SIMD bitwidth too low");
2442 : 0 : hw->use_vec_rx = 0;
2443 : : }
2444 : : }
2445 : : }
2446 : :
2447 : : return 0;
2448 : : }
2449 : :
2450 : :
2451 : : static int
2452 : 0 : virtio_dev_start(struct rte_eth_dev *dev)
2453 : : {
2454 : : uint16_t nb_queues, i;
2455 : : struct virtqueue *vq;
2456 : 0 : struct virtio_hw *hw = dev->data->dev_private;
2457 : : int ret;
2458 : :
2459 : : /* Finish the initialization of the queues */
2460 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
2461 : 0 : ret = virtio_dev_rx_queue_setup_finish(dev, i);
2462 [ # # ]: 0 : if (ret < 0)
2463 : 0 : return ret;
2464 : : }
2465 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
2466 : 0 : ret = virtio_dev_tx_queue_setup_finish(dev, i);
2467 [ # # ]: 0 : if (ret < 0)
2468 : 0 : return ret;
2469 : : }
2470 : :
2471 : : /* check if lsc interrupt feature is enabled */
2472 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.lsc) {
2473 [ # # ]: 0 : if (!(dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)) {
2474 : 0 : PMD_DRV_LOG(ERR, "link status not supported by host");
2475 : 0 : return -ENOTSUP;
2476 : : }
2477 : : }
2478 : :
2479 : : /* Enable uio/vfio intr/eventfd mapping: although we already did that
2480 : : * in device configure, but it could be unmapped when device is
2481 : : * stopped.
2482 : : */
2483 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.lsc ||
2484 : : dev->data->dev_conf.intr_conf.rxq) {
2485 : 0 : virtio_intr_disable(dev);
2486 : :
2487 : : /* Setup interrupt callback */
2488 [ # # ]: 0 : if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
2489 : 0 : rte_intr_callback_register(dev->intr_handle,
2490 : : virtio_interrupt_handler,
2491 : : dev);
2492 : :
2493 [ # # ]: 0 : if (virtio_intr_enable(dev) < 0) {
2494 : 0 : PMD_DRV_LOG(ERR, "interrupt enable failed");
2495 : 0 : return -EIO;
2496 : : }
2497 : : }
2498 : :
2499 : : /*Notify the backend
2500 : : *Otherwise the tap backend might already stop its queue due to fullness.
2501 : : *vhost backend will have no chance to be waked up
2502 : : */
2503 : 0 : nb_queues = RTE_MAX(dev->data->nb_rx_queues, dev->data->nb_tx_queues);
2504 [ # # ]: 0 : if (hw->max_queue_pairs > 1) {
2505 [ # # ]: 0 : if (virtio_set_multiple_queues(dev, nb_queues) != 0)
2506 : : return -EINVAL;
2507 : : }
2508 : :
2509 : 0 : PMD_INIT_LOG(DEBUG, "nb_queues=%u (port=%u)", nb_queues,
2510 : : dev->data->port_id);
2511 : :
2512 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
2513 : 0 : vq = virtnet_rxq_to_vq(dev->data->rx_queues[i]);
2514 : : /* Flush the old packets */
2515 : 0 : virtqueue_rxvq_flush(vq);
2516 : : virtqueue_notify(vq);
2517 : : }
2518 : :
2519 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
2520 : 0 : vq = virtnet_txq_to_vq(dev->data->tx_queues[i]);
2521 : : virtqueue_notify(vq);
2522 : : }
2523 : :
2524 : 0 : PMD_INIT_LOG(DEBUG, "Notified backend at initialization (port=%u)",
2525 : : dev->data->port_id);
2526 : :
2527 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
2528 : : vq = virtnet_rxq_to_vq(dev->data->rx_queues[i]);
2529 : : VIRTQUEUE_DUMP(vq);
2530 : : }
2531 : :
2532 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
2533 : : vq = virtnet_txq_to_vq(dev->data->tx_queues[i]);
2534 : : VIRTQUEUE_DUMP(vq);
2535 : : }
2536 : :
2537 : 0 : set_rxtx_funcs(dev);
2538 : 0 : hw->started = 1;
2539 : :
2540 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
2541 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
2542 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
2543 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
2544 : :
2545 : : /* Initialize Link state */
2546 : 0 : virtio_dev_link_update(dev, 0);
2547 : :
2548 : 0 : return 0;
2549 : : }
2550 : :
2551 : 0 : static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
2552 : : {
2553 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
2554 : : uint16_t nr_vq = virtio_get_nr_vq(hw);
2555 : : const char *type __rte_unused;
2556 : : unsigned int i, mbuf_num = 0;
2557 : : struct virtqueue *vq;
2558 : : struct rte_mbuf *buf;
2559 : : int queue_type;
2560 : :
2561 [ # # ]: 0 : if (hw->vqs == NULL)
2562 : : return;
2563 : :
2564 [ # # ]: 0 : for (i = 0; i < nr_vq; i++) {
2565 : 0 : vq = hw->vqs[i];
2566 [ # # ]: 0 : if (!vq)
2567 : 0 : continue;
2568 : :
2569 [ # # ]: 0 : queue_type = virtio_get_queue_type(hw, i);
2570 : : if (queue_type == VTNET_RQ)
2571 : : type = "rxq";
2572 [ # # ]: 0 : else if (queue_type == VTNET_TQ)
2573 : : type = "txq";
2574 : : else
2575 : 0 : continue;
2576 : :
2577 : 0 : PMD_INIT_LOG(DEBUG,
2578 : : "Before freeing %s[%d] used and unused buf",
2579 : : type, i);
2580 : : VIRTQUEUE_DUMP(vq);
2581 : :
2582 [ # # ]: 0 : while ((buf = virtqueue_detach_unused(vq)) != NULL) {
2583 : 0 : rte_pktmbuf_free(buf);
2584 : 0 : mbuf_num++;
2585 : : }
2586 : :
2587 : 0 : PMD_INIT_LOG(DEBUG,
2588 : : "After freeing %s[%d] used and unused buf",
2589 : : type, i);
2590 : : VIRTQUEUE_DUMP(vq);
2591 : : }
2592 : :
2593 : 0 : PMD_INIT_LOG(DEBUG, "%d mbufs freed", mbuf_num);
2594 : : }
2595 : :
2596 : : static void
2597 : 0 : virtio_tx_completed_cleanup(struct rte_eth_dev *dev)
2598 : : {
2599 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
2600 : : struct virtqueue *vq;
2601 : : int qidx;
2602 : : void (*xmit_cleanup)(struct virtqueue *vq, uint16_t nb_used);
2603 : :
2604 [ # # ]: 0 : if (virtio_with_packed_queue(hw)) {
2605 [ # # ]: 0 : if (hw->use_vec_tx)
2606 : : xmit_cleanup = &virtio_xmit_cleanup_inorder_packed;
2607 [ # # ]: 0 : else if (virtio_with_feature(hw, VIRTIO_F_IN_ORDER))
2608 : : xmit_cleanup = &virtio_xmit_cleanup_inorder_packed;
2609 : : else
2610 : : xmit_cleanup = &virtio_xmit_cleanup_normal_packed;
2611 : : } else {
2612 [ # # ]: 0 : if (hw->use_inorder_tx)
2613 : : xmit_cleanup = &virtio_xmit_cleanup_inorder;
2614 : : else
2615 : : xmit_cleanup = &virtio_xmit_cleanup;
2616 : : }
2617 : :
2618 [ # # ]: 0 : for (qidx = 0; qidx < hw->max_queue_pairs; qidx++) {
2619 : 0 : vq = hw->vqs[2 * qidx + VTNET_SQ_TQ_QUEUE_IDX];
2620 [ # # ]: 0 : if (vq != NULL)
2621 : 0 : xmit_cleanup(vq, virtqueue_nused(vq));
2622 : : }
2623 : 0 : }
2624 : :
2625 : : /*
2626 : : * Stop device: disable interrupt and mark link down
2627 : : */
2628 : : int
2629 : 0 : virtio_dev_stop(struct rte_eth_dev *dev)
2630 : : {
2631 : 0 : struct virtio_hw *hw = dev->data->dev_private;
2632 : : struct rte_eth_link link;
2633 : : struct rte_eth_intr_conf *intr_conf = &dev->data->dev_conf.intr_conf;
2634 : : uint16_t i;
2635 : :
2636 : 0 : PMD_INIT_LOG(DEBUG, "stop");
2637 : 0 : dev->data->dev_started = 0;
2638 : :
2639 : 0 : rte_spinlock_lock(&hw->state_lock);
2640 [ # # ]: 0 : if (!hw->started)
2641 : 0 : goto out_unlock;
2642 : 0 : hw->started = 0;
2643 : :
2644 : 0 : virtio_tx_completed_cleanup(dev);
2645 : :
2646 [ # # ]: 0 : if (intr_conf->lsc || intr_conf->rxq) {
2647 : 0 : virtio_intr_disable(dev);
2648 : :
2649 : : /* Reset interrupt callback */
2650 [ # # ]: 0 : if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) {
2651 : 0 : rte_intr_callback_unregister(dev->intr_handle,
2652 : : virtio_interrupt_handler,
2653 : : dev);
2654 : : }
2655 : : }
2656 : :
2657 : : memset(&link, 0, sizeof(link));
2658 : 0 : rte_eth_linkstatus_set(dev, &link);
2659 : 0 : out_unlock:
2660 : : rte_spinlock_unlock(&hw->state_lock);
2661 : :
2662 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
2663 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
2664 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
2665 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
2666 : :
2667 : 0 : return 0;
2668 : : }
2669 : :
2670 : : static int
2671 : 0 : virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete)
2672 : : {
2673 : : struct rte_eth_link link;
2674 : : uint16_t status;
2675 [ # # ]: 0 : struct virtio_hw *hw = dev->data->dev_private;
2676 : :
2677 : : memset(&link, 0, sizeof(link));
2678 : 0 : link.link_duplex = hw->duplex;
2679 : 0 : link.link_speed = hw->speed;
2680 : 0 : link.link_autoneg = RTE_ETH_LINK_AUTONEG;
2681 : :
2682 [ # # ]: 0 : if (!hw->started) {
2683 : : link.link_status = RTE_ETH_LINK_DOWN;
2684 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_NONE;
2685 [ # # ]: 0 : } else if (virtio_with_feature(hw, VIRTIO_NET_F_STATUS)) {
2686 : 0 : PMD_INIT_LOG(DEBUG, "Get link status from hw");
2687 : 0 : virtio_read_dev_config(hw,
2688 : : offsetof(struct virtio_net_config, status),
2689 : : &status, sizeof(status));
2690 [ # # ]: 0 : if ((status & VIRTIO_NET_S_LINK_UP) == 0) {
2691 : : link.link_status = RTE_ETH_LINK_DOWN;
2692 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_NONE;
2693 : 0 : PMD_INIT_LOG(DEBUG, "Port %d is down",
2694 : : dev->data->port_id);
2695 : : } else {
2696 : 0 : link.link_status = RTE_ETH_LINK_UP;
2697 [ # # ]: 0 : if (hw->get_speed_via_feat)
2698 : 0 : virtio_get_speed_duplex(dev, &link);
2699 : 0 : PMD_INIT_LOG(DEBUG, "Port %d is up",
2700 : : dev->data->port_id);
2701 : : }
2702 : : } else {
2703 : 0 : link.link_status = RTE_ETH_LINK_UP;
2704 [ # # ]: 0 : if (hw->get_speed_via_feat)
2705 : 0 : virtio_get_speed_duplex(dev, &link);
2706 : : }
2707 : :
2708 : 0 : return rte_eth_linkstatus_set(dev, &link);
2709 : : }
2710 : :
2711 : : static int
2712 : 0 : virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
2713 : : {
2714 : 0 : const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
2715 : 0 : struct virtio_hw *hw = dev->data->dev_private;
2716 : 0 : uint64_t offloads = rxmode->offloads;
2717 : :
2718 [ # # ]: 0 : if (mask & RTE_ETH_VLAN_FILTER_MASK) {
2719 [ # # # # ]: 0 : if ((offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) &&
2720 : : !virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) {
2721 : :
2722 : 0 : PMD_DRV_LOG(NOTICE,
2723 : : "vlan filtering not available on this host");
2724 : :
2725 : 0 : return -ENOTSUP;
2726 : : }
2727 : : }
2728 : :
2729 [ # # ]: 0 : if (mask & RTE_ETH_VLAN_STRIP_MASK)
2730 : 0 : hw->vlan_strip = !!(offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP);
2731 : :
2732 : : return 0;
2733 : : }
2734 : :
2735 : : static int
2736 : 0 : virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
2737 : : {
2738 : : uint64_t tso_mask, host_features;
2739 : 0 : uint32_t rss_hash_types = 0;
2740 : 0 : struct virtio_hw *hw = dev->data->dev_private;
2741 : 0 : dev_info->speed_capa = virtio_dev_speed_capa_get(hw->speed);
2742 : :
2743 : 0 : dev_info->max_rx_queues =
2744 : 0 : RTE_MIN(hw->max_queue_pairs, VIRTIO_MAX_RX_QUEUES);
2745 : 0 : dev_info->max_tx_queues =
2746 : : RTE_MIN(hw->max_queue_pairs, VIRTIO_MAX_TX_QUEUES);
2747 : 0 : dev_info->min_rx_bufsize = VIRTIO_MIN_RX_BUFSIZE;
2748 : 0 : dev_info->max_rx_pktlen = VIRTIO_MAX_RX_PKTLEN;
2749 : 0 : dev_info->max_mac_addrs = VIRTIO_MAX_MAC_ADDRS;
2750 : 0 : dev_info->max_mtu = hw->max_mtu;
2751 : :
2752 : 0 : host_features = VIRTIO_OPS(hw)->get_features(hw);
2753 : 0 : dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
2754 [ # # ]: 0 : if (host_features & (1ULL << VIRTIO_NET_F_MRG_RXBUF))
2755 : 0 : dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SCATTER;
2756 [ # # ]: 0 : if (host_features & (1ULL << VIRTIO_NET_F_GUEST_CSUM)) {
2757 : 0 : dev_info->rx_offload_capa |=
2758 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
2759 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM;
2760 : : }
2761 [ # # ]: 0 : if (host_features & (1ULL << VIRTIO_NET_F_CTRL_VLAN))
2762 : 0 : dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
2763 : : tso_mask = (1ULL << VIRTIO_NET_F_GUEST_TSO4) |
2764 : : (1ULL << VIRTIO_NET_F_GUEST_TSO6);
2765 [ # # ]: 0 : if ((host_features & tso_mask) == tso_mask)
2766 : 0 : dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
2767 : :
2768 : 0 : dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
2769 : : RTE_ETH_TX_OFFLOAD_VLAN_INSERT;
2770 [ # # ]: 0 : if (host_features & (1ULL << VIRTIO_NET_F_CSUM)) {
2771 : 0 : dev_info->tx_offload_capa |=
2772 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
2773 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM;
2774 : : }
2775 : : tso_mask = (1ULL << VIRTIO_NET_F_HOST_TSO4) |
2776 : : (1ULL << VIRTIO_NET_F_HOST_TSO6);
2777 [ # # ]: 0 : if ((host_features & tso_mask) == tso_mask)
2778 : 0 : dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_TCP_TSO;
2779 : :
2780 [ # # ]: 0 : if (host_features & (1ULL << VIRTIO_NET_F_RSS)) {
2781 : 0 : virtio_dev_get_rss_config(hw, &rss_hash_types);
2782 : 0 : dev_info->hash_key_size = VIRTIO_NET_RSS_KEY_SIZE;
2783 : 0 : dev_info->reta_size = VIRTIO_NET_RSS_RETA_SIZE;
2784 : 0 : dev_info->flow_type_rss_offloads =
2785 : 0 : virtio_to_ethdev_rss_offloads(rss_hash_types);
2786 : : } else {
2787 : 0 : dev_info->hash_key_size = 0;
2788 : 0 : dev_info->reta_size = 0;
2789 : 0 : dev_info->flow_type_rss_offloads = 0;
2790 : : }
2791 : :
2792 [ # # ]: 0 : if (host_features & (1ULL << VIRTIO_NET_F_HASH_REPORT))
2793 : 0 : dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
2794 : :
2795 [ # # ]: 0 : if (host_features & (1ULL << VIRTIO_F_RING_PACKED)) {
2796 : : /*
2797 : : * According to 2.7 Packed Virtqueues,
2798 : : * 2.7.10.1 Structure Size and Alignment:
2799 : : * The Queue Size value does not have to be a power of 2.
2800 : : */
2801 : 0 : dev_info->rx_desc_lim.nb_max = UINT16_MAX;
2802 : 0 : dev_info->tx_desc_lim.nb_max = UINT16_MAX;
2803 : : } else {
2804 : : /*
2805 : : * According to 2.6 Split Virtqueues:
2806 : : * Queue Size value is always a power of 2. The maximum Queue
2807 : : * Size value is 32768.
2808 : : */
2809 : 0 : dev_info->rx_desc_lim.nb_max = 32768;
2810 : 0 : dev_info->tx_desc_lim.nb_max = 32768;
2811 : : }
2812 : : /*
2813 : : * Actual minimum is not the same for virtqueues of different kinds,
2814 : : * but to avoid tangling the code with separate branches, rely on
2815 : : * default thresholds since desc number must be at least of their size.
2816 : : */
2817 : 0 : dev_info->rx_desc_lim.nb_min = RTE_MAX(DEFAULT_RX_FREE_THRESH,
2818 : : RTE_VIRTIO_VPMD_RX_REARM_THRESH);
2819 : 0 : dev_info->tx_desc_lim.nb_min = DEFAULT_TX_FREE_THRESH;
2820 : 0 : dev_info->rx_desc_lim.nb_align = 1;
2821 : 0 : dev_info->tx_desc_lim.nb_align = 1;
2822 : :
2823 : 0 : return 0;
2824 : : }
2825 : :
2826 : : /*
2827 : : * It enables testpmd to collect per queue stats.
2828 : : */
2829 : : static int
2830 : 0 : virtio_dev_queue_stats_mapping_set(__rte_unused struct rte_eth_dev *eth_dev,
2831 : : __rte_unused uint16_t queue_id, __rte_unused uint8_t stat_idx,
2832 : : __rte_unused uint8_t is_rx)
2833 : : {
2834 : 0 : return 0;
2835 : : }
2836 : :
2837 [ - + ]: 253 : RTE_LOG_REGISTER_SUFFIX(virtio_logtype_init, init, NOTICE);
2838 [ - + ]: 253 : RTE_LOG_REGISTER_SUFFIX(virtio_logtype_driver, driver, NOTICE);
|