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_representor.h"
7 : :
8 : : #include "../nfd3/nfp_nfd3.h"
9 : : #include "../nfpcore/nfp_nsp.h"
10 : : #include "../nfp_logs.h"
11 : : #include "../nfp_mtr.h"
12 : : #include "nfp_flower_service.h"
13 : :
14 : : /* Type of representor */
15 : : enum nfp_repr_type {
16 : : NFP_REPR_TYPE_PHYS_PORT, /*<< External NIC port */
17 : : NFP_REPR_TYPE_PF, /*<< Physical function */
18 : : NFP_REPR_TYPE_VF, /*<< Virtual function */
19 : : NFP_REPR_TYPE_MAX, /*<< Number of representor types */
20 : : };
21 : :
22 : : static int
23 : 0 : nfp_flower_repr_link_update(struct rte_eth_dev *dev,
24 : : __rte_unused int wait_to_complete)
25 : : {
26 : : int ret;
27 : : uint32_t nn_link_status;
28 : : struct nfp_net_hw *pf_hw;
29 : : struct rte_eth_link *link;
30 : : struct nfp_flower_representor *repr;
31 : :
32 : 0 : repr = dev->data->dev_private;
33 : 0 : link = &repr->link;
34 : :
35 : 0 : pf_hw = repr->app_fw_flower->pf_hw;
36 : 0 : nn_link_status = nn_cfg_readw(&pf_hw->super, NFP_NET_CFG_STS);
37 : :
38 : 0 : ret = nfp_net_link_update_common(dev, pf_hw, link, nn_link_status);
39 : :
40 : 0 : return ret;
41 : : }
42 : :
43 : : static int
44 : 0 : nfp_flower_repr_dev_infos_get(__rte_unused struct rte_eth_dev *dev,
45 : : struct rte_eth_dev_info *dev_info)
46 : : {
47 : : struct nfp_net_hw *pf_hw;
48 : : struct nfp_flower_representor *repr;
49 : :
50 : 0 : repr = dev->data->dev_private;
51 : 0 : pf_hw = repr->app_fw_flower->pf_hw;
52 : :
53 : : /* Hardcoded pktlen and queues for now */
54 : 0 : dev_info->max_rx_queues = 1;
55 : 0 : dev_info->max_tx_queues = 1;
56 : 0 : dev_info->min_rx_bufsize = RTE_ETHER_MIN_MTU;
57 : 0 : dev_info->max_rx_pktlen = 9000;
58 : :
59 : : dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
60 : 0 : dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
61 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
62 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM;
63 : :
64 : : dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT;
65 : : dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
66 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
67 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM;
68 : : dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_TCP_TSO;
69 : 0 : dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
70 : :
71 : 0 : dev_info->max_mac_addrs = 1;
72 : :
73 [ # # ]: 0 : if ((pf_hw->super.cap & NFP_NET_CFG_CTRL_RSS_ANY) != 0) {
74 : 0 : dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
75 : 0 : dev_info->flow_type_rss_offloads = NFP_NET_RSS_CAP;
76 : 0 : dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ;
77 : 0 : dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ;
78 : : }
79 : :
80 : 0 : return 0;
81 : : }
82 : :
83 : : static int
84 : 0 : nfp_flower_repr_dev_start(struct rte_eth_dev *dev)
85 : : {
86 : : struct nfp_flower_representor *repr;
87 : : struct nfp_app_fw_flower *app_fw_flower;
88 : : uint16_t i;
89 : :
90 : 0 : repr = dev->data->dev_private;
91 : 0 : app_fw_flower = repr->app_fw_flower;
92 : :
93 [ # # ]: 0 : if (repr->repr_type == NFP_REPR_TYPE_PHYS_PORT) {
94 : 0 : nfp_eth_set_configured(app_fw_flower->pf_hw->pf_dev->cpp,
95 : : repr->nfp_idx, 1);
96 : : }
97 : :
98 : 0 : nfp_flower_cmsg_port_mod(app_fw_flower, repr->port_id, true);
99 : :
100 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
101 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
102 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
103 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
104 : :
105 : 0 : return 0;
106 : : }
107 : :
108 : : static int
109 : 0 : nfp_flower_repr_dev_stop(struct rte_eth_dev *dev)
110 : : {
111 : : struct nfp_flower_representor *repr;
112 : : struct nfp_app_fw_flower *app_fw_flower;
113 : : uint16_t i;
114 : :
115 : 0 : repr = dev->data->dev_private;
116 : 0 : app_fw_flower = repr->app_fw_flower;
117 : :
118 : 0 : nfp_flower_cmsg_port_mod(app_fw_flower, repr->port_id, false);
119 : :
120 [ # # ]: 0 : if (repr->repr_type == NFP_REPR_TYPE_PHYS_PORT) {
121 : 0 : nfp_eth_set_configured(app_fw_flower->pf_hw->pf_dev->cpp,
122 : : repr->nfp_idx, 0);
123 : : }
124 : :
125 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
126 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
127 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
128 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
129 : :
130 : 0 : return 0;
131 : : }
132 : :
133 : : static int
134 : 0 : nfp_flower_repr_rx_queue_setup(struct rte_eth_dev *dev,
135 : : uint16_t rx_queue_id,
136 : : __rte_unused uint16_t nb_rx_desc,
137 : : unsigned int socket_id,
138 : : __rte_unused const struct rte_eth_rxconf *rx_conf,
139 : : __rte_unused struct rte_mempool *mb_pool)
140 : : {
141 : : struct nfp_net_rxq *rxq;
142 : : struct nfp_net_hw *pf_hw;
143 : : struct nfp_flower_representor *repr;
144 : :
145 : 0 : repr = dev->data->dev_private;
146 : 0 : pf_hw = repr->app_fw_flower->pf_hw;
147 : :
148 : : /* Allocating rx queue data structure */
149 : 0 : rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct nfp_net_rxq),
150 : : RTE_CACHE_LINE_SIZE, socket_id);
151 [ # # ]: 0 : if (rxq == NULL)
152 : : return -ENOMEM;
153 : :
154 : 0 : rxq->hw = pf_hw;
155 : 0 : rxq->qidx = rx_queue_id;
156 : 0 : rxq->port_id = dev->data->port_id;
157 : 0 : dev->data->rx_queues[rx_queue_id] = rxq;
158 : :
159 : 0 : return 0;
160 : : }
161 : :
162 : : static int
163 : 0 : nfp_flower_repr_tx_queue_setup(struct rte_eth_dev *dev,
164 : : uint16_t tx_queue_id,
165 : : __rte_unused uint16_t nb_tx_desc,
166 : : unsigned int socket_id,
167 : : __rte_unused const struct rte_eth_txconf *tx_conf)
168 : : {
169 : : struct nfp_net_txq *txq;
170 : : struct nfp_net_hw *pf_hw;
171 : : struct nfp_flower_representor *repr;
172 : :
173 : 0 : repr = dev->data->dev_private;
174 : 0 : pf_hw = repr->app_fw_flower->pf_hw;
175 : :
176 : : /* Allocating tx queue data structure */
177 : 0 : txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct nfp_net_txq),
178 : : RTE_CACHE_LINE_SIZE, socket_id);
179 [ # # ]: 0 : if (txq == NULL)
180 : : return -ENOMEM;
181 : :
182 : 0 : txq->hw = pf_hw;
183 : 0 : txq->qidx = tx_queue_id;
184 : 0 : txq->port_id = dev->data->port_id;
185 : 0 : dev->data->tx_queues[tx_queue_id] = txq;
186 : :
187 : 0 : return 0;
188 : : }
189 : :
190 : : static int
191 : 0 : nfp_flower_repr_stats_get(struct rte_eth_dev *ethdev,
192 : : struct rte_eth_stats *stats)
193 : : {
194 : : struct nfp_flower_representor *repr;
195 : :
196 : 0 : repr = ethdev->data->dev_private;
197 [ # # ]: 0 : rte_memcpy(stats, &repr->repr_stats, sizeof(struct rte_eth_stats));
198 : :
199 : 0 : return 0;
200 : : }
201 : :
202 : : static int
203 : 0 : nfp_flower_repr_stats_reset(struct rte_eth_dev *ethdev)
204 : : {
205 : : struct nfp_flower_representor *repr;
206 : :
207 : 0 : repr = ethdev->data->dev_private;
208 : 0 : memset(&repr->repr_stats, 0, sizeof(struct rte_eth_stats));
209 : :
210 : 0 : return 0;
211 : : }
212 : :
213 : : static int
214 : 0 : nfp_flower_repr_mac_addr_set(struct rte_eth_dev *ethdev,
215 : : struct rte_ether_addr *mac_addr)
216 : : {
217 : : struct nfp_flower_representor *repr;
218 : :
219 : 0 : repr = ethdev->data->dev_private;
220 : : rte_ether_addr_copy(mac_addr, &repr->mac_addr);
221 : 0 : rte_ether_addr_copy(mac_addr, ethdev->data->mac_addrs);
222 : :
223 : 0 : return 0;
224 : : }
225 : :
226 : : static uint16_t
227 : 0 : nfp_flower_repr_rx_burst(void *rx_queue,
228 : : struct rte_mbuf **rx_pkts,
229 : : uint16_t nb_pkts)
230 : : {
231 : : unsigned int available = 0;
232 : : unsigned int total_dequeue;
233 : : struct nfp_net_rxq *rxq;
234 : : struct rte_eth_dev *dev;
235 : : struct nfp_flower_representor *repr;
236 : :
237 : : rxq = rx_queue;
238 [ # # ]: 0 : if (unlikely(rxq == NULL)) {
239 : : PMD_RX_LOG(ERR, "RX Bad queue");
240 : : return 0;
241 : : }
242 : :
243 : 0 : dev = &rte_eth_devices[rxq->port_id];
244 : 0 : repr = dev->data->dev_private;
245 [ # # ]: 0 : if (unlikely(repr->ring == NULL)) {
246 : : PMD_RX_LOG(ERR, "representor %s has no ring configured!",
247 : : repr->name);
248 : : return 0;
249 : : }
250 : :
251 [ # # # # : 0 : total_dequeue = rte_ring_dequeue_burst(repr->ring, (void *)rx_pkts,
# ]
252 : : nb_pkts, &available);
253 [ # # ]: 0 : if (total_dequeue != 0) {
254 : : PMD_RX_LOG(DEBUG, "Representor Rx burst for %s, port_id: %#x, "
255 : : "received: %u, available: %u", repr->name,
256 : : repr->port_id, total_dequeue, available);
257 : :
258 : 0 : repr->repr_stats.ipackets += total_dequeue;
259 : : }
260 : :
261 : 0 : return total_dequeue;
262 : : }
263 : :
264 : : static uint16_t
265 : 0 : nfp_flower_repr_tx_burst(void *tx_queue,
266 : : struct rte_mbuf **tx_pkts,
267 : : uint16_t nb_pkts)
268 : : {
269 : : uint16_t i;
270 : : uint16_t sent;
271 : : void *pf_tx_queue;
272 : : struct nfp_net_txq *txq;
273 : : struct nfp_net_hw *pf_hw;
274 : : struct rte_eth_dev *dev;
275 : : struct rte_eth_dev *repr_dev;
276 : : struct nfp_flower_representor *repr;
277 : :
278 : : txq = tx_queue;
279 [ # # ]: 0 : if (unlikely(txq == NULL)) {
280 : : PMD_TX_LOG(ERR, "TX Bad queue");
281 : : return 0;
282 : : }
283 : :
284 : : /* Grab a handle to the representor struct */
285 : 0 : repr_dev = &rte_eth_devices[txq->port_id];
286 : 0 : repr = repr_dev->data->dev_private;
287 : :
288 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++)
289 : 0 : nfp_flower_pkt_add_metadata(repr->app_fw_flower,
290 : 0 : tx_pkts[i], repr->port_id);
291 : :
292 : : /* This points to the PF vNIC that owns this representor */
293 : 0 : pf_hw = txq->hw;
294 : 0 : dev = pf_hw->eth_dev;
295 : :
296 : : /* Only using Tx queue 0 for now. */
297 : 0 : pf_tx_queue = dev->data->tx_queues[0];
298 : 0 : sent = nfp_flower_pf_xmit_pkts(pf_tx_queue, tx_pkts, nb_pkts);
299 [ # # ]: 0 : if (sent != 0) {
300 : : PMD_TX_LOG(DEBUG, "Representor Tx burst for %s, port_id: %#x transmitted: %hu",
301 : : repr->name, repr->port_id, sent);
302 : 0 : repr->repr_stats.opackets += sent;
303 : : }
304 : :
305 : : return sent;
306 : : }
307 : :
308 : : static int
309 : 0 : nfp_flower_repr_uninit(struct rte_eth_dev *eth_dev)
310 : : {
311 : : uint16_t index;
312 : : struct nfp_flower_representor *repr;
313 : :
314 : 0 : repr = eth_dev->data->dev_private;
315 : 0 : rte_ring_free(repr->ring);
316 : :
317 [ # # ]: 0 : if (repr->repr_type == NFP_REPR_TYPE_PHYS_PORT) {
318 : 0 : index = NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM(repr->port_id);
319 : 0 : repr->app_fw_flower->phy_reprs[index] = NULL;
320 : : } else {
321 : 0 : index = repr->vf_id;
322 : 0 : repr->app_fw_flower->vf_reprs[index] = NULL;
323 : : }
324 : :
325 : 0 : return 0;
326 : : }
327 : :
328 : : static int
329 : : nfp_flower_pf_repr_uninit(struct rte_eth_dev *eth_dev)
330 : : {
331 : 0 : struct nfp_flower_representor *repr = eth_dev->data->dev_private;
332 : :
333 : 0 : repr->app_fw_flower->pf_repr = NULL;
334 : :
335 : 0 : return 0;
336 : : }
337 : :
338 : : static void
339 : 0 : nfp_flower_repr_free(struct nfp_flower_representor *repr,
340 : : enum nfp_repr_type repr_type)
341 : : {
342 [ # # # # ]: 0 : switch (repr_type) {
343 : 0 : case NFP_REPR_TYPE_PHYS_PORT:
344 : 0 : nfp_flower_repr_uninit(repr->eth_dev);
345 : 0 : break;
346 : 0 : case NFP_REPR_TYPE_PF:
347 : 0 : nfp_flower_pf_repr_uninit(repr->eth_dev);
348 : : break;
349 : 0 : case NFP_REPR_TYPE_VF:
350 : 0 : nfp_flower_repr_uninit(repr->eth_dev);
351 : 0 : break;
352 : 0 : default:
353 : 0 : PMD_DRV_LOG(ERR, "Unsupported repr port type.");
354 : 0 : break;
355 : : }
356 : 0 : }
357 : :
358 : : /* Reset and stop device. The device can not be restarted. */
359 : : static int
360 : 0 : nfp_flower_repr_dev_close(struct rte_eth_dev *dev)
361 : : {
362 : : uint16_t i;
363 : : struct nfp_net_hw *hw;
364 : : struct nfp_pf_dev *pf_dev;
365 : : struct nfp_net_txq *this_tx_q;
366 : : struct nfp_net_rxq *this_rx_q;
367 : : struct nfp_flower_representor *repr;
368 : : struct nfp_app_fw_flower *app_fw_flower;
369 : :
370 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
371 : : return 0;
372 : :
373 : 0 : repr = dev->data->dev_private;
374 : 0 : app_fw_flower = repr->app_fw_flower;
375 : 0 : hw = app_fw_flower->pf_hw;
376 : 0 : pf_dev = hw->pf_dev;
377 : :
378 : : /*
379 : : * We assume that the DPDK application is stopping all the
380 : : * threads/queues before calling the device close function.
381 : : */
382 : 0 : nfp_net_disable_queues(dev);
383 : :
384 : : /* Clear queues */
385 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
386 : 0 : this_tx_q = dev->data->tx_queues[i];
387 : 0 : nfp_net_reset_tx_queue(this_tx_q);
388 : : }
389 : :
390 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
391 : 0 : this_rx_q = dev->data->rx_queues[i];
392 : 0 : nfp_net_reset_rx_queue(this_rx_q);
393 : : }
394 : :
395 [ # # ]: 0 : if (pf_dev->app_fw_id != NFP_APP_FW_FLOWER_NIC)
396 : : return -EINVAL;
397 : :
398 : 0 : nfp_flower_repr_free(repr, repr->repr_type);
399 : :
400 [ # # ]: 0 : for (i = 0; i < MAX_FLOWER_VFS; i++) {
401 [ # # ]: 0 : if (app_fw_flower->vf_reprs[i] != NULL)
402 : : return 0;
403 : : }
404 : :
405 [ # # ]: 0 : for (i = 0; i < NFP_MAX_PHYPORTS; i++) {
406 [ # # ]: 0 : if (app_fw_flower->phy_reprs[i] != NULL)
407 : : return 0;
408 : : }
409 : :
410 [ # # ]: 0 : if (app_fw_flower->pf_repr != NULL)
411 : : return 0;
412 : :
413 : : /* Stop flower service first */
414 : 0 : nfp_flower_service_stop(app_fw_flower);
415 : :
416 : : /* Disable cpp service */
417 : 0 : nfp_service_disable(&pf_dev->cpp_service_info);
418 : :
419 : : /* Now it is safe to free all PF resources */
420 : 0 : nfp_uninit_app_fw_flower(pf_dev);
421 : 0 : nfp_pf_uninit(pf_dev);
422 : :
423 : 0 : return 0;
424 : : }
425 : :
426 : : static const struct eth_dev_ops nfp_flower_pf_repr_dev_ops = {
427 : : .dev_infos_get = nfp_flower_repr_dev_infos_get,
428 : :
429 : : .dev_start = nfp_flower_pf_start,
430 : : .dev_configure = nfp_net_configure,
431 : : .dev_stop = nfp_net_stop,
432 : : .dev_close = nfp_flower_repr_dev_close,
433 : :
434 : : .rx_queue_setup = nfp_net_rx_queue_setup,
435 : : .tx_queue_setup = nfp_net_tx_queue_setup,
436 : :
437 : : .link_update = nfp_flower_repr_link_update,
438 : :
439 : : .stats_get = nfp_flower_repr_stats_get,
440 : : .stats_reset = nfp_flower_repr_stats_reset,
441 : :
442 : : .promiscuous_enable = nfp_net_promisc_enable,
443 : : .promiscuous_disable = nfp_net_promisc_disable,
444 : :
445 : : .mac_addr_set = nfp_flower_repr_mac_addr_set,
446 : : .fw_version_get = nfp_net_firmware_version_get,
447 : : };
448 : :
449 : : static const struct eth_dev_ops nfp_flower_repr_dev_ops = {
450 : : .dev_infos_get = nfp_flower_repr_dev_infos_get,
451 : :
452 : : .dev_start = nfp_flower_repr_dev_start,
453 : : .dev_configure = nfp_net_configure,
454 : : .dev_stop = nfp_flower_repr_dev_stop,
455 : : .dev_close = nfp_flower_repr_dev_close,
456 : :
457 : : .rx_queue_setup = nfp_flower_repr_rx_queue_setup,
458 : : .tx_queue_setup = nfp_flower_repr_tx_queue_setup,
459 : :
460 : : .link_update = nfp_flower_repr_link_update,
461 : :
462 : : .stats_get = nfp_flower_repr_stats_get,
463 : : .stats_reset = nfp_flower_repr_stats_reset,
464 : :
465 : : .promiscuous_enable = nfp_net_promisc_enable,
466 : : .promiscuous_disable = nfp_net_promisc_disable,
467 : :
468 : : .mac_addr_set = nfp_flower_repr_mac_addr_set,
469 : : .fw_version_get = nfp_net_firmware_version_get,
470 : :
471 : : .flow_ops_get = nfp_flow_ops_get,
472 : : .mtr_ops_get = nfp_net_mtr_ops_get,
473 : : };
474 : :
475 : : static uint32_t
476 : : nfp_flower_get_phys_port_id(uint8_t port)
477 : : {
478 : 0 : return (NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT << 28) | port;
479 : : }
480 : :
481 : : static uint32_t
482 : : nfp_get_pcie_port_id(struct nfp_cpp *cpp,
483 : : int type,
484 : : uint8_t vnic,
485 : : uint8_t queue)
486 : : {
487 : : uint8_t nfp_pcie;
488 : : uint32_t port_id;
489 : :
490 : 0 : nfp_pcie = NFP_CPP_INTERFACE_UNIT_of(nfp_cpp_interface(cpp));
491 : 0 : port_id = ((nfp_pcie & 0x3) << 14) |
492 : 0 : ((type & 0x3) << 12) |
493 : 0 : ((vnic & 0x3f) << 6) |
494 : 0 : (queue & 0x3f) |
495 : : ((NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT & 0xf) << 28);
496 : :
497 : : return port_id;
498 : : }
499 : :
500 : : static int
501 : 0 : nfp_flower_pf_repr_init(struct rte_eth_dev *eth_dev,
502 : : void *init_params)
503 : : {
504 : : struct nfp_flower_representor *repr;
505 : : struct nfp_flower_representor *init_repr_data;
506 : :
507 : : /* Cast the input representor data to the correct struct here */
508 : : init_repr_data = init_params;
509 : :
510 : : /* Memory has been allocated in the eth_dev_create() function */
511 : 0 : repr = eth_dev->data->dev_private;
512 : :
513 : : /* Copy data here from the input representor template */
514 : 0 : repr->vf_id = init_repr_data->vf_id;
515 : 0 : repr->switch_domain_id = init_repr_data->switch_domain_id;
516 : 0 : repr->repr_type = init_repr_data->repr_type;
517 : 0 : repr->app_fw_flower = init_repr_data->app_fw_flower;
518 : :
519 : 0 : snprintf(repr->name, sizeof(repr->name), "%s", init_repr_data->name);
520 : :
521 : 0 : eth_dev->dev_ops = &nfp_flower_pf_repr_dev_ops;
522 : 0 : eth_dev->rx_pkt_burst = nfp_net_recv_pkts;
523 : 0 : eth_dev->tx_pkt_burst = nfp_flower_pf_xmit_pkts;
524 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
525 : :
526 : 0 : eth_dev->data->representor_id = 0;
527 : :
528 : : /* This backer port is that of the eth_device created for the PF vNIC */
529 : 0 : eth_dev->data->backer_port_id = 0;
530 : :
531 : : /* Only single queues for representor devices */
532 : 0 : eth_dev->data->nb_rx_queues = 1;
533 : 0 : eth_dev->data->nb_tx_queues = 1;
534 : :
535 : : /* Allocating memory for mac addr */
536 : 0 : eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", RTE_ETHER_ADDR_LEN, 0);
537 [ # # ]: 0 : if (eth_dev->data->mac_addrs == NULL) {
538 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for repr MAC");
539 : 0 : return -ENOMEM;
540 : : }
541 : :
542 : : rte_ether_addr_copy(&init_repr_data->mac_addr, &repr->mac_addr);
543 : : rte_ether_addr_copy(&init_repr_data->mac_addr, eth_dev->data->mac_addrs);
544 : :
545 : 0 : repr->app_fw_flower->pf_repr = repr;
546 : 0 : repr->app_fw_flower->pf_hw->eth_dev = eth_dev;
547 : 0 : repr->eth_dev = eth_dev;
548 : :
549 : 0 : return 0;
550 : : }
551 : :
552 : : static int
553 : 0 : nfp_flower_repr_init(struct rte_eth_dev *eth_dev,
554 : : void *init_params)
555 : : {
556 : : int ret;
557 : : uint16_t index;
558 : : unsigned int numa_node;
559 : : char ring_name[RTE_ETH_NAME_MAX_LEN];
560 : : struct nfp_app_fw_flower *app_fw_flower;
561 : : struct nfp_flower_representor *repr;
562 : : struct nfp_flower_representor *init_repr_data;
563 : :
564 : : /* Cast the input representor data to the correct struct here */
565 : : init_repr_data = init_params;
566 : 0 : app_fw_flower = init_repr_data->app_fw_flower;
567 : :
568 : : /* Memory has been allocated in the eth_dev_create() function */
569 : 0 : repr = eth_dev->data->dev_private;
570 : :
571 : : /*
572 : : * We need multiproduce rings as we can have multiple PF ports.
573 : : * On the other hand, we need single consumer rings, as just one
574 : : * representor PMD will try to read from the ring.
575 : : */
576 : 0 : snprintf(ring_name, sizeof(ring_name), "%s_%s", init_repr_data->name, "ring");
577 : 0 : numa_node = rte_socket_id();
578 : 0 : repr->ring = rte_ring_create(ring_name, 256, numa_node, RING_F_SC_DEQ);
579 [ # # ]: 0 : if (repr->ring == NULL) {
580 : 0 : PMD_DRV_LOG(ERR, "rte_ring_create failed for %s", ring_name);
581 : 0 : return -ENOMEM;
582 : : }
583 : :
584 : : /* Copy data here from the input representor template */
585 : 0 : repr->vf_id = init_repr_data->vf_id;
586 : 0 : repr->switch_domain_id = init_repr_data->switch_domain_id;
587 : 0 : repr->port_id = init_repr_data->port_id;
588 : 0 : repr->nfp_idx = init_repr_data->nfp_idx;
589 : 0 : repr->repr_type = init_repr_data->repr_type;
590 : 0 : repr->app_fw_flower = init_repr_data->app_fw_flower;
591 : :
592 [ # # ]: 0 : snprintf(repr->name, sizeof(repr->name), "%s", init_repr_data->name);
593 : :
594 : 0 : eth_dev->dev_ops = &nfp_flower_repr_dev_ops;
595 : 0 : eth_dev->rx_pkt_burst = nfp_flower_repr_rx_burst;
596 : 0 : eth_dev->tx_pkt_burst = nfp_flower_repr_tx_burst;
597 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
598 : :
599 [ # # ]: 0 : if (repr->repr_type == NFP_REPR_TYPE_PHYS_PORT)
600 : 0 : eth_dev->data->representor_id = repr->vf_id;
601 : : else
602 : 0 : eth_dev->data->representor_id = repr->vf_id +
603 : 0 : app_fw_flower->num_phyport_reprs + 1;
604 : :
605 : : /* This backer port is that of the eth_device created for the PF vNIC */
606 : 0 : eth_dev->data->backer_port_id = 0;
607 : :
608 : : /* Only single queues for representor devices */
609 : 0 : eth_dev->data->nb_rx_queues = 1;
610 : 0 : eth_dev->data->nb_tx_queues = 1;
611 : :
612 : : /* Allocating memory for mac addr */
613 : 0 : eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", RTE_ETHER_ADDR_LEN, 0);
614 [ # # ]: 0 : if (eth_dev->data->mac_addrs == NULL) {
615 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for repr MAC");
616 : : ret = -ENOMEM;
617 : 0 : goto ring_cleanup;
618 : : }
619 : :
620 : : rte_ether_addr_copy(&init_repr_data->mac_addr, &repr->mac_addr);
621 : : rte_ether_addr_copy(&init_repr_data->mac_addr, eth_dev->data->mac_addrs);
622 : :
623 : : /* Send reify message to hardware to inform it about the new repr */
624 : 0 : ret = nfp_flower_cmsg_repr_reify(app_fw_flower, repr);
625 [ # # ]: 0 : if (ret != 0) {
626 : 0 : PMD_INIT_LOG(WARNING, "Failed to send repr reify message");
627 : 0 : goto mac_cleanup;
628 : : }
629 : :
630 : : /* Add repr to correct array */
631 [ # # ]: 0 : if (repr->repr_type == NFP_REPR_TYPE_PHYS_PORT) {
632 : 0 : index = NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM(repr->port_id);
633 : 0 : app_fw_flower->phy_reprs[index] = repr;
634 : : } else {
635 : 0 : index = repr->vf_id;
636 : 0 : app_fw_flower->vf_reprs[index] = repr;
637 : : }
638 : :
639 : 0 : repr->eth_dev = eth_dev;
640 : :
641 : 0 : return 0;
642 : :
643 : : mac_cleanup:
644 : 0 : rte_free(eth_dev->data->mac_addrs);
645 : 0 : ring_cleanup:
646 : 0 : rte_ring_free(repr->ring);
647 : :
648 : 0 : return ret;
649 : : }
650 : :
651 : : static void
652 : 0 : nfp_flower_repr_free_all(struct nfp_app_fw_flower *app_fw_flower)
653 : : {
654 : : uint32_t i;
655 : : struct nfp_flower_representor *repr;
656 : :
657 [ # # ]: 0 : for (i = 0; i < MAX_FLOWER_VFS; i++) {
658 : 0 : repr = app_fw_flower->vf_reprs[i];
659 [ # # ]: 0 : if (repr != NULL) {
660 : : nfp_flower_repr_free(repr, NFP_REPR_TYPE_VF);
661 : 0 : app_fw_flower->vf_reprs[i] = NULL;
662 : : }
663 : : }
664 : :
665 [ # # ]: 0 : for (i = 0; i < NFP_MAX_PHYPORTS; i++) {
666 : 0 : repr = app_fw_flower->phy_reprs[i];
667 [ # # ]: 0 : if (repr != NULL) {
668 : : nfp_flower_repr_free(repr, NFP_REPR_TYPE_PHYS_PORT);
669 : 0 : app_fw_flower->phy_reprs[i] = NULL;
670 : : }
671 : : }
672 : :
673 : 0 : repr = app_fw_flower->pf_repr;
674 [ # # ]: 0 : if (repr != NULL) {
675 : : nfp_flower_repr_free(repr, NFP_REPR_TYPE_PF);
676 : 0 : app_fw_flower->pf_repr = NULL;
677 : : }
678 : 0 : }
679 : :
680 : : static int
681 : 0 : nfp_flower_repr_alloc(struct nfp_app_fw_flower *app_fw_flower)
682 : : {
683 : : int i;
684 : : int ret;
685 : : const char *pci_name;
686 : : struct rte_eth_dev *eth_dev;
687 : : struct rte_pci_device *pci_dev;
688 : : struct nfp_eth_table *nfp_eth_table;
689 : : struct nfp_eth_table_port *eth_port;
690 : 0 : struct nfp_flower_representor flower_repr = {
691 : 0 : .switch_domain_id = app_fw_flower->switch_domain_id,
692 : : .app_fw_flower = app_fw_flower,
693 : : };
694 : :
695 : 0 : nfp_eth_table = app_fw_flower->pf_hw->pf_dev->nfp_eth_table;
696 : 0 : eth_dev = app_fw_flower->ctrl_hw->eth_dev;
697 : :
698 : : /* Send a NFP_FLOWER_CMSG_TYPE_MAC_REPR cmsg to hardware */
699 : 0 : ret = nfp_flower_cmsg_mac_repr(app_fw_flower);
700 [ # # ]: 0 : if (ret != 0) {
701 : 0 : PMD_INIT_LOG(ERR, "Cloud not send mac repr cmsgs");
702 : 0 : return ret;
703 : : }
704 : :
705 : : /* Create a rte_eth_dev for PF vNIC representor */
706 : 0 : flower_repr.repr_type = NFP_REPR_TYPE_PF;
707 : :
708 : : /* PF vNIC reprs get a random MAC address */
709 : 0 : rte_eth_random_addr(flower_repr.mac_addr.addr_bytes);
710 : :
711 : 0 : pci_dev = app_fw_flower->pf_hw->pf_dev->pci_dev;
712 : :
713 : 0 : pci_name = strchr(pci_dev->name, ':') + 1;
714 : :
715 : : snprintf(flower_repr.name, sizeof(flower_repr.name),
716 : : "%s_repr_pf", pci_name);
717 : :
718 : : /* Create a eth_dev for this representor */
719 : 0 : ret = rte_eth_dev_create(eth_dev->device, flower_repr.name,
720 : : sizeof(struct nfp_flower_representor),
721 : : NULL, NULL, nfp_flower_pf_repr_init, &flower_repr);
722 [ # # ]: 0 : if (ret != 0) {
723 : 0 : PMD_INIT_LOG(ERR, "Failed to init the pf repr");
724 : 0 : return -EINVAL;
725 : : }
726 : :
727 : : /* Create a rte_eth_dev for every phyport representor */
728 [ # # ]: 0 : for (i = 0; i < app_fw_flower->num_phyport_reprs; i++) {
729 : : eth_port = &nfp_eth_table->ports[i];
730 : 0 : flower_repr.repr_type = NFP_REPR_TYPE_PHYS_PORT;
731 : 0 : flower_repr.port_id = nfp_flower_get_phys_port_id(eth_port->index);
732 : 0 : flower_repr.nfp_idx = eth_port->eth_index;
733 : 0 : flower_repr.vf_id = i + 1;
734 : :
735 : : /* Copy the real mac of the interface to the representor struct */
736 : : rte_ether_addr_copy(ð_port->mac_addr, &flower_repr.mac_addr);
737 : : snprintf(flower_repr.name, sizeof(flower_repr.name),
738 : : "%s_repr_p%d", pci_name, i);
739 : :
740 : : /*
741 : : * Create a eth_dev for this representor.
742 : : * This will also allocate private memory for the device.
743 : : */
744 : 0 : ret = rte_eth_dev_create(eth_dev->device, flower_repr.name,
745 : : sizeof(struct nfp_flower_representor),
746 : : NULL, NULL, nfp_flower_repr_init, &flower_repr);
747 [ # # ]: 0 : if (ret != 0) {
748 : 0 : PMD_INIT_LOG(ERR, "Cloud not create eth_dev for repr");
749 : 0 : break;
750 : : }
751 : : }
752 : :
753 [ # # ]: 0 : if (i < app_fw_flower->num_phyport_reprs)
754 : 0 : goto repr_free;
755 : :
756 : : /*
757 : : * Now allocate eth_dev's for VF representors.
758 : : * Also send reify messages.
759 : : */
760 [ # # ]: 0 : for (i = 0; i < app_fw_flower->num_vf_reprs; i++) {
761 : 0 : flower_repr.repr_type = NFP_REPR_TYPE_VF;
762 : 0 : flower_repr.port_id = nfp_get_pcie_port_id(app_fw_flower->pf_hw->cpp,
763 : : NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF, i, 0);
764 : 0 : flower_repr.nfp_idx = 0;
765 : 0 : flower_repr.vf_id = i;
766 : :
767 : : /* VF reprs get a random MAC address */
768 : 0 : rte_eth_random_addr(flower_repr.mac_addr.addr_bytes);
769 : : snprintf(flower_repr.name, sizeof(flower_repr.name),
770 : : "%s_repr_vf%d", pci_name, i);
771 : :
772 : : /* This will also allocate private memory for the device */
773 : 0 : ret = rte_eth_dev_create(eth_dev->device, flower_repr.name,
774 : : sizeof(struct nfp_flower_representor),
775 : : NULL, NULL, nfp_flower_repr_init, &flower_repr);
776 [ # # ]: 0 : if (ret != 0) {
777 : 0 : PMD_INIT_LOG(ERR, "Cloud not create eth_dev for repr");
778 : 0 : break;
779 : : }
780 : : }
781 : :
782 [ # # ]: 0 : if (i < app_fw_flower->num_vf_reprs)
783 : 0 : goto repr_free;
784 : :
785 : : return 0;
786 : :
787 : 0 : repr_free:
788 : 0 : nfp_flower_repr_free_all(app_fw_flower);
789 : :
790 : 0 : return ret;
791 : : }
792 : :
793 : : int
794 : 0 : nfp_flower_repr_create(struct nfp_app_fw_flower *app_fw_flower)
795 : : {
796 : : int ret;
797 : : struct nfp_pf_dev *pf_dev;
798 : : struct rte_pci_device *pci_dev;
799 : : struct nfp_eth_table *nfp_eth_table;
800 : 0 : struct rte_eth_devargs eth_da = {
801 : : .nb_representor_ports = 0
802 : : };
803 : :
804 : 0 : pf_dev = app_fw_flower->pf_hw->pf_dev;
805 : 0 : pci_dev = pf_dev->pci_dev;
806 : :
807 : : /* Allocate a switch domain for the flower app */
808 [ # # # # ]: 0 : if (app_fw_flower->switch_domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID &&
809 : 0 : rte_eth_switch_domain_alloc(&app_fw_flower->switch_domain_id) != 0) {
810 : 0 : PMD_INIT_LOG(WARNING, "failed to allocate switch domain for device");
811 : : }
812 : :
813 : : /* Now parse PCI device args passed for representor info */
814 [ # # ]: 0 : if (pci_dev->device.devargs != NULL) {
815 : 0 : ret = rte_eth_devargs_parse(pci_dev->device.devargs->args, ð_da, 1);
816 [ # # ]: 0 : if (ret < 0) {
817 : 0 : PMD_INIT_LOG(ERR, "devarg parse failed");
818 : 0 : return -EINVAL;
819 : : }
820 : : }
821 : :
822 [ # # ]: 0 : if (eth_da.nb_representor_ports == 0) {
823 : 0 : PMD_INIT_LOG(DEBUG, "No representor port need to create.");
824 : 0 : return 0;
825 : : }
826 : :
827 : : /* There always exist phy repr */
828 : 0 : nfp_eth_table = pf_dev->nfp_eth_table;
829 [ # # ]: 0 : if (eth_da.nb_representor_ports < nfp_eth_table->count + 1) {
830 : 0 : PMD_INIT_LOG(ERR, "Should also create repr port for phy port and PF vNIC.");
831 : 0 : return -ERANGE;
832 : : }
833 : :
834 : : /* Only support VF representor creation via the command line */
835 [ # # ]: 0 : if (eth_da.type != RTE_ETH_REPRESENTOR_VF) {
836 : 0 : PMD_INIT_LOG(ERR, "Unsupported representor type: %d", eth_da.type);
837 : 0 : return -ENOTSUP;
838 : : }
839 : :
840 : : /* Fill in flower app with repr counts */
841 : 0 : app_fw_flower->num_phyport_reprs = (uint8_t)nfp_eth_table->count;
842 : 0 : app_fw_flower->num_vf_reprs = eth_da.nb_representor_ports -
843 : 0 : nfp_eth_table->count - 1;
844 : :
845 : 0 : PMD_INIT_LOG(INFO, "%d number of VF reprs", app_fw_flower->num_vf_reprs);
846 : 0 : PMD_INIT_LOG(INFO, "%d number of phyport reprs", app_fw_flower->num_phyport_reprs);
847 : :
848 : 0 : ret = nfp_flower_repr_alloc(app_fw_flower);
849 [ # # ]: 0 : if (ret != 0) {
850 : 0 : PMD_INIT_LOG(ERR, "representors allocation failed");
851 : : ret = -EINVAL;
852 : 0 : goto domain_free;
853 : : }
854 : :
855 : : return 0;
856 : :
857 : : domain_free:
858 [ # # ]: 0 : if (rte_eth_switch_domain_free(app_fw_flower->switch_domain_id) != 0)
859 : 0 : PMD_INIT_LOG(WARNING, "failed to free switch domain for device");
860 : :
861 : : return ret;
862 : : }
863 : :
864 : : bool
865 : 0 : nfp_flower_repr_is_vf(struct nfp_flower_representor *repr)
866 : : {
867 : 0 : return repr->repr_type == NFP_REPR_TYPE_VF;
868 : : }
|