Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2025 Yunsilicon Technology Co., Ltd.
3 : : */
4 : :
5 : : #include <rte_dev_info.h>
6 : : #include <ethdev_pci.h>
7 : : #include <rte_interrupts.h>
8 : :
9 : : #include "xsc_log.h"
10 : : #include "xsc_defs.h"
11 : : #include "xsc_ethdev.h"
12 : : #include "xsc_rx.h"
13 : : #include "xsc_tx.h"
14 : : #include "xsc_dev.h"
15 : : #include "xsc_cmd.h"
16 : :
17 : : static int
18 : 0 : xsc_ethdev_rss_hash_conf_get(struct rte_eth_dev *dev,
19 : : struct rte_eth_rss_conf *rss_conf)
20 : : {
21 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
22 : :
23 [ # # # # ]: 0 : if (rss_conf->rss_key != NULL && rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)
24 : 0 : memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, priv->rss_conf.rss_key_len);
25 : :
26 : 0 : rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
27 : 0 : rss_conf->rss_hf = priv->rss_conf.rss_hf;
28 : 0 : return 0;
29 : : }
30 : :
31 : : static int
32 : 0 : xsc_ethdev_rss_hash_update(struct rte_eth_dev *dev,
33 : : struct rte_eth_rss_conf *rss_conf)
34 : : {
35 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
36 : : int ret = 0;
37 : :
38 : 0 : ret = xsc_dev_rss_key_modify(priv->xdev, rss_conf->rss_key, rss_conf->rss_key_len);
39 [ # # ]: 0 : if (ret == 0) {
40 : 0 : memcpy(priv->rss_conf.rss_key, rss_conf->rss_key,
41 : 0 : priv->rss_conf.rss_key_len);
42 : 0 : priv->rss_conf.rss_key_len = rss_conf->rss_key_len;
43 : 0 : priv->rss_conf.rss_hf = rss_conf->rss_hf;
44 : : }
45 : :
46 : 0 : return ret;
47 : : }
48 : :
49 : : static int
50 : 0 : xsc_ethdev_configure(struct rte_eth_dev *dev)
51 : : {
52 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
53 : : int ret;
54 : : struct rte_eth_rss_conf *rss_conf;
55 : :
56 : 0 : priv->num_sq = dev->data->nb_tx_queues;
57 : 0 : priv->num_rq = dev->data->nb_rx_queues;
58 : :
59 [ # # ]: 0 : if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
60 : 0 : dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
61 : :
62 [ # # ]: 0 : if (priv->rss_conf.rss_key == NULL) {
63 : 0 : priv->rss_conf.rss_key = rte_zmalloc(NULL, XSC_RSS_HASH_KEY_LEN,
64 : : RTE_CACHE_LINE_SIZE);
65 [ # # ]: 0 : if (priv->rss_conf.rss_key == NULL) {
66 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rss key");
67 : 0 : rte_errno = ENOMEM;
68 : : ret = -rte_errno;
69 : 0 : goto error;
70 : : }
71 : 0 : priv->rss_conf.rss_key_len = XSC_RSS_HASH_KEY_LEN;
72 : : }
73 : :
74 [ # # ]: 0 : if (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key != NULL) {
75 : 0 : rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf;
76 : 0 : ret = xsc_ethdev_rss_hash_update(dev, rss_conf);
77 [ # # ]: 0 : if (ret != 0) {
78 : 0 : PMD_DRV_LOG(ERR, "Xsc pmd set rss key error!");
79 : 0 : rte_errno = -ENOEXEC;
80 : 0 : goto error;
81 : : }
82 : : }
83 : :
84 : 0 : priv->txqs = (void *)dev->data->tx_queues;
85 : 0 : priv->rxqs = (void *)dev->data->rx_queues;
86 : 0 : return 0;
87 : :
88 : 0 : error:
89 : 0 : return -rte_errno;
90 : : }
91 : :
92 : : static void
93 : 0 : xsc_ethdev_txq_release(struct rte_eth_dev *dev, uint16_t idx)
94 : : {
95 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
96 [ # # ]: 0 : struct xsc_txq_data *txq_data = xsc_txq_get(priv, idx);
97 : 0 : uint8_t txq_state = dev->data->tx_queue_state[idx];
98 : :
99 [ # # ]: 0 : if (txq_data == NULL || txq_state == RTE_ETH_QUEUE_STATE_STOPPED)
100 : : return;
101 : :
102 : 0 : xsc_dev_set_qpsetid(priv->xdev, txq_data->qpn, 0);
103 : 0 : xsc_txq_obj_release(priv->xdev, txq_data);
104 : 0 : rte_free(txq_data->fcqs);
105 : 0 : txq_data->fcqs = NULL;
106 : 0 : xsc_txq_elts_free(txq_data);
107 : :
108 : 0 : dev->data->tx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED;
109 : : }
110 : :
111 : : static void
112 : 0 : xsc_ethdev_rxq_release(struct rte_eth_dev *dev, uint16_t idx)
113 : : {
114 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
115 [ # # ]: 0 : struct xsc_rxq_data *rxq_data = xsc_rxq_get(priv, idx);
116 : 0 : uint8_t rxq_state = dev->data->rx_queue_state[idx];
117 : :
118 [ # # ]: 0 : if (rxq_data == NULL || rxq_state == RTE_ETH_QUEUE_STATE_STOPPED)
119 : : return;
120 : :
121 : 0 : xsc_rxq_rss_obj_release(priv->xdev, rxq_data);
122 : 0 : xsc_rxq_elts_free(rxq_data);
123 : :
124 : 0 : dev->data->rx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED;
125 : : }
126 : :
127 : : static int
128 : 0 : xsc_ethdev_enable(struct rte_eth_dev *dev)
129 : : {
130 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
131 : : struct xsc_hwinfo *hwinfo;
132 : : int peer_dstinfo = 0;
133 : : int peer_logicalport = 0;
134 : : int logical_port = 0;
135 : : int local_dstinfo = 0;
136 : : int pcie_logic_port = 0;
137 : : int qp_set_id;
138 : : int repr_id;
139 : : struct xsc_rxq_data *rxq;
140 : : uint16_t rx_qpn;
141 : : int i, vld;
142 : : struct xsc_txq_data *txq;
143 : : struct xsc_repr_port *repr;
144 : : struct xsc_repr_info *repr_info;
145 : 0 : uint8_t mac_filter_en = !dev->data->promiscuous;
146 : :
147 [ # # ]: 0 : if (priv->funcid_type != XSC_PHYPORT_MAC_FUNCID)
148 : : return -ENODEV;
149 : :
150 : : rxq = xsc_rxq_get(priv, 0);
151 : : if (rxq == NULL)
152 : : return -EINVAL;
153 : :
154 : 0 : rx_qpn = (uint16_t)rxq->qpn;
155 : 0 : hwinfo = &priv->xdev->hwinfo;
156 : 0 : repr_id = priv->representor_id;
157 : 0 : repr = &priv->xdev->repr_ports[repr_id];
158 : : repr_info = &repr->info;
159 : :
160 : 0 : qp_set_id = xsc_dev_qp_set_id_get(priv->xdev, repr_id);
161 : 0 : logical_port = repr_info->logical_port;
162 : 0 : local_dstinfo = repr_info->local_dstinfo;
163 : 0 : peer_logicalport = repr_info->peer_logical_port;
164 : 0 : peer_dstinfo = repr_info->peer_dstinfo;
165 : :
166 : 0 : pcie_logic_port = hwinfo->pcie_no + 8;
167 : :
168 [ # # ]: 0 : for (i = 0; i < priv->num_sq; i++) {
169 : : txq = xsc_txq_get(priv, i);
170 : : if (txq == NULL)
171 : : return -EINVAL;
172 : 0 : xsc_dev_modify_qp_status(priv->xdev, txq->qpn, 1, XSC_CMD_OP_RTR2RTS_QP);
173 : 0 : xsc_dev_modify_qp_qostree(priv->xdev, txq->qpn);
174 : 0 : xsc_dev_set_qpsetid(priv->xdev, txq->qpn, qp_set_id);
175 : : }
176 : :
177 [ # # ]: 0 : if (!xsc_dev_is_vf(priv->xdev)) {
178 : 0 : xsc_dev_create_ipat(priv->xdev, logical_port, peer_dstinfo);
179 : 0 : xsc_dev_create_vfos_baselp(priv->xdev);
180 : 0 : xsc_dev_create_epat(priv->xdev, local_dstinfo, pcie_logic_port,
181 : 0 : rx_qpn - hwinfo->raw_rss_qp_id_base,
182 : 0 : priv->num_rq, &priv->rss_conf,
183 : 0 : mac_filter_en, priv->mac[0].addr_bytes);
184 : 0 : xsc_dev_create_pct(priv->xdev, repr_id, logical_port, peer_dstinfo);
185 : 0 : xsc_dev_create_pct(priv->xdev, repr_id, peer_logicalport, local_dstinfo);
186 : : } else {
187 : 0 : vld = xsc_dev_get_ipat_vld(priv->xdev, logical_port);
188 [ # # ]: 0 : if (vld == 0)
189 : 0 : xsc_dev_create_ipat(priv->xdev, logical_port, peer_dstinfo);
190 : 0 : xsc_dev_vf_modify_epat(priv->xdev, local_dstinfo,
191 : 0 : rx_qpn - hwinfo->raw_rss_qp_id_base,
192 : 0 : priv->num_rq, &priv->rss_conf,
193 : 0 : mac_filter_en, priv->mac[0].addr_bytes);
194 : : }
195 : :
196 : : return 0;
197 : : }
198 : :
199 : : static void
200 : : xsc_rxq_stop(struct rte_eth_dev *dev)
201 : : {
202 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
203 : : uint16_t i;
204 : :
205 [ # # # # : 0 : for (i = 0; i != priv->num_rq; ++i)
# # ]
206 : 0 : xsc_ethdev_rxq_release(dev, i);
207 : : }
208 : :
209 : : static void
210 : : xsc_txq_stop(struct rte_eth_dev *dev)
211 : : {
212 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
213 : : uint16_t i;
214 : :
215 [ # # # # : 0 : for (i = 0; i != priv->num_sq; ++i)
# # ]
216 : 0 : xsc_ethdev_txq_release(dev, i);
217 : : }
218 : :
219 : : static int
220 : 0 : xsc_txq_start(struct xsc_ethdev_priv *priv)
221 : : {
222 : : struct xsc_txq_data *txq_data;
223 : 0 : struct rte_eth_dev *dev = priv->eth_dev;
224 : : uint16_t i;
225 : : int ret;
226 : : size_t size;
227 : :
228 [ # # ]: 0 : for (i = 0; i != priv->num_sq; ++i) {
229 [ # # ]: 0 : txq_data = xsc_txq_get(priv, i);
230 : : if (txq_data == NULL)
231 : 0 : goto error;
232 : 0 : xsc_txq_elts_alloc(txq_data);
233 : 0 : ret = xsc_txq_obj_new(priv->xdev, txq_data, i);
234 [ # # ]: 0 : if (ret < 0)
235 : 0 : goto error;
236 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
237 : 0 : PMD_DRV_LOG(INFO, "Port %u create tx success", dev->data->port_id);
238 : :
239 : 0 : size = txq_data->cqe_s * sizeof(*txq_data->fcqs);
240 : 0 : txq_data->fcqs = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
241 [ # # ]: 0 : if (!txq_data->fcqs) {
242 : 0 : PMD_DRV_LOG(ERR, "Port %u txq %u alloc fcqs memory failed",
243 : : dev->data->port_id, i);
244 : 0 : rte_errno = ENOMEM;
245 : 0 : goto error;
246 : : }
247 : : }
248 : :
249 : : return 0;
250 : :
251 : 0 : error:
252 : : /* Queue resources are released by xsc_ethdev_start calling the stop interface */
253 : 0 : return -rte_errno;
254 : : }
255 : :
256 : : static int
257 : 0 : xsc_rxq_start(struct xsc_ethdev_priv *priv)
258 : : {
259 : : struct xsc_rxq_data *rxq_data;
260 : : uint16_t i;
261 : : int ret;
262 : :
263 [ # # ]: 0 : for (i = 0; i != priv->num_rq; ++i) {
264 [ # # ]: 0 : rxq_data = xsc_rxq_get(priv, i);
265 : : if (rxq_data == NULL)
266 : 0 : goto error;
267 : 0 : ret = xsc_rxq_elts_alloc(rxq_data);
268 [ # # ]: 0 : if (ret != 0)
269 : 0 : goto error;
270 : : }
271 : :
272 : 0 : ret = xsc_rxq_rss_obj_new(priv, priv->dev_data->port_id);
273 [ # # ]: 0 : if (ret != 0)
274 : 0 : goto error;
275 : :
276 [ # # ]: 0 : for (i = 0; i != priv->num_rq; ++i)
277 : 0 : priv->dev_data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
278 : :
279 : : return 0;
280 : 0 : error:
281 : : /* Queue resources are released by xsc_ethdev_start calling the stop interface */
282 : 0 : return -rte_errno;
283 : : }
284 : :
285 : : static int
286 : 0 : xsc_ethdev_start(struct rte_eth_dev *dev)
287 : : {
288 : : int ret;
289 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
290 : :
291 : 0 : ret = xsc_txq_start(priv);
292 [ # # ]: 0 : if (ret) {
293 : 0 : PMD_DRV_LOG(ERR, "Port %u txq start failed: %s",
294 : : dev->data->port_id, strerror(rte_errno));
295 : 0 : goto error;
296 : : }
297 : :
298 : 0 : ret = xsc_rxq_start(priv);
299 [ # # ]: 0 : if (ret) {
300 : 0 : PMD_DRV_LOG(ERR, "Port %u Rx queue start failed: %s",
301 : : dev->data->port_id, strerror(rte_errno));
302 : 0 : goto error;
303 : : }
304 : :
305 : 0 : dev->data->dev_started = 1;
306 : :
307 : 0 : dev->rx_pkt_burst = xsc_rx_burst;
308 : 0 : dev->tx_pkt_burst = xsc_tx_burst;
309 : :
310 : 0 : ret = xsc_ethdev_enable(dev);
311 [ # # ]: 0 : if (ret) {
312 : 0 : PMD_DRV_LOG(ERR, "Failed to enable port: %u",
313 : : dev->data->port_id);
314 : 0 : goto error;
315 : : }
316 : :
317 : : return 0;
318 : :
319 : 0 : error:
320 : 0 : dev->data->dev_started = 0;
321 : : xsc_txq_stop(dev);
322 : : xsc_rxq_stop(dev);
323 : 0 : return -rte_errno;
324 : : }
325 : :
326 : : static int
327 : 0 : xsc_ethdev_stop(struct rte_eth_dev *dev)
328 : : {
329 : 0 : PMD_DRV_LOG(DEBUG, "Port %u stopping", dev->data->port_id);
330 : 0 : dev->data->dev_started = 0;
331 : 0 : dev->rx_pkt_burst = rte_eth_pkt_burst_dummy;
332 : 0 : dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
333 : : rte_wmb();
334 : :
335 : : xsc_txq_stop(dev);
336 : : xsc_rxq_stop(dev);
337 : :
338 : 0 : return 0;
339 : : }
340 : :
341 : : static int
342 : 0 : xsc_ethdev_close(struct rte_eth_dev *dev)
343 : : {
344 : : int idx;
345 : : struct xsc_rxq_data *rxq_data;
346 : : struct xsc_txq_data *txq_data;
347 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
348 : :
349 : 0 : PMD_DRV_LOG(DEBUG, "Port %u closing", dev->data->port_id);
350 : 0 : dev->rx_pkt_burst = rte_eth_pkt_burst_dummy;
351 : 0 : dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
352 : : rte_wmb();
353 : :
354 : : xsc_txq_stop(dev);
355 : : xsc_rxq_stop(dev);
356 : :
357 [ # # ]: 0 : for (idx = 0; idx < priv->num_rq; idx++) {
358 : : rxq_data = xsc_rxq_get(priv, idx);
359 : 0 : rte_free(rxq_data);
360 : 0 : dev->data->rx_queues[idx] = NULL;
361 : : }
362 : :
363 [ # # ]: 0 : for (idx = 0; idx < priv->num_sq; idx++) {
364 : : txq_data = xsc_txq_get(priv, idx);
365 : 0 : rte_free(txq_data);
366 : 0 : dev->data->tx_queues[idx] = NULL;
367 : : }
368 : :
369 : 0 : priv->rxqs = NULL;
370 : 0 : priv->txqs = NULL;
371 : :
372 : 0 : rte_free(priv->rss_conf.rss_key);
373 [ # # ]: 0 : if (!xsc_dev_is_vf(priv->xdev))
374 : 0 : xsc_dev_intr_handler_uninstall(priv->xdev);
375 : 0 : xsc_dev_close(priv->xdev, priv->representor_id);
376 : 0 : dev->data->mac_addrs = NULL;
377 : 0 : return 0;
378 : : }
379 : :
380 : : static int
381 : 0 : xsc_ethdev_set_link_up(struct rte_eth_dev *dev)
382 : : {
383 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
384 : 0 : struct xsc_dev *xdev = priv->xdev;
385 : :
386 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
387 : : return -ENOTSUP;
388 : 0 : return xsc_dev_link_status_set(xdev, RTE_ETH_LINK_UP);
389 : : }
390 : :
391 : : static int
392 : 0 : xsc_ethdev_set_link_down(struct rte_eth_dev *dev)
393 : : {
394 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
395 : 0 : struct xsc_dev *xdev = priv->xdev;
396 : :
397 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
398 : : return -ENOTSUP;
399 : 0 : return xsc_dev_link_status_set(xdev, RTE_ETH_LINK_DOWN);
400 : : }
401 : :
402 : : static int
403 : 0 : xsc_ethdev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
404 : : {
405 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
406 : 0 : struct xsc_dev *xdev = priv->xdev;
407 : 0 : struct rte_eth_link link = { };
408 : : int ret = 0;
409 : :
410 : : RTE_SET_USED(wait_to_complete);
411 : 0 : ret = xsc_dev_link_get(xdev, &link);
412 [ # # ]: 0 : if (ret != 0)
413 : : return ret;
414 : 0 : rte_eth_linkstatus_set(dev, &link);
415 : :
416 : 0 : return 0;
417 : : }
418 : :
419 : : static uint64_t
420 : : xsc_get_rx_queue_offloads(struct rte_eth_dev *dev)
421 : : {
422 : : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
423 : : struct xsc_dev_config *config = &priv->config;
424 : : uint64_t offloads = 0;
425 : :
426 : 0 : if (config->hw_csum)
427 : : offloads |= (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
428 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
429 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM);
430 : :
431 : : return offloads;
432 : : }
433 : :
434 : : static uint64_t
435 : : xsc_get_tx_port_offloads(struct rte_eth_dev *dev)
436 : : {
437 : : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
438 : : uint64_t offloads = 0;
439 : : struct xsc_dev_config *config = &priv->config;
440 : :
441 : : if (config->hw_csum)
442 : : offloads |= (RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
443 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
444 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM);
445 : 0 : if (config->tso)
446 : 0 : offloads |= RTE_ETH_TX_OFFLOAD_TCP_TSO;
447 : : return offloads;
448 : : }
449 : :
450 : : static int
451 : 0 : xsc_ethdev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
452 : : {
453 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
454 : :
455 : 0 : info->min_rx_bufsize = 64;
456 : 0 : info->max_rx_pktlen = 65536;
457 : 0 : info->max_lro_pkt_size = 0;
458 : 0 : info->max_rx_queues = 256;
459 : 0 : info->max_tx_queues = 1024;
460 : 0 : info->rx_desc_lim.nb_max = 4096;
461 : 0 : info->rx_desc_lim.nb_min = 16;
462 : 0 : info->tx_desc_lim.nb_max = 8192;
463 [ # # ]: 0 : info->tx_desc_lim.nb_min = 128;
464 : :
465 : 0 : info->rx_queue_offload_capa = xsc_get_rx_queue_offloads(dev);
466 [ # # ]: 0 : info->rx_offload_capa = info->rx_queue_offload_capa;
467 : 0 : info->tx_offload_capa = xsc_get_tx_port_offloads(dev);
468 : :
469 : 0 : info->if_index = priv->ifindex;
470 : 0 : info->speed_capa = priv->xdev->link_speed_capa;
471 : 0 : info->hash_key_size = XSC_RSS_HASH_KEY_LEN;
472 : 0 : info->tx_desc_lim.nb_seg_max = 8;
473 : 0 : info->tx_desc_lim.nb_mtu_seg_max = 8;
474 : 0 : info->switch_info.name = dev->data->name;
475 : 0 : info->switch_info.port_id = priv->representor_id;
476 : 0 : return 0;
477 : : }
478 : :
479 : : static int
480 : 0 : xsc_ethdev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
481 : : uint32_t socket, const struct rte_eth_rxconf *conf,
482 : : struct rte_mempool *mp)
483 : : {
484 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
485 : : struct xsc_rxq_data *rxq_data = NULL;
486 : : uint16_t desc_n;
487 : : uint16_t rx_free_thresh;
488 : 0 : uint64_t offloads = conf->offloads | dev->data->dev_conf.rxmode.offloads;
489 : :
490 : 0 : desc = (desc > XSC_MAX_DESC_NUMBER) ? XSC_MAX_DESC_NUMBER : desc;
491 : : desc_n = desc;
492 : :
493 [ # # ]: 0 : if (!rte_is_power_of_2(desc))
494 : 0 : desc_n = 1 << rte_log2_u32(desc);
495 : :
496 : 0 : rxq_data = rte_malloc_socket(NULL, sizeof(*rxq_data) + desc_n * sizeof(struct rte_mbuf *),
497 : : RTE_CACHE_LINE_SIZE, socket);
498 [ # # ]: 0 : if (rxq_data == NULL) {
499 : 0 : PMD_DRV_LOG(ERR, "Port %u create rxq idx %d failure",
500 : : dev->data->port_id, idx);
501 : 0 : rte_errno = ENOMEM;
502 : 0 : return -rte_errno;
503 : : }
504 : 0 : rxq_data->idx = idx;
505 : 0 : rxq_data->priv = priv;
506 : 0 : (*priv->rxqs)[idx] = rxq_data;
507 : :
508 [ # # ]: 0 : rx_free_thresh = (conf->rx_free_thresh) ? conf->rx_free_thresh : XSC_RX_FREE_THRESH;
509 : 0 : rxq_data->rx_free_thresh = rx_free_thresh;
510 : :
511 : 0 : rxq_data->elts = (struct rte_mbuf *(*)[desc_n])(rxq_data + 1);
512 : 0 : rxq_data->mp = mp;
513 : 0 : rxq_data->socket = socket;
514 : :
515 : 0 : rxq_data->csum = !!(offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM);
516 : 0 : rxq_data->hw_timestamp = !!(offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP);
517 : 0 : rxq_data->crc_present = 0;
518 : :
519 : 0 : rxq_data->wqe_n = rte_log2_u32(desc_n);
520 : 0 : rxq_data->wqe_s = desc_n;
521 : 0 : rxq_data->wqe_m = desc_n - 1;
522 : :
523 : 0 : rxq_data->port_id = dev->data->port_id;
524 : 0 : dev->data->rx_queues[idx] = rxq_data;
525 : 0 : return 0;
526 : : }
527 : :
528 : : static int
529 : 0 : xsc_ethdev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
530 : : uint32_t socket, const struct rte_eth_txconf *conf)
531 : : {
532 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
533 : : struct xsc_txq_data *txq;
534 : : uint16_t desc_n;
535 : :
536 : 0 : desc = (desc > XSC_MAX_DESC_NUMBER) ? XSC_MAX_DESC_NUMBER : desc;
537 : : desc_n = desc;
538 : :
539 [ # # ]: 0 : if (!rte_is_power_of_2(desc))
540 : 0 : desc_n = 1 << rte_log2_u32(desc);
541 : :
542 : 0 : txq = rte_malloc_socket(NULL, sizeof(*txq) + desc_n * sizeof(struct rte_mbuf *),
543 : : RTE_CACHE_LINE_SIZE, socket);
544 : 0 : txq->offloads = conf->offloads | dev->data->dev_conf.txmode.offloads;
545 : 0 : txq->priv = priv;
546 : 0 : txq->socket = socket;
547 : :
548 : 0 : txq->elts_n = rte_log2_u32(desc_n);
549 : 0 : txq->elts_s = desc_n;
550 : 0 : txq->elts_m = desc_n - 1;
551 : 0 : txq->port_id = dev->data->port_id;
552 : 0 : txq->idx = idx;
553 : :
554 : 0 : (*priv->txqs)[idx] = txq;
555 : 0 : return 0;
556 : : }
557 : :
558 : : static int
559 : 0 : xsc_ethdev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
560 : : {
561 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
562 : : int ret = 0;
563 : :
564 [ # # ]: 0 : if (priv->eth_type != RTE_ETH_REPRESENTOR_PF) {
565 : 0 : priv->mtu = mtu;
566 : 0 : return 0;
567 : : }
568 : :
569 : 0 : ret = xsc_dev_set_mtu(priv->xdev, mtu);
570 [ # # ]: 0 : if (ret) {
571 : 0 : PMD_DRV_LOG(ERR, "Mtu set to %u failure", mtu);
572 : 0 : return -EAGAIN;
573 : : }
574 : :
575 : 0 : priv->mtu = mtu;
576 : 0 : return 0;
577 : : }
578 : :
579 : : static int
580 : 0 : xsc_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
581 : : {
582 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
583 : 0 : uint32_t rxqs_n = priv->num_rq;
584 : 0 : uint32_t txqs_n = priv->num_sq;
585 : : uint32_t i, idx;
586 : : struct xsc_rxq_data *rxq;
587 : : struct xsc_txq_data *txq;
588 : :
589 [ # # ]: 0 : for (i = 0; i < rxqs_n; ++i) {
590 [ # # ]: 0 : rxq = xsc_rxq_get(priv, i);
591 [ # # ]: 0 : if (unlikely(rxq == NULL))
592 : 0 : continue;
593 : :
594 : 0 : idx = rxq->idx;
595 [ # # ]: 0 : if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
596 : 0 : stats->q_ipackets[idx] += rxq->stats.rx_pkts;
597 : 0 : stats->q_ibytes[idx] += rxq->stats.rx_bytes;
598 : 0 : stats->q_errors[idx] += rxq->stats.rx_errors +
599 : 0 : rxq->stats.rx_nombuf;
600 : : }
601 : 0 : stats->ipackets += rxq->stats.rx_pkts;
602 : 0 : stats->ibytes += rxq->stats.rx_bytes;
603 : 0 : stats->ierrors += rxq->stats.rx_errors;
604 : 0 : stats->rx_nombuf += rxq->stats.rx_nombuf;
605 : : }
606 : :
607 [ # # ]: 0 : for (i = 0; i < txqs_n; ++i) {
608 [ # # ]: 0 : txq = xsc_txq_get(priv, i);
609 [ # # ]: 0 : if (unlikely(txq == NULL))
610 : 0 : continue;
611 : :
612 : 0 : idx = txq->idx;
613 [ # # ]: 0 : if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
614 : 0 : stats->q_opackets[idx] += txq->stats.tx_pkts;
615 : 0 : stats->q_obytes[idx] += txq->stats.tx_bytes;
616 : 0 : stats->q_errors[idx] += txq->stats.tx_errors;
617 : : }
618 : 0 : stats->opackets += txq->stats.tx_pkts;
619 : 0 : stats->obytes += txq->stats.tx_bytes;
620 : 0 : stats->oerrors += txq->stats.tx_errors;
621 : : }
622 : :
623 : 0 : return 0;
624 : : }
625 : :
626 : : static int
627 : 0 : xsc_ethdev_stats_reset(struct rte_eth_dev *dev)
628 : : {
629 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
630 : 0 : uint32_t rxqs_n = priv->num_rq;
631 : 0 : uint32_t txqs_n = priv->num_sq;
632 : : uint32_t i;
633 : : struct xsc_rxq_data *rxq;
634 : : struct xsc_txq_data *txq;
635 : :
636 [ # # ]: 0 : for (i = 0; i < rxqs_n; ++i) {
637 [ # # ]: 0 : rxq = xsc_rxq_get(priv, i);
638 [ # # ]: 0 : if (unlikely(rxq == NULL))
639 : 0 : continue;
640 : 0 : memset(&rxq->stats, 0, sizeof(struct xsc_rxq_stats));
641 : : }
642 [ # # ]: 0 : for (i = 0; i < txqs_n; ++i) {
643 [ # # ]: 0 : txq = xsc_txq_get(priv, i);
644 [ # # ]: 0 : if (unlikely(txq == NULL))
645 : 0 : continue;
646 : 0 : memset(&txq->stats, 0, sizeof(struct xsc_txq_stats));
647 : : }
648 : :
649 : 0 : return 0;
650 : : }
651 : :
652 : : static int
653 : 0 : xsc_ethdev_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, uint32_t index)
654 : : {
655 : : int i;
656 : :
657 : 0 : rte_errno = EINVAL;
658 [ # # ]: 0 : if (index > XSC_MAX_MAC_ADDRESSES)
659 : : return -rte_errno;
660 : :
661 [ # # ]: 0 : if (rte_is_zero_ether_addr(mac))
662 : : return -rte_errno;
663 : :
664 [ # # ]: 0 : for (i = 0; i != XSC_MAX_MAC_ADDRESSES; ++i) {
665 [ # # ]: 0 : if (i == (int)index)
666 : 0 : continue;
667 [ # # ]: 0 : if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac)) != 0)
668 : 0 : continue;
669 : : /* Address already configured elsewhere, return with error */
670 : 0 : rte_errno = EADDRINUSE;
671 : 0 : return -rte_errno;
672 : : }
673 : :
674 : 0 : dev->data->mac_addrs[index] = *mac;
675 : 0 : return 0;
676 : : }
677 : :
678 : : static int
679 : 0 : xsc_set_promiscuous(struct rte_eth_dev *dev, uint8_t mac_filter_en)
680 : : {
681 : : int repr_id;
682 : : struct xsc_repr_port *repr;
683 : : struct xsc_repr_info *repr_info;
684 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
685 : :
686 : 0 : repr_id = priv->representor_id;
687 : 0 : repr = &priv->xdev->repr_ports[repr_id];
688 : : repr_info = &repr->info;
689 : :
690 : 0 : return xsc_dev_modify_epat_mac_filter(priv->xdev,
691 : 0 : repr_info->local_dstinfo,
692 : : mac_filter_en);
693 : : }
694 : :
695 : : static int
696 : 0 : xsc_ethdev_promiscuous_enable(struct rte_eth_dev *dev)
697 : : {
698 : : int ret;
699 : :
700 : 0 : ret = xsc_set_promiscuous(dev, 0);
701 [ # # ]: 0 : if (ret != 0) {
702 : 0 : PMD_DRV_LOG(ERR, "Enable port %u promiscuous failure",
703 : : dev->data->port_id);
704 : 0 : return ret;
705 : : }
706 : :
707 : 0 : dev->data->promiscuous = 1;
708 : 0 : return 0;
709 : : }
710 : :
711 : : static int
712 : 0 : xsc_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
713 : : {
714 : : int ret;
715 : :
716 : 0 : ret = xsc_set_promiscuous(dev, 1);
717 [ # # ]: 0 : if (ret != 0) {
718 : 0 : PMD_DRV_LOG(ERR, "Disable port %u promiscuous failure",
719 : : dev->data->port_id);
720 : 0 : return ret;
721 : : }
722 : :
723 : 0 : dev->data->promiscuous = 0;
724 : 0 : return 0;
725 : : }
726 : :
727 : : static int
728 : 0 : xsc_ethdev_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
729 : : {
730 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
731 : :
732 : 0 : return xsc_dev_fw_version_get(priv->xdev, fw_version, fw_size);
733 : : }
734 : :
735 : : static int
736 : 0 : xsc_ethdev_get_module_info(struct rte_eth_dev *dev,
737 : : struct rte_eth_dev_module_info *modinfo)
738 : : {
739 : : int size_read = 0;
740 : 0 : uint8_t data[4] = { 0 };
741 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
742 : :
743 : 0 : size_read = xsc_dev_query_module_eeprom(priv->xdev, 0, 3, data);
744 [ # # ]: 0 : if (size_read < 3)
745 : : return -1;
746 : :
747 : : /* data[0] = identifier byte */
748 [ # # # # : 0 : switch (data[0]) {
# ]
749 : 0 : case XSC_MODULE_ID_QSFP:
750 : 0 : modinfo->type = RTE_ETH_MODULE_SFF_8436;
751 : 0 : modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8436_MAX_LEN;
752 : 0 : break;
753 : 0 : case XSC_MODULE_ID_QSFP_PLUS:
754 : : case XSC_MODULE_ID_QSFP28:
755 : : /* data[1] = revision id */
756 [ # # # # ]: 0 : if (data[0] == XSC_MODULE_ID_QSFP28 || data[1] >= 0x3) {
757 : 0 : modinfo->type = RTE_ETH_MODULE_SFF_8636;
758 : 0 : modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8636_MAX_LEN;
759 : : } else {
760 : 0 : modinfo->type = RTE_ETH_MODULE_SFF_8436;
761 : 0 : modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8436_MAX_LEN;
762 : : }
763 : : break;
764 : 0 : case XSC_MODULE_ID_SFP:
765 : 0 : modinfo->type = RTE_ETH_MODULE_SFF_8472;
766 : 0 : modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
767 : 0 : break;
768 : 0 : case XSC_MODULE_ID_QSFP_DD:
769 : : case XSC_MODULE_ID_DSFP:
770 : : case XSC_MODULE_ID_QSFP_PLUS_CMIS:
771 : 0 : modinfo->type = RTE_ETH_MODULE_SFF_8636;
772 : : /* Verify if module EEPROM is a flat memory. In case of flat
773 : : * memory only page 00h (0-255 bytes) can be read. Otherwise
774 : : * upper pages 01h and 02h can also be read. Upper pages 10h
775 : : * and 11h are currently not supported by the driver.
776 : : */
777 [ # # ]: 0 : if (data[2] & 0x80)
778 : 0 : modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8636_LEN;
779 : : else
780 : 0 : modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
781 : : break;
782 : 0 : default:
783 : 0 : PMD_DRV_LOG(ERR, "Cable type 0x%x not recognized",
784 : : data[0]);
785 : 0 : return -EINVAL;
786 : : }
787 : :
788 : : return 0;
789 : : }
790 : :
791 : : static int
792 : 0 : xsc_ethdev_get_module_eeprom(struct rte_eth_dev *dev,
793 : : struct rte_dev_eeprom_info *info)
794 : : {
795 : : uint32_t i = 0;
796 : : uint8_t *data;
797 : : int size_read;
798 : 0 : uint32_t offset = info->offset;
799 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
800 : :
801 [ # # ]: 0 : if (info->length == 0) {
802 : 0 : PMD_DRV_LOG(ERR, "Failed to get module eeprom, eeprom length is 0");
803 : 0 : rte_errno = EINVAL;
804 : 0 : return -rte_errno;
805 : : }
806 : :
807 : 0 : data = malloc(info->length);
808 [ # # ]: 0 : if (data == NULL) {
809 : 0 : PMD_DRV_LOG(ERR, "Failed to get module eeprom, cannot allocate memory");
810 : 0 : rte_errno = ENOMEM;
811 : 0 : return -rte_errno;
812 : : }
813 : : memset(data, 0, info->length);
814 : :
815 [ # # ]: 0 : while (i < info->length) {
816 : 0 : size_read = xsc_dev_query_module_eeprom(priv->xdev, offset,
817 : 0 : info->length - i, data + i);
818 [ # # ]: 0 : if (!size_read)
819 : : /* Done reading */
820 : 0 : goto exit;
821 : :
822 [ # # ]: 0 : if (size_read < 0) {
823 : 0 : PMD_DRV_LOG(ERR, "Failed to get module eeprom, size read=%d",
824 : : size_read);
825 : 0 : goto exit;
826 : : }
827 : :
828 : 0 : i += size_read;
829 : 0 : offset += size_read;
830 : : }
831 : :
832 : 0 : memcpy(info->data, data, info->length);
833 : :
834 : 0 : exit:
835 : 0 : free(data);
836 : 0 : return 0;
837 : : }
838 : :
839 : : static int
840 : 0 : xsc_ethdev_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa)
841 : : {
842 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
843 : :
844 : 0 : return xsc_dev_fec_get(priv->xdev, fec_capa);
845 : : }
846 : :
847 : : static int
848 : 0 : xsc_ethdev_fec_set(struct rte_eth_dev *dev, uint32_t mode)
849 : : {
850 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
851 : :
852 : 0 : return xsc_dev_fec_set(priv->xdev, mode);
853 : : }
854 : :
855 : : const struct eth_dev_ops xsc_eth_dev_ops = {
856 : : .dev_configure = xsc_ethdev_configure,
857 : : .dev_start = xsc_ethdev_start,
858 : : .dev_stop = xsc_ethdev_stop,
859 : : .dev_set_link_up = xsc_ethdev_set_link_up,
860 : : .dev_set_link_down = xsc_ethdev_set_link_down,
861 : : .dev_close = xsc_ethdev_close,
862 : : .link_update = xsc_ethdev_link_update,
863 : : .promiscuous_enable = xsc_ethdev_promiscuous_enable,
864 : : .promiscuous_disable = xsc_ethdev_promiscuous_disable,
865 : : .stats_get = xsc_ethdev_stats_get,
866 : : .stats_reset = xsc_ethdev_stats_reset,
867 : : .dev_infos_get = xsc_ethdev_infos_get,
868 : : .rx_queue_setup = xsc_ethdev_rx_queue_setup,
869 : : .tx_queue_setup = xsc_ethdev_tx_queue_setup,
870 : : .rx_queue_release = xsc_ethdev_rxq_release,
871 : : .tx_queue_release = xsc_ethdev_txq_release,
872 : : .mtu_set = xsc_ethdev_set_mtu,
873 : : .rss_hash_update = xsc_ethdev_rss_hash_update,
874 : : .rss_hash_conf_get = xsc_ethdev_rss_hash_conf_get,
875 : : .fw_version_get = xsc_ethdev_fw_version_get,
876 : : .get_module_info = xsc_ethdev_get_module_info,
877 : : .get_module_eeprom = xsc_ethdev_get_module_eeprom,
878 : : .fec_get = xsc_ethdev_fec_get,
879 : : .fec_set = xsc_ethdev_fec_set,
880 : : };
881 : :
882 : : static int
883 : 0 : xsc_ethdev_init_one_representor(struct rte_eth_dev *eth_dev, void *init_params)
884 : : {
885 : : int ret;
886 : : struct xsc_repr_port *repr_port = (struct xsc_repr_port *)init_params;
887 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
888 : : struct xsc_dev_config *config = &priv->config;
889 : 0 : struct rte_ether_addr mac = priv->mac[0];
890 : :
891 : 0 : priv->repr_port = repr_port;
892 : 0 : repr_port->drv_data = eth_dev;
893 : 0 : priv->xdev = repr_port->xdev;
894 : 0 : priv->mtu = RTE_ETHER_MTU;
895 : 0 : priv->funcid_type = (repr_port->info.funcid & XSC_FUNCID_TYPE_MASK) >> 14;
896 : 0 : priv->funcid = repr_port->info.funcid & XSC_FUNCID_MASK;
897 [ # # ]: 0 : if (repr_port->info.port_type == XSC_PORT_TYPE_UPLINK ||
898 : : repr_port->info.port_type == XSC_PORT_TYPE_UPLINK_BOND)
899 : 0 : priv->eth_type = RTE_ETH_REPRESENTOR_PF;
900 : : else
901 : 0 : priv->eth_type = RTE_ETH_REPRESENTOR_VF;
902 : 0 : priv->representor_id = repr_port->info.repr_id;
903 : 0 : priv->dev_data = eth_dev->data;
904 : 0 : priv->ifindex = repr_port->info.ifindex;
905 : :
906 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
907 [ # # ]: 0 : eth_dev->data->mac_addrs = priv->mac;
908 [ # # ]: 0 : if (rte_is_zero_ether_addr(eth_dev->data->mac_addrs)) {
909 : 0 : ret = xsc_dev_get_mac(priv->xdev, mac.addr_bytes);
910 [ # # ]: 0 : if (ret != 0) {
911 : 0 : PMD_DRV_LOG(ERR, "Port %u cannot get MAC address",
912 : : eth_dev->data->port_id);
913 : 0 : return -ENODEV;
914 : : }
915 : : }
916 : :
917 : 0 : xsc_ethdev_mac_addr_add(eth_dev, &mac, 0);
918 : :
919 : 0 : config->hw_csum = 1;
920 : 0 : config->pph_flag = priv->xdev->devargs.pph_mode;
921 [ # # ]: 0 : if ((config->pph_flag & XSC_TX_PPH) != 0) {
922 : 0 : config->tso = 0;
923 : : } else {
924 : 0 : config->tso = 1;
925 : 0 : config->tso_max_payload_sz = 1500;
926 : : }
927 : :
928 : 0 : priv->is_representor = 1;
929 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
930 : 0 : eth_dev->data->representor_id = priv->representor_id;
931 : 0 : eth_dev->data->backer_port_id = eth_dev->data->port_id;
932 : :
933 : 0 : eth_dev->dev_ops = &xsc_eth_dev_ops;
934 : 0 : eth_dev->rx_pkt_burst = rte_eth_pkt_burst_dummy;
935 : 0 : eth_dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
936 : :
937 : 0 : rte_eth_dev_probing_finish(eth_dev);
938 : :
939 : 0 : return 0;
940 : : }
941 : :
942 : : static int
943 : 0 : xsc_ethdev_init_representors(struct rte_eth_dev *eth_dev)
944 : : {
945 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
946 : 0 : struct rte_eth_devargs eth_da = { .nb_representor_ports = 0 };
947 : : struct rte_device *dev;
948 : : struct xsc_dev *xdev;
949 : : struct xsc_repr_port *repr_port;
950 : : char name[RTE_ETH_NAME_MAX_LEN];
951 : : int i;
952 : : int ret;
953 : :
954 : 0 : PMD_INIT_FUNC_TRACE();
955 : :
956 : 0 : dev = &priv->pci_dev->device;
957 [ # # ]: 0 : if (dev->devargs != NULL) {
958 : 0 : ret = rte_eth_devargs_parse(dev->devargs->args, ð_da, 1);
959 [ # # ]: 0 : if (ret < 0) {
960 : 0 : PMD_DRV_LOG(ERR, "Failed to parse device arguments: %s",
961 : : dev->devargs->args);
962 : 0 : return -EINVAL;
963 : : }
964 : : }
965 : :
966 : 0 : xdev = priv->xdev;
967 : 0 : ret = xsc_dev_repr_ports_probe(xdev, eth_da.nb_representor_ports, RTE_MAX_ETHPORTS);
968 [ # # ]: 0 : if (ret != 0) {
969 : 0 : PMD_DRV_LOG(ERR, "Failed to probe %d xsc device representors",
970 : : eth_da.nb_representor_ports);
971 : 0 : return ret;
972 : : }
973 : :
974 : : /* PF rep init */
975 : 0 : repr_port = &xdev->repr_ports[xdev->num_repr_ports - 1];
976 : 0 : ret = xsc_ethdev_init_one_representor(eth_dev, repr_port);
977 [ # # ]: 0 : if (ret != 0) {
978 : 0 : PMD_DRV_LOG(ERR, "Failed to init backing representor");
979 : 0 : return ret;
980 : : }
981 : :
982 : : /* VF rep init */
983 [ # # ]: 0 : for (i = 0; i < eth_da.nb_representor_ports; i++) {
984 : 0 : repr_port = &xdev->repr_ports[i];
985 : 0 : snprintf(name, sizeof(name), "%s_rep_%d",
986 : 0 : xdev->name, repr_port->info.repr_id);
987 : 0 : ret = rte_eth_dev_create(dev,
988 : : name,
989 : : sizeof(struct xsc_ethdev_priv),
990 : : NULL, NULL,
991 : : xsc_ethdev_init_one_representor,
992 : : repr_port);
993 [ # # ]: 0 : if (ret != 0) {
994 : 0 : PMD_DRV_LOG(ERR, "Failed to create representor: %d", i);
995 : 0 : goto destroy_reprs;
996 : : }
997 : : }
998 : :
999 [ # # ]: 0 : if (!xsc_dev_is_vf(priv->xdev)) {
1000 : 0 : ret = xsc_ethdev_set_link_up(eth_dev);
1001 [ # # ]: 0 : if (ret != 0) {
1002 : 0 : PMD_DRV_LOG(ERR, "Failed to set port %u link up", eth_dev->data->port_id);
1003 : 0 : goto destroy_reprs;
1004 : : }
1005 : : }
1006 : :
1007 : : return 0;
1008 : :
1009 : 0 : destroy_reprs:
1010 : : /* Destroy vf reprs */
1011 [ # # ]: 0 : while ((i--) > 1) {
1012 : 0 : repr_port = &xdev->repr_ports[i];
1013 : 0 : rte_eth_dev_destroy((struct rte_eth_dev *)repr_port->drv_data, NULL);
1014 : : }
1015 : :
1016 : : /* Destroy pf repr */
1017 : 0 : repr_port = &xdev->repr_ports[xdev->num_repr_ports - 1];
1018 : 0 : rte_eth_dev_destroy((struct rte_eth_dev *)repr_port->drv_data, NULL);
1019 : 0 : return ret;
1020 : : }
1021 : :
1022 : : static void
1023 : 0 : xsc_ethdev_intr_handler(void *param)
1024 : : {
1025 : : struct rte_eth_dev *eth_dev = param;
1026 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
1027 : : int event_type;
1028 : :
1029 : 0 : event_type = xsc_dev_intr_event_get(priv->xdev);
1030 [ # # ]: 0 : switch (event_type) {
1031 : 0 : case XSC_EVENT_TYPE_CHANGE_LINK:
1032 : 0 : PMD_DRV_LOG(DEBUG, "Get intr event type=%04x", event_type);
1033 : 0 : xsc_ethdev_link_update(eth_dev, 0);
1034 : 0 : rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL);
1035 : 0 : break;
1036 : : default:
1037 : : break;
1038 : : }
1039 : 0 : }
1040 : :
1041 : : static int
1042 : 0 : xsc_ethdev_init(struct rte_eth_dev *eth_dev)
1043 : : {
1044 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
1045 : : int ret;
1046 : :
1047 : 0 : PMD_INIT_FUNC_TRACE();
1048 : :
1049 : 0 : priv->eth_dev = eth_dev;
1050 : 0 : priv->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
1051 : :
1052 : 0 : ret = xsc_dev_init(priv->pci_dev, &priv->xdev);
1053 [ # # ]: 0 : if (ret) {
1054 : 0 : PMD_DRV_LOG(ERR, "Failed to initialize xsc device");
1055 : 0 : return ret;
1056 : : }
1057 : 0 : priv->xdev->port_id = eth_dev->data->port_id;
1058 : :
1059 : 0 : ret = xsc_ethdev_init_representors(eth_dev);
1060 [ # # ]: 0 : if (ret != 0) {
1061 : 0 : PMD_DRV_LOG(ERR, "Failed to initialize representors");
1062 : 0 : goto uninit_xsc_dev;
1063 : : }
1064 : :
1065 [ # # ]: 0 : if (!xsc_dev_is_vf(priv->xdev)) {
1066 : 0 : ret = xsc_dev_intr_handler_install(priv->xdev, xsc_ethdev_intr_handler, eth_dev);
1067 [ # # ]: 0 : if (ret != 0) {
1068 : 0 : PMD_DRV_LOG(ERR, "Failed to install intr handler");
1069 : 0 : goto uninit_xsc_dev;
1070 : : }
1071 : : }
1072 : :
1073 : : return 0;
1074 : :
1075 : 0 : uninit_xsc_dev:
1076 : 0 : xsc_dev_uninit(priv->xdev);
1077 : 0 : return ret;
1078 : : }
1079 : :
1080 : : static int
1081 : 0 : xsc_ethdev_uninit(struct rte_eth_dev *eth_dev)
1082 : : {
1083 : : int ret = 0;
1084 : : uint16_t port_id;
1085 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
1086 : :
1087 : 0 : PMD_INIT_FUNC_TRACE();
1088 [ # # ]: 0 : RTE_ETH_FOREACH_DEV_OF(port_id, eth_dev->device) {
1089 [ # # ]: 0 : if (port_id != eth_dev->data->port_id)
1090 : 0 : ret |= rte_eth_dev_close(port_id);
1091 : : }
1092 : :
1093 : 0 : ret |= xsc_ethdev_close(eth_dev);
1094 : 0 : xsc_dev_pct_uninit(priv->xdev);
1095 : 0 : rte_free(priv->xdev);
1096 : :
1097 [ # # ]: 0 : return ret == 0 ? 0 : -EIO;
1098 : : }
1099 : :
1100 : : static int
1101 : 0 : xsc_ethdev_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
1102 : : struct rte_pci_device *pci_dev)
1103 : : {
1104 : : int ret;
1105 : :
1106 : 0 : PMD_INIT_FUNC_TRACE();
1107 : :
1108 : 0 : ret = rte_eth_dev_pci_generic_probe(pci_dev,
1109 : : sizeof(struct xsc_ethdev_priv),
1110 : : xsc_ethdev_init);
1111 [ # # ]: 0 : if (ret) {
1112 : 0 : PMD_DRV_LOG(ERR, "Failed to probe ethdev: %s", pci_dev->name);
1113 : 0 : return ret;
1114 : : }
1115 : :
1116 : : return 0;
1117 : : }
1118 : :
1119 : : static int
1120 : 0 : xsc_ethdev_pci_remove(struct rte_pci_device *pci_dev)
1121 : : {
1122 : : int ret;
1123 : :
1124 : 0 : PMD_INIT_FUNC_TRACE();
1125 : :
1126 : 0 : ret = rte_eth_dev_pci_generic_remove(pci_dev, xsc_ethdev_uninit);
1127 [ # # ]: 0 : if (ret) {
1128 : 0 : PMD_DRV_LOG(ERR, "Could not remove ethdev: %s", pci_dev->name);
1129 : 0 : return ret;
1130 : : }
1131 : :
1132 : : return 0;
1133 : : }
1134 : :
1135 : : static const struct rte_pci_id xsc_ethdev_pci_id_map[] = {
1136 : : { RTE_PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_PCI_DEV_ID_MS) },
1137 : : { RTE_PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_PCI_DEV_ID_MSVF) },
1138 : : { RTE_PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_PCI_DEV_ID_MVH) },
1139 : : { RTE_PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_PCI_DEV_ID_MVHVF) },
1140 : : { RTE_PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_PCI_DEV_ID_MVS) },
1141 : : { RTE_PCI_DEVICE(0, 0) },
1142 : : };
1143 : :
1144 : : static struct rte_pci_driver xsc_ethdev_pci_driver = {
1145 : : .id_table = xsc_ethdev_pci_id_map,
1146 : : .probe = xsc_ethdev_pci_probe,
1147 : : .remove = xsc_ethdev_pci_remove,
1148 : : };
1149 : :
1150 : 253 : RTE_PMD_REGISTER_PCI(net_xsc, xsc_ethdev_pci_driver);
1151 : : RTE_PMD_REGISTER_PCI_TABLE(net_xsc, xsc_ethdev_pci_id_map);
1152 : : RTE_PMD_REGISTER_PARAM_STRING(net_xsc,
1153 : : XSC_PPH_MODE_ARG "=<x>"
1154 : : XSC_NIC_MODE_ARG "=<x>"
1155 : : XSC_FLOW_MODE_ARG "=<x>");
1156 : :
1157 [ - + ]: 253 : RTE_LOG_REGISTER_SUFFIX(xsc_logtype_init, init, NOTICE);
1158 [ - + ]: 253 : RTE_LOG_REGISTER_SUFFIX(xsc_logtype_driver, driver, NOTICE);
|