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