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