Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2022 Corigine, Inc.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "nfp_flower.h"
7 : :
8 : : #include <rte_alarm.h>
9 : : #include <rte_malloc.h>
10 : : #include <rte_service_component.h>
11 : :
12 : : #include "../nfd3/nfp_nfd3.h"
13 : : #include "../nfdk/nfp_nfdk.h"
14 : : #include "../nfpcore/nfp_nsp.h"
15 : : #include "../nfpcore/nfp_rtsym.h"
16 : : #include "../nfp_cpp_bridge.h"
17 : : #include "../nfp_logs.h"
18 : : #include "../nfp_mtr.h"
19 : : #include "nfp_flower_ctrl.h"
20 : : #include "nfp_flower_representor.h"
21 : :
22 : : #define CTRL_VNIC_NB_DESC 512
23 : :
24 : : int
25 : 0 : nfp_flower_pf_start(struct rte_eth_dev *dev)
26 : : {
27 : : int ret;
28 : : uint16_t i;
29 : : struct nfp_hw *hw;
30 : : uint32_t new_ctrl;
31 : : uint32_t update = 0;
32 : : struct nfp_net_hw *net_hw;
33 : : struct nfp_flower_representor *repr;
34 : :
35 : 0 : repr = dev->data->dev_private;
36 : 0 : net_hw = repr->app_fw_flower->pf_hw;
37 : 0 : hw = &net_hw->super;
38 : :
39 : : /* Disabling queues just in case... */
40 : 0 : nfp_net_disable_queues(dev);
41 : :
42 : : /* Enabling the required queues in the device */
43 : 0 : nfp_net_enable_queues(dev);
44 : :
45 : 0 : new_ctrl = nfp_check_offloads(dev);
46 : :
47 : : /* Writing configuration parameters in the device */
48 : 0 : nfp_net_params_setup(net_hw);
49 : :
50 : : update |= NFP_NET_CFG_UPDATE_RSS;
51 [ # # ]: 0 : new_ctrl |= nfp_net_cfg_ctrl_rss(hw->cap);
52 : :
53 : : /* Enable device */
54 : 0 : new_ctrl |= NFP_NET_CFG_CTRL_ENABLE;
55 : :
56 : : update |= NFP_NET_CFG_UPDATE_GEN | NFP_NET_CFG_UPDATE_RING;
57 : :
58 [ # # ]: 0 : if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0)
59 : 0 : new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG;
60 : :
61 : : /* If an error when reconfig we avoid to change hw state */
62 : 0 : ret = nfp_reconfig(hw, new_ctrl, update);
63 [ # # ]: 0 : if (ret != 0) {
64 : 0 : PMD_INIT_LOG(ERR, "Failed to reconfig PF vnic");
65 : 0 : return -EIO;
66 : : }
67 : :
68 : 0 : hw->ctrl = new_ctrl;
69 : :
70 : : /* Setup the freelist ring */
71 : 0 : ret = nfp_net_rx_freelist_setup(dev);
72 [ # # ]: 0 : if (ret != 0) {
73 : 0 : PMD_INIT_LOG(ERR, "Error with flower PF vNIC freelist setup");
74 : 0 : return -EIO;
75 : : }
76 : :
77 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
78 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
79 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
80 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
81 : :
82 : : return 0;
83 : : }
84 : :
85 : : /* Reset and stop device. The device can not be restarted. */
86 : : static int
87 : 0 : nfp_flower_pf_close(struct rte_eth_dev *dev)
88 : : {
89 : : uint16_t i;
90 : : struct nfp_net_hw *hw;
91 : : struct nfp_pf_dev *pf_dev;
92 : : struct nfp_net_txq *this_tx_q;
93 : : struct nfp_net_rxq *this_rx_q;
94 : : struct nfp_flower_representor *repr;
95 : : struct nfp_app_fw_flower *app_fw_flower;
96 : :
97 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
98 : : return 0;
99 : :
100 : 0 : repr = dev->data->dev_private;
101 : 0 : hw = repr->app_fw_flower->pf_hw;
102 : 0 : pf_dev = hw->pf_dev;
103 : 0 : app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);
104 : :
105 : 0 : nfp_mtr_priv_uninit(pf_dev);
106 : :
107 : : /*
108 : : * We assume that the DPDK application is stopping all the
109 : : * threads/queues before calling the device close function.
110 : : */
111 : 0 : nfp_net_disable_queues(dev);
112 : :
113 : : /* Clear queues */
114 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
115 : 0 : this_tx_q = dev->data->tx_queues[i];
116 : 0 : nfp_net_reset_tx_queue(this_tx_q);
117 : : }
118 : :
119 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
120 : 0 : this_rx_q = dev->data->rx_queues[i];
121 : 0 : nfp_net_reset_rx_queue(this_rx_q);
122 : : }
123 : :
124 : : /* Cancel possible impending LSC work here before releasing the port */
125 : 0 : rte_eal_alarm_cancel(nfp_net_dev_interrupt_delayed_handler, (void *)dev);
126 : :
127 : : nn_cfg_writeb(&hw->super, NFP_NET_CFG_LSC, 0xff);
128 : :
129 : : /* Now it is safe to free all PF resources */
130 : 0 : PMD_DRV_LOG(INFO, "Freeing PF resources");
131 : 0 : nfp_cpp_area_free(pf_dev->ctrl_area);
132 : 0 : nfp_cpp_area_free(pf_dev->qc_area);
133 : 0 : free(pf_dev->hwinfo);
134 : 0 : free(pf_dev->sym_tbl);
135 : 0 : nfp_cpp_free(pf_dev->cpp);
136 : 0 : rte_free(app_fw_flower);
137 : 0 : rte_free(pf_dev);
138 : :
139 : 0 : return 0;
140 : : }
141 : :
142 : : static const struct eth_dev_ops nfp_flower_pf_vnic_ops = {
143 : : .dev_infos_get = nfp_net_infos_get,
144 : : .link_update = nfp_net_link_update,
145 : : .dev_configure = nfp_net_configure,
146 : :
147 : : .dev_start = nfp_flower_pf_start,
148 : : .dev_stop = nfp_net_stop,
149 : : .dev_close = nfp_flower_pf_close,
150 : : };
151 : :
152 : : static inline struct nfp_flower_representor *
153 : : nfp_flower_get_repr(struct nfp_net_hw *hw,
154 : : uint32_t port_id)
155 : : {
156 : : uint8_t port;
157 : : struct nfp_app_fw_flower *app_fw_flower;
158 : :
159 : : /* Obtain handle to app_fw_flower here */
160 : 0 : app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(hw->pf_dev->app_fw_priv);
161 : :
162 : 0 : switch (NFP_FLOWER_CMSG_PORT_TYPE(port_id)) {
163 : 0 : case NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT:
164 : : port = NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM(port_id);
165 : 0 : return app_fw_flower->phy_reprs[port];
166 : 0 : case NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT:
167 : 0 : port = NFP_FLOWER_CMSG_PORT_VNIC(port_id);
168 : 0 : return app_fw_flower->vf_reprs[port];
169 : : default:
170 : : break;
171 : : }
172 : :
173 : : return NULL;
174 : : }
175 : :
176 : : bool
177 [ # # # ]: 0 : nfp_flower_pf_dispatch_pkts(struct nfp_net_hw *hw,
178 : : struct rte_mbuf *mbuf,
179 : : uint32_t port_id)
180 : : {
181 : : struct nfp_flower_representor *repr;
182 : :
183 : : repr = nfp_flower_get_repr(hw, port_id);
184 [ # # ]: 0 : if (repr == NULL) {
185 : : PMD_RX_LOG(ERR, "Can not get repr for port %u", hw->idx);
186 : : return false;
187 : : }
188 : :
189 [ # # ]: 0 : if (repr->ring == NULL) {
190 : : PMD_RX_LOG(ERR, "No ring available for repr_port %s", repr->name);
191 : : return false;
192 : : }
193 : :
194 : 0 : rte_ring_enqueue(repr->ring, (void *)mbuf);
195 : 0 : return true;
196 : : }
197 : :
198 : : static uint16_t
199 : 0 : nfp_flower_pf_nfd3_xmit_pkts(void *tx_queue,
200 : : struct rte_mbuf **tx_pkts,
201 : : uint16_t nb_pkts)
202 : : {
203 : 0 : return nfp_net_nfd3_xmit_pkts_common(tx_queue, tx_pkts, nb_pkts, true);
204 : : }
205 : :
206 : : static uint16_t
207 : 0 : nfp_flower_pf_nfdk_xmit_pkts(void *tx_queue,
208 : : struct rte_mbuf **tx_pkts,
209 : : uint16_t nb_pkts)
210 : : {
211 : 0 : return nfp_net_nfdk_xmit_pkts_common(tx_queue, tx_pkts, nb_pkts, true);
212 : : }
213 : :
214 : : static void
215 : : nfp_flower_pf_xmit_pkts_register(struct nfp_app_fw_flower *app_fw_flower)
216 : : {
217 : : struct nfp_net_hw *hw;
218 : : struct nfp_flower_nfd_func *nfd_func;
219 : :
220 : 0 : hw = app_fw_flower->pf_hw;
221 : : nfd_func = &app_fw_flower->nfd_func;
222 : :
223 [ # # ]: 0 : if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
224 : 0 : nfd_func->pf_xmit_t = nfp_flower_pf_nfd3_xmit_pkts;
225 : : else
226 : 0 : nfd_func->pf_xmit_t = nfp_flower_pf_nfdk_xmit_pkts;
227 : : }
228 : :
229 : : uint16_t
230 : 0 : nfp_flower_pf_xmit_pkts(void *tx_queue,
231 : : struct rte_mbuf **tx_pkts,
232 : : uint16_t nb_pkts)
233 : : {
234 : : struct nfp_net_txq *txq;
235 : : struct nfp_app_fw_flower *app_fw_flower;
236 : :
237 : : txq = tx_queue;
238 : 0 : app_fw_flower = txq->hw->pf_dev->app_fw_priv;
239 : :
240 : 0 : return app_fw_flower->nfd_func.pf_xmit_t(tx_queue, tx_pkts, nb_pkts);
241 : : }
242 : :
243 : : static int
244 : 0 : nfp_flower_init_vnic_common(struct nfp_net_hw *hw,
245 : : const char *vnic_type)
246 : : {
247 : : int err;
248 : : uint32_t start_q;
249 : : uint64_t rx_bar_off;
250 : : uint64_t tx_bar_off;
251 : : struct nfp_pf_dev *pf_dev;
252 : : struct rte_pci_device *pci_dev;
253 : :
254 : 0 : pf_dev = hw->pf_dev;
255 : 0 : pci_dev = hw->pf_dev->pci_dev;
256 : :
257 : 0 : PMD_INIT_LOG(DEBUG, "%s vNIC ctrl bar: %p", vnic_type, hw->super.ctrl_bar);
258 : :
259 : 0 : err = nfp_net_common_init(pci_dev, hw);
260 [ # # ]: 0 : if (err != 0)
261 : : return err;
262 : :
263 : : /* Work out where in the BAR the queues start */
264 : : start_q = nn_cfg_readl(&hw->super, NFP_NET_CFG_START_TXQ);
265 : 0 : tx_bar_off = (uint64_t)start_q * NFP_QCP_QUEUE_ADDR_SZ;
266 : : start_q = nn_cfg_readl(&hw->super, NFP_NET_CFG_START_RXQ);
267 : 0 : rx_bar_off = (uint64_t)start_q * NFP_QCP_QUEUE_ADDR_SZ;
268 : :
269 : 0 : hw->tx_bar = pf_dev->qc_bar + tx_bar_off;
270 : 0 : hw->rx_bar = pf_dev->qc_bar + rx_bar_off;
271 : :
272 : : /* Set the current MTU to the maximum supported */
273 : 0 : hw->mtu = hw->max_mtu;
274 : :
275 : : /* Reuse cfg queue setup function */
276 : 0 : nfp_net_cfg_queue_setup(hw);
277 : :
278 : 0 : PMD_INIT_LOG(INFO, "%s vNIC max_rx_queues: %u, max_tx_queues: %u",
279 : : vnic_type, hw->max_rx_queues, hw->max_tx_queues);
280 : :
281 : : /* Initializing spinlock for reconfigs */
282 : : rte_spinlock_init(&hw->super.reconfig_lock);
283 : :
284 : 0 : return 0;
285 : : }
286 : :
287 : : static int
288 : 0 : nfp_flower_init_ctrl_vnic(struct nfp_net_hw *hw)
289 : : {
290 : : uint16_t i;
291 : : int ret = 0;
292 : : uint16_t n_txq;
293 : : uint16_t n_rxq;
294 : : const char *pci_name;
295 : : unsigned int numa_node;
296 : : struct rte_mempool *mp;
297 : : struct nfp_net_rxq *rxq;
298 : : struct nfp_net_txq *txq;
299 : : struct nfp_pf_dev *pf_dev;
300 : : struct rte_eth_dev *eth_dev;
301 : : const struct rte_memzone *tz;
302 : : struct nfp_app_fw_flower *app_fw_flower;
303 : : char ctrl_rxring_name[RTE_MEMZONE_NAMESIZE];
304 : : char ctrl_txring_name[RTE_MEMZONE_NAMESIZE];
305 : : char ctrl_pktmbuf_pool_name[RTE_MEMZONE_NAMESIZE];
306 : :
307 : : /* Set up some pointers here for ease of use */
308 : 0 : pf_dev = hw->pf_dev;
309 : 0 : app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);
310 : :
311 : 0 : ret = nfp_flower_init_vnic_common(hw, "ctrl_vnic");
312 [ # # ]: 0 : if (ret != 0) {
313 : 0 : PMD_INIT_LOG(ERR, "Could not init pf vnic");
314 : 0 : return -EINVAL;
315 : : }
316 : :
317 : : /* Allocate memory for the eth_dev of the vNIC */
318 : 0 : hw->eth_dev = rte_zmalloc("nfp_ctrl_vnic",
319 : : sizeof(struct rte_eth_dev), RTE_CACHE_LINE_SIZE);
320 [ # # ]: 0 : if (hw->eth_dev == NULL) {
321 : 0 : PMD_INIT_LOG(ERR, "Could not allocate ctrl vnic");
322 : 0 : return -ENOMEM;
323 : : }
324 : :
325 : : /* Grab the pointer to the newly created rte_eth_dev here */
326 : : eth_dev = hw->eth_dev;
327 : :
328 : : /* Also allocate memory for the data part of the eth_dev */
329 : 0 : eth_dev->data = rte_zmalloc("nfp_ctrl_vnic_data",
330 : : sizeof(struct rte_eth_dev_data), RTE_CACHE_LINE_SIZE);
331 [ # # ]: 0 : if (eth_dev->data == NULL) {
332 : 0 : PMD_INIT_LOG(ERR, "Could not allocate ctrl vnic data");
333 : : ret = -ENOMEM;
334 : 0 : goto eth_dev_cleanup;
335 : : }
336 : :
337 : 0 : pci_name = strchr(pf_dev->pci_dev->name, ':') + 1;
338 : :
339 : : /* Create a mbuf pool for the ctrl vNIC */
340 : 0 : numa_node = rte_socket_id();
341 : : snprintf(ctrl_pktmbuf_pool_name, sizeof(ctrl_pktmbuf_pool_name),
342 : : "%s_ctrlmp", pci_name);
343 : 0 : app_fw_flower->ctrl_pktmbuf_pool =
344 : 0 : rte_pktmbuf_pool_create(ctrl_pktmbuf_pool_name,
345 : : 4 * CTRL_VNIC_NB_DESC, 64, 0, 9216, numa_node);
346 [ # # ]: 0 : if (app_fw_flower->ctrl_pktmbuf_pool == NULL) {
347 : 0 : PMD_INIT_LOG(ERR, "Create mbuf pool for ctrl vnic failed");
348 : : ret = -ENOMEM;
349 : 0 : goto dev_data_cleanup;
350 : : }
351 : :
352 : : mp = app_fw_flower->ctrl_pktmbuf_pool;
353 : :
354 : : /* Configure the ctrl vNIC device */
355 : 0 : n_rxq = hw->max_rx_queues;
356 : 0 : n_txq = hw->max_tx_queues;
357 : 0 : eth_dev->data->rx_queues = rte_zmalloc("ethdev->rx_queues",
358 : : sizeof(eth_dev->data->rx_queues[0]) * n_rxq,
359 : : RTE_CACHE_LINE_SIZE);
360 [ # # ]: 0 : if (eth_dev->data->rx_queues == NULL) {
361 : 0 : PMD_INIT_LOG(ERR, "rte_zmalloc failed for ctrl vNIC rx queues");
362 : : ret = -ENOMEM;
363 : 0 : goto mempool_cleanup;
364 : : }
365 : :
366 : 0 : eth_dev->data->tx_queues = rte_zmalloc("ethdev->tx_queues",
367 : : sizeof(eth_dev->data->tx_queues[0]) * n_txq,
368 : : RTE_CACHE_LINE_SIZE);
369 [ # # ]: 0 : if (eth_dev->data->tx_queues == NULL) {
370 : 0 : PMD_INIT_LOG(ERR, "rte_zmalloc failed for ctrl vNIC tx queues");
371 : : ret = -ENOMEM;
372 : 0 : goto rx_queue_free;
373 : : }
374 : :
375 : : /* Fill in some of the eth_dev fields */
376 : 0 : eth_dev->device = &pf_dev->pci_dev->device;
377 : 0 : eth_dev->data->nb_tx_queues = n_rxq;
378 : 0 : eth_dev->data->nb_rx_queues = n_txq;
379 : 0 : eth_dev->data->dev_private = hw;
380 : :
381 : : snprintf(ctrl_rxring_name, sizeof(ctrl_rxring_name), "%s_ctrx_ring", pci_name);
382 : : /* Set up the Rx queues */
383 [ # # ]: 0 : for (i = 0; i < n_rxq; i++) {
384 : 0 : rxq = rte_zmalloc_socket("ethdev RX queue",
385 : : sizeof(struct nfp_net_rxq), RTE_CACHE_LINE_SIZE,
386 : : numa_node);
387 [ # # ]: 0 : if (rxq == NULL) {
388 : 0 : PMD_DRV_LOG(ERR, "Error allocating rxq");
389 : : ret = -ENOMEM;
390 : 0 : goto rx_queue_setup_cleanup;
391 : : }
392 : :
393 : 0 : eth_dev->data->rx_queues[i] = rxq;
394 : :
395 : : /* Hw queues mapping based on firmware configuration */
396 : 0 : rxq->qidx = i;
397 : 0 : rxq->fl_qcidx = i * hw->stride_rx;
398 : 0 : rxq->qcp_fl = hw->rx_bar + NFP_QCP_QUEUE_OFF(rxq->fl_qcidx);
399 : :
400 : : /*
401 : : * Tracking mbuf size for detecting a potential mbuf overflow due to
402 : : * RX offset.
403 : : */
404 : 0 : rxq->mem_pool = mp;
405 : 0 : rxq->mbuf_size = rxq->mem_pool->elt_size;
406 : 0 : rxq->mbuf_size -= (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM);
407 : 0 : hw->flbufsz = rxq->mbuf_size;
408 : :
409 : 0 : rxq->rx_count = CTRL_VNIC_NB_DESC;
410 : 0 : rxq->rx_free_thresh = DEFAULT_RX_FREE_THRESH;
411 : :
412 : : /*
413 : : * Allocate RX ring hardware descriptors. A memzone large enough to
414 : : * handle the maximum ring size is allocated in order to allow for
415 : : * resizing in later calls to the queue setup function.
416 : : */
417 : 0 : tz = rte_eth_dma_zone_reserve(eth_dev, ctrl_rxring_name, i,
418 : : sizeof(struct nfp_net_rx_desc) *
419 : 0 : hw->dev_info->max_qc_size,
420 : : NFP_MEMZONE_ALIGN, numa_node);
421 [ # # ]: 0 : if (tz == NULL) {
422 : 0 : PMD_DRV_LOG(ERR, "Error allocating rx dma");
423 : 0 : rte_free(rxq);
424 : : ret = -ENOMEM;
425 : 0 : goto rx_queue_setup_cleanup;
426 : : }
427 : :
428 : : /* Saving physical and virtual addresses for the RX ring */
429 : 0 : rxq->dma = (uint64_t)tz->iova;
430 : 0 : rxq->rxds = tz->addr;
431 : :
432 : : /* Mbuf pointers array for referencing mbufs linked to RX descriptors */
433 : 0 : rxq->rxbufs = rte_zmalloc_socket("rxq->rxbufs",
434 : : sizeof(*rxq->rxbufs) * CTRL_VNIC_NB_DESC,
435 : : RTE_CACHE_LINE_SIZE, numa_node);
436 [ # # ]: 0 : if (rxq->rxbufs == NULL) {
437 : 0 : rte_eth_dma_zone_free(eth_dev, ctrl_rxring_name, i);
438 : 0 : rte_free(rxq);
439 : : ret = -ENOMEM;
440 : 0 : goto rx_queue_setup_cleanup;
441 : : }
442 : :
443 : 0 : nfp_net_reset_rx_queue(rxq);
444 : :
445 : 0 : rxq->hw = hw;
446 : :
447 : : /*
448 : : * Telling the HW about the physical address of the RX ring and number
449 : : * of descriptors in log2 format.
450 : : */
451 : 0 : nn_cfg_writeq(&hw->super, NFP_NET_CFG_RXR_ADDR(i), rxq->dma);
452 : 0 : nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_SZ(i), rte_log2_u32(CTRL_VNIC_NB_DESC));
453 : : }
454 : :
455 : : snprintf(ctrl_txring_name, sizeof(ctrl_txring_name), "%s_cttx_ring", pci_name);
456 : : /* Set up the Tx queues */
457 [ # # ]: 0 : for (i = 0; i < n_txq; i++) {
458 : 0 : txq = rte_zmalloc_socket("ethdev TX queue",
459 : : sizeof(struct nfp_net_txq), RTE_CACHE_LINE_SIZE,
460 : : numa_node);
461 [ # # ]: 0 : if (txq == NULL) {
462 : 0 : PMD_DRV_LOG(ERR, "Error allocating txq");
463 : : ret = -ENOMEM;
464 : 0 : goto tx_queue_setup_cleanup;
465 : : }
466 : :
467 : 0 : eth_dev->data->tx_queues[i] = txq;
468 : :
469 : : /*
470 : : * Allocate TX ring hardware descriptors. A memzone large enough to
471 : : * handle the maximum ring size is allocated in order to allow for
472 : : * resizing in later calls to the queue setup function.
473 : : */
474 : 0 : tz = rte_eth_dma_zone_reserve(eth_dev, ctrl_txring_name, i,
475 : : sizeof(struct nfp_net_nfd3_tx_desc) *
476 : 0 : hw->dev_info->max_qc_size,
477 : : NFP_MEMZONE_ALIGN, numa_node);
478 [ # # ]: 0 : if (tz == NULL) {
479 : 0 : PMD_DRV_LOG(ERR, "Error allocating tx dma");
480 : 0 : rte_free(txq);
481 : : ret = -ENOMEM;
482 : 0 : goto tx_queue_setup_cleanup;
483 : : }
484 : :
485 : 0 : txq->tx_count = CTRL_VNIC_NB_DESC;
486 : 0 : txq->tx_free_thresh = DEFAULT_RX_FREE_THRESH;
487 : :
488 : : /* Queue mapping based on firmware configuration */
489 : 0 : txq->qidx = i;
490 : 0 : txq->tx_qcidx = i * hw->stride_tx;
491 : 0 : txq->qcp_q = hw->tx_bar + NFP_QCP_QUEUE_OFF(txq->tx_qcidx);
492 : :
493 : : /* Saving physical and virtual addresses for the TX ring */
494 : 0 : txq->dma = (uint64_t)tz->iova;
495 : 0 : txq->txds = tz->addr;
496 : :
497 : : /* Mbuf pointers array for referencing mbufs linked to TX descriptors */
498 : 0 : txq->txbufs = rte_zmalloc_socket("txq->txbufs",
499 : : sizeof(*txq->txbufs) * CTRL_VNIC_NB_DESC,
500 : : RTE_CACHE_LINE_SIZE, numa_node);
501 [ # # ]: 0 : if (txq->txbufs == NULL) {
502 : 0 : rte_eth_dma_zone_free(eth_dev, ctrl_txring_name, i);
503 : 0 : rte_free(txq);
504 : : ret = -ENOMEM;
505 : 0 : goto tx_queue_setup_cleanup;
506 : : }
507 : :
508 : 0 : nfp_net_reset_tx_queue(txq);
509 : :
510 : 0 : txq->hw = hw;
511 : :
512 : : /*
513 : : * Telling the HW about the physical address of the TX ring and number
514 : : * of descriptors in log2 format.
515 : : */
516 : 0 : nn_cfg_writeq(&hw->super, NFP_NET_CFG_TXR_ADDR(i), txq->dma);
517 : 0 : nn_cfg_writeb(&hw->super, NFP_NET_CFG_TXR_SZ(i), rte_log2_u32(CTRL_VNIC_NB_DESC));
518 : : }
519 : :
520 : : return 0;
521 : :
522 : : tx_queue_setup_cleanup:
523 [ # # ]: 0 : for (i = 0; i < hw->max_tx_queues; i++) {
524 : 0 : txq = eth_dev->data->tx_queues[i];
525 [ # # ]: 0 : if (txq != NULL) {
526 : 0 : rte_free(txq->txbufs);
527 : 0 : rte_eth_dma_zone_free(eth_dev, ctrl_txring_name, i);
528 : 0 : rte_free(txq);
529 : : }
530 : : }
531 : 0 : rx_queue_setup_cleanup:
532 [ # # ]: 0 : for (i = 0; i < hw->max_rx_queues; i++) {
533 : 0 : rxq = eth_dev->data->rx_queues[i];
534 [ # # ]: 0 : if (rxq != NULL) {
535 : 0 : rte_free(rxq->rxbufs);
536 : 0 : rte_eth_dma_zone_free(eth_dev, ctrl_rxring_name, i);
537 : 0 : rte_free(rxq);
538 : : }
539 : : }
540 : 0 : rte_free(eth_dev->data->tx_queues);
541 : 0 : rx_queue_free:
542 : 0 : rte_free(eth_dev->data->rx_queues);
543 : 0 : mempool_cleanup:
544 : 0 : rte_mempool_free(mp);
545 : 0 : dev_data_cleanup:
546 : 0 : rte_free(eth_dev->data);
547 : 0 : eth_dev_cleanup:
548 : 0 : rte_free(eth_dev);
549 : :
550 : 0 : return ret;
551 : : }
552 : :
553 : : static void
554 : 0 : nfp_flower_cleanup_ctrl_vnic(struct nfp_net_hw *hw)
555 : : {
556 : : uint32_t i;
557 : : const char *pci_name;
558 : : struct nfp_net_rxq *rxq;
559 : : struct nfp_net_txq *txq;
560 : : struct rte_eth_dev *eth_dev;
561 : : struct nfp_app_fw_flower *app_fw_flower;
562 : : char ctrl_txring_name[RTE_MEMZONE_NAMESIZE];
563 : : char ctrl_rxring_name[RTE_MEMZONE_NAMESIZE];
564 : :
565 : 0 : eth_dev = hw->eth_dev;
566 : 0 : app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(hw->pf_dev->app_fw_priv);
567 : :
568 : 0 : pci_name = strchr(app_fw_flower->pf_hw->pf_dev->pci_dev->name, ':') + 1;
569 : :
570 : : snprintf(ctrl_txring_name, sizeof(ctrl_txring_name), "%s_cttx_ring", pci_name);
571 [ # # ]: 0 : for (i = 0; i < hw->max_tx_queues; i++) {
572 : 0 : txq = eth_dev->data->tx_queues[i];
573 [ # # ]: 0 : if (txq != NULL) {
574 : 0 : rte_free(txq->txbufs);
575 : 0 : rte_eth_dma_zone_free(eth_dev, ctrl_txring_name, i);
576 : 0 : rte_free(txq);
577 : : }
578 : : }
579 : :
580 : : snprintf(ctrl_rxring_name, sizeof(ctrl_rxring_name), "%s_ctrx_ring", pci_name);
581 [ # # ]: 0 : for (i = 0; i < hw->max_rx_queues; i++) {
582 : 0 : rxq = eth_dev->data->rx_queues[i];
583 [ # # ]: 0 : if (rxq != NULL) {
584 : 0 : rte_free(rxq->rxbufs);
585 : 0 : rte_eth_dma_zone_free(eth_dev, ctrl_rxring_name, i);
586 : 0 : rte_free(rxq);
587 : : }
588 : : }
589 : :
590 : 0 : rte_free(eth_dev->data->tx_queues);
591 : 0 : rte_free(eth_dev->data->rx_queues);
592 : 0 : rte_mempool_free(app_fw_flower->ctrl_pktmbuf_pool);
593 : 0 : rte_free(eth_dev->data);
594 : 0 : rte_free(eth_dev);
595 : 0 : }
596 : :
597 : : static int
598 : 0 : nfp_flower_start_ctrl_vnic(struct nfp_net_hw *net_hw)
599 : : {
600 : : int ret;
601 : : uint32_t update;
602 : : uint32_t new_ctrl;
603 : : struct nfp_hw *hw;
604 : : struct rte_eth_dev *dev;
605 : :
606 : 0 : dev = net_hw->eth_dev;
607 : 0 : hw = &net_hw->super;
608 : :
609 : : /* Disabling queues just in case... */
610 : 0 : nfp_net_disable_queues(dev);
611 : :
612 : : /* Enabling the required queues in the device */
613 : 0 : nfp_net_enable_queues(dev);
614 : :
615 : : /* Writing configuration parameters in the device */
616 : 0 : nfp_net_params_setup(net_hw);
617 : :
618 : : new_ctrl = NFP_NET_CFG_CTRL_ENABLE;
619 : : update = NFP_NET_CFG_UPDATE_GEN | NFP_NET_CFG_UPDATE_RING |
620 : : NFP_NET_CFG_UPDATE_MSIX;
621 : :
622 : : rte_wmb();
623 : :
624 : : /* If an error when reconfig we avoid to change hw state */
625 : 0 : ret = nfp_reconfig(hw, new_ctrl, update);
626 [ # # ]: 0 : if (ret != 0) {
627 : 0 : PMD_INIT_LOG(ERR, "Failed to reconfig ctrl vnic");
628 : 0 : return -EIO;
629 : : }
630 : :
631 : 0 : hw->ctrl = new_ctrl;
632 : :
633 : : /* Setup the freelist ring */
634 : 0 : ret = nfp_net_rx_freelist_setup(dev);
635 [ # # ]: 0 : if (ret != 0) {
636 : 0 : PMD_INIT_LOG(ERR, "Error with flower ctrl vNIC freelist setup");
637 : 0 : return -EIO;
638 : : }
639 : :
640 : : return 0;
641 : : }
642 : :
643 : : static int
644 : 0 : nfp_flower_ctrl_vnic_service(void *arg)
645 : : {
646 : : struct nfp_app_fw_flower *app_fw_flower = arg;
647 : :
648 : 0 : nfp_flower_ctrl_vnic_poll(app_fw_flower);
649 : :
650 : 0 : return 0;
651 : : }
652 : :
653 : : static int
654 : 0 : nfp_flower_enable_services(struct nfp_app_fw_flower *app_fw_flower)
655 : : {
656 : : int ret;
657 : : uint32_t service_id;
658 : 0 : const struct rte_service_spec flower_service = {
659 : : .name = "flower_ctrl_vnic_service",
660 : : .callback = nfp_flower_ctrl_vnic_service,
661 : : .callback_userdata = (void *)app_fw_flower,
662 : : };
663 : :
664 : : /* Register the flower services */
665 : 0 : ret = rte_service_component_register(&flower_service, &service_id);
666 [ # # ]: 0 : if (ret != 0) {
667 : 0 : PMD_INIT_LOG(ERR, "Could not register %s", flower_service.name);
668 : 0 : return -EINVAL;
669 : : }
670 : :
671 : 0 : app_fw_flower->ctrl_vnic_id = service_id;
672 : 0 : PMD_INIT_LOG(INFO, "%s registered", flower_service.name);
673 : :
674 : : /* Map them to available service cores */
675 : 0 : ret = nfp_map_service(service_id);
676 [ # # ]: 0 : if (ret != 0) {
677 : 0 : PMD_INIT_LOG(ERR, "Could not map %s", flower_service.name);
678 : 0 : return -EINVAL;
679 : : }
680 : :
681 : : return 0;
682 : : }
683 : :
684 : : static void
685 : : nfp_flower_pkt_add_metadata_register(struct nfp_app_fw_flower *app_fw_flower)
686 : : {
687 : : struct nfp_net_hw *hw;
688 : : struct nfp_flower_nfd_func *nfd_func;
689 : :
690 : 0 : hw = app_fw_flower->pf_hw;
691 : : nfd_func = &app_fw_flower->nfd_func;
692 : :
693 : 0 : if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
694 : 0 : nfd_func->pkt_add_metadata_t = nfp_flower_nfd3_pkt_add_metadata;
695 : : else
696 : 0 : nfd_func->pkt_add_metadata_t = nfp_flower_nfdk_pkt_add_metadata;
697 : : }
698 : :
699 : : uint32_t
700 : 0 : nfp_flower_pkt_add_metadata(struct nfp_app_fw_flower *app_fw_flower,
701 : : struct rte_mbuf *mbuf,
702 : : uint32_t port_id)
703 : : {
704 : 0 : return app_fw_flower->nfd_func.pkt_add_metadata_t(mbuf, port_id);
705 : : }
706 : :
707 : : static void
708 [ # # ]: 0 : nfp_flower_nfd_func_register(struct nfp_app_fw_flower *app_fw_flower)
709 : : {
710 : : nfp_flower_pkt_add_metadata_register(app_fw_flower);
711 : 0 : nfp_flower_ctrl_vnic_xmit_register(app_fw_flower);
712 : : nfp_flower_pf_xmit_pkts_register(app_fw_flower);
713 : 0 : }
714 : :
715 : : int
716 : 0 : nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev,
717 : : const struct nfp_dev_info *dev_info)
718 : : {
719 : : int ret;
720 : : int err;
721 : : uint64_t ext_features;
722 : : unsigned int numa_node;
723 : : struct nfp_net_hw *pf_hw;
724 : : struct nfp_net_hw *ctrl_hw;
725 : : struct nfp_app_fw_flower *app_fw_flower;
726 : :
727 : 0 : numa_node = rte_socket_id();
728 : :
729 : : /* Allocate memory for the Flower app */
730 : 0 : app_fw_flower = rte_zmalloc_socket("nfp_app_fw_flower", sizeof(*app_fw_flower),
731 : : RTE_CACHE_LINE_SIZE, numa_node);
732 [ # # ]: 0 : if (app_fw_flower == NULL) {
733 : 0 : PMD_INIT_LOG(ERR, "Could not malloc app fw flower");
734 : 0 : return -ENOMEM;
735 : : }
736 : :
737 : 0 : pf_dev->app_fw_priv = app_fw_flower;
738 : :
739 : 0 : ret = nfp_flow_priv_init(pf_dev);
740 [ # # ]: 0 : if (ret != 0) {
741 : 0 : PMD_INIT_LOG(ERR, "init flow priv failed");
742 : 0 : goto app_cleanup;
743 : : }
744 : :
745 : 0 : ret = nfp_mtr_priv_init(pf_dev);
746 [ # # ]: 0 : if (ret != 0) {
747 : 0 : PMD_INIT_LOG(ERR, "Error initializing metering private data");
748 : 0 : goto flow_priv_cleanup;
749 : : }
750 : :
751 : : /* Allocate memory for the PF AND ctrl vNIC here (hence the * 2) */
752 : 0 : pf_hw = rte_zmalloc_socket("nfp_pf_vnic", 2 * sizeof(struct nfp_net_hw),
753 : : RTE_CACHE_LINE_SIZE, numa_node);
754 [ # # ]: 0 : if (pf_hw == NULL) {
755 : 0 : PMD_INIT_LOG(ERR, "Could not malloc nfp pf vnic");
756 : : ret = -ENOMEM;
757 : 0 : goto mtr_priv_cleanup;
758 : : }
759 : :
760 : : /* Map the PF ctrl bar */
761 : 0 : pf_dev->ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, "_pf0_net_bar0",
762 : : NFP_NET_CFG_BAR_SZ, &pf_dev->ctrl_area);
763 [ # # ]: 0 : if (pf_dev->ctrl_bar == NULL) {
764 : 0 : PMD_INIT_LOG(ERR, "Cloud not map the PF vNIC ctrl bar");
765 : : ret = -ENODEV;
766 : 0 : goto vnic_cleanup;
767 : : }
768 : :
769 : : /* Read the extra features */
770 : 0 : ext_features = nfp_rtsym_read_le(pf_dev->sym_tbl, "_abi_flower_extra_features",
771 : : &err);
772 [ # # ]: 0 : if (err != 0) {
773 : 0 : PMD_INIT_LOG(ERR, "Couldn't read extra features from fw");
774 : : ret = -EIO;
775 : 0 : goto pf_cpp_area_cleanup;
776 : : }
777 : :
778 : : /* Store the extra features */
779 : 0 : app_fw_flower->ext_features = ext_features;
780 : :
781 : : /* Fill in the PF vNIC and populate app struct */
782 : 0 : app_fw_flower->pf_hw = pf_hw;
783 : 0 : pf_hw->super.ctrl_bar = pf_dev->ctrl_bar;
784 : 0 : pf_hw->pf_dev = pf_dev;
785 : 0 : pf_hw->cpp = pf_dev->cpp;
786 : 0 : pf_hw->dev_info = dev_info;
787 : :
788 : 0 : ret = nfp_flower_init_vnic_common(app_fw_flower->pf_hw, "pf_vnic");
789 [ # # ]: 0 : if (ret != 0) {
790 : 0 : PMD_INIT_LOG(ERR, "Could not initialize flower PF vNIC");
791 : 0 : goto pf_cpp_area_cleanup;
792 : : }
793 : :
794 : 0 : nfp_flower_nfd_func_register(app_fw_flower);
795 : :
796 : : /* The ctrl vNIC struct comes directly after the PF one */
797 : 0 : app_fw_flower->ctrl_hw = pf_hw + 1;
798 : : ctrl_hw = app_fw_flower->ctrl_hw;
799 : :
800 : : /* Map the ctrl vNIC ctrl bar */
801 : 0 : ctrl_hw->super.ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, "_pf0_net_ctrl_bar",
802 : : NFP_NET_CFG_BAR_SZ, &ctrl_hw->ctrl_area);
803 [ # # ]: 0 : if (ctrl_hw->super.ctrl_bar == NULL) {
804 : 0 : PMD_INIT_LOG(ERR, "Cloud not map the ctrl vNIC ctrl bar");
805 : : ret = -ENODEV;
806 : 0 : goto pf_cpp_area_cleanup;
807 : : }
808 : :
809 : : /* Now populate the ctrl vNIC */
810 : 0 : ctrl_hw->pf_dev = pf_dev;
811 : 0 : ctrl_hw->cpp = pf_dev->cpp;
812 : 0 : ctrl_hw->dev_info = dev_info;
813 : :
814 : 0 : ret = nfp_flower_init_ctrl_vnic(app_fw_flower->ctrl_hw);
815 [ # # ]: 0 : if (ret != 0) {
816 : 0 : PMD_INIT_LOG(ERR, "Could not initialize flower ctrl vNIC");
817 : 0 : goto ctrl_cpp_area_cleanup;
818 : : }
819 : :
820 : : /* Start the ctrl vNIC */
821 : 0 : ret = nfp_flower_start_ctrl_vnic(app_fw_flower->ctrl_hw);
822 [ # # ]: 0 : if (ret != 0) {
823 : 0 : PMD_INIT_LOG(ERR, "Could not start flower ctrl vNIC");
824 : 0 : goto ctrl_vnic_cleanup;
825 : : }
826 : :
827 : : /* Start up flower services */
828 : 0 : ret = nfp_flower_enable_services(app_fw_flower);
829 [ # # ]: 0 : if (ret != 0) {
830 : 0 : PMD_INIT_LOG(ERR, "Could not enable flower services");
831 : : ret = -ESRCH;
832 : 0 : goto ctrl_vnic_cleanup;
833 : : }
834 : :
835 : 0 : ret = nfp_flower_repr_create(app_fw_flower);
836 [ # # ]: 0 : if (ret != 0) {
837 : 0 : PMD_INIT_LOG(ERR, "Could not create representor ports");
838 : 0 : goto ctrl_vnic_cleanup;
839 : : }
840 : :
841 : : return 0;
842 : :
843 : 0 : ctrl_vnic_cleanup:
844 : 0 : nfp_flower_cleanup_ctrl_vnic(app_fw_flower->ctrl_hw);
845 : 0 : ctrl_cpp_area_cleanup:
846 : 0 : nfp_cpp_area_free(ctrl_hw->ctrl_area);
847 : 0 : pf_cpp_area_cleanup:
848 : 0 : nfp_cpp_area_free(pf_dev->ctrl_area);
849 : 0 : vnic_cleanup:
850 : 0 : rte_free(pf_hw);
851 : 0 : mtr_priv_cleanup:
852 : 0 : nfp_mtr_priv_uninit(pf_dev);
853 : 0 : flow_priv_cleanup:
854 : 0 : nfp_flow_priv_uninit(pf_dev);
855 : 0 : app_cleanup:
856 : 0 : rte_free(app_fw_flower);
857 : :
858 : 0 : return ret;
859 : : }
860 : :
861 : : int
862 : 0 : nfp_secondary_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
863 : : {
864 : : struct rte_eth_dev *eth_dev;
865 : : const char *port_name = "pf_vnic_eth_dev";
866 : :
867 : 0 : PMD_INIT_LOG(DEBUG, "Secondary attaching to port %s", port_name);
868 : :
869 : 0 : eth_dev = rte_eth_dev_attach_secondary(port_name);
870 [ # # ]: 0 : if (eth_dev == NULL) {
871 : 0 : PMD_INIT_LOG(ERR, "Secondary process attach to port %s failed", port_name);
872 : 0 : return -ENODEV;
873 : : }
874 : :
875 : 0 : eth_dev->process_private = pf_dev->cpp;
876 : 0 : eth_dev->dev_ops = &nfp_flower_pf_vnic_ops;
877 : 0 : eth_dev->rx_pkt_burst = nfp_net_recv_pkts;
878 : 0 : eth_dev->tx_pkt_burst = nfp_flower_pf_xmit_pkts;
879 : 0 : rte_eth_dev_probing_finish(eth_dev);
880 : :
881 : 0 : return 0;
882 : : }
|