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 <unistd.h>
9 : :
10 : : #include <eal_firmware.h>
11 : : #include <rte_alarm.h>
12 : :
13 : : #include "flower/nfp_flower.h"
14 : : #include "nfd3/nfp_nfd3.h"
15 : : #include "nfdk/nfp_nfdk.h"
16 : : #include "nfpcore/nfp_cpp.h"
17 : : #include "nfpcore/nfp_hwinfo.h"
18 : : #include "nfpcore/nfp_rtsym.h"
19 : : #include "nfpcore/nfp_nsp.h"
20 : : #include "nfpcore/nfp6000_pcie.h"
21 : : #include "nfpcore/nfp_resource.h"
22 : : #include "nfpcore/nfp_sync.h"
23 : :
24 : : #include "nfp_cpp_bridge.h"
25 : : #include "nfp_ipsec.h"
26 : : #include "nfp_logs.h"
27 : : #include "nfp_net_flow.h"
28 : :
29 : : /* 64-bit per app capabilities */
30 : : #define NFP_NET_APP_CAP_SP_INDIFF RTE_BIT64(0) /* Indifferent to port speed */
31 : :
32 : : #define NFP_PF_DRIVER_NAME net_nfp_pf
33 : :
34 : : static void
35 : : nfp_net_pf_read_mac(struct nfp_app_fw_nic *app_fw_nic,
36 : : uint16_t port)
37 : : {
38 : : struct nfp_net_hw *hw;
39 : : struct nfp_eth_table *nfp_eth_table;
40 : :
41 : : /* Grab a pointer to the correct physical port */
42 : 0 : hw = app_fw_nic->ports[port];
43 : :
44 : 0 : nfp_eth_table = app_fw_nic->pf_dev->nfp_eth_table;
45 : :
46 : : rte_ether_addr_copy(&nfp_eth_table->ports[port].mac_addr, &hw->super.mac_addr);
47 : : }
48 : :
49 : : static uint32_t
50 : 0 : nfp_net_speed_bitmap2speed(uint32_t speeds_bitmap)
51 : : {
52 [ # # # # : 0 : switch (speeds_bitmap) {
# # # # #
# # # # #
# # ]
53 : : case RTE_ETH_LINK_SPEED_10M_HD:
54 : : return RTE_ETH_SPEED_NUM_10M;
55 : : case RTE_ETH_LINK_SPEED_10M:
56 : : return RTE_ETH_SPEED_NUM_10M;
57 : 0 : case RTE_ETH_LINK_SPEED_100M_HD:
58 : 0 : return RTE_ETH_SPEED_NUM_100M;
59 : 0 : case RTE_ETH_LINK_SPEED_100M:
60 : 0 : return RTE_ETH_SPEED_NUM_100M;
61 : 0 : case RTE_ETH_LINK_SPEED_1G:
62 : 0 : return RTE_ETH_SPEED_NUM_1G;
63 : 0 : case RTE_ETH_LINK_SPEED_2_5G:
64 : 0 : return RTE_ETH_SPEED_NUM_2_5G;
65 : 0 : case RTE_ETH_LINK_SPEED_5G:
66 : 0 : return RTE_ETH_SPEED_NUM_5G;
67 : 0 : case RTE_ETH_LINK_SPEED_10G:
68 : 0 : return RTE_ETH_SPEED_NUM_10G;
69 : 0 : case RTE_ETH_LINK_SPEED_20G:
70 : 0 : return RTE_ETH_SPEED_NUM_20G;
71 : 0 : case RTE_ETH_LINK_SPEED_25G:
72 : 0 : return RTE_ETH_SPEED_NUM_25G;
73 : 0 : case RTE_ETH_LINK_SPEED_40G:
74 : 0 : return RTE_ETH_SPEED_NUM_40G;
75 : 0 : case RTE_ETH_LINK_SPEED_50G:
76 : 0 : return RTE_ETH_SPEED_NUM_50G;
77 : 0 : case RTE_ETH_LINK_SPEED_56G:
78 : 0 : return RTE_ETH_SPEED_NUM_56G;
79 : 0 : case RTE_ETH_LINK_SPEED_100G:
80 : 0 : return RTE_ETH_SPEED_NUM_100G;
81 : 0 : case RTE_ETH_LINK_SPEED_200G:
82 : 0 : return RTE_ETH_SPEED_NUM_200G;
83 : 0 : case RTE_ETH_LINK_SPEED_400G:
84 : 0 : return RTE_ETH_SPEED_NUM_400G;
85 : 0 : default:
86 : 0 : return RTE_ETH_SPEED_NUM_NONE;
87 : : }
88 : : }
89 : :
90 : : static int
91 : 0 : nfp_net_nfp4000_speed_configure_check(uint16_t port_id,
92 : : uint32_t configure_speed,
93 : : struct nfp_eth_table *nfp_eth_table)
94 : : {
95 [ # # # ]: 0 : switch (port_id) {
96 : 0 : case 0:
97 [ # # ]: 0 : if (configure_speed == RTE_ETH_SPEED_NUM_25G &&
98 [ # # ]: 0 : nfp_eth_table->ports[1].speed == RTE_ETH_SPEED_NUM_10G) {
99 : 0 : PMD_DRV_LOG(ERR, "The speed configuration is not supported for NFP4000.");
100 : 0 : return -ENOTSUP;
101 : : }
102 : : break;
103 : 0 : case 1:
104 [ # # ]: 0 : if (configure_speed == RTE_ETH_SPEED_NUM_10G &&
105 [ # # ]: 0 : nfp_eth_table->ports[0].speed == RTE_ETH_SPEED_NUM_25G) {
106 : 0 : PMD_DRV_LOG(ERR, "The speed configuration is not supported for NFP4000.");
107 : 0 : return -ENOTSUP;
108 : : }
109 : : break;
110 : 0 : default:
111 : 0 : PMD_DRV_LOG(ERR, "The port id is invalid.");
112 : 0 : return -EINVAL;
113 : : }
114 : :
115 : : return 0;
116 : : }
117 : :
118 : : static int
119 : 0 : nfp_net_speed_configure(struct rte_eth_dev *dev,
120 : : struct nfp_net_hw *net_hw)
121 : : {
122 : : int ret;
123 : : uint32_t speed_capa;
124 : : struct nfp_nsp *nsp;
125 : : uint32_t link_speeds;
126 : : uint32_t configure_speed;
127 : : struct nfp_eth_table_port *eth_port;
128 : : struct nfp_eth_table *nfp_eth_table;
129 : :
130 : 0 : nfp_eth_table = net_hw->pf_dev->nfp_eth_table;
131 : 0 : eth_port = &nfp_eth_table->ports[net_hw->idx];
132 : :
133 : 0 : speed_capa = net_hw->pf_dev->speed_capa;
134 [ # # ]: 0 : if (speed_capa == 0) {
135 : 0 : PMD_DRV_LOG(ERR, "Speed_capa is invalid.");
136 : 0 : return -EINVAL;
137 : : }
138 : :
139 : 0 : link_speeds = dev->data->dev_conf.link_speeds;
140 : 0 : configure_speed = nfp_net_speed_bitmap2speed(speed_capa & link_speeds);
141 : 0 : if (configure_speed == RTE_ETH_SPEED_NUM_NONE &&
142 [ # # ]: 0 : link_speeds != RTE_ETH_LINK_SPEED_AUTONEG) {
143 : 0 : PMD_DRV_LOG(ERR, "Configured speed is invalid.");
144 : 0 : return -EINVAL;
145 : : }
146 : :
147 : : /* NFP4000 does not allow the port 0 25Gbps and port 1 10Gbps at the same time. */
148 [ # # ]: 0 : if (net_hw->device_id == PCI_DEVICE_ID_NFP4000_PF_NIC) {
149 : 0 : ret = nfp_net_nfp4000_speed_configure_check(net_hw->idx,
150 : : configure_speed, nfp_eth_table);
151 [ # # ]: 0 : if (ret != 0) {
152 : 0 : PMD_DRV_LOG(ERR, "Failed to configure speed for NFP4000.");
153 : 0 : return ret;
154 : : }
155 : : }
156 : :
157 : 0 : nsp = nfp_eth_config_start(net_hw->cpp, eth_port->index);
158 [ # # ]: 0 : if (nsp == NULL) {
159 : 0 : PMD_DRV_LOG(ERR, "Couldn't get NSP.");
160 : 0 : return -EIO;
161 : : }
162 : :
163 [ # # ]: 0 : if (link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) {
164 [ # # ]: 0 : if (eth_port->supp_aneg) {
165 : 0 : ret = nfp_eth_set_aneg(nsp, NFP_ANEG_AUTO);
166 [ # # ]: 0 : if (ret != 0) {
167 : 0 : PMD_DRV_LOG(ERR, "Failed to set ANEG enable.");
168 : 0 : goto config_cleanup;
169 : : }
170 : : }
171 : : } else {
172 : 0 : ret = nfp_eth_set_aneg(nsp, NFP_ANEG_DISABLED);
173 [ # # ]: 0 : if (ret != 0) {
174 : 0 : PMD_DRV_LOG(ERR, "Failed to set ANEG disable.");
175 : 0 : goto config_cleanup;
176 : : }
177 : :
178 : 0 : ret = nfp_eth_set_speed(nsp, configure_speed);
179 [ # # ]: 0 : if (ret != 0) {
180 : 0 : PMD_DRV_LOG(ERR, "Failed to set speed.");
181 : 0 : goto config_cleanup;
182 : : }
183 : : }
184 : :
185 : 0 : return nfp_eth_config_commit_end(nsp);
186 : :
187 : 0 : config_cleanup:
188 : 0 : nfp_eth_config_cleanup_end(nsp);
189 : :
190 : 0 : return ret;
191 : : }
192 : :
193 : : static int
194 : 0 : nfp_net_start(struct rte_eth_dev *dev)
195 : : {
196 : : int ret;
197 : : uint16_t i;
198 : : struct nfp_hw *hw;
199 : : uint32_t new_ctrl;
200 : : struct nfp_cpp *cpp;
201 : : uint32_t update = 0;
202 : : uint32_t cap_extend;
203 : : uint32_t intr_vector;
204 : : uint32_t ctrl_extend = 0;
205 : : struct nfp_net_hw *net_hw;
206 : : struct nfp_pf_dev *pf_dev;
207 : : struct rte_eth_rxmode *rxmode;
208 : : struct nfp_app_fw_nic *app_fw_nic;
209 : 0 : struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
210 : 0 : struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
211 : :
212 : 0 : net_hw = dev->data->dev_private;
213 : 0 : pf_dev = net_hw->pf_dev;
214 : 0 : app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv);
215 : 0 : hw = &net_hw->super;
216 : :
217 : : /* Disabling queues just in case... */
218 : 0 : nfp_net_disable_queues(dev);
219 : :
220 : : /* Enabling the required queues in the device */
221 : 0 : nfp_net_enable_queues(dev);
222 : :
223 : : /* Configure the port speed and the auto-negotiation mode. */
224 : 0 : ret = nfp_net_speed_configure(dev, net_hw);
225 [ # # ]: 0 : if (ret < 0) {
226 : 0 : PMD_DRV_LOG(ERR, "Failed to set the speed and auto-negotiation mode.");
227 : 0 : return ret;
228 : : }
229 : :
230 : : /* Check and configure queue intr-vector mapping */
231 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.rxq != 0) {
232 [ # # ]: 0 : if (app_fw_nic->multiport) {
233 : 0 : PMD_INIT_LOG(ERR, "PMD rx interrupt is not supported "
234 : : "with NFP multiport PF");
235 : 0 : return -EINVAL;
236 : : }
237 : :
238 [ # # ]: 0 : if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) {
239 : : /*
240 : : * Better not to share LSC with RX interrupts.
241 : : * Unregistering LSC interrupt handler.
242 : : */
243 : 0 : rte_intr_callback_unregister(intr_handle,
244 : : nfp_net_dev_interrupt_handler, (void *)dev);
245 : :
246 [ # # ]: 0 : if (dev->data->nb_rx_queues > 1) {
247 : 0 : PMD_INIT_LOG(ERR, "PMD rx interrupt only "
248 : : "supports 1 queue with UIO");
249 : 0 : return -EIO;
250 : : }
251 : : }
252 : :
253 : 0 : intr_vector = dev->data->nb_rx_queues;
254 [ # # ]: 0 : if (rte_intr_efd_enable(intr_handle, intr_vector) != 0)
255 : : return -1;
256 : :
257 : 0 : nfp_configure_rx_interrupt(dev, intr_handle);
258 : : update = NFP_NET_CFG_UPDATE_MSIX;
259 : : }
260 : :
261 : : /* Checking MTU set */
262 [ # # ]: 0 : if (dev->data->mtu > net_hw->flbufsz) {
263 : 0 : PMD_INIT_LOG(ERR, "MTU (%u) can't be larger than the current NFP_FRAME_SIZE (%u)",
264 : : dev->data->mtu, net_hw->flbufsz);
265 : 0 : return -ERANGE;
266 : : }
267 : :
268 : 0 : rte_intr_enable(intr_handle);
269 : :
270 : 0 : new_ctrl = nfp_check_offloads(dev);
271 : :
272 : : /* Writing configuration parameters in the device */
273 : 0 : nfp_net_params_setup(net_hw);
274 : :
275 : 0 : rxmode = &dev->data->dev_conf.rxmode;
276 [ # # ]: 0 : if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS) != 0) {
277 : 0 : nfp_net_rss_config_default(dev);
278 : 0 : update |= NFP_NET_CFG_UPDATE_RSS;
279 [ # # ]: 0 : new_ctrl |= nfp_net_cfg_ctrl_rss(hw->cap);
280 : : }
281 : :
282 : : /* Enable device */
283 : 0 : new_ctrl |= NFP_NET_CFG_CTRL_ENABLE;
284 : :
285 : 0 : update |= NFP_NET_CFG_UPDATE_GEN | NFP_NET_CFG_UPDATE_RING;
286 : :
287 : : /* Enable vxlan */
288 [ # # ]: 0 : if ((hw->cap & NFP_NET_CFG_CTRL_VXLAN) != 0) {
289 : 0 : new_ctrl |= NFP_NET_CFG_CTRL_VXLAN;
290 : 0 : update |= NFP_NET_CFG_UPDATE_VXLAN;
291 : : }
292 : :
293 [ # # ]: 0 : if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0)
294 : 0 : new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG;
295 : :
296 [ # # ]: 0 : if (nfp_reconfig(hw, new_ctrl, update) != 0)
297 : : return -EIO;
298 : :
299 : 0 : hw->ctrl = new_ctrl;
300 : :
301 : : /* Enable packet type offload by extend ctrl word1. */
302 : 0 : cap_extend = hw->cap_ext;
303 [ # # ]: 0 : if ((cap_extend & NFP_NET_CFG_CTRL_PKT_TYPE) != 0)
304 : : ctrl_extend = NFP_NET_CFG_CTRL_PKT_TYPE;
305 : :
306 [ # # ]: 0 : if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0)
307 : 0 : ctrl_extend |= NFP_NET_CFG_CTRL_IPSEC |
308 : : NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP |
309 : : NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP;
310 : :
311 : : /* Enable flow steer by extend ctrl word1. */
312 [ # # ]: 0 : if ((cap_extend & NFP_NET_CFG_CTRL_FLOW_STEER) != 0)
313 : 0 : ctrl_extend |= NFP_NET_CFG_CTRL_FLOW_STEER;
314 : :
315 : : update = NFP_NET_CFG_UPDATE_GEN;
316 [ # # ]: 0 : if (nfp_ext_reconfig(hw, ctrl_extend, update) != 0)
317 : : return -EIO;
318 : :
319 : 0 : hw->ctrl_ext = ctrl_extend;
320 : :
321 : : /*
322 : : * Allocating rte mbufs for configured rx queues.
323 : : * This requires queues being enabled before.
324 : : */
325 [ # # ]: 0 : if (nfp_net_rx_freelist_setup(dev) != 0) {
326 : : ret = -ENOMEM;
327 : 0 : goto error;
328 : : }
329 : :
330 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY)
331 : 0 : cpp = net_hw->cpp;
332 : : else
333 : 0 : cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp;
334 : :
335 : : /* Configure the physical port up */
336 : 0 : nfp_eth_set_configured(cpp, net_hw->nfp_idx, 1);
337 : :
338 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
339 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
340 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
341 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
342 : :
343 : : return 0;
344 : :
345 : : error:
346 : : /*
347 : : * An error returned by this function should mean the app
348 : : * exiting and then the system releasing all the memory
349 : : * allocated even memory coming from hugepages.
350 : : *
351 : : * The device could be enabled at this point with some queues
352 : : * ready for getting packets. This is true if the call to
353 : : * nfp_net_rx_freelist_setup() succeeds for some queues but
354 : : * fails for subsequent queues.
355 : : *
356 : : * This should make the app exiting but better if we tell the
357 : : * device first.
358 : : */
359 : 0 : nfp_net_disable_queues(dev);
360 : :
361 : 0 : return ret;
362 : : }
363 : :
364 : : /* Set the link up. */
365 : : static int
366 : 0 : nfp_net_set_link_up(struct rte_eth_dev *dev)
367 : : {
368 : : struct nfp_cpp *cpp;
369 : : struct nfp_net_hw *hw;
370 : :
371 : 0 : hw = dev->data->dev_private;
372 : :
373 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY)
374 : 0 : cpp = hw->cpp;
375 : : else
376 : 0 : cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp;
377 : :
378 : 0 : return nfp_eth_set_configured(cpp, hw->nfp_idx, 1);
379 : : }
380 : :
381 : : /* Set the link down. */
382 : : static int
383 : 0 : nfp_net_set_link_down(struct rte_eth_dev *dev)
384 : : {
385 : : struct nfp_cpp *cpp;
386 : : struct nfp_net_hw *hw;
387 : :
388 : 0 : hw = dev->data->dev_private;
389 : :
390 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY)
391 : 0 : cpp = hw->cpp;
392 : : else
393 : 0 : cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp;
394 : :
395 : 0 : return nfp_eth_set_configured(cpp, hw->nfp_idx, 0);
396 : : }
397 : :
398 : : static uint8_t
399 : : nfp_function_id_get(const struct nfp_pf_dev *pf_dev,
400 : : uint8_t phy_port)
401 : : {
402 [ # # # # : 0 : if (pf_dev->multi_pf.enabled)
# # # # ]
403 : 0 : return pf_dev->multi_pf.function_id;
404 : :
405 : : return phy_port;
406 : : }
407 : :
408 : : static void
409 : 0 : nfp_net_beat_timer(void *arg)
410 : : {
411 : : uint64_t cur_sec;
412 : : struct nfp_multi_pf *multi_pf = arg;
413 : :
414 : : cur_sec = rte_rdtsc();
415 : 0 : nn_writeq(cur_sec, multi_pf->beat_addr + NFP_BEAT_OFFSET(multi_pf->function_id));
416 : :
417 : : /* Beat once per second. */
418 [ # # ]: 0 : if (rte_eal_alarm_set(1000 * 1000, nfp_net_beat_timer,
419 : : (void *)multi_pf) < 0) {
420 : 0 : PMD_DRV_LOG(ERR, "Error setting alarm");
421 : : }
422 : 0 : }
423 : :
424 : : static int
425 : 0 : nfp_net_keepalive_init(struct nfp_cpp *cpp,
426 : : struct nfp_multi_pf *multi_pf)
427 : : {
428 : : uint8_t *base;
429 : : uint64_t addr;
430 : : uint32_t size;
431 : : uint32_t cpp_id;
432 : : struct nfp_resource *res;
433 : :
434 : 0 : res = nfp_resource_acquire(cpp, NFP_RESOURCE_KEEPALIVE);
435 [ # # ]: 0 : if (res == NULL)
436 : : return -EIO;
437 : :
438 : 0 : cpp_id = nfp_resource_cpp_id(res);
439 : 0 : addr = nfp_resource_address(res);
440 : 0 : size = nfp_resource_size(res);
441 : :
442 : 0 : nfp_resource_release(res);
443 : :
444 : : /* Allocate a fixed area for keepalive. */
445 : 0 : base = nfp_cpp_map_area(cpp, cpp_id, addr, size, &multi_pf->beat_area);
446 [ # # ]: 0 : if (base == NULL) {
447 : 0 : PMD_DRV_LOG(ERR, "Failed to map area for keepalive.");
448 : 0 : return -EIO;
449 : : }
450 : :
451 : 0 : multi_pf->beat_addr = base;
452 : :
453 : 0 : return 0;
454 : : }
455 : :
456 : : static void
457 : : nfp_net_keepalive_uninit(struct nfp_multi_pf *multi_pf)
458 : : {
459 : 0 : nfp_cpp_area_release_free(multi_pf->beat_area);
460 : 0 : }
461 : :
462 : : static int
463 : 0 : nfp_net_keepalive_start(struct nfp_multi_pf *multi_pf)
464 : : {
465 [ # # ]: 0 : if (rte_eal_alarm_set(1000 * 1000, nfp_net_beat_timer,
466 : : (void *)multi_pf) < 0) {
467 : 0 : PMD_DRV_LOG(ERR, "Error setting alarm");
468 : 0 : return -EIO;
469 : : }
470 : :
471 : : return 0;
472 : : }
473 : :
474 : : static void
475 : : nfp_net_keepalive_clear(uint8_t *beat_addr,
476 : : uint8_t function_id)
477 : : {
478 : 0 : nn_writeq(0, beat_addr + NFP_BEAT_OFFSET(function_id));
479 : 0 : }
480 : :
481 : : static void
482 : : nfp_net_keepalive_clear_others(const struct nfp_dev_info *dev_info,
483 : : struct nfp_multi_pf *multi_pf)
484 : : {
485 : : uint8_t port_num;
486 : :
487 [ # # ]: 0 : for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) {
488 [ # # ]: 0 : if (port_num == multi_pf->function_id)
489 : 0 : continue;
490 : :
491 : 0 : nfp_net_keepalive_clear(multi_pf->beat_addr, port_num);
492 : : }
493 : : }
494 : :
495 : : static void
496 : : nfp_net_keepalive_stop(struct nfp_multi_pf *multi_pf)
497 : : {
498 : : /* Cancel keepalive for multiple PF setup */
499 : 0 : rte_eal_alarm_cancel(nfp_net_beat_timer, (void *)multi_pf);
500 : : }
501 : :
502 : : static void
503 : 0 : nfp_net_uninit(struct rte_eth_dev *eth_dev)
504 : : {
505 : : struct nfp_net_hw *net_hw;
506 : :
507 : 0 : net_hw = eth_dev->data->dev_private;
508 : :
509 [ # # ]: 0 : if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0)
510 : 0 : nfp_net_flow_priv_uninit(net_hw->pf_dev, net_hw->idx);
511 : :
512 : 0 : rte_free(net_hw->eth_xstats_base);
513 : 0 : nfp_ipsec_uninit(eth_dev);
514 [ # # ]: 0 : if (net_hw->mac_stats_area != NULL)
515 : 0 : nfp_cpp_area_release_free(net_hw->mac_stats_area);
516 : 0 : }
517 : :
518 : : static void
519 : 0 : nfp_cleanup_port_app_fw_nic(struct nfp_pf_dev *pf_dev,
520 : : uint8_t id)
521 : : {
522 : : struct rte_eth_dev *eth_dev;
523 : : struct nfp_app_fw_nic *app_fw_nic;
524 : :
525 : 0 : app_fw_nic = pf_dev->app_fw_priv;
526 [ # # ]: 0 : if (app_fw_nic->ports[id] != NULL) {
527 : 0 : eth_dev = app_fw_nic->ports[id]->eth_dev;
528 [ # # ]: 0 : if (eth_dev != NULL)
529 : 0 : nfp_net_uninit(eth_dev);
530 : :
531 : 0 : app_fw_nic->ports[id] = NULL;
532 : : }
533 : 0 : }
534 : :
535 : : static void
536 : : nfp_uninit_app_fw_nic(struct nfp_pf_dev *pf_dev)
537 : : {
538 : 0 : nfp_cpp_area_release_free(pf_dev->ctrl_area);
539 : 0 : rte_free(pf_dev->app_fw_priv);
540 : : }
541 : :
542 : : void
543 : 0 : nfp_pf_uninit(struct nfp_pf_dev *pf_dev)
544 : : {
545 : 0 : nfp_cpp_area_release_free(pf_dev->qc_area);
546 : 0 : free(pf_dev->sym_tbl);
547 [ # # ]: 0 : if (pf_dev->multi_pf.enabled) {
548 : 0 : nfp_net_keepalive_stop(&pf_dev->multi_pf);
549 : 0 : nfp_net_keepalive_clear(pf_dev->multi_pf.beat_addr, pf_dev->multi_pf.function_id);
550 : : nfp_net_keepalive_uninit(&pf_dev->multi_pf);
551 : : }
552 : 0 : free(pf_dev->nfp_eth_table);
553 : 0 : free(pf_dev->hwinfo);
554 : 0 : nfp_cpp_free(pf_dev->cpp);
555 : 0 : nfp_sync_free(pf_dev->sync);
556 : 0 : rte_free(pf_dev);
557 : 0 : }
558 : :
559 : : static int
560 : 0 : nfp_pf_secondary_uninit(struct nfp_pf_dev *pf_dev)
561 : : {
562 : 0 : free(pf_dev->sym_tbl);
563 : 0 : nfp_cpp_free(pf_dev->cpp);
564 : 0 : nfp_sync_free(pf_dev->sync);
565 : 0 : rte_free(pf_dev);
566 : :
567 : 0 : return 0;
568 : : }
569 : :
570 : : /* Reset and stop device. The device can not be restarted. */
571 : : static int
572 : 0 : nfp_net_close(struct rte_eth_dev *dev)
573 : : {
574 : : uint8_t i;
575 : : uint8_t id;
576 : : struct nfp_net_hw *hw;
577 : : struct nfp_pf_dev *pf_dev;
578 : : struct rte_pci_device *pci_dev;
579 : : struct nfp_app_fw_nic *app_fw_nic;
580 : :
581 : : /*
582 : : * In secondary process, a released eth device can be found by its name
583 : : * in shared memory.
584 : : * If the state of the eth device is RTE_ETH_DEV_UNUSED, it means the
585 : : * eth device has been released.
586 : : */
587 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
588 [ # # ]: 0 : if (dev->state == RTE_ETH_DEV_UNUSED)
589 : : return 0;
590 : :
591 : 0 : nfp_pf_secondary_uninit(dev->process_private);
592 : 0 : return 0;
593 : : }
594 : :
595 : 0 : hw = dev->data->dev_private;
596 : 0 : pf_dev = hw->pf_dev;
597 : 0 : pci_dev = RTE_ETH_DEV_TO_PCI(dev);
598 : 0 : app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv);
599 : :
600 : : /*
601 : : * We assume that the DPDK application is stopping all the
602 : : * threads/queues before calling the device close function.
603 : : */
604 : 0 : nfp_net_disable_queues(dev);
605 : :
606 : : /* Clear queues */
607 : 0 : nfp_net_close_tx_queue(dev);
608 : 0 : nfp_net_close_rx_queue(dev);
609 : :
610 : : /* Cancel possible impending LSC work here before releasing the port */
611 : 0 : rte_eal_alarm_cancel(nfp_net_dev_interrupt_delayed_handler, (void *)dev);
612 : :
613 : : /* Only free PF resources after all physical ports have been closed */
614 : : /* Mark this port as unused and free device priv resources */
615 : : nn_cfg_writeb(&hw->super, NFP_NET_CFG_LSC, 0xff);
616 : :
617 [ # # ]: 0 : if (pf_dev->app_fw_id != NFP_APP_FW_CORE_NIC)
618 : : return -EINVAL;
619 : :
620 : 0 : nfp_cleanup_port_app_fw_nic(pf_dev, hw->idx);
621 : :
622 [ # # ]: 0 : for (i = 0; i < app_fw_nic->total_phyports; i++) {
623 : : id = nfp_function_id_get(pf_dev, i);
624 : :
625 : : /* Check to see if ports are still in use */
626 [ # # ]: 0 : if (app_fw_nic->ports[id] != NULL)
627 : : return 0;
628 : : }
629 : :
630 : : /* Enable in nfp_net_start() */
631 : 0 : rte_intr_disable(pci_dev->intr_handle);
632 : :
633 : : /* Register in nfp_net_init() */
634 : 0 : rte_intr_callback_unregister(pci_dev->intr_handle,
635 : : nfp_net_dev_interrupt_handler, (void *)dev);
636 : :
637 : : nfp_uninit_app_fw_nic(pf_dev);
638 : 0 : nfp_pf_uninit(pf_dev);
639 : :
640 : 0 : return 0;
641 : : }
642 : :
643 : : static int
644 : : nfp_net_find_vxlan_idx(struct nfp_net_hw *hw,
645 : : uint16_t port,
646 : : uint32_t *idx)
647 : : {
648 : : uint32_t i;
649 : : int free_idx = -1;
650 : :
651 [ # # # # ]: 0 : for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i++) {
652 [ # # # # ]: 0 : if (hw->vxlan_ports[i] == port) {
653 : 0 : free_idx = i;
654 : 0 : break;
655 : : }
656 : :
657 [ # # # # ]: 0 : if (hw->vxlan_usecnt[i] == 0) {
658 : 0 : free_idx = i;
659 : 0 : break;
660 : : }
661 : : }
662 : :
663 [ # # # # ]: 0 : if (free_idx == -1)
664 : : return -EINVAL;
665 : :
666 : 0 : *idx = free_idx;
667 : :
668 : : return 0;
669 : : }
670 : :
671 : : static int
672 : 0 : nfp_udp_tunnel_port_add(struct rte_eth_dev *dev,
673 : : struct rte_eth_udp_tunnel *tunnel_udp)
674 : : {
675 : : int ret;
676 : : uint32_t idx;
677 : : uint16_t vxlan_port;
678 : : struct nfp_net_hw *hw;
679 : : enum rte_eth_tunnel_type tnl_type;
680 : :
681 : 0 : hw = dev->data->dev_private;
682 : 0 : vxlan_port = tunnel_udp->udp_port;
683 : 0 : tnl_type = tunnel_udp->prot_type;
684 : :
685 [ # # ]: 0 : if (tnl_type != RTE_ETH_TUNNEL_TYPE_VXLAN) {
686 : 0 : PMD_DRV_LOG(ERR, "Not VXLAN tunnel");
687 : 0 : return -ENOTSUP;
688 : : }
689 : :
690 : 0 : ret = nfp_net_find_vxlan_idx(hw, vxlan_port, &idx);
691 : : if (ret != 0) {
692 : 0 : PMD_DRV_LOG(ERR, "Failed find valid vxlan idx");
693 : 0 : return -EINVAL;
694 : : }
695 : :
696 [ # # ]: 0 : if (hw->vxlan_usecnt[idx] == 0) {
697 : 0 : ret = nfp_net_set_vxlan_port(hw, idx, vxlan_port);
698 [ # # ]: 0 : if (ret != 0) {
699 : 0 : PMD_DRV_LOG(ERR, "Failed set vxlan port");
700 : 0 : return -EINVAL;
701 : : }
702 : : }
703 : :
704 : 0 : hw->vxlan_usecnt[idx]++;
705 : :
706 : 0 : return 0;
707 : : }
708 : :
709 : : static int
710 : 0 : nfp_udp_tunnel_port_del(struct rte_eth_dev *dev,
711 : : struct rte_eth_udp_tunnel *tunnel_udp)
712 : : {
713 : : int ret;
714 : : uint32_t idx;
715 : : uint16_t vxlan_port;
716 : : struct nfp_net_hw *hw;
717 : : enum rte_eth_tunnel_type tnl_type;
718 : :
719 : 0 : hw = dev->data->dev_private;
720 : 0 : vxlan_port = tunnel_udp->udp_port;
721 : 0 : tnl_type = tunnel_udp->prot_type;
722 : :
723 [ # # ]: 0 : if (tnl_type != RTE_ETH_TUNNEL_TYPE_VXLAN) {
724 : 0 : PMD_DRV_LOG(ERR, "Not VXLAN tunnel");
725 : 0 : return -ENOTSUP;
726 : : }
727 : :
728 : : ret = nfp_net_find_vxlan_idx(hw, vxlan_port, &idx);
729 [ # # ]: 0 : if (ret != 0 || hw->vxlan_usecnt[idx] == 0) {
730 : 0 : PMD_DRV_LOG(ERR, "Failed find valid vxlan idx");
731 : 0 : return -EINVAL;
732 : : }
733 : :
734 : 0 : hw->vxlan_usecnt[idx]--;
735 : :
736 [ # # ]: 0 : if (hw->vxlan_usecnt[idx] == 0) {
737 : 0 : ret = nfp_net_set_vxlan_port(hw, idx, 0);
738 [ # # ]: 0 : if (ret != 0) {
739 : 0 : PMD_DRV_LOG(ERR, "Failed set vxlan port");
740 : 0 : return -EINVAL;
741 : : }
742 : : }
743 : :
744 : : return 0;
745 : : }
746 : :
747 : : /* Initialise and register driver with DPDK Application */
748 : : static const struct eth_dev_ops nfp_net_eth_dev_ops = {
749 : : .dev_configure = nfp_net_configure,
750 : : .dev_start = nfp_net_start,
751 : : .dev_stop = nfp_net_stop,
752 : : .dev_set_link_up = nfp_net_set_link_up,
753 : : .dev_set_link_down = nfp_net_set_link_down,
754 : : .dev_close = nfp_net_close,
755 : : .promiscuous_enable = nfp_net_promisc_enable,
756 : : .promiscuous_disable = nfp_net_promisc_disable,
757 : : .allmulticast_enable = nfp_net_allmulticast_enable,
758 : : .allmulticast_disable = nfp_net_allmulticast_disable,
759 : : .link_update = nfp_net_link_update,
760 : : .stats_get = nfp_net_stats_get,
761 : : .stats_reset = nfp_net_stats_reset,
762 : : .xstats_get = nfp_net_xstats_get,
763 : : .xstats_reset = nfp_net_xstats_reset,
764 : : .xstats_get_names = nfp_net_xstats_get_names,
765 : : .xstats_get_by_id = nfp_net_xstats_get_by_id,
766 : : .xstats_get_names_by_id = nfp_net_xstats_get_names_by_id,
767 : : .dev_infos_get = nfp_net_infos_get,
768 : : .dev_supported_ptypes_get = nfp_net_supported_ptypes_get,
769 : : .mtu_set = nfp_net_dev_mtu_set,
770 : : .mac_addr_set = nfp_net_set_mac_addr,
771 : : .vlan_offload_set = nfp_net_vlan_offload_set,
772 : : .reta_update = nfp_net_reta_update,
773 : : .reta_query = nfp_net_reta_query,
774 : : .rss_hash_update = nfp_net_rss_hash_update,
775 : : .rss_hash_conf_get = nfp_net_rss_hash_conf_get,
776 : : .rx_queue_setup = nfp_net_rx_queue_setup,
777 : : .rx_queue_release = nfp_net_rx_queue_release,
778 : : .tx_queue_setup = nfp_net_tx_queue_setup,
779 : : .tx_queue_release = nfp_net_tx_queue_release,
780 : : .rx_queue_intr_enable = nfp_rx_queue_intr_enable,
781 : : .rx_queue_intr_disable = nfp_rx_queue_intr_disable,
782 : : .udp_tunnel_port_add = nfp_udp_tunnel_port_add,
783 : : .udp_tunnel_port_del = nfp_udp_tunnel_port_del,
784 : : .fw_version_get = nfp_net_firmware_version_get,
785 : : .flow_ctrl_get = nfp_net_flow_ctrl_get,
786 : : .flow_ctrl_set = nfp_net_flow_ctrl_set,
787 : : .flow_ops_get = nfp_net_flow_ops_get,
788 : : .fec_get_capability = nfp_net_fec_get_capability,
789 : : .fec_get = nfp_net_fec_get,
790 : : .fec_set = nfp_net_fec_set,
791 : : };
792 : :
793 : : static inline void
794 : : nfp_net_ethdev_ops_mount(struct nfp_net_hw *hw,
795 : : struct rte_eth_dev *eth_dev)
796 : : {
797 [ # # ]: 0 : if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
798 : 0 : eth_dev->tx_pkt_burst = nfp_net_nfd3_xmit_pkts;
799 : : else
800 : 0 : eth_dev->tx_pkt_burst = nfp_net_nfdk_xmit_pkts;
801 : :
802 : 0 : eth_dev->dev_ops = &nfp_net_eth_dev_ops;
803 : 0 : eth_dev->rx_queue_count = nfp_net_rx_queue_count;
804 : 0 : eth_dev->rx_pkt_burst = &nfp_net_recv_pkts;
805 : : }
806 : :
807 : : static int
808 : 0 : nfp_net_init(struct rte_eth_dev *eth_dev)
809 : : {
810 : : int err;
811 : : uint16_t port;
812 : : uint64_t rx_base;
813 : : uint64_t tx_base;
814 : : struct nfp_hw *hw;
815 : : struct nfp_net_hw *net_hw;
816 : : struct nfp_pf_dev *pf_dev;
817 : : struct rte_pci_device *pci_dev;
818 : : struct nfp_app_fw_nic *app_fw_nic;
819 : :
820 : 0 : pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
821 : 0 : net_hw = eth_dev->data->dev_private;
822 : :
823 : : /* Use backpointer here to the PF of this eth_dev */
824 : 0 : pf_dev = net_hw->pf_dev;
825 : :
826 : : /* Use backpointer to the CoreNIC app struct */
827 : 0 : app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv);
828 : :
829 : 0 : port = ((struct nfp_net_hw *)eth_dev->data->dev_private)->idx;
830 [ # # ]: 0 : if (port > 7) {
831 : 0 : PMD_DRV_LOG(ERR, "Port value is wrong");
832 : 0 : return -ENODEV;
833 : : }
834 : :
835 : 0 : hw = &net_hw->super;
836 : :
837 : 0 : PMD_INIT_LOG(DEBUG, "Working with physical port number: %hu, "
838 : : "NFP internal port number: %d", port, net_hw->nfp_idx);
839 : :
840 : 0 : rte_eth_copy_pci_info(eth_dev, pci_dev);
841 : :
842 [ # # # # ]: 0 : if (port == 0 || pf_dev->multi_pf.enabled) {
843 : : uint32_t min_size;
844 : :
845 : 0 : hw->ctrl_bar = pf_dev->ctrl_bar;
846 : 0 : min_size = NFP_MAC_STATS_SIZE * net_hw->pf_dev->nfp_eth_table->max_index;
847 : 0 : net_hw->mac_stats_bar = nfp_rtsym_map(net_hw->pf_dev->sym_tbl, "_mac_stats",
848 : : min_size, &net_hw->mac_stats_area);
849 [ # # ]: 0 : if (net_hw->mac_stats_bar == NULL) {
850 : 0 : PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for _mac_stats_bar");
851 : 0 : return -EIO;
852 : : }
853 : :
854 : 0 : net_hw->mac_stats = net_hw->mac_stats_bar;
855 : : } else {
856 : : /* Use port offset in pf ctrl_bar for this ports control bar */
857 : 0 : hw->ctrl_bar = pf_dev->ctrl_bar + (port * NFP_NET_CFG_BAR_SZ);
858 : 0 : net_hw->mac_stats = app_fw_nic->ports[0]->mac_stats_bar +
859 : 0 : (net_hw->nfp_idx * NFP_MAC_STATS_SIZE);
860 : : }
861 : :
862 : 0 : PMD_INIT_LOG(DEBUG, "ctrl bar: %p", hw->ctrl_bar);
863 : 0 : PMD_INIT_LOG(DEBUG, "MAC stats: %p", net_hw->mac_stats);
864 : :
865 : 0 : err = nfp_net_common_init(pci_dev, net_hw);
866 [ # # ]: 0 : if (err != 0)
867 : 0 : goto free_area;
868 : :
869 : 0 : err = nfp_net_tlv_caps_parse(eth_dev);
870 [ # # ]: 0 : if (err != 0) {
871 : 0 : PMD_INIT_LOG(ERR, "Failed to parser TLV caps");
872 : 0 : return err;
873 : : goto free_area;
874 : : }
875 : :
876 : 0 : err = nfp_ipsec_init(eth_dev);
877 [ # # ]: 0 : if (err != 0) {
878 : 0 : PMD_INIT_LOG(ERR, "Failed to init IPsec module");
879 : 0 : goto free_area;
880 : : }
881 : :
882 : : nfp_net_ethdev_ops_mount(net_hw, eth_dev);
883 : :
884 : 0 : net_hw->eth_xstats_base = rte_malloc("rte_eth_xstat", sizeof(struct rte_eth_xstat) *
885 : 0 : nfp_net_xstats_size(eth_dev), 0);
886 [ # # ]: 0 : if (net_hw->eth_xstats_base == NULL) {
887 : 0 : PMD_INIT_LOG(ERR, "no memory for xstats base values on device %s!",
888 : : pci_dev->device.name);
889 : : err = -ENOMEM;
890 : 0 : goto ipsec_exit;
891 : : }
892 : :
893 : : /* Work out where in the BAR the queues start. */
894 : 0 : tx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ);
895 : 0 : rx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_RXQ);
896 : :
897 : 0 : net_hw->tx_bar = pf_dev->qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ;
898 : 0 : net_hw->rx_bar = pf_dev->qc_bar + rx_base * NFP_QCP_QUEUE_ADDR_SZ;
899 : 0 : eth_dev->data->dev_private = net_hw;
900 : :
901 : 0 : PMD_INIT_LOG(DEBUG, "ctrl_bar: %p, tx_bar: %p, rx_bar: %p",
902 : : hw->ctrl_bar, net_hw->tx_bar, net_hw->rx_bar);
903 : :
904 : 0 : nfp_net_cfg_queue_setup(net_hw);
905 : 0 : net_hw->mtu = RTE_ETHER_MTU;
906 : :
907 : : /* VLAN insertion is incompatible with LSOv2 */
908 [ # # ]: 0 : if ((hw->cap & NFP_NET_CFG_CTRL_LSO2) != 0)
909 : 0 : hw->cap &= ~NFP_NET_CFG_CTRL_TXVLAN;
910 : :
911 : 0 : nfp_net_log_device_information(net_hw);
912 : :
913 : : /* Initializing spinlock for reconfigs */
914 : : rte_spinlock_init(&hw->reconfig_lock);
915 : :
916 : : /* Allocating memory for mac addr */
917 : 0 : eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", RTE_ETHER_ADDR_LEN, 0);
918 [ # # ]: 0 : if (eth_dev->data->mac_addrs == NULL) {
919 : 0 : PMD_INIT_LOG(ERR, "Failed to space for MAC address");
920 : : err = -ENOMEM;
921 : 0 : goto xstats_free;
922 : : }
923 : :
924 : : nfp_net_pf_read_mac(app_fw_nic, port);
925 : 0 : nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]);
926 : :
927 : : if (rte_is_valid_assigned_ether_addr(&hw->mac_addr) == 0) {
928 : 0 : PMD_INIT_LOG(INFO, "Using random mac address for port %d", port);
929 : : /* Using random mac addresses for VFs */
930 : 0 : rte_eth_random_addr(&hw->mac_addr.addr_bytes[0]);
931 : 0 : nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]);
932 : : }
933 : :
934 : : /* Copying mac address to DPDK eth_dev struct */
935 [ # # ]: 0 : rte_ether_addr_copy(&hw->mac_addr, eth_dev->data->mac_addrs);
936 : :
937 [ # # ]: 0 : if ((hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0)
938 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_NOLIVE_MAC_ADDR;
939 : :
940 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
941 : :
942 : 0 : PMD_INIT_LOG(INFO, "port %d VendorID=%#x DeviceID=%#x "
943 : : "mac=" RTE_ETHER_ADDR_PRT_FMT,
944 : : eth_dev->data->port_id, pci_dev->id.vendor_id,
945 : : pci_dev->id.device_id,
946 : : RTE_ETHER_ADDR_BYTES(&hw->mac_addr));
947 : :
948 : : /* Registering LSC interrupt handler */
949 : 0 : rte_intr_callback_register(pci_dev->intr_handle,
950 : : nfp_net_dev_interrupt_handler, (void *)eth_dev);
951 : : /* Telling the firmware about the LSC interrupt entry */
952 : : nn_cfg_writeb(hw, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
953 : : /* Unmask the LSC interrupt */
954 : 0 : nfp_net_irq_unmask(eth_dev);
955 : : /* Recording current stats counters values */
956 : 0 : nfp_net_stats_reset(eth_dev);
957 : :
958 [ # # ]: 0 : if ((hw->cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) {
959 : 0 : err = nfp_net_flow_priv_init(pf_dev, port);
960 [ # # ]: 0 : if (err != 0) {
961 : 0 : PMD_INIT_LOG(ERR, "Init net flow priv failed");
962 : 0 : goto xstats_free;
963 : : }
964 : : }
965 : :
966 : : return 0;
967 : :
968 : 0 : xstats_free:
969 : 0 : rte_free(net_hw->eth_xstats_base);
970 : 0 : ipsec_exit:
971 : 0 : nfp_ipsec_uninit(eth_dev);
972 : 0 : free_area:
973 [ # # ]: 0 : if (net_hw->mac_stats_area != NULL)
974 : 0 : nfp_cpp_area_release_free(net_hw->mac_stats_area);
975 : :
976 : : return err;
977 : : }
978 : :
979 : : #define DEFAULT_FW_PATH "/lib/firmware/netronome"
980 : :
981 : : static int
982 : 0 : nfp_fw_get_name(struct rte_pci_device *dev,
983 : : struct nfp_nsp *nsp,
984 : : char *card,
985 : : char *fw_name,
986 : : size_t fw_size)
987 : : {
988 : : char serial[40];
989 : : uint16_t interface;
990 : : uint32_t cpp_serial_len;
991 : : const uint8_t *cpp_serial;
992 : 0 : struct nfp_cpp *cpp = nfp_nsp_cpp(nsp);
993 : :
994 : 0 : cpp_serial_len = nfp_cpp_serial(cpp, &cpp_serial);
995 [ # # ]: 0 : if (cpp_serial_len != NFP_SERIAL_LEN)
996 : : return -ERANGE;
997 : :
998 : 0 : interface = nfp_cpp_interface(cpp);
999 : :
1000 : : /* Looking for firmware file in order of priority */
1001 : :
1002 : : /* First try to find a firmware image specific for this device */
1003 : 0 : snprintf(serial, sizeof(serial),
1004 : : "serial-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
1005 : 0 : cpp_serial[0], cpp_serial[1], cpp_serial[2], cpp_serial[3],
1006 : 0 : cpp_serial[4], cpp_serial[5], interface >> 8, interface & 0xff);
1007 : : snprintf(fw_name, fw_size, "%s/%s.nffw", DEFAULT_FW_PATH, serial);
1008 : :
1009 : 0 : PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name);
1010 [ # # ]: 0 : if (access(fw_name, F_OK) == 0)
1011 : : return 0;
1012 : :
1013 : : /* Then try the PCI name */
1014 : : snprintf(fw_name, fw_size, "%s/pci-%s.nffw", DEFAULT_FW_PATH,
1015 : 0 : dev->name);
1016 : :
1017 : 0 : PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name);
1018 [ # # ]: 0 : if (access(fw_name, F_OK) == 0)
1019 : : return 0;
1020 : :
1021 : : /* Finally try the card type and media */
1022 : : snprintf(fw_name, fw_size, "%s/%s", DEFAULT_FW_PATH, card);
1023 : 0 : PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name);
1024 [ # # ]: 0 : if (access(fw_name, F_OK) == 0)
1025 : 0 : return 0;
1026 : :
1027 : : return -ENOENT;
1028 : : }
1029 : :
1030 : : static int
1031 : 0 : nfp_fw_upload(struct nfp_nsp *nsp,
1032 : : char *fw_name)
1033 : : {
1034 : : int err;
1035 : : void *fw_buf;
1036 : : size_t fsize;
1037 : :
1038 : 0 : err = rte_firmware_read(fw_name, &fw_buf, &fsize);
1039 [ # # ]: 0 : if (err != 0) {
1040 : 0 : PMD_DRV_LOG(ERR, "firmware %s not found!", fw_name);
1041 : 0 : return -ENOENT;
1042 : : }
1043 : :
1044 : 0 : PMD_DRV_LOG(INFO, "Firmware file found at %s with size: %zu",
1045 : : fw_name, fsize);
1046 : 0 : PMD_DRV_LOG(INFO, "Uploading the firmware ...");
1047 [ # # ]: 0 : if (nfp_nsp_load_fw(nsp, fw_buf, fsize) < 0) {
1048 : 0 : free(fw_buf);
1049 : 0 : PMD_DRV_LOG(ERR, "Firmware load failed.");
1050 : 0 : return -EIO;
1051 : : }
1052 : :
1053 : 0 : PMD_DRV_LOG(INFO, "Done");
1054 : :
1055 : 0 : free(fw_buf);
1056 : :
1057 : 0 : return 0;
1058 : : }
1059 : :
1060 : : static void
1061 : 0 : nfp_fw_unload(struct nfp_cpp *cpp)
1062 : : {
1063 : : struct nfp_nsp *nsp;
1064 : :
1065 : 0 : nsp = nfp_nsp_open(cpp);
1066 [ # # ]: 0 : if (nsp == NULL)
1067 : : return;
1068 : :
1069 : 0 : nfp_nsp_device_soft_reset(nsp);
1070 : 0 : nfp_nsp_close(nsp);
1071 : : }
1072 : :
1073 : : static int
1074 : 0 : nfp_fw_reload(struct nfp_nsp *nsp,
1075 : : char *fw_name)
1076 : : {
1077 : : int err;
1078 : :
1079 : 0 : nfp_nsp_device_soft_reset(nsp);
1080 : 0 : err = nfp_fw_upload(nsp, fw_name);
1081 [ # # ]: 0 : if (err != 0)
1082 : 0 : PMD_DRV_LOG(ERR, "NFP firmware load failed");
1083 : :
1084 : 0 : return err;
1085 : : }
1086 : :
1087 : : static bool
1088 : 0 : nfp_fw_skip_load(const struct nfp_dev_info *dev_info,
1089 : : struct nfp_multi_pf *multi_pf)
1090 : 0 : {
1091 : : uint8_t i;
1092 : : uint64_t tmp_beat;
1093 : : uint32_t port_num;
1094 : : uint8_t in_use = 0;
1095 : 0 : uint64_t beat[dev_info->pf_num_per_unit];
1096 : 0 : uint32_t offset[dev_info->pf_num_per_unit];
1097 : : uint8_t abnormal = dev_info->pf_num_per_unit;
1098 : :
1099 [ # # ]: 0 : for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) {
1100 : 0 : offset[port_num] = NFP_BEAT_OFFSET(port_num);
1101 : 0 : beat[port_num] = nn_readq(multi_pf->beat_addr + offset[port_num]);
1102 [ # # ]: 0 : if (beat[port_num] == 0)
1103 : 0 : abnormal--;
1104 : : }
1105 : :
1106 [ # # ]: 0 : if (abnormal == 0)
1107 : : return true;
1108 : :
1109 [ # # ]: 0 : for (i = 0; i < 3; i++) {
1110 : 0 : sleep(1);
1111 [ # # ]: 0 : for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) {
1112 [ # # ]: 0 : if (port_num == multi_pf->function_id)
1113 : 0 : continue;
1114 : :
1115 [ # # ]: 0 : if (beat[port_num] == 0)
1116 : 0 : continue;
1117 : :
1118 : 0 : tmp_beat = nn_readq(multi_pf->beat_addr + offset[port_num]);
1119 [ # # ]: 0 : if (tmp_beat != beat[port_num]) {
1120 : 0 : in_use++;
1121 : 0 : abnormal--;
1122 : 0 : beat[port_num] = 0;
1123 : : }
1124 : : }
1125 : :
1126 [ # # ]: 0 : if (abnormal == 0)
1127 : : return true;
1128 : : }
1129 : :
1130 [ # # ]: 0 : if (in_use != 0) {
1131 : 0 : PMD_DRV_LOG(WARNING, "Abnormal %u != 0, the nic has port which is exit abnormally.",
1132 : : abnormal);
1133 : 0 : return true;
1134 : : }
1135 : :
1136 : : return false;
1137 : : }
1138 : :
1139 : : static int
1140 : 0 : nfp_fw_reload_for_multipf(struct nfp_nsp *nsp,
1141 : : char *fw_name,
1142 : : struct nfp_cpp *cpp,
1143 : : const struct nfp_dev_info *dev_info,
1144 : : struct nfp_multi_pf *multi_pf)
1145 : : {
1146 : : int err;
1147 : : bool skip_load_fw = false;
1148 : :
1149 : 0 : err = nfp_net_keepalive_init(cpp, multi_pf);
1150 [ # # ]: 0 : if (err != 0) {
1151 : 0 : PMD_DRV_LOG(ERR, "NFP init beat failed");
1152 : 0 : return err;
1153 : : }
1154 : :
1155 : 0 : err = nfp_net_keepalive_start(multi_pf);
1156 [ # # ]: 0 : if (err != 0) {
1157 : : nfp_net_keepalive_uninit(multi_pf);
1158 : 0 : PMD_DRV_LOG(ERR, "NFP write beat failed");
1159 : 0 : return err;
1160 : : }
1161 : :
1162 [ # # ]: 0 : if (nfp_nsp_fw_loaded(nsp))
1163 : 0 : skip_load_fw = nfp_fw_skip_load(dev_info, multi_pf);
1164 : :
1165 [ # # ]: 0 : if (skip_load_fw)
1166 : : return 0;
1167 : :
1168 : 0 : err = nfp_fw_reload(nsp, fw_name);
1169 [ # # ]: 0 : if (err != 0) {
1170 : : nfp_net_keepalive_stop(multi_pf);
1171 : : nfp_net_keepalive_uninit(multi_pf);
1172 : 0 : return err;
1173 : : }
1174 : :
1175 : : nfp_net_keepalive_clear_others(dev_info, multi_pf);
1176 : :
1177 : : return 0;
1178 : : }
1179 : :
1180 : : static int
1181 : 0 : nfp_fw_setup(struct rte_pci_device *dev,
1182 : : struct nfp_cpp *cpp,
1183 : : struct nfp_eth_table *nfp_eth_table,
1184 : : struct nfp_hwinfo *hwinfo,
1185 : : const struct nfp_dev_info *dev_info,
1186 : : struct nfp_multi_pf *multi_pf)
1187 : : {
1188 : : int err;
1189 : : char fw_name[125];
1190 : : char card_desc[100];
1191 : : struct nfp_nsp *nsp;
1192 : : const char *nfp_fw_model;
1193 : :
1194 : 0 : nfp_fw_model = nfp_hwinfo_lookup(hwinfo, "nffw.partno");
1195 [ # # ]: 0 : if (nfp_fw_model == NULL)
1196 : 0 : nfp_fw_model = nfp_hwinfo_lookup(hwinfo, "assembly.partno");
1197 : :
1198 [ # # ]: 0 : if (nfp_fw_model != NULL) {
1199 : 0 : PMD_DRV_LOG(INFO, "firmware model found: %s", nfp_fw_model);
1200 : : } else {
1201 : 0 : PMD_DRV_LOG(ERR, "firmware model NOT found");
1202 : 0 : return -EIO;
1203 : : }
1204 : :
1205 [ # # ]: 0 : if (nfp_eth_table->count == 0 || nfp_eth_table->count > 8) {
1206 : 0 : PMD_DRV_LOG(ERR, "NFP ethernet table reports wrong ports: %u",
1207 : : nfp_eth_table->count);
1208 : 0 : return -EIO;
1209 : : }
1210 : :
1211 : 0 : PMD_DRV_LOG(INFO, "NFP ethernet port table reports %u ports",
1212 : : nfp_eth_table->count);
1213 : :
1214 : 0 : PMD_DRV_LOG(INFO, "Port speed: %u", nfp_eth_table->ports[0].speed);
1215 : :
1216 : 0 : snprintf(card_desc, sizeof(card_desc), "nic_%s_%dx%d.nffw",
1217 : : nfp_fw_model, nfp_eth_table->count,
1218 : 0 : nfp_eth_table->ports[0].speed / 1000);
1219 : :
1220 : 0 : nsp = nfp_nsp_open(cpp);
1221 [ # # ]: 0 : if (nsp == NULL) {
1222 : 0 : PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle");
1223 : 0 : return -EIO;
1224 : : }
1225 : :
1226 : 0 : err = nfp_fw_get_name(dev, nsp, card_desc, fw_name, sizeof(fw_name));
1227 [ # # ]: 0 : if (err != 0) {
1228 : 0 : PMD_DRV_LOG(ERR, "Can't find suitable firmware.");
1229 : 0 : nfp_nsp_close(nsp);
1230 : 0 : return err;
1231 : : }
1232 : :
1233 [ # # ]: 0 : if (multi_pf->enabled)
1234 : 0 : err = nfp_fw_reload_for_multipf(nsp, fw_name, cpp, dev_info, multi_pf);
1235 : : else
1236 : 0 : err = nfp_fw_reload(nsp, fw_name);
1237 : :
1238 : 0 : nfp_nsp_close(nsp);
1239 : 0 : return err;
1240 : : }
1241 : :
1242 : : static inline bool
1243 : : nfp_check_multi_pf_from_fw(uint32_t total_vnics)
1244 : : {
1245 [ # # # # ]: 0 : if (total_vnics == 1)
1246 : : return true;
1247 : :
1248 : : return false;
1249 : : }
1250 : :
1251 : : static inline bool
1252 : 0 : nfp_check_multi_pf_from_nsp(struct rte_pci_device *pci_dev,
1253 : : struct nfp_cpp *cpp)
1254 : : {
1255 : : bool flag;
1256 : : struct nfp_nsp *nsp;
1257 : :
1258 : 0 : nsp = nfp_nsp_open(cpp);
1259 [ # # ]: 0 : if (nsp == NULL) {
1260 : 0 : PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle");
1261 : 0 : return false;
1262 : : }
1263 : :
1264 [ # # ]: 0 : flag = (nfp_nsp_get_abi_ver_major(nsp) > 0) &&
1265 [ # # ]: 0 : (pci_dev->id.device_id == PCI_DEVICE_ID_NFP3800_PF_NIC);
1266 : :
1267 : 0 : nfp_nsp_close(nsp);
1268 : 0 : return flag;
1269 : : }
1270 : :
1271 : : static int
1272 : 0 : nfp_enable_multi_pf(struct nfp_pf_dev *pf_dev)
1273 : : {
1274 : : int err = 0;
1275 : : uint64_t tx_base;
1276 : : uint8_t *ctrl_bar;
1277 : : struct nfp_hw *hw;
1278 : : uint32_t cap_extend;
1279 : : struct nfp_net_hw net_hw;
1280 : : struct nfp_cpp_area *area;
1281 : : char name[RTE_ETH_NAME_MAX_LEN];
1282 : :
1283 : : memset(&net_hw, 0, sizeof(struct nfp_net_hw));
1284 : :
1285 : : /* Map the symbol table */
1286 : 0 : snprintf(name, sizeof(name), "_pf%u_net_bar0",
1287 : 0 : pf_dev->multi_pf.function_id);
1288 : 0 : ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, name, NFP_NET_CFG_BAR_SZ,
1289 : : &area);
1290 [ # # ]: 0 : if (ctrl_bar == NULL) {
1291 : 0 : PMD_INIT_LOG(ERR, "Failed to find data vNIC memory symbol");
1292 : 0 : return -ENODEV;
1293 : : }
1294 : :
1295 : : hw = &net_hw.super;
1296 : 0 : hw->ctrl_bar = ctrl_bar;
1297 : :
1298 : : cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
1299 [ # # ]: 0 : if ((cap_extend & NFP_NET_CFG_CTRL_MULTI_PF) == 0) {
1300 : 0 : PMD_INIT_LOG(ERR, "Loaded firmware doesn't support multiple PF");
1301 : : err = -EINVAL;
1302 : 0 : goto end;
1303 : : }
1304 : :
1305 : 0 : tx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ);
1306 : 0 : net_hw.tx_bar = pf_dev->qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ;
1307 : 0 : nfp_net_cfg_queue_setup(&net_hw);
1308 : : rte_spinlock_init(&hw->reconfig_lock);
1309 : 0 : nfp_ext_reconfig(&net_hw.super, NFP_NET_CFG_CTRL_MULTI_PF, NFP_NET_CFG_UPDATE_GEN);
1310 : 0 : end:
1311 : 0 : nfp_cpp_area_release_free(area);
1312 : 0 : return err;
1313 : : }
1314 : :
1315 : : static int
1316 : 0 : nfp_init_app_fw_nic(struct nfp_pf_dev *pf_dev,
1317 : : const struct nfp_dev_info *dev_info)
1318 : : {
1319 : : uint8_t i;
1320 : : uint8_t id;
1321 : 0 : int ret = 0;
1322 : : uint32_t total_vnics;
1323 : : struct nfp_net_hw *hw;
1324 : : unsigned int numa_node;
1325 : : struct rte_eth_dev *eth_dev;
1326 : : struct nfp_app_fw_nic *app_fw_nic;
1327 : : struct nfp_eth_table *nfp_eth_table;
1328 : : char bar_name[RTE_ETH_NAME_MAX_LEN];
1329 : : char port_name[RTE_ETH_NAME_MAX_LEN];
1330 : : char vnic_name[RTE_ETH_NAME_MAX_LEN];
1331 : :
1332 : 0 : nfp_eth_table = pf_dev->nfp_eth_table;
1333 : 0 : PMD_INIT_LOG(INFO, "Total physical ports: %d", nfp_eth_table->count);
1334 : : id = nfp_function_id_get(pf_dev, 0);
1335 : :
1336 : : /* Allocate memory for the CoreNIC app */
1337 : 0 : app_fw_nic = rte_zmalloc("nfp_app_fw_nic", sizeof(*app_fw_nic), 0);
1338 [ # # ]: 0 : if (app_fw_nic == NULL)
1339 : : return -ENOMEM;
1340 : :
1341 : : /* Point the app_fw_priv pointer in the PF to the coreNIC app */
1342 : 0 : pf_dev->app_fw_priv = app_fw_nic;
1343 : :
1344 : : /* Read the number of vNIC's created for the PF */
1345 : 0 : snprintf(vnic_name, sizeof(vnic_name), "nfd_cfg_pf%u_num_ports", id);
1346 : 0 : total_vnics = nfp_rtsym_read_le(pf_dev->sym_tbl, vnic_name, &ret);
1347 [ # # # # ]: 0 : if (ret != 0 || total_vnics == 0 || total_vnics > 8) {
1348 : 0 : PMD_INIT_LOG(ERR, "%s symbol with wrong value", vnic_name);
1349 : 0 : ret = -ENODEV;
1350 : 0 : goto app_cleanup;
1351 : : }
1352 : :
1353 [ # # ]: 0 : if (pf_dev->multi_pf.enabled) {
1354 : : if (!nfp_check_multi_pf_from_fw(total_vnics)) {
1355 : 0 : PMD_INIT_LOG(ERR, "NSP report multipf, but FW report not multipf");
1356 : 0 : ret = -ENODEV;
1357 : 0 : goto app_cleanup;
1358 : : }
1359 : : } else {
1360 : : /*
1361 : : * For coreNIC the number of vNICs exposed should be the same as the
1362 : : * number of physical ports.
1363 : : */
1364 [ # # ]: 0 : if (total_vnics != nfp_eth_table->count) {
1365 : 0 : PMD_INIT_LOG(ERR, "Total physical ports do not match number of vNICs");
1366 : 0 : ret = -ENODEV;
1367 : 0 : goto app_cleanup;
1368 : : }
1369 : : }
1370 : :
1371 : : /* Populate coreNIC app properties */
1372 : 0 : app_fw_nic->total_phyports = total_vnics;
1373 : 0 : app_fw_nic->pf_dev = pf_dev;
1374 [ # # ]: 0 : if (total_vnics > 1)
1375 : 0 : app_fw_nic->multiport = true;
1376 : :
1377 : : /* Map the symbol table */
1378 : : snprintf(bar_name, sizeof(bar_name), "_pf%u_net_bar0", id);
1379 : 0 : pf_dev->ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, bar_name,
1380 : 0 : app_fw_nic->total_phyports * NFP_NET_CFG_BAR_SZ,
1381 : : &pf_dev->ctrl_area);
1382 [ # # ]: 0 : if (pf_dev->ctrl_bar == NULL) {
1383 : 0 : PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for %s", bar_name);
1384 : 0 : ret = -EIO;
1385 : 0 : goto app_cleanup;
1386 : : }
1387 : :
1388 : 0 : PMD_INIT_LOG(DEBUG, "ctrl bar: %p", pf_dev->ctrl_bar);
1389 : :
1390 : : /* Loop through all physical ports on PF */
1391 : 0 : numa_node = rte_socket_id();
1392 [ # # ]: 0 : for (i = 0; i < app_fw_nic->total_phyports; i++) {
1393 [ # # ]: 0 : if (pf_dev->multi_pf.enabled)
1394 : 0 : snprintf(port_name, sizeof(port_name), "%s",
1395 : 0 : pf_dev->pci_dev->device.name);
1396 : : else
1397 : 0 : snprintf(port_name, sizeof(port_name), "%s_port%u",
1398 : 0 : pf_dev->pci_dev->device.name, i);
1399 : :
1400 : : /* Allocate a eth_dev for this phyport */
1401 : 0 : eth_dev = rte_eth_dev_allocate(port_name);
1402 [ # # ]: 0 : if (eth_dev == NULL) {
1403 : 0 : ret = -ENODEV;
1404 : 0 : goto port_cleanup;
1405 : : }
1406 : :
1407 : : /* Allocate memory for this phyport */
1408 : 0 : eth_dev->data->dev_private = rte_zmalloc_socket(port_name,
1409 : : sizeof(struct nfp_net_hw),
1410 : : RTE_CACHE_LINE_SIZE, numa_node);
1411 [ # # ]: 0 : if (eth_dev->data->dev_private == NULL) {
1412 : 0 : ret = -ENOMEM;
1413 : 0 : rte_eth_dev_release_port(eth_dev);
1414 : 0 : goto port_cleanup;
1415 : : }
1416 : :
1417 : : hw = eth_dev->data->dev_private;
1418 : : id = nfp_function_id_get(pf_dev, i);
1419 : :
1420 : : /* Add this device to the PF's array of physical ports */
1421 : 0 : app_fw_nic->ports[id] = hw;
1422 : :
1423 : 0 : hw->dev_info = dev_info;
1424 : 0 : hw->pf_dev = pf_dev;
1425 : 0 : hw->cpp = pf_dev->cpp;
1426 : 0 : hw->eth_dev = eth_dev;
1427 : 0 : hw->idx = id;
1428 : 0 : hw->nfp_idx = nfp_eth_table->ports[id].index;
1429 : :
1430 : 0 : eth_dev->device = &pf_dev->pci_dev->device;
1431 : :
1432 : : /*
1433 : : * Ctrl/tx/rx BAR mappings and remaining init happens in
1434 : : * @nfp_net_init()
1435 : : */
1436 : 0 : ret = nfp_net_init(eth_dev);
1437 [ # # ]: 0 : if (ret != 0) {
1438 : 0 : ret = -ENODEV;
1439 : 0 : goto port_cleanup;
1440 : : }
1441 : :
1442 : 0 : rte_eth_dev_probing_finish(eth_dev);
1443 : :
1444 : : } /* End loop, all ports on this PF */
1445 : :
1446 : : return 0;
1447 : :
1448 : : port_cleanup:
1449 [ # # ]: 0 : for (i = 0; i < app_fw_nic->total_phyports; i++) {
1450 : : id = nfp_function_id_get(pf_dev, i);
1451 : 0 : hw = app_fw_nic->ports[id];
1452 : :
1453 [ # # # # ]: 0 : if (hw != NULL && hw->eth_dev != NULL) {
1454 : 0 : nfp_net_uninit(hw->eth_dev);
1455 : 0 : rte_eth_dev_release_port(hw->eth_dev);
1456 : : }
1457 : : }
1458 : 0 : nfp_cpp_area_release_free(pf_dev->ctrl_area);
1459 : 0 : app_cleanup:
1460 : 0 : rte_free(app_fw_nic);
1461 : :
1462 : 0 : return ret;
1463 : : }
1464 : :
1465 : : static int
1466 : 0 : nfp_net_hwinfo_set(uint8_t function_id,
1467 : : struct nfp_rtsym_table *sym_tbl,
1468 : : struct nfp_cpp *cpp)
1469 : : {
1470 : 0 : int ret = 0;
1471 : : uint64_t app_cap;
1472 : : uint8_t sp_indiff;
1473 : : struct nfp_nsp *nsp;
1474 : : char hw_info[RTE_ETH_NAME_MAX_LEN];
1475 : : char app_cap_name[RTE_ETH_NAME_MAX_LEN];
1476 : :
1477 : : /* Read the app capabilities of the firmware loaded */
1478 : 0 : snprintf(app_cap_name, sizeof(app_cap_name), "_pf%u_net_app_cap", function_id);
1479 : 0 : app_cap = nfp_rtsym_read_le(sym_tbl, app_cap_name, &ret);
1480 [ # # ]: 0 : if (ret != 0) {
1481 : 0 : PMD_INIT_LOG(ERR, "Couldn't read app_fw_cap from firmware.");
1482 : 0 : return ret;
1483 : : }
1484 : :
1485 : : /* Calculate the value of sp_indiff and write to hw_info */
1486 : 0 : sp_indiff = app_cap & NFP_NET_APP_CAP_SP_INDIFF;
1487 : 0 : snprintf(hw_info, sizeof(hw_info), "sp_indiff=%u", sp_indiff);
1488 : :
1489 : 0 : nsp = nfp_nsp_open(cpp);
1490 [ # # ]: 0 : if (nsp == NULL) {
1491 : 0 : PMD_INIT_LOG(ERR, "Couldn't get NSP.");
1492 : 0 : return -EIO;
1493 : : }
1494 : :
1495 : 0 : ret = nfp_nsp_hwinfo_set(nsp, hw_info, sizeof(hw_info));
1496 : 0 : nfp_nsp_close(nsp);
1497 [ # # ]: 0 : if (ret != 0) {
1498 : 0 : PMD_INIT_LOG(ERR, "Failed to set parameter to hwinfo.");
1499 : 0 : return ret;
1500 : : }
1501 : :
1502 : : return 0;
1503 : : }
1504 : :
1505 : : const uint32_t nfp_eth_media_table[NFP_MEDIA_LINK_MODES_NUMBER] = {
1506 : : [NFP_MEDIA_W0_RJ45_10M] = RTE_ETH_LINK_SPEED_10M,
1507 : : [NFP_MEDIA_W0_RJ45_10M_HD] = RTE_ETH_LINK_SPEED_10M_HD,
1508 : : [NFP_MEDIA_W0_RJ45_100M] = RTE_ETH_LINK_SPEED_100M,
1509 : : [NFP_MEDIA_W0_RJ45_100M_HD] = RTE_ETH_LINK_SPEED_100M_HD,
1510 : : [NFP_MEDIA_W0_RJ45_1G] = RTE_ETH_LINK_SPEED_1G,
1511 : : [NFP_MEDIA_W0_RJ45_2P5G] = RTE_ETH_LINK_SPEED_2_5G,
1512 : : [NFP_MEDIA_W0_RJ45_5G] = RTE_ETH_LINK_SPEED_5G,
1513 : : [NFP_MEDIA_W0_RJ45_10G] = RTE_ETH_LINK_SPEED_10G,
1514 : : [NFP_MEDIA_1000BASE_CX] = RTE_ETH_LINK_SPEED_1G,
1515 : : [NFP_MEDIA_1000BASE_KX] = RTE_ETH_LINK_SPEED_1G,
1516 : : [NFP_MEDIA_10GBASE_KX4] = RTE_ETH_LINK_SPEED_10G,
1517 : : [NFP_MEDIA_10GBASE_KR] = RTE_ETH_LINK_SPEED_10G,
1518 : : [NFP_MEDIA_10GBASE_CX4] = RTE_ETH_LINK_SPEED_10G,
1519 : : [NFP_MEDIA_10GBASE_CR] = RTE_ETH_LINK_SPEED_10G,
1520 : : [NFP_MEDIA_10GBASE_SR] = RTE_ETH_LINK_SPEED_10G,
1521 : : [NFP_MEDIA_10GBASE_ER] = RTE_ETH_LINK_SPEED_10G,
1522 : : [NFP_MEDIA_25GBASE_KR] = RTE_ETH_LINK_SPEED_25G,
1523 : : [NFP_MEDIA_25GBASE_KR_S] = RTE_ETH_LINK_SPEED_25G,
1524 : : [NFP_MEDIA_25GBASE_CR] = RTE_ETH_LINK_SPEED_25G,
1525 : : [NFP_MEDIA_25GBASE_CR_S] = RTE_ETH_LINK_SPEED_25G,
1526 : : [NFP_MEDIA_25GBASE_SR] = RTE_ETH_LINK_SPEED_25G,
1527 : : [NFP_MEDIA_40GBASE_CR4] = RTE_ETH_LINK_SPEED_40G,
1528 : : [NFP_MEDIA_40GBASE_KR4] = RTE_ETH_LINK_SPEED_40G,
1529 : : [NFP_MEDIA_40GBASE_SR4] = RTE_ETH_LINK_SPEED_40G,
1530 : : [NFP_MEDIA_40GBASE_LR4] = RTE_ETH_LINK_SPEED_40G,
1531 : : [NFP_MEDIA_50GBASE_KR] = RTE_ETH_LINK_SPEED_50G,
1532 : : [NFP_MEDIA_50GBASE_SR] = RTE_ETH_LINK_SPEED_50G,
1533 : : [NFP_MEDIA_50GBASE_CR] = RTE_ETH_LINK_SPEED_50G,
1534 : : [NFP_MEDIA_50GBASE_LR] = RTE_ETH_LINK_SPEED_50G,
1535 : : [NFP_MEDIA_50GBASE_ER] = RTE_ETH_LINK_SPEED_50G,
1536 : : [NFP_MEDIA_50GBASE_FR] = RTE_ETH_LINK_SPEED_50G,
1537 : : [NFP_MEDIA_100GBASE_KR4] = RTE_ETH_LINK_SPEED_100G,
1538 : : [NFP_MEDIA_100GBASE_SR4] = RTE_ETH_LINK_SPEED_100G,
1539 : : [NFP_MEDIA_100GBASE_CR4] = RTE_ETH_LINK_SPEED_100G,
1540 : : [NFP_MEDIA_100GBASE_KP4] = RTE_ETH_LINK_SPEED_100G,
1541 : : [NFP_MEDIA_100GBASE_CR10] = RTE_ETH_LINK_SPEED_100G,
1542 : : [NFP_MEDIA_10GBASE_LR] = RTE_ETH_LINK_SPEED_10G,
1543 : : [NFP_MEDIA_25GBASE_LR] = RTE_ETH_LINK_SPEED_25G,
1544 : : [NFP_MEDIA_25GBASE_ER] = RTE_ETH_LINK_SPEED_25G
1545 : : };
1546 : :
1547 : : static int
1548 : 0 : nfp_net_speed_capa_get_real(struct nfp_eth_media_buf *media_buf,
1549 : : struct nfp_pf_dev *pf_dev)
1550 : : {
1551 : : uint32_t i;
1552 : : uint32_t j;
1553 : : uint32_t offset;
1554 : : uint32_t speed_capa = 0;
1555 : : uint64_t supported_modes;
1556 : :
1557 [ # # ]: 0 : for (i = 0; i < RTE_DIM(media_buf->supported_modes); i++) {
1558 : 0 : supported_modes = media_buf->supported_modes[i];
1559 : 0 : offset = i * UINT64_BIT;
1560 [ # # ]: 0 : for (j = 0; j < UINT64_BIT; j++) {
1561 [ # # ]: 0 : if (supported_modes == 0)
1562 : : break;
1563 : :
1564 [ # # ]: 0 : if ((supported_modes & 1) != 0) {
1565 [ # # ]: 0 : if ((j + offset) >= NFP_MEDIA_LINK_MODES_NUMBER) {
1566 : 0 : PMD_DRV_LOG(ERR, "Invalid offset of media table.");
1567 : 0 : return -EINVAL;
1568 : : }
1569 : :
1570 : 0 : speed_capa |= nfp_eth_media_table[j + offset];
1571 : : }
1572 : :
1573 : 0 : supported_modes = supported_modes >> 1;
1574 : : }
1575 : : }
1576 : :
1577 : 0 : pf_dev->speed_capa = speed_capa;
1578 : :
1579 [ # # ]: 0 : return pf_dev->speed_capa == 0 ? -EINVAL : 0;
1580 : : }
1581 : :
1582 : : static int
1583 : 0 : nfp_net_speed_capa_get(struct nfp_pf_dev *pf_dev,
1584 : : uint32_t port_id)
1585 : : {
1586 : : int ret;
1587 : : struct nfp_nsp *nsp;
1588 : : struct nfp_eth_media_buf media_buf;
1589 : :
1590 : 0 : media_buf.eth_index = pf_dev->nfp_eth_table->ports[port_id].eth_index;
1591 : 0 : pf_dev->speed_capa = 0;
1592 : :
1593 : 0 : nsp = nfp_nsp_open(pf_dev->cpp);
1594 [ # # ]: 0 : if (nsp == NULL) {
1595 : 0 : PMD_DRV_LOG(ERR, "Couldn't get NSP.");
1596 : 0 : return -EIO;
1597 : : }
1598 : :
1599 : 0 : ret = nfp_nsp_read_media(nsp, &media_buf, sizeof(media_buf));
1600 : 0 : nfp_nsp_close(nsp);
1601 [ # # ]: 0 : if (ret != 0) {
1602 : 0 : PMD_DRV_LOG(ERR, "Failed to read media.");
1603 : 0 : return ret;
1604 : : }
1605 : :
1606 : 0 : ret = nfp_net_speed_capa_get_real(&media_buf, pf_dev);
1607 [ # # ]: 0 : if (ret < 0) {
1608 : 0 : PMD_DRV_LOG(ERR, "Speed capability is invalid.");
1609 : 0 : return ret;
1610 : : }
1611 : :
1612 : : return 0;
1613 : : }
1614 : :
1615 : : static int
1616 : 0 : nfp_pf_init(struct rte_pci_device *pci_dev)
1617 : : {
1618 : : void *sync;
1619 : : uint32_t i;
1620 : : uint32_t id;
1621 : 0 : int ret = 0;
1622 : : uint64_t addr;
1623 : : uint32_t index;
1624 : : uint32_t cpp_id;
1625 : : uint8_t function_id;
1626 : : struct nfp_cpp *cpp;
1627 : : struct nfp_pf_dev *pf_dev;
1628 : : struct nfp_hwinfo *hwinfo;
1629 : : enum nfp_app_fw_id app_fw_id;
1630 : : char name[RTE_ETH_NAME_MAX_LEN];
1631 : : struct nfp_rtsym_table *sym_tbl;
1632 : : char app_name[RTE_ETH_NAME_MAX_LEN];
1633 : : struct nfp_eth_table *nfp_eth_table;
1634 : : const struct nfp_dev_info *dev_info;
1635 : :
1636 [ # # ]: 0 : if (pci_dev == NULL)
1637 : : return -ENODEV;
1638 : :
1639 [ # # ]: 0 : if (pci_dev->mem_resource[0].addr == NULL) {
1640 : 0 : PMD_INIT_LOG(ERR, "The address of BAR0 is NULL.");
1641 : 0 : return -ENODEV;
1642 : : }
1643 : :
1644 : 0 : dev_info = nfp_dev_info_get(pci_dev->id.device_id);
1645 [ # # ]: 0 : if (dev_info == NULL) {
1646 : 0 : PMD_INIT_LOG(ERR, "Not supported device ID");
1647 : 0 : return -ENODEV;
1648 : : }
1649 : :
1650 : : /* Allocate memory for the PF "device" */
1651 : 0 : function_id = (pci_dev->addr.function) & 0x07;
1652 : 0 : snprintf(name, sizeof(name), "nfp_pf%u", function_id);
1653 : 0 : pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0);
1654 [ # # ]: 0 : if (pf_dev == NULL) {
1655 : 0 : PMD_INIT_LOG(ERR, "Can't allocate memory for the PF device");
1656 : 0 : return -ENOMEM;
1657 : : }
1658 : :
1659 : 0 : sync = nfp_sync_alloc();
1660 [ # # ]: 0 : if (sync == NULL) {
1661 : 0 : PMD_INIT_LOG(ERR, "Failed to alloc sync zone.");
1662 : 0 : ret = -ENOMEM;
1663 : 0 : goto pf_cleanup;
1664 : : }
1665 : :
1666 : : /*
1667 : : * When device bound to UIO, the device could be used, by mistake,
1668 : : * by two DPDK apps, and the UIO driver does not avoid it. This
1669 : : * could lead to a serious problem when configuring the NFP CPP
1670 : : * interface. Here we avoid this telling to the CPP init code to
1671 : : * use a lock file if UIO is being used.
1672 : : */
1673 [ # # ]: 0 : if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO)
1674 : 0 : cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, false);
1675 : : else
1676 : 0 : cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, true);
1677 : :
1678 [ # # ]: 0 : if (cpp == NULL) {
1679 : 0 : PMD_INIT_LOG(ERR, "A CPP handle can not be obtained");
1680 : 0 : ret = -EIO;
1681 : 0 : goto sync_free;
1682 : : }
1683 : :
1684 : 0 : hwinfo = nfp_hwinfo_read(cpp);
1685 [ # # ]: 0 : if (hwinfo == NULL) {
1686 : 0 : PMD_INIT_LOG(ERR, "Error reading hwinfo table");
1687 : 0 : ret = -EIO;
1688 : 0 : goto cpp_cleanup;
1689 : : }
1690 : :
1691 : : /* Read the number of physical ports from hardware */
1692 : 0 : nfp_eth_table = nfp_eth_read_ports(cpp);
1693 [ # # ]: 0 : if (nfp_eth_table == NULL) {
1694 : 0 : PMD_INIT_LOG(ERR, "Error reading NFP ethernet table");
1695 : 0 : ret = -EIO;
1696 : 0 : goto hwinfo_cleanup;
1697 : : }
1698 : :
1699 : 0 : pf_dev->multi_pf.enabled = nfp_check_multi_pf_from_nsp(pci_dev, cpp);
1700 : 0 : pf_dev->multi_pf.function_id = function_id;
1701 : :
1702 : : /* Force the physical port down to clear the possible DMA error */
1703 [ # # ]: 0 : for (i = 0; i < nfp_eth_table->count; i++) {
1704 [ # # ]: 0 : id = nfp_function_id_get(pf_dev, i);
1705 : 0 : index = nfp_eth_table->ports[id].index;
1706 : 0 : nfp_eth_set_configured(cpp, index, 0);
1707 : : }
1708 : :
1709 [ # # ]: 0 : if (nfp_fw_setup(pci_dev, cpp, nfp_eth_table, hwinfo,
1710 : : dev_info, &pf_dev->multi_pf) != 0) {
1711 : 0 : PMD_INIT_LOG(ERR, "Error when uploading firmware");
1712 : 0 : ret = -EIO;
1713 : 0 : goto eth_table_cleanup;
1714 : : }
1715 : :
1716 : : /* Now the symbol table should be there */
1717 : 0 : sym_tbl = nfp_rtsym_table_read(cpp);
1718 [ # # ]: 0 : if (sym_tbl == NULL) {
1719 : 0 : PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table");
1720 : 0 : ret = -EIO;
1721 : 0 : goto fw_cleanup;
1722 : : }
1723 : :
1724 : : /* Read the app ID of the firmware loaded */
1725 : : snprintf(app_name, sizeof(app_name), "_pf%u_net_app_id", function_id);
1726 : 0 : app_fw_id = nfp_rtsym_read_le(sym_tbl, app_name, &ret);
1727 [ # # ]: 0 : if (ret != 0) {
1728 : 0 : PMD_INIT_LOG(ERR, "Couldn't read %s from firmware", app_name);
1729 : 0 : ret = -EIO;
1730 : 0 : goto sym_tbl_cleanup;
1731 : : }
1732 : :
1733 : : /* Write sp_indiff to hw_info */
1734 : 0 : ret = nfp_net_hwinfo_set(function_id, sym_tbl, cpp);
1735 [ # # ]: 0 : if (ret != 0) {
1736 : 0 : PMD_INIT_LOG(ERR, "Failed to set hwinfo.");
1737 : 0 : ret = -EIO;
1738 : 0 : goto sym_tbl_cleanup;
1739 : : }
1740 : :
1741 : : /* Populate the newly created PF device */
1742 : 0 : pf_dev->app_fw_id = app_fw_id;
1743 : 0 : pf_dev->cpp = cpp;
1744 : 0 : pf_dev->hwinfo = hwinfo;
1745 : 0 : pf_dev->sym_tbl = sym_tbl;
1746 : 0 : pf_dev->pci_dev = pci_dev;
1747 : 0 : pf_dev->nfp_eth_table = nfp_eth_table;
1748 : 0 : pf_dev->sync = sync;
1749 : :
1750 : : /* Get the speed capability */
1751 [ # # ]: 0 : for (i = 0; i < nfp_eth_table->count; i++) {
1752 [ # # ]: 0 : id = nfp_function_id_get(pf_dev, i);
1753 : 0 : ret = nfp_net_speed_capa_get(pf_dev, id);
1754 [ # # ]: 0 : if (ret != 0) {
1755 : 0 : PMD_INIT_LOG(ERR, "Failed to get speed capability.");
1756 : 0 : ret = -EIO;
1757 : 0 : goto sym_tbl_cleanup;
1758 : : }
1759 : : }
1760 : :
1761 : : /* Configure access to tx/rx vNIC BARs */
1762 : 0 : addr = nfp_qcp_queue_offset(dev_info, 0);
1763 : : cpp_id = NFP_CPP_ISLAND_ID(0, NFP_CPP_ACTION_RW, 0, 0);
1764 : :
1765 : 0 : pf_dev->qc_bar = nfp_cpp_map_area(pf_dev->cpp, cpp_id,
1766 : 0 : addr, dev_info->qc_area_sz, &pf_dev->qc_area);
1767 [ # # ]: 0 : if (pf_dev->qc_bar == NULL) {
1768 : 0 : PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for net.qc");
1769 : 0 : ret = -EIO;
1770 : 0 : goto sym_tbl_cleanup;
1771 : : }
1772 : :
1773 : 0 : PMD_INIT_LOG(DEBUG, "qc_bar address: %p", pf_dev->qc_bar);
1774 : :
1775 : : /*
1776 : : * PF initialization has been done at this point. Call app specific
1777 : : * init code now.
1778 : : */
1779 [ # # # ]: 0 : switch (pf_dev->app_fw_id) {
1780 : 0 : case NFP_APP_FW_CORE_NIC:
1781 [ # # ]: 0 : if (pf_dev->multi_pf.enabled) {
1782 : 0 : ret = nfp_enable_multi_pf(pf_dev);
1783 [ # # ]: 0 : if (ret != 0)
1784 : 0 : goto hwqueues_cleanup;
1785 : : }
1786 : :
1787 : 0 : PMD_INIT_LOG(INFO, "Initializing coreNIC");
1788 : 0 : ret = nfp_init_app_fw_nic(pf_dev, dev_info);
1789 [ # # ]: 0 : if (ret != 0) {
1790 : 0 : PMD_INIT_LOG(ERR, "Could not initialize coreNIC!");
1791 : 0 : goto hwqueues_cleanup;
1792 : : }
1793 : : break;
1794 : 0 : case NFP_APP_FW_FLOWER_NIC:
1795 : 0 : PMD_INIT_LOG(INFO, "Initializing Flower");
1796 : 0 : ret = nfp_init_app_fw_flower(pf_dev, dev_info);
1797 [ # # ]: 0 : if (ret != 0) {
1798 : 0 : PMD_INIT_LOG(ERR, "Could not initialize Flower!");
1799 : 0 : goto hwqueues_cleanup;
1800 : : }
1801 : : break;
1802 : 0 : default:
1803 : 0 : PMD_INIT_LOG(ERR, "Unsupported Firmware loaded");
1804 : 0 : ret = -EINVAL;
1805 : 0 : goto hwqueues_cleanup;
1806 : : }
1807 : :
1808 : : /* Register the CPP bridge service here for primary use */
1809 : 0 : ret = nfp_enable_cpp_service(pf_dev);
1810 [ # # ]: 0 : if (ret != 0)
1811 : 0 : PMD_INIT_LOG(INFO, "Enable cpp service failed.");
1812 : :
1813 : : return 0;
1814 : :
1815 : 0 : hwqueues_cleanup:
1816 : 0 : nfp_cpp_area_release_free(pf_dev->qc_area);
1817 : 0 : sym_tbl_cleanup:
1818 : 0 : free(sym_tbl);
1819 : 0 : fw_cleanup:
1820 : 0 : nfp_fw_unload(cpp);
1821 : : nfp_net_keepalive_stop(&pf_dev->multi_pf);
1822 : 0 : nfp_net_keepalive_clear(pf_dev->multi_pf.beat_addr, pf_dev->multi_pf.function_id);
1823 : : nfp_net_keepalive_uninit(&pf_dev->multi_pf);
1824 : 0 : eth_table_cleanup:
1825 : 0 : free(nfp_eth_table);
1826 : 0 : hwinfo_cleanup:
1827 : 0 : free(hwinfo);
1828 : 0 : cpp_cleanup:
1829 : 0 : nfp_cpp_free(cpp);
1830 : 0 : sync_free:
1831 : 0 : nfp_sync_free(sync);
1832 : 0 : pf_cleanup:
1833 : 0 : rte_free(pf_dev);
1834 : :
1835 : 0 : return ret;
1836 : : }
1837 : :
1838 : : static int
1839 : 0 : nfp_secondary_init_app_fw_nic(struct nfp_pf_dev *pf_dev)
1840 : : {
1841 : : uint32_t i;
1842 : 0 : int err = 0;
1843 : : int ret = 0;
1844 : : uint8_t function_id;
1845 : : uint32_t total_vnics;
1846 : : struct nfp_net_hw *hw;
1847 : : char pf_name[RTE_ETH_NAME_MAX_LEN];
1848 : :
1849 : : /* Read the number of vNIC's created for the PF */
1850 : 0 : function_id = (pf_dev->pci_dev->addr.function) & 0x07;
1851 : 0 : snprintf(pf_name, sizeof(pf_name), "nfd_cfg_pf%u_num_ports", function_id);
1852 : 0 : total_vnics = nfp_rtsym_read_le(pf_dev->sym_tbl, pf_name, &err);
1853 [ # # # # ]: 0 : if (err != 0 || total_vnics == 0 || total_vnics > 8) {
1854 : 0 : PMD_INIT_LOG(ERR, "%s symbol with wrong value", pf_name);
1855 : 0 : return -ENODEV;
1856 : : }
1857 : :
1858 [ # # ]: 0 : for (i = 0; i < total_vnics; i++) {
1859 : : struct rte_eth_dev *eth_dev;
1860 : : char port_name[RTE_ETH_NAME_MAX_LEN];
1861 : :
1862 : : if (nfp_check_multi_pf_from_fw(total_vnics))
1863 : 0 : snprintf(port_name, sizeof(port_name), "%s",
1864 : 0 : pf_dev->pci_dev->device.name);
1865 : : else
1866 : 0 : snprintf(port_name, sizeof(port_name), "%s_port%u",
1867 : 0 : pf_dev->pci_dev->device.name, i);
1868 : :
1869 : 0 : PMD_INIT_LOG(DEBUG, "Secondary attaching to port %s", port_name);
1870 : 0 : eth_dev = rte_eth_dev_attach_secondary(port_name);
1871 [ # # ]: 0 : if (eth_dev == NULL) {
1872 : 0 : PMD_INIT_LOG(ERR, "Secondary process attach to port %s failed", port_name);
1873 : : ret = -ENODEV;
1874 : 0 : break;
1875 : : }
1876 : :
1877 : 0 : eth_dev->process_private = pf_dev;
1878 [ # # ]: 0 : hw = eth_dev->data->dev_private;
1879 : : nfp_net_ethdev_ops_mount(hw, eth_dev);
1880 : :
1881 : 0 : rte_eth_dev_probing_finish(eth_dev);
1882 : : }
1883 : :
1884 : : return ret;
1885 : : }
1886 : :
1887 : : /*
1888 : : * When attaching to the NFP4000/6000 PF on a secondary process there
1889 : : * is no need to initialise the PF again. Only minimal work is required
1890 : : * here.
1891 : : */
1892 : : static int
1893 : 0 : nfp_pf_secondary_init(struct rte_pci_device *pci_dev)
1894 : : {
1895 : : void *sync;
1896 : 0 : int ret = 0;
1897 : : struct nfp_cpp *cpp;
1898 : : uint8_t function_id;
1899 : : struct nfp_pf_dev *pf_dev;
1900 : : enum nfp_app_fw_id app_fw_id;
1901 : : char name[RTE_ETH_NAME_MAX_LEN];
1902 : : struct nfp_rtsym_table *sym_tbl;
1903 : : const struct nfp_dev_info *dev_info;
1904 : : char app_name[RTE_ETH_NAME_MAX_LEN];
1905 : :
1906 [ # # ]: 0 : if (pci_dev == NULL)
1907 : : return -ENODEV;
1908 : :
1909 [ # # ]: 0 : if (pci_dev->mem_resource[0].addr == NULL) {
1910 : 0 : PMD_INIT_LOG(ERR, "The address of BAR0 is NULL.");
1911 : 0 : return -ENODEV;
1912 : : }
1913 : :
1914 : 0 : dev_info = nfp_dev_info_get(pci_dev->id.device_id);
1915 [ # # ]: 0 : if (dev_info == NULL) {
1916 : 0 : PMD_INIT_LOG(ERR, "Not supported device ID");
1917 : 0 : return -ENODEV;
1918 : : }
1919 : :
1920 : : /* Allocate memory for the PF "device" */
1921 : : snprintf(name, sizeof(name), "nfp_pf%d", 0);
1922 : 0 : pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0);
1923 [ # # ]: 0 : if (pf_dev == NULL) {
1924 : 0 : PMD_INIT_LOG(ERR, "Can't allocate memory for the PF device");
1925 : 0 : return -ENOMEM;
1926 : : }
1927 : :
1928 : 0 : sync = nfp_sync_alloc();
1929 [ # # ]: 0 : if (sync == NULL) {
1930 : 0 : PMD_INIT_LOG(ERR, "Failed to alloc sync zone.");
1931 : 0 : ret = -ENOMEM;
1932 : 0 : goto pf_cleanup;
1933 : : }
1934 : :
1935 : : /*
1936 : : * When device bound to UIO, the device could be used, by mistake,
1937 : : * by two DPDK apps, and the UIO driver does not avoid it. This
1938 : : * could lead to a serious problem when configuring the NFP CPP
1939 : : * interface. Here we avoid this telling to the CPP init code to
1940 : : * use a lock file if UIO is being used.
1941 : : */
1942 [ # # ]: 0 : if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO)
1943 : 0 : cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, false);
1944 : : else
1945 : 0 : cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, true);
1946 : :
1947 [ # # ]: 0 : if (cpp == NULL) {
1948 : 0 : PMD_INIT_LOG(ERR, "A CPP handle can not be obtained");
1949 : 0 : ret = -EIO;
1950 : 0 : goto sync_free;
1951 : : }
1952 : :
1953 : : /*
1954 : : * We don't have access to the PF created in the primary process
1955 : : * here so we have to read the number of ports from firmware.
1956 : : */
1957 : 0 : sym_tbl = nfp_rtsym_table_read(cpp);
1958 [ # # ]: 0 : if (sym_tbl == NULL) {
1959 : 0 : PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table");
1960 : 0 : ret = -EIO;
1961 : 0 : goto sync_free;
1962 : : }
1963 : :
1964 : : /* Read the app ID of the firmware loaded */
1965 : 0 : function_id = pci_dev->addr.function & 0x7;
1966 : 0 : snprintf(app_name, sizeof(app_name), "_pf%u_net_app_id", function_id);
1967 : 0 : app_fw_id = nfp_rtsym_read_le(sym_tbl, app_name, &ret);
1968 [ # # ]: 0 : if (ret != 0) {
1969 : 0 : PMD_INIT_LOG(ERR, "Couldn't read %s from fw", app_name);
1970 : 0 : ret = -EIO;
1971 : 0 : goto sym_tbl_cleanup;
1972 : : }
1973 : :
1974 : : /* Populate the newly created PF device */
1975 : 0 : pf_dev->app_fw_id = app_fw_id;
1976 : 0 : pf_dev->cpp = cpp;
1977 : 0 : pf_dev->sym_tbl = sym_tbl;
1978 : 0 : pf_dev->pci_dev = pci_dev;
1979 : 0 : pf_dev->sync = sync;
1980 : :
1981 : : /* Call app specific init code now */
1982 [ # # # ]: 0 : switch (app_fw_id) {
1983 : 0 : case NFP_APP_FW_CORE_NIC:
1984 : 0 : PMD_INIT_LOG(INFO, "Initializing coreNIC");
1985 : 0 : ret = nfp_secondary_init_app_fw_nic(pf_dev);
1986 [ # # ]: 0 : if (ret != 0) {
1987 : 0 : PMD_INIT_LOG(ERR, "Could not initialize coreNIC!");
1988 : 0 : goto sym_tbl_cleanup;
1989 : : }
1990 : : break;
1991 : 0 : case NFP_APP_FW_FLOWER_NIC:
1992 : 0 : PMD_INIT_LOG(INFO, "Initializing Flower");
1993 : 0 : ret = nfp_secondary_init_app_fw_flower(pf_dev);
1994 [ # # ]: 0 : if (ret != 0) {
1995 : 0 : PMD_INIT_LOG(ERR, "Could not initialize Flower!");
1996 : 0 : goto sym_tbl_cleanup;
1997 : : }
1998 : : break;
1999 : 0 : default:
2000 : 0 : PMD_INIT_LOG(ERR, "Unsupported Firmware loaded");
2001 : 0 : ret = -EINVAL;
2002 : 0 : goto sym_tbl_cleanup;
2003 : : }
2004 : :
2005 : : return 0;
2006 : :
2007 : 0 : sym_tbl_cleanup:
2008 : 0 : free(sym_tbl);
2009 : 0 : sync_free:
2010 : 0 : nfp_sync_free(sync);
2011 : 0 : pf_cleanup:
2012 : 0 : rte_free(pf_dev);
2013 : :
2014 : 0 : return ret;
2015 : : }
2016 : :
2017 : : static int
2018 : 0 : nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
2019 : : struct rte_pci_device *dev)
2020 : : {
2021 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY)
2022 : 0 : return nfp_pf_init(dev);
2023 : : else
2024 : 0 : return nfp_pf_secondary_init(dev);
2025 : : }
2026 : :
2027 : : static const struct rte_pci_id pci_id_nfp_pf_net_map[] = {
2028 : : {
2029 : : RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
2030 : : PCI_DEVICE_ID_NFP3800_PF_NIC)
2031 : : },
2032 : : {
2033 : : RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
2034 : : PCI_DEVICE_ID_NFP4000_PF_NIC)
2035 : : },
2036 : : {
2037 : : RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
2038 : : PCI_DEVICE_ID_NFP6000_PF_NIC)
2039 : : },
2040 : : {
2041 : : RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE,
2042 : : PCI_DEVICE_ID_NFP3800_PF_NIC)
2043 : : },
2044 : : {
2045 : : RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE,
2046 : : PCI_DEVICE_ID_NFP4000_PF_NIC)
2047 : : },
2048 : : {
2049 : : RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE,
2050 : : PCI_DEVICE_ID_NFP6000_PF_NIC)
2051 : : },
2052 : : {
2053 : : .vendor_id = 0,
2054 : : },
2055 : : };
2056 : :
2057 : : static int
2058 : 0 : nfp_pci_uninit(struct rte_eth_dev *eth_dev)
2059 : : {
2060 : : uint16_t port_id;
2061 : : struct rte_pci_device *pci_dev;
2062 : :
2063 : 0 : pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
2064 : :
2065 : : /* Free up all physical ports under PF */
2066 [ # # ]: 0 : RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device)
2067 : 0 : rte_eth_dev_close(port_id);
2068 : : /*
2069 : : * Ports can be closed and freed but hotplugging is not
2070 : : * currently supported.
2071 : : */
2072 : 0 : return -ENOTSUP;
2073 : : }
2074 : :
2075 : : static int
2076 : 0 : eth_nfp_pci_remove(struct rte_pci_device *pci_dev)
2077 : : {
2078 : 0 : return rte_eth_dev_pci_generic_remove(pci_dev, nfp_pci_uninit);
2079 : : }
2080 : :
2081 : : static struct rte_pci_driver rte_nfp_net_pf_pmd = {
2082 : : .id_table = pci_id_nfp_pf_net_map,
2083 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
2084 : : .probe = nfp_pf_pci_probe,
2085 : : .remove = eth_nfp_pci_remove,
2086 : : };
2087 : :
2088 : 238 : RTE_PMD_REGISTER_PCI(NFP_PF_DRIVER_NAME, rte_nfp_net_pf_pmd);
2089 : : RTE_PMD_REGISTER_PCI_TABLE(NFP_PF_DRIVER_NAME, pci_id_nfp_pf_net_map);
2090 : : RTE_PMD_REGISTER_KMOD_DEP(NFP_PF_DRIVER_NAME, "* igb_uio | uio_pci_generic | vfio");
|