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