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