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_bus_pci.h>
7 : : #include <rte_kvargs.h>
8 : : #include <rte_random.h>
9 : : #include <dpaax_iova_table.h>
10 : : #include "enetc_logs.h"
11 : : #include "enetc.h"
12 : :
13 : : #define ENETC4_VSI_DISABLE "enetc4_vsi_disable"
14 : : #define ENETC4_VSI_TIMEOUT "enetc4_vsi_timeout"
15 : : #define ENETC4_VSI_DELAY "enetc4_vsi_delay"
16 : : #define ENETC4_NC_MEMORY "nc"
17 : :
18 : : static void
19 : 0 : enetc4_vf_get_devarg_nc(struct rte_eth_dev *dev)
20 : : {
21 : : struct enetc_eth_hw *hw =
22 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
23 : 0 : struct rte_devargs *devargs = dev->device->devargs;
24 : : struct rte_kvargs *kvlist;
25 : : const char *val;
26 : :
27 [ # # ]: 0 : if (!devargs)
28 : : return;
29 : :
30 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
31 [ # # ]: 0 : if (!kvlist)
32 : : return;
33 : :
34 : 0 : val = rte_kvargs_get(kvlist, ENETC4_NC_MEMORY);
35 [ # # # # ]: 0 : if (val && atoi(val) == 1)
36 : 0 : hw->nc_mode = 1;
37 : :
38 : 0 : rte_kvargs_free(kvlist);
39 : : }
40 : :
41 : : #define ENETC_CRC_TABLE_SIZE 256
42 : : #define ENETC_POLY 0x1021
43 : : #define ENETC_CRC_INIT 0xffff
44 : : #define ENETC_BYTE_SIZE 8
45 : : #define ENETC_MSB_BIT 0x8000
46 : :
47 : : /* Backward-compat devarg for a PF running a kernel before 6.18.37, which uses
48 : : * the legacy PF-to-VF link message layout (4-bit speed code + 4-bit cookie).
49 : : * Usage: -a <pci_addr>,vf_link_legacy=1
50 : : */
51 : : #define ENETC_VF_LINK_LEGACY "vf_link_legacy"
52 : :
53 : : uint16_t enetc_crc_table[ENETC_CRC_TABLE_SIZE];
54 : : bool enetc_crc_gen;
55 : :
56 : : /* Supported Rx offloads */
57 : : static uint64_t dev_rx_offloads_sup =
58 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
59 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
60 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
61 : : RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
62 : : RTE_ETH_RX_OFFLOAD_KEEP_CRC |
63 : : RTE_ETH_RX_OFFLOAD_TCP_LRO |
64 : : RTE_ETH_RX_OFFLOAD_SCATTER;
65 : :
66 : : /* Supported Tx offloads */
67 : : static uint64_t dev_tx_offloads_sup =
68 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
69 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
70 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
71 : : RTE_ETH_TX_OFFLOAD_TCP_TSO |
72 : : RTE_ETH_TX_OFFLOAD_UDP_TSO |
73 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
74 : :
75 : : static void
76 : 0 : enetc_gen_crc_table(void)
77 : : {
78 : : uint16_t crc = 0;
79 : : uint16_t c;
80 : :
81 [ # # ]: 0 : for (int i = 0; i < ENETC_CRC_TABLE_SIZE; i++) {
82 : : crc = 0;
83 : 0 : c = i << ENETC_BYTE_SIZE;
84 [ # # ]: 0 : for (int j = 0; j < ENETC_BYTE_SIZE; j++) {
85 [ # # ]: 0 : if ((crc ^ c) & ENETC_MSB_BIT)
86 : 0 : crc = (crc << 1) ^ ENETC_POLY;
87 : : else
88 : 0 : crc = crc << 1;
89 : 0 : c = c << 1;
90 : : }
91 : :
92 : 0 : enetc_crc_table[i] = crc;
93 : : }
94 : :
95 : 0 : enetc_crc_gen = true;
96 : 0 : }
97 : :
98 : : static uint16_t
99 : : enetc_crc_calc(uint16_t crc, const uint8_t *buffer, size_t len)
100 : : {
101 : : uint8_t data;
102 : :
103 [ # # # # : 0 : while (len--) {
# # # # #
# # # # #
# # # # #
# # # #
# ]
104 : 0 : data = *buffer;
105 : 0 : crc = (crc << 8) ^ enetc_crc_table[((crc >> 8) ^ data) & 0xff];
106 : 0 : buffer++;
107 : : }
108 : : return crc;
109 : : }
110 : :
111 : : static int
112 : 0 : parse_vf_link_legacy(const char *key __rte_unused, const char *value,
113 : : void *opaque)
114 : : {
115 : : struct rte_eth_dev *dev = (struct rte_eth_dev *)opaque;
116 : : struct enetc_eth_hw *hw =
117 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
118 : : char *endptr;
119 : : unsigned long val;
120 : :
121 [ # # # # ]: 0 : if (!value || *value == '\0') {
122 : 0 : ENETC_PMD_WARN("Empty value for devarg %s, ignoring",
123 : : ENETC_VF_LINK_LEGACY);
124 : 0 : return -EINVAL;
125 : : }
126 : :
127 : 0 : errno = 0;
128 : 0 : val = strtoul(value, &endptr, 0);
129 [ # # # # : 0 : if (errno != 0 || *endptr != '\0' || val > 1) {
# # ]
130 : 0 : ENETC_PMD_WARN("Invalid value '%s' for devarg %s, expected 0 or 1",
131 : : value, ENETC_VF_LINK_LEGACY);
132 : 0 : return -EINVAL;
133 : : }
134 : :
135 : 0 : hw->vf_link_legacy = (uint8_t)val;
136 : :
137 : 0 : return 0;
138 : : }
139 : :
140 : : static void
141 : 0 : enetc4_vf_get_devargs(struct rte_eth_dev *dev)
142 : : {
143 : : struct rte_devargs *devargs;
144 : : struct rte_kvargs *kvlist;
145 : :
146 : 0 : devargs = dev->device->devargs;
147 [ # # ]: 0 : if (!devargs)
148 : : return;
149 : :
150 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
151 [ # # ]: 0 : if (!kvlist)
152 : : return;
153 : :
154 [ # # ]: 0 : if (rte_kvargs_count(kvlist, ENETC_VF_LINK_LEGACY)) {
155 [ # # ]: 0 : if (rte_kvargs_process(kvlist, ENETC_VF_LINK_LEGACY,
156 : : parse_vf_link_legacy, (void *)dev) < 0)
157 : 0 : ENETC_PMD_WARN("Failed to parse devarg %s",
158 : : ENETC_VF_LINK_LEGACY);
159 : : }
160 : :
161 : 0 : rte_kvargs_free(kvlist);
162 : : }
163 : :
164 : : static int
165 : 0 : enetc4_vf_dev_infos_get(struct rte_eth_dev *dev,
166 : : struct rte_eth_dev_info *dev_info)
167 : : {
168 : : struct enetc_eth_hw *hw =
169 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
170 : :
171 : 0 : PMD_INIT_FUNC_TRACE();
172 : :
173 : 0 : dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
174 : : .nb_max = MAX_BD_COUNT,
175 : : .nb_min = MIN_BD_COUNT,
176 : : .nb_align = BD_ALIGN,
177 : : .nb_seg_max = ENETC4_MAX_SEGS,
178 : : .nb_mtu_seg_max = ENETC4_MAX_SEGS,
179 : : };
180 : 0 : dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
181 : : .nb_max = MAX_BD_COUNT,
182 : : .nb_min = MIN_BD_COUNT,
183 : : .nb_align = BD_ALIGN,
184 : : .nb_seg_max = ENETC4_MAX_SEGS,
185 : : .nb_mtu_seg_max = ENETC4_MAX_SEGS,
186 : : };
187 : 0 : dev_info->max_rx_queues = hw->max_rx_queues;
188 : 0 : dev_info->max_tx_queues = hw->max_tx_queues;
189 : 0 : dev_info->max_rx_pktlen = ENETC4_MAC_MAXFRM_SIZE;
190 : 0 : dev_info->max_mtu = dev_info->max_rx_pktlen - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN);
191 : 0 : dev_info->max_mac_addrs = ENETC4_MAC_ENTRIES;
192 : 0 : dev_info->rx_offload_capa = dev_rx_offloads_sup;
193 : 0 : dev_info->tx_offload_capa = dev_tx_offloads_sup;
194 : 0 : dev_info->flow_type_rss_offloads = ENETC_RSS_OFFLOAD_ALL;
195 : :
196 : 0 : return 0;
197 : : }
198 : :
199 : :
200 : : int
201 : 0 : enetc4_vf_dev_stop(struct rte_eth_dev *dev __rte_unused)
202 : : {
203 : 0 : PMD_INIT_FUNC_TRACE();
204 : :
205 : 0 : return 0;
206 : : }
207 : :
208 : : static int
209 : 0 : enetc4_vf_dev_start(struct rte_eth_dev *dev __rte_unused)
210 : : {
211 : 0 : PMD_INIT_FUNC_TRACE();
212 : :
213 : 0 : return 0;
214 : : }
215 : :
216 : : static int
217 : 0 : enetc4_vf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats,
218 : : struct eth_queue_stats *qstats __rte_unused)
219 : : {
220 : : struct enetc_eth_hw *hw =
221 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
222 : : struct enetc_hw *enetc_hw = &hw->hw;
223 : : struct enetc_bdr *rx_ring;
224 : : uint8_t i;
225 : :
226 : 0 : PMD_INIT_FUNC_TRACE();
227 : :
228 : : /*
229 : : * The SI-level counters are read-only for a VF; they cannot be
230 : : * zeroed directly. Instead, stats_reset captures a baseline
231 : : * snapshot, and stats_get reports the delta so that the reported
232 : : * values appear to start from zero after each reset call.
233 : : */
234 : 0 : stats->ipackets = enetc4_rd64(enetc_hw, ENETC4_SIRFRM0) -
235 : 0 : hw->vf_stats_saved.ipackets;
236 : 0 : stats->opackets = enetc4_rd64(enetc_hw, ENETC4_SITFRM0) -
237 : 0 : hw->vf_stats_saved.opackets;
238 : 0 : stats->ibytes = enetc4_rd64(enetc_hw, ENETC4_SIROCT0) -
239 : 0 : hw->vf_stats_saved.ibytes;
240 : 0 : stats->obytes = enetc4_rd64(enetc_hw, ENETC4_SITOCT0) -
241 : 0 : hw->vf_stats_saved.obytes;
242 : 0 : stats->oerrors = (uint32_t)enetc4_rd(enetc_hw, ENETC4_SITDFCR) -
243 : 0 : (uint32_t)hw->vf_stats_saved.oerrors;
244 : :
245 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
246 : 0 : rx_ring = dev->data->rx_queues[i];
247 : 0 : stats->ierrors += rx_ring->ierrors;
248 : : }
249 : :
250 : 0 : return 0;
251 : : }
252 : :
253 : : /*
254 : : * Reset VF statistics by capturing a new baseline snapshot of the
255 : : * SI-level hardware counters. Because those counters are read-only
256 : : * for a VF (hardware erratum prevents reliable clear via FLR/soft
257 : : * reset too), the driver uses a software delta approach: every
258 : : * stats_get call reports current_hw_value - saved_baseline.
259 : : */
260 : : static int
261 : 0 : enetc4_vf_stats_reset(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 : : struct enetc_bdr *rx_ring;
267 : : uint8_t i;
268 : :
269 : 0 : PMD_INIT_FUNC_TRACE();
270 : :
271 : : /* Snapshot current HW SI counter values as the new zero baseline. */
272 : 0 : hw->vf_stats_saved.ipackets = enetc4_rd64(enetc_hw, ENETC4_SIRFRM0);
273 : 0 : hw->vf_stats_saved.opackets = enetc4_rd64(enetc_hw, ENETC4_SITFRM0);
274 : 0 : hw->vf_stats_saved.ibytes = enetc4_rd64(enetc_hw, ENETC4_SIROCT0);
275 : 0 : hw->vf_stats_saved.obytes = enetc4_rd64(enetc_hw, ENETC4_SITOCT0);
276 : 0 : hw->vf_stats_saved.oerrors = enetc4_rd(enetc_hw, ENETC4_SITDFCR);
277 : :
278 : : /* Reset the per-ring software Rx error accumulators. */
279 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
280 : 0 : rx_ring = dev->data->rx_queues[i];
281 [ # # ]: 0 : if (rx_ring)
282 : 0 : rx_ring->ierrors = 0;
283 : : }
284 : :
285 : 0 : return 0;
286 : : }
287 : :
288 : :
289 : : static void
290 : : enetc_msg_vf_fill_common_hdr(struct enetc_msg_swbd *msg,
291 : : uint8_t class_id, uint8_t cmd_id, uint8_t proto_ver,
292 : : uint8_t len, uint8_t cookie)
293 : : {
294 : 0 : struct enetc_msg_cmd_header *hdr = msg->vaddr;
295 : :
296 : 0 : hdr->class_id = class_id;
297 : 0 : hdr->cmd_id = cmd_id;
298 : 0 : hdr->proto_ver = proto_ver;
299 : 0 : hdr->len = len;
300 : 0 : hdr->cookie = cookie;
301 : : /* Incrementing msg 2 bytes ahead as the first two bytes are for CRC */
302 : 0 : hdr->csum = rte_cpu_to_be_16(enetc_crc_calc(ENETC_CRC_INIT,
303 : : (uint8_t *)msg->vaddr + sizeof(uint16_t),
304 : : msg->size - sizeof(uint16_t)));
305 : :
306 : : dcbf(hdr);
307 : 0 : }
308 : :
309 : : /* Messaging */
310 : : static void
311 : : enetc4_msg_vsi_write_msg(struct enetc_hw *hw,
312 : : struct enetc_msg_swbd *msg)
313 : : {
314 : : uint32_t val;
315 : :
316 [ # # ]: 0 : val = enetc_vsi_set_msize(msg->size) | lower_32_bits(msg->dma);
317 : 0 : enetc_wr(hw, ENETC4_VSIMSGSNDAR1, upper_32_bits(msg->dma));
318 : 0 : enetc_wr(hw, ENETC4_VSIMSGSNDAR0, val);
319 : 0 : }
320 : :
321 : : static void
322 : : enetc4_msg_vsi_reply_msg(struct enetc_eth_hw *hw, int vsimsgsr,
323 : : struct enetc_psi_reply_msg *reply_msg)
324 : : {
325 : : int8_t class_id = 0;
326 : : uint8_t status = 0;
327 : :
328 : : /* Extracting 8 bits of message result in class_id */
329 : 0 : class_id |= ((ENETC_SIMSGSR_GET_MC(vsimsgsr) >> 8) & 0xff);
330 : :
331 : : /* Extracting message result in status. With an older kernel PF
332 : : * (vf_link_legacy set) the lower byte holds a 4-bit cookie in the
333 : : * low nibble and a 4-bit result in the high nibble, so extract the
334 : : * upper 4 bits. Otherwise the full lower byte carries the result.
335 : : */
336 : 0 : if (hw->vf_link_legacy)
337 : 0 : status |= ((ENETC_SIMSGSR_GET_MC(vsimsgsr) >> 4) & 0xf);
338 : : else
339 : 0 : status |= (ENETC_SIMSGSR_GET_MC(vsimsgsr) & 0xff);
340 : :
341 : 0 : reply_msg->class_id = class_id;
342 : 0 : reply_msg->status = status;
343 : 0 : }
344 : :
345 : : static void
346 : : enetc4_msg_get_psi_msg(struct enetc_hw *enetc_hw, struct enetc_psi_reply_msg *reply_msg)
347 : : {
348 : 0 : struct enetc_eth_hw *hw = container_of(enetc_hw, struct enetc_eth_hw, hw);
349 : : int vsimsgrr;
350 : : int8_t class_id = 0;
351 : : uint8_t status = 0;
352 : :
353 : 0 : vsimsgrr = enetc_rd(enetc_hw, ENETC4_VSIMSGRR);
354 : :
355 : : /* Extracting 8 bits of message result in class_id */
356 : 0 : class_id |= ((ENETC_SIMSGSR_GET_MC(vsimsgrr) >> 8) & 0xff);
357 : :
358 : : /* Extracting message result in status. With an older kernel PF
359 : : * (vf_link_legacy set) the lower byte holds a 4-bit cookie in the
360 : : * low nibble and a 4-bit result in the high nibble, so extract the
361 : : * upper 4 bits. Otherwise the full lower byte carries the result.
362 : : */
363 [ # # ]: 0 : if (hw->vf_link_legacy)
364 : 0 : status |= ((ENETC_SIMSGSR_GET_MC(vsimsgrr) >> 4) & 0xf);
365 : : else
366 : 0 : status |= (ENETC_SIMSGSR_GET_MC(vsimsgrr) & 0xff);
367 : :
368 : 0 : reply_msg->class_id = class_id;
369 : 0 : reply_msg->status = status;
370 : : }
371 : :
372 : : /* Forward declaration: defined later in this file */
373 : : static int enetc4_vf_get_link_speed(struct rte_eth_dev *dev,
374 : : struct enetc_psi_reply_msg *reply_msg);
375 : :
376 : : /*
377 : : * Decode a PF-to-VF link-speed status code into the link_speed and
378 : : * link_duplex fields of *link. vf_link_legacy selects the older
379 : : * 4-bit code layout used by kernel PFs before v6.18.37.
380 : : */
381 : : static void
382 : 0 : enetc4_decode_link_speed(uint8_t status, bool vf_link_legacy,
383 : : struct rte_eth_link *link)
384 : : {
385 [ # # # # : 0 : switch (status) {
# # # #
# ]
386 : 0 : case ENETC_SPEED_UNKNOWN:
387 : 0 : ENETC_PMD_DEBUG("Speed unknown");
388 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_NONE;
389 : 0 : break;
390 : 0 : case ENETC_SPEED_10_HALF_DUPLEX:
391 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_10M;
392 : 0 : link->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
393 : 0 : break;
394 : 0 : case ENETC_SPEED_10_FULL_DUPLEX:
395 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_10M;
396 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
397 : 0 : break;
398 : 0 : case ENETC_SPEED_100_HALF_DUPLEX:
399 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_100M;
400 : 0 : link->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
401 : 0 : break;
402 : 0 : case ENETC_SPEED_100_FULL_DUPLEX:
403 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_100M;
404 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
405 : 0 : break;
406 : 0 : case ENETC_SPEED_1000:
407 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_1G;
408 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
409 : 0 : break;
410 : 0 : case ENETC_SPEED_2500:
411 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_2_5G;
412 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
413 : 0 : break;
414 : 0 : case ENETC_SPEED_5000:
415 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_5G;
416 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
417 : 0 : break;
418 : 0 : default:
419 [ # # ]: 0 : if (vf_link_legacy) {
420 : : /* Legacy PF-to-VF message layout (older kernel PF):
421 : : * speeds above 5Gbps use fixed 4-bit class codes.
422 : : */
423 : : switch (status) {
424 : 0 : case ENETC_SPEED_LEGACY_10G:
425 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_10G;
426 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
427 : 0 : break;
428 : 0 : case ENETC_SPEED_LEGACY_25G:
429 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_25G;
430 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
431 : 0 : break;
432 : 0 : case ENETC_SPEED_LEGACY_50G:
433 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_50G;
434 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
435 : 0 : break;
436 : 0 : case ENETC_SPEED_LEGACY_100G:
437 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_100G;
438 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
439 : 0 : break;
440 : 0 : case ENETC_SPEED_LEGACY_NOT_SUPPORTED:
441 : 0 : ENETC_PMD_DEBUG("Speed not supported");
442 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
443 : 0 : break;
444 : 0 : default:
445 : 0 : ENETC_PMD_ERR("Unknown speed status");
446 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
447 : 0 : break;
448 : : }
449 : : break;
450 : : }
451 : : /* Any status here is > ENETC_SPEED_5000. Validate against
452 : : * the set of speeds that the NETC IP is known to support.
453 : : * An unrecognised code yields UNKNOWN rather than a
454 : : * fabricated speed.
455 : : */
456 [ # # # # : 0 : switch ((status - ENETC_SPEED_5000) * 1000 + 5000) {
# # # ]
457 : 0 : case RTE_ETH_SPEED_NUM_10G:
458 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_10G;
459 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
460 : 0 : break;
461 : 0 : case RTE_ETH_SPEED_NUM_25G:
462 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_25G;
463 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
464 : 0 : break;
465 : 0 : case RTE_ETH_SPEED_NUM_40G:
466 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_40G;
467 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
468 : 0 : break;
469 : 0 : case RTE_ETH_SPEED_NUM_50G:
470 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_50G;
471 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
472 : 0 : break;
473 : 0 : case RTE_ETH_SPEED_NUM_100G:
474 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_100G;
475 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
476 : 0 : break;
477 : 0 : case RTE_ETH_SPEED_NUM_200G:
478 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_200G;
479 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
480 : 0 : break;
481 : 0 : default:
482 : 0 : ENETC_PMD_WARN("Unrecognized speed code 0x%x, "
483 : : "reporting unknown", status);
484 : 0 : link->link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
485 : 0 : break;
486 : : }
487 : : break;
488 : : }
489 : 0 : }
490 : :
491 : : /*
492 : : * Set or clear ENETC_RBMR_CM (congestion mode) on all active VF RX rings.
493 : : * When set, the ring signals congestion to the MAC, causing it to emit TX
494 : : * PAUSE frames on ingress pressure. hw->tx_pause_active is updated so rings
495 : : * started later inherit the correct state.
496 : : */
497 : : static void
498 : 0 : enetc4_vf_set_congestion_mode(struct rte_eth_dev *eth_dev, bool enable)
499 : : {
500 : : struct enetc_eth_hw *hw =
501 : 0 : ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
502 : : struct enetc_hw *enetc_hw = &hw->hw;
503 : 0 : uint16_t nb_rx = eth_dev->data->nb_rx_queues;
504 : : uint16_t i;
505 : : uint32_t rbmr;
506 : :
507 : 0 : pthread_mutex_lock(&hw->vsi_lock);
508 : :
509 : 0 : if (rte_atomic_load_explicit(&hw->tx_pause_active,
510 : : rte_memory_order_relaxed) ==
511 [ # # ]: 0 : (enable ? 1 : 0)) {
512 : 0 : pthread_mutex_unlock(&hw->vsi_lock);
513 : 0 : return;
514 : : }
515 : :
516 : 0 : rte_atomic_store_explicit(&hw->tx_pause_active, enable ? 1 : 0,
517 : : rte_memory_order_relaxed);
518 : :
519 [ # # ]: 0 : for (i = 0; i < nb_rx; i++) {
520 : 0 : rbmr = enetc4_rxbdr_rd(enetc_hw, i, ENETC_RBMR);
521 [ # # ]: 0 : if (enable)
522 : 0 : rbmr |= ENETC_RBMR_CM;
523 : : else
524 : 0 : rbmr &= ~(uint32_t)ENETC_RBMR_CM;
525 : 0 : enetc4_rxbdr_wr(enetc_hw, i, ENETC_RBMR, rbmr);
526 : : }
527 : 0 : pthread_mutex_unlock(&hw->vsi_lock);
528 : :
529 [ # # ]: 0 : ENETC_PMD_DEBUG("VF congestion mode %s on %u RX rings",
530 : : enable ? "enabled" : "disabled", nb_rx);
531 : : }
532 : :
533 : : static void
534 : 0 : enetc4_process_psi_msg(struct rte_eth_dev *eth_dev, struct enetc_hw *enetc_hw)
535 : : {
536 : : struct enetc_eth_hw *hw =
537 : 0 : ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
538 : : struct enetc_psi_reply_msg *msg;
539 : : struct rte_eth_link link;
540 : : bool tx_pause;
541 : : int ret = 0;
542 : :
543 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
544 [ # # ]: 0 : if (!msg) {
545 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
546 : 0 : return;
547 : : }
548 : :
549 : 0 : rte_eth_linkstatus_get(eth_dev, &link);
550 : : enetc4_msg_get_psi_msg(enetc_hw, msg);
551 : :
552 [ # # ]: 0 : if (msg->class_id == ENETC_CLASS_ID_LINK_STATUS) {
553 [ # # ]: 0 : if (msg->status & ENETC_LINK_DOWN) {
554 : 0 : ENETC_PMD_DEBUG("Link is down");
555 : 0 : link.link_status = RTE_ETH_LINK_DOWN;
556 : : /* Clear congestion mode on link-down so VF rings do not
557 : : * assert congestion while the port is offline.
558 : : */
559 : 0 : enetc4_vf_set_congestion_mode(eth_dev, false);
560 : : } else {
561 : : /* BIT(1) is set when the port has negotiated TX PAUSE.
562 : : * Legacy PF does not set this bit so tx_pause stays false.
563 : : */
564 : 0 : tx_pause = !!(msg->status & ENETC_LINK_TX_PAUSE);
565 : 0 : ENETC_PMD_DEBUG("Link is up, tx_pause=%d", tx_pause);
566 : 0 : link.link_status = RTE_ETH_LINK_UP;
567 : :
568 : : /* Apply congestion mode before raising the carrier so
569 : : * the VF rings are ready to emit PAUSE before traffic
570 : : * starts flowing.
571 : : */
572 : 0 : enetc4_vf_set_congestion_mode(eth_dev, tx_pause);
573 : :
574 : : /* Re-query speed from PF so the cached value reflects
575 : : * the current negotiated speed after link-up. This is a
576 : : * mailbox round trip issued from the link-status
577 : : * interrupt handler, which runs on the shared EAL
578 : : * interrupt thread with the mailbox interrupt masked, so
579 : : * it busy-waits up to (vsi_timeout * vsi_delay) us
580 : : * (by default 100 * 2000 us = 200 ms). If this stall on
581 : : * the EAL interrupt thread ever becomes a problem, reduce
582 : : * the wait budget with the "enetc4_vsi_timeout" and
583 : : * "enetc4_vsi_delay" devargs.
584 : : */
585 : : memset(msg, 0, sizeof(*msg));
586 [ # # ]: 0 : if (!enetc4_vf_get_link_speed(eth_dev, msg) &&
587 [ # # ]: 0 : msg->class_id == ENETC_CLASS_ID_LINK_SPEED)
588 : 0 : enetc4_decode_link_speed(msg->status,
589 : 0 : hw->vf_link_legacy,
590 : : &link);
591 : : }
592 : : ret = rte_eth_linkstatus_set(eth_dev, &link);
593 : : if (!ret)
594 : 0 : ENETC_PMD_DEBUG("Link status has been changed");
595 : :
596 : : /* Process user registered callback */
597 : 0 : rte_eth_dev_callback_process(eth_dev,
598 : : RTE_ETH_EVENT_INTR_LSC, NULL);
599 : : } else {
600 : 0 : ENETC_PMD_ERR("Wrong message 0x%x", msg->class_id);
601 : : }
602 : :
603 : 0 : rte_free(msg);
604 : : }
605 : :
606 : : static int
607 : 0 : enetc4_msg_vsi_send(struct enetc_eth_hw *hw, struct enetc_msg_swbd *msg,
608 : : int *vsimsgsr_out)
609 : : {
610 : : struct enetc_hw *enetc_hw = &hw->hw;
611 [ # # ]: 0 : int timeout = hw->vsi_timeout ? (int)hw->vsi_timeout :
612 : : ENETC4_DEF_VSI_WAIT_TIMEOUT_UPDATE;
613 [ # # ]: 0 : int delay_us = hw->vsi_delay ? (int)hw->vsi_delay :
614 : : ENETC4_DEF_VSI_WAIT_DELAY_UPDATE;
615 : : uint8_t class_id = 0;
616 : : int err = 0;
617 : : int vsimsgsr;
618 : :
619 : 0 : pthread_mutex_lock(&hw->vsi_lock);
620 : : enetc4_msg_vsi_write_msg(enetc_hw, msg);
621 : :
622 : : do {
623 : 0 : vsimsgsr = enetc_rd(enetc_hw, ENETC4_VSIMSGSR);
624 [ # # ]: 0 : if (!(vsimsgsr & ENETC4_VSIMSGSR_MB))
625 : : break;
626 : 0 : rte_delay_us(delay_us);
627 [ # # ]: 0 : } while (--timeout);
628 : :
629 [ # # ]: 0 : if (!timeout) {
630 : 0 : ENETC_PMD_ERR("Message not processed by PSI");
631 : 0 : pthread_mutex_unlock(&hw->vsi_lock);
632 : 0 : return -ETIMEDOUT;
633 : : }
634 : : /* check for message delivery error */
635 [ # # ]: 0 : if (vsimsgsr & ENETC4_VSIMSGSR_MS) {
636 : 0 : ENETC_PMD_ERR("Transfer error when copying the data");
637 : 0 : pthread_mutex_unlock(&hw->vsi_lock);
638 : 0 : return -EIO;
639 : : }
640 : :
641 : 0 : class_id |= ((ENETC_SIMSGSR_GET_MC(vsimsgsr) >> 8) & 0xff);
642 : :
643 : : /* Check the user-defined completion status. */
644 [ # # ]: 0 : if (class_id != ENETC_MSG_CLASS_ID_CMD_SUCCESS) {
645 [ # # # # : 0 : switch (class_id) {
# # # #
# ]
646 : 0 : case ENETC_MSG_CLASS_ID_PERMISSION_DENY:
647 : 0 : ENETC_PMD_ERR("Permission denied");
648 : : err = -EACCES;
649 : 0 : break;
650 : 0 : case ENETC_MSG_CLASS_ID_CMD_NOT_SUPPORT:
651 : 0 : ENETC_PMD_ERR("Command not supported");
652 : : err = -EOPNOTSUPP;
653 : 0 : break;
654 : 0 : case ENETC_MSG_CLASS_ID_PSI_BUSY:
655 : 0 : ENETC_PMD_ERR("PSI Busy");
656 : : err = -EBUSY;
657 : 0 : break;
658 : 0 : case ENETC_MSG_CLASS_ID_CMD_TIMEOUT:
659 : 0 : ENETC_PMD_ERR("Command timeout");
660 : : err = -ETIME;
661 : 0 : break;
662 : 0 : case ENETC_MSG_CLASS_ID_CRC_ERROR:
663 : 0 : ENETC_PMD_ERR("CRC error");
664 : : err = -EIO;
665 : 0 : break;
666 : 0 : case ENETC_MSG_CLASS_ID_PROTO_NOT_SUPPORT:
667 : 0 : ENETC_PMD_ERR("Protocol Version not supported");
668 : : err = -EOPNOTSUPP;
669 : 0 : break;
670 : 0 : case ENETC_MSG_CLASS_ID_INVALID_MSG_LEN:
671 : 0 : ENETC_PMD_ERR("Invalid message length");
672 : : err = -EINVAL;
673 : 0 : break;
674 : : case ENETC_CLASS_ID_MAC_FILTER:
675 : : case ENETC_CLASS_ID_LINK_STATUS:
676 : : case ENETC_CLASS_ID_LINK_SPEED:
677 : : case ENETC_CLASS_ID_GET_IP_VER:
678 : : break;
679 : 0 : default:
680 : : err = -EIO;
681 : : }
682 : : }
683 : :
684 [ # # ]: 0 : if (vsimsgsr_out != NULL)
685 : 0 : *vsimsgsr_out = vsimsgsr;
686 : 0 : pthread_mutex_unlock(&hw->vsi_lock);
687 : 0 : return err;
688 : : }
689 : :
690 : : static int
691 : 0 : enetc4_vf_set_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *addr)
692 : : {
693 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
694 : : struct enetc_msg_cmd_set_primary_mac *cmd;
695 : : struct enetc_msg_swbd *msg;
696 : : struct enetc_psi_reply_msg *reply_msg;
697 : : uint32_t msg_size;
698 : : int err = 0;
699 : 0 : int vsimsgsr_mac_set = 0;
700 : :
701 : 0 : PMD_INIT_FUNC_TRACE();
702 : 0 : reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
703 [ # # ]: 0 : if (!reply_msg) {
704 : 0 : ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
705 : 0 : return -ENOMEM;
706 : : }
707 : :
708 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
709 [ # # ]: 0 : if (!msg) {
710 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
711 : : err = -ENOMEM;
712 : 0 : rte_free(reply_msg);
713 : 0 : return err;
714 : : }
715 : :
716 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac),
717 : : ENETC_VSI_PSI_MSG_SIZE);
718 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
719 [ # # ]: 0 : if (!msg->vaddr) {
720 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
721 : 0 : rte_free(msg);
722 : 0 : rte_free(reply_msg);
723 : 0 : return -ENOMEM;
724 : : }
725 : :
726 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
727 : 0 : msg->size = msg_size;
728 : :
729 : 0 : cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr;
730 : :
731 : 0 : cmd->count = 0;
732 : 0 : memcpy(&cmd->addr.addr_bytes, addr, sizeof(struct rte_ether_addr));
733 : :
734 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
735 : : ENETC_CMD_ID_SET_PRIMARY_MAC, 0, 0, 0);
736 : :
737 : : /* send the command and wait */
738 : 0 : err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_mac_set);
739 [ # # ]: 0 : if (err) {
740 : 0 : ENETC_PMD_ERR("VSI message send error");
741 : 0 : goto end;
742 : : }
743 : :
744 [ # # ]: 0 : enetc4_msg_vsi_reply_msg(hw, vsimsgsr_mac_set, reply_msg);
745 : :
746 [ # # ]: 0 : if (reply_msg->class_id == ENETC_CLASS_ID_MAC_FILTER) {
747 [ # # # ]: 0 : switch (reply_msg->status) {
748 : 0 : case ENETC_INVALID_MAC_ADDR:
749 : 0 : ENETC_PMD_ERR("Invalid MAC address");
750 : : err = -EINVAL;
751 : : break;
752 : 0 : case ENETC_DUPLICATE_MAC_ADDR:
753 : 0 : ENETC_PMD_ERR("Duplicate MAC address");
754 : : err = -EINVAL;
755 : : break;
756 : : default:
757 : : err = -EINVAL;
758 : : break;
759 : : }
760 : : }
761 : :
762 : : if (err) {
763 : 0 : ENETC_PMD_ERR("VSI command execute error!");
764 : 0 : goto end;
765 : : }
766 : :
767 : 0 : rte_ether_addr_copy((struct rte_ether_addr *)&cmd->addr,
768 : 0 : &dev->data->mac_addrs[0]);
769 : :
770 : 0 : end:
771 : : /* free memory no longer required */
772 : 0 : rte_free(msg->vaddr);
773 : 0 : rte_free(reply_msg);
774 : 0 : rte_free(msg);
775 : 0 : return err;
776 : : }
777 : :
778 : : static int
779 : 0 : enetc4_vf_promisc_send_message(struct rte_eth_dev *dev, bool promisc_en)
780 : : {
781 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
782 : : struct enetc_msg_cmd_set_promisc *cmd;
783 : : struct enetc_msg_swbd *msg;
784 : : uint32_t msg_size;
785 : : int err = 0;
786 : :
787 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
788 [ # # ]: 0 : if (!msg) {
789 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
790 : : err = -ENOMEM;
791 : 0 : return err;
792 : : }
793 : :
794 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_promisc), ENETC_VSI_PSI_MSG_SIZE);
795 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
796 [ # # ]: 0 : if (!msg->vaddr) {
797 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
798 : 0 : rte_free(msg);
799 : 0 : return -ENOMEM;
800 : : }
801 : :
802 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
803 : 0 : msg->size = msg_size;
804 : :
805 : 0 : cmd = (struct enetc_msg_cmd_set_promisc *)msg->vaddr;
806 : :
807 : : /* op_type is based on the result of message format
808 : : * 7 6 1 0
809 : : type promisc flush
810 : : */
811 : :
812 [ # # ]: 0 : if (promisc_en)
813 : 0 : cmd->op_type = ENETC_PROMISC_ENABLE;
814 : : else
815 : 0 : cmd->op_type = ENETC_PROMISC_DISABLE;
816 : :
817 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
818 : : ENETC_CMD_ID_SET_MAC_PROMISCUOUS, 0, 0, 0);
819 : :
820 : : /* send the command and wait */
821 : 0 : err = enetc4_msg_vsi_send(hw, msg, NULL);
822 [ # # ]: 0 : if (err) {
823 : 0 : ENETC_PMD_ERR("VSI message send error");
824 : 0 : goto end;
825 : : }
826 : :
827 : 0 : end:
828 : : /* free memory no longer required */
829 : 0 : rte_free(msg->vaddr);
830 : 0 : rte_free(msg);
831 : 0 : return err;
832 : : }
833 : :
834 : : static int
835 : 0 : enetc4_vf_allmulti_send_message(struct rte_eth_dev *dev, bool mc_promisc)
836 : : {
837 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
838 : : struct enetc_msg_cmd_set_promisc *cmd;
839 : : struct enetc_msg_swbd *msg;
840 : : uint32_t msg_size;
841 : : int err = 0;
842 : :
843 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
844 [ # # ]: 0 : if (!msg) {
845 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
846 : : err = -ENOMEM;
847 : 0 : return err;
848 : : }
849 : :
850 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_promisc),
851 : : ENETC_VSI_PSI_MSG_SIZE);
852 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
853 [ # # ]: 0 : if (!msg->vaddr) {
854 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
855 : 0 : rte_free(msg);
856 : 0 : return -ENOMEM;
857 : : }
858 : :
859 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
860 : 0 : msg->size = msg_size;
861 : :
862 : 0 : cmd = (struct enetc_msg_cmd_set_promisc *)msg->vaddr;
863 : :
864 : : /* op_type is based on the result of message format
865 : : * 7 6 1 0
866 : : type promisc flush
867 : : */
868 : :
869 [ # # ]: 0 : if (mc_promisc)
870 : 0 : cmd->op_type = ENETC_ALLMULTI_PROMISC_EN;
871 : : else
872 : 0 : cmd->op_type = ENETC_ALLMULTI_PROMISC_DIS;
873 : :
874 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
875 : : ENETC_CMD_ID_SET_MAC_PROMISCUOUS, 0, 0, 0);
876 : :
877 : : /* send the command and wait */
878 : 0 : err = enetc4_msg_vsi_send(hw, msg, NULL);
879 [ # # ]: 0 : if (err) {
880 : 0 : ENETC_PMD_ERR("VSI message send error");
881 : 0 : goto end;
882 : : }
883 : :
884 : 0 : end:
885 : : /* free memory no longer required */
886 : 0 : rte_free(msg->vaddr);
887 : 0 : rte_free(msg);
888 : 0 : return err;
889 : : }
890 : :
891 : :
892 : : static int
893 : 0 : enetc4_vf_multicast_enable(struct rte_eth_dev *dev)
894 : : {
895 : : int err;
896 : :
897 : 0 : PMD_INIT_FUNC_TRACE();
898 : 0 : err = enetc4_vf_allmulti_send_message(dev, true);
899 [ # # ]: 0 : if (err) {
900 : 0 : ENETC_PMD_ERR("Failed to enable multicast promiscuous mode");
901 : 0 : return err;
902 : : }
903 : :
904 : : return 0;
905 : : }
906 : :
907 : : static int
908 : 0 : enetc4_vf_multicast_disable(struct rte_eth_dev *dev)
909 : : {
910 : : int err;
911 : :
912 : 0 : PMD_INIT_FUNC_TRACE();
913 : 0 : err = enetc4_vf_allmulti_send_message(dev, false);
914 [ # # ]: 0 : if (err) {
915 : 0 : ENETC_PMD_ERR("Failed to disable multicast promiscuous mode");
916 : 0 : return err;
917 : : }
918 : :
919 : : return 0;
920 : : }
921 : :
922 : : static int
923 : 0 : enetc4_vf_promisc_enable(struct rte_eth_dev *dev)
924 : : {
925 : : int err;
926 : :
927 : 0 : PMD_INIT_FUNC_TRACE();
928 : 0 : err = enetc4_vf_promisc_send_message(dev, true);
929 [ # # ]: 0 : if (err) {
930 : 0 : ENETC_PMD_ERR("Failed to enable promiscuous mode");
931 : 0 : return err;
932 : : }
933 : :
934 : : return 0;
935 : : }
936 : :
937 : : static int
938 : 0 : enetc4_vf_promisc_disable(struct rte_eth_dev *dev)
939 : : {
940 : : int err;
941 : :
942 : 0 : PMD_INIT_FUNC_TRACE();
943 : 0 : err = enetc4_vf_promisc_send_message(dev, false);
944 [ # # ]: 0 : if (err) {
945 : 0 : ENETC_PMD_ERR("Failed to disable promiscuous mode");
946 : 0 : return err;
947 : : }
948 : :
949 : : return 0;
950 : : }
951 : :
952 : : static int
953 : 0 : enetc4_vf_get_link_status(struct rte_eth_dev *dev, struct enetc_psi_reply_msg *reply_msg)
954 : : {
955 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
956 : : struct enetc_msg_swbd *msg;
957 : : uint32_t msg_size;
958 : : int err = 0;
959 : 0 : int vsimsgsr_link_st = 0;
960 : :
961 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
962 [ # # ]: 0 : if (!msg) {
963 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
964 : : err = -ENOMEM;
965 : 0 : return err;
966 : : }
967 : :
968 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_link_status),
969 : : ENETC_VSI_PSI_MSG_SIZE);
970 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
971 [ # # ]: 0 : if (!msg->vaddr) {
972 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
973 : 0 : rte_free(msg);
974 : 0 : return -ENOMEM;
975 : : }
976 : :
977 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
978 : 0 : msg->size = msg_size;
979 : :
980 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_LINK_STATUS,
981 : : ENETC_CMD_ID_GET_LINK_STATUS, 0, 0, 0);
982 : :
983 : : /* send the command and wait */
984 : 0 : err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_link_st);
985 [ # # ]: 0 : if (err) {
986 : 0 : ENETC_PMD_ERR("VSI message send error");
987 : 0 : goto end;
988 : : }
989 : :
990 [ # # ]: 0 : enetc4_msg_vsi_reply_msg(hw, vsimsgsr_link_st, reply_msg);
991 : 0 : end:
992 : : /* free memory no longer required */
993 : 0 : rte_free(msg->vaddr);
994 : 0 : rte_free(msg);
995 : 0 : return err;
996 : : }
997 : :
998 : : static int
999 : 0 : enetc4_vf_get_link_speed(struct rte_eth_dev *dev, struct enetc_psi_reply_msg *reply_msg)
1000 : : {
1001 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1002 : : struct enetc_msg_swbd *msg;
1003 : : uint32_t msg_size;
1004 : : int err = 0;
1005 : 0 : int vsimsgsr_link_sp = 0;
1006 : :
1007 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
1008 [ # # ]: 0 : if (!msg) {
1009 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
1010 : : err = -ENOMEM;
1011 : 0 : return err;
1012 : : }
1013 : :
1014 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_link_speed),
1015 : : ENETC_VSI_PSI_MSG_SIZE);
1016 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
1017 [ # # ]: 0 : if (!msg->vaddr) {
1018 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
1019 : 0 : rte_free(msg);
1020 : 0 : return -ENOMEM;
1021 : : }
1022 : :
1023 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
1024 : 0 : msg->size = msg_size;
1025 : :
1026 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_LINK_SPEED,
1027 : : ENETC_CMD_ID_GET_LINK_SPEED, 0, 0, 0);
1028 : :
1029 : : /* send the command and wait */
1030 : 0 : err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_link_sp);
1031 [ # # ]: 0 : if (err) {
1032 : 0 : ENETC_PMD_ERR("VSI message send error");
1033 : 0 : goto end;
1034 : : }
1035 : :
1036 [ # # ]: 0 : enetc4_msg_vsi_reply_msg(hw, vsimsgsr_link_sp, reply_msg);
1037 : 0 : end:
1038 : : /* free memory no longer required */
1039 : 0 : rte_free(msg->vaddr);
1040 : 0 : rte_free(msg);
1041 : 0 : return err;
1042 : : }
1043 : :
1044 : : /*
1045 : : * Get the NETC IP minor revision (IP_MN) from the PSI using the 'Get IP
1046 : : * version' command class (class ID 0xF0, cmd_id 0x1). In the reply, the
1047 : : * low 8 bits of the return code carry the minor revision and the upper 8
1048 : : * bits carry the class code (0xF0). The PSI only implements the IP_MN
1049 : : * command of this class; the major revision comes from the PCI revision.
1050 : : */
1051 : : static int
1052 : 0 : enetc4_vf_get_ip_minor_revision(struct rte_eth_dev *dev, uint8_t *ip_mn)
1053 : : {
1054 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1055 : : struct enetc_msg_swbd *msg;
1056 : : uint32_t msg_size;
1057 : : uint16_t mc;
1058 : : uint8_t class_id;
1059 : 0 : int vsimsgsr = 0;
1060 : : int err = 0;
1061 : :
1062 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
1063 [ # # ]: 0 : if (!msg) {
1064 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
1065 : 0 : return -ENOMEM;
1066 : : }
1067 : :
1068 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_ip_ver),
1069 : : ENETC_VSI_PSI_MSG_SIZE);
1070 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
1071 [ # # ]: 0 : if (!msg->vaddr) {
1072 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
1073 : 0 : rte_free(msg);
1074 : 0 : return -ENOMEM;
1075 : : }
1076 : :
1077 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
1078 : 0 : msg->size = msg_size;
1079 : :
1080 : : /* COOKIE is 0 so that the command is executed as blocking on PSI */
1081 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_GET_IP_VER,
1082 : : ENETC_CMD_ID_GET_IP_MN, 0, 0, 0);
1083 : :
1084 : : /* send the command and wait */
1085 : 0 : err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr);
1086 [ # # ]: 0 : if (err) {
1087 : 0 : ENETC_PMD_ERR("VSI message send error");
1088 : 0 : goto end;
1089 : : }
1090 : :
1091 : : /*
1092 : : * For the IP version command class the class-specific field is
1093 : : * reused to carry the 8-bit version value in the lower byte of the
1094 : : * return code, so parse the full low byte here instead of using the
1095 : : * generic reply parser.
1096 : : */
1097 : 0 : mc = ENETC_SIMSGSR_GET_MC(vsimsgsr);
1098 : 0 : class_id = (mc >> 8) & 0xff;
1099 : :
1100 [ # # ]: 0 : if (class_id != ENETC_CLASS_ID_GET_IP_VER) {
1101 : 0 : ENETC_PMD_ERR("Wrong reply message 0x%x", class_id);
1102 : : err = -EIO;
1103 : 0 : goto end;
1104 : : }
1105 : :
1106 : 0 : *ip_mn = mc & 0xff;
1107 [ # # ]: 0 : if (*ip_mn == ENETC_IP_VER_NOT_AVAILABLE) {
1108 : 0 : ENETC_PMD_DEBUG("IP minor revision not available");
1109 : : err = -ENOTSUP;
1110 : : }
1111 : :
1112 : 0 : end:
1113 : : /* free memory no longer required */
1114 : 0 : rte_free(msg->vaddr);
1115 : 0 : rte_free(msg);
1116 : 0 : return err;
1117 : : }
1118 : :
1119 : : /*
1120 : : * Retrieve the NETC firmware/IP version and format it as
1121 : : * "<major>.<minor>". The IP major revision is taken from the PCI
1122 : : * revision ID register, and the IP minor revision is fetched from the
1123 : : * PSI via VSI-PSI messaging ('Get IP version' command class). This
1124 : : * mirrors the behaviour of the kernel PF/VF drivers, where the PSI only
1125 : : * implements the IP_MN command of the 0xF0 class.
1126 : : */
1127 : : static int
1128 : 0 : enetc4_vf_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
1129 : : {
1130 : 0 : struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(dev, *pci_dev);
1131 : 0 : uint8_t ip_mj = 0, ip_mn = 0;
1132 : : int ret;
1133 : :
1134 : 0 : PMD_INIT_FUNC_TRACE();
1135 : :
1136 [ # # ]: 0 : if (fw_version == NULL)
1137 : : return -EINVAL;
1138 : :
1139 : : /* IP major revision is exposed through the PCI revision ID */
1140 : 0 : ret = rte_pci_read_config(pci_dev, &ip_mj, sizeof(ip_mj),
1141 : : RTE_PCI_REVISION_ID);
1142 [ # # ]: 0 : if (ret != sizeof(ip_mj)) {
1143 : 0 : ENETC_PMD_ERR("Failed to read PCI revision ID");
1144 : 0 : return -EIO;
1145 : : }
1146 : :
1147 : : /* IP minor revision is fetched from the PSI via VSI-PSI messaging.
1148 : : * If the PSI reports the version as unavailable, fall back to a
1149 : : * partial version string so the caller still gets useful output.
1150 : : */
1151 : 0 : ret = enetc4_vf_get_ip_minor_revision(dev, &ip_mn);
1152 [ # # ]: 0 : if (ret && ret != -ENOTSUP) {
1153 : 0 : ENETC_PMD_ERR("Failed to get NETC minor revision");
1154 : 0 : return ret;
1155 : : }
1156 : :
1157 [ # # ]: 0 : if (fw_size == 0) {
1158 [ # # ]: 0 : if (ret == -ENOTSUP)
1159 : 0 : return snprintf(NULL, 0, "%u.unknown", ip_mj) + 1;
1160 : : else
1161 : 0 : return snprintf(NULL, 0, "%u.%u", ip_mj, ip_mn) + 1;
1162 : : }
1163 : :
1164 [ # # ]: 0 : if (ret == -ENOTSUP)
1165 : 0 : ret = snprintf(fw_version, fw_size, "%u.unknown", ip_mj);
1166 : : else
1167 : 0 : ret = snprintf(fw_version, fw_size, "%u.%u", ip_mj, ip_mn);
1168 [ # # ]: 0 : if (ret < 0)
1169 : : return -EINVAL;
1170 : :
1171 : 0 : ret += 1; /* add trailing '\0' */
1172 [ # # ]: 0 : if ((size_t)ret > fw_size)
1173 : 0 : return ret;
1174 : :
1175 : : return 0;
1176 : : }
1177 : :
1178 : : /* VF station interface registers dumped by .get_reg */
1179 : : static const uint32_t enetc4_vf_si_regs[] = {
1180 : : ENETC_SIMR, ENETC_SICAPR0, ENETC_SIPMAR0, ENETC_SIPMAR1,
1181 : : ENETC4_SIROCT0, ENETC4_SIRFRM0, ENETC4_SITOCT0, ENETC4_SITFRM0,
1182 : : ENETC4_SITDFCR, ENETC4_SIMSIVR, ENETC4_VSIIER, ENETC4_VSIIDR,
1183 : : ENETC4_VSIMSGSR, ENETC4_VSIMSGRR,
1184 : : };
1185 : :
1186 : : /*
1187 : : * Dump the VF-accessible registers. Only station interface and per-ring
1188 : : * BD ring registers are reachable by a VF; port registers are not.
1189 : : * When info->data is NULL, only the register count and width are
1190 : : * reported so the caller can size its buffer.
1191 : : */
1192 : : static int
1193 : 0 : enetc4_vf_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs)
1194 : : {
1195 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1196 : : struct enetc_hw *enetc_hw = &hw->hw;
1197 : : uint32_t count, addr;
1198 : : uint32_t *buf;
1199 : : uint16_t i, j;
1200 : :
1201 : : count = RTE_DIM(enetc4_vf_si_regs);
1202 : 0 : count += RTE_DIM(enetc4_txbdr_regs) * dev->data->nb_tx_queues;
1203 : 0 : count += RTE_DIM(enetc4_rxbdr_regs) * dev->data->nb_rx_queues;
1204 : :
1205 [ # # ]: 0 : if (regs->data == NULL) {
1206 : 0 : regs->length = count;
1207 : 0 : regs->width = sizeof(uint32_t);
1208 : 0 : return 0;
1209 : : }
1210 : :
1211 [ # # # # ]: 0 : if (regs->length && regs->length < count)
1212 : : return -ENOTSUP;
1213 : :
1214 : : buf = regs->data;
1215 : :
1216 [ # # ]: 0 : for (i = 0; i < RTE_DIM(enetc4_vf_si_regs); i++)
1217 : 0 : *buf++ = enetc_rd(enetc_hw, enetc4_vf_si_regs[i]);
1218 : :
1219 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1220 [ # # ]: 0 : for (j = 0; j < RTE_DIM(enetc4_txbdr_regs); j++) {
1221 : 0 : addr = ENETC_BDR(TX, i, enetc4_txbdr_regs[j]);
1222 : 0 : *buf++ = enetc_rd(enetc_hw, addr);
1223 : : }
1224 : : }
1225 : :
1226 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1227 [ # # ]: 0 : for (j = 0; j < RTE_DIM(enetc4_rxbdr_regs); j++) {
1228 : 0 : addr = ENETC_BDR(RX, i, enetc4_rxbdr_regs[j]);
1229 : 0 : *buf++ = enetc_rd(enetc_hw, addr);
1230 : : }
1231 : : }
1232 : :
1233 : 0 : regs->version = (uint32_t)hw->device_id << 16 | hw->revision_id;
1234 : :
1235 : 0 : return 0;
1236 : : }
1237 : :
1238 : : static int
1239 : 0 : enetc4_vf_link_update_dummy(struct rte_eth_dev *dev __rte_unused,
1240 : : int wait_to_complete __rte_unused)
1241 : : {
1242 : 0 : return 0;
1243 : : }
1244 : :
1245 : : static int
1246 : 0 : enetc4_vf_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
1247 : : {
1248 : : struct enetc_eth_hw *hw =
1249 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1250 : : struct enetc_psi_reply_msg *reply_msg;
1251 : : struct rte_eth_link link;
1252 : : int err;
1253 : :
1254 : 0 : PMD_INIT_FUNC_TRACE();
1255 : 0 : reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
1256 [ # # ]: 0 : if (!reply_msg) {
1257 : 0 : ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
1258 : 0 : return -ENOMEM;
1259 : : }
1260 : :
1261 : : memset(&link, 0, sizeof(struct rte_eth_link));
1262 : :
1263 : 0 : err = enetc4_vf_get_link_status(dev, reply_msg);
1264 [ # # ]: 0 : if (err) {
1265 : 0 : ENETC_PMD_ERR("Failed to get link status");
1266 : 0 : rte_free(reply_msg);
1267 : 0 : return err;
1268 : : }
1269 : :
1270 [ # # ]: 0 : if (reply_msg->class_id == ENETC_CLASS_ID_LINK_STATUS) {
1271 [ # # ]: 0 : if (reply_msg->status & ENETC_LINK_DOWN) {
1272 : : link.link_status = RTE_ETH_LINK_DOWN;
1273 : : /* Link is down: disable congestion mode on all RX rings. */
1274 : 0 : enetc4_vf_set_congestion_mode(dev, false);
1275 : : } else {
1276 : 0 : link.link_status = RTE_ETH_LINK_UP;
1277 : : /* Restore congestion mode from the TX PAUSE bit. */
1278 : 0 : enetc4_vf_set_congestion_mode(dev,
1279 : : !!(reply_msg->status & ENETC_LINK_TX_PAUSE));
1280 : : }
1281 : : } else {
1282 : 0 : ENETC_PMD_ERR("Wrong reply message");
1283 : 0 : rte_free(reply_msg);
1284 : 0 : return -1;
1285 : : }
1286 : :
1287 : 0 : err = enetc4_vf_get_link_speed(dev, reply_msg);
1288 [ # # ]: 0 : if (err) {
1289 : 0 : ENETC_PMD_ERR("Failed to get link speed");
1290 : 0 : rte_free(reply_msg);
1291 : 0 : return err;
1292 : : }
1293 : :
1294 [ # # ]: 0 : if (reply_msg->class_id == ENETC_CLASS_ID_LINK_SPEED) {
1295 : 0 : enetc4_decode_link_speed(reply_msg->status,
1296 : 0 : hw->vf_link_legacy, &link);
1297 : : } else {
1298 : 0 : ENETC_PMD_ERR("Wrong reply message");
1299 : 0 : rte_free(reply_msg);
1300 : 0 : return -1;
1301 : : }
1302 : :
1303 : 0 : link.link_autoneg = 1;
1304 : 0 : rte_eth_linkstatus_set(dev, &link);
1305 : 0 : rte_free(reply_msg);
1306 : :
1307 : 0 : return 0;
1308 : : }
1309 : :
1310 : : static int
1311 : 0 : enetc4_vf_vlan_promisc(struct rte_eth_dev *dev, bool promisc_en)
1312 : : {
1313 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1314 : : struct enetc_msg_cmd_set_vlan_promisc *cmd;
1315 : : struct enetc_msg_swbd *msg;
1316 : : uint32_t msg_size;
1317 : : int err = 0;
1318 : :
1319 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
1320 [ # # ]: 0 : if (!msg) {
1321 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
1322 : : err = -ENOMEM;
1323 : 0 : return err;
1324 : : }
1325 : :
1326 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_vlan_promisc),
1327 : : ENETC_VSI_PSI_MSG_SIZE);
1328 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
1329 [ # # ]: 0 : if (!msg->vaddr) {
1330 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
1331 : 0 : rte_free(msg);
1332 : 0 : return -ENOMEM;
1333 : : }
1334 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
1335 : 0 : msg->size = msg_size;
1336 : :
1337 : 0 : cmd = (struct enetc_msg_cmd_set_vlan_promisc *)msg->vaddr;
1338 : : /* op is based on the result of message format
1339 : : * 1 0
1340 : : * promisc flush
1341 : : */
1342 : :
1343 [ # # ]: 0 : if (promisc_en)
1344 : 0 : cmd->op = ENETC_PROMISC_VLAN_ENABLE;
1345 : : else
1346 : 0 : cmd->op = ENETC_PROMISC_VLAN_DISABLE;
1347 : :
1348 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
1349 : : ENETC_CMD_ID_SET_VLAN_PROMISCUOUS, 0, 0, 0);
1350 : :
1351 : : /* send the command and wait */
1352 : 0 : err = enetc4_msg_vsi_send(hw, msg, NULL);
1353 [ # # ]: 0 : if (err) {
1354 : 0 : ENETC_PMD_ERR("VSI message send error");
1355 : 0 : goto end;
1356 : : }
1357 : :
1358 : 0 : end:
1359 : : /* free memory no longer required */
1360 : 0 : rte_free(msg->vaddr);
1361 : 0 : rte_free(msg);
1362 : 0 : return err;
1363 : : }
1364 : :
1365 : : static int
1366 : 0 : enetc4_vf_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *addr,
1367 : : uint32_t index __rte_unused, uint32_t pool __rte_unused)
1368 : : {
1369 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1370 : : struct enetc_msg_cmd_set_primary_mac *cmd;
1371 : : struct enetc_msg_swbd *msg;
1372 : : struct enetc_psi_reply_msg *reply_msg;
1373 : : uint32_t msg_size;
1374 : : int err = 0;
1375 : 0 : int vsimsgsr_mac_add = 0;
1376 : :
1377 : 0 : PMD_INIT_FUNC_TRACE();
1378 : :
1379 : : if (!rte_is_valid_assigned_ether_addr(addr))
1380 : : return -EINVAL;
1381 : :
1382 : 0 : reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
1383 [ # # ]: 0 : if (!reply_msg) {
1384 : 0 : ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
1385 : 0 : return -ENOMEM;
1386 : : }
1387 : :
1388 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
1389 [ # # ]: 0 : if (!msg) {
1390 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
1391 : : err = -ENOMEM;
1392 : 0 : rte_free(reply_msg);
1393 : 0 : return err;
1394 : : }
1395 : :
1396 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac),
1397 : : ENETC_VSI_PSI_MSG_SIZE);
1398 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
1399 [ # # ]: 0 : if (!msg->vaddr) {
1400 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
1401 : 0 : rte_free(msg);
1402 : 0 : rte_free(reply_msg);
1403 : 0 : return -ENOMEM;
1404 : : }
1405 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
1406 : 0 : msg->size = msg_size;
1407 : 0 : cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr;
1408 : 0 : memcpy(&cmd->addr.addr_bytes, addr, sizeof(struct rte_ether_addr));
1409 : 0 : cmd->count = 1;
1410 : :
1411 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
1412 : : ENETC_MSG_ADD_EXACT_MAC_ENTRIES, 0, 0, 0);
1413 : :
1414 : : /* send the command and wait */
1415 : 0 : err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_mac_add);
1416 [ # # ]: 0 : if (err) {
1417 : 0 : ENETC_PMD_ERR("VSI message send error");
1418 : 0 : goto end;
1419 : : }
1420 : :
1421 [ # # ]: 0 : enetc4_msg_vsi_reply_msg(hw, vsimsgsr_mac_add, reply_msg);
1422 : :
1423 [ # # ]: 0 : if (reply_msg->class_id == ENETC_CLASS_ID_MAC_FILTER) {
1424 [ # # # # ]: 0 : switch (reply_msg->status) {
1425 : 0 : case ENETC_INVALID_MAC_ADDR:
1426 : 0 : ENETC_PMD_ERR("Invalid MAC address");
1427 : : err = -EINVAL;
1428 : : break;
1429 : 0 : case ENETC_DUPLICATE_MAC_ADDR:
1430 : 0 : ENETC_PMD_ERR("Duplicate MAC address");
1431 : : err = -EINVAL;
1432 : : break;
1433 : 0 : case ENETC_MAC_FILTER_NO_RESOURCE:
1434 : 0 : ENETC_PMD_ERR("Not enough exact-match entries available");
1435 : : err = -EINVAL;
1436 : : break;
1437 : : default:
1438 : : err = -EINVAL;
1439 : : break;
1440 : : }
1441 : : }
1442 : :
1443 : : if (err) {
1444 : 0 : ENETC_PMD_ERR("VSI command execute error!");
1445 : 0 : goto end;
1446 : : }
1447 : :
1448 : 0 : end:
1449 : : /* free memory no longer required */
1450 : 0 : rte_free(msg->vaddr);
1451 : 0 : rte_free(reply_msg);
1452 : 0 : rte_free(msg);
1453 : 0 : return err;
1454 : : }
1455 : :
1456 : 0 : static int enetc4_vf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
1457 : : {
1458 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1459 : : struct enetc_msg_vlan_exact_filter *cmd;
1460 : : struct enetc_msg_swbd *msg;
1461 : : struct enetc_psi_reply_msg *reply_msg;
1462 : : uint32_t msg_size;
1463 : : int err = 0;
1464 : 0 : int vsimsgsr_vlan = 0;
1465 : :
1466 : 0 : PMD_INIT_FUNC_TRACE();
1467 : :
1468 : 0 : reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
1469 [ # # ]: 0 : if (!reply_msg) {
1470 : 0 : ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
1471 : 0 : return -ENOMEM;
1472 : : }
1473 : :
1474 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
1475 [ # # ]: 0 : if (!msg) {
1476 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
1477 : : err = -ENOMEM;
1478 : 0 : rte_free(reply_msg);
1479 : 0 : return err;
1480 : : }
1481 : :
1482 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_vlan_exact_filter),
1483 : : ENETC_VSI_PSI_MSG_SIZE);
1484 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
1485 [ # # ]: 0 : if (!msg->vaddr) {
1486 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
1487 : 0 : rte_free(msg);
1488 : 0 : rte_free(reply_msg);
1489 : 0 : return -ENOMEM;
1490 : : }
1491 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
1492 : 0 : msg->size = msg_size;
1493 : 0 : cmd = (struct enetc_msg_vlan_exact_filter *)msg->vaddr;
1494 : 0 : cmd->vlan_count = 1;
1495 : 0 : cmd->vlan_id = vlan_id;
1496 : :
1497 : : /* TPID 2-bit encoding value is taken from the H/W block guide:
1498 : : * 00b Standard C-VLAN 0x8100
1499 : : * 01b Standard S-VLAN 0x88A8
1500 : : * 10b Custom VLAN as defined by CVLANR1[ETYPE]
1501 : : * 11b Custom VLAN as defined by CVLANR2[ETYPE]
1502 : : * Currently Standard C-VLAN is supported. To support others in future.
1503 : : */
1504 : 0 : cmd->tpid = 0;
1505 : :
1506 [ # # ]: 0 : if (on) {
1507 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
1508 : : ENETC_MSG_ADD_EXACT_VLAN_ENTRIES, 0, 0, 0);
1509 : : } else {
1510 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
1511 : : ENETC_MSG_REMOVE_EXACT_VLAN_ENTRIES, 0, 0, 0);
1512 : : }
1513 : :
1514 : : /* send the command and wait */
1515 : 0 : err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_vlan);
1516 [ # # ]: 0 : if (err) {
1517 : 0 : ENETC_PMD_ERR("VSI message send error");
1518 : 0 : goto end;
1519 : : }
1520 : :
1521 [ # # ]: 0 : enetc4_msg_vsi_reply_msg(hw, vsimsgsr_vlan, reply_msg);
1522 : :
1523 [ # # ]: 0 : if (reply_msg->class_id == ENETC_CLASS_ID_VLAN_FILTER) {
1524 [ # # # # : 0 : switch (reply_msg->status) {
# ]
1525 : 0 : case ENETC_INVALID_VLAN_ENTRY:
1526 : 0 : ENETC_PMD_ERR("VLAN entry not valid");
1527 : : err = -EINVAL;
1528 : : break;
1529 : 0 : case ENETC_DUPLICATE_VLAN_ENTRY:
1530 : 0 : ENETC_PMD_ERR("Duplicated VLAN entry");
1531 : : err = -EINVAL;
1532 : : break;
1533 : 0 : case ENETC_VLAN_ENTRY_NOT_FOUND:
1534 : 0 : ENETC_PMD_ERR("VLAN entry not found");
1535 : : err = -EINVAL;
1536 : : break;
1537 : 0 : case ENETC_VLAN_NO_RESOURCE:
1538 : 0 : ENETC_PMD_ERR("Not enough exact-match entries available");
1539 : : err = -EINVAL;
1540 : : break;
1541 : : default:
1542 : : err = -EINVAL;
1543 : : break;
1544 : : }
1545 : : }
1546 : :
1547 : : if (err) {
1548 : 0 : ENETC_PMD_ERR("VSI command execute error!");
1549 : 0 : goto end;
1550 : : }
1551 : :
1552 : 0 : end:
1553 : : /* free memory no longer required */
1554 : 0 : rte_free(msg->vaddr);
1555 : 0 : rte_free(reply_msg);
1556 : 0 : rte_free(msg);
1557 : 0 : return err;
1558 : : }
1559 : :
1560 : 0 : static int enetc4_vf_vlan_offload_set(struct rte_eth_dev *dev, int mask __rte_unused)
1561 : : {
1562 : : int err = 0;
1563 : :
1564 : 0 : PMD_INIT_FUNC_TRACE();
1565 : :
1566 [ # # ]: 0 : if (dev->data->dev_conf.rxmode.offloads) {
1567 : 0 : ENETC_PMD_DEBUG("VLAN filter table entry inserted:"
1568 : : "Disabling VLAN promisc mode");
1569 : 0 : err = enetc4_vf_vlan_promisc(dev, false);
1570 [ # # ]: 0 : if (err) {
1571 : 0 : ENETC_PMD_ERR("Added VLAN filter table entry:"
1572 : : "Failed to disable promiscuous mode");
1573 : 0 : return err;
1574 : : }
1575 : : } else {
1576 : 0 : ENETC_PMD_DEBUG("Enabling VLAN promisc mode");
1577 : 0 : err = enetc4_vf_vlan_promisc(dev, true);
1578 [ # # ]: 0 : if (err) {
1579 : 0 : ENETC_PMD_ERR("Vlan filter table empty:"
1580 : : "Failed to enable promiscuous mode");
1581 : 0 : return err;
1582 : : }
1583 : : }
1584 : :
1585 : : return 0;
1586 : : }
1587 : :
1588 : : /* Configure SI-based VLAN insertion/removal via VSI-PSI mailbox (class 0x24). */
1589 : : static int
1590 : 0 : enetc4_vf_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
1591 : : {
1592 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1593 : : struct enetc_msg_si_vlan_iso *cmd;
1594 : : struct enetc_msg_swbd *msg;
1595 : : struct enetc_psi_reply_msg *reply_msg;
1596 : : uint32_t msg_size;
1597 : : int err = 0;
1598 : 0 : int vsimsgsr_pvid = 0;
1599 : :
1600 : 0 : PMD_INIT_FUNC_TRACE();
1601 : :
1602 [ # # ]: 0 : if (vlan_id > RTE_ETHER_MAX_VLAN_ID) {
1603 : 0 : ENETC_PMD_ERR("Invalid vlan_id = %u > %d", vlan_id,
1604 : : RTE_ETHER_MAX_VLAN_ID);
1605 : 0 : return -EINVAL;
1606 : : }
1607 : :
1608 : 0 : reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
1609 [ # # ]: 0 : if (!reply_msg) {
1610 : 0 : ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
1611 : 0 : return -ENOMEM;
1612 : : }
1613 : :
1614 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
1615 [ # # ]: 0 : if (!msg) {
1616 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
1617 : 0 : rte_free(reply_msg);
1618 : 0 : return -ENOMEM;
1619 : : }
1620 : :
1621 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_si_vlan_iso),
1622 : : ENETC_VSI_PSI_MSG_SIZE);
1623 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
1624 [ # # ]: 0 : if (!msg->vaddr) {
1625 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg body");
1626 : 0 : rte_free(msg);
1627 : 0 : rte_free(reply_msg);
1628 : 0 : return -ENOMEM;
1629 : : }
1630 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
1631 [ # # ]: 0 : if (msg->dma == RTE_BAD_IOVA) {
1632 : 0 : ENETC_PMD_ERR("Failed to get IOVA for SI VLAN isolation msg body");
1633 : 0 : rte_free(msg->vaddr);
1634 : 0 : rte_free(msg);
1635 : 0 : rte_free(reply_msg);
1636 : 0 : return -ENOMEM;
1637 : : }
1638 : 0 : msg->size = msg_size;
1639 : :
1640 : 0 : cmd = (struct enetc_msg_si_vlan_iso *)msg->vaddr;
1641 : :
1642 [ # # ]: 0 : if (on) {
1643 : 0 : cmd->ctrl = (uint8_t)ENETC_SI_VLAN_ISO_E;
1644 : 0 : cmd->pcp_dei_vid_hi = (uint8_t)((vlan_id >> 8) & 0x0f);
1645 : 0 : cmd->vid_lo = (uint8_t)(vlan_id & 0xff);
1646 : 0 : cmd->flags = (uint8_t)(ENETC_SI_VLAN_ISO_SVIE | ENETC_SI_VLAN_ISO_VTE);
1647 : : }
1648 : : /* on=0: all fields zero (rte_zmalloc cleared the buffer) */
1649 : :
1650 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_SI_VLAN_ISO,
1651 : : ENETC_CMD_ID_SET_SI_VLAN_ISO, 0, 0, 0);
1652 : :
1653 : : /* send the command and wait for PSI reply */
1654 : 0 : err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_pvid);
1655 [ # # ]: 0 : if (err) {
1656 : 0 : ENETC_PMD_ERR("VSI message send error for SI VLAN isolation");
1657 : 0 : goto end;
1658 : : }
1659 : :
1660 [ # # ]: 0 : enetc4_msg_vsi_reply_msg(hw, vsimsgsr_pvid, reply_msg);
1661 : :
1662 : : /*
1663 : : * The PSI reports command completion in the reply class_id: a
1664 : : * successful command returns ENETC_MSG_CLASS_ID_CMD_SUCCESS (0x1),
1665 : : * while any other class_id (e.g. CMD_NOT_SUPPORT 0x3) indicates a
1666 : : * failure. The command class value (0x24) is only used in the
1667 : : * outgoing VF-to-PSI header and is never echoed back in the reply,
1668 : : * so treat class_id != CMD_SUCCESS as failure.
1669 : : */
1670 [ # # ]: 0 : if (reply_msg->class_id != ENETC_MSG_CLASS_ID_CMD_SUCCESS) {
1671 : 0 : ENETC_PMD_ERR("SI VLAN isolation command failed: class_id=0x%x status=0x%x",
1672 : : reply_msg->class_id, reply_msg->status);
1673 : : err = -EINVAL;
1674 : : }
1675 : :
1676 : 0 : end:
1677 : 0 : rte_free(msg->vaddr);
1678 : 0 : rte_free(msg);
1679 : 0 : rte_free(reply_msg);
1680 : 0 : return err;
1681 : : }
1682 : :
1683 : : static int
1684 : 0 : enetc4_vf_mtu_set(struct rte_eth_dev *dev __rte_unused, uint16_t mtu __rte_unused)
1685 : : {
1686 : 0 : return 0;
1687 : : }
1688 : :
1689 : : static int
1690 : 0 : enetc4_vf_link_register_notif(struct rte_eth_dev *dev, bool enable)
1691 : : {
1692 : 0 : struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1693 : : struct enetc_msg_swbd *msg;
1694 : : struct rte_eth_link link;
1695 : : uint32_t msg_size;
1696 : : int err = 0;
1697 : : uint8_t cmd;
1698 : :
1699 : 0 : PMD_INIT_FUNC_TRACE();
1700 : : memset(&link, 0, sizeof(struct rte_eth_link));
1701 : 0 : msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
1702 [ # # ]: 0 : if (!msg) {
1703 : 0 : ENETC_PMD_ERR("Failed to alloc msg");
1704 : : err = -ENOMEM;
1705 : 0 : return err;
1706 : : }
1707 : :
1708 : : msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_link_status), ENETC_VSI_PSI_MSG_SIZE);
1709 : 0 : msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
1710 [ # # ]: 0 : if (!msg->vaddr) {
1711 : 0 : ENETC_PMD_ERR("Failed to alloc memory for msg");
1712 : 0 : rte_free(msg);
1713 : 0 : return -ENOMEM;
1714 : : }
1715 : :
1716 : 0 : msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
1717 : 0 : msg->size = msg_size;
1718 [ # # ]: 0 : if (enable)
1719 : : cmd = ENETC_CMD_ID_REGISTER_LINK_NOTIF;
1720 : : else
1721 : : cmd = ENETC_CMD_ID_UNREGISTER_LINK_NOTIF;
1722 : : enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_LINK_STATUS,
1723 : : cmd, 0, 0, 0);
1724 : :
1725 : : /* send the command and wait */
1726 : 0 : err = enetc4_msg_vsi_send(hw, msg, NULL);
1727 [ # # ]: 0 : if (err)
1728 : 0 : ENETC_PMD_ERR("VSI msg error for link status notification");
1729 : :
1730 : : /* free memory no longer required */
1731 : 0 : rte_free(msg->vaddr);
1732 : 0 : rte_free(msg);
1733 : :
1734 : 0 : return err;
1735 : : }
1736 : :
1737 : : /*
1738 : : * The set of PCI devices this driver supports
1739 : : */
1740 : : static const struct rte_pci_id pci_vf_id_enetc4_map[] = {
1741 : : { RTE_PCI_DEVICE(PCI_VENDOR_ID_NXP, ENETC4_DEV_ID_VF) },
1742 : : { .vendor_id = 0, /* sentinel */ },
1743 : : };
1744 : :
1745 : : static int
1746 : 0 : enetc4_vf_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
1747 : : {
1748 : : struct enetc_eth_hw *hw =
1749 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1750 : : struct enetc_hw *enetc_hw = &hw->hw;
1751 : : struct enetc_bdr *rx_ring;
1752 : : uint16_t vec;
1753 : :
1754 [ # # ]: 0 : if (hw->nc_mode)
1755 : : return -ENOTSUP;
1756 : :
1757 [ # # ]: 0 : if (!hw->rxq_intr_en)
1758 : : return -ENOTSUP;
1759 : :
1760 : 0 : vec = queue_id + ENETC4_VF_RX_VEC_BASE;
1761 : 0 : rx_ring = (struct enetc_bdr *)dev->data->rx_queues[queue_id];
1762 : :
1763 : 0 : enetc_wr(enetc_hw, ENETC_SIMSIRRV(queue_id), vec);
1764 : : /*
1765 : : * Do not overwrite RBICR1 when RSC (LRO) is active: the timer
1766 : : * programmed there is the coalesce-hold window and zeroing it
1767 : : * would disable coalescing, flushing every segment individually.
1768 : : */
1769 [ # # ]: 0 : if (!rx_ring->rsc_enable)
1770 : 0 : enetc4_rxbdr_wr(enetc_hw, queue_id, ENETC4_RBICR1, 0);
1771 : 0 : enetc4_rxbdr_wr(enetc_hw, queue_id, ENETC4_RBICR0,
1772 : : ENETC4_RBICR0_ICEN | ENETC4_RBICR0_ICPT(1));
1773 : 0 : enetc_wr(enetc_hw, ENETC_SIRXIDR, BIT(queue_id));
1774 : :
1775 : 0 : enetc4_rxbdr_wr(enetc_hw, queue_id, ENETC_RBIER, ENETC_RBIER_RXTIE);
1776 : :
1777 : 0 : return 0;
1778 : : }
1779 : :
1780 : : static int
1781 : 0 : enetc4_vf_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
1782 : : {
1783 : : struct enetc_eth_hw *hw =
1784 : 0 : ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1785 : : struct enetc_hw *enetc_hw = &hw->hw;
1786 : :
1787 [ # # ]: 0 : if (hw->nc_mode)
1788 : : return -ENOTSUP;
1789 : :
1790 [ # # ]: 0 : if (!hw->rxq_intr_en)
1791 : : return 0;
1792 : :
1793 : 0 : enetc4_rxbdr_wr(enetc_hw, queue_id, ENETC_RBIER, 0);
1794 : 0 : enetc_wr(enetc_hw, ENETC_SIMSIRRV(queue_id), 0);
1795 : :
1796 : 0 : return 0;
1797 : : }
1798 : :
1799 : : /* Features supported by this driver */
1800 : : /* ops table used when VSI messaging is disabled */
1801 : : static const struct eth_dev_ops enetc4_vf_ops_no_vsi_m = {
1802 : : .dev_configure = enetc4_dev_configure,
1803 : : .dev_start = enetc4_vf_dev_start,
1804 : : .dev_stop = enetc4_vf_dev_stop,
1805 : : .dev_close = enetc4_dev_close,
1806 : : .stats_get = enetc4_vf_stats_get,
1807 : : .stats_reset = enetc4_vf_stats_reset,
1808 : : .dev_infos_get = enetc4_vf_dev_infos_get,
1809 : : .get_reg = enetc4_vf_get_regs,
1810 : : .mtu_set = enetc4_vf_mtu_set,
1811 : : .link_update = enetc4_vf_link_update_dummy,
1812 : : .rx_queue_setup = enetc4_rx_queue_setup,
1813 : : .rx_queue_start = enetc4_rx_queue_start,
1814 : : .rx_queue_stop = enetc4_rx_queue_stop,
1815 : : .rx_queue_release = enetc4_rx_queue_release,
1816 : : .rxq_info_get = enetc4_rxq_info_get,
1817 : : .rx_queue_intr_enable = enetc4_vf_rx_queue_intr_enable,
1818 : : .rx_queue_intr_disable = enetc4_vf_rx_queue_intr_disable,
1819 : : .tx_queue_setup = enetc4_tx_queue_setup,
1820 : : .tx_queue_start = enetc4_tx_queue_start,
1821 : : .tx_queue_stop = enetc4_tx_queue_stop,
1822 : : .tx_queue_release = enetc4_tx_queue_release,
1823 : : .txq_info_get = enetc4_txq_info_get,
1824 : : .dev_supported_ptypes_get = enetc4_supported_ptypes_get,
1825 : : };
1826 : :
1827 : : static const struct eth_dev_ops enetc4_vf_ops = {
1828 : : .dev_configure = enetc4_dev_configure,
1829 : : .dev_start = enetc4_vf_dev_start,
1830 : : .dev_stop = enetc4_vf_dev_stop,
1831 : : .dev_close = enetc4_dev_close,
1832 : : .stats_get = enetc4_vf_stats_get,
1833 : : .stats_reset = enetc4_vf_stats_reset,
1834 : : .dev_infos_get = enetc4_vf_dev_infos_get,
1835 : : .fw_version_get = enetc4_vf_fw_version_get,
1836 : : .get_reg = enetc4_vf_get_regs,
1837 : : .mtu_set = enetc4_vf_mtu_set,
1838 : : .mac_addr_set = enetc4_vf_set_mac_addr,
1839 : : .mac_addr_add = enetc4_vf_mac_addr_add,
1840 : : .promiscuous_enable = enetc4_vf_promisc_enable,
1841 : : .promiscuous_disable = enetc4_vf_promisc_disable,
1842 : : .allmulticast_enable = enetc4_vf_multicast_enable,
1843 : : .allmulticast_disable = enetc4_vf_multicast_disable,
1844 : : .link_update = enetc4_vf_link_update,
1845 : : .vlan_filter_set = enetc4_vf_vlan_filter_set,
1846 : : .vlan_offload_set = enetc4_vf_vlan_offload_set,
1847 : : .vlan_pvid_set = enetc4_vf_vlan_pvid_set,
1848 : : .rx_queue_setup = enetc4_rx_queue_setup,
1849 : : .rx_queue_start = enetc4_rx_queue_start,
1850 : : .rx_queue_stop = enetc4_rx_queue_stop,
1851 : : .rx_queue_release = enetc4_rx_queue_release,
1852 : : .rxq_info_get = enetc4_rxq_info_get,
1853 : : .rx_queue_intr_enable = enetc4_vf_rx_queue_intr_enable,
1854 : : .rx_queue_intr_disable = enetc4_vf_rx_queue_intr_disable,
1855 : : .tx_queue_setup = enetc4_tx_queue_setup,
1856 : : .tx_queue_start = enetc4_tx_queue_start,
1857 : : .tx_queue_stop = enetc4_tx_queue_stop,
1858 : : .tx_queue_release = enetc4_tx_queue_release,
1859 : : .txq_info_get = enetc4_txq_info_get,
1860 : : .dev_supported_ptypes_get = enetc4_supported_ptypes_get,
1861 : : };
1862 : :
1863 : : static int
1864 : 0 : enetc4_vf_mac_init(struct enetc_eth_hw *hw, struct rte_eth_dev *eth_dev)
1865 : : {
1866 : 0 : uint32_t *mac = (uint32_t *)hw->mac.addr;
1867 : : struct enetc_hw *enetc_hw = &hw->hw;
1868 : : uint32_t high_mac = 0;
1869 : : uint16_t low_mac = 0;
1870 : : char vf_eth_name[ENETC_ETH_NAMESIZE];
1871 : :
1872 : 0 : PMD_INIT_FUNC_TRACE();
1873 : :
1874 : : /* Enabling Station Interface */
1875 : 0 : enetc4_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN);
1876 : 0 : *mac = (uint32_t)enetc_rd(enetc_hw, ENETC_SIPMAR0);
1877 : : high_mac = (uint32_t)*mac;
1878 : : mac++;
1879 : 0 : *mac = (uint16_t)enetc_rd(enetc_hw, ENETC_SIPMAR1);
1880 : : low_mac = (uint16_t)*mac;
1881 : :
1882 [ # # ]: 0 : if ((high_mac | low_mac) == 0) {
1883 : : char *first_byte;
1884 : 0 : ENETC_PMD_NOTICE("MAC is not available for this SI, "
1885 : : "set random MAC");
1886 : : mac = (uint32_t *)hw->mac.addr;
1887 : 0 : *mac = (uint32_t)rte_rand();
1888 : : first_byte = (char *)mac;
1889 : 0 : *first_byte &= 0xfe; /* clear multicast bit */
1890 : 0 : *first_byte |= 0x02; /* set local assignment bit (IEEE802) */
1891 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PMAR0, *mac);
1892 : : mac++;
1893 : 0 : *mac = (uint16_t)rte_rand();
1894 : 0 : enetc4_port_wr(enetc_hw, ENETC4_PMAR1, *mac);
1895 : 0 : enetc_print_ethaddr("New address: ",
1896 : : (const struct rte_ether_addr *)hw->mac.addr);
1897 : : }
1898 : :
1899 : : /* Allocate memory for storing MAC addresses */
1900 : 0 : snprintf(vf_eth_name, sizeof(vf_eth_name), "enetc4_vf_eth_%d", eth_dev->data->port_id);
1901 : 0 : eth_dev->data->mac_addrs = rte_zmalloc(vf_eth_name,
1902 : : RTE_ETHER_ADDR_LEN, 0);
1903 [ # # ]: 0 : if (!eth_dev->data->mac_addrs) {
1904 : 0 : ENETC_PMD_ERR("Failed to allocate %d bytes needed to "
1905 : : "store MAC addresses",
1906 : : RTE_ETHER_ADDR_LEN * 1);
1907 : 0 : return -ENOMEM;
1908 : : }
1909 : :
1910 [ # # ]: 0 : if (!enetc_crc_gen)
1911 : 0 : enetc_gen_crc_table();
1912 : :
1913 : : /* Copy the permanent MAC address */
1914 : : rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr,
1915 : : ð_dev->data->mac_addrs[0]);
1916 : :
1917 : 0 : return 0;
1918 : : }
1919 : :
1920 : : static void
1921 : 0 : enetc_vf_enable_mr_int(struct enetc_hw *hw, bool en)
1922 : : {
1923 : : uint32_t val;
1924 : :
1925 : 0 : val = enetc_rd(hw, ENETC4_VSIIER);
1926 : 0 : val &= ~ENETC4_VSIIER_MRIE;
1927 [ # # ]: 0 : val |= (en) ? ENETC4_VSIIER_MRIE : 0;
1928 : 0 : enetc_wr(hw, ENETC4_VSIIER, val);
1929 : 0 : ENETC_PMD_DEBUG("Interrupt enable status (VSIIER) = 0x%x", val);
1930 : 0 : }
1931 : :
1932 : : static void
1933 : 0 : enetc4_dev_interrupt_handler(void *param)
1934 : : {
1935 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)param;
1936 : : struct enetc_eth_hw *hw =
1937 : 0 : ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1938 : 0 : struct enetc_hw *enetc_hw = &hw->hw;
1939 : : uint32_t status;
1940 : :
1941 : : /* Disable interrupts before process */
1942 : 0 : enetc_vf_enable_mr_int(enetc_hw, false);
1943 : :
1944 : 0 : status = enetc_rd(enetc_hw, ENETC4_VSIIDR);
1945 : 0 : ENETC_PMD_DEBUG("Got INTR VSIIDR status = 0x%0x", status);
1946 : : /* Check for PSI to VSI message interrupt */
1947 [ # # ]: 0 : if (!(status & ENETC4_VSIIER_MRIE)) {
1948 : 0 : ENETC_PMD_ERR("Interrupt is not PSI to VSI");
1949 : 0 : goto intr_clear;
1950 : : }
1951 : :
1952 : 0 : enetc4_process_psi_msg(eth_dev, enetc_hw);
1953 : 0 : intr_clear:
1954 : : /* Clear Interrupts */
1955 : 0 : enetc_wr(enetc_hw, ENETC4_VSIIDR, 0xffffffff);
1956 : 0 : enetc_vf_enable_mr_int(enetc_hw, true);
1957 : 0 : }
1958 : :
1959 : : static int
1960 : 0 : enetc4_vf_dev_init(struct rte_eth_dev *eth_dev)
1961 : : {
1962 : 0 : struct enetc_eth_hw *hw =
1963 : 0 : ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
1964 : 0 : struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
1965 : : int error = 0;
1966 : : uint32_t si_cap;
1967 : : struct enetc_hw *enetc_hw = &hw->hw;
1968 : : pthread_mutexattr_t attr;
1969 : :
1970 : 0 : PMD_INIT_FUNC_TRACE();
1971 : :
1972 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
1973 : 0 : eth_dev->dev_ops = &enetc4_vf_ops;
1974 : : /*
1975 : : * Secondary process: set the fast-path burst pointers here or
1976 : : * rte_eth_rx_burst()/rte_eth_tx_burst() would dereference NULL.
1977 : : * hw->nc_mode lives in the shared dev_private and has already
1978 : : * been set by the primary, so honour it to match the base BD
1979 : : * ring layout. The RSC (LRO) and LSO (TSO) bursts use doubled
1980 : : * 32B descriptor rings that the primary selects only at queue
1981 : : * setup; the secondary cannot observe that choice, so it always
1982 : : * uses the base (nc or cacheable) burst. Running the Rx/Tx
1983 : : * datapath from a secondary is therefore not supported when LRO
1984 : : * or TSO is enabled (see the ENETC4 NIC guide).
1985 : : */
1986 [ # # ]: 0 : if (hw->nc_mode) {
1987 : 0 : eth_dev->rx_pkt_burst = &enetc_recv_pkts_nc;
1988 : 0 : eth_dev->tx_pkt_burst = &enetc_xmit_pkts_nc;
1989 : : } else {
1990 : 0 : eth_dev->rx_pkt_burst = &enetc_recv_pkts_cacheable;
1991 : 0 : eth_dev->tx_pkt_burst = &enetc_xmit_pkts_cacheable;
1992 : : }
1993 : 0 : return 0;
1994 : : }
1995 : :
1996 : : /* check if VSI messaging should be disabled via devarg */
1997 [ # # ]: 0 : if (eth_dev->device->devargs) {
1998 : : struct rte_kvargs *kvlist;
1999 : :
2000 : 0 : kvlist = rte_kvargs_parse(eth_dev->device->devargs->args,
2001 : : NULL);
2002 [ # # ]: 0 : if (kvlist) {
2003 : : const char *val;
2004 : :
2005 [ # # ]: 0 : if (rte_kvargs_count(kvlist, ENETC4_VSI_DISABLE) != 0) {
2006 : 0 : ENETC_PMD_NOTICE("VSI messaging disabled by devarg");
2007 : 0 : eth_dev->dev_ops = &enetc4_vf_ops_no_vsi_m;
2008 : : } else {
2009 : 0 : eth_dev->dev_ops = &enetc4_vf_ops;
2010 : : }
2011 : :
2012 : : /* parse optional VSI-PSI timeout devarg */
2013 : 0 : val = rte_kvargs_get(kvlist, ENETC4_VSI_TIMEOUT);
2014 [ # # ]: 0 : if (val) {
2015 : 0 : errno = 0;
2016 : 0 : hw->vsi_timeout = (uint32_t)strtoul(val, NULL, 0);
2017 [ # # # # ]: 0 : if (errno != 0 || hw->vsi_timeout == 0) {
2018 : 0 : ENETC_PMD_ERR("Invalid VSI Timeout value = %u",
2019 : : hw->vsi_timeout);
2020 : 0 : rte_kvargs_free(kvlist);
2021 : 0 : return -1;
2022 : : }
2023 : 0 : ENETC_PMD_NOTICE("VSI timeout set to %u", hw->vsi_timeout);
2024 : : }
2025 : :
2026 : : /* parse optional VSI-PSI delay devarg */
2027 : 0 : val = rte_kvargs_get(kvlist, ENETC4_VSI_DELAY);
2028 [ # # ]: 0 : if (val) {
2029 : 0 : errno = 0;
2030 : 0 : hw->vsi_delay = (uint32_t)strtoul(val, NULL, 0);
2031 [ # # # # ]: 0 : if (errno != 0 || hw->vsi_delay == 0) {
2032 : 0 : ENETC_PMD_ERR("Invalid VSI Delay value = %u",
2033 : : hw->vsi_delay);
2034 : 0 : rte_kvargs_free(kvlist);
2035 : 0 : return -1;
2036 : : }
2037 : 0 : ENETC_PMD_NOTICE("VSI delay set to %u us", hw->vsi_delay);
2038 : : }
2039 : :
2040 : 0 : rte_kvargs_free(kvlist);
2041 : : } else {
2042 : 0 : eth_dev->dev_ops = &enetc4_vf_ops;
2043 : : }
2044 : : } else {
2045 : 0 : eth_dev->dev_ops = &enetc4_vf_ops;
2046 : : }
2047 : :
2048 : 0 : enetc4_dev_hw_init(eth_dev);
2049 : :
2050 : 0 : pthread_mutexattr_init(&attr);
2051 : 0 : pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
2052 : 0 : pthread_mutex_init(&hw->vsi_lock, &attr);
2053 : 0 : pthread_mutexattr_destroy(&attr);
2054 : :
2055 : 0 : hw->nc_mode = 0;
2056 : 0 : enetc4_vf_get_devarg_nc(eth_dev);
2057 [ # # ]: 0 : if (hw->nc_mode) {
2058 : 0 : eth_dev->rx_pkt_burst = &enetc_recv_pkts_nc;
2059 : 0 : eth_dev->tx_pkt_burst = &enetc_xmit_pkts_nc;
2060 : 0 : ENETC_PMD_LOG(INFO, "nc=1: using non-cacheable BD ops (_nc)");
2061 : : }
2062 : :
2063 : 0 : si_cap = enetc_rd(enetc_hw, ENETC_SICAPR0);
2064 : 0 : hw->max_tx_queues = si_cap & ENETC_SICAPR0_BDR_MASK;
2065 : 0 : hw->max_rx_queues = (si_cap >> 16) & ENETC_SICAPR0_BDR_MASK;
2066 : :
2067 : 0 : ENETC_PMD_DEBUG("Max RX queues = %d Max TX queues = %d",
2068 : : hw->max_rx_queues, hw->max_tx_queues);
2069 : 0 : error = enetc4_vf_mac_init(hw, eth_dev);
2070 [ # # ]: 0 : if (error != 0) {
2071 : 0 : ENETC_PMD_ERR("MAC initialization failed!!");
2072 : 0 : return -1;
2073 : : }
2074 : :
2075 [ # # ]: 0 : if (rte_eal_iova_mode() == RTE_IOVA_PA)
2076 : 0 : dpaax_iova_table_populate();
2077 : :
2078 : : /* Parse VF specific devargs (e.g. vf_link_legacy) before the first
2079 : : * link update so that PF-to-VF link messages are interpreted using
2080 : : * the correct (legacy or current) layout.
2081 : : */
2082 : 0 : enetc4_vf_get_devargs(eth_dev);
2083 : :
2084 : 0 : ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
2085 : : eth_dev->data->port_id, pci_dev->id.vendor_id,
2086 : : pci_dev->id.device_id);
2087 : : /* update link if VSI messaging is enabled */
2088 [ # # ]: 0 : if (eth_dev->dev_ops == &enetc4_vf_ops)
2089 : 0 : enetc4_vf_link_update(eth_dev, 0);
2090 : :
2091 : : return 0;
2092 : : }
2093 : :
2094 : : static int
2095 : 0 : enetc4_vf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
2096 : : struct rte_pci_device *pci_dev)
2097 : : {
2098 : 0 : return rte_eth_dev_pci_generic_probe(pci_dev,
2099 : : sizeof(struct enetc_eth_adapter),
2100 : : enetc4_vf_dev_init);
2101 : : }
2102 : :
2103 : : int
2104 : 0 : enetc4_vf_dev_intr(struct rte_eth_dev *eth_dev, bool enable)
2105 : : {
2106 : : struct enetc_eth_hw *hw =
2107 : 0 : ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
2108 : 0 : struct enetc_hw *enetc_hw = &hw->hw;
2109 : 0 : struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
2110 : 0 : struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
2111 : : int ret = 0;
2112 : :
2113 : 0 : PMD_INIT_FUNC_TRACE();
2114 [ # # # # ]: 0 : if (!(intr_handle && rte_intr_fd_get(intr_handle))) {
2115 : 0 : ENETC_PMD_ERR("No INTR handle");
2116 : 0 : return -1;
2117 : : }
2118 [ # # ]: 0 : if (enable) {
2119 : : /* if the interrupts were configured on this devices*/
2120 : 0 : ret = rte_intr_callback_register(intr_handle,
2121 : : enetc4_dev_interrupt_handler, eth_dev);
2122 [ # # ]: 0 : if (ret) {
2123 : 0 : ENETC_PMD_ERR("Failed to register INTR callback %d", ret);
2124 : 0 : return ret;
2125 : : }
2126 : : /* set one IRQ entry for PSI-to-VSI messaging */
2127 : : /* Vector index 0 */
2128 : 0 : enetc_wr(enetc_hw, ENETC4_SIMSIVR, ENETC4_SI_INT_IDX);
2129 : :
2130 [ # # ]: 0 : if (rte_intr_cap_multiple(intr_handle) &&
2131 [ # # ]: 0 : eth_dev->data->nb_rx_queues > 0) {
2132 : : uint16_t nb_rx = eth_dev->data->nb_rx_queues;
2133 : : uint16_t i;
2134 : :
2135 : 0 : ret = rte_intr_efd_enable(intr_handle,
2136 : 0 : nb_rx + ENETC4_VF_RX_VEC_BASE);
2137 [ # # ]: 0 : if (ret) {
2138 : 0 : ENETC_PMD_WARN("Failed to enable per-queue Rx eventfds: %d",
2139 : : ret);
2140 : 0 : hw->rxq_intr_en = 0;
2141 : : } else {
2142 : 0 : ret = rte_intr_vec_list_alloc(intr_handle,
2143 : : "enetc4_vf_rx_intr", nb_rx);
2144 [ # # ]: 0 : if (ret) {
2145 : 0 : ENETC_PMD_WARN("Failed to alloc intr vec list: %d",
2146 : : ret);
2147 : 0 : rte_intr_efd_disable(intr_handle);
2148 : 0 : hw->rxq_intr_en = 0;
2149 : : } else {
2150 [ # # ]: 0 : for (i = 0; i < nb_rx; i++)
2151 : 0 : rte_intr_vec_list_index_set(intr_handle, i,
2152 : : i + ENETC4_VF_RX_VEC_BASE);
2153 : 0 : hw->rxq_intr_en = 1;
2154 : : }
2155 : : }
2156 : : }
2157 : :
2158 : : /* enable uio/vfio intr/eventfd mapping */
2159 : 0 : ret = rte_intr_enable(intr_handle);
2160 [ # # ]: 0 : if (ret) {
2161 : 0 : ENETC_PMD_ERR("Failed to enable INTR %d", ret);
2162 : 0 : goto intr_enable_fail;
2163 : : }
2164 : :
2165 : : /* Enable message received interrupt */
2166 : 0 : enetc_vf_enable_mr_int(enetc_hw, true);
2167 : 0 : ret = enetc4_vf_link_register_notif(eth_dev, true);
2168 [ # # ]: 0 : if (ret) {
2169 : 0 : ENETC_PMD_ERR("Failed to register link notifications %d", ret);
2170 : 0 : goto disable;
2171 : : }
2172 : :
2173 : : return ret;
2174 : : }
2175 : :
2176 : 0 : ret = enetc4_vf_link_register_notif(eth_dev, false);
2177 [ # # ]: 0 : if (ret)
2178 : 0 : ENETC_PMD_WARN("Failed to un-register link notification %d", ret);
2179 : 0 : disable:
2180 : 0 : enetc_vf_enable_mr_int(enetc_hw, false);
2181 : 0 : hw->rxq_intr_en = 0;
2182 : 0 : ret = rte_intr_disable(intr_handle);
2183 [ # # ]: 0 : if (ret)
2184 : 0 : ENETC_PMD_WARN("Failed to disable INTR %d", ret);
2185 : 0 : intr_enable_fail:
2186 : 0 : rte_intr_vec_list_free(intr_handle);
2187 : 0 : rte_intr_efd_disable(intr_handle);
2188 : 0 : ret = rte_intr_callback_unregister(intr_handle,
2189 : : enetc4_dev_interrupt_handler, eth_dev);
2190 [ # # ]: 0 : if (ret < 0)
2191 : 0 : ENETC_PMD_WARN("Failed to unregister intr callback: %d", ret);
2192 : :
2193 : : return ret;
2194 : : }
2195 : :
2196 : : static struct rte_pci_driver rte_enetc4_vf_pmd = {
2197 : : .id_table = pci_vf_id_enetc4_map,
2198 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
2199 : : .probe = enetc4_vf_pci_probe,
2200 : : .remove = enetc4_pci_remove,
2201 : : };
2202 : :
2203 : 302 : RTE_PMD_REGISTER_PCI(net_enetc4_vf, rte_enetc4_vf_pmd);
2204 : : RTE_PMD_REGISTER_PCI_TABLE(net_enetc4_vf, pci_vf_id_enetc4_map);
2205 : : RTE_PMD_REGISTER_KMOD_DEP(net_enetc4_vf, "* igb_uio | uio_pci_generic | vfio-pci");
2206 : : RTE_PMD_REGISTER_PARAM_STRING(net_enetc4_vf,
2207 : : ENETC4_VSI_DISABLE "=<any> "
2208 : : ENETC4_VSI_TIMEOUT "=<uint> "
2209 : : ENETC4_VSI_DELAY "=<uint> "
2210 : : ENETC4_NC_MEMORY "=<int> "
2211 : : ENETC4_TXQ_PRIORITIES "=<string> "
2212 : : ENETC4_TXQ_WRR "=<string> "
2213 : : ENETC_VF_LINK_LEGACY "=<0|1>");
2214 [ - + ]: 302 : RTE_LOG_REGISTER_DEFAULT(enetc4_vf_logtype_pmd, NOTICE);
|