Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2014-2021 Netronome Systems, Inc.
3 : : * All rights reserved.
4 : : *
5 : : * Small portions derived from code Copyright(c) 2010-2015 Intel Corporation.
6 : : */
7 : :
8 : : #include <rte_alarm.h>
9 : : #include <nfp_common_pci.h>
10 : :
11 : : #include "nfd3/nfp_nfd3.h"
12 : : #include "nfdk/nfp_nfdk.h"
13 : : #include "nfpcore/nfp_cpp.h"
14 : :
15 : : #include "nfp_logs.h"
16 : : #include "nfp_net_common.h"
17 : : #include "nfp_rxtx_vec.h"
18 : :
19 : : #define NFP_VF_DRIVER_NAME net_nfp_vf
20 : :
21 : : static int
22 : 0 : nfp_netvf_start(struct rte_eth_dev *dev)
23 : : {
24 : : int ret;
25 : : uint16_t i;
26 : : struct nfp_hw *hw;
27 : : uint32_t new_ctrl;
28 : : uint32_t update = 0;
29 : : uint32_t intr_vector;
30 : : struct nfp_net_hw *net_hw;
31 : : struct rte_eth_conf *dev_conf;
32 : : struct rte_eth_rxmode *rxmode;
33 : 0 : struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(dev, *pci_dev);
34 : 0 : struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
35 : :
36 : : /* Disabling queues just in case... */
37 : 0 : nfp_net_disable_queues(dev);
38 : :
39 : : /* Enabling the required queues in the device */
40 : 0 : nfp_net_enable_queues(dev);
41 : :
42 : : /* Check and configure queue intr-vector mapping */
43 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.rxq != 0) {
44 [ # # ]: 0 : if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) {
45 : : /*
46 : : * Better not to share LSC with RX interrupts.
47 : : * Unregistering LSC interrupt handler.
48 : : */
49 : 0 : rte_intr_callback_unregister(intr_handle,
50 : : nfp_net_dev_interrupt_handler, (void *)dev);
51 : :
52 [ # # ]: 0 : if (dev->data->nb_rx_queues > 1) {
53 : 0 : PMD_INIT_LOG(ERR, "PMD rx interrupt only "
54 : : "supports 1 queue with UIO.");
55 : 0 : return -EIO;
56 : : }
57 : : }
58 : :
59 : 0 : intr_vector = dev->data->nb_rx_queues;
60 [ # # ]: 0 : if (rte_intr_efd_enable(intr_handle, intr_vector) != 0)
61 : : return -1;
62 : :
63 : 0 : nfp_configure_rx_interrupt(dev, intr_handle);
64 : : update = NFP_NET_CFG_UPDATE_MSIX;
65 : : }
66 : :
67 : 0 : rte_intr_enable(intr_handle);
68 : :
69 : 0 : new_ctrl = nfp_check_offloads(dev);
70 : :
71 : : /* Writing configuration parameters in the device */
72 : 0 : net_hw = dev->data->dev_private;
73 : 0 : hw = &net_hw->super;
74 : 0 : nfp_net_params_setup(net_hw);
75 : :
76 : 0 : dev_conf = &dev->data->dev_conf;
77 : : rxmode = &dev_conf->rxmode;
78 : :
79 [ # # ]: 0 : if ((rxmode->offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH) != 0) {
80 : 0 : nfp_net_rss_config_default(dev);
81 : 0 : update |= NFP_NET_CFG_UPDATE_RSS;
82 [ # # ]: 0 : new_ctrl |= nfp_net_cfg_ctrl_rss(hw->cap);
83 : : }
84 : :
85 : : /* Enable device */
86 : 0 : new_ctrl |= NFP_NET_CFG_CTRL_ENABLE;
87 : :
88 : 0 : update |= NFP_NET_CFG_UPDATE_GEN | NFP_NET_CFG_UPDATE_RING;
89 : :
90 [ # # ]: 0 : if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0)
91 : 0 : new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG;
92 : :
93 : : nn_cfg_writel(hw, NFP_NET_CFG_CTRL, new_ctrl);
94 [ # # ]: 0 : if (nfp_reconfig(hw, new_ctrl, update) != 0)
95 : : return -EIO;
96 : :
97 : 0 : hw->ctrl = new_ctrl;
98 : :
99 : : /*
100 : : * Allocating rte mbufs for configured rx queues.
101 : : * This requires queues being enabled before.
102 : : */
103 [ # # ]: 0 : if (nfp_net_rx_freelist_setup(dev) != 0) {
104 : : ret = -ENOMEM;
105 : 0 : goto error;
106 : : }
107 : :
108 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
109 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
110 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
111 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
112 : :
113 : : return 0;
114 : :
115 : : error:
116 : : /*
117 : : * An error returned by this function should mean the app
118 : : * exiting and then the system releasing all the memory
119 : : * allocated even memory coming from hugepages.
120 : : *
121 : : * The device could be enabled at this point with some queues
122 : : * ready for getting packets. This is true if the call to
123 : : * nfp_net_rx_freelist_setup() succeeds for some queues but
124 : : * fails for subsequent queues.
125 : : *
126 : : * This should make the app exiting but better if we tell the
127 : : * device first.
128 : : */
129 : 0 : nfp_net_disable_queues(dev);
130 : :
131 : 0 : return ret;
132 : : }
133 : :
134 : : static int
135 : 0 : nfp_netvf_stop(struct rte_eth_dev *dev)
136 : : {
137 : 0 : nfp_net_disable_queues(dev);
138 : :
139 : : /* Clear queues */
140 : 0 : nfp_net_stop_tx_queue(dev);
141 : :
142 : 0 : nfp_net_stop_rx_queue(dev);
143 : :
144 : 0 : return 0;
145 : : }
146 : :
147 : : static int
148 : 0 : nfp_netvf_set_link_up(struct rte_eth_dev *dev __rte_unused)
149 : : {
150 : 0 : return -ENOTSUP;
151 : : }
152 : :
153 : : /* Set the link down. */
154 : : static int
155 : 0 : nfp_netvf_set_link_down(struct rte_eth_dev *dev __rte_unused)
156 : : {
157 : 0 : return -ENOTSUP;
158 : : }
159 : :
160 : : /* Reset and stop device. The device can not be restarted. */
161 : : static int
162 : 0 : nfp_netvf_close(struct rte_eth_dev *dev)
163 : : {
164 : : struct nfp_net_hw *net_hw;
165 : : struct rte_pci_device *pci_dev;
166 : : struct nfp_net_hw_priv *hw_priv;
167 : :
168 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
169 : : return 0;
170 : :
171 : 0 : net_hw = dev->data->dev_private;
172 : 0 : pci_dev = RTE_CLASS_TO_BUS_DEVICE(dev, *pci_dev);
173 : 0 : hw_priv = dev->process_private;
174 : :
175 : 0 : rte_free(net_hw->eth_qstats_base);
176 : 0 : rte_free(net_hw->eth_xstats_base);
177 : 0 : rte_free(hw_priv);
178 : :
179 : : /*
180 : : * We assume that the DPDK application is stopping all the
181 : : * threads/queues before calling the device close function.
182 : : */
183 : 0 : nfp_net_disable_queues(dev);
184 : :
185 : : /* Clear queues */
186 : 0 : nfp_net_close_tx_queue(dev);
187 : 0 : nfp_net_close_rx_queue(dev);
188 : :
189 : 0 : rte_intr_disable(pci_dev->intr_handle);
190 : :
191 : : /* Unregister callback func from eal lib */
192 : 0 : rte_intr_callback_unregister(pci_dev->intr_handle,
193 : : nfp_net_dev_interrupt_handler, (void *)dev);
194 : :
195 : : /* Cancel possible impending LSC work here before releasing the port */
196 : 0 : rte_eal_alarm_cancel(nfp_net_dev_interrupt_delayed_handler, (void *)dev);
197 : :
198 : 0 : return 0;
199 : : }
200 : :
201 : : /* Initialise and register VF driver with DPDK Application */
202 : : static const struct eth_dev_ops nfp_netvf_eth_dev_ops = {
203 : : .dev_configure = nfp_net_configure,
204 : : .dev_start = nfp_netvf_start,
205 : : .dev_stop = nfp_netvf_stop,
206 : : .dev_set_link_up = nfp_netvf_set_link_up,
207 : : .dev_set_link_down = nfp_netvf_set_link_down,
208 : : .dev_close = nfp_netvf_close,
209 : : .promiscuous_enable = nfp_net_promisc_enable,
210 : : .promiscuous_disable = nfp_net_promisc_disable,
211 : : .allmulticast_enable = nfp_net_allmulticast_enable,
212 : : .allmulticast_disable = nfp_net_allmulticast_disable,
213 : : .link_update = nfp_net_link_update,
214 : : .stats_get = nfp_net_stats_get,
215 : : .stats_reset = nfp_net_stats_reset,
216 : : .xstats_get = nfp_net_xstats_get,
217 : : .xstats_reset = nfp_net_xstats_reset,
218 : : .xstats_get_names = nfp_net_xstats_get_names,
219 : : .xstats_get_by_id = nfp_net_xstats_get_by_id,
220 : : .xstats_get_names_by_id = nfp_net_xstats_get_names_by_id,
221 : : .dev_infos_get = nfp_net_infos_get,
222 : : .dev_supported_ptypes_get = nfp_net_supported_ptypes_get,
223 : : .mtu_set = nfp_net_dev_mtu_set,
224 : : .mac_addr_set = nfp_net_set_mac_addr,
225 : : .vlan_offload_set = nfp_net_vlan_offload_set,
226 : : .reta_update = nfp_net_reta_update,
227 : : .reta_query = nfp_net_reta_query,
228 : : .rss_hash_update = nfp_net_rss_hash_update,
229 : : .rss_hash_conf_get = nfp_net_rss_hash_conf_get,
230 : : .rx_queue_setup = nfp_net_rx_queue_setup,
231 : : .rx_queue_release = nfp_net_rx_queue_release,
232 : : .tx_queue_setup = nfp_net_tx_queue_setup,
233 : : .tx_queue_release = nfp_net_tx_queue_release,
234 : : .rx_queue_intr_enable = nfp_rx_queue_intr_enable,
235 : : .rx_queue_intr_disable = nfp_rx_queue_intr_disable,
236 : : .rx_burst_mode_get = nfp_net_rx_burst_mode_get,
237 : : .tx_burst_mode_get = nfp_net_tx_burst_mode_get,
238 : : };
239 : :
240 : : static inline void
241 : 0 : nfp_netvf_ethdev_ops_mount(struct nfp_pf_dev *pf_dev,
242 : : struct rte_eth_dev *eth_dev)
243 : : {
244 [ # # ]: 0 : if (pf_dev->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
245 : 0 : eth_dev->tx_pkt_burst = nfp_net_nfd3_xmit_pkts;
246 : : else
247 : 0 : nfp_net_nfdk_xmit_pkts_set(eth_dev);
248 : :
249 : 0 : eth_dev->dev_ops = &nfp_netvf_eth_dev_ops;
250 : 0 : eth_dev->rx_queue_count = nfp_net_rx_queue_count;
251 : 0 : nfp_net_recv_pkts_set(eth_dev);
252 : 0 : }
253 : :
254 : : static int
255 : 0 : nfp_netvf_init(struct rte_eth_dev *eth_dev)
256 : : {
257 : : int err;
258 : : uint16_t port;
259 : : uint32_t start_q;
260 : : struct nfp_hw *hw;
261 : : struct nfp_net_hw *net_hw;
262 : : struct nfp_pf_dev *pf_dev;
263 : : uint64_t tx_bar_off = 0;
264 : : uint64_t rx_bar_off = 0;
265 : : struct rte_pci_device *pci_dev;
266 : : struct nfp_net_hw_priv *hw_priv;
267 : : const struct nfp_dev_info *dev_info;
268 : :
269 : 0 : port = eth_dev->data->port_id;
270 : 0 : pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
271 : :
272 : 0 : dev_info = nfp_dev_info_get(pci_dev->id.device_id);
273 [ # # ]: 0 : if (dev_info == NULL) {
274 : 0 : PMD_INIT_LOG(ERR, "Not supported device ID.");
275 : 0 : return -ENODEV;
276 : : }
277 : :
278 : 0 : net_hw = eth_dev->data->dev_private;
279 : 0 : hw = &net_hw->super;
280 : :
281 : 0 : hw->ctrl_bar = pci_dev->mem_resource[0].addr;
282 [ # # ]: 0 : if (hw->ctrl_bar == NULL) {
283 : 0 : PMD_DRV_LOG(ERR, "The hw->super.ctrl_bar is NULL. BAR0 not configured.");
284 : 0 : return -ENODEV;
285 : : }
286 : :
287 : 0 : pf_dev = rte_zmalloc(NULL, sizeof(*pf_dev), 0);
288 [ # # ]: 0 : if (pf_dev == NULL) {
289 : 0 : PMD_INIT_LOG(ERR, "Can not allocate memory for the PF device.");
290 : 0 : return -ENOMEM;
291 : : }
292 : :
293 : 0 : pf_dev->pci_dev = pci_dev;
294 : :
295 : : /* Check the version from firmware */
296 [ # # ]: 0 : if (!nfp_net_version_check(hw, pf_dev)) {
297 : : err = -EINVAL;
298 : 0 : goto pf_dev_free;
299 : : }
300 : :
301 : : /* Set the ctrl bar size */
302 : 0 : nfp_net_ctrl_bar_size_set(pf_dev);
303 : :
304 : 0 : PMD_INIT_LOG(DEBUG, "Ctrl bar: %p.", hw->ctrl_bar);
305 : :
306 : 0 : err = nfp_net_common_init(pf_dev, net_hw);
307 [ # # ]: 0 : if (err != 0)
308 : 0 : goto pf_dev_free;
309 : :
310 : 0 : nfp_netvf_ethdev_ops_mount(pf_dev, eth_dev);
311 : :
312 : 0 : hw_priv = rte_zmalloc(NULL, sizeof(*hw_priv), 0);
313 [ # # ]: 0 : if (hw_priv == NULL) {
314 : 0 : PMD_INIT_LOG(ERR, "Can not alloc memory for hw priv data.");
315 : : err = -ENOMEM;
316 : 0 : goto hw_priv_free;
317 : : }
318 : :
319 : 0 : hw_priv->dev_info = dev_info;
320 : 0 : hw_priv->pf_dev = pf_dev;
321 : :
322 [ # # ]: 0 : if (!nfp_net_recv_pkt_meta_check_register(hw_priv)) {
323 : 0 : PMD_INIT_LOG(ERR, "VF register meta check function failed.");
324 : : err = -EINVAL;
325 : 0 : goto hw_priv_free;
326 : : }
327 : :
328 : 0 : eth_dev->process_private = hw_priv;
329 : :
330 : : /* For secondary processes, the primary has done all the work */
331 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
332 : : return 0;
333 : :
334 : 0 : net_hw->eth_xstats_base = rte_calloc("rte_eth_xstat",
335 : 0 : nfp_net_xstats_size(eth_dev), sizeof(struct rte_eth_xstat), 0);
336 [ # # ]: 0 : if (net_hw->eth_xstats_base == NULL) {
337 : 0 : PMD_INIT_LOG(ERR, "No memory for xstats base values on device %s!",
338 : : pci_dev->device.name);
339 : : err = -ENOMEM;
340 : 0 : goto hw_priv_free;
341 : : }
342 : :
343 : 0 : net_hw->eth_qstats_base = rte_calloc("eth_queue_stats",
344 : 0 : RTE_MAX(net_hw->max_rx_queues, net_hw->max_tx_queues),
345 : : sizeof(struct eth_queue_stats), 0);
346 [ # # ]: 0 : if (net_hw->eth_qstats_base == NULL) {
347 : 0 : PMD_INIT_LOG(ERR, "No memory for queue stats base values on device %s!",
348 : : pci_dev->device.name);
349 : 0 : rte_free(net_hw->eth_xstats_base);
350 : : err = -ENOMEM;
351 : 0 : goto hw_priv_free;
352 : : }
353 : :
354 : : /* Work out where in the BAR the queues start. */
355 : : start_q = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ);
356 : 0 : tx_bar_off = nfp_qcp_queue_offset(dev_info, start_q);
357 : : start_q = nn_cfg_readl(hw, NFP_NET_CFG_START_RXQ);
358 : 0 : rx_bar_off = nfp_qcp_queue_offset(dev_info, start_q);
359 : :
360 : 0 : net_hw->tx_bar = (uint8_t *)pci_dev->mem_resource[2].addr + tx_bar_off;
361 : 0 : net_hw->rx_bar = (uint8_t *)pci_dev->mem_resource[2].addr + rx_bar_off;
362 : :
363 : 0 : PMD_INIT_LOG(DEBUG, "The ctrl_bar: %p, tx_bar: %p, rx_bar: %p.",
364 : : hw->ctrl_bar, net_hw->tx_bar, net_hw->rx_bar);
365 : :
366 : 0 : nfp_net_cfg_queue_setup(net_hw);
367 : 0 : net_hw->mtu = RTE_ETHER_MTU;
368 : :
369 : : /* VLAN insertion is incompatible with LSOv2 */
370 [ # # ]: 0 : if ((hw->cap & NFP_NET_CFG_CTRL_LSO2) != 0)
371 : 0 : hw->cap &= ~NFP_NET_CFG_CTRL_TXVLAN;
372 : :
373 : 0 : nfp_net_log_device_information(net_hw, pf_dev);
374 : :
375 : : /* Initializing spinlock for reconfigs */
376 : : rte_spinlock_init(&hw->reconfig_lock);
377 : :
378 : : /* Allocating memory for mac addr */
379 : 0 : eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", RTE_ETHER_ADDR_LEN, 0);
380 [ # # ]: 0 : if (eth_dev->data->mac_addrs == NULL) {
381 : 0 : PMD_INIT_LOG(ERR, "Failed to space for MAC address.");
382 : : err = -ENOMEM;
383 : 0 : goto free_xstats;
384 : : }
385 : :
386 : 0 : nfp_read_mac(hw);
387 : : if (rte_is_valid_assigned_ether_addr(&hw->mac_addr) == 0) {
388 : 0 : PMD_INIT_LOG(INFO, "Using random mac address for port %hu.", port);
389 : : /* Using random mac addresses for VFs */
390 : 0 : rte_eth_random_addr(&hw->mac_addr.addr_bytes[0]);
391 : 0 : nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]);
392 : : }
393 : :
394 : : /* Copying mac address to DPDK eth_dev struct */
395 [ # # ]: 0 : rte_ether_addr_copy(&hw->mac_addr, eth_dev->data->mac_addrs);
396 : :
397 [ # # ]: 0 : if ((hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0)
398 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_NOLIVE_MAC_ADDR;
399 : :
400 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
401 : :
402 : 0 : PMD_INIT_LOG(INFO, "Port %hu VendorID=%#x DeviceID=%#x "
403 : : "mac=" RTE_ETHER_ADDR_PRT_FMT,
404 : : port, pci_dev->id.vendor_id,
405 : : pci_dev->id.device_id,
406 : : RTE_ETHER_ADDR_BYTES(&hw->mac_addr));
407 : :
408 : : /* Registering LSC interrupt handler */
409 : 0 : rte_intr_callback_register(pci_dev->intr_handle,
410 : : nfp_net_dev_interrupt_handler, (void *)eth_dev);
411 : : /* Telling the firmware about the LSC interrupt entry */
412 : : nn_cfg_writeb(hw, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
413 : : /* Unmask the LSC interrupt */
414 : 0 : nfp_net_irq_unmask(eth_dev);
415 : : /* Recording current stats counters values */
416 : 0 : nfp_net_stats_reset(eth_dev);
417 : :
418 : 0 : return 0;
419 : :
420 : : free_xstats:
421 : 0 : rte_free(net_hw->eth_qstats_base);
422 : 0 : rte_free(net_hw->eth_xstats_base);
423 : 0 : hw_priv_free:
424 : 0 : rte_free(hw_priv);
425 : 0 : pf_dev_free:
426 : 0 : rte_free(pf_dev);
427 : :
428 : 0 : return err;
429 : : }
430 : :
431 : : static const struct rte_pci_id pci_id_nfp_vf_net_map[] = {
432 : : {
433 : : RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
434 : : PCI_DEVICE_ID_NFP3800_VF_NIC)
435 : : },
436 : : {
437 : : RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
438 : : PCI_DEVICE_ID_NFP6000_VF_NIC)
439 : : },
440 : : {
441 : : RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE,
442 : : PCI_DEVICE_ID_NFP3800_VF_NIC)
443 : : },
444 : : {
445 : : RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE,
446 : : PCI_DEVICE_ID_NFP6000_VF_NIC)
447 : : },
448 : : {
449 : : .vendor_id = 0,
450 : : },
451 : : };
452 : :
453 : : static int
454 : 0 : nfp_vf_pci_uninit(struct rte_eth_dev *eth_dev)
455 : : {
456 : : /* VF cleanup, just free private port data */
457 : 0 : return nfp_netvf_close(eth_dev);
458 : : }
459 : :
460 : : static int
461 : 0 : nfp_vf_pci_probe(struct rte_pci_device *pci_dev)
462 : : {
463 : 0 : return rte_eth_dev_pci_generic_probe(pci_dev,
464 : : sizeof(struct nfp_net_hw), nfp_netvf_init);
465 : : }
466 : :
467 : : static int
468 : 0 : nfp_vf_pci_remove(struct rte_pci_device *pci_dev)
469 : : {
470 : 0 : return rte_eth_dev_pci_generic_remove(pci_dev, nfp_vf_pci_uninit);
471 : : }
472 : :
473 : : static struct nfp_class_driver rte_nfp_net_vf_pmd = {
474 : : .drv_class = NFP_CLASS_ETH,
475 : : .name = RTE_STR(net_nfp_vf),
476 : : .id_table = pci_id_nfp_vf_net_map,
477 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
478 : : .probe = nfp_vf_pci_probe,
479 : : .remove = nfp_vf_pci_remove,
480 : : };
481 : :
482 : 302 : RTE_INIT(rte_nfp_vf_pmd_init)
483 : : {
484 : 302 : nfp_class_driver_register(&rte_nfp_net_vf_pmd);
485 : 302 : }
486 : :
487 : : RTE_PMD_REGISTER_PCI_TABLE(NFP_VF_DRIVER_NAME, pci_id_nfp_vf_net_map);
488 : : RTE_PMD_REGISTER_KMOD_DEP(NFP_VF_DRIVER_NAME, "* igb_uio | uio_pci_generic | vfio");
|