1 /* SPDX-License-Identifier: Apache-2.0
2 * Copyright (c) 2023 Cisco Systems, Inc.
6 #include <vnet/dev/dev.h>
7 #include <vnet/dev/pci.h>
8 #include <vnet/dev/counters.h>
9 #include <dev_octeon/octeon.h>
10 #include <dev_octeon/common.h>
11 #include <vnet/ethernet/ethernet.h>
13 VLIB_REGISTER_LOG_CLASS (oct_log, static) = {
14 .class_name = "octeon",
15 .subclass_name = "port",
18 static const u8 default_rss_key[] = {
19 0xfe, 0xed, 0x0b, 0xad, 0xfe, 0xed, 0x0b, 0xad, 0xad, 0x0b, 0xed, 0xfe,
20 0xad, 0x0b, 0xed, 0xfe, 0x13, 0x57, 0x9b, 0xef, 0x24, 0x68, 0xac, 0x0e,
21 0x91, 0x72, 0x53, 0x11, 0x82, 0x64, 0x20, 0x44, 0x12, 0xef, 0x34, 0xcd,
22 0x56, 0xbc, 0x78, 0x9a, 0x9a, 0x78, 0xbc, 0x56, 0xcd, 0x34, 0xef, 0x12
25 static const u32 default_rss_flowkey =
26 (FLOW_KEY_TYPE_IPV4 | FLOW_KEY_TYPE_IPV6 | FLOW_KEY_TYPE_TCP |
27 FLOW_KEY_TYPE_UDP | FLOW_KEY_TYPE_SCTP);
29 static const u64 rxq_cfg =
30 ROC_NIX_LF_RX_CFG_DIS_APAD | ROC_NIX_LF_RX_CFG_IP6_UDP_OPT |
31 ROC_NIX_LF_RX_CFG_L2_LEN_ERR | ROC_NIX_LF_RX_CFG_DROP_RE |
32 ROC_NIX_LF_RX_CFG_CSUM_OL4 | ROC_NIX_LF_RX_CFG_CSUM_IL4 |
33 ROC_NIX_LF_RX_CFG_LEN_OL3 | ROC_NIX_LF_RX_CFG_LEN_OL4 |
34 ROC_NIX_LF_RX_CFG_LEN_IL3 | ROC_NIX_LF_RX_CFG_LEN_IL4;
37 oct_roc_err (vnet_dev_t *dev, int rv, char *fmt, ...)
43 s = va_format (s, fmt, &va);
46 log_err (dev, "%v - ROC error %s (%d)", s, roc_error_msg_get (rv), rv);
49 return VNET_DEV_ERR_INTERNAL;
53 oct_port_init (vlib_main_t *vm, vnet_dev_port_t *port)
55 vnet_dev_t *dev = port->dev;
56 oct_device_t *cd = vnet_dev_get_data (dev);
57 oct_port_t *cp = vnet_dev_get_port_data (port);
58 struct roc_nix *nix = cd->nix;
62 log_debug (dev, "port init: port %u", port->port_id);
64 if ((rrv = roc_nix_lf_alloc (nix, port->intf.num_rx_queues,
65 port->intf.num_tx_queues, rxq_cfg)))
67 oct_port_deinit (vm, port);
70 "roc_nix_lf_alloc(nb_rxq = %u, nb_txq = %d, rxq_cfg=0x%lx) failed",
71 port->intf.num_rx_queues, port->intf.num_tx_queues, rxq_cfg);
75 if ((rrv = roc_nix_tm_init (nix)))
77 oct_port_deinit (vm, port);
78 return oct_roc_err (dev, rrv, "roc_nix_tm_init() failed");
80 cp->tm_initialized = 1;
82 if ((rrv = roc_nix_tm_hierarchy_enable (nix, ROC_NIX_TM_DEFAULT,
83 /* xmit_enable */ 0)))
85 oct_port_deinit (vm, port);
86 return oct_roc_err (dev, rrv, "roc_nix_tm_hierarchy_enable() failed");
89 if ((rrv = roc_nix_rss_default_setup (nix, default_rss_flowkey)))
91 oct_port_deinit (vm, port);
92 return oct_roc_err (dev, rrv, "roc_nix_rss_default_setup() failed");
95 roc_nix_rss_key_set (nix, default_rss_key);
97 cp->npc.roc_nix = nix;
98 if ((rrv = roc_npc_init (&cp->npc)))
100 oct_port_deinit (vm, port);
101 return oct_roc_err (dev, rrv, "roc_npc_init() failed");
103 cp->npc_initialized = 1;
105 foreach_vnet_dev_port_rx_queue (q, port)
107 if ((rv = oct_rxq_init (vm, q)))
109 oct_port_deinit (vm, port);
113 foreach_vnet_dev_port_tx_queue (q, port)
115 if ((rv = oct_txq_init (vm, q)))
117 oct_port_deinit (vm, port);
125 oct_port_deinit (vlib_main_t *vm, vnet_dev_port_t *port)
127 vnet_dev_t *dev = port->dev;
128 oct_device_t *cd = vnet_dev_get_data (dev);
129 oct_port_t *cp = vnet_dev_get_port_data (port);
130 struct roc_nix *nix = cd->nix;
133 foreach_vnet_dev_port_rx_queue (q, port)
134 oct_rxq_deinit (vm, q);
135 foreach_vnet_dev_port_tx_queue (q, port)
136 oct_txq_deinit (vm, q);
138 if (cp->npc_initialized)
140 if ((rrv = roc_npc_fini (&cp->npc)))
141 oct_roc_err (dev, rrv, "roc_npc_fini() failed");
142 cp->npc_initialized = 0;
145 if (cp->tm_initialized)
147 roc_nix_tm_fini (nix);
148 cp->tm_initialized = 0;
151 if (cp->lf_allocated)
153 if ((rrv = roc_nix_lf_free (nix)))
154 oct_roc_err (dev, rrv, "roc_nix_lf_free() failed");
155 cp->lf_allocated = 0;
160 oct_port_poll (vlib_main_t *vm, vnet_dev_port_t *port)
162 vnet_dev_t *dev = port->dev;
163 oct_device_t *cd = vnet_dev_get_data (dev);
164 struct roc_nix *nix = cd->nix;
165 struct roc_nix_link_info link_info = {};
166 vnet_dev_port_state_changes_t changes = {};
169 rrv = roc_nix_mac_link_info_get (nix, &link_info);
173 if (cd->status != link_info.status)
175 changes.change.link_state = 1;
176 changes.link_state = link_info.status;
177 cd->status = link_info.status;
180 if (cd->full_duplex != link_info.full_duplex)
182 changes.change.link_duplex = 1;
183 changes.full_duplex = link_info.full_duplex;
184 cd->full_duplex = link_info.full_duplex;
187 if (cd->speed != link_info.speed)
189 changes.change.link_speed = 1;
190 changes.link_speed = link_info.speed;
191 cd->speed = link_info.speed;
194 if (changes.change.any == 0)
198 "status %u full_duplex %u speed %u port %u lmac_type_id %u "
199 "fec %u aautoneg %u",
200 link_info.status, link_info.full_duplex, link_info.speed,
201 link_info.port, link_info.lmac_type_id, link_info.fec,
203 vnet_dev_port_state_change (vm, port, changes);
207 oct_rxq_start (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
209 vnet_dev_t *dev = rxq->port->dev;
210 oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
211 u32 buffer_indices[rxq->size], n_alloc;
212 u8 bpi = vnet_dev_get_rx_queue_buffer_pool_index (rxq);
215 n_alloc = vlib_buffer_alloc_from_pool (vm, buffer_indices, rxq->size, bpi);
217 for (int i = 0; i < n_alloc; i++)
218 roc_npa_aura_op_free (
220 pointer_to_uword (vlib_get_buffer (vm, buffer_indices[i])) -
223 crq->n_enq = n_alloc;
225 if (roc_npa_aura_op_available (crq->aura_handle) != rxq->size)
226 log_warn (rxq->port->dev, "rx queue %u aura not filled completelly",
229 if ((rrv = roc_nix_rq_ena_dis (&crq->rq, 1)))
230 return oct_roc_err (dev, rrv, "roc_nix_rq_ena_dis() failed");
235 oct_rxq_stop (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
237 vnet_dev_t *dev = rxq->port->dev;
238 oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
242 if ((rrv = roc_nix_rq_ena_dis (&crq->rq, 0)))
243 oct_roc_err (dev, rrv, "roc_nix_rq_ena_dis() failed");
245 n = oct_aura_free_all_buffers (vm, crq->aura_handle, crq->hdr_off);
247 if (crq->n_enq - n > 0)
248 log_err (dev, "%u buffers leaked on rx queue %u stop", crq->n_enq - n,
251 log_debug (dev, "%u buffers freed from rx queue %u", n, rxq->queue_id);
257 oct_txq_stop (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
259 vnet_dev_t *dev = txq->port->dev;
260 oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
261 oct_npa_batch_alloc_cl128_t *cl;
262 u32 n, off = ctq->hdr_off;
264 n = oct_aura_free_all_buffers (vm, ctq->aura_handle, off);
267 if (ctq->n_enq > 0 && ctq->ba_num_cl > 0)
268 for (n = ctq->ba_num_cl, cl = ctq->ba_buffer + ctq->ba_first_cl; n;
271 if (cl->status.ccode != 0)
272 for (u32 i = 0; i < cl->status.count; i++)
274 vlib_buffer_t *b = (vlib_buffer_t *) (cl->iova[i] + off);
275 vlib_buffer_free_one (vm, vlib_get_buffer_index (vm, b));
281 log_err (dev, "%u buffers leaked on tx queue %u stop", ctq->n_enq,
284 log_debug (dev, "%u buffers freed from tx queue %u", n, txq->queue_id);
290 oct_port_start (vlib_main_t *vm, vnet_dev_port_t *port)
292 vnet_dev_t *dev = port->dev;
293 oct_device_t *cd = vnet_dev_get_data (dev);
294 struct roc_nix *nix = cd->nix;
295 struct roc_nix_eeprom_info eeprom_info = {};
299 log_debug (port->dev, "port start: port %u", port->port_id);
301 foreach_vnet_dev_port_rx_queue (q, port)
302 if ((rv = oct_rxq_start (vm, q)) != VNET_DEV_OK)
305 foreach_vnet_dev_port_tx_queue (q, port)
307 oct_txq_t *ctq = vnet_dev_get_tx_queue_data (q);
311 if ((rrv = roc_nix_mac_mtu_set (nix, 9200)))
313 rv = oct_roc_err (dev, rrv, "roc_nix_mac_mtu_set() failed");
317 if ((rrv = roc_nix_npc_rx_ena_dis (nix, true)))
319 rv = oct_roc_err (dev, rrv, "roc_nix_npc_rx_ena_dis() failed");
323 vnet_dev_poll_port_add (vm, port, 0.5, oct_port_poll);
325 if (roc_nix_eeprom_info_get (nix, &eeprom_info) == 0)
327 log_debug (dev, "sff_id %u data %U", eeprom_info.sff_id, format_hexdump,
328 eeprom_info.buf, sizeof (eeprom_info.buf));
331 if (rv != VNET_DEV_OK)
332 oct_port_stop (vm, port);
337 oct_port_stop (vlib_main_t *vm, vnet_dev_port_t *port)
339 vnet_dev_t *dev = port->dev;
340 oct_device_t *cd = vnet_dev_get_data (dev);
341 struct roc_nix *nix = cd->nix;
344 log_debug (port->dev, "port stop: port %u", port->port_id);
346 vnet_dev_poll_port_remove (vm, port, oct_port_poll);
348 rrv = roc_nix_npc_rx_ena_dis (nix, false);
351 oct_roc_err (dev, rrv, "roc_nix_npc_rx_ena_dis() failed");
355 foreach_vnet_dev_port_rx_queue (q, port)
356 oct_rxq_stop (vm, q);
358 foreach_vnet_dev_port_tx_queue (q, port)
359 oct_txq_stop (vm, q);
363 oct_port_cfg_change_precheck (vlib_main_t *vm, vnet_dev_port_t *port,
364 vnet_dev_port_cfg_change_req_t *req)
366 vnet_dev_rv_t rv = VNET_DEV_OK;
370 case VNET_DEV_PORT_CFG_MAX_RX_FRAME_SIZE:
372 rv = VNET_DEV_ERR_PORT_STARTED;
375 case VNET_DEV_PORT_CFG_PROMISC_MODE:
376 case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
377 case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
378 case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
382 rv = VNET_DEV_ERR_NOT_SUPPORTED;
389 oct_port_cfg_change (vlib_main_t *vm, vnet_dev_port_t *port,
390 vnet_dev_port_cfg_change_req_t *req)
392 vnet_dev_rv_t rv = VNET_DEV_OK;
396 case VNET_DEV_PORT_CFG_PROMISC_MODE:
401 case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
404 case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
407 case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
410 case VNET_DEV_PORT_CFG_MAX_RX_FRAME_SIZE:
414 return VNET_DEV_ERR_NOT_SUPPORTED;