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