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 : : static int hn_eth_recovering_callback(uint16_t port_id,
54 : : enum rte_eth_event_type event, void *cb_arg, void *out);
55 : : static int hn_eth_recovery_success_callback(uint16_t port_id,
56 : : enum rte_eth_event_type event, void *cb_arg, void *out);
57 : : static int hn_eth_recovery_failed_callback(uint16_t port_id,
58 : : enum rte_eth_event_type event, void *cb_arg, void *out);
59 : :
60 : : /*
61 : : * Attach new PCI VF device and return the port_id
62 : : */
63 : 0 : static int hn_vf_attach(struct rte_eth_dev *dev, struct hn_data *hv)
64 : : {
65 : 0 : struct rte_eth_dev_owner owner = { .id = RTE_ETH_DEV_NO_OWNER };
66 : : int port, ret;
67 : :
68 [ # # ]: 0 : if (hv->vf_ctx.vf_attached) {
69 : 0 : PMD_DRV_LOG(NOTICE, "VF already attached");
70 : 0 : return -EEXIST;
71 : : }
72 : :
73 : 0 : port = hn_vf_match(dev);
74 [ # # ]: 0 : if (port < 0) {
75 : 0 : PMD_DRV_LOG(NOTICE, "Couldn't find port for VF");
76 : 0 : return port;
77 : : }
78 : :
79 : 0 : PMD_DRV_LOG(NOTICE, "found matching VF port %d", port);
80 : 0 : ret = rte_eth_dev_owner_get(port, &owner);
81 [ # # ]: 0 : if (ret < 0) {
82 : 0 : PMD_DRV_LOG(ERR, "Can not find owner for port %d", port);
83 : 0 : return ret;
84 : : }
85 : :
86 [ # # ]: 0 : if (owner.id != RTE_ETH_DEV_NO_OWNER) {
87 : 0 : PMD_DRV_LOG(ERR, "Port %u already owned by other device %s",
88 : : port, owner.name);
89 : 0 : return -EBUSY;
90 : : }
91 : :
92 : 0 : ret = rte_eth_dev_owner_set(port, &hv->owner);
93 [ # # ]: 0 : if (ret < 0) {
94 : 0 : PMD_DRV_LOG(ERR, "Can set owner for port %d", port);
95 : 0 : return ret;
96 : : }
97 : :
98 : 0 : PMD_DRV_LOG(DEBUG, "Attach VF device %u", port);
99 : 0 : hv->vf_ctx.vf_attached = true;
100 : 0 : hv->vf_ctx.vf_port = port;
101 : :
102 : 0 : ret = rte_eth_dev_callback_register(hv->vf_ctx.vf_port,
103 : : RTE_ETH_EVENT_INTR_RMV,
104 : : hn_eth_rmv_event_callback,
105 : : hv);
106 [ # # ]: 0 : if (ret) {
107 : : /* Rollback state changes on callback registration failure */
108 : 0 : hv->vf_ctx.vf_attached = false;
109 : 0 : hv->vf_ctx.vf_port = 0;
110 : :
111 : : /* Release port ownership */
112 [ # # ]: 0 : if (rte_eth_dev_owner_unset(port, hv->owner.id) < 0)
113 : 0 : PMD_DRV_LOG(ERR, "Failed to unset owner for port %d", port);
114 : :
115 : 0 : PMD_DRV_LOG(ERR,
116 : : "Registering callback failed for vf port %d ret %d",
117 : : port, ret);
118 : 0 : return ret;
119 : : }
120 : :
121 : : /* Register recovery event callbacks for service reset handling */
122 : 0 : ret = rte_eth_dev_callback_register(hv->vf_ctx.vf_port,
123 : : RTE_ETH_EVENT_ERR_RECOVERING,
124 : : hn_eth_recovering_callback, hv);
125 [ # # ]: 0 : if (ret) {
126 : 0 : PMD_DRV_LOG(ERR,
127 : : "Registering recovering callback failed for vf port %d ret %d",
128 : : port, ret);
129 : 0 : goto err_recovering;
130 : : }
131 : :
132 : 0 : ret = rte_eth_dev_callback_register(hv->vf_ctx.vf_port,
133 : : RTE_ETH_EVENT_RECOVERY_SUCCESS,
134 : : hn_eth_recovery_success_callback, hv);
135 [ # # ]: 0 : if (ret) {
136 : 0 : PMD_DRV_LOG(ERR,
137 : : "Registering recovery success callback failed for vf port %d ret %d",
138 : : port, ret);
139 : 0 : goto err_recovery_success;
140 : : }
141 : :
142 : 0 : ret = rte_eth_dev_callback_register(hv->vf_ctx.vf_port,
143 : : RTE_ETH_EVENT_RECOVERY_FAILED,
144 : : hn_eth_recovery_failed_callback, hv);
145 [ # # ]: 0 : if (ret) {
146 : 0 : PMD_DRV_LOG(ERR,
147 : : "Registering recovery failed callback failed for vf port %d ret %d",
148 : : port, ret);
149 : 0 : goto err_recovery_failed;
150 : : }
151 : :
152 : : return 0;
153 : :
154 : : err_recovery_failed:
155 : 0 : rte_eth_dev_callback_unregister(hv->vf_ctx.vf_port,
156 : : RTE_ETH_EVENT_RECOVERY_SUCCESS,
157 : : hn_eth_recovery_success_callback, hv);
158 : 0 : err_recovery_success:
159 : 0 : rte_eth_dev_callback_unregister(hv->vf_ctx.vf_port,
160 : : RTE_ETH_EVENT_ERR_RECOVERING,
161 : : hn_eth_recovering_callback, hv);
162 : 0 : err_recovering:
163 : 0 : rte_eth_dev_callback_unregister(hv->vf_ctx.vf_port,
164 : : RTE_ETH_EVENT_INTR_RMV,
165 : : hn_eth_rmv_event_callback, hv);
166 : 0 : hv->vf_ctx.vf_attached = false;
167 : 0 : hv->vf_ctx.vf_port = 0;
168 [ # # ]: 0 : if (rte_eth_dev_owner_unset(port, hv->owner.id) < 0)
169 : 0 : PMD_DRV_LOG(ERR, "Failed to unset owner for port %d", port);
170 : : return ret;
171 : : }
172 : :
173 : : static void hn_vf_remove_unlocked(struct hn_data *hv);
174 : :
175 : 0 : static void hn_remove_delayed(void *args)
176 : : {
177 : : struct hn_data *hv = args;
178 : 0 : uint16_t port_id = hv->vf_ctx.vf_port;
179 : 0 : struct rte_device *dev = rte_eth_devices[port_id].device;
180 : : int ret;
181 : : bool all_eth_removed;
182 : :
183 : 0 : PMD_DRV_LOG(NOTICE, "Start to remove port %d", port_id);
184 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
185 : :
186 : : /* Tell VSP to switch data path to synthetic */
187 : 0 : hn_vf_remove_unlocked(hv);
188 : :
189 : : /* Give back ownership */
190 : 0 : ret = rte_eth_dev_owner_unset(port_id, hv->owner.id);
191 [ # # ]: 0 : if (ret)
192 : 0 : PMD_DRV_LOG(ERR, "rte_eth_dev_owner_unset failed ret=%d",
193 : : ret);
194 : 0 : hv->vf_ctx.vf_attached = false;
195 : :
196 : 0 : ret = rte_eth_dev_callback_unregister(port_id, RTE_ETH_EVENT_INTR_RMV,
197 : : hn_eth_rmv_event_callback, hv);
198 [ # # ]: 0 : if (ret)
199 : 0 : PMD_DRV_LOG(ERR,
200 : : "rte_eth_dev_callback_unregister failed ret=%d",
201 : : ret);
202 : 0 : rte_eth_dev_callback_unregister(port_id, RTE_ETH_EVENT_ERR_RECOVERING,
203 : : hn_eth_recovering_callback, hv);
204 : 0 : rte_eth_dev_callback_unregister(port_id, RTE_ETH_EVENT_RECOVERY_SUCCESS,
205 : : hn_eth_recovery_success_callback, hv);
206 : 0 : rte_eth_dev_callback_unregister(port_id, RTE_ETH_EVENT_RECOVERY_FAILED,
207 : : hn_eth_recovery_failed_callback, hv);
208 : :
209 : : /* Detach and release port_id from system */
210 : 0 : ret = rte_eth_dev_stop(port_id);
211 [ # # ]: 0 : if (ret)
212 : 0 : PMD_DRV_LOG(ERR, "rte_eth_dev_stop failed port_id=%u ret=%d",
213 : : port_id, ret);
214 : :
215 : 0 : ret = rte_eth_dev_close(port_id);
216 [ # # ]: 0 : if (ret)
217 : 0 : PMD_DRV_LOG(ERR, "rte_eth_dev_close failed port_id=%u ret=%d",
218 : : port_id, ret);
219 : :
220 : 0 : ret = netvsc_mp_req_vf(hv, NETVSC_MP_REQ_VF_REMOVE, port_id);
221 [ # # ]: 0 : if (ret)
222 : 0 : PMD_DRV_LOG(ERR, "failed to request secondary VF remove");
223 : :
224 : : /* Remove the rte device when all its eth devices are removed */
225 : : all_eth_removed = true;
226 [ # # ]: 0 : RTE_ETH_FOREACH_DEV_OF(port_id, dev) {
227 [ # # ]: 0 : if (rte_eth_devices[port_id].state != RTE_ETH_DEV_UNUSED) {
228 : : all_eth_removed = false;
229 : : break;
230 : : }
231 : : }
232 [ # # ]: 0 : if (all_eth_removed)
233 : 0 : ret = rte_dev_remove(dev);
234 : :
235 : 0 : hv->vf_ctx.vf_state = vf_removed;
236 : :
237 : : rte_rwlock_write_unlock(&hv->vf_lock);
238 : 0 : }
239 : :
240 : 0 : int hn_eth_rmv_event_callback(uint16_t port_id,
241 : : enum rte_eth_event_type event __rte_unused,
242 : : void *cb_arg, void *out __rte_unused)
243 : : {
244 : : struct hn_data *hv = cb_arg;
245 : :
246 : 0 : PMD_DRV_LOG(NOTICE, "Removing VF portid %d", port_id);
247 : 0 : rte_eal_alarm_set(1, hn_remove_delayed, hv);
248 : :
249 : 0 : return 0;
250 : : }
251 : :
252 : : /*
253 : : * Deferred handler for VF error recovery event.
254 : : * Switch data path to synthetic but keep the VF attached.
255 : : */
256 : 0 : static void hn_recovering_delayed(void *args)
257 : : {
258 : : struct hn_data *hv = args;
259 : :
260 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
261 : 0 : hn_vf_remove_unlocked(hv);
262 : : rte_rwlock_write_unlock(&hv->vf_lock);
263 : 0 : }
264 : :
265 : : static int
266 : 0 : hn_eth_recovering_callback(uint16_t port_id,
267 : : enum rte_eth_event_type event __rte_unused,
268 : : void *cb_arg, void *out __rte_unused)
269 : : {
270 : : struct hn_data *hv = cb_arg;
271 : :
272 : 0 : PMD_DRV_LOG(NOTICE, "VF port %u recovering from error", port_id);
273 : 0 : rte_eal_alarm_set(1, hn_recovering_delayed, hv);
274 : :
275 : 0 : return 0;
276 : : }
277 : :
278 : : /*
279 : : * Deferred handler for VF recovery success event.
280 : : * Switch data path back to VF.
281 : : */
282 : 0 : static void hn_recovery_success_delayed(void *args)
283 : : {
284 : : struct hn_data *hv = args;
285 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[hv->port_id];
286 : : int ret;
287 : :
288 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
289 : : /* Only switch data path to VF if the netvsc device is started,
290 : : * mirroring the check in hn_vf_add_unlocked. If the device was
291 : : * stopped during recovery, defer to hn_vf_start().
292 : : */
293 [ # # ]: 0 : if (dev->data->dev_started &&
294 [ # # # # ]: 0 : hv->vf_ctx.vf_attached && !hv->vf_ctx.vf_vsc_switched) {
295 : 0 : ret = hn_nvs_set_datapath(hv, NVS_DATAPATH_VF);
296 [ # # ]: 0 : if (ret)
297 : 0 : PMD_DRV_LOG(ERR,
298 : : "Failed to switch to VF after recovery");
299 : : else
300 : 0 : hv->vf_ctx.vf_vsc_switched = true;
301 : : }
302 : : rte_rwlock_write_unlock(&hv->vf_lock);
303 : 0 : }
304 : :
305 : : static int
306 : 0 : hn_eth_recovery_success_callback(uint16_t port_id,
307 : : enum rte_eth_event_type event __rte_unused,
308 : : void *cb_arg, void *out __rte_unused)
309 : : {
310 : : struct hn_data *hv = cb_arg;
311 : :
312 : 0 : PMD_DRV_LOG(NOTICE, "VF port %u recovery succeeded", port_id);
313 : 0 : rte_eal_alarm_set(1, hn_recovery_success_delayed, hv);
314 : :
315 : 0 : return 0;
316 : : }
317 : :
318 : : /*
319 : : * Handle VF recovery failure event from MANA PMD.
320 : : * VF is unusable, do full removal.
321 : : */
322 : : static int
323 : 0 : hn_eth_recovery_failed_callback(uint16_t port_id,
324 : : enum rte_eth_event_type event __rte_unused,
325 : : void *cb_arg, void *out __rte_unused)
326 : : {
327 : : struct hn_data *hv = cb_arg;
328 : :
329 : 0 : PMD_DRV_LOG(NOTICE, "VF port %u recovery failed, removing", port_id);
330 : 0 : rte_eal_alarm_set(1, hn_remove_delayed, hv);
331 : :
332 : 0 : return 0;
333 : : }
334 : :
335 : 0 : static int hn_setup_vf_queues(int port, struct rte_eth_dev *dev)
336 : : {
337 : : struct hn_rx_queue *rx_queue;
338 : : struct rte_eth_txq_info txinfo;
339 : : struct rte_eth_rxq_info rxinfo;
340 : : int i, ret = 0;
341 : :
342 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
343 : 0 : ret = rte_eth_tx_queue_info_get(dev->data->port_id, i, &txinfo);
344 [ # # ]: 0 : if (ret) {
345 : 0 : PMD_DRV_LOG(ERR,
346 : : "rte_eth_tx_queue_info_get failed ret=%d",
347 : : ret);
348 : 0 : return ret;
349 : : }
350 : :
351 : 0 : ret = rte_eth_tx_queue_setup(port, i, txinfo.nb_desc, 0,
352 : : &txinfo.conf);
353 [ # # ]: 0 : if (ret) {
354 : 0 : PMD_DRV_LOG(ERR,
355 : : "rte_eth_tx_queue_setup failed ret=%d",
356 : : ret);
357 : 0 : return ret;
358 : : }
359 : : }
360 : :
361 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
362 : 0 : ret = rte_eth_rx_queue_info_get(dev->data->port_id, i, &rxinfo);
363 [ # # ]: 0 : if (ret) {
364 : 0 : PMD_DRV_LOG(ERR,
365 : : "rte_eth_rx_queue_info_get failed ret=%d",
366 : : ret);
367 : 0 : return ret;
368 : : }
369 : :
370 : 0 : rx_queue = dev->data->rx_queues[i];
371 : :
372 : 0 : ret = rte_eth_rx_queue_setup(port, i, rxinfo.nb_desc, 0,
373 : : &rxinfo.conf, rx_queue->mb_pool);
374 [ # # ]: 0 : if (ret) {
375 : 0 : PMD_DRV_LOG(ERR,
376 : : "rte_eth_rx_queue_setup failed ret=%d",
377 : : ret);
378 : 0 : return ret;
379 : : }
380 : : }
381 : :
382 : : return ret;
383 : : }
384 : :
385 : : int hn_vf_configure(struct rte_eth_dev *dev,
386 : : const struct rte_eth_conf *dev_conf);
387 : :
388 : : /* Undo hn_vf_attach() on configure/start failure */
389 : 0 : static void hn_vf_detach(struct hn_data *hv)
390 : : {
391 : 0 : uint16_t port = hv->vf_ctx.vf_port;
392 : :
393 : 0 : rte_eth_dev_callback_unregister(port, RTE_ETH_EVENT_INTR_RMV,
394 : : hn_eth_rmv_event_callback, hv);
395 : 0 : rte_eth_dev_callback_unregister(port, RTE_ETH_EVENT_ERR_RECOVERING,
396 : : hn_eth_recovering_callback, hv);
397 : 0 : rte_eth_dev_callback_unregister(port, RTE_ETH_EVENT_RECOVERY_SUCCESS,
398 : : hn_eth_recovery_success_callback, hv);
399 : 0 : rte_eth_dev_callback_unregister(port, RTE_ETH_EVENT_RECOVERY_FAILED,
400 : : hn_eth_recovery_failed_callback, hv);
401 : :
402 [ # # ]: 0 : if (rte_eth_dev_owner_unset(port, hv->owner.id) < 0)
403 : 0 : PMD_DRV_LOG(ERR, "Failed to unset owner for port %d", port);
404 : :
405 : 0 : hv->vf_ctx.vf_attached = false;
406 : 0 : hv->vf_ctx.vf_port = 0;
407 : 0 : }
408 : :
409 : : /* Add new VF device to synthetic device, unlocked version */
410 : 0 : int hn_vf_add_unlocked(struct rte_eth_dev *dev, struct hn_data *hv)
411 : : {
412 : : int ret = 0, port;
413 : : bool fresh_attach;
414 : :
415 [ # # # # ]: 0 : if (!hv->vf_ctx.vf_vsp_reported || hv->vf_ctx.vf_vsc_switched)
416 : 0 : goto exit;
417 : :
418 : 0 : ret = hn_vf_attach(dev, hv);
419 [ # # ]: 0 : if (ret && ret != -EEXIST)
420 : 0 : goto exit;
421 : :
422 : : fresh_attach = (ret == 0);
423 : :
424 : 0 : port = hv->vf_ctx.vf_port;
425 : :
426 : : /* If the primary device has started, this is a VF hot add.
427 : : * Configure and start VF device.
428 : : */
429 [ # # ]: 0 : if (dev->data->dev_started) {
430 [ # # ]: 0 : if (rte_eth_devices[port].data->dev_started) {
431 : 0 : PMD_DRV_LOG(ERR, "VF already started on hot add");
432 : 0 : goto switch_data_path;
433 : : }
434 : :
435 : 0 : PMD_DRV_LOG(NOTICE, "configuring VF port %d", port);
436 : 0 : ret = hn_vf_configure(dev, &dev->data->dev_conf);
437 [ # # ]: 0 : if (ret) {
438 : 0 : PMD_DRV_LOG(ERR, "Failed to configure VF port %d",
439 : : port);
440 : 0 : goto detach;
441 : : }
442 : :
443 : 0 : ret = hn_setup_vf_queues(port, dev);
444 [ # # ]: 0 : if (ret) {
445 : 0 : PMD_DRV_LOG(ERR,
446 : : "Failed to configure VF queues port %d",
447 : : port);
448 : 0 : goto detach;
449 : : }
450 : :
451 : 0 : ret = rte_eth_dev_set_mtu(port, dev->data->mtu);
452 [ # # ]: 0 : if (ret) {
453 : 0 : PMD_DRV_LOG(ERR, "Failed to set VF MTU");
454 : 0 : goto detach;
455 : : }
456 : :
457 : 0 : PMD_DRV_LOG(NOTICE, "Starting VF port %d", port);
458 : 0 : ret = rte_eth_dev_start(port);
459 [ # # ]: 0 : if (ret) {
460 : 0 : PMD_DRV_LOG(ERR, "rte_eth_dev_start failed ret=%d",
461 : : ret);
462 : 0 : goto detach;
463 : : }
464 : 0 : hv->vf_ctx.vf_state = vf_started;
465 : : }
466 : :
467 : 0 : switch_data_path:
468 : : /* Only switch data path to VF if the device is started.
469 : : * Otherwise defer to hn_vf_start() to avoid routing traffic
470 : : * to the VF before queues are set up.
471 : : */
472 [ # # ]: 0 : if (dev->data->dev_started) {
473 : 0 : ret = hn_nvs_set_datapath(hv, NVS_DATAPATH_VF);
474 [ # # ]: 0 : if (ret)
475 : 0 : PMD_DRV_LOG(ERR, "Failed to switch to VF: %d", ret);
476 : : else
477 : 0 : hv->vf_ctx.vf_vsc_switched = true;
478 : : }
479 : :
480 : 0 : exit:
481 : : return ret;
482 : :
483 : 0 : detach:
484 [ # # ]: 0 : if (fresh_attach)
485 : 0 : hn_vf_detach(hv);
486 : : return ret;
487 : : }
488 : :
489 : : /* Add new VF device to synthetic device, locked version */
490 : 0 : int hn_vf_add(struct rte_eth_dev *dev, struct hn_data *hv)
491 : : {
492 : : int ret;
493 : :
494 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
495 : 0 : ret = hn_vf_add_unlocked(dev, hv);
496 : : rte_rwlock_write_unlock(&hv->vf_lock);
497 : :
498 : 0 : return ret;
499 : : }
500 : :
501 : : /* Switch data path to synthetic, unlocked version */
502 : 0 : static void hn_vf_remove_unlocked(struct hn_data *hv)
503 : : {
504 : : int ret;
505 : :
506 [ # # ]: 0 : if (!hv->vf_ctx.vf_vsc_switched) {
507 : 0 : PMD_DRV_LOG(ERR, "VF path not active");
508 : : } else {
509 : : /* Stop incoming packets from arriving on VF */
510 : 0 : ret = hn_nvs_set_datapath(hv, NVS_DATAPATH_SYNTHETIC);
511 [ # # ]: 0 : if (ret)
512 : 0 : PMD_DRV_LOG(ERR, "Failed to switch to synthetic");
513 : :
514 : : /* Clear switched flag regardless — VF is being removed */
515 : 0 : hv->vf_ctx.vf_vsc_switched = false;
516 : : }
517 : 0 : }
518 : :
519 : : /* Handle VF association message from host */
520 : : void
521 : 0 : hn_nvs_handle_vfassoc(struct rte_eth_dev *dev,
522 : : const struct vmbus_chanpkt_hdr *hdr,
523 : : const void *data)
524 : : {
525 [ # # ]: 0 : struct hn_data *hv = dev->data->dev_private;
526 : : const struct hn_nvs_vf_association *vf_assoc = data;
527 : :
528 [ # # ]: 0 : if (unlikely(vmbus_chanpkt_datalen(hdr) < sizeof(*vf_assoc))) {
529 : 0 : PMD_DRV_LOG(ERR, "invalid vf association NVS");
530 : 0 : return;
531 : : }
532 : :
533 [ # # ]: 0 : PMD_DRV_LOG(DEBUG, "VF serial %u %s port %u",
534 : : vf_assoc->serial,
535 : : vf_assoc->allocated ? "add to" : "remove from",
536 : : dev->data->port_id);
537 : :
538 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
539 : :
540 : 0 : hv->vf_ctx.vf_vsp_reported = vf_assoc->allocated;
541 [ # # ]: 0 : if (dev->state == RTE_ETH_DEV_ATTACHED) {
542 [ # # ]: 0 : if (vf_assoc->allocated)
543 : 0 : hn_vf_add_unlocked(dev, hv);
544 : : else
545 : 0 : hn_vf_remove_unlocked(hv);
546 : : }
547 : :
548 : : rte_rwlock_write_unlock(&hv->vf_lock);
549 : : }
550 : :
551 : : static void
552 : : hn_vf_merge_desc_lim(struct rte_eth_desc_lim *lim,
553 : : const struct rte_eth_desc_lim *vf_lim)
554 : : {
555 : 0 : lim->nb_max = RTE_MIN(vf_lim->nb_max, lim->nb_max);
556 : 0 : lim->nb_min = RTE_MAX(vf_lim->nb_min, lim->nb_min);
557 : 0 : lim->nb_align = RTE_MAX(vf_lim->nb_align, lim->nb_align);
558 : 0 : lim->nb_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max);
559 : 0 : lim->nb_mtu_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max);
560 : : }
561 : :
562 : : /*
563 : : * Merge the info from the VF and synthetic path.
564 : : * use the default config of the VF
565 : : * and the minimum number of queues and buffer sizes.
566 : : */
567 : 0 : static int hn_vf_info_merge(struct rte_eth_dev *vf_dev,
568 : : struct rte_eth_dev_info *info)
569 : : {
570 : : struct rte_eth_dev_info vf_info;
571 : : int ret;
572 : :
573 : 0 : ret = rte_eth_dev_info_get(vf_dev->data->port_id, &vf_info);
574 [ # # ]: 0 : if (ret != 0)
575 : : return ret;
576 : :
577 : 0 : info->speed_capa = vf_info.speed_capa;
578 : 0 : info->default_rxportconf = vf_info.default_rxportconf;
579 : 0 : info->default_txportconf = vf_info.default_txportconf;
580 : :
581 : 0 : info->max_rx_queues = RTE_MIN(vf_info.max_rx_queues,
582 : : info->max_rx_queues);
583 : 0 : info->rx_offload_capa &= vf_info.rx_offload_capa;
584 : 0 : info->rx_queue_offload_capa &= vf_info.rx_queue_offload_capa;
585 : 0 : info->flow_type_rss_offloads &= vf_info.flow_type_rss_offloads;
586 : :
587 : 0 : info->max_tx_queues = RTE_MIN(vf_info.max_tx_queues,
588 : : info->max_tx_queues);
589 : 0 : info->tx_offload_capa &= vf_info.tx_offload_capa;
590 : 0 : info->tx_queue_offload_capa &= vf_info.tx_queue_offload_capa;
591 : : hn_vf_merge_desc_lim(&info->tx_desc_lim, &vf_info.tx_desc_lim);
592 : :
593 : 0 : info->min_rx_bufsize = RTE_MAX(vf_info.min_rx_bufsize,
594 : : info->min_rx_bufsize);
595 : 0 : info->max_rx_pktlen = RTE_MAX(vf_info.max_rx_pktlen,
596 : : info->max_rx_pktlen);
597 : : hn_vf_merge_desc_lim(&info->rx_desc_lim, &vf_info.rx_desc_lim);
598 : :
599 : 0 : return 0;
600 : : }
601 : :
602 : 0 : int hn_vf_info_get(struct hn_data *hv, struct rte_eth_dev_info *info)
603 : : {
604 : : struct rte_eth_dev *vf_dev;
605 : : int ret = 0;
606 : :
607 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
608 : : vf_dev = hn_get_vf_dev(hv);
609 : : if (vf_dev)
610 : 0 : ret = hn_vf_info_merge(vf_dev, info);
611 : : rte_rwlock_read_unlock(&hv->vf_lock);
612 : 0 : return ret;
613 : : }
614 : :
615 : 0 : int hn_vf_configure(struct rte_eth_dev *dev,
616 : : const struct rte_eth_conf *dev_conf)
617 : : {
618 : 0 : struct hn_data *hv = dev->data->dev_private;
619 : 0 : struct rte_eth_conf vf_conf = *dev_conf;
620 : : int ret = 0;
621 : :
622 : : /* link state interrupt does not matter here. */
623 : 0 : vf_conf.intr_conf.lsc = 0;
624 : :
625 : : /* need to monitor removal event */
626 : 0 : vf_conf.intr_conf.rmv = 1;
627 : :
628 [ # # ]: 0 : if (hv->vf_ctx.vf_attached) {
629 : 0 : ret = rte_eth_dev_configure(hv->vf_ctx.vf_port,
630 : 0 : dev->data->nb_rx_queues,
631 : 0 : dev->data->nb_tx_queues,
632 : : &vf_conf);
633 [ # # ]: 0 : if (ret) {
634 : 0 : PMD_DRV_LOG(ERR, "VF configuration failed: %d", ret);
635 : 0 : return ret;
636 : : }
637 : :
638 : 0 : hv->vf_ctx.vf_state = vf_configured;
639 : : }
640 : :
641 : : return ret;
642 : : }
643 : :
644 : : /* Configure VF if present.
645 : : * VF device will have the same number of queues as the synthetic device
646 : : */
647 : 0 : int hn_vf_configure_locked(struct rte_eth_dev *dev,
648 : : const struct rte_eth_conf *dev_conf)
649 : : {
650 : 0 : struct hn_data *hv = dev->data->dev_private;
651 : : int ret = 0;
652 : :
653 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
654 : 0 : ret = hn_vf_configure(dev, dev_conf);
655 : : rte_rwlock_write_unlock(&hv->vf_lock);
656 : :
657 : 0 : return ret;
658 : : }
659 : :
660 : 0 : const uint32_t *hn_vf_supported_ptypes(struct rte_eth_dev *dev,
661 : : size_t *no_of_elements)
662 : : {
663 : 0 : struct hn_data *hv = dev->data->dev_private;
664 : : struct rte_eth_dev *vf_dev;
665 : : const uint32_t *ptypes = NULL;
666 : :
667 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
668 : : vf_dev = hn_get_vf_dev(hv);
669 [ # # ]: 0 : if (vf_dev && vf_dev->dev_ops->dev_supported_ptypes_get)
670 : 0 : ptypes = (*vf_dev->dev_ops->dev_supported_ptypes_get)(vf_dev,
671 : : no_of_elements);
672 : : rte_rwlock_read_unlock(&hv->vf_lock);
673 : :
674 : 0 : return ptypes;
675 : : }
676 : :
677 : 0 : int hn_vf_start(struct rte_eth_dev *dev)
678 : : {
679 : 0 : struct hn_data *hv = dev->data->dev_private;
680 : : struct rte_eth_dev *vf_dev;
681 : : int ret = 0;
682 : :
683 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
684 : : vf_dev = hn_get_vf_dev(hv);
685 : : if (vf_dev) {
686 : 0 : ret = rte_eth_dev_start(vf_dev->data->port_id);
687 [ # # ]: 0 : if (ret == 0) {
688 : : /* Re-switch data path to VF if VSP has reported
689 : : * VF is present and we haven't switched yet
690 : : * (e.g. after a stop/start cycle).
691 : : */
692 [ # # ]: 0 : if (hv->vf_ctx.vf_vsp_reported &&
693 [ # # ]: 0 : !hv->vf_ctx.vf_vsc_switched) {
694 : 0 : ret = hn_nvs_set_datapath(hv,
695 : : NVS_DATAPATH_VF);
696 [ # # ]: 0 : if (ret) {
697 : 0 : PMD_DRV_LOG(ERR,
698 : : "Failed to switch to VF: %d",
699 : : ret);
700 : 0 : rte_eth_dev_stop(vf_dev->data->port_id);
701 : : } else {
702 : 0 : hv->vf_ctx.vf_vsc_switched = true;
703 : : }
704 : : }
705 : : }
706 : : }
707 : : rte_rwlock_write_unlock(&hv->vf_lock);
708 : 0 : return ret;
709 : : }
710 : :
711 : 0 : int hn_vf_stop(struct rte_eth_dev *dev)
712 : : {
713 : 0 : struct hn_data *hv = dev->data->dev_private;
714 : : struct rte_eth_dev *vf_dev;
715 : : int ret = 0;
716 : : int err;
717 : :
718 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
719 : : vf_dev = hn_get_vf_dev(hv);
720 : : if (vf_dev) {
721 : : /* Switch data path back to synthetic before stopping VF,
722 : : * so the host stops routing traffic to the VF device.
723 : : */
724 [ # # ]: 0 : if (hv->vf_ctx.vf_vsc_switched) {
725 : 0 : ret = hn_nvs_set_datapath(hv, NVS_DATAPATH_SYNTHETIC);
726 [ # # ]: 0 : if (ret) {
727 : 0 : PMD_DRV_LOG(ERR,
728 : : "Failed to switch to synthetic: %d",
729 : : ret);
730 : : } else {
731 : 0 : hv->vf_ctx.vf_vsc_switched = false;
732 : : }
733 : : }
734 : :
735 : 0 : err = rte_eth_dev_stop(vf_dev->data->port_id);
736 [ # # ]: 0 : if (err != 0)
737 : 0 : PMD_DRV_LOG(ERR, "Failed to stop device on port %u",
738 : : vf_dev->data->port_id);
739 [ # # ]: 0 : if (ret == 0)
740 : : ret = err;
741 : : }
742 : : rte_rwlock_write_unlock(&hv->vf_lock);
743 : :
744 : 0 : return ret;
745 : : }
746 : :
747 : : /* If VF is present, then cascade configuration down */
748 : : #define VF_ETHDEV_FUNC(dev, func) \
749 : : { \
750 : : struct hn_data *hv = (dev)->data->dev_private; \
751 : : struct rte_eth_dev *vf_dev; \
752 : : rte_rwlock_read_lock(&hv->vf_lock); \
753 : : vf_dev = hn_get_vf_dev(hv); \
754 : : if (vf_dev) \
755 : : func(vf_dev->data->port_id); \
756 : : rte_rwlock_read_unlock(&hv->vf_lock); \
757 : : }
758 : :
759 : : /* If VF is present, then cascade configuration down */
760 : : #define VF_ETHDEV_FUNC_RET_STATUS(dev, func) \
761 : : { \
762 : : struct hn_data *hv = (dev)->data->dev_private; \
763 : : struct rte_eth_dev *vf_dev; \
764 : : int ret = 0; \
765 : : rte_rwlock_read_lock(&hv->vf_lock); \
766 : : vf_dev = hn_get_vf_dev(hv); \
767 : : if (vf_dev) \
768 : : ret = func(vf_dev->data->port_id); \
769 : : rte_rwlock_read_unlock(&hv->vf_lock); \
770 : : return ret; \
771 : : }
772 : :
773 : 0 : int hn_vf_close(struct rte_eth_dev *dev)
774 : : {
775 : : int ret = 0;
776 : 0 : struct hn_data *hv = dev->data->dev_private;
777 : :
778 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
779 [ # # ]: 0 : if (hv->vf_ctx.vf_attached) {
780 : 0 : rte_eth_dev_callback_unregister(hv->vf_ctx.vf_port,
781 : : RTE_ETH_EVENT_INTR_RMV,
782 : : hn_eth_rmv_event_callback,
783 : : hv);
784 : 0 : rte_eth_dev_callback_unregister(hv->vf_ctx.vf_port,
785 : : RTE_ETH_EVENT_ERR_RECOVERING,
786 : : hn_eth_recovering_callback,
787 : : hv);
788 : 0 : rte_eth_dev_callback_unregister(hv->vf_ctx.vf_port,
789 : : RTE_ETH_EVENT_RECOVERY_SUCCESS,
790 : : hn_eth_recovery_success_callback,
791 : : hv);
792 : 0 : rte_eth_dev_callback_unregister(hv->vf_ctx.vf_port,
793 : : RTE_ETH_EVENT_RECOVERY_FAILED,
794 : : hn_eth_recovery_failed_callback,
795 : : hv);
796 : 0 : rte_eal_alarm_cancel(hn_remove_delayed, hv);
797 : 0 : rte_eal_alarm_cancel(hn_recovering_delayed, hv);
798 : 0 : rte_eal_alarm_cancel(hn_recovery_success_delayed, hv);
799 : 0 : ret = rte_eth_dev_close(hv->vf_ctx.vf_port);
800 : 0 : hv->vf_ctx.vf_attached = false;
801 : : }
802 : : rte_rwlock_write_unlock(&hv->vf_lock);
803 : :
804 : 0 : return ret;
805 : : }
806 : :
807 : 0 : int hn_vf_stats_reset(struct rte_eth_dev *dev)
808 : : {
809 : 0 : VF_ETHDEV_FUNC_RET_STATUS(dev, rte_eth_stats_reset);
810 : : }
811 : :
812 : 0 : int hn_vf_allmulticast_enable(struct rte_eth_dev *dev)
813 : : {
814 : 0 : VF_ETHDEV_FUNC_RET_STATUS(dev, rte_eth_allmulticast_enable);
815 : : }
816 : :
817 : 0 : int hn_vf_allmulticast_disable(struct rte_eth_dev *dev)
818 : : {
819 : 0 : VF_ETHDEV_FUNC_RET_STATUS(dev, rte_eth_allmulticast_disable);
820 : : }
821 : :
822 : 0 : int hn_vf_promiscuous_enable(struct rte_eth_dev *dev)
823 : : {
824 : 0 : VF_ETHDEV_FUNC_RET_STATUS(dev, rte_eth_promiscuous_enable);
825 : : }
826 : :
827 : 0 : int hn_vf_promiscuous_disable(struct rte_eth_dev *dev)
828 : : {
829 : 0 : VF_ETHDEV_FUNC_RET_STATUS(dev, rte_eth_promiscuous_disable);
830 : : }
831 : :
832 : 0 : int hn_vf_mc_addr_list(struct rte_eth_dev *dev,
833 : : struct rte_ether_addr *mc_addr_set,
834 : : uint32_t nb_mc_addr)
835 : : {
836 : 0 : struct hn_data *hv = dev->data->dev_private;
837 : : struct rte_eth_dev *vf_dev;
838 : : int ret = 0;
839 : :
840 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
841 : : vf_dev = hn_get_vf_dev(hv);
842 : : if (vf_dev)
843 : 0 : ret = rte_eth_dev_set_mc_addr_list(vf_dev->data->port_id,
844 : : mc_addr_set, nb_mc_addr);
845 : : rte_rwlock_read_unlock(&hv->vf_lock);
846 : 0 : return ret;
847 : : }
848 : :
849 : 0 : int hn_vf_tx_queue_setup(struct rte_eth_dev *dev,
850 : : uint16_t queue_idx, uint16_t nb_desc,
851 : : unsigned int socket_id,
852 : : const struct rte_eth_txconf *tx_conf)
853 : : {
854 : 0 : struct hn_data *hv = dev->data->dev_private;
855 : : struct rte_eth_dev *vf_dev;
856 : : int ret = 0;
857 : :
858 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
859 : : vf_dev = hn_get_vf_dev(hv);
860 : : if (vf_dev)
861 : 0 : ret = rte_eth_tx_queue_setup(vf_dev->data->port_id,
862 : : queue_idx, nb_desc,
863 : : socket_id, tx_conf);
864 : : rte_rwlock_read_unlock(&hv->vf_lock);
865 : 0 : return ret;
866 : : }
867 : :
868 : 0 : void hn_vf_tx_queue_release(struct hn_data *hv, uint16_t queue_id)
869 : : {
870 : : struct rte_eth_dev *vf_dev;
871 : :
872 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
873 : : vf_dev = hn_get_vf_dev(hv);
874 [ # # ]: 0 : if (vf_dev && vf_dev->dev_ops->tx_queue_release) {
875 : 0 : (*vf_dev->dev_ops->tx_queue_release)(vf_dev, queue_id);
876 : 0 : vf_dev->data->tx_queues[queue_id] = NULL;
877 : : }
878 : :
879 : : rte_rwlock_write_unlock(&hv->vf_lock);
880 : 0 : }
881 : :
882 : 0 : int hn_vf_rx_queue_setup(struct rte_eth_dev *dev,
883 : : uint16_t queue_idx, uint16_t nb_desc,
884 : : unsigned int socket_id,
885 : : const struct rte_eth_rxconf *rx_conf,
886 : : struct rte_mempool *mp)
887 : : {
888 : 0 : struct hn_data *hv = dev->data->dev_private;
889 : : struct rte_eth_dev *vf_dev;
890 : : int ret = 0;
891 : :
892 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
893 : : vf_dev = hn_get_vf_dev(hv);
894 : : if (vf_dev)
895 : 0 : ret = rte_eth_rx_queue_setup(vf_dev->data->port_id,
896 : : queue_idx, nb_desc,
897 : : socket_id, rx_conf, mp);
898 : : rte_rwlock_read_unlock(&hv->vf_lock);
899 : 0 : return ret;
900 : : }
901 : :
902 : 0 : void hn_vf_rx_queue_release(struct hn_data *hv, uint16_t queue_id)
903 : : {
904 : : struct rte_eth_dev *vf_dev;
905 : :
906 : 0 : rte_rwlock_write_lock(&hv->vf_lock);
907 : : vf_dev = hn_get_vf_dev(hv);
908 [ # # ]: 0 : if (vf_dev && vf_dev->dev_ops->rx_queue_release) {
909 : 0 : (*vf_dev->dev_ops->rx_queue_release)(vf_dev, queue_id);
910 : 0 : vf_dev->data->rx_queues[queue_id] = NULL;
911 : : }
912 : : rte_rwlock_write_unlock(&hv->vf_lock);
913 : 0 : }
914 : :
915 : 0 : int hn_vf_stats_get(struct rte_eth_dev *dev,
916 : : struct rte_eth_stats *stats,
917 : : struct eth_queue_stats *qstats)
918 : : {
919 : 0 : struct hn_data *hv = dev->data->dev_private;
920 : : struct rte_eth_dev *vf_dev;
921 : : int ret = 0;
922 : :
923 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
924 : : vf_dev = hn_get_vf_dev(hv);
925 : : if (vf_dev) {
926 : : /* Call dev_ops->stats_get directly instead of the public
927 : : * rte_eth_stats_get API because we need to forward the
928 : : * per-queue stats (qstats) which the public API does not
929 : : * support. The caller (eth_stats_qstats_get) has already
930 : : * zeroed stats and qstats before invoking this callback.
931 : : */
932 [ # # ]: 0 : if (vf_dev->dev_ops->stats_get != NULL)
933 : 0 : ret = vf_dev->dev_ops->stats_get(vf_dev, stats,
934 : : qstats);
935 : : else
936 : : ret = -ENOTSUP;
937 : : }
938 : : rte_rwlock_read_unlock(&hv->vf_lock);
939 : 0 : return ret;
940 : : }
941 : :
942 : 0 : int hn_vf_xstats_get_names(struct rte_eth_dev *dev,
943 : : struct rte_eth_xstat_name *names,
944 : : unsigned int n)
945 : : {
946 : 0 : struct hn_data *hv = dev->data->dev_private;
947 : : struct rte_eth_dev *vf_dev;
948 : : int i, count = 0;
949 : :
950 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
951 : : vf_dev = hn_get_vf_dev(hv);
952 : : if (vf_dev)
953 : 0 : count = rte_eth_xstats_get_names(vf_dev->data->port_id,
954 : : names, n);
955 : : rte_rwlock_read_unlock(&hv->vf_lock);
956 : :
957 : : /* add vf_ prefix to xstat names */
958 [ # # ]: 0 : if (names) {
959 [ # # ]: 0 : for (i = 0; i < count; i++) {
960 : : char tmp[RTE_ETH_XSTATS_NAME_SIZE];
961 : :
962 : 0 : snprintf(tmp, sizeof(tmp), "vf_%s", names[i].name);
963 : : strlcpy(names[i].name, tmp, sizeof(names[i].name));
964 : : }
965 : : }
966 : :
967 : 0 : return count;
968 : : }
969 : :
970 : 0 : int hn_vf_xstats_get(struct rte_eth_dev *dev,
971 : : struct rte_eth_xstat *xstats,
972 : : unsigned int offset,
973 : : unsigned int n)
974 : : {
975 : 0 : struct hn_data *hv = dev->data->dev_private;
976 : : struct rte_eth_dev *vf_dev;
977 : : int i, count = 0;
978 : :
979 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
980 : : vf_dev = hn_get_vf_dev(hv);
981 : : if (vf_dev)
982 : 0 : count = rte_eth_xstats_get(vf_dev->data->port_id,
983 : 0 : xstats + offset, n - offset);
984 : : rte_rwlock_read_unlock(&hv->vf_lock);
985 : :
986 : : /* Offset id's for VF stats */
987 [ # # ]: 0 : if (count > 0) {
988 [ # # ]: 0 : for (i = 0; i < count; i++)
989 : 0 : xstats[i + offset].id += offset;
990 : : }
991 : :
992 : 0 : return count;
993 : : }
994 : :
995 : 0 : int hn_vf_xstats_reset(struct rte_eth_dev *dev)
996 : : {
997 : 0 : struct hn_data *hv = dev->data->dev_private;
998 : : struct rte_eth_dev *vf_dev;
999 : : int ret;
1000 : :
1001 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
1002 : : vf_dev = hn_get_vf_dev(hv);
1003 : : if (vf_dev)
1004 : 0 : ret = rte_eth_xstats_reset(vf_dev->data->port_id);
1005 : : else
1006 : : ret = -EINVAL;
1007 : : rte_rwlock_read_unlock(&hv->vf_lock);
1008 : :
1009 : 0 : return ret;
1010 : : }
1011 : :
1012 : 0 : int hn_vf_rss_hash_update(struct rte_eth_dev *dev,
1013 : : struct rte_eth_rss_conf *rss_conf)
1014 : : {
1015 : 0 : struct hn_data *hv = dev->data->dev_private;
1016 : : struct rte_eth_dev *vf_dev;
1017 : : int ret = 0;
1018 : :
1019 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
1020 : : vf_dev = hn_get_vf_dev(hv);
1021 [ # # ]: 0 : if (vf_dev && vf_dev->dev_ops->rss_hash_update)
1022 : 0 : ret = vf_dev->dev_ops->rss_hash_update(vf_dev, rss_conf);
1023 : : rte_rwlock_read_unlock(&hv->vf_lock);
1024 : :
1025 : 0 : return ret;
1026 : : }
1027 : :
1028 : 0 : int hn_vf_reta_hash_update(struct rte_eth_dev *dev,
1029 : : struct rte_eth_rss_reta_entry64 *reta_conf,
1030 : : uint16_t reta_size)
1031 : : {
1032 : 0 : struct hn_data *hv = dev->data->dev_private;
1033 : : struct rte_eth_dev *vf_dev;
1034 : : int ret = 0;
1035 : :
1036 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
1037 : : vf_dev = hn_get_vf_dev(hv);
1038 [ # # ]: 0 : if (vf_dev && vf_dev->dev_ops->reta_update)
1039 : 0 : ret = vf_dev->dev_ops->reta_update(vf_dev,
1040 : : reta_conf, reta_size);
1041 : : rte_rwlock_read_unlock(&hv->vf_lock);
1042 : :
1043 : 0 : return ret;
1044 : : }
1045 : :
1046 : 0 : int hn_vf_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
1047 : : {
1048 : 0 : struct hn_data *hv = dev->data->dev_private;
1049 : : struct rte_eth_dev *vf_dev;
1050 : : int ret = 0;
1051 : :
1052 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
1053 : : vf_dev = hn_get_vf_dev(hv);
1054 [ # # # # ]: 0 : if (hv->vf_ctx.vf_vsc_switched && vf_dev)
1055 : 0 : ret = rte_eth_dev_set_mtu(vf_dev->data->port_id, mtu);
1056 : : rte_rwlock_read_unlock(&hv->vf_lock);
1057 : :
1058 : 0 : return ret;
1059 : : }
|