Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2018 Microsoft Corp.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <stdio.h>
7 : : #include <stdint.h>
8 : : #include <string.h>
9 : : #include <stdbool.h>
10 : : #include <errno.h>
11 : : #include <unistd.h>
12 : : #include <dirent.h>
13 : : #include <fcntl.h>
14 : : #include <sys/types.h>
15 : : #include <sys/uio.h>
16 : :
17 : : #include <rte_ether.h>
18 : : #include <rte_ethdev.h>
19 : : #include <ethdev_driver.h>
20 : : #include <rte_lcore.h>
21 : : #include <rte_memory.h>
22 : : #include <bus_vmbus_driver.h>
23 : : #include <rte_pci.h>
24 : : #include <bus_pci_driver.h>
25 : : #include <rte_log.h>
26 : : #include <rte_string_fns.h>
27 : : #include <rte_alarm.h>
28 : :
29 : : #include "hn_logs.h"
30 : : #include "hn_var.h"
31 : : #include "hn_nvs.h"
32 : :
33 : : /* Search for VF with matching MAC address, return port id */
34 : 0 : static int hn_vf_match(const struct rte_eth_dev *dev)
35 : : {
36 : 0 : const struct rte_ether_addr *mac = dev->data->mac_addrs;
37 : : int i;
38 : :
39 [ # # ]: 0 : RTE_ETH_FOREACH_DEV(i) {
40 : 0 : const struct rte_eth_dev *vf_dev = &rte_eth_devices[i];
41 : 0 : const struct rte_ether_addr *vf_mac = vf_dev->data->mac_addrs;
42 : :
43 [ # # ]: 0 : if (vf_dev == dev)
44 : 0 : continue;
45 : :
46 [ # # ]: 0 : if (rte_is_same_ether_addr(mac, vf_mac))
47 : 0 : return i;
48 : : }
49 : : return -ENOENT;
50 : : }
51 : :
52 : :
53 : : /*
54 : : * Attach new PCI VF device and return the port_id
55 : : */
56 : 0 : static int hn_vf_attach(struct rte_eth_dev *dev, struct hn_data *hv)
57 : : {
58 : 0 : struct rte_eth_dev_owner owner = { .id = RTE_ETH_DEV_NO_OWNER };
59 : : int port, ret;
60 : :
61 [ # # ]: 0 : if (hv->vf_ctx.vf_attached) {
62 : 0 : PMD_DRV_LOG(ERR, "VF already attached");
63 : 0 : return 0;
64 : : }
65 : :
66 : 0 : port = hn_vf_match(dev);
67 [ # # ]: 0 : if (port < 0) {
68 : 0 : PMD_DRV_LOG(NOTICE, "Couldn't find port for VF");
69 : 0 : return port;
70 : : }
71 : :
72 : 0 : PMD_DRV_LOG(NOTICE, "found matching VF port %d", port);
73 : 0 : ret = rte_eth_dev_owner_get(port, &owner);
74 [ # # ]: 0 : if (ret < 0) {
75 : 0 : PMD_DRV_LOG(ERR, "Can not find owner for port %d", port);
76 : 0 : return ret;
77 : : }
78 : :
79 [ # # ]: 0 : if (owner.id != RTE_ETH_DEV_NO_OWNER) {
80 : 0 : PMD_DRV_LOG(ERR, "Port %u already owned by other device %s",
81 : : port, owner.name);
82 : 0 : return -EBUSY;
83 : : }
84 : :
85 : 0 : ret = rte_eth_dev_owner_set(port, &hv->owner);
86 [ # # ]: 0 : if (ret < 0) {
87 : 0 : PMD_DRV_LOG(ERR, "Can set owner for port %d", port);
88 : 0 : return ret;
89 : : }
90 : :
91 : 0 : PMD_DRV_LOG(DEBUG, "Attach VF device %u", port);
92 : 0 : hv->vf_ctx.vf_attached = true;
93 : 0 : hv->vf_ctx.vf_port = port;
94 : 0 : return 0;
95 : : }
96 : :
97 : : static void hn_vf_remove(struct hn_data *hv);
98 : :
99 : 0 : static void hn_remove_delayed(void *args)
100 : : {
101 : : struct hn_data *hv = args;
102 : 0 : uint16_t port_id = hv->vf_ctx.vf_port;
103 : 0 : struct rte_device *dev = rte_eth_devices[port_id].device;
104 : : int ret;
105 : : bool all_eth_removed;
106 : :
107 : : /* Tell VSP to switch data path to synthetic */
108 : 0 : hn_vf_remove(hv);
109 : :
110 : 0 : PMD_DRV_LOG(NOTICE, "Start to remove port %d", port_id);
111 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
112 : :
113 : : /* Give back ownership */
114 : 0 : ret = rte_eth_dev_owner_unset(port_id, hv->owner.id);
115 [ # # ]: 0 : if (ret)
116 : 0 : PMD_DRV_LOG(ERR, "rte_eth_dev_owner_unset failed ret=%d",
117 : : ret);
118 : 0 : hv->vf_ctx.vf_attached = false;
119 : :
120 : 0 : ret = rte_eth_dev_callback_unregister(port_id, RTE_ETH_EVENT_INTR_RMV,
121 : : hn_eth_rmv_event_callback, hv);
122 [ # # ]: 0 : if (ret)
123 : 0 : PMD_DRV_LOG(ERR,
124 : : "rte_eth_dev_callback_unregister failed ret=%d",
125 : : ret);
126 : :
127 : : /* Detach and release port_id from system */
128 : 0 : ret = rte_eth_dev_stop(port_id);
129 [ # # ]: 0 : if (ret)
130 : 0 : PMD_DRV_LOG(ERR, "rte_eth_dev_stop failed port_id=%u ret=%d",
131 : : port_id, ret);
132 : :
133 : 0 : ret = rte_eth_dev_close(port_id);
134 [ # # ]: 0 : if (ret)
135 : 0 : PMD_DRV_LOG(ERR, "rte_eth_dev_close failed port_id=%u ret=%d",
136 : : port_id, ret);
137 : :
138 : : /* Remove the rte device when all its eth devices are removed */
139 : : all_eth_removed = true;
140 [ # # ]: 0 : RTE_ETH_FOREACH_DEV_OF(port_id, dev) {
141 [ # # ]: 0 : if (rte_eth_devices[port_id].state != RTE_ETH_DEV_UNUSED) {
142 : : all_eth_removed = false;
143 : : break;
144 : : }
145 : : }
146 [ # # ]: 0 : if (all_eth_removed)
147 : 0 : ret = rte_dev_remove(dev);
148 : :
149 : 0 : hv->vf_ctx.vf_state = vf_removed;
150 : :
151 : : rte_rwlock_write_unlock(&hv->vf_lock);
152 : 0 : }
153 : :
154 : 0 : int hn_eth_rmv_event_callback(uint16_t port_id,
155 : : enum rte_eth_event_type event __rte_unused,
156 : : void *cb_arg, void *out __rte_unused)
157 : : {
158 : : struct hn_data *hv = cb_arg;
159 : :
160 : 0 : PMD_DRV_LOG(NOTICE, "Removing VF portid %d", port_id);
161 : 0 : rte_eal_alarm_set(1, hn_remove_delayed, hv);
162 : :
163 : 0 : return 0;
164 : : }
165 : :
166 : 0 : static int hn_setup_vf_queues(int port, struct rte_eth_dev *dev)
167 : : {
168 : : struct hn_rx_queue *rx_queue;
169 : : struct rte_eth_txq_info txinfo;
170 : : struct rte_eth_rxq_info rxinfo;
171 : : int i, ret = 0;
172 : :
173 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
174 : 0 : ret = rte_eth_tx_queue_info_get(dev->data->port_id, i, &txinfo);
175 [ # # ]: 0 : if (ret) {
176 : 0 : PMD_DRV_LOG(ERR,
177 : : "rte_eth_tx_queue_info_get failed ret=%d",
178 : : ret);
179 : 0 : return ret;
180 : : }
181 : :
182 : 0 : ret = rte_eth_tx_queue_setup(port, i, txinfo.nb_desc, 0,
183 : : &txinfo.conf);
184 [ # # ]: 0 : if (ret) {
185 : 0 : PMD_DRV_LOG(ERR,
186 : : "rte_eth_tx_queue_setup failed ret=%d",
187 : : ret);
188 : 0 : return ret;
189 : : }
190 : : }
191 : :
192 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
193 : 0 : ret = rte_eth_rx_queue_info_get(dev->data->port_id, i, &rxinfo);
194 [ # # ]: 0 : if (ret) {
195 : 0 : PMD_DRV_LOG(ERR,
196 : : "rte_eth_rx_queue_info_get failed ret=%d",
197 : : ret);
198 : 0 : return ret;
199 : : }
200 : :
201 : 0 : rx_queue = dev->data->rx_queues[i];
202 : :
203 : 0 : ret = rte_eth_rx_queue_setup(port, i, rxinfo.nb_desc, 0,
204 : : &rxinfo.conf, rx_queue->mb_pool);
205 [ # # ]: 0 : if (ret) {
206 : 0 : PMD_DRV_LOG(ERR,
207 : : "rte_eth_rx_queue_setup failed ret=%d",
208 : : ret);
209 : 0 : return ret;
210 : : }
211 : : }
212 : :
213 : : return ret;
214 : : }
215 : :
216 : : int hn_vf_add(struct rte_eth_dev *dev, struct hn_data *hv);
217 : :
218 : 0 : static void hn_vf_add_retry(void *args)
219 : : {
220 : : struct rte_eth_dev *dev = args;
221 : 0 : struct hn_data *hv = dev->data->dev_private;
222 : :
223 : 0 : hn_vf_add(dev, hv);
224 : 0 : }
225 : :
226 : : int hn_vf_configure(struct rte_eth_dev *dev,
227 : : const struct rte_eth_conf *dev_conf);
228 : :
229 : : /* Add new VF device to synthetic device */
230 : 0 : int hn_vf_add(struct rte_eth_dev *dev, struct hn_data *hv)
231 : : {
232 : : int ret, port;
233 : :
234 [ # # # # ]: 0 : if (!hv->vf_ctx.vf_vsp_reported || hv->vf_ctx.vf_vsc_switched)
235 : : return 0;
236 : :
237 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
238 : :
239 : 0 : ret = hn_vf_attach(dev, hv);
240 [ # # ]: 0 : if (ret) {
241 : 0 : PMD_DRV_LOG(NOTICE,
242 : : "RNDIS reports VF but device not found, retrying");
243 : 0 : rte_eal_alarm_set(1000000, hn_vf_add_retry, dev);
244 : 0 : goto exit;
245 : : }
246 : :
247 : 0 : port = hv->vf_ctx.vf_port;
248 : :
249 : : /* If the primary device has started, this is a VF hot add.
250 : : * Configure and start VF device.
251 : : */
252 [ # # ]: 0 : if (dev->data->dev_started) {
253 [ # # ]: 0 : if (rte_eth_devices[port].data->dev_started) {
254 : 0 : PMD_DRV_LOG(ERR, "VF already started on hot add");
255 : 0 : goto exit;
256 : : }
257 : :
258 : 0 : PMD_DRV_LOG(NOTICE, "configuring VF port %d", port);
259 : 0 : ret = hn_vf_configure(dev, &dev->data->dev_conf);
260 [ # # ]: 0 : if (ret) {
261 : 0 : PMD_DRV_LOG(ERR, "Failed to configure VF port %d",
262 : : port);
263 : 0 : goto exit;
264 : : }
265 : :
266 : 0 : ret = hn_setup_vf_queues(port, dev);
267 [ # # ]: 0 : if (ret) {
268 : 0 : PMD_DRV_LOG(ERR,
269 : : "Failed to configure VF queues port %d",
270 : : port);
271 : 0 : goto exit;
272 : : }
273 : :
274 : 0 : ret = rte_eth_dev_set_mtu(port, dev->data->mtu);
275 [ # # ]: 0 : if (ret) {
276 : 0 : PMD_DRV_LOG(ERR, "Failed to set VF MTU");
277 : 0 : goto exit;
278 : : }
279 : :
280 : 0 : PMD_DRV_LOG(NOTICE, "Starting VF port %d", port);
281 : 0 : ret = rte_eth_dev_start(port);
282 [ # # ]: 0 : if (ret) {
283 : 0 : PMD_DRV_LOG(ERR, "rte_eth_dev_start failed ret=%d",
284 : : ret);
285 : 0 : goto exit;
286 : : }
287 : 0 : hv->vf_ctx.vf_state = vf_started;
288 : : }
289 : :
290 : 0 : ret = hn_nvs_set_datapath(hv, NVS_DATAPATH_VF);
291 [ # # ]: 0 : if (ret == 0)
292 : 0 : hv->vf_ctx.vf_vsc_switched = true;
293 : :
294 : 0 : exit:
295 : : rte_rwlock_write_unlock(&hv->vf_lock);
296 : 0 : return ret;
297 : : }
298 : :
299 : : /* Switch data path to VF device */
300 : 0 : static void hn_vf_remove(struct hn_data *hv)
301 : : {
302 : : int ret;
303 : :
304 [ # # ]: 0 : if (!hv->vf_ctx.vf_vsc_switched) {
305 : 0 : PMD_DRV_LOG(ERR, "VF path not active");
306 : 0 : return;
307 : : }
308 : :
309 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
310 [ # # ]: 0 : if (!hv->vf_ctx.vf_vsc_switched) {
311 : 0 : PMD_DRV_LOG(ERR, "VF path not active");
312 : : } else {
313 : : /* Stop incoming packets from arriving on VF */
314 : 0 : ret = hn_nvs_set_datapath(hv, NVS_DATAPATH_SYNTHETIC);
315 [ # # ]: 0 : if (ret)
316 : 0 : PMD_DRV_LOG(ERR, "Failed to switch to synthetic");
317 : 0 : hv->vf_ctx.vf_vsc_switched = false;
318 : : }
319 : : rte_rwlock_write_unlock(&hv->vf_lock);
320 : : }
321 : :
322 : : /* Handle VF association message from host */
323 : : void
324 : 0 : hn_nvs_handle_vfassoc(struct rte_eth_dev *dev,
325 : : const struct vmbus_chanpkt_hdr *hdr,
326 : : const void *data)
327 : : {
328 [ # # ]: 0 : struct hn_data *hv = dev->data->dev_private;
329 : : const struct hn_nvs_vf_association *vf_assoc = data;
330 : :
331 [ # # ]: 0 : if (unlikely(vmbus_chanpkt_datalen(hdr) < sizeof(*vf_assoc))) {
332 : 0 : PMD_DRV_LOG(ERR, "invalid vf association NVS");
333 : 0 : return;
334 : : }
335 : :
336 [ # # ]: 0 : PMD_DRV_LOG(DEBUG, "VF serial %u %s port %u",
337 : : vf_assoc->serial,
338 : : vf_assoc->allocated ? "add to" : "remove from",
339 : : dev->data->port_id);
340 : :
341 : 0 : hv->vf_ctx.vf_vsp_reported = vf_assoc->allocated;
342 : :
343 [ # # ]: 0 : if (dev->state == RTE_ETH_DEV_ATTACHED) {
344 [ # # ]: 0 : if (vf_assoc->allocated)
345 : 0 : hn_vf_add(dev, hv);
346 : : else
347 : 0 : hn_vf_remove(hv);
348 : : }
349 : : }
350 : :
351 : : static void
352 : : hn_vf_merge_desc_lim(struct rte_eth_desc_lim *lim,
353 : : const struct rte_eth_desc_lim *vf_lim)
354 : : {
355 : 0 : lim->nb_max = RTE_MIN(vf_lim->nb_max, lim->nb_max);
356 : 0 : lim->nb_min = RTE_MAX(vf_lim->nb_min, lim->nb_min);
357 : 0 : lim->nb_align = RTE_MAX(vf_lim->nb_align, lim->nb_align);
358 : 0 : lim->nb_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max);
359 : 0 : lim->nb_mtu_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max);
360 : : }
361 : :
362 : : /*
363 : : * Merge the info from the VF and synthetic path.
364 : : * use the default config of the VF
365 : : * and the minimum number of queues and buffer sizes.
366 : : */
367 : 0 : static int hn_vf_info_merge(struct rte_eth_dev *vf_dev,
368 : : struct rte_eth_dev_info *info)
369 : : {
370 : : struct rte_eth_dev_info vf_info;
371 : : int ret;
372 : :
373 : 0 : ret = rte_eth_dev_info_get(vf_dev->data->port_id, &vf_info);
374 [ # # ]: 0 : if (ret != 0)
375 : : return ret;
376 : :
377 : 0 : info->speed_capa = vf_info.speed_capa;
378 : 0 : info->default_rxportconf = vf_info.default_rxportconf;
379 : 0 : info->default_txportconf = vf_info.default_txportconf;
380 : :
381 : 0 : info->max_rx_queues = RTE_MIN(vf_info.max_rx_queues,
382 : : info->max_rx_queues);
383 : 0 : info->rx_offload_capa &= vf_info.rx_offload_capa;
384 : 0 : info->rx_queue_offload_capa &= vf_info.rx_queue_offload_capa;
385 : 0 : info->flow_type_rss_offloads &= vf_info.flow_type_rss_offloads;
386 : :
387 : 0 : info->max_tx_queues = RTE_MIN(vf_info.max_tx_queues,
388 : : info->max_tx_queues);
389 : 0 : info->tx_offload_capa &= vf_info.tx_offload_capa;
390 : 0 : info->tx_queue_offload_capa &= vf_info.tx_queue_offload_capa;
391 : : hn_vf_merge_desc_lim(&info->tx_desc_lim, &vf_info.tx_desc_lim);
392 : :
393 : 0 : info->min_rx_bufsize = RTE_MAX(vf_info.min_rx_bufsize,
394 : : info->min_rx_bufsize);
395 : 0 : info->max_rx_pktlen = RTE_MAX(vf_info.max_rx_pktlen,
396 : : info->max_rx_pktlen);
397 : : hn_vf_merge_desc_lim(&info->rx_desc_lim, &vf_info.rx_desc_lim);
398 : :
399 : 0 : return 0;
400 : : }
401 : :
402 : 0 : int hn_vf_info_get(struct hn_data *hv, struct rte_eth_dev_info *info)
403 : : {
404 : : struct rte_eth_dev *vf_dev;
405 : : int ret = 0;
406 : :
407 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
408 : : vf_dev = hn_get_vf_dev(hv);
409 : : if (vf_dev)
410 : 0 : ret = hn_vf_info_merge(vf_dev, info);
411 : : rte_rwlock_read_unlock(&hv->vf_lock);
412 : 0 : return ret;
413 : : }
414 : :
415 : 0 : int hn_vf_configure(struct rte_eth_dev *dev,
416 : : const struct rte_eth_conf *dev_conf)
417 : : {
418 : 0 : struct hn_data *hv = dev->data->dev_private;
419 : 0 : struct rte_eth_conf vf_conf = *dev_conf;
420 : : int ret = 0;
421 : :
422 : : /* link state interrupt does not matter here. */
423 : 0 : vf_conf.intr_conf.lsc = 0;
424 : :
425 : : /* need to monitor removal event */
426 : 0 : vf_conf.intr_conf.rmv = 1;
427 : :
428 [ # # ]: 0 : if (hv->vf_ctx.vf_attached) {
429 : 0 : ret = rte_eth_dev_callback_register(hv->vf_ctx.vf_port,
430 : : RTE_ETH_EVENT_INTR_RMV,
431 : : hn_eth_rmv_event_callback,
432 : : hv);
433 [ # # ]: 0 : if (ret) {
434 : 0 : PMD_DRV_LOG(ERR,
435 : : "Registering callback failed for vf port %d ret %d",
436 : : hv->vf_ctx.vf_port, ret);
437 : 0 : return ret;
438 : : }
439 : :
440 : 0 : ret = rte_eth_dev_configure(hv->vf_ctx.vf_port,
441 : 0 : dev->data->nb_rx_queues,
442 : 0 : dev->data->nb_tx_queues,
443 : : &vf_conf);
444 [ # # ]: 0 : if (ret) {
445 : 0 : PMD_DRV_LOG(ERR, "VF configuration failed: %d", ret);
446 : :
447 : 0 : rte_eth_dev_callback_unregister(hv->vf_ctx.vf_port,
448 : : RTE_ETH_EVENT_INTR_RMV,
449 : : hn_eth_rmv_event_callback,
450 : : hv);
451 : :
452 : 0 : return ret;
453 : : }
454 : :
455 : 0 : hv->vf_ctx.vf_state = vf_configured;
456 : : }
457 : :
458 : : return ret;
459 : : }
460 : :
461 : : /* Configure VF if present.
462 : : * VF device will have the same number of queues as the synthetic device
463 : : */
464 : 0 : int hn_vf_configure_locked(struct rte_eth_dev *dev,
465 : : const struct rte_eth_conf *dev_conf)
466 : : {
467 : 0 : struct hn_data *hv = dev->data->dev_private;
468 : : int ret = 0;
469 : :
470 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
471 : 0 : ret = hn_vf_configure(dev, dev_conf);
472 : : rte_rwlock_write_unlock(&hv->vf_lock);
473 : :
474 : 0 : return ret;
475 : : }
476 : :
477 : 0 : const uint32_t *hn_vf_supported_ptypes(struct rte_eth_dev *dev,
478 : : size_t *no_of_elements)
479 : : {
480 : 0 : struct hn_data *hv = dev->data->dev_private;
481 : : struct rte_eth_dev *vf_dev;
482 : : const uint32_t *ptypes = NULL;
483 : :
484 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
485 : : vf_dev = hn_get_vf_dev(hv);
486 [ # # ]: 0 : if (vf_dev && vf_dev->dev_ops->dev_supported_ptypes_get)
487 : 0 : ptypes = (*vf_dev->dev_ops->dev_supported_ptypes_get)(vf_dev,
488 : : no_of_elements);
489 : : rte_rwlock_read_unlock(&hv->vf_lock);
490 : :
491 : 0 : return ptypes;
492 : : }
493 : :
494 : 0 : int hn_vf_start(struct rte_eth_dev *dev)
495 : : {
496 : 0 : struct hn_data *hv = dev->data->dev_private;
497 : : struct rte_eth_dev *vf_dev;
498 : : int ret = 0;
499 : :
500 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
501 : : vf_dev = hn_get_vf_dev(hv);
502 : : if (vf_dev)
503 : 0 : ret = rte_eth_dev_start(vf_dev->data->port_id);
504 : : rte_rwlock_read_unlock(&hv->vf_lock);
505 : 0 : return ret;
506 : : }
507 : :
508 : 0 : int hn_vf_stop(struct rte_eth_dev *dev)
509 : : {
510 : 0 : struct hn_data *hv = dev->data->dev_private;
511 : : struct rte_eth_dev *vf_dev;
512 : : int ret = 0;
513 : :
514 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
515 : : vf_dev = hn_get_vf_dev(hv);
516 : : if (vf_dev) {
517 : 0 : ret = rte_eth_dev_stop(vf_dev->data->port_id);
518 [ # # ]: 0 : if (ret != 0)
519 : 0 : PMD_DRV_LOG(ERR, "Failed to stop device on port %u",
520 : : vf_dev->data->port_id);
521 : : }
522 : : rte_rwlock_read_unlock(&hv->vf_lock);
523 : :
524 : 0 : return ret;
525 : : }
526 : :
527 : : /* If VF is present, then cascade configuration down */
528 : : #define VF_ETHDEV_FUNC(dev, func) \
529 : : { \
530 : : struct hn_data *hv = (dev)->data->dev_private; \
531 : : struct rte_eth_dev *vf_dev; \
532 : : rte_rwlock_read_lock(&hv->vf_lock); \
533 : : vf_dev = hn_get_vf_dev(hv); \
534 : : if (vf_dev) \
535 : : func(vf_dev->data->port_id); \
536 : : rte_rwlock_read_unlock(&hv->vf_lock); \
537 : : }
538 : :
539 : : /* If VF is present, then cascade configuration down */
540 : : #define VF_ETHDEV_FUNC_RET_STATUS(dev, func) \
541 : : { \
542 : : struct hn_data *hv = (dev)->data->dev_private; \
543 : : struct rte_eth_dev *vf_dev; \
544 : : int ret = 0; \
545 : : rte_rwlock_read_lock(&hv->vf_lock); \
546 : : vf_dev = hn_get_vf_dev(hv); \
547 : : if (vf_dev) \
548 : : ret = func(vf_dev->data->port_id); \
549 : : rte_rwlock_read_unlock(&hv->vf_lock); \
550 : : return ret; \
551 : : }
552 : :
553 : 0 : int hn_vf_close(struct rte_eth_dev *dev)
554 : : {
555 : : int ret = 0;
556 : 0 : struct hn_data *hv = dev->data->dev_private;
557 : :
558 : 0 : rte_eal_alarm_cancel(hn_vf_add_retry, dev);
559 : :
560 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
561 [ # # ]: 0 : if (hv->vf_ctx.vf_attached) {
562 : 0 : rte_eth_dev_callback_unregister(hv->vf_ctx.vf_port,
563 : : RTE_ETH_EVENT_INTR_RMV,
564 : : hn_eth_rmv_event_callback,
565 : : hv);
566 : 0 : rte_eal_alarm_cancel(hn_remove_delayed, hv);
567 : 0 : ret = rte_eth_dev_close(hv->vf_ctx.vf_port);
568 : 0 : hv->vf_ctx.vf_attached = false;
569 : : }
570 : : rte_rwlock_read_unlock(&hv->vf_lock);
571 : :
572 : 0 : return ret;
573 : : }
574 : :
575 : 0 : int hn_vf_stats_reset(struct rte_eth_dev *dev)
576 : : {
577 : 0 : VF_ETHDEV_FUNC_RET_STATUS(dev, rte_eth_stats_reset);
578 : : }
579 : :
580 : 0 : int hn_vf_allmulticast_enable(struct rte_eth_dev *dev)
581 : : {
582 : 0 : VF_ETHDEV_FUNC_RET_STATUS(dev, rte_eth_allmulticast_enable);
583 : : }
584 : :
585 : 0 : int hn_vf_allmulticast_disable(struct rte_eth_dev *dev)
586 : : {
587 : 0 : VF_ETHDEV_FUNC_RET_STATUS(dev, rte_eth_allmulticast_disable);
588 : : }
589 : :
590 : 0 : int hn_vf_promiscuous_enable(struct rte_eth_dev *dev)
591 : : {
592 : 0 : VF_ETHDEV_FUNC_RET_STATUS(dev, rte_eth_promiscuous_enable);
593 : : }
594 : :
595 : 0 : int hn_vf_promiscuous_disable(struct rte_eth_dev *dev)
596 : : {
597 : 0 : VF_ETHDEV_FUNC_RET_STATUS(dev, rte_eth_promiscuous_disable);
598 : : }
599 : :
600 : 0 : int hn_vf_mc_addr_list(struct rte_eth_dev *dev,
601 : : struct rte_ether_addr *mc_addr_set,
602 : : uint32_t nb_mc_addr)
603 : : {
604 : 0 : struct hn_data *hv = dev->data->dev_private;
605 : : struct rte_eth_dev *vf_dev;
606 : : int ret = 0;
607 : :
608 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
609 : : vf_dev = hn_get_vf_dev(hv);
610 : : if (vf_dev)
611 : 0 : ret = rte_eth_dev_set_mc_addr_list(vf_dev->data->port_id,
612 : : mc_addr_set, nb_mc_addr);
613 : : rte_rwlock_read_unlock(&hv->vf_lock);
614 : 0 : return ret;
615 : : }
616 : :
617 : 0 : int hn_vf_tx_queue_setup(struct rte_eth_dev *dev,
618 : : uint16_t queue_idx, uint16_t nb_desc,
619 : : unsigned int socket_id,
620 : : const struct rte_eth_txconf *tx_conf)
621 : : {
622 : 0 : struct hn_data *hv = dev->data->dev_private;
623 : : struct rte_eth_dev *vf_dev;
624 : : int ret = 0;
625 : :
626 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
627 : : vf_dev = hn_get_vf_dev(hv);
628 : : if (vf_dev)
629 : 0 : ret = rte_eth_tx_queue_setup(vf_dev->data->port_id,
630 : : queue_idx, nb_desc,
631 : : socket_id, tx_conf);
632 : : rte_rwlock_read_unlock(&hv->vf_lock);
633 : 0 : return ret;
634 : : }
635 : :
636 : 0 : void hn_vf_tx_queue_release(struct hn_data *hv, uint16_t queue_id)
637 : : {
638 : : struct rte_eth_dev *vf_dev;
639 : :
640 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
641 : : vf_dev = hn_get_vf_dev(hv);
642 [ # # ]: 0 : if (vf_dev && vf_dev->dev_ops->tx_queue_release)
643 : 0 : (*vf_dev->dev_ops->tx_queue_release)(vf_dev, queue_id);
644 : :
645 : : rte_rwlock_read_unlock(&hv->vf_lock);
646 : 0 : }
647 : :
648 : 0 : int hn_vf_rx_queue_setup(struct rte_eth_dev *dev,
649 : : uint16_t queue_idx, uint16_t nb_desc,
650 : : unsigned int socket_id,
651 : : const struct rte_eth_rxconf *rx_conf,
652 : : struct rte_mempool *mp)
653 : : {
654 : 0 : struct hn_data *hv = dev->data->dev_private;
655 : : struct rte_eth_dev *vf_dev;
656 : : int ret = 0;
657 : :
658 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
659 : : vf_dev = hn_get_vf_dev(hv);
660 : : if (vf_dev)
661 : 0 : ret = rte_eth_rx_queue_setup(vf_dev->data->port_id,
662 : : queue_idx, nb_desc,
663 : : socket_id, rx_conf, mp);
664 : : rte_rwlock_read_unlock(&hv->vf_lock);
665 : 0 : return ret;
666 : : }
667 : :
668 : 0 : void hn_vf_rx_queue_release(struct hn_data *hv, uint16_t queue_id)
669 : : {
670 : : struct rte_eth_dev *vf_dev;
671 : :
672 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
673 : : vf_dev = hn_get_vf_dev(hv);
674 [ # # ]: 0 : if (vf_dev && vf_dev->dev_ops->rx_queue_release)
675 : 0 : (*vf_dev->dev_ops->rx_queue_release)(vf_dev, queue_id);
676 : : rte_rwlock_read_unlock(&hv->vf_lock);
677 : 0 : }
678 : :
679 : 0 : int hn_vf_stats_get(struct rte_eth_dev *dev,
680 : : struct rte_eth_stats *stats)
681 : : {
682 : 0 : struct hn_data *hv = dev->data->dev_private;
683 : : struct rte_eth_dev *vf_dev;
684 : : int ret = 0;
685 : :
686 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
687 : : vf_dev = hn_get_vf_dev(hv);
688 : : if (vf_dev)
689 : 0 : ret = rte_eth_stats_get(vf_dev->data->port_id, stats);
690 : : rte_rwlock_read_unlock(&hv->vf_lock);
691 : 0 : return ret;
692 : : }
693 : :
694 : 0 : int hn_vf_xstats_get_names(struct rte_eth_dev *dev,
695 : : struct rte_eth_xstat_name *names,
696 : : unsigned int n)
697 : : {
698 : 0 : struct hn_data *hv = dev->data->dev_private;
699 : : struct rte_eth_dev *vf_dev;
700 : : int i, count = 0;
701 : :
702 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
703 : : vf_dev = hn_get_vf_dev(hv);
704 : : if (vf_dev)
705 : 0 : count = rte_eth_xstats_get_names(vf_dev->data->port_id,
706 : : names, n);
707 : : rte_rwlock_read_unlock(&hv->vf_lock);
708 : :
709 : : /* add vf_ prefix to xstat names */
710 [ # # ]: 0 : if (names) {
711 [ # # ]: 0 : for (i = 0; i < count; i++) {
712 : : char tmp[RTE_ETH_XSTATS_NAME_SIZE];
713 : :
714 : 0 : snprintf(tmp, sizeof(tmp), "vf_%s", names[i].name);
715 : : strlcpy(names[i].name, tmp, sizeof(names[i].name));
716 : : }
717 : : }
718 : :
719 : 0 : return count;
720 : : }
721 : :
722 : 0 : int hn_vf_xstats_get(struct rte_eth_dev *dev,
723 : : struct rte_eth_xstat *xstats,
724 : : unsigned int offset,
725 : : unsigned int n)
726 : : {
727 : 0 : struct hn_data *hv = dev->data->dev_private;
728 : : struct rte_eth_dev *vf_dev;
729 : : int i, count = 0;
730 : :
731 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
732 : : vf_dev = hn_get_vf_dev(hv);
733 : : if (vf_dev)
734 : 0 : count = rte_eth_xstats_get(vf_dev->data->port_id,
735 : 0 : xstats + offset, n - offset);
736 : : rte_rwlock_read_unlock(&hv->vf_lock);
737 : :
738 : : /* Offset id's for VF stats */
739 [ # # ]: 0 : if (count > 0) {
740 [ # # ]: 0 : for (i = 0; i < count; i++)
741 : 0 : xstats[i + offset].id += offset;
742 : : }
743 : :
744 : 0 : return count;
745 : : }
746 : :
747 : 0 : int hn_vf_xstats_reset(struct rte_eth_dev *dev)
748 : : {
749 : 0 : struct hn_data *hv = dev->data->dev_private;
750 : : struct rte_eth_dev *vf_dev;
751 : : int ret;
752 : :
753 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
754 : : vf_dev = hn_get_vf_dev(hv);
755 : : if (vf_dev)
756 : 0 : ret = rte_eth_xstats_reset(vf_dev->data->port_id);
757 : : else
758 : : ret = -EINVAL;
759 : : rte_rwlock_read_unlock(&hv->vf_lock);
760 : :
761 : 0 : return ret;
762 : : }
763 : :
764 : 0 : int hn_vf_rss_hash_update(struct rte_eth_dev *dev,
765 : : struct rte_eth_rss_conf *rss_conf)
766 : : {
767 : 0 : struct hn_data *hv = dev->data->dev_private;
768 : : struct rte_eth_dev *vf_dev;
769 : : int ret = 0;
770 : :
771 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
772 : : vf_dev = hn_get_vf_dev(hv);
773 [ # # ]: 0 : if (vf_dev && vf_dev->dev_ops->rss_hash_update)
774 : 0 : ret = vf_dev->dev_ops->rss_hash_update(vf_dev, rss_conf);
775 : : rte_rwlock_read_unlock(&hv->vf_lock);
776 : :
777 : 0 : return ret;
778 : : }
779 : :
780 : 0 : int hn_vf_reta_hash_update(struct rte_eth_dev *dev,
781 : : struct rte_eth_rss_reta_entry64 *reta_conf,
782 : : uint16_t reta_size)
783 : : {
784 : 0 : struct hn_data *hv = dev->data->dev_private;
785 : : struct rte_eth_dev *vf_dev;
786 : : int ret = 0;
787 : :
788 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
789 : : vf_dev = hn_get_vf_dev(hv);
790 [ # # ]: 0 : if (vf_dev && vf_dev->dev_ops->reta_update)
791 : 0 : ret = vf_dev->dev_ops->reta_update(vf_dev,
792 : : reta_conf, reta_size);
793 : : rte_rwlock_read_unlock(&hv->vf_lock);
794 : :
795 : 0 : return ret;
796 : : }
797 : :
798 : 0 : int hn_vf_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
799 : : {
800 : 0 : struct hn_data *hv = dev->data->dev_private;
801 : : struct rte_eth_dev *vf_dev;
802 : : int ret = 0;
803 : :
804 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
805 : : vf_dev = hn_get_vf_dev(hv);
806 [ # # # # ]: 0 : if (hv->vf_ctx.vf_vsc_switched && vf_dev)
807 : 0 : ret = rte_eth_dev_set_mtu(vf_dev->data->port_id, mtu);
808 : : rte_rwlock_read_unlock(&hv->vf_lock);
809 : :
810 : 0 : return ret;
811 : : }
|