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