Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2024-2026 NXP
3 : : */
4 : :
5 : : #include <stdbool.h>
6 : : #include <rte_kvargs.h>
7 : : #include <rte_random.h>
8 : : #include <dpaax_iova_table.h>
9 : :
10 : : #include "base/enetc4_hw.h"
11 : : #include "enetc_logs.h"
12 : : #include "enetc.h"
13 : :
14 : : /*
15 : : * Per-ring Tx/Rx BDR registers dumped by .get_reg (shared by PF and VF).
16 : : * The array sizes here must match the extern declarations in enetc.h, which
17 : : * carry explicit dimensions so RTE_DIM() works at the use sites in enetc4_vf.c
18 : : * (a separate translation unit). The explicit dimensions below turn any drift
19 : : * between the initializer and the declared size into a compile error instead
20 : : * of a silent mismatch.
21 : : */
22 : : const uint32_t enetc4_txbdr_regs[6] = {
23 : : ENETC_TBMR, ENETC_TBSR, ENETC_TBBAR0, ENETC_TBBAR1,
24 : : ENETC_TBCIR, ENETC_TBLENR,
25 : : };
26 : :
27 : : const uint32_t enetc4_rxbdr_regs[8] = {
28 : : ENETC_RBMR, ENETC_RBSR, ENETC_RBBSR, ENETC_RBCIR,
29 : : ENETC_RBBAR0, ENETC_RBBAR1, ENETC_RBPIR, ENETC_RBLENR,
30 : : };
31 : :
32 : : /* Supported Rx offloads */
33 : : static uint64_t dev_rx_offloads_sup =
34 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
35 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
36 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
37 : : RTE_ETH_RX_OFFLOAD_SCATTER |
38 : : RTE_ETH_RX_OFFLOAD_KEEP_CRC |
39 : : RTE_ETH_RX_OFFLOAD_TCP_LRO;
40 : :
41 : : /* Supported Tx offloads */
42 : : static uint64_t dev_tx_offloads_sup =
43 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
44 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
45 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
46 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
47 : : RTE_ETH_TX_OFFLOAD_TCP_TSO |
48 : : RTE_ETH_TX_OFFLOAD_UDP_TSO;
49 : :
50 : : #define ENETC4_NC_MEMORY "nc"
51 : :
52 : : static int
53 : 0 : parse_txq_prior(const char *key __rte_unused, const char *value, void *opaque)
54 : : {
55 : : struct rte_eth_dev *dev = (struct rte_eth_dev *)opaque;
56 : : struct enetc_eth_hw *hw =
57 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
58 : : char *input_str;
59 : 0 : char *saveptr = NULL;
60 : : char *str;
61 : : uint32_t i = 0;
62 : :
63 : 0 : input_str = strdup(value);
64 [ # # ]: 0 : if (!input_str)
65 : : return -ENOMEM;
66 : :
67 : 0 : free(hw->txq_prior);
68 : 0 : hw->txq_prior = calloc(hw->max_tx_queues, sizeof(uint32_t));
69 [ # # ]: 0 : if (!hw->txq_prior) {
70 : 0 : free(input_str);
71 : 0 : return -ENOMEM;
72 : : }
73 : :
74 : 0 : str = strtok_r(input_str, "|", &saveptr);
75 [ # # # # ]: 0 : while (str != NULL && i < hw->max_tx_queues) {
76 : 0 : char *endptr = NULL;
77 : : unsigned long prio;
78 : :
79 : 0 : errno = 0;
80 : 0 : prio = strtoul(str, &endptr, 10);
81 : : /*
82 : : * strtoul() accepts a leading '-' and wraps it, so reject it
83 : : * explicitly. Priority must fit in ENETC_TBMR[PRIO] (0..7).
84 : : */
85 [ # # # # : 0 : if (errno != 0 || endptr == str || *endptr != '\0' ||
# # ]
86 [ # # # # ]: 0 : str[0] == '-' || prio > ENETC_TBMR_PRIO_MASK) {
87 : 0 : ENETC_PMD_ERR("Invalid Tx priority value '%s' (expected 0..%u)",
88 : : str, ENETC_TBMR_PRIO_MASK);
89 : 0 : free(hw->txq_prior);
90 : 0 : hw->txq_prior = NULL;
91 : 0 : free(input_str);
92 : 0 : return -EINVAL;
93 : : }
94 : 0 : hw->txq_prior[i++] = (uint32_t)prio;
95 : 0 : str = strtok_r(NULL, "|", &saveptr);
96 : : }
97 : :
98 : 0 : free(input_str);
99 : 0 : return 0;
100 : : }
101 : :
102 : : /* Parse enetc4_txq_wrr="w0|w1|..." devarg; weight 1..8 per ring. */
103 : 0 : static int parse_txq_wrr(const char *key __rte_unused, const char *value,
104 : : void *opaque)
105 : : {
106 : : struct rte_eth_dev *dev = (struct rte_eth_dev *)opaque;
107 : : struct enetc_eth_hw *hw =
108 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
109 : : char *input_str;
110 : 0 : char *saveptr = NULL;
111 : : char *str;
112 : : uint32_t i = 0;
113 : :
114 : 0 : input_str = strdup(value);
115 [ # # ]: 0 : if (!input_str)
116 : : return -ENOMEM;
117 : :
118 : 0 : free(hw->txq_wrr);
119 : 0 : hw->txq_wrr = calloc(hw->max_tx_queues, sizeof(uint32_t));
120 [ # # ]: 0 : if (!hw->txq_wrr) {
121 : 0 : free(input_str);
122 : 0 : return -ENOMEM;
123 : : }
124 : :
125 : 0 : str = strtok_r(input_str, "|", &saveptr);
126 [ # # # # ]: 0 : while (str != NULL && i < hw->max_tx_queues) {
127 : 0 : char *endptr = NULL;
128 : : unsigned long w;
129 : :
130 : 0 : errno = 0;
131 : 0 : w = strtoul(str, &endptr, 10);
132 : : /*
133 : : * strtoul() accepts a leading '-' and wraps it, so reject it
134 : : * explicitly. WRR weight is limited to 1..8 (ENETC_TBMR_WRR).
135 : : */
136 [ # # # # : 0 : if (errno != 0 || endptr == str || *endptr != '\0' ||
# # ]
137 [ # # # # ]: 0 : str[0] == '-' || w < 1 || w > 8) {
138 : 0 : ENETC_PMD_ERR("Invalid Tx WRR weight value '%s' (expected 1..8)",
139 : : str);
140 : 0 : free(hw->txq_wrr);
141 : 0 : hw->txq_wrr = NULL;
142 : 0 : free(input_str);
143 : 0 : return -EINVAL;
144 : : }
145 : 0 : hw->txq_wrr[i++] = ENETC_TBMR_WRR(w);
146 : 0 : str = strtok_r(NULL, "|", &saveptr);
147 : : }
148 : :
149 : 0 : free(input_str);
150 : 0 : return 0;
151 : : }
152 : :
153 : : static int
154 : 0 : parse_nc(const char *key __rte_unused, const char *value, void *extra_args)
155 : : {
156 : : struct rte_eth_dev *dev = extra_args;
157 : : struct enetc_eth_hw *hw =
158 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
159 : :
160 [ # # # # ]: 0 : if (value && atoi(value) == 1)
161 : 0 : hw->nc_mode = 1;
162 : :
163 : 0 : return 0;
164 : : }
165 : :
166 : : static int
167 : 0 : enetc4_get_devargs(struct rte_eth_dev *dev, const char *key)
168 : : {
169 : 0 : struct rte_devargs *devargs = dev->device->devargs;
170 : : struct rte_kvargs *kvlist;
171 : :
172 [ # # ]: 0 : if (!devargs)
173 : : return 0;
174 : :
175 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
176 [ # # ]: 0 : if (!kvlist)
177 : : return 0;
178 : :
179 [ # # ]: 0 : if (!rte_kvargs_count(kvlist, key)) {
180 : 0 : rte_kvargs_free(kvlist);
181 : 0 : return 0;
182 : : }
183 : :
184 [ # # ]: 0 : if (!strcmp(key, ENETC4_TXQ_PRIORITIES)) {
185 [ # # ]: 0 : if (rte_kvargs_process(kvlist, key,
186 : : parse_txq_prior, (void *)dev) < 0) {
187 : 0 : rte_kvargs_free(kvlist);
188 : 0 : return 0;
189 : : }
190 : : }
191 [ # # ]: 0 : if (!strcmp(key, ENETC4_TXQ_WRR)) {
192 [ # # ]: 0 : if (rte_kvargs_process(kvlist, key,
193 : : parse_txq_wrr, (void *)dev) < 0) {
194 : 0 : rte_kvargs_free(kvlist);
195 : 0 : return 0;
196 : : }
197 : : }
198 [ # # ]: 0 : if (!strcmp(key, ENETC4_NC_MEMORY)) {
199 [ # # ]: 0 : if (rte_kvargs_process(kvlist, key,
200 : : parse_nc, (void *)dev) < 0) {
201 : 0 : rte_kvargs_free(kvlist);
202 : 0 : return 0;
203 : : }
204 : : }
205 : :
206 : 0 : rte_kvargs_free(kvlist);
207 : 0 : return 0;
208 : : }
209 : :
210 : : static int
211 : 0 : enetc4_dev_start(struct rte_eth_dev *dev)
212 : : {
213 : : struct enetc_eth_hw *hw =
214 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
215 : : struct enetc_hw *enetc_hw = &hw->hw;
216 : : struct enetc_bdr *txq, *rxq;
217 : : uint32_t val;
218 : : int i, ret;
219 : :
220 : 0 : PMD_INIT_FUNC_TRACE();
221 : :
222 : : /* Start TX queues that are not deferred */
223 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
224 : 0 : txq = dev->data->tx_queues[i];
225 [ # # # # ]: 0 : if (txq && !txq->tx_deferred_start) {
226 : 0 : ret = enetc4_tx_queue_start(dev, i);
227 [ # # ]: 0 : if (ret < 0)
228 : 0 : return ret;
229 : : }
230 : : }
231 : :
232 : : /* Start RX queues that are not deferred */
233 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
234 : 0 : rxq = dev->data->rx_queues[i];
235 [ # # # # ]: 0 : if (rxq && !rxq->rx_deferred_start) {
236 : 0 : ret = enetc4_rx_queue_start(dev, i);
237 [ # # ]: 0 : if (ret < 0)
238 : 0 : return ret;
239 : : }
240 : : }
241 : :
242 : 0 : val = enetc4_port_rd(enetc_hw, ENETC4_PM_CMD_CFG(0));
243 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PM_CMD_CFG(0),
244 : : val | PM_CMD_CFG_TX_EN | PM_CMD_CFG_RX_EN);
245 : :
246 : 0 : val = enetc4_port_rd(enetc_hw, ENETC4_PM_CMD_CFG(1));
247 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PM_CMD_CFG(1),
248 : : val | PM_CMD_CFG_TX_EN | PM_CMD_CFG_RX_EN);
249 : :
250 : : /* Enable port */
251 : 0 : val = enetc4_port_rd(enetc_hw, ENETC4_PMR);
252 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PMR, val | ENETC4_PMR_EN);
253 : :
254 : : /* Enable port transmit/receive */
255 : 0 : enetc4_port_wr(enetc_hw, ENETC4_POR, 0);
256 : :
257 : 0 : return 0;
258 : : }
259 : :
260 : : static int
261 : 0 : enetc4_dev_stop(struct rte_eth_dev *dev)
262 : : {
263 : : struct enetc_eth_hw *hw =
264 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
265 : : struct enetc_hw *enetc_hw = &hw->hw;
266 : : uint32_t val;
267 : :
268 : 0 : PMD_INIT_FUNC_TRACE();
269 : :
270 : : /* Disable port */
271 : 0 : val = enetc4_port_rd(enetc_hw, ENETC4_PMR);
272 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PMR, val & (~ENETC4_PMR_EN));
273 : :
274 : 0 : val = enetc4_port_rd(enetc_hw, ENETC4_PM_CMD_CFG(0));
275 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PM_CMD_CFG(0),
276 : : val & (~(PM_CMD_CFG_TX_EN | PM_CMD_CFG_RX_EN)));
277 : :
278 : 0 : val = enetc4_port_rd(enetc_hw, ENETC4_PM_CMD_CFG(1));
279 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PM_CMD_CFG(1),
280 : : val & (~(PM_CMD_CFG_TX_EN | PM_CMD_CFG_RX_EN)));
281 : :
282 : 0 : return 0;
283 : : }
284 : :
285 : : /* return 0 means link status changed, -1 means not changed */
286 : : static int
287 : 0 : enetc4_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
288 : : {
289 : : struct enetc_eth_hw *hw =
290 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
291 : : struct enetc_hw *enetc_hw = &hw->hw;
292 : : struct rte_eth_link link;
293 : : uint32_t status;
294 : :
295 : 0 : PMD_INIT_FUNC_TRACE();
296 : :
297 : : memset(&link, 0, sizeof(link));
298 : :
299 : 0 : status = enetc4_port_rd(enetc_hw, ENETC4_PM_IF_STATUS(0));
300 : :
301 [ # # ]: 0 : if (status & ENETC4_LINK_MODE)
302 : 0 : link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
303 : : else
304 : 0 : link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
305 : :
306 [ # # ]: 0 : if (status & ENETC4_LINK_STATUS)
307 : 0 : link.link_status = RTE_ETH_LINK_UP;
308 : : else
309 : 0 : link.link_status = RTE_ETH_LINK_DOWN;
310 : :
311 [ # # # ]: 0 : switch (status & ENETC4_LINK_SPEED_MASK) {
312 : 0 : case ENETC4_LINK_SPEED_1G:
313 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_1G;
314 : 0 : break;
315 : :
316 : 0 : case ENETC4_LINK_SPEED_100M:
317 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_100M;
318 : 0 : break;
319 : :
320 : 0 : default:
321 : : case ENETC4_LINK_SPEED_10M:
322 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_10M;
323 : : }
324 : :
325 : 0 : return rte_eth_linkstatus_set(dev, &link);
326 : : }
327 : :
328 : : static int
329 : 0 : enetc4_mac_init(struct enetc_eth_hw *hw, struct rte_eth_dev *eth_dev)
330 : : {
331 : : struct enetc_hw *enetc_hw = &hw->hw;
332 : : uint32_t high_mac = 0;
333 : : uint16_t low_mac = 0;
334 : : char eth_name[ENETC_ETH_NAMESIZE];
335 : :
336 : 0 : PMD_INIT_FUNC_TRACE();
337 : :
338 : : /* Enabling Station Interface */
339 : 0 : enetc4_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN);
340 : :
341 : 0 : high_mac = (uint32_t)enetc4_port_rd(enetc_hw, ENETC4_PSIPMAR0(0));
342 : 0 : low_mac = (uint16_t)enetc4_port_rd(enetc_hw, ENETC4_PSIPMAR1(0));
343 : :
344 [ # # ]: 0 : if ((high_mac | low_mac) == 0) {
345 : 0 : ENETC_PMD_NOTICE("MAC is not available for this SI, "
346 : : "set random MAC");
347 : 0 : rte_eth_random_addr(hw->mac.addr);
348 : 0 : high_mac = *(uint32_t *)hw->mac.addr;
349 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PMAR0, high_mac);
350 : 0 : low_mac = *(uint16_t *)(hw->mac.addr + 4);
351 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PMAR1, low_mac);
352 : 0 : enetc_print_ethaddr("New address: ",
353 : : (const struct rte_ether_addr *)hw->mac.addr);
354 : : }
355 : :
356 : : /* Allocate memory for storing MAC addresses */
357 : 0 : snprintf(eth_name, sizeof(eth_name), "enetc4_eth_%d", eth_dev->data->port_id);
358 : 0 : eth_dev->data->mac_addrs = rte_zmalloc(eth_name,
359 : : RTE_ETHER_ADDR_LEN, 0);
360 [ # # ]: 0 : if (!eth_dev->data->mac_addrs) {
361 : 0 : ENETC_PMD_ERR("Failed to allocate %d bytes needed to "
362 : : "store MAC addresses",
363 : : RTE_ETHER_ADDR_LEN * 1);
364 : 0 : return -ENOMEM;
365 : : }
366 : :
367 : : /* Copy the permanent MAC address */
368 : : rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr,
369 : : ð_dev->data->mac_addrs[0]);
370 : :
371 : 0 : return 0;
372 : : }
373 : :
374 : : int
375 : 0 : enetc4_dev_infos_get(struct rte_eth_dev *dev,
376 : : struct rte_eth_dev_info *dev_info)
377 : : {
378 : : struct enetc_eth_hw *hw =
379 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
380 : :
381 : 0 : PMD_INIT_FUNC_TRACE();
382 : :
383 : 0 : dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
384 : : .nb_max = MAX_BD_COUNT,
385 : : .nb_min = MIN_BD_COUNT,
386 : : .nb_align = BD_ALIGN,
387 : : .nb_seg_max = ENETC4_MAX_SEGS,
388 : : .nb_mtu_seg_max = ENETC4_MAX_SEGS,
389 : : };
390 : 0 : dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
391 : : .nb_max = MAX_BD_COUNT,
392 : : .nb_min = MIN_BD_COUNT,
393 : : .nb_align = BD_ALIGN,
394 : : .nb_seg_max = ENETC4_MAX_SEGS,
395 : : .nb_mtu_seg_max = ENETC4_MAX_SEGS,
396 : : };
397 : 0 : dev_info->max_rx_queues = hw->max_rx_queues;
398 : 0 : dev_info->max_tx_queues = hw->max_tx_queues;
399 : 0 : dev_info->max_rx_pktlen = ENETC4_MAC_MAXFRM_SIZE;
400 : 0 : dev_info->rx_offload_capa = dev_rx_offloads_sup;
401 : 0 : dev_info->tx_offload_capa = dev_tx_offloads_sup;
402 : : /* Max RSC (LRO) coalesced frame size; matches RBaRSCR[SIZE]. */
403 : 0 : dev_info->max_lro_pkt_size = ENETC4_RSC_MAX_FRAME;
404 : 0 : dev_info->flow_type_rss_offloads = ENETC_RSS_OFFLOAD_ALL;
405 : :
406 : 0 : return 0;
407 : : }
408 : :
409 : : static int
410 : 0 : enetc4_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc)
411 : : {
412 : : int size;
413 : : uint32_t ring_desc;
414 : :
415 : : /*
416 : : * On LSO-enabled rings each frame uses an extra 16B extension BD
417 : : * (logical 32B descriptor) plus the payload BDs. Size the ring with
418 : : * twice the requested entries so the effective frame capacity is
419 : : * preserved. Non-LSO rings are sized exactly as requested.
420 : : */
421 [ # # ]: 0 : ring_desc = txr->lso_enable ? (uint32_t)nb_desc * 2 : (uint32_t)nb_desc;
422 [ # # ]: 0 : if (ring_desc > MAX_BD_COUNT) {
423 : 0 : ENETC_PMD_ERR("LSO ring_desc %u > MAX_BD_COUNT %u; "
424 : : "reduce nb_desc to <= %u with LSO enabled",
425 : : ring_desc, MAX_BD_COUNT, MAX_BD_COUNT / 2);
426 : 0 : return -EINVAL;
427 : : }
428 : :
429 : 0 : size = ring_desc * sizeof(struct enetc_swbd);
430 : : /* Zero q_swbd so buffer_addr is NULL for all uninitialized slots. */
431 : 0 : txr->q_swbd = rte_zmalloc(NULL, size, ENETC_BD_RING_ALIGN);
432 [ # # ]: 0 : if (txr->q_swbd == NULL)
433 : : return -ENOMEM;
434 : :
435 : : /* Allocate the TX BD ring: each BD is struct enetc_tx_bd (16 bytes). */
436 : 0 : size = ring_desc * sizeof(struct enetc_tx_bd);
437 : 0 : txr->bd_base = rte_zmalloc(NULL, size, ENETC_BD_RING_ALIGN);
438 [ # # ]: 0 : if (txr->bd_base == NULL) {
439 : 0 : rte_free(txr->q_swbd);
440 : 0 : txr->q_swbd = NULL;
441 : 0 : return -ENOMEM;
442 : : }
443 : 0 : txr->bd_count = ring_desc;
444 : 0 : txr->next_to_clean = 0;
445 : 0 : txr->next_to_use = 0;
446 : :
447 : 0 : return 0;
448 : : }
449 : :
450 : : static void
451 : : enetc4_free_bdr(struct enetc_bdr *rxr)
452 : : {
453 : 0 : rte_free(rxr->bd_base);
454 : 0 : rte_free(rxr->q_swbd);
455 : 0 : rxr->q_swbd = NULL;
456 : 0 : rxr->bd_base = NULL;
457 : : }
458 : :
459 : : static void
460 : 0 : enetc4_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
461 : : {
462 : 0 : int idx = tx_ring->index;
463 : : phys_addr_t bd_address;
464 : :
465 : : bd_address = (phys_addr_t)
466 : 0 : rte_mem_virt2iova((const void *)tx_ring->bd_base);
467 : 0 : enetc4_txbdr_wr(hw, idx, ENETC_TBBAR0,
468 : : lower_32_bits((uint64_t)bd_address));
469 : 0 : enetc4_txbdr_wr(hw, idx, ENETC_TBBAR1,
470 : : upper_32_bits((uint64_t)bd_address));
471 : 0 : enetc4_txbdr_wr(hw, idx, ENETC_TBLENR,
472 : : ENETC_RTBLENR_LEN(tx_ring->bd_count));
473 : :
474 : 0 : enetc4_txbdr_wr(hw, idx, ENETC_TBCIR, 0);
475 : 0 : enetc4_txbdr_wr(hw, idx, ENETC_TBCISR, 0);
476 : 0 : tx_ring->tcir = (void *)((size_t)hw->reg +
477 : : ENETC_BDR(TX, idx, ENETC_TBCIR));
478 : 0 : tx_ring->tcisr = (void *)((size_t)hw->reg +
479 : : ENETC_BDR(TX, idx, ENETC_TBCISR));
480 : 0 : }
481 : :
482 : : int
483 : 0 : enetc4_tx_queue_setup(struct rte_eth_dev *dev,
484 : : uint16_t queue_idx,
485 : : uint16_t nb_desc,
486 : : unsigned int socket_id __rte_unused,
487 : : const struct rte_eth_txconf *tx_conf)
488 : : {
489 : : int err;
490 : : uint32_t tx_data;
491 : : struct enetc_bdr *tx_ring;
492 : 0 : struct rte_eth_dev_data *data = dev->data;
493 : 0 : struct enetc_eth_adapter *priv =
494 : : ENETC_DEV_PRIVATE(data->dev_private);
495 : : uint64_t tx_offloads;
496 : :
497 : 0 : PMD_INIT_FUNC_TRACE();
498 [ # # ]: 0 : if (nb_desc > MAX_BD_COUNT)
499 : : return -1;
500 : :
501 : 0 : tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
502 [ # # ]: 0 : if (tx_ring == NULL) {
503 : 0 : ENETC_PMD_ERR("Failed to allocate TX ring memory");
504 : : err = -ENOMEM;
505 : 0 : return err;
506 : : }
507 : :
508 : 0 : tx_ring->index = queue_idx;
509 : : /*
510 : : * LSO (TCP/UDP segmentation) is a port-level offload. The Tx burst is
511 : : * a single device-level function pointer, so it must be consistent for
512 : : * all queues; likewise every ring must be sized the same way. Decide
513 : : * from the port offloads only (not the per-queue tx_conf) so that all
514 : : * queues either use the LSO burst with a doubled ring, or none do.
515 : : * The LSO burst also handles non-TSO packets, so it is safe on queues
516 : : * that never carry TSO traffic. LSO needs HW FCS insertion, so it is
517 : : * incompatible with KEEP_CRC on Rx.
518 : : */
519 : 0 : tx_offloads = data->dev_conf.txmode.offloads;
520 [ # # ]: 0 : if (tx_offloads & (RTE_ETH_TX_OFFLOAD_TCP_TSO |
521 : : RTE_ETH_TX_OFFLOAD_UDP_TSO)) {
522 [ # # ]: 0 : if (data->dev_conf.rxmode.offloads &
523 : : RTE_ETH_RX_OFFLOAD_KEEP_CRC) {
524 : 0 : ENETC_PMD_ERR("LSO (TSO) is incompatible with KEEP_CRC");
525 : 0 : rte_free(tx_ring);
526 : 0 : return -EINVAL;
527 : : }
528 : 0 : tx_ring->lso_enable = 1;
529 : 0 : dev->tx_pkt_burst = &enetc_xmit_pkts_lso;
530 : : } else {
531 : : struct enetc_eth_hw *hw =
532 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
533 [ # # ]: 0 : dev->tx_pkt_burst = hw->nc_mode ? &enetc_xmit_pkts_nc :
534 : : &enetc_xmit_pkts_cacheable;
535 : : }
536 : :
537 : 0 : err = enetc4_alloc_txbdr(tx_ring, nb_desc);
538 [ # # ]: 0 : if (err)
539 : 0 : goto fail;
540 : :
541 : 0 : tx_ring->ndev = dev;
542 : : /* reset queue */
543 : 0 : tx_data = enetc4_txbdr_rd(&priv->hw.hw, tx_ring->index, ENETC_TBMR);
544 : 0 : tx_data &= ~ENETC_TBMR_EN;
545 : 0 : enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR, tx_data);
546 : 0 : enetc4_setup_txbdr(&priv->hw.hw, tx_ring);
547 : 0 : data->tx_queues[queue_idx] = tx_ring;
548 : 0 : tx_ring->tx_deferred_start = tx_conf->tx_deferred_start;
549 [ # # ]: 0 : if (!tx_conf->tx_deferred_start) {
550 : : /* Clear scheduler bits before applying fresh devarg values. */
551 : 0 : tx_data &= ~(ENETC_TBMR_PRIO_MASK | ENETC_TBMR_WRR_MASK);
552 : 0 : tx_data |= ENETC_TBMR_EN;
553 : : /* apply TX queue priority if configured */
554 [ # # ]: 0 : if (priv->hw.txq_prior)
555 : 0 : tx_data |= priv->hw.txq_prior[tx_ring->index];
556 [ # # ]: 0 : if (priv->hw.txq_wrr)
557 : 0 : tx_data |= priv->hw.txq_wrr[tx_ring->index];
558 : : /* enable ring */
559 : 0 : enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index,
560 : : ENETC_TBMR, tx_data);
561 : 0 : dev->data->tx_queue_state[tx_ring->index] =
562 : : RTE_ETH_QUEUE_STATE_STARTED;
563 : : } else {
564 : 0 : dev->data->tx_queue_state[tx_ring->index] =
565 : : RTE_ETH_QUEUE_STATE_STOPPED;
566 : : }
567 : :
568 : : return 0;
569 : : fail:
570 : 0 : rte_free(tx_ring);
571 : :
572 : 0 : return err;
573 : : }
574 : :
575 : : void
576 : 0 : enetc4_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
577 : : {
578 : 0 : void *txq = dev->data->tx_queues[qid];
579 : : struct enetc_hw *hw;
580 : : struct enetc_swbd *tx_swbd;
581 : : int i;
582 : : uint32_t val;
583 : : struct enetc_bdr *tx_ring;
584 : : struct enetc_eth_hw *eth_hw;
585 : :
586 : 0 : PMD_INIT_FUNC_TRACE();
587 [ # # ]: 0 : if (txq == NULL)
588 : : return;
589 : :
590 : : tx_ring = (struct enetc_bdr *)txq;
591 : : eth_hw =
592 : 0 : ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private);
593 : :
594 : : /* Disable the ring */
595 : : hw = ð_hw->hw;
596 : 0 : val = enetc4_txbdr_rd(hw, tx_ring->index, ENETC_TBMR);
597 : 0 : val &= (~ENETC_TBMR_EN);
598 : 0 : enetc4_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val);
599 : :
600 : : /* clean the ring*/
601 : 0 : i = tx_ring->next_to_clean;
602 : 0 : tx_swbd = &tx_ring->q_swbd[i];
603 [ # # ]: 0 : while (tx_swbd->buffer_addr != NULL) {
604 : 0 : rte_pktmbuf_free(tx_swbd->buffer_addr);
605 : 0 : tx_swbd->buffer_addr = NULL;
606 : 0 : tx_swbd++;
607 : 0 : i++;
608 [ # # ]: 0 : if (unlikely(i == tx_ring->bd_count)) {
609 : : i = 0;
610 : 0 : tx_swbd = &tx_ring->q_swbd[i];
611 : : }
612 : : }
613 : :
614 : : enetc4_free_bdr(tx_ring);
615 : 0 : rte_free(tx_ring);
616 : : }
617 : :
618 : : static int
619 : 0 : enetc4_alloc_rxbdr(struct enetc_bdr *rxr, uint16_t nb_desc)
620 : : {
621 : : int size;
622 : : uint32_t ring_desc;
623 : :
624 : : /*
625 : : * RSC rings use 32B descriptors (RBaMR[BDS] = 1), i.e. two 16B slots
626 : : * each, so allocate 2 * nb_desc slots. Non-RSC rings use 16B slots.
627 : : */
628 [ # # ]: 0 : ring_desc = rxr->rsc_enable ? (uint32_t)nb_desc * 2 : (uint32_t)nb_desc;
629 [ # # ]: 0 : if (ring_desc > MAX_BD_COUNT) {
630 : 0 : ENETC_PMD_ERR("RSC ring_desc %u > MAX_BD_COUNT %u; "
631 : : "reduce nb_desc to <= %u with RSC enabled",
632 : : ring_desc, MAX_BD_COUNT, MAX_BD_COUNT / 2);
633 : 0 : return -EINVAL;
634 : : }
635 : :
636 : 0 : size = ring_desc * sizeof(struct enetc_swbd);
637 : : /* Zero q_swbd so buffer_addr is NULL for all uninitialized slots. */
638 : 0 : rxr->q_swbd = rte_zmalloc(NULL, size, ENETC_BD_RING_ALIGN);
639 [ # # ]: 0 : if (rxr->q_swbd == NULL)
640 : : return -ENOMEM;
641 : :
642 : : /* Allocate the RX BD ring: each BD is union enetc_rx_bd (16 bytes). */
643 : 0 : size = ring_desc * sizeof(union enetc_rx_bd);
644 : 0 : rxr->bd_base = rte_zmalloc(NULL, size, ENETC_BD_RING_ALIGN);
645 [ # # ]: 0 : if (rxr->bd_base == NULL) {
646 : 0 : rte_free(rxr->q_swbd);
647 : 0 : rxr->q_swbd = NULL;
648 : 0 : return -ENOMEM;
649 : : }
650 : 0 : rxr->bd_count = ring_desc;
651 : 0 : rxr->next_to_clean = 0;
652 : 0 : rxr->next_to_use = 0;
653 : 0 : rxr->next_to_alloc = 0;
654 : :
655 : 0 : return 0;
656 : : }
657 : :
658 : : static void
659 : 0 : enetc4_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
660 : : struct rte_mempool *mb_pool)
661 : : {
662 : 0 : int idx = rx_ring->index;
663 : : uint16_t buf_size;
664 : : phys_addr_t bd_address;
665 : :
666 : : bd_address = (phys_addr_t)
667 : 0 : rte_mem_virt2iova((const void *)rx_ring->bd_base);
668 : :
669 : 0 : enetc4_rxbdr_wr(hw, idx, ENETC_RBBAR0,
670 : : lower_32_bits((uint64_t)bd_address));
671 : 0 : enetc4_rxbdr_wr(hw, idx, ENETC_RBBAR1,
672 : : upper_32_bits((uint64_t)bd_address));
673 : : /*
674 : : * RBaLENR counts HW descriptors. With RSC (BDS = 1) a descriptor is
675 : : * 32B (two 16B slots), so program bd_count / 2; otherwise bd_count.
676 : : */
677 [ # # ]: 0 : enetc4_rxbdr_wr(hw, idx, ENETC_RBLENR,
678 : : ENETC_RTBLENR_LEN(rx_ring->rsc_enable ?
679 : : rx_ring->bd_count / 2 : rx_ring->bd_count));
680 : :
681 : 0 : rx_ring->mb_pool = mb_pool;
682 : 0 : rx_ring->rcir = (void *)((size_t)hw->reg +
683 : 0 : ENETC_BDR(RX, idx, ENETC_RBCIR));
684 : : /* RSC rings clear their Rx interrupt-detect event via SIRXIDR (see
685 : : * enetc_clean_rx_ring_rsc); cache the register address here.
686 : : */
687 [ # # ]: 0 : if (rx_ring->rsc_enable)
688 : 0 : rx_ring->rbidr = (void *)((size_t)hw->reg + ENETC_SIRXIDR);
689 : :
690 : : /* RSC rings use the 2-slot-stride refill for 32B descriptors. */
691 [ # # ]: 0 : if (rx_ring->rsc_enable)
692 : 0 : enetc_refill_rx_ring_rsc(rx_ring,
693 : : ENETC_BD_ALIGN_DOWN(enetc_bd_unused(rx_ring)));
694 : : else
695 : 0 : enetc_refill_rx_ring(rx_ring,
696 : : ENETC_BD_ALIGN_DOWN(enetc_bd_unused(rx_ring)));
697 [ # # ]: 0 : buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) -
698 : : RTE_PKTMBUF_HEADROOM);
699 : 0 : enetc4_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size);
700 : 0 : enetc4_rxbdr_wr(hw, idx, ENETC_RBPIR, 0);
701 : 0 : }
702 : :
703 : : int
704 : 0 : enetc4_rx_queue_setup(struct rte_eth_dev *dev,
705 : : uint16_t rx_queue_id,
706 : : uint16_t nb_rx_desc,
707 : : unsigned int socket_id __rte_unused,
708 : : const struct rte_eth_rxconf *rx_conf,
709 : : struct rte_mempool *mb_pool)
710 : : {
711 : : int err = 0;
712 : : uint32_t rx_enable;
713 : : struct enetc_bdr *rx_ring;
714 : 0 : struct rte_eth_dev_data *data = dev->data;
715 : 0 : struct enetc_eth_adapter *adapter =
716 : : ENETC_DEV_PRIVATE(data->dev_private);
717 : 0 : uint64_t rx_offloads = data->dev_conf.rxmode.offloads;
718 : : uint32_t rsc_size;
719 : : bool keep_crc;
720 : : bool rsc_enable;
721 : :
722 : 0 : PMD_INIT_FUNC_TRACE();
723 [ # # ]: 0 : if (nb_rx_desc > MAX_BD_COUNT)
724 : : return -1;
725 : :
726 : 0 : rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
727 [ # # ]: 0 : if (rx_ring == NULL) {
728 : 0 : ENETC_PMD_ERR("Failed to allocate RX ring memory");
729 : : err = -ENOMEM;
730 : 0 : return err;
731 : : }
732 : :
733 : 0 : rx_ring->index = rx_queue_id;
734 : 0 : keep_crc = !!(rx_offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC);
735 [ # # ]: 0 : rx_ring->crc_len = (uint8_t)(keep_crc ? RTE_ETHER_CRC_LEN : 0);
736 : :
737 : : /*
738 : : * RSC (LRO) is a port-level offload: the Rx burst is a single device
739 : : * function pointer, so decide from port offloads (not per-queue
740 : : * rx_conf) to keep all rings consistent. RSC needs HW FCS stripping
741 : : * (RBaMR[CRC] = 0), so it is incompatible with KEEP_CRC.
742 : : */
743 : 0 : rsc_enable = !!(rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO);
744 [ # # ]: 0 : if (rsc_enable) {
745 [ # # ]: 0 : if (keep_crc) {
746 : 0 : ENETC_PMD_ERR("RSC (LRO) is incompatible with KEEP_CRC");
747 : 0 : rte_free(rx_ring);
748 : 0 : return -EINVAL;
749 : : }
750 [ # # ]: 0 : if (adapter->hw.nc_mode) {
751 : 0 : ENETC_PMD_ERR("RSC (LRO) is incompatible with nc=1 (non-cacheable mode)");
752 : 0 : rte_free(rx_ring);
753 : 0 : return -EINVAL;
754 : : }
755 [ # # ]: 0 : if (!(rx_offloads & RTE_ETH_RX_OFFLOAD_SCATTER)) {
756 : 0 : ENETC_PMD_ERR("RSC (LRO) requires RTE_ETH_RX_OFFLOAD_SCATTER");
757 : 0 : rte_free(rx_ring);
758 : 0 : return -EINVAL;
759 : : }
760 : 0 : rx_ring->rsc_enable = 1;
761 : : }
762 : :
763 : 0 : data->lro = rsc_enable;
764 : 0 : data->scattered_rx = rsc_enable;
765 : :
766 : 0 : err = enetc4_alloc_rxbdr(rx_ring, nb_rx_desc);
767 [ # # ]: 0 : if (err)
768 : 0 : goto fail;
769 : :
770 [ # # ]: 0 : if (rsc_enable) {
771 : 0 : dev->rx_pkt_burst = &enetc_recv_pkts_rsc;
772 : : } else {
773 : 0 : dev->rx_pkt_burst = adapter->hw.nc_mode ?
774 [ # # ]: 0 : &enetc_recv_pkts_nc :
775 : : &enetc_recv_pkts_cacheable;
776 : : }
777 : :
778 : 0 : rx_ring->ndev = dev;
779 : : /* reset queue */
780 : 0 : rx_enable = enetc4_rxbdr_rd(&adapter->hw.hw, rx_ring->index, ENETC_RBMR);
781 : 0 : rx_enable &= ~ENETC_RBMR_EN;
782 : 0 : enetc4_rxbdr_wr(&adapter->hw.hw, rx_ring->index, ENETC_RBMR, rx_enable);
783 : 0 : enetc4_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool);
784 : 0 : data->rx_queues[rx_queue_id] = rx_ring;
785 : 0 : rx_ring->rx_deferred_start = rx_conf->rx_deferred_start;
786 : :
787 [ # # ]: 0 : if (keep_crc)
788 : 0 : rx_enable |= ENETC4_RBMR_CRC;
789 : : else
790 : 0 : rx_enable &= ~ENETC4_RBMR_CRC;
791 : :
792 [ # # ]: 0 : if (rsc_enable) {
793 : : /*
794 : : * RSC preconditions (all must hold or RBaRSCR[EN] is ignored):
795 : : * BDS = 1 (32B descriptors), CRC = 0 (FCS stripped, enforced
796 : : * above), ICEN = 1 (its timer doubles as the RSC flush timer),
797 : : * and RBaRSCR[EN] with CT for timestamped segments. SIZE caps
798 : : * the coalesced frame; honor rxmode.max_lro_pkt_size clamped to
799 : : * the HW max.
800 : : */
801 : 0 : rx_enable |= ENETC4_RBMR_BDS;
802 : :
803 : : /*
804 : : * Commit RBMR[BDS] to HW now (ring still disabled, EN clear)
805 : : * so the 32B descriptor mode is active before RBaRSCR[EN] is
806 : : * set. BDS = 1 is a hard RSC precondition: if RBaRSCR[EN] is
807 : : * written while BDS is still 0 in HW, RSC may be silently
808 : : * ignored. The ring-enable step below writes RBMR again with
809 : : * EN added.
810 : : */
811 : 0 : enetc4_rxbdr_wr(&adapter->hw.hw, rx_ring->index, ENETC_RBMR,
812 : : rx_enable);
813 : :
814 : 0 : rsc_size = data->dev_conf.rxmode.max_lro_pkt_size;
815 : : if (rsc_size > ENETC4_RSC_MAX_FRAME)
816 : : rsc_size = ENETC4_RSC_MAX_FRAME;
817 : :
818 : : /*
819 : : * Program ICTT FIRST (with ICEN = 0) then enable ICEN, as the
820 : : * RM requires. ICTT is the RSC coalesce-hold window; a zero
821 : : * value disables the timer and forces HW to flush every frame
822 : : * (no coalescing), so use a non-zero default.
823 : : */
824 : 0 : enetc4_rxbdr_wr(&adapter->hw.hw, rx_ring->index,
825 : : ENETC4_RBICR1, ENETC4_RSC_DEF_ICTT);
826 : 0 : enetc4_rxbdr_wr(&adapter->hw.hw, rx_ring->index,
827 : : ENETC4_RBICR0, ENETC4_RBICR0_ICEN |
828 : : ENETC4_RBICR0_ICPT(ENETC4_RSC_DEF_ICPT));
829 : 0 : enetc4_rxbdr_wr(&adapter->hw.hw, rx_ring->index,
830 : : ENETC4_RBRSCR, ENETC4_RBRSCR_EN |
831 : : ENETC4_RBRSCR_CT |
832 : : ENETC4_RBRSCR_SIZE(rsc_size));
833 : : }
834 : :
835 [ # # ]: 0 : if (!rx_conf->rx_deferred_start) {
836 : : /* Enable ring; apply congestion mode if TX PAUSE is already active. */
837 : : rx_enable |= ENETC_RBMR_EN;
838 : : /* vsi_lock serializes RBMR RMW with enetc4_vf_set_congestion_mode().
839 : : * Only VF has that interrupt-driven path; PF skips the lock.
840 : : */
841 [ # # ]: 0 : if (adapter->hw.device_id == ENETC4_DEV_ID_VF)
842 : 0 : pthread_mutex_lock(&adapter->hw.vsi_lock);
843 [ # # ]: 0 : if (rte_atomic_load_explicit(&adapter->hw.tx_pause_active,
844 : : rte_memory_order_relaxed))
845 : 0 : rx_enable |= ENETC_RBMR_CM;
846 : : else
847 : 0 : rx_enable &= ~(uint32_t)ENETC_RBMR_CM;
848 : 0 : enetc4_rxbdr_wr(&adapter->hw.hw, rx_ring->index, ENETC_RBMR,
849 : : rx_enable);
850 [ # # ]: 0 : if (adapter->hw.device_id == ENETC4_DEV_ID_VF)
851 : 0 : pthread_mutex_unlock(&adapter->hw.vsi_lock);
852 : 0 : dev->data->rx_queue_state[rx_ring->index] =
853 : : RTE_ETH_QUEUE_STATE_STARTED;
854 : : } else {
855 : 0 : enetc4_rxbdr_wr(&adapter->hw.hw, rx_ring->index, ENETC_RBMR,
856 : : rx_enable);
857 : 0 : dev->data->rx_queue_state[rx_ring->index] =
858 : : RTE_ETH_QUEUE_STATE_STOPPED;
859 : : }
860 : :
861 : : return 0;
862 : : fail:
863 : 0 : rte_free(rx_ring);
864 : :
865 : 0 : return err;
866 : : }
867 : :
868 : : void
869 : 0 : enetc4_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
870 : : {
871 : 0 : void *rxq = dev->data->rx_queues[qid];
872 : : struct enetc_swbd *q_swbd;
873 : : struct enetc_hw *hw;
874 : : uint32_t val;
875 : : int i;
876 : : struct enetc_bdr *rx_ring;
877 : : struct enetc_eth_hw *eth_hw;
878 : :
879 : 0 : PMD_INIT_FUNC_TRACE();
880 [ # # ]: 0 : if (rxq == NULL)
881 : : return;
882 : :
883 : : rx_ring = (struct enetc_bdr *)rxq;
884 : : eth_hw =
885 : 0 : ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private);
886 : :
887 : : /* Disable the ring */
888 : : hw = ð_hw->hw;
889 : 0 : val = enetc4_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR);
890 : 0 : val &= (~ENETC_RBMR_EN);
891 : 0 : enetc4_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val);
892 : :
893 : : /* Clean the ring */
894 : 0 : i = rx_ring->next_to_clean;
895 : 0 : q_swbd = &rx_ring->q_swbd[i];
896 [ # # ]: 0 : while (i != rx_ring->next_to_use) {
897 : 0 : rte_pktmbuf_free(q_swbd->buffer_addr);
898 : 0 : q_swbd->buffer_addr = NULL;
899 : 0 : q_swbd++;
900 : 0 : i++;
901 [ # # ]: 0 : if (unlikely(i == rx_ring->bd_count)) {
902 : : i = 0;
903 : 0 : q_swbd = &rx_ring->q_swbd[i];
904 : : }
905 : : }
906 : :
907 : : enetc4_free_bdr(rx_ring);
908 : 0 : rte_free(rx_ring);
909 : : }
910 : :
911 : : static
912 : 0 : int enetc4_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats,
913 : : struct eth_queue_stats *qstats __rte_unused)
914 : : {
915 : : struct enetc_eth_hw *hw =
916 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
917 : : struct enetc_hw *enetc_hw = &hw->hw;
918 : :
919 : : /*
920 : : * Total received packets, bad + good, if we want to get counters
921 : : * of only good received packets then use ENETC4_PM_RFRM,
922 : : * ENETC4_PM_TFRM registers.
923 : : */
924 : 0 : stats->ipackets = enetc4_port_rd(enetc_hw, ENETC4_PM_RPKT(0));
925 : 0 : stats->opackets = enetc4_port_rd(enetc_hw, ENETC4_PM_TPKT(0));
926 : 0 : stats->ibytes = enetc4_port_rd(enetc_hw, ENETC4_PM_REOCT(0));
927 : 0 : stats->obytes = enetc4_port_rd(enetc_hw, ENETC4_PM_TEOCT(0));
928 : : /*
929 : : * Dropped + Truncated packets, use ENETC4_PM_RDRNTP(0) for without
930 : : * truncated packets
931 : : */
932 : 0 : stats->imissed = enetc4_port_rd(enetc_hw, ENETC4_PM_RDRP(0));
933 : 0 : stats->ierrors = enetc4_port_rd(enetc_hw, ENETC4_PM_RERR(0));
934 : 0 : stats->oerrors = enetc4_port_rd(enetc_hw, ENETC4_PM_TERR(0));
935 : :
936 : 0 : return 0;
937 : : }
938 : :
939 : : static int
940 : 0 : enetc4_stats_reset(struct rte_eth_dev *dev)
941 : : {
942 : : struct enetc_eth_hw *hw =
943 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
944 : : struct enetc_hw *enetc_hw = &hw->hw;
945 : :
946 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PM0_STAT_CONFIG, ENETC4_CLEAR_STATS);
947 : :
948 : 0 : return 0;
949 : : }
950 : :
951 : : static void
952 : : enetc4_rss_configure(struct enetc_hw *hw, int enable)
953 : : {
954 : : uint32_t reg;
955 : :
956 : 0 : reg = enetc4_rd(hw, ENETC_SIMR);
957 : 0 : reg &= ~ENETC_SIMR_RSSE;
958 : 0 : reg |= (enable) ? ENETC_SIMR_RSSE : 0;
959 : 0 : enetc4_wr(hw, ENETC_SIMR, reg);
960 : 0 : }
961 : :
962 : : int
963 : 0 : enetc4_dev_close(struct rte_eth_dev *dev)
964 : : {
965 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
966 : : struct enetc_hw *enetc_hw = &hw->hw;
967 : : uint16_t i;
968 : : int ret;
969 : :
970 : 0 : PMD_INIT_FUNC_TRACE();
971 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
972 : : return 0;
973 : :
974 [ # # ]: 0 : if (hw->device_id == ENETC4_DEV_ID_VF) {
975 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.lsc != 0 ||
976 : : dev->data->dev_conf.intr_conf.rxq != 0)
977 : 0 : enetc4_vf_dev_intr(dev, false);
978 : 0 : ret = enetc4_vf_dev_stop(dev);
979 : 0 : pthread_mutex_destroy(&hw->vsi_lock);
980 : : } else {
981 : 0 : ret = enetc4_dev_stop(dev);
982 : : }
983 : :
984 [ # # ]: 0 : if (dev->data->nb_rx_queues > 1) {
985 : : /* Disable RSS */
986 : : enetc4_rss_configure(enetc_hw, false);
987 : : /* Free CBDR */
988 : 0 : enetc_free_cbdr(&hw->cbdr);
989 : : }
990 : :
991 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
992 : 0 : enetc4_rx_queue_release(dev, i);
993 : 0 : dev->data->rx_queues[i] = NULL;
994 : : }
995 : 0 : dev->data->nb_rx_queues = 0;
996 : :
997 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
998 : 0 : enetc4_tx_queue_release(dev, i);
999 : 0 : dev->data->tx_queues[i] = NULL;
1000 : : }
1001 : 0 : dev->data->nb_tx_queues = 0;
1002 : 0 : free(hw->txq_prior);
1003 : 0 : hw->txq_prior = NULL;
1004 : 0 : free(hw->txq_wrr);
1005 : 0 : hw->txq_wrr = NULL;
1006 [ # # ]: 0 : if (rte_eal_iova_mode() == RTE_IOVA_PA)
1007 : 0 : dpaax_iova_table_depopulate();
1008 : :
1009 : : return ret;
1010 : : }
1011 : :
1012 : : /* Configure SI-based VLAN insertion (Tx) and removal (Rx) for the PF. */
1013 : : static int
1014 : 0 : enetc4_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
1015 : : {
1016 : : struct enetc_eth_hw *hw =
1017 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1018 : : struct enetc_hw *enetc_hw = &hw->hw;
1019 : : uint32_t psivlanr, psicfgr0;
1020 : :
1021 : 0 : PMD_INIT_FUNC_TRACE();
1022 : :
1023 [ # # ]: 0 : if (vlan_id > RTE_ETHER_MAX_VLAN_ID) {
1024 : 0 : ENETC_PMD_ERR("Invalid vlan_id = %u > %d", vlan_id,
1025 : : RTE_ETHER_MAX_VLAN_ID);
1026 : 0 : return -EINVAL;
1027 : : }
1028 : :
1029 : 0 : psicfgr0 = enetc4_port_rd(enetc_hw, ENETC4_PSICFGR0(0));
1030 : :
1031 [ # # ]: 0 : if (on) {
1032 : : /* Build the VLAN register: enable bit + VID (PCP/DEI left 0) */
1033 : 0 : psivlanr = (uint32_t)ENETC4_PSIVLANR_E |
1034 : 0 : ENETC4_PSIVLANR_VID(vlan_id);
1035 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PSIVLANR(0), psivlanr);
1036 : :
1037 : : /* Allow C-VLAN TPID, enable Tx insertion and Rx removal */
1038 : 0 : psicfgr0 |= ENETC4_PSICFGR0_SIVC_CVLAN |
1039 : : ENETC4_PSICFGR0_SIVIE |
1040 : : ENETC4_PSICFGR0_VTE;
1041 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PSICFGR0(0), psicfgr0);
1042 : : } else {
1043 : : /* Clear Tx insertion, Rx removal and C-VLAN allow bits */
1044 : 0 : psicfgr0 &= ~(ENETC4_PSICFGR0_SIVC_CVLAN |
1045 : : ENETC4_PSICFGR0_SIVIE |
1046 : : ENETC4_PSICFGR0_VTE);
1047 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PSICFGR0(0), psicfgr0);
1048 : :
1049 : : /* Clear the VLAN register (disable SI VLAN processing) */
1050 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PSIVLANR(0), 0);
1051 : : }
1052 : :
1053 : : return 0;
1054 : : }
1055 : :
1056 : : static int
1057 : 0 : enetc4_promiscuous_enable(struct rte_eth_dev *dev)
1058 : : {
1059 : : struct enetc_eth_hw *hw =
1060 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1061 : : struct enetc_hw *enetc_hw = &hw->hw;
1062 : : uint32_t psipmr = 0;
1063 : :
1064 : 0 : psipmr = enetc4_port_rd(enetc_hw, ENETC4_PSIPMMR);
1065 : :
1066 : : /* Setting to enable promiscuous mode for all ports*/
1067 : 0 : psipmr |= PSIPMMR_SI_MAC_UP | PSIPMMR_SI_MAC_MP;
1068 : :
1069 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PSIPMMR, psipmr);
1070 : :
1071 : 0 : return 0;
1072 : : }
1073 : :
1074 : : static int
1075 : 0 : enetc4_promiscuous_disable(struct rte_eth_dev *dev)
1076 : : {
1077 : : struct enetc_eth_hw *hw =
1078 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1079 : : struct enetc_hw *enetc_hw = &hw->hw;
1080 : : uint32_t psipmr = 0;
1081 : :
1082 : : /* Setting to disable promiscuous mode for SI0*/
1083 : 0 : psipmr = enetc4_port_rd(enetc_hw, ENETC4_PSIPMMR);
1084 : 0 : psipmr &= (~PSIPMMR_SI_MAC_UP);
1085 : :
1086 [ # # ]: 0 : if (dev->data->all_multicast == 0)
1087 : 0 : psipmr &= (~PSIPMMR_SI_MAC_MP);
1088 : :
1089 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PSIPMMR, psipmr);
1090 : :
1091 : 0 : return 0;
1092 : : }
1093 : :
1094 : : int
1095 : 0 : enetc4_dev_configure(struct rte_eth_dev *dev)
1096 : : {
1097 : : struct enetc_eth_hw *hw =
1098 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1099 : : struct rte_eth_conf *eth_conf = &dev->data->dev_conf;
1100 : 0 : uint64_t rx_offloads = eth_conf->rxmode.offloads;
1101 : 0 : uint64_t tx_offloads = eth_conf->txmode.offloads;
1102 : : uint32_t checksum = L3_CKSUM | L4_CKSUM;
1103 : 0 : struct enetc_hw *enetc_hw = &hw->hw;
1104 : : uint32_t max_len;
1105 : : uint32_t val, num_rss;
1106 : : uint32_t ret = 0, i;
1107 : : uint32_t *rss_table;
1108 : :
1109 : 0 : PMD_INIT_FUNC_TRACE();
1110 : :
1111 : : /* Port-level register writes are PF-only; skip for VF devices */
1112 [ # # ]: 0 : if (hw->device_id != ENETC4_DEV_ID_VF) {
1113 : 0 : max_len = dev->data->dev_conf.rxmode.mtu + RTE_ETHER_HDR_LEN +
1114 : : RTE_ETHER_CRC_LEN;
1115 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PM_MAXFRM(0),
1116 : : ENETC_SET_MAXFRM(max_len));
1117 : :
1118 : : val = ENETC4_MAC_MAXFRM_SIZE | SDU_TYPE_MPDU;
1119 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PTCTMSDUR(0),
1120 : : val | SDU_TYPE_MPDU);
1121 : : }
1122 : :
1123 : : /* Rx offloads which are enabled by default */
1124 [ # # ]: 0 : if (dev_rx_offloads_sup & ~rx_offloads) {
1125 : 0 : ENETC_PMD_INFO("Some of rx offloads enabled by default"
1126 : : " - requested 0x%" PRIx64 " fixed are 0x%" PRIx64,
1127 : : rx_offloads, dev_rx_offloads_sup);
1128 : : }
1129 : :
1130 : : /* Tx offloads which are enabled by default */
1131 [ # # ]: 0 : if (dev_tx_offloads_sup & ~tx_offloads) {
1132 : 0 : ENETC_PMD_INFO("Some of tx offloads enabled by default"
1133 : : " - requested 0x%" PRIx64 " fixed are 0x%" PRIx64,
1134 : : tx_offloads, dev_tx_offloads_sup);
1135 : : }
1136 : :
1137 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM)
1138 : : checksum &= ~L3_CKSUM;
1139 : :
1140 [ # # ]: 0 : if (rx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM))
1141 : 0 : checksum &= ~L4_CKSUM;
1142 : :
1143 [ # # ]: 0 : if (hw->device_id != ENETC4_DEV_ID_VF)
1144 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PARCSCR, checksum);
1145 : :
1146 [ # # ]: 0 : if (hw->device_id == ENETC4_DEV_ID_VF) {
1147 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.lsc != 0 ||
1148 : : dev->data->dev_conf.intr_conf.rxq != 0) {
1149 : 0 : ret = enetc4_vf_dev_intr(dev, true);
1150 [ # # ]: 0 : if (ret)
1151 : 0 : ENETC_PMD_WARN("Failed to setup VF interrupts: %d", ret);
1152 : : }
1153 : : }
1154 : :
1155 : : /* Disable and reset RX and TX rings */
1156 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
1157 : 0 : enetc4_rxbdr_wr(enetc_hw, i, ENETC_RBMR, ENETC_BMR_RESET);
1158 : :
1159 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
1160 : 0 : enetc4_txbdr_wr(enetc_hw, i, ENETC_TBMR, ENETC_BMR_RESET);
1161 : :
1162 : 0 : hw->nc_mode = 0;
1163 : 0 : enetc4_get_devargs(dev, ENETC4_TXQ_PRIORITIES);
1164 : 0 : enetc4_get_devargs(dev, ENETC4_TXQ_WRR);
1165 : 0 : enetc4_get_devargs(dev, ENETC4_NC_MEMORY);
1166 : :
1167 [ # # ]: 0 : if (dev->data->nb_rx_queues <= 1)
1168 : : return 0;
1169 : :
1170 : : /* Setup RSS */
1171 : : /* Setup control BDR */
1172 : 0 : ret = enetc4_setup_cbdr(dev, enetc_hw, ENETC_CBDR_SIZE, &hw->cbdr);
1173 [ # # ]: 0 : if (ret) {
1174 : : /* Disable RSS */
1175 : : enetc4_rss_configure(enetc_hw, false);
1176 : 0 : return ret;
1177 : : }
1178 : :
1179 : : /* Reset CIR again after enable CBDR*/
1180 : 0 : rte_delay_us(ENETC_CBDR_DELAY);
1181 : 0 : ENETC_PMD_DEBUG("CIR %x after CBDR enable", rte_read32(hw->cbdr.regs.cir));
1182 : 0 : rte_write32(0, hw->cbdr.regs.cir);
1183 : 0 : ENETC_PMD_DEBUG("CIR %x after reset", rte_read32(hw->cbdr.regs.cir));
1184 : :
1185 : 0 : val = enetc_rd(enetc_hw, ENETC_SIPCAPR0);
1186 [ # # ]: 0 : if (val & ENETC_SIPCAPR0_RSS) {
1187 : 0 : num_rss = enetc_rd(enetc_hw, ENETC_SIRSSCAPR);
1188 : 0 : hw->num_rss = ENETC_SIRSSCAPR_GET_NUM_RSS(num_rss);
1189 : 0 : ENETC_PMD_DEBUG("num_rss = %d", hw->num_rss);
1190 : :
1191 : : /* Add number of BDR groups */
1192 : 0 : enetc4_wr(enetc_hw, ENETC_SIRBGCR, dev->data->nb_rx_queues);
1193 : :
1194 : :
1195 : : /* Configuring indirecton table with default values
1196 : : * Hash algorithm and RSS secret key to be filled by PF
1197 : : */
1198 : 0 : rss_table = rte_malloc(NULL, hw->num_rss * sizeof(*rss_table), ENETC_CBDR_ALIGN);
1199 [ # # ]: 0 : if (!rss_table) {
1200 : : enetc4_rss_configure(enetc_hw, false);
1201 : 0 : enetc_free_cbdr(&hw->cbdr);
1202 : 0 : return -ENOMEM;
1203 : : }
1204 : :
1205 : 0 : ENETC_PMD_DEBUG("Enabling RSS for port %s with queues = %d", dev->device->name,
1206 : : dev->data->nb_rx_queues);
1207 [ # # ]: 0 : for (i = 0; i < hw->num_rss; i++)
1208 : 0 : rss_table[i] = i % dev->data->nb_rx_queues;
1209 : :
1210 : 0 : ret = enetc_ntmp_rsst_query_or_update_entry(&hw->cbdr,
1211 : : rss_table, hw->num_rss, false);
1212 [ # # ]: 0 : if (ret) {
1213 : 0 : ENETC_PMD_WARN("RSS indirection table update fails,"
1214 : : "Scaling behaviour is undefined");
1215 : : enetc4_rss_configure(enetc_hw, false);
1216 : 0 : enetc_free_cbdr(&hw->cbdr);
1217 : : }
1218 : 0 : rte_free(rss_table);
1219 : :
1220 : : /* Enable RSS */
1221 : : enetc4_rss_configure(enetc_hw, true);
1222 : : }
1223 : :
1224 : : return 0;
1225 : : }
1226 : :
1227 : : int
1228 : 0 : enetc4_rx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
1229 : : {
1230 : 0 : struct enetc_eth_adapter *priv =
1231 : 0 : ENETC_DEV_PRIVATE(dev->data->dev_private);
1232 : : struct enetc_bdr *rx_ring;
1233 : : uint32_t rx_data;
1234 : :
1235 : 0 : PMD_INIT_FUNC_TRACE();
1236 : 0 : rx_ring = dev->data->rx_queues[qidx];
1237 [ # # ]: 0 : if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) {
1238 [ # # ]: 0 : if (priv->hw.device_id == ENETC4_DEV_ID_VF)
1239 : 0 : pthread_mutex_lock(&priv->hw.vsi_lock);
1240 : 0 : rx_data = enetc4_rxbdr_rd(&priv->hw.hw, rx_ring->index,
1241 : : ENETC_RBMR);
1242 : : rx_data |= ENETC_RBMR_EN;
1243 : : /* Restore congestion mode if TX PAUSE is active. */
1244 [ # # ]: 0 : if (rte_atomic_load_explicit(&priv->hw.tx_pause_active,
1245 : : rte_memory_order_relaxed))
1246 : 0 : rx_data |= ENETC_RBMR_CM;
1247 : : else
1248 : 0 : rx_data &= ~(uint32_t)ENETC_RBMR_CM;
1249 : 0 : enetc4_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR,
1250 : : rx_data);
1251 [ # # ]: 0 : if (priv->hw.device_id == ENETC4_DEV_ID_VF)
1252 : 0 : pthread_mutex_unlock(&priv->hw.vsi_lock);
1253 : 0 : dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
1254 : : }
1255 : :
1256 : 0 : return 0;
1257 : : }
1258 : :
1259 : : int
1260 : 0 : enetc4_rx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
1261 : : {
1262 : 0 : struct enetc_eth_adapter *priv =
1263 : 0 : ENETC_DEV_PRIVATE(dev->data->dev_private);
1264 : : struct enetc_bdr *rx_ring;
1265 : : uint32_t rx_data;
1266 : :
1267 : 0 : PMD_INIT_FUNC_TRACE();
1268 : 0 : rx_ring = dev->data->rx_queues[qidx];
1269 [ # # ]: 0 : if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) {
1270 [ # # ]: 0 : if (priv->hw.device_id == ENETC4_DEV_ID_VF)
1271 : 0 : pthread_mutex_lock(&priv->hw.vsi_lock);
1272 : 0 : rx_data = enetc4_rxbdr_rd(&priv->hw.hw, rx_ring->index,
1273 : : ENETC_RBMR);
1274 : 0 : rx_data = rx_data & (~ENETC_RBMR_EN);
1275 : 0 : enetc4_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR,
1276 : : rx_data);
1277 [ # # ]: 0 : if (priv->hw.device_id == ENETC4_DEV_ID_VF)
1278 : 0 : pthread_mutex_unlock(&priv->hw.vsi_lock);
1279 : 0 : dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
1280 : : }
1281 : :
1282 : 0 : return 0;
1283 : : }
1284 : :
1285 : : int
1286 : 0 : enetc4_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
1287 : : {
1288 : 0 : struct enetc_eth_adapter *priv =
1289 : 0 : ENETC_DEV_PRIVATE(dev->data->dev_private);
1290 : : struct enetc_bdr *tx_ring;
1291 : : uint32_t tx_data;
1292 : :
1293 : 0 : PMD_INIT_FUNC_TRACE();
1294 : 0 : tx_ring = dev->data->tx_queues[qidx];
1295 [ # # ]: 0 : if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) {
1296 : 0 : tx_data = enetc4_txbdr_rd(&priv->hw.hw, tx_ring->index,
1297 : : ENETC_TBMR);
1298 : : /* Clear scheduler bits before applying fresh devarg values. */
1299 : 0 : tx_data &= ~(ENETC_TBMR_PRIO_MASK | ENETC_TBMR_WRR_MASK);
1300 : 0 : tx_data |= ENETC_TBMR_EN;
1301 [ # # ]: 0 : if (priv->hw.txq_prior)
1302 : 0 : tx_data |= priv->hw.txq_prior[tx_ring->index];
1303 [ # # ]: 0 : if (priv->hw.txq_wrr)
1304 : 0 : tx_data |= priv->hw.txq_wrr[tx_ring->index];
1305 : 0 : enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR,
1306 : : tx_data);
1307 : 0 : dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
1308 : : }
1309 : :
1310 : 0 : return 0;
1311 : : }
1312 : :
1313 : : int
1314 : 0 : enetc4_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
1315 : : {
1316 : 0 : struct enetc_eth_adapter *priv =
1317 : 0 : ENETC_DEV_PRIVATE(dev->data->dev_private);
1318 : : struct enetc_bdr *tx_ring;
1319 : : uint32_t tx_data;
1320 : :
1321 : 0 : PMD_INIT_FUNC_TRACE();
1322 : 0 : tx_ring = dev->data->tx_queues[qidx];
1323 [ # # ]: 0 : if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) {
1324 : 0 : tx_data = enetc4_txbdr_rd(&priv->hw.hw, tx_ring->index,
1325 : : ENETC_TBMR);
1326 : 0 : tx_data = tx_data & (~ENETC_TBMR_EN);
1327 : 0 : enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR,
1328 : : tx_data);
1329 : 0 : dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
1330 : : }
1331 : :
1332 : 0 : return 0;
1333 : : }
1334 : :
1335 : : void
1336 : 0 : enetc4_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
1337 : : struct rte_eth_rxq_info *qinfo)
1338 : : {
1339 : 0 : struct enetc_bdr *rxq = dev->data->rx_queues[queue_id];
1340 : :
1341 : 0 : qinfo->mp = rxq->mb_pool;
1342 : 0 : qinfo->scattered_rx = dev->data->scattered_rx;
1343 : : /* RSC rings use 2 slots per descriptor; report the requested count. */
1344 [ # # ]: 0 : qinfo->nb_desc = rxq->rsc_enable ? rxq->bd_count / 2 : rxq->bd_count;
1345 : 0 : qinfo->conf.rx_free_thresh = 0;
1346 : 0 : qinfo->conf.rx_deferred_start = rxq->rx_deferred_start;
1347 : 0 : qinfo->conf.rx_drop_en = 0;
1348 : 0 : }
1349 : :
1350 : : void
1351 : 0 : enetc4_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
1352 : : struct rte_eth_txq_info *qinfo)
1353 : : {
1354 : 0 : struct enetc_bdr *txq = dev->data->tx_queues[queue_id];
1355 : :
1356 : : /* LSO rings use 2 slots per descriptor; report the requested count. */
1357 [ # # ]: 0 : qinfo->nb_desc = txq->lso_enable ? txq->bd_count / 2 : txq->bd_count;
1358 : 0 : qinfo->conf.tx_thresh.pthresh = 0;
1359 : 0 : qinfo->conf.tx_thresh.hthresh = 0;
1360 : 0 : qinfo->conf.tx_thresh.wthresh = 0;
1361 : 0 : qinfo->conf.tx_deferred_start = txq->tx_deferred_start;
1362 : 0 : qinfo->conf.tx_free_thresh = 0;
1363 : 0 : qinfo->conf.tx_rs_thresh = 0;
1364 : 0 : }
1365 : :
1366 : : const uint32_t *
1367 : 0 : enetc4_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
1368 : : size_t *no_of_elements)
1369 : : {
1370 : 0 : PMD_INIT_FUNC_TRACE();
1371 : : static const uint32_t ptypes[] = {
1372 : : RTE_PTYPE_L2_ETHER,
1373 : : RTE_PTYPE_L3_IPV4,
1374 : : RTE_PTYPE_L3_IPV6,
1375 : : RTE_PTYPE_L4_TCP,
1376 : : RTE_PTYPE_L4_UDP,
1377 : : RTE_PTYPE_L4_SCTP,
1378 : : RTE_PTYPE_L4_ICMP,
1379 : : RTE_PTYPE_L4_FRAG,
1380 : : RTE_PTYPE_TUNNEL_ESP,
1381 : : RTE_PTYPE_UNKNOWN
1382 : : };
1383 : :
1384 : 0 : *no_of_elements = RTE_DIM(ptypes);
1385 : 0 : return ptypes;
1386 : : }
1387 : :
1388 : : /* Station interface registers dumped by .get_reg */
1389 : : static const uint32_t enetc4_pf_si_regs[] = {
1390 : : ENETC_SIMR, ENETC_SICAPR0, ENETC_SIPMAR0, ENETC_SIPMAR1,
1391 : : ENETC4_SIROCT0, ENETC4_SIRFRM0, ENETC4_SITOCT0, ENETC4_SITFRM0,
1392 : : ENETC4_SITDFCR,
1393 : : };
1394 : :
1395 : : /* Port registers dumped by .get_reg (accessible only by the PF) */
1396 : : static const uint32_t enetc4_pf_port_regs[] = {
1397 : : ENETC4_PMR, ENETC4_PSIPMMR, ENETC4_PMAR0, ENETC4_PMAR1,
1398 : : ENETC4_PM_CMD_CFG(0), ENETC4_PM_MAXFRM(0), ENETC4_PM_IF_MODE(0),
1399 : : ENETC4_PM_IF_STATUS(0),
1400 : : };
1401 : :
1402 : : /*
1403 : : * Dump the PF-accessible registers: station interface, port and per-ring
1404 : : * BD ring registers. When info->data is NULL, only the register count and
1405 : : * width are reported so the caller can size its buffer.
1406 : : */
1407 : : static int
1408 : 0 : enetc4_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs)
1409 : : {
1410 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1411 : : struct enetc_hw *enetc_hw = &hw->hw;
1412 : : uint32_t count, addr;
1413 : : uint32_t *buf;
1414 : : uint16_t i, j;
1415 : :
1416 : : count = RTE_DIM(enetc4_pf_si_regs);
1417 : : count += RTE_DIM(enetc4_pf_port_regs);
1418 : 0 : count += RTE_DIM(enetc4_txbdr_regs) * dev->data->nb_tx_queues;
1419 : 0 : count += RTE_DIM(enetc4_rxbdr_regs) * dev->data->nb_rx_queues;
1420 : :
1421 [ # # ]: 0 : if (regs->data == NULL) {
1422 : 0 : regs->length = count;
1423 : 0 : regs->width = sizeof(uint32_t);
1424 : 0 : return 0;
1425 : : }
1426 : :
1427 [ # # # # ]: 0 : if (regs->length && regs->length < count)
1428 : : return -ENOTSUP;
1429 : :
1430 : : buf = regs->data;
1431 : :
1432 [ # # ]: 0 : for (i = 0; i < RTE_DIM(enetc4_pf_si_regs); i++)
1433 : 0 : *buf++ = enetc4_rd(enetc_hw, enetc4_pf_si_regs[i]);
1434 : :
1435 [ # # ]: 0 : for (i = 0; i < RTE_DIM(enetc4_pf_port_regs); i++)
1436 : 0 : *buf++ = enetc4_port_rd(enetc_hw, enetc4_pf_port_regs[i]);
1437 : :
1438 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1439 [ # # ]: 0 : for (j = 0; j < RTE_DIM(enetc4_txbdr_regs); j++) {
1440 : 0 : addr = ENETC_BDR(TX, i, enetc4_txbdr_regs[j]);
1441 : 0 : *buf++ = enetc4_rd(enetc_hw, addr);
1442 : : }
1443 : : }
1444 : :
1445 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1446 [ # # ]: 0 : for (j = 0; j < RTE_DIM(enetc4_rxbdr_regs); j++) {
1447 : 0 : addr = ENETC_BDR(RX, i, enetc4_rxbdr_regs[j]);
1448 : 0 : *buf++ = enetc4_rd(enetc_hw, addr);
1449 : : }
1450 : : }
1451 : :
1452 : 0 : regs->version = (uint32_t)hw->device_id << 16 | hw->revision_id;
1453 : :
1454 : 0 : return 0;
1455 : : }
1456 : :
1457 : : /*
1458 : : * The set of PCI devices this driver supports
1459 : : */
1460 : : static const struct rte_pci_id pci_id_enetc4_map[] = {
1461 : : { RTE_PCI_DEVICE(PCI_VENDOR_ID_NXP, ENETC4_DEV_ID) },
1462 : : { .vendor_id = 0, /* sentinel */ },
1463 : : };
1464 : :
1465 : : /* Features supported by this driver */
1466 : : static const struct eth_dev_ops enetc4_ops = {
1467 : : .dev_configure = enetc4_dev_configure,
1468 : : .dev_start = enetc4_dev_start,
1469 : : .dev_stop = enetc4_dev_stop,
1470 : : .dev_close = enetc4_dev_close,
1471 : : .dev_infos_get = enetc4_dev_infos_get,
1472 : : .link_update = enetc4_link_update,
1473 : : .stats_get = enetc4_stats_get,
1474 : : .stats_reset = enetc4_stats_reset,
1475 : : .get_reg = enetc4_get_regs,
1476 : : .promiscuous_enable = enetc4_promiscuous_enable,
1477 : : .promiscuous_disable = enetc4_promiscuous_disable,
1478 : : .vlan_pvid_set = enetc4_vlan_pvid_set,
1479 : : .rx_queue_setup = enetc4_rx_queue_setup,
1480 : : .rx_queue_start = enetc4_rx_queue_start,
1481 : : .rx_queue_stop = enetc4_rx_queue_stop,
1482 : : .rx_queue_release = enetc4_rx_queue_release,
1483 : : .rxq_info_get = enetc4_rxq_info_get,
1484 : : .tx_queue_setup = enetc4_tx_queue_setup,
1485 : : .tx_queue_start = enetc4_tx_queue_start,
1486 : : .tx_queue_stop = enetc4_tx_queue_stop,
1487 : : .tx_queue_release = enetc4_tx_queue_release,
1488 : : .txq_info_get = enetc4_txq_info_get,
1489 : : .dev_supported_ptypes_get = enetc4_supported_ptypes_get,
1490 : : };
1491 : :
1492 : : /*
1493 : : * Storing the HW base addresses
1494 : : *
1495 : : * @param eth_dev
1496 : : * - Pointer to the structure rte_eth_dev
1497 : : */
1498 : : void
1499 : 0 : enetc4_dev_hw_init(struct rte_eth_dev *eth_dev)
1500 : : {
1501 : : struct enetc_eth_hw *hw =
1502 : 0 : ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1503 : 0 : struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
1504 : :
1505 : 0 : eth_dev->rx_pkt_burst = &enetc_recv_pkts_cacheable;
1506 : 0 : eth_dev->tx_pkt_burst = &enetc_xmit_pkts_cacheable;
1507 : :
1508 : : /* Retrieving and storing the HW base address of device */
1509 : 0 : hw->hw.reg = (void *)pci_dev->mem_resource[0].addr;
1510 : 0 : hw->device_id = pci_dev->id.device_id;
1511 : :
1512 : : /* Calculating and storing the base HW addresses */
1513 : 0 : hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE);
1514 : 0 : hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE);
1515 : 0 : }
1516 : :
1517 : : /**
1518 : : * Initialisation of the enetc4 device
1519 : : *
1520 : : * @param eth_dev
1521 : : * - Pointer to the structure rte_eth_dev
1522 : : *
1523 : : * @return
1524 : : * - On success, zero.
1525 : : * - On failure, negative value.
1526 : : */
1527 : :
1528 : : static int
1529 : 0 : enetc4_dev_init(struct rte_eth_dev *eth_dev)
1530 : : {
1531 : 0 : struct enetc_eth_hw *hw =
1532 : 0 : ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1533 : 0 : struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
1534 : : int error = 0;
1535 : : uint32_t si_cap;
1536 : : struct enetc_hw *enetc_hw = &hw->hw;
1537 : :
1538 : 0 : PMD_INIT_FUNC_TRACE();
1539 : :
1540 : 0 : eth_dev->dev_ops = &enetc4_ops;
1541 : :
1542 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
1543 : : /*
1544 : : * Secondary process: dev_ops is set above, but the fast-path
1545 : : * burst pointers must also be set here or
1546 : : * rte_eth_rx_burst()/rte_eth_tx_burst() would dereference NULL.
1547 : : * hw->nc_mode lives in the shared dev_private and has already
1548 : : * been set by the primary, so honour it to match the base BD
1549 : : * ring layout. The RSC (LRO) and LSO (TSO) bursts use doubled
1550 : : * 32B descriptor rings that the primary selects only at queue
1551 : : * setup; the secondary cannot observe that choice, so it always
1552 : : * uses the base (nc or cacheable) burst. Running the Rx/Tx
1553 : : * datapath from a secondary is therefore not supported when LRO
1554 : : * or TSO is enabled (see the ENETC4 NIC guide).
1555 : : */
1556 [ # # ]: 0 : if (hw->nc_mode) {
1557 : 0 : eth_dev->rx_pkt_burst = &enetc_recv_pkts_nc;
1558 : 0 : eth_dev->tx_pkt_burst = &enetc_xmit_pkts_nc;
1559 : : } else {
1560 : 0 : eth_dev->rx_pkt_burst = &enetc_recv_pkts_cacheable;
1561 : 0 : eth_dev->tx_pkt_burst = &enetc_xmit_pkts_cacheable;
1562 : : }
1563 : 0 : return 0;
1564 : : }
1565 : 0 : enetc4_dev_hw_init(eth_dev);
1566 : :
1567 : 0 : si_cap = enetc_rd(enetc_hw, ENETC_SICAPR0);
1568 : 0 : hw->max_tx_queues = si_cap & ENETC_SICAPR0_BDR_MASK;
1569 : 0 : hw->max_rx_queues = (si_cap >> 16) & ENETC_SICAPR0_BDR_MASK;
1570 : :
1571 : 0 : hw->nc_mode = 0;
1572 : 0 : enetc4_get_devargs(eth_dev, ENETC4_TXQ_PRIORITIES);
1573 : 0 : enetc4_get_devargs(eth_dev, ENETC4_NC_MEMORY);
1574 [ # # ]: 0 : if (hw->nc_mode) {
1575 : 0 : eth_dev->rx_pkt_burst = &enetc_recv_pkts_nc;
1576 : 0 : eth_dev->tx_pkt_burst = &enetc_xmit_pkts_nc;
1577 : 0 : ENETC_PMD_LOG(INFO, "nc=1: using non-cacheable BD ops (_nc)");
1578 : : }
1579 : :
1580 : 0 : ENETC_PMD_DEBUG("Max RX queues = %d Max TX queues = %d",
1581 : : hw->max_rx_queues, hw->max_tx_queues);
1582 : 0 : error = enetc4_mac_init(hw, eth_dev);
1583 [ # # ]: 0 : if (error != 0) {
1584 : 0 : ENETC_PMD_ERR("MAC initialization failed");
1585 : 0 : return -1;
1586 : : }
1587 : :
1588 : : /* Set MTU */
1589 : 0 : enetc_port_wr(&hw->hw, ENETC4_PM_MAXFRM(0),
1590 : : ENETC_SET_MAXFRM(RTE_ETHER_MAX_LEN));
1591 : 0 : eth_dev->data->mtu = RTE_ETHER_MAX_LEN - RTE_ETHER_HDR_LEN -
1592 : : RTE_ETHER_CRC_LEN;
1593 : :
1594 [ # # ]: 0 : if (rte_eal_iova_mode() == RTE_IOVA_PA)
1595 : 0 : dpaax_iova_table_populate();
1596 : :
1597 : 0 : ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
1598 : : eth_dev->data->port_id, pci_dev->id.vendor_id,
1599 : : pci_dev->id.device_id);
1600 : 0 : return 0;
1601 : : }
1602 : :
1603 : : static int
1604 : 0 : enetc4_dev_uninit(struct rte_eth_dev *eth_dev)
1605 : : {
1606 : 0 : PMD_INIT_FUNC_TRACE();
1607 : :
1608 : 0 : return enetc4_dev_close(eth_dev);
1609 : : }
1610 : :
1611 : : static int
1612 : 0 : enetc4_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
1613 : : struct rte_pci_device *pci_dev)
1614 : : {
1615 : 0 : return rte_eth_dev_pci_generic_probe(pci_dev,
1616 : : sizeof(struct enetc_eth_adapter),
1617 : : enetc4_dev_init);
1618 : : }
1619 : :
1620 : : int
1621 : 0 : enetc4_pci_remove(struct rte_pci_device *pci_dev)
1622 : : {
1623 : 0 : return rte_eth_dev_pci_generic_remove(pci_dev, enetc4_dev_uninit);
1624 : : }
1625 : :
1626 : : static struct rte_pci_driver rte_enetc4_pmd = {
1627 : : .id_table = pci_id_enetc4_map,
1628 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
1629 : : .probe = enetc4_pci_probe,
1630 : : .remove = enetc4_pci_remove,
1631 : : };
1632 : :
1633 : 302 : RTE_PMD_REGISTER_PCI(net_enetc4, rte_enetc4_pmd);
1634 : : RTE_PMD_REGISTER_PCI_TABLE(net_enetc4, pci_id_enetc4_map);
1635 : : RTE_PMD_REGISTER_KMOD_DEP(net_enetc4, "* vfio-pci");
1636 : : RTE_PMD_REGISTER_PARAM_STRING(net_enetc4,
1637 : : ENETC4_TXQ_PRIORITIES "=<string> "
1638 : : ENETC4_TXQ_WRR "=<string> "
1639 : : ENETC4_NC_MEMORY "=<int>");
1640 [ - + ]: 302 : RTE_LOG_REGISTER_DEFAULT(enetc4_logtype_pmd, NOTICE);
|