Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2025 Yunsilicon Technology Co., Ltd.
3 : : */
4 : :
5 : : #include <ethdev_pci.h>
6 : :
7 : : #include "xsc_log.h"
8 : : #include "xsc_defs.h"
9 : : #include "xsc_ethdev.h"
10 : : #include "xsc_rx.h"
11 : : #include "xsc_tx.h"
12 : : #include "xsc_dev.h"
13 : : #include "xsc_cmd.h"
14 : :
15 : : static int
16 : 0 : xsc_ethdev_rss_hash_conf_get(struct rte_eth_dev *dev,
17 : : struct rte_eth_rss_conf *rss_conf)
18 : : {
19 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
20 : :
21 [ # # # # ]: 0 : if (rss_conf->rss_key != NULL && rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)
22 : 0 : memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, priv->rss_conf.rss_key_len);
23 : :
24 : 0 : rss_conf->rss_key_len = priv->rss_conf.rss_key_len;
25 : 0 : rss_conf->rss_hf = priv->rss_conf.rss_hf;
26 : 0 : return 0;
27 : : }
28 : :
29 : : static int
30 : 0 : xsc_ethdev_rss_hash_update(struct rte_eth_dev *dev,
31 : : struct rte_eth_rss_conf *rss_conf)
32 : : {
33 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
34 : : int ret = 0;
35 : :
36 : 0 : ret = xsc_dev_rss_key_modify(priv->xdev, rss_conf->rss_key, rss_conf->rss_key_len);
37 [ # # ]: 0 : if (ret == 0) {
38 : 0 : memcpy(priv->rss_conf.rss_key, rss_conf->rss_key,
39 : 0 : priv->rss_conf.rss_key_len);
40 : 0 : priv->rss_conf.rss_key_len = rss_conf->rss_key_len;
41 : 0 : priv->rss_conf.rss_hf = rss_conf->rss_hf;
42 : : }
43 : :
44 : 0 : return ret;
45 : : }
46 : :
47 : : static int
48 : 0 : xsc_ethdev_configure(struct rte_eth_dev *dev)
49 : : {
50 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
51 : : int ret;
52 : : struct rte_eth_rss_conf *rss_conf;
53 : :
54 : 0 : priv->num_sq = dev->data->nb_tx_queues;
55 : 0 : priv->num_rq = dev->data->nb_rx_queues;
56 : :
57 [ # # ]: 0 : if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
58 : 0 : dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
59 : :
60 [ # # ]: 0 : if (priv->rss_conf.rss_key == NULL) {
61 : 0 : priv->rss_conf.rss_key = rte_zmalloc(NULL, XSC_RSS_HASH_KEY_LEN,
62 : : RTE_CACHE_LINE_SIZE);
63 [ # # ]: 0 : if (priv->rss_conf.rss_key == NULL) {
64 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rss key");
65 : 0 : rte_errno = ENOMEM;
66 : : ret = -rte_errno;
67 : 0 : goto error;
68 : : }
69 : 0 : priv->rss_conf.rss_key_len = XSC_RSS_HASH_KEY_LEN;
70 : : }
71 : :
72 [ # # ]: 0 : if (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key != NULL) {
73 : 0 : rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf;
74 : 0 : ret = xsc_ethdev_rss_hash_update(dev, rss_conf);
75 [ # # ]: 0 : if (ret != 0) {
76 : 0 : PMD_DRV_LOG(ERR, "Xsc pmd set rss key error!");
77 : 0 : rte_errno = -ENOEXEC;
78 : 0 : goto error;
79 : : }
80 : : }
81 : :
82 : 0 : priv->txqs = (void *)dev->data->tx_queues;
83 : 0 : priv->rxqs = (void *)dev->data->rx_queues;
84 : 0 : return 0;
85 : :
86 : 0 : error:
87 : 0 : return -rte_errno;
88 : : }
89 : :
90 : : static void
91 : 0 : xsc_ethdev_txq_release(struct rte_eth_dev *dev, uint16_t idx)
92 : : {
93 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
94 [ # # ]: 0 : struct xsc_txq_data *txq_data = xsc_txq_get(priv, idx);
95 : :
96 : : if (txq_data == NULL)
97 : : return;
98 : :
99 : 0 : xsc_dev_set_qpsetid(priv->xdev, txq_data->qpn, 0);
100 : 0 : xsc_txq_obj_release(priv->xdev, txq_data);
101 : 0 : rte_free(txq_data->fcqs);
102 : 0 : txq_data->fcqs = NULL;
103 : 0 : xsc_txq_elts_free(txq_data);
104 : 0 : rte_free(txq_data);
105 : 0 : (*priv->txqs)[idx] = NULL;
106 : :
107 : 0 : dev->data->tx_queues[idx] = NULL;
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 : :
117 : : if (rxq_data == NULL)
118 : : return;
119 : 0 : xsc_rxq_rss_obj_release(priv->xdev, rxq_data);
120 : 0 : xsc_rxq_elts_free(rxq_data);
121 : 0 : rte_free(rxq_data);
122 : 0 : (*priv->rxqs)[idx] = NULL;
123 : :
124 : 0 : dev->data->rx_queues[idx] = NULL;
125 : 0 : dev->data->rx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED;
126 : : }
127 : :
128 : : static int
129 : 0 : xsc_ethdev_enable(struct rte_eth_dev *dev)
130 : : {
131 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
132 : : struct xsc_hwinfo *hwinfo;
133 : : int peer_dstinfo = 0;
134 : : int peer_logicalport = 0;
135 : : int logical_port = 0;
136 : : int local_dstinfo = 0;
137 : : int pcie_logic_port = 0;
138 : : int qp_set_id;
139 : : int repr_id;
140 : : struct xsc_rxq_data *rxq;
141 : : uint16_t rx_qpn;
142 : : int i, vld;
143 : : struct xsc_txq_data *txq;
144 : : struct xsc_repr_port *repr;
145 : : struct xsc_repr_info *repr_info;
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 : xsc_dev_create_pct(priv->xdev, repr_id, logical_port, peer_dstinfo);
184 : 0 : xsc_dev_create_pct(priv->xdev, repr_id, peer_logicalport, local_dstinfo);
185 : : } else {
186 : 0 : vld = xsc_dev_get_ipat_vld(priv->xdev, logical_port);
187 [ # # ]: 0 : if (vld == 0)
188 : 0 : xsc_dev_create_ipat(priv->xdev, logical_port, peer_dstinfo);
189 : 0 : xsc_dev_vf_modify_epat(priv->xdev, local_dstinfo,
190 : 0 : rx_qpn - hwinfo->raw_rss_qp_id_base,
191 : 0 : priv->num_rq, &priv->rss_conf);
192 : : }
193 : :
194 : : return 0;
195 : : }
196 : :
197 : : static void
198 : 0 : xsc_rxq_stop(struct rte_eth_dev *dev)
199 : : {
200 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
201 : : uint16_t i;
202 : :
203 [ # # ]: 0 : for (i = 0; i != priv->num_rq; ++i)
204 : 0 : xsc_ethdev_rxq_release(dev, i);
205 : 0 : priv->rxqs = NULL;
206 : 0 : priv->flags &= ~XSC_FLAG_RX_QUEUE_INIT;
207 : 0 : }
208 : :
209 : : static void
210 : 0 : 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 : 0 : priv->txqs = NULL;
218 : 0 : priv->flags &= ~XSC_FLAG_TX_QUEUE_INIT;
219 : 0 : }
220 : :
221 : : static int
222 : 0 : xsc_txq_start(struct xsc_ethdev_priv *priv)
223 : : {
224 : : struct xsc_txq_data *txq_data;
225 : 0 : struct rte_eth_dev *dev = priv->eth_dev;
226 : 0 : uint64_t offloads = dev->data->dev_conf.txmode.offloads;
227 : : uint16_t i;
228 : : int ret;
229 : : size_t size;
230 : :
231 [ # # ]: 0 : if (priv->flags & XSC_FLAG_TX_QUEUE_INIT) {
232 [ # # ]: 0 : for (i = 0; i != priv->num_sq; ++i)
233 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
234 : : return 0;
235 : : }
236 : :
237 [ # # ]: 0 : for (i = 0; i != priv->num_sq; ++i) {
238 [ # # ]: 0 : txq_data = xsc_txq_get(priv, i);
239 : : if (txq_data == NULL)
240 : 0 : goto error;
241 : 0 : xsc_txq_elts_alloc(txq_data);
242 : 0 : ret = xsc_txq_obj_new(priv->xdev, txq_data, offloads, i);
243 [ # # ]: 0 : if (ret < 0)
244 : 0 : goto error;
245 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
246 : 0 : PMD_DRV_LOG(INFO, "Port %u create tx success", dev->data->port_id);
247 : :
248 : 0 : size = txq_data->cqe_s * sizeof(*txq_data->fcqs);
249 : 0 : txq_data->fcqs = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
250 [ # # ]: 0 : if (!txq_data->fcqs) {
251 : 0 : PMD_DRV_LOG(ERR, "Port %u txq %u alloc fcqs memory failed",
252 : : dev->data->port_id, i);
253 : 0 : rte_errno = ENOMEM;
254 : 0 : goto error;
255 : : }
256 : : }
257 : :
258 : 0 : priv->flags |= XSC_FLAG_TX_QUEUE_INIT;
259 : 0 : return 0;
260 : :
261 : 0 : error:
262 : : /* Queue resources are released by xsc_ethdev_start calling the stop interface */
263 : 0 : return -rte_errno;
264 : : }
265 : :
266 : : static int
267 : 0 : xsc_rxq_start(struct xsc_ethdev_priv *priv)
268 : : {
269 : : struct xsc_rxq_data *rxq_data;
270 : 0 : struct rte_eth_dev *dev = priv->eth_dev;
271 : : uint16_t i;
272 : : int ret;
273 : :
274 [ # # ]: 0 : if (priv->flags & XSC_FLAG_RX_QUEUE_INIT) {
275 [ # # ]: 0 : for (i = 0; i != priv->num_sq; ++i)
276 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
277 : : return 0;
278 : : }
279 : :
280 [ # # ]: 0 : for (i = 0; i != priv->num_rq; ++i) {
281 [ # # ]: 0 : rxq_data = xsc_rxq_get(priv, i);
282 : : if (rxq_data == NULL)
283 : 0 : goto error;
284 [ # # ]: 0 : if (dev->data->rx_queue_state[i] != RTE_ETH_QUEUE_STATE_STARTED) {
285 : 0 : ret = xsc_rxq_elts_alloc(rxq_data);
286 [ # # ]: 0 : if (ret != 0)
287 : 0 : goto error;
288 : : }
289 : : }
290 : :
291 : 0 : ret = xsc_rxq_rss_obj_new(priv, priv->dev_data->port_id);
292 [ # # ]: 0 : if (ret != 0)
293 : 0 : goto error;
294 : :
295 : 0 : priv->flags |= XSC_FLAG_RX_QUEUE_INIT;
296 : 0 : return 0;
297 : 0 : error:
298 : : /* Queue resources are released by xsc_ethdev_start calling the stop interface */
299 : 0 : return -rte_errno;
300 : : }
301 : :
302 : : static int
303 : 0 : xsc_ethdev_start(struct rte_eth_dev *dev)
304 : : {
305 : : int ret;
306 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
307 : :
308 : 0 : ret = xsc_txq_start(priv);
309 [ # # ]: 0 : if (ret) {
310 : 0 : PMD_DRV_LOG(ERR, "Port %u txq start failed: %s",
311 : : dev->data->port_id, strerror(rte_errno));
312 : 0 : goto error;
313 : : }
314 : :
315 : 0 : ret = xsc_rxq_start(priv);
316 [ # # ]: 0 : if (ret) {
317 : 0 : PMD_DRV_LOG(ERR, "Port %u Rx queue start failed: %s",
318 : : dev->data->port_id, strerror(rte_errno));
319 : 0 : goto error;
320 : : }
321 : :
322 : 0 : dev->data->dev_started = 1;
323 : :
324 : 0 : dev->rx_pkt_burst = xsc_rx_burst;
325 : 0 : dev->tx_pkt_burst = xsc_tx_burst;
326 : :
327 : 0 : ret = xsc_ethdev_enable(dev);
328 [ # # ]: 0 : if (ret) {
329 : 0 : PMD_DRV_LOG(ERR, "Failed to enable port: %u",
330 : : dev->data->port_id);
331 : 0 : goto error;
332 : : }
333 : :
334 : : return 0;
335 : :
336 : 0 : error:
337 : 0 : dev->data->dev_started = 0;
338 : 0 : xsc_txq_stop(dev);
339 : 0 : xsc_rxq_stop(dev);
340 : 0 : return -rte_errno;
341 : : }
342 : :
343 : : static int
344 : 0 : xsc_ethdev_stop(struct rte_eth_dev *dev)
345 : : {
346 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
347 : : uint16_t i;
348 : :
349 : 0 : PMD_DRV_LOG(DEBUG, "Port %u stopping", dev->data->port_id);
350 : 0 : dev->data->dev_started = 0;
351 : 0 : dev->rx_pkt_burst = rte_eth_pkt_burst_dummy;
352 : 0 : dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
353 : : rte_wmb();
354 : :
355 : 0 : rte_delay_us_sleep(1000 * priv->num_rq);
356 [ # # ]: 0 : for (i = 0; i < priv->num_rq; ++i)
357 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
358 [ # # ]: 0 : for (i = 0; i < priv->num_sq; ++i)
359 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
360 : :
361 : 0 : return 0;
362 : : }
363 : :
364 : : static int
365 : 0 : xsc_ethdev_close(struct rte_eth_dev *dev)
366 : : {
367 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
368 : :
369 : 0 : PMD_DRV_LOG(DEBUG, "Port %u closing", dev->data->port_id);
370 : 0 : dev->rx_pkt_burst = rte_eth_pkt_burst_dummy;
371 : 0 : dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
372 : : rte_wmb();
373 : :
374 : 0 : xsc_txq_stop(dev);
375 : 0 : xsc_rxq_stop(dev);
376 : :
377 : 0 : rte_free(priv->rss_conf.rss_key);
378 : 0 : xsc_dev_close(priv->xdev, priv->representor_id);
379 : 0 : dev->data->mac_addrs = NULL;
380 : 0 : return 0;
381 : : }
382 : :
383 : : static int
384 : 0 : xsc_ethdev_set_link_up(struct rte_eth_dev *dev)
385 : : {
386 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
387 : 0 : struct xsc_dev *xdev = priv->xdev;
388 : :
389 : 0 : return xsc_dev_set_link_up(xdev);
390 : : }
391 : :
392 : : static int
393 : 0 : xsc_ethdev_set_link_down(struct rte_eth_dev *dev)
394 : : {
395 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
396 : 0 : struct xsc_dev *xdev = priv->xdev;
397 : :
398 : 0 : return xsc_dev_set_link_down(xdev);
399 : : }
400 : :
401 : : static int
402 : 0 : xsc_ethdev_link_update(struct rte_eth_dev *dev,
403 : : 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 : : int ret = 0;
408 : :
409 : 0 : ret = xsc_dev_link_update(xdev, priv->funcid_type, wait_to_complete);
410 [ # # ]: 0 : if (ret == 0) {
411 : 0 : dev->data->dev_link = xdev->pf_dev_link;
412 : 0 : dev->data->dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
413 : : RTE_ETH_LINK_SPEED_FIXED);
414 : : }
415 : 0 : return ret;
416 : : }
417 : :
418 : : static uint64_t
419 : : xsc_get_rx_queue_offloads(struct rte_eth_dev *dev)
420 : : {
421 : : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
422 : : struct xsc_dev_config *config = &priv->config;
423 : : uint64_t offloads = 0;
424 : :
425 : 0 : if (config->hw_csum)
426 : : offloads |= (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
427 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
428 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM);
429 : :
430 : : return offloads;
431 : : }
432 : :
433 : : static uint64_t
434 : : xsc_get_tx_port_offloads(struct rte_eth_dev *dev)
435 : : {
436 : : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
437 : : uint64_t offloads = 0;
438 : : struct xsc_dev_config *config = &priv->config;
439 : :
440 : : if (config->hw_csum)
441 : : offloads |= (RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
442 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
443 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM);
444 : 0 : if (config->tso)
445 : 0 : offloads |= RTE_ETH_TX_OFFLOAD_TCP_TSO;
446 : : return offloads;
447 : : }
448 : :
449 : : static int
450 : 0 : xsc_ethdev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
451 : : {
452 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
453 : :
454 : 0 : info->min_rx_bufsize = 64;
455 : 0 : info->max_rx_pktlen = 65536;
456 : 0 : info->max_lro_pkt_size = 0;
457 : 0 : info->max_rx_queues = 256;
458 : 0 : info->max_tx_queues = 1024;
459 : 0 : info->rx_desc_lim.nb_max = 4096;
460 : 0 : info->rx_desc_lim.nb_min = 16;
461 : 0 : info->tx_desc_lim.nb_max = 8192;
462 [ # # ]: 0 : info->tx_desc_lim.nb_min = 128;
463 : :
464 : 0 : info->rx_queue_offload_capa = xsc_get_rx_queue_offloads(dev);
465 [ # # ]: 0 : info->rx_offload_capa = info->rx_queue_offload_capa;
466 : 0 : info->tx_offload_capa = xsc_get_tx_port_offloads(dev);
467 : :
468 : 0 : info->if_index = priv->ifindex;
469 : 0 : info->speed_capa = priv->xdev->link_speed_capa;
470 : 0 : info->hash_key_size = XSC_RSS_HASH_KEY_LEN;
471 : 0 : info->tx_desc_lim.nb_seg_max = 8;
472 : 0 : info->tx_desc_lim.nb_mtu_seg_max = 8;
473 : 0 : info->switch_info.name = dev->data->name;
474 : 0 : info->switch_info.port_id = priv->representor_id;
475 : 0 : return 0;
476 : : }
477 : :
478 : : static int
479 : 0 : xsc_ethdev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
480 : : uint32_t socket, const struct rte_eth_rxconf *conf,
481 : : struct rte_mempool *mp)
482 : : {
483 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
484 : : struct xsc_rxq_data *rxq_data = NULL;
485 : : uint16_t desc_n;
486 : : uint16_t rx_free_thresh;
487 : 0 : uint64_t offloads = conf->offloads | dev->data->dev_conf.rxmode.offloads;
488 : :
489 : 0 : desc = (desc > XSC_MAX_DESC_NUMBER) ? XSC_MAX_DESC_NUMBER : desc;
490 : : desc_n = desc;
491 : :
492 [ # # ]: 0 : if (!rte_is_power_of_2(desc))
493 : 0 : desc_n = 1 << rte_log2_u32(desc);
494 : :
495 : 0 : rxq_data = rte_malloc_socket(NULL, sizeof(*rxq_data) + desc_n * sizeof(struct rte_mbuf *),
496 : : RTE_CACHE_LINE_SIZE, socket);
497 [ # # ]: 0 : if (rxq_data == NULL) {
498 : 0 : PMD_DRV_LOG(ERR, "Port %u create rxq idx %d failure",
499 : : dev->data->port_id, idx);
500 : 0 : rte_errno = ENOMEM;
501 : 0 : return -rte_errno;
502 : : }
503 : 0 : rxq_data->idx = idx;
504 : 0 : rxq_data->priv = priv;
505 : 0 : (*priv->rxqs)[idx] = rxq_data;
506 : :
507 [ # # ]: 0 : rx_free_thresh = (conf->rx_free_thresh) ? conf->rx_free_thresh : XSC_RX_FREE_THRESH;
508 : 0 : rxq_data->rx_free_thresh = rx_free_thresh;
509 : :
510 : 0 : rxq_data->elts = (struct rte_mbuf *(*)[desc_n])(rxq_data + 1);
511 : 0 : rxq_data->mp = mp;
512 : 0 : rxq_data->socket = socket;
513 : :
514 : 0 : rxq_data->csum = !!(offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM);
515 : 0 : rxq_data->hw_timestamp = !!(offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP);
516 : 0 : rxq_data->crc_present = 0;
517 : :
518 : 0 : rxq_data->wqe_n = rte_log2_u32(desc_n);
519 : 0 : rxq_data->wqe_s = desc_n;
520 : 0 : rxq_data->wqe_m = desc_n - 1;
521 : :
522 : 0 : rxq_data->port_id = dev->data->port_id;
523 : 0 : dev->data->rx_queues[idx] = rxq_data;
524 : 0 : return 0;
525 : : }
526 : :
527 : : static int
528 : 0 : xsc_ethdev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
529 : : uint32_t socket, const struct rte_eth_txconf *conf)
530 : : {
531 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
532 : : struct xsc_txq_data *txq;
533 : : uint16_t desc_n;
534 : :
535 : 0 : desc = (desc > XSC_MAX_DESC_NUMBER) ? XSC_MAX_DESC_NUMBER : desc;
536 : : desc_n = desc;
537 : :
538 [ # # ]: 0 : if (!rte_is_power_of_2(desc))
539 : 0 : desc_n = 1 << rte_log2_u32(desc);
540 : :
541 : 0 : txq = rte_malloc_socket(NULL, sizeof(*txq) + desc_n * sizeof(struct rte_mbuf *),
542 : : RTE_CACHE_LINE_SIZE, socket);
543 : 0 : txq->offloads = conf->offloads | dev->data->dev_conf.txmode.offloads;
544 : 0 : txq->priv = priv;
545 : 0 : txq->socket = socket;
546 : :
547 : 0 : txq->elts_n = rte_log2_u32(desc_n);
548 : 0 : txq->elts_s = desc_n;
549 : 0 : txq->elts_m = desc_n - 1;
550 : 0 : txq->port_id = dev->data->port_id;
551 : 0 : txq->idx = idx;
552 : :
553 : 0 : (*priv->txqs)[idx] = txq;
554 : 0 : return 0;
555 : : }
556 : :
557 : : static int
558 : 0 : xsc_ethdev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
559 : : {
560 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
561 : : int ret = 0;
562 : :
563 [ # # ]: 0 : if (priv->eth_type != RTE_ETH_REPRESENTOR_PF) {
564 : 0 : priv->mtu = mtu;
565 : 0 : return 0;
566 : : }
567 : :
568 : 0 : ret = xsc_dev_set_mtu(priv->xdev, mtu);
569 [ # # ]: 0 : if (ret) {
570 : 0 : PMD_DRV_LOG(ERR, "Mtu set to %u failure", mtu);
571 : 0 : return -EAGAIN;
572 : : }
573 : :
574 : 0 : priv->mtu = mtu;
575 : 0 : return 0;
576 : : }
577 : :
578 : : static int
579 : 0 : xsc_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
580 : : {
581 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
582 : 0 : uint32_t rxqs_n = priv->num_rq;
583 : 0 : uint32_t txqs_n = priv->num_sq;
584 : : uint32_t i, idx;
585 : : struct xsc_rxq_data *rxq;
586 : : struct xsc_txq_data *txq;
587 : :
588 [ # # ]: 0 : for (i = 0; i < rxqs_n; ++i) {
589 [ # # ]: 0 : rxq = xsc_rxq_get(priv, i);
590 [ # # ]: 0 : if (unlikely(rxq == NULL))
591 : 0 : continue;
592 : :
593 : 0 : idx = rxq->idx;
594 [ # # ]: 0 : if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
595 : 0 : stats->q_ipackets[idx] += rxq->stats.rx_pkts;
596 : 0 : stats->q_ibytes[idx] += rxq->stats.rx_bytes;
597 : 0 : stats->q_errors[idx] += rxq->stats.rx_errors +
598 : 0 : rxq->stats.rx_nombuf;
599 : : }
600 : 0 : stats->ipackets += rxq->stats.rx_pkts;
601 : 0 : stats->ibytes += rxq->stats.rx_bytes;
602 : 0 : stats->ierrors += rxq->stats.rx_errors;
603 : 0 : stats->rx_nombuf += rxq->stats.rx_nombuf;
604 : : }
605 : :
606 [ # # ]: 0 : for (i = 0; i < txqs_n; ++i) {
607 [ # # ]: 0 : txq = xsc_txq_get(priv, i);
608 [ # # ]: 0 : if (unlikely(txq == NULL))
609 : 0 : continue;
610 : :
611 : 0 : idx = txq->idx;
612 [ # # ]: 0 : if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
613 : 0 : stats->q_opackets[idx] += txq->stats.tx_pkts;
614 : 0 : stats->q_obytes[idx] += txq->stats.tx_bytes;
615 : 0 : stats->q_errors[idx] += txq->stats.tx_errors;
616 : : }
617 : 0 : stats->opackets += txq->stats.tx_pkts;
618 : 0 : stats->obytes += txq->stats.tx_bytes;
619 : 0 : stats->oerrors += txq->stats.tx_errors;
620 : : }
621 : :
622 : 0 : return 0;
623 : : }
624 : :
625 : : static int
626 : 0 : xsc_ethdev_stats_reset(struct rte_eth_dev *dev)
627 : : {
628 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
629 : 0 : uint32_t rxqs_n = priv->num_rq;
630 : 0 : uint32_t txqs_n = priv->num_sq;
631 : : uint32_t i;
632 : : struct xsc_rxq_data *rxq;
633 : : struct xsc_txq_data *txq;
634 : :
635 [ # # ]: 0 : for (i = 0; i < rxqs_n; ++i) {
636 [ # # ]: 0 : rxq = xsc_rxq_get(priv, i);
637 [ # # ]: 0 : if (unlikely(rxq == NULL))
638 : 0 : continue;
639 : 0 : memset(&rxq->stats, 0, sizeof(struct xsc_rxq_stats));
640 : : }
641 [ # # ]: 0 : for (i = 0; i < txqs_n; ++i) {
642 [ # # ]: 0 : txq = xsc_txq_get(priv, i);
643 [ # # ]: 0 : if (unlikely(txq == NULL))
644 : 0 : continue;
645 : 0 : memset(&txq->stats, 0, sizeof(struct xsc_txq_stats));
646 : : }
647 : :
648 : 0 : return 0;
649 : : }
650 : :
651 : : static int
652 : 0 : xsc_ethdev_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, uint32_t index)
653 : : {
654 : : int i;
655 : :
656 : 0 : rte_errno = EINVAL;
657 [ # # ]: 0 : if (index > XSC_MAX_MAC_ADDRESSES)
658 : : return -rte_errno;
659 : :
660 [ # # ]: 0 : if (rte_is_zero_ether_addr(mac))
661 : : return -rte_errno;
662 : :
663 [ # # ]: 0 : for (i = 0; i != XSC_MAX_MAC_ADDRESSES; ++i) {
664 [ # # ]: 0 : if (i == (int)index)
665 : 0 : continue;
666 [ # # ]: 0 : if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac)) != 0)
667 : 0 : continue;
668 : : /* Address already configured elsewhere, return with error */
669 : 0 : rte_errno = EADDRINUSE;
670 : 0 : return -rte_errno;
671 : : }
672 : :
673 : 0 : dev->data->mac_addrs[index] = *mac;
674 : 0 : return 0;
675 : : }
676 : :
677 : : const struct eth_dev_ops xsc_eth_dev_ops = {
678 : : .dev_configure = xsc_ethdev_configure,
679 : : .dev_start = xsc_ethdev_start,
680 : : .dev_stop = xsc_ethdev_stop,
681 : : .dev_set_link_up = xsc_ethdev_set_link_up,
682 : : .dev_set_link_down = xsc_ethdev_set_link_down,
683 : : .dev_close = xsc_ethdev_close,
684 : : .link_update = xsc_ethdev_link_update,
685 : : .stats_get = xsc_ethdev_stats_get,
686 : : .stats_reset = xsc_ethdev_stats_reset,
687 : : .dev_infos_get = xsc_ethdev_infos_get,
688 : : .rx_queue_setup = xsc_ethdev_rx_queue_setup,
689 : : .tx_queue_setup = xsc_ethdev_tx_queue_setup,
690 : : .rx_queue_release = xsc_ethdev_rxq_release,
691 : : .tx_queue_release = xsc_ethdev_txq_release,
692 : : .mtu_set = xsc_ethdev_set_mtu,
693 : : .rss_hash_update = xsc_ethdev_rss_hash_update,
694 : : .rss_hash_conf_get = xsc_ethdev_rss_hash_conf_get,
695 : : };
696 : :
697 : : static int
698 : 0 : xsc_ethdev_init_one_representor(struct rte_eth_dev *eth_dev, void *init_params)
699 : : {
700 : : int ret;
701 : : struct xsc_repr_port *repr_port = (struct xsc_repr_port *)init_params;
702 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
703 : : struct xsc_dev_config *config = &priv->config;
704 : : struct rte_ether_addr mac;
705 : :
706 : 0 : priv->repr_port = repr_port;
707 : 0 : repr_port->drv_data = eth_dev;
708 : 0 : priv->xdev = repr_port->xdev;
709 : 0 : priv->mtu = RTE_ETHER_MTU;
710 : 0 : priv->funcid_type = (repr_port->info.funcid & XSC_FUNCID_TYPE_MASK) >> 14;
711 : 0 : priv->funcid = repr_port->info.funcid & XSC_FUNCID_MASK;
712 [ # # ]: 0 : if (repr_port->info.port_type == XSC_PORT_TYPE_UPLINK ||
713 : : repr_port->info.port_type == XSC_PORT_TYPE_UPLINK_BOND)
714 : 0 : priv->eth_type = RTE_ETH_REPRESENTOR_PF;
715 : : else
716 : 0 : priv->eth_type = RTE_ETH_REPRESENTOR_VF;
717 : 0 : priv->representor_id = repr_port->info.repr_id;
718 : 0 : priv->dev_data = eth_dev->data;
719 : 0 : priv->ifindex = repr_port->info.ifindex;
720 : :
721 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
722 [ # # ]: 0 : eth_dev->data->mac_addrs = priv->mac;
723 [ # # ]: 0 : if (rte_is_zero_ether_addr(eth_dev->data->mac_addrs)) {
724 : 0 : ret = xsc_dev_get_mac(priv->xdev, mac.addr_bytes);
725 [ # # ]: 0 : if (ret != 0) {
726 : 0 : PMD_DRV_LOG(ERR, "Port %u cannot get MAC address",
727 : : eth_dev->data->port_id);
728 : 0 : return -ENODEV;
729 : : }
730 : : }
731 : :
732 : 0 : xsc_ethdev_mac_addr_add(eth_dev, &mac, 0);
733 : :
734 : 0 : config->hw_csum = 1;
735 : 0 : config->pph_flag = priv->xdev->devargs.pph_mode;
736 [ # # ]: 0 : if ((config->pph_flag & XSC_TX_PPH) != 0) {
737 : 0 : config->tso = 0;
738 : : } else {
739 : 0 : config->tso = 1;
740 : 0 : config->tso_max_payload_sz = 1500;
741 : : }
742 : :
743 : 0 : priv->is_representor = 1;
744 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
745 : 0 : eth_dev->data->representor_id = priv->representor_id;
746 : 0 : eth_dev->data->backer_port_id = eth_dev->data->port_id;
747 : :
748 : 0 : eth_dev->dev_ops = &xsc_eth_dev_ops;
749 : 0 : eth_dev->rx_pkt_burst = rte_eth_pkt_burst_dummy;
750 : 0 : eth_dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
751 : :
752 : 0 : rte_eth_dev_probing_finish(eth_dev);
753 : :
754 : 0 : return 0;
755 : : }
756 : :
757 : : static int
758 : 0 : xsc_ethdev_init_representors(struct rte_eth_dev *eth_dev)
759 : : {
760 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
761 : 0 : struct rte_eth_devargs eth_da = { .nb_representor_ports = 0 };
762 : : struct rte_device *dev;
763 : : struct xsc_dev *xdev;
764 : : struct xsc_repr_port *repr_port;
765 : : char name[RTE_ETH_NAME_MAX_LEN];
766 : : int i;
767 : : int ret;
768 : :
769 : 0 : PMD_INIT_FUNC_TRACE();
770 : :
771 : 0 : dev = &priv->pci_dev->device;
772 [ # # ]: 0 : if (dev->devargs != NULL) {
773 : 0 : ret = rte_eth_devargs_parse(dev->devargs->args, ð_da, 1);
774 [ # # ]: 0 : if (ret < 0) {
775 : 0 : PMD_DRV_LOG(ERR, "Failed to parse device arguments: %s",
776 : : dev->devargs->args);
777 : 0 : return -EINVAL;
778 : : }
779 : : }
780 : :
781 : 0 : xdev = priv->xdev;
782 : 0 : ret = xsc_dev_repr_ports_probe(xdev, eth_da.nb_representor_ports, RTE_MAX_ETHPORTS);
783 [ # # ]: 0 : if (ret != 0) {
784 : 0 : PMD_DRV_LOG(ERR, "Failed to probe %d xsc device representors",
785 : : eth_da.nb_representor_ports);
786 : 0 : return ret;
787 : : }
788 : :
789 : : /* PF rep init */
790 : 0 : repr_port = &xdev->repr_ports[xdev->num_repr_ports - 1];
791 : 0 : ret = xsc_ethdev_init_one_representor(eth_dev, repr_port);
792 [ # # ]: 0 : if (ret != 0) {
793 : 0 : PMD_DRV_LOG(ERR, "Failed to init backing representor");
794 : 0 : return ret;
795 : : }
796 : :
797 : : /* VF rep init */
798 [ # # ]: 0 : for (i = 0; i < eth_da.nb_representor_ports; i++) {
799 : 0 : repr_port = &xdev->repr_ports[i];
800 : 0 : snprintf(name, sizeof(name), "%s_rep_%d",
801 : 0 : xdev->name, repr_port->info.repr_id);
802 : 0 : ret = rte_eth_dev_create(dev,
803 : : name,
804 : : sizeof(struct xsc_ethdev_priv),
805 : : NULL, NULL,
806 : : xsc_ethdev_init_one_representor,
807 : : repr_port);
808 [ # # ]: 0 : if (ret != 0) {
809 : 0 : PMD_DRV_LOG(ERR, "Failed to create representor: %d", i);
810 : 0 : goto destroy_reprs;
811 : : }
812 : : }
813 : :
814 : : return 0;
815 : :
816 : : destroy_reprs:
817 : : /* Destroy vf reprs */
818 [ # # ]: 0 : while ((i--) > 1) {
819 : 0 : repr_port = &xdev->repr_ports[i];
820 : 0 : rte_eth_dev_destroy((struct rte_eth_dev *)repr_port->drv_data, NULL);
821 : : }
822 : :
823 : : /* Destroy pf repr */
824 : 0 : repr_port = &xdev->repr_ports[xdev->num_repr_ports - 1];
825 : 0 : rte_eth_dev_destroy((struct rte_eth_dev *)repr_port->drv_data, NULL);
826 : 0 : return ret;
827 : : }
828 : :
829 : : static int
830 : 0 : xsc_ethdev_init(struct rte_eth_dev *eth_dev)
831 : : {
832 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
833 : : int ret;
834 : :
835 : 0 : PMD_INIT_FUNC_TRACE();
836 : :
837 : 0 : priv->eth_dev = eth_dev;
838 : 0 : priv->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
839 : :
840 : 0 : ret = xsc_dev_init(priv->pci_dev, &priv->xdev);
841 [ # # ]: 0 : if (ret) {
842 : 0 : PMD_DRV_LOG(ERR, "Failed to initialize xsc device");
843 : 0 : return ret;
844 : : }
845 : 0 : priv->xdev->port_id = eth_dev->data->port_id;
846 : :
847 : 0 : ret = xsc_ethdev_init_representors(eth_dev);
848 [ # # ]: 0 : if (ret != 0) {
849 : 0 : PMD_DRV_LOG(ERR, "Failed to initialize representors");
850 : 0 : goto uninit_xsc_dev;
851 : : }
852 : :
853 : : return 0;
854 : :
855 : : uninit_xsc_dev:
856 : 0 : xsc_dev_uninit(priv->xdev);
857 : 0 : return ret;
858 : : }
859 : :
860 : : static int
861 : 0 : xsc_ethdev_uninit(struct rte_eth_dev *eth_dev)
862 : : {
863 : 0 : struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
864 : :
865 : 0 : PMD_INIT_FUNC_TRACE();
866 : :
867 : 0 : xsc_dev_uninit(priv->xdev);
868 : :
869 : 0 : return 0;
870 : : }
871 : :
872 : : static int
873 : 0 : xsc_ethdev_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
874 : : struct rte_pci_device *pci_dev)
875 : : {
876 : : int ret;
877 : :
878 : 0 : PMD_INIT_FUNC_TRACE();
879 : :
880 : 0 : ret = rte_eth_dev_pci_generic_probe(pci_dev,
881 : : sizeof(struct xsc_ethdev_priv),
882 : : xsc_ethdev_init);
883 [ # # ]: 0 : if (ret) {
884 : 0 : PMD_DRV_LOG(ERR, "Failed to probe ethdev: %s", pci_dev->name);
885 : 0 : return ret;
886 : : }
887 : :
888 : : return 0;
889 : : }
890 : :
891 : : static int
892 : 0 : xsc_ethdev_pci_remove(struct rte_pci_device *pci_dev)
893 : : {
894 : : int ret;
895 : :
896 : 0 : PMD_INIT_FUNC_TRACE();
897 : :
898 : 0 : ret = rte_eth_dev_pci_generic_remove(pci_dev, xsc_ethdev_uninit);
899 [ # # ]: 0 : if (ret) {
900 : 0 : PMD_DRV_LOG(ERR, "Could not remove ethdev: %s", pci_dev->name);
901 : 0 : return ret;
902 : : }
903 : :
904 : : return 0;
905 : : }
906 : :
907 : : static const struct rte_pci_id xsc_ethdev_pci_id_map[] = {
908 : : { RTE_PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_PCI_DEV_ID_MS) },
909 : : { RTE_PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_PCI_DEV_ID_MSVF) },
910 : : { RTE_PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_PCI_DEV_ID_MVH) },
911 : : { RTE_PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_PCI_DEV_ID_MVHVF) },
912 : : { RTE_PCI_DEVICE(XSC_PCI_VENDOR_ID, XSC_PCI_DEV_ID_MVS) },
913 : : { RTE_PCI_DEVICE(0, 0) },
914 : : };
915 : :
916 : : static struct rte_pci_driver xsc_ethdev_pci_driver = {
917 : : .id_table = xsc_ethdev_pci_id_map,
918 : : .probe = xsc_ethdev_pci_probe,
919 : : .remove = xsc_ethdev_pci_remove,
920 : : };
921 : :
922 : 252 : RTE_PMD_REGISTER_PCI(net_xsc, xsc_ethdev_pci_driver);
923 : : RTE_PMD_REGISTER_PCI_TABLE(net_xsc, xsc_ethdev_pci_id_map);
924 : : RTE_PMD_REGISTER_PARAM_STRING(net_xsc,
925 : : XSC_PPH_MODE_ARG "=<x>"
926 : : XSC_NIC_MODE_ARG "=<x>"
927 : : XSC_FLOW_MODE_ARG "=<x>");
928 : :
929 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(xsc_logtype_init, init, NOTICE);
930 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(xsc_logtype_driver, driver, NOTICE);
|