Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <cnxk_ethdev.h>
6 : :
7 : : int
8 : 0 : cnxk_nix_info_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *devinfo)
9 : : {
10 : 0 : struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
11 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
12 : : int max_rx_pktlen;
13 : :
14 : 0 : max_rx_pktlen = (roc_nix_max_pkt_len(&dev->nix) + RTE_ETHER_CRC_LEN -
15 : : CNXK_NIX_MAX_VTAG_ACT_SIZE);
16 : :
17 : 0 : devinfo->min_rx_bufsize = NIX_MIN_HW_FRS + RTE_ETHER_CRC_LEN;
18 : 0 : devinfo->max_rx_pktlen = max_rx_pktlen;
19 : 0 : devinfo->max_rx_queues = RTE_MAX_QUEUES_PER_PORT;
20 : 0 : devinfo->max_tx_queues = RTE_MAX_QUEUES_PER_PORT;
21 : 0 : devinfo->max_mac_addrs = dev->max_mac_entries;
22 : 0 : devinfo->max_vfs = pci_dev->max_vfs;
23 : 0 : devinfo->max_mtu = devinfo->max_rx_pktlen -
24 : : (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN);
25 : 0 : devinfo->min_mtu = devinfo->min_rx_bufsize - CNXK_NIX_L2_OVERHEAD;
26 : :
27 : 0 : devinfo->rx_offload_capa = dev->rx_offload_capa;
28 : 0 : devinfo->tx_offload_capa = dev->tx_offload_capa;
29 : 0 : devinfo->rx_queue_offload_capa = 0;
30 : 0 : devinfo->tx_queue_offload_capa = 0;
31 : :
32 : 0 : devinfo->reta_size = dev->nix.reta_sz;
33 : 0 : devinfo->hash_key_size = ROC_NIX_RSS_KEY_LEN;
34 : 0 : devinfo->flow_type_rss_offloads = CNXK_NIX_RSS_OFFLOAD;
35 : :
36 : 0 : devinfo->default_rxconf = (struct rte_eth_rxconf){
37 : : .rx_drop_en = 0,
38 : : .offloads = 0,
39 : : };
40 : :
41 : 0 : devinfo->default_txconf = (struct rte_eth_txconf){
42 : : .offloads = 0,
43 : : };
44 : :
45 : 0 : devinfo->default_rxportconf = (struct rte_eth_dev_portconf){
46 : : .ring_size = CNXK_NIX_RX_DEFAULT_RING_SZ,
47 : : };
48 : :
49 : 0 : devinfo->rx_desc_lim = (struct rte_eth_desc_lim){
50 : : .nb_max = UINT16_MAX,
51 : : .nb_min = CNXK_NIX_RX_MIN_DESC,
52 : : .nb_align = CNXK_NIX_RX_MIN_DESC_ALIGN,
53 : : .nb_seg_max = CNXK_NIX_RX_NB_SEG_MAX,
54 : : .nb_mtu_seg_max = CNXK_NIX_RX_NB_SEG_MAX,
55 : : };
56 : 0 : devinfo->rx_desc_lim.nb_max =
57 : : RTE_ALIGN_MUL_FLOOR(devinfo->rx_desc_lim.nb_max,
58 : : CNXK_NIX_RX_MIN_DESC_ALIGN);
59 : :
60 : 0 : devinfo->tx_desc_lim = (struct rte_eth_desc_lim){
61 : : .nb_max = UINT16_MAX,
62 : : .nb_min = 1,
63 : : .nb_align = 1,
64 : : .nb_seg_max = CNXK_NIX_TX_NB_SEG_MAX,
65 : : .nb_mtu_seg_max = CNXK_NIX_TX_NB_SEG_MAX,
66 : : };
67 : :
68 : 0 : devinfo->speed_capa = dev->speed_capa;
69 : 0 : devinfo->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
70 : : RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP |
71 : : RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
72 : :
73 : 0 : devinfo->max_rx_mempools = CNXK_NIX_NUM_POOLS_MAX;
74 : :
75 : 0 : return 0;
76 : : }
77 : :
78 : : int
79 : 0 : cnxk_nix_rx_burst_mode_get(struct rte_eth_dev *eth_dev, uint16_t queue_id,
80 : : struct rte_eth_burst_mode *mode)
81 : : {
82 : : ssize_t bytes = 0, str_size = RTE_ETH_BURST_MODE_INFO_SIZE, rc;
83 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
84 : : const struct burst_info {
85 : : uint64_t flags;
86 : : const char *output;
87 : 0 : } rx_offload_map[] = {
88 : : {RTE_ETH_RX_OFFLOAD_VLAN_STRIP, " VLAN Strip,"},
89 : : {RTE_ETH_RX_OFFLOAD_IPV4_CKSUM, " Inner IPv4 Checksum,"},
90 : : {RTE_ETH_RX_OFFLOAD_UDP_CKSUM, " UDP Checksum,"},
91 : : {RTE_ETH_RX_OFFLOAD_TCP_CKSUM, " TCP Checksum,"},
92 : : {RTE_ETH_RX_OFFLOAD_TCP_LRO, " TCP LRO,"},
93 : : {RTE_ETH_RX_OFFLOAD_QINQ_STRIP, " QinQ VLAN Strip,"},
94 : : {RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM, " Outer IPv4 Checksum,"},
95 : : {RTE_ETH_RX_OFFLOAD_MACSEC_STRIP, " MACsec Strip,"},
96 : : {RTE_ETH_RX_OFFLOAD_VLAN_FILTER, " VLAN Filter,"},
97 : : {RTE_ETH_RX_OFFLOAD_VLAN_EXTEND, " VLAN Extend,"},
98 : : {RTE_ETH_RX_OFFLOAD_SCATTER, " Scattered,"},
99 : : {RTE_ETH_RX_OFFLOAD_TIMESTAMP, " Timestamp,"},
100 : : {RTE_ETH_RX_OFFLOAD_SECURITY, " Security,"},
101 : : {RTE_ETH_RX_OFFLOAD_KEEP_CRC, " Keep CRC,"},
102 : : {RTE_ETH_RX_OFFLOAD_SCTP_CKSUM, " SCTP,"},
103 : : {RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM, " Outer UDP Checksum,"},
104 : : {RTE_ETH_RX_OFFLOAD_RSS_HASH, " RSS,"}
105 : : };
106 : : static const char *const burst_mode[] = {"Vector Neon, Rx Offloads:",
107 : : "Scalar, Rx Offloads:"
108 : : };
109 : : uint32_t i;
110 : :
111 : : PLT_SET_USED(queue_id);
112 : :
113 : : /* Update burst mode info */
114 : 0 : rc = rte_strscpy(mode->info + bytes, burst_mode[dev->scalar_ena],
115 : : str_size - bytes);
116 [ # # ]: 0 : if (rc < 0)
117 : 0 : goto done;
118 : :
119 : : bytes += rc;
120 : :
121 : : /* Update Rx offload info */
122 [ # # ]: 0 : for (i = 0; i < RTE_DIM(rx_offload_map); i++) {
123 [ # # ]: 0 : if (dev->rx_offloads & rx_offload_map[i].flags) {
124 : 0 : rc = rte_strscpy(mode->info + bytes,
125 : 0 : rx_offload_map[i].output,
126 : 0 : str_size - bytes);
127 [ # # ]: 0 : if (rc < 0)
128 : 0 : goto done;
129 : :
130 : 0 : bytes += rc;
131 : : }
132 : : }
133 : :
134 : 0 : done:
135 : 0 : return 0;
136 : : }
137 : :
138 : : int
139 : 0 : cnxk_nix_tx_burst_mode_get(struct rte_eth_dev *eth_dev, uint16_t queue_id,
140 : : struct rte_eth_burst_mode *mode)
141 : : {
142 : : ssize_t bytes = 0, str_size = RTE_ETH_BURST_MODE_INFO_SIZE, rc;
143 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
144 : : const struct burst_info {
145 : : uint64_t flags;
146 : : const char *output;
147 : 0 : } tx_offload_map[] = {
148 : : {RTE_ETH_TX_OFFLOAD_VLAN_INSERT, " VLAN Insert,"},
149 : : {RTE_ETH_TX_OFFLOAD_IPV4_CKSUM, " Inner IPv4 Checksum,"},
150 : : {RTE_ETH_TX_OFFLOAD_UDP_CKSUM, " UDP Checksum,"},
151 : : {RTE_ETH_TX_OFFLOAD_TCP_CKSUM, " TCP Checksum,"},
152 : : {RTE_ETH_TX_OFFLOAD_SCTP_CKSUM, " SCTP Checksum,"},
153 : : {RTE_ETH_TX_OFFLOAD_TCP_TSO, " TCP TSO,"},
154 : : {RTE_ETH_TX_OFFLOAD_UDP_TSO, " UDP TSO,"},
155 : : {RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM, " Outer IPv4 Checksum,"},
156 : : {RTE_ETH_TX_OFFLOAD_QINQ_INSERT, " QinQ VLAN Insert,"},
157 : : {RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO, " VXLAN Tunnel TSO,"},
158 : : {RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO, " GRE Tunnel TSO,"},
159 : : {RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO, " IP-in-IP Tunnel TSO,"},
160 : : {RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO, " Geneve Tunnel TSO,"},
161 : : {RTE_ETH_TX_OFFLOAD_MACSEC_INSERT, " MACsec Insert,"},
162 : : {RTE_ETH_TX_OFFLOAD_MT_LOCKFREE, " Multi Thread Lockless Tx,"},
163 : : {RTE_ETH_TX_OFFLOAD_MULTI_SEGS, " Scattered,"},
164 : : {RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE, " H/W MBUF Free,"},
165 : : {RTE_ETH_TX_OFFLOAD_SECURITY, " Security,"},
166 : : {RTE_ETH_TX_OFFLOAD_UDP_TNL_TSO, " UDP Tunnel TSO,"},
167 : : {RTE_ETH_TX_OFFLOAD_IP_TNL_TSO, " IP Tunnel TSO,"},
168 : : {RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM, " Outer UDP Checksum,"},
169 : : {RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP, " Timestamp,"}
170 : : };
171 : : static const char *const burst_mode[] = {"Vector Neon, Tx Offloads:",
172 : : "Scalar, Tx Offloads:"
173 : : };
174 : : uint32_t i;
175 : :
176 : : PLT_SET_USED(queue_id);
177 : :
178 : : /* Update burst mode info */
179 : 0 : rc = rte_strscpy(mode->info + bytes, burst_mode[dev->scalar_ena],
180 : : str_size - bytes);
181 [ # # ]: 0 : if (rc < 0)
182 : 0 : goto done;
183 : :
184 : : bytes += rc;
185 : :
186 : : /* Update Tx offload info */
187 [ # # ]: 0 : for (i = 0; i < RTE_DIM(tx_offload_map); i++) {
188 [ # # ]: 0 : if (dev->tx_offloads & tx_offload_map[i].flags) {
189 : 0 : rc = rte_strscpy(mode->info + bytes,
190 : 0 : tx_offload_map[i].output,
191 : 0 : str_size - bytes);
192 [ # # ]: 0 : if (rc < 0)
193 : 0 : goto done;
194 : :
195 : 0 : bytes += rc;
196 : : }
197 : : }
198 : :
199 : 0 : done:
200 : 0 : return 0;
201 : : }
202 : :
203 : : int
204 : 0 : cnxk_nix_flow_ctrl_get(struct rte_eth_dev *eth_dev,
205 : : struct rte_eth_fc_conf *fc_conf)
206 : : {
207 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
208 : 0 : enum rte_eth_fc_mode mode_map[2][2] = {
209 : : [0][0] = RTE_ETH_FC_NONE,
210 : : [0][1] = RTE_ETH_FC_TX_PAUSE,
211 : : [1][0] = RTE_ETH_FC_RX_PAUSE,
212 : : [1][1] = RTE_ETH_FC_FULL,
213 : : };
214 : 0 : struct roc_nix *nix = &dev->nix;
215 : : uint8_t rx_pause, tx_pause;
216 : : int mode, i;
217 : :
218 [ # # ]: 0 : if (roc_nix_is_sdp(nix))
219 : : return 0;
220 : :
221 : 0 : mode = roc_nix_fc_mode_get(nix);
222 [ # # ]: 0 : if (mode < 0)
223 : : return mode;
224 : :
225 : 0 : rx_pause = (mode == ROC_NIX_FC_FULL) || (mode == ROC_NIX_FC_RX);
226 : 0 : tx_pause = (mode == ROC_NIX_FC_FULL) || (mode == ROC_NIX_FC_TX);
227 : :
228 : : /* Report flow control as disabled even if one RQ/SQ has it disabled */
229 [ # # ]: 0 : for (i = 0; i < dev->nb_rxq; i++) {
230 [ # # ]: 0 : if (dev->rqs[i].tc == ROC_NIX_PFC_CLASS_INVALID)
231 : : tx_pause = 0;
232 : : }
233 : :
234 [ # # ]: 0 : for (i = 0; i < dev->nb_txq; i++) {
235 [ # # ]: 0 : if (dev->sqs[i].tc == ROC_NIX_PFC_CLASS_INVALID)
236 : : rx_pause = 0;
237 : : }
238 : :
239 : : memset(fc_conf, 0, sizeof(struct rte_eth_fc_conf));
240 : 0 : fc_conf->mode = mode_map[rx_pause][tx_pause];
241 : 0 : return 0;
242 : : }
243 : :
244 : : int
245 : 0 : cnxk_nix_flow_ctrl_set(struct rte_eth_dev *eth_dev,
246 : : struct rte_eth_fc_conf *fc_conf)
247 : : {
248 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
249 : 0 : enum roc_nix_fc_mode mode_map[] = {
250 : : ROC_NIX_FC_NONE, ROC_NIX_FC_RX,
251 : : ROC_NIX_FC_TX, ROC_NIX_FC_FULL
252 : : };
253 : : struct rte_eth_dev_data *data = eth_dev->data;
254 : : struct cnxk_fc_cfg *fc = &dev->fc_cfg;
255 : 0 : struct roc_nix *nix = &dev->nix;
256 : : struct cnxk_eth_rxq_sp *rxq;
257 : : struct cnxk_eth_txq_sp *txq;
258 : : uint8_t rx_pause, tx_pause;
259 : : struct roc_nix_sq *sq;
260 : : struct roc_nix_cq *cq;
261 : : struct roc_nix_rq *rq;
262 : : uint8_t tc;
263 : : int rc, i;
264 : :
265 [ # # ]: 0 : if (roc_nix_is_sdp(nix))
266 : : return 0;
267 : :
268 [ # # ]: 0 : if (dev->pfc_cfg.rx_pause_en || dev->pfc_cfg.tx_pause_en) {
269 : 0 : plt_err("Disable PFC before configuring Flow Control");
270 : 0 : return -ENOTSUP;
271 : : }
272 : :
273 [ # # # # : 0 : if (fc_conf->high_water || fc_conf->low_water || fc_conf->pause_time ||
# # ]
274 [ # # ]: 0 : fc_conf->mac_ctrl_frame_fwd || fc_conf->autoneg) {
275 : 0 : plt_info("Only MODE configuration is supported");
276 : 0 : return -EINVAL;
277 : : }
278 : :
279 : : /* Disallow flow control changes when device is in started state */
280 [ # # ]: 0 : if (data->dev_started) {
281 : 0 : plt_info("Stop the port=%d for setting flow control", data->port_id);
282 : 0 : return -EBUSY;
283 : : }
284 : :
285 : 0 : rx_pause = (fc_conf->mode == RTE_ETH_FC_FULL) || (fc_conf->mode == RTE_ETH_FC_RX_PAUSE);
286 : 0 : tx_pause = (fc_conf->mode == RTE_ETH_FC_FULL) || (fc_conf->mode == RTE_ETH_FC_TX_PAUSE);
287 : :
288 : : /* Check if TX pause frame is already enabled or not */
289 [ # # ]: 0 : tc = tx_pause ? 0 : ROC_NIX_PFC_CLASS_INVALID;
290 [ # # ]: 0 : for (i = 0; i < data->nb_rx_queues; i++) {
291 : : struct roc_nix_fc_cfg fc_cfg;
292 : :
293 : : /* Skip if RQ does not exist */
294 [ # # ]: 0 : if (!data->rx_queues[i])
295 : 0 : continue;
296 : :
297 : : rxq = cnxk_eth_rxq_to_sp(data->rx_queues[i]);
298 : 0 : rq = &dev->rqs[rxq->qid];
299 : 0 : cq = &dev->cqs[rxq->qid];
300 : :
301 : : /* Skip if RQ is in expected state */
302 [ # # # # ]: 0 : if (fc->tx_pause == tx_pause && rq->tc == tc)
303 : 0 : continue;
304 : :
305 : : memset(&fc_cfg, 0, sizeof(struct roc_nix_fc_cfg));
306 : 0 : fc_cfg.type = ROC_NIX_FC_RQ_CFG;
307 : 0 : fc_cfg.rq_cfg.enable = !!tx_pause;
308 : : fc_cfg.rq_cfg.tc = 0;
309 : 0 : fc_cfg.rq_cfg.rq = rq->qid;
310 : 0 : fc_cfg.rq_cfg.pool = rq->aura_handle;
311 : 0 : fc_cfg.rq_cfg.spb_pool = rq->spb_aura_handle;
312 : 0 : fc_cfg.rq_cfg.cq_drop = cq->drop_thresh;
313 : 0 : fc_cfg.rq_cfg.pool_drop_pct = ROC_NIX_AURA_THRESH;
314 : :
315 : 0 : rc = roc_nix_fc_config_set(nix, &fc_cfg);
316 [ # # ]: 0 : if (rc)
317 : 0 : return rc;
318 : 0 : rxq->tx_pause = !!tx_pause;
319 : : }
320 : :
321 : : /* Check if RX pause frame is enabled or not */
322 [ # # ]: 0 : tc = rx_pause ? 0 : ROC_NIX_PFC_CLASS_INVALID;
323 [ # # ]: 0 : for (i = 0; i < data->nb_tx_queues; i++) {
324 : : struct roc_nix_fc_cfg fc_cfg;
325 : :
326 : : /* Skip if SQ does not exist */
327 [ # # ]: 0 : if (!data->tx_queues[i])
328 : 0 : continue;
329 : :
330 : : txq = cnxk_eth_txq_to_sp(data->tx_queues[i]);
331 : 0 : sq = &dev->sqs[txq->qid];
332 : :
333 : : /* Skip if SQ is in expected state */
334 [ # # # # ]: 0 : if (fc->rx_pause == rx_pause && sq->tc == tc)
335 : 0 : continue;
336 : :
337 : : memset(&fc_cfg, 0, sizeof(struct roc_nix_fc_cfg));
338 : 0 : fc_cfg.type = ROC_NIX_FC_TM_CFG;
339 : 0 : fc_cfg.tm_cfg.sq = txq->qid;
340 : : fc_cfg.tm_cfg.tc = 0;
341 : 0 : fc_cfg.tm_cfg.enable = !!rx_pause;
342 : 0 : rc = roc_nix_fc_config_set(nix, &fc_cfg);
343 [ # # ]: 0 : if (rc && rc != EEXIST)
344 : 0 : return rc;
345 : : }
346 : :
347 : : /* Skip mode set if it is we are in same state */
348 [ # # # # ]: 0 : if (fc->rx_pause == rx_pause && fc->tx_pause == tx_pause)
349 : : return 0;
350 : :
351 : 0 : rc = roc_nix_fc_mode_set(nix, mode_map[fc_conf->mode]);
352 [ # # ]: 0 : if (rc)
353 : : return rc;
354 : :
355 : 0 : fc->rx_pause = rx_pause;
356 : 0 : fc->tx_pause = tx_pause;
357 : 0 : fc->mode = fc_conf->mode;
358 : 0 : return rc;
359 : : }
360 : :
361 : : int
362 : 0 : cnxk_nix_priority_flow_ctrl_queue_info_get(struct rte_eth_dev *eth_dev,
363 : : struct rte_eth_pfc_queue_info *pfc_info)
364 : : {
365 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
366 : :
367 : 0 : pfc_info->tc_max = roc_nix_chan_count_get(&dev->nix);
368 : 0 : pfc_info->mode_capa = RTE_ETH_FC_FULL;
369 : 0 : return 0;
370 : : }
371 : :
372 : : int
373 [ # # ]: 0 : cnxk_nix_priority_flow_ctrl_queue_config(struct rte_eth_dev *eth_dev,
374 : : struct rte_eth_pfc_queue_conf *pfc_conf)
375 : : {
376 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
377 : : struct rte_eth_dev_data *data = eth_dev->data;
378 : 0 : struct roc_nix *nix = &dev->nix;
379 : : enum rte_eth_fc_mode mode;
380 : : uint8_t en, tc;
381 : : uint16_t qid;
382 : : int rc = 0;
383 : :
384 [ # # ]: 0 : if (dev->fc_cfg.mode != RTE_ETH_FC_NONE) {
385 : 0 : plt_err("Disable Flow Control before configuring PFC");
386 : 0 : return -ENOTSUP;
387 : : }
388 : :
389 [ # # # # ]: 0 : if (roc_nix_is_sdp(nix) || roc_nix_is_lbk(nix)) {
390 : 0 : plt_nix_dbg("Prio flow ctrl config is not allowed on SDP/LBK");
391 : 0 : return -ENOTSUP;
392 : : }
393 : :
394 : : /* Disallow flow control changes when device is in started state */
395 [ # # ]: 0 : if (data->dev_started) {
396 : 0 : plt_info("Stop the port=%d for setting PFC", data->port_id);
397 : 0 : return -EBUSY;
398 : : }
399 : :
400 : 0 : mode = pfc_conf->mode;
401 : :
402 : : /* Perform Tx pause configuration on RQ */
403 : 0 : qid = pfc_conf->tx_pause.rx_qid;
404 [ # # ]: 0 : if (qid < eth_dev->data->nb_rx_queues) {
405 : 0 : en = (mode == RTE_ETH_FC_FULL) || (mode == RTE_ETH_FC_TX_PAUSE);
406 : 0 : tc = pfc_conf->tx_pause.tc;
407 : 0 : rc = nix_priority_flow_ctrl_rq_conf(eth_dev, qid, en, tc);
408 : : }
409 : :
410 : : /* Perform Rx pause configuration on SQ */
411 : 0 : qid = pfc_conf->rx_pause.tx_qid;
412 [ # # ]: 0 : if (qid < eth_dev->data->nb_tx_queues) {
413 : 0 : en = (mode == RTE_ETH_FC_FULL) || (mode == RTE_ETH_FC_RX_PAUSE);
414 : 0 : tc = pfc_conf->rx_pause.tc;
415 : 0 : rc |= nix_priority_flow_ctrl_sq_conf(eth_dev, qid, en, tc);
416 : : }
417 : :
418 : : return rc;
419 : : }
420 : :
421 : : int
422 : 0 : cnxk_nix_flow_ops_get(struct rte_eth_dev *eth_dev,
423 : : const struct rte_flow_ops **ops)
424 : : {
425 : : RTE_SET_USED(eth_dev);
426 : :
427 : 0 : *ops = &cnxk_flow_ops;
428 : 0 : return 0;
429 : : }
430 : :
431 : : int
432 : 0 : cnxk_nix_mac_addr_set(struct rte_eth_dev *eth_dev, struct rte_ether_addr *addr)
433 : : {
434 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
435 : 0 : struct roc_nix *nix = &dev->nix;
436 : : int rc;
437 : :
438 : : /* Update mac address at NPC */
439 : 0 : rc = roc_nix_npc_mac_addr_set(nix, addr->addr_bytes);
440 [ # # ]: 0 : if (rc)
441 : 0 : goto exit;
442 : :
443 : : /* Update mac address at CGX for PFs only */
444 [ # # ]: 0 : if (!roc_nix_is_vf_or_sdp(nix)) {
445 : 0 : rc = roc_nix_mac_addr_set(nix, addr->addr_bytes);
446 [ # # ]: 0 : if (rc) {
447 : : /* Rollback to previous mac address */
448 : 0 : roc_nix_npc_mac_addr_set(nix, dev->mac_addr);
449 : 0 : goto exit;
450 : : }
451 : : }
452 : :
453 : : /* Update mac address to cnxk ethernet device */
454 [ # # ]: 0 : rte_memcpy(dev->mac_addr, addr->addr_bytes, RTE_ETHER_ADDR_LEN);
455 : :
456 : 0 : exit:
457 : 0 : return rc;
458 : : }
459 : :
460 : : int
461 : 0 : cnxk_nix_mac_addr_add(struct rte_eth_dev *eth_dev, struct rte_ether_addr *addr,
462 : : uint32_t index, uint32_t pool)
463 : : {
464 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
465 : 0 : struct roc_nix *nix = &dev->nix;
466 : : int rc;
467 : :
468 : : PLT_SET_USED(index);
469 : : PLT_SET_USED(pool);
470 : :
471 : 0 : rc = roc_nix_mac_addr_add(nix, addr->addr_bytes);
472 [ # # ]: 0 : if (rc < 0) {
473 : 0 : plt_err("Failed to add mac address, rc=%d", rc);
474 : 0 : return rc;
475 : : }
476 : :
477 : 0 : dev->dmac_idx_map[index] = rc;
478 : :
479 : : /* Enable promiscuous mode at NIX level */
480 : 0 : roc_nix_npc_promisc_ena_dis(nix, true);
481 : 0 : dev->dmac_filter_enable = true;
482 : 0 : eth_dev->data->promiscuous = false;
483 : 0 : dev->dmac_filter_count++;
484 : :
485 : 0 : return 0;
486 : : }
487 : :
488 : : void
489 : 0 : cnxk_nix_mac_addr_del(struct rte_eth_dev *eth_dev, uint32_t index)
490 : : {
491 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
492 : 0 : struct roc_nix *nix = &dev->nix;
493 : : int rc;
494 : :
495 : 0 : rc = roc_nix_mac_addr_del(nix, dev->dmac_idx_map[index]);
496 [ # # ]: 0 : if (rc)
497 : 0 : plt_err("Failed to delete mac address, rc=%d", rc);
498 : :
499 : 0 : dev->dmac_filter_count--;
500 : 0 : }
501 : :
502 : : int
503 : 0 : cnxk_nix_sq_flush(struct rte_eth_dev *eth_dev)
504 : : {
505 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
506 : : struct rte_eth_dev_data *data = eth_dev->data;
507 : : int i, rc = 0;
508 : :
509 : : /* Flush all tx queues */
510 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
511 : 0 : struct roc_nix_sq *sq = &dev->sqs[i];
512 : :
513 [ # # ]: 0 : if (eth_dev->data->tx_queues[i] == NULL)
514 : 0 : continue;
515 : :
516 : 0 : rc = roc_nix_tm_sq_aura_fc(sq, false);
517 [ # # ]: 0 : if (rc) {
518 : 0 : plt_err("Failed to disable sqb aura fc, rc=%d", rc);
519 : 0 : goto exit;
520 : : }
521 : :
522 : : /* Wait for sq entries to be flushed */
523 : 0 : rc = roc_nix_tm_sq_flush_spin(sq);
524 [ # # ]: 0 : if (rc) {
525 : 0 : plt_err("Failed to drain sq, rc=%d\n", rc);
526 : 0 : goto exit;
527 : : }
528 [ # # ]: 0 : if (data->tx_queue_state[i] == RTE_ETH_QUEUE_STATE_STARTED) {
529 : 0 : rc = roc_nix_tm_sq_aura_fc(sq, true);
530 [ # # ]: 0 : if (rc) {
531 : 0 : plt_err("Failed to enable sq aura fc, txq=%u, rc=%d", i, rc);
532 : 0 : goto exit;
533 : : }
534 : : }
535 : : }
536 : 0 : exit:
537 : 0 : return rc;
538 : : }
539 : :
540 : : int
541 : 0 : cnxk_nix_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
542 : : {
543 [ # # ]: 0 : uint32_t old_frame_size, frame_size = mtu + CNXK_NIX_L2_OVERHEAD;
544 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
545 : : struct rte_eth_dev_data *data = eth_dev->data;
546 : 0 : struct roc_nix *nix = &dev->nix;
547 : : int rc = -EINVAL;
548 : : uint32_t buffsz;
549 : :
550 : 0 : frame_size += CNXK_NIX_TIMESYNC_RX_OFFSET * dev->ptp_en;
551 : :
552 : : /* Check if MTU is within the allowed range */
553 [ # # ]: 0 : if ((frame_size - RTE_ETHER_CRC_LEN) < NIX_MIN_HW_FRS) {
554 : 0 : plt_err("MTU is lesser than minimum");
555 : 0 : goto exit;
556 : : }
557 : :
558 : 0 : if ((frame_size - RTE_ETHER_CRC_LEN) >
559 [ # # ]: 0 : ((uint32_t)roc_nix_max_pkt_len(nix))) {
560 : 0 : plt_err("MTU is greater than maximum");
561 : 0 : goto exit;
562 : : }
563 : :
564 : 0 : buffsz = data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM;
565 : 0 : old_frame_size = data->mtu + CNXK_NIX_L2_OVERHEAD;
566 : :
567 : : /* Refuse MTU that requires the support of scattered packets
568 : : * when this feature has not been enabled before.
569 : : */
570 [ # # # # ]: 0 : if (data->dev_started && frame_size > buffsz &&
571 [ # # ]: 0 : !(dev->rx_offloads & RTE_ETH_RX_OFFLOAD_SCATTER)) {
572 : 0 : plt_err("Scatter offload is not enabled for mtu");
573 : 0 : goto exit;
574 : : }
575 : :
576 : : /* Check <seg size> * <max_seg> >= max_frame */
577 [ # # ]: 0 : if ((dev->rx_offloads & RTE_ETH_RX_OFFLOAD_SCATTER) &&
578 [ # # ]: 0 : frame_size > (buffsz * CNXK_NIX_RX_NB_SEG_MAX)) {
579 : 0 : plt_err("Greater than maximum supported packet length");
580 : 0 : goto exit;
581 : : }
582 : :
583 : : /* if new MTU was smaller than old one, then flush all SQs before MTU change */
584 [ # # ]: 0 : if (old_frame_size > frame_size) {
585 [ # # ]: 0 : if (data->dev_started) {
586 : 0 : plt_err("Reducing MTU is not supported when device started");
587 : 0 : goto exit;
588 : : }
589 : 0 : cnxk_nix_sq_flush(eth_dev);
590 : : }
591 : :
592 : : frame_size -= RTE_ETHER_CRC_LEN;
593 : :
594 : : /* Update mtu on Tx */
595 : 0 : rc = roc_nix_mac_mtu_set(nix, frame_size);
596 [ # # ]: 0 : if (rc) {
597 : 0 : plt_err("Failed to set MTU, rc=%d", rc);
598 : 0 : goto exit;
599 : : }
600 : :
601 : : /* Sync same frame size on Rx */
602 : 0 : rc = roc_nix_mac_max_rx_len_set(nix, frame_size);
603 [ # # ]: 0 : if (rc) {
604 : : /* Rollback to older mtu */
605 : 0 : roc_nix_mac_mtu_set(nix,
606 : 0 : old_frame_size - RTE_ETHER_CRC_LEN);
607 : 0 : plt_err("Failed to max Rx frame length, rc=%d", rc);
608 : 0 : goto exit;
609 : : }
610 : 0 : exit:
611 : 0 : return rc;
612 : : }
613 : :
614 : : int
615 : 0 : cnxk_nix_promisc_enable(struct rte_eth_dev *eth_dev)
616 : : {
617 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
618 : 0 : struct roc_nix *nix = &dev->nix;
619 : : int rc = 0;
620 : :
621 [ # # ]: 0 : if (roc_nix_is_vf_or_sdp(nix))
622 : : return rc;
623 : :
624 : 0 : rc = roc_nix_npc_promisc_ena_dis(nix, true);
625 [ # # ]: 0 : if (rc) {
626 : 0 : plt_err("Failed to setup promisc mode in npc, rc=%d(%s)", rc,
627 : : roc_error_msg_get(rc));
628 : 0 : return rc;
629 : : }
630 : :
631 : 0 : rc = roc_nix_mac_promisc_mode_enable(nix, true);
632 [ # # ]: 0 : if (rc) {
633 : 0 : plt_err("Failed to setup promisc mode in mac, rc=%d(%s)", rc,
634 : : roc_error_msg_get(rc));
635 : 0 : roc_nix_npc_promisc_ena_dis(nix, false);
636 : 0 : return rc;
637 : : }
638 : :
639 : : return 0;
640 : : }
641 : :
642 : : int
643 : 0 : cnxk_nix_promisc_disable(struct rte_eth_dev *eth_dev)
644 : : {
645 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
646 : 0 : struct roc_nix *nix = &dev->nix;
647 : : int rc = 0;
648 : :
649 [ # # ]: 0 : if (roc_nix_is_vf_or_sdp(nix))
650 : : return rc;
651 : :
652 : 0 : rc = roc_nix_npc_promisc_ena_dis(nix, dev->dmac_filter_enable);
653 [ # # ]: 0 : if (rc) {
654 : 0 : plt_err("Failed to setup promisc mode in npc, rc=%d(%s)", rc,
655 : : roc_error_msg_get(rc));
656 : 0 : return rc;
657 : : }
658 : :
659 : 0 : rc = roc_nix_mac_promisc_mode_enable(nix, false);
660 [ # # ]: 0 : if (rc) {
661 : 0 : plt_err("Failed to setup promisc mode in mac, rc=%d(%s)", rc,
662 : : roc_error_msg_get(rc));
663 : 0 : roc_nix_npc_promisc_ena_dis(nix, !dev->dmac_filter_enable);
664 : 0 : return rc;
665 : : }
666 : :
667 : 0 : dev->dmac_filter_enable = false;
668 : 0 : return 0;
669 : : }
670 : :
671 : : int
672 : 0 : cnxk_nix_allmulticast_enable(struct rte_eth_dev *eth_dev)
673 : : {
674 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
675 : :
676 : 0 : return roc_nix_npc_mcast_config(&dev->nix, true,
677 : 0 : eth_dev->data->promiscuous);
678 : : }
679 : :
680 : : int
681 : 0 : cnxk_nix_allmulticast_disable(struct rte_eth_dev *eth_dev)
682 : : {
683 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
684 : :
685 : 0 : return roc_nix_npc_mcast_config(&dev->nix, false,
686 : 0 : eth_dev->data->promiscuous);
687 : : }
688 : :
689 : : int
690 : 0 : cnxk_nix_set_link_up(struct rte_eth_dev *eth_dev)
691 : : {
692 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
693 : 0 : struct roc_nix *nix = &dev->nix;
694 : : int rc, i;
695 : :
696 [ # # ]: 0 : if (roc_nix_is_vf_or_sdp(nix))
697 : : return -ENOTSUP;
698 : :
699 : 0 : rc = roc_nix_mac_link_state_set(nix, true);
700 [ # # ]: 0 : if (rc)
701 : 0 : goto exit;
702 : :
703 : : /* Start tx queues */
704 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
705 : 0 : rc = cnxk_nix_tx_queue_start(eth_dev, i);
706 [ # # ]: 0 : if (rc)
707 : 0 : goto exit;
708 : : }
709 : :
710 : 0 : exit:
711 : : return rc;
712 : : }
713 : :
714 : : int
715 : 0 : cnxk_nix_set_link_down(struct rte_eth_dev *eth_dev)
716 : : {
717 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
718 : 0 : struct roc_nix *nix = &dev->nix;
719 : : int rc, i;
720 : :
721 [ # # ]: 0 : if (roc_nix_is_vf_or_sdp(nix))
722 : : return -ENOTSUP;
723 : :
724 : : /* Stop tx queues */
725 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
726 : 0 : rc = cnxk_nix_tx_queue_stop(eth_dev, i);
727 [ # # ]: 0 : if (rc)
728 : 0 : goto exit;
729 : : }
730 : :
731 : 0 : rc = roc_nix_mac_link_state_set(nix, false);
732 : : exit:
733 : : return rc;
734 : : }
735 : :
736 : : int
737 : 0 : cnxk_nix_get_module_info(struct rte_eth_dev *eth_dev,
738 : : struct rte_eth_dev_module_info *modinfo)
739 : : {
740 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
741 : 0 : struct roc_nix_eeprom_info eeprom_info = {0};
742 : 0 : struct roc_nix *nix = &dev->nix;
743 : : int rc;
744 : :
745 : 0 : rc = roc_nix_eeprom_info_get(nix, &eeprom_info);
746 [ # # ]: 0 : if (rc)
747 : : return rc;
748 : :
749 : 0 : modinfo->type = eeprom_info.sff_id;
750 : 0 : modinfo->eeprom_len = ROC_NIX_EEPROM_SIZE;
751 : 0 : return 0;
752 : : }
753 : :
754 : : int
755 [ # # ]: 0 : cnxk_nix_get_module_eeprom(struct rte_eth_dev *eth_dev,
756 : : struct rte_dev_eeprom_info *info)
757 : : {
758 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
759 : 0 : struct roc_nix_eeprom_info eeprom_info = {0};
760 : 0 : struct roc_nix *nix = &dev->nix;
761 : : int rc = -EINVAL;
762 : :
763 [ # # # # ]: 0 : if (!info->data || !info->length ||
764 [ # # ]: 0 : (info->offset + info->length > ROC_NIX_EEPROM_SIZE))
765 : : return rc;
766 : :
767 : 0 : rc = roc_nix_eeprom_info_get(nix, &eeprom_info);
768 [ # # ]: 0 : if (rc)
769 : : return rc;
770 : :
771 [ # # ]: 0 : rte_memcpy(info->data, eeprom_info.buf + info->offset, info->length);
772 : : return 0;
773 : : }
774 : :
775 : : int
776 : 0 : cnxk_nix_rx_queue_intr_enable(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
777 : : {
778 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
779 : :
780 : 0 : roc_nix_rx_queue_intr_enable(&dev->nix, rx_queue_id);
781 : 0 : return 0;
782 : : }
783 : :
784 : : int
785 : 0 : cnxk_nix_rx_queue_intr_disable(struct rte_eth_dev *eth_dev,
786 : : uint16_t rx_queue_id)
787 : : {
788 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
789 : :
790 : 0 : roc_nix_rx_queue_intr_disable(&dev->nix, rx_queue_id);
791 : 0 : return 0;
792 : : }
793 : :
794 : : int
795 : 0 : cnxk_nix_pool_ops_supported(struct rte_eth_dev *eth_dev, const char *pool)
796 : : {
797 : : RTE_SET_USED(eth_dev);
798 : :
799 [ # # ]: 0 : if (!strcmp(pool, rte_mbuf_platform_mempool_ops()))
800 : 0 : return 0;
801 : :
802 : : return -ENOTSUP;
803 : : }
804 : :
805 : : int
806 : 0 : cnxk_nix_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
807 : : size_t fw_size)
808 : : {
809 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
810 : 0 : const char *str = roc_npc_profile_name_get(&dev->npc);
811 : 0 : uint32_t size = strlen(str) + 1;
812 : :
813 [ # # ]: 0 : if (fw_size > size)
814 : : fw_size = size;
815 : :
816 : : rte_strlcpy(fw_version, str, fw_size);
817 : :
818 [ # # ]: 0 : if (fw_size < size)
819 : 0 : return size;
820 : :
821 : : return 0;
822 : : }
823 : :
824 : : void
825 : 0 : cnxk_nix_rxq_info_get(struct rte_eth_dev *eth_dev, uint16_t qid,
826 : : struct rte_eth_rxq_info *qinfo)
827 : : {
828 : 0 : void *rxq = eth_dev->data->rx_queues[qid];
829 : : struct cnxk_eth_rxq_sp *rxq_sp = cnxk_eth_rxq_to_sp(rxq);
830 : :
831 : : memset(qinfo, 0, sizeof(*qinfo));
832 : :
833 : 0 : qinfo->mp = rxq_sp->qconf.mp;
834 : 0 : qinfo->scattered_rx = eth_dev->data->scattered_rx;
835 : 0 : qinfo->nb_desc = rxq_sp->qconf.nb_desc;
836 : :
837 : 0 : memcpy(&qinfo->conf, &rxq_sp->qconf.conf.rx, sizeof(qinfo->conf));
838 : 0 : }
839 : :
840 : : void
841 : 0 : cnxk_nix_txq_info_get(struct rte_eth_dev *eth_dev, uint16_t qid,
842 : : struct rte_eth_txq_info *qinfo)
843 : : {
844 : 0 : void *txq = eth_dev->data->tx_queues[qid];
845 : : struct cnxk_eth_txq_sp *txq_sp = cnxk_eth_txq_to_sp(txq);
846 : :
847 : : memset(qinfo, 0, sizeof(*qinfo));
848 : :
849 : 0 : qinfo->nb_desc = txq_sp->qconf.nb_desc;
850 : :
851 : 0 : memcpy(&qinfo->conf, &txq_sp->qconf.conf.tx, sizeof(qinfo->conf));
852 : 0 : }
853 : :
854 : : uint32_t
855 : 0 : cnxk_nix_rx_queue_count(void *rxq)
856 : : {
857 : : struct cnxk_eth_rxq_sp *rxq_sp = cnxk_eth_rxq_to_sp(rxq);
858 : 0 : struct roc_nix *nix = &rxq_sp->dev->nix;
859 : : uint32_t head, tail;
860 : :
861 : 0 : roc_nix_cq_head_tail_get(nix, rxq_sp->qid, &head, &tail);
862 : 0 : return (tail - head) % (rxq_sp->qconf.nb_desc);
863 : : }
864 : :
865 : : static inline int
866 : : nix_offset_has_packet(uint32_t head, uint32_t tail, uint16_t offset, bool is_rx)
867 : : {
868 : : /* Check given offset(queue index) has packet filled/xmit by HW
869 : : * in case of Rx or Tx.
870 : : * Also, checks for wrap around case.
871 : : */
872 [ # # # # : 0 : return ((tail > head && offset <= tail && offset >= head) ||
# # # # #
# # # ]
873 [ # # # # : 0 : (head > tail && (offset >= head || offset <= tail))) ?
# # # # ]
874 : 0 : is_rx :
875 : : !is_rx;
876 : : }
877 : :
878 : : int
879 : 0 : cnxk_nix_rx_descriptor_status(void *rxq, uint16_t offset)
880 : : {
881 : : struct cnxk_eth_rxq_sp *rxq_sp = cnxk_eth_rxq_to_sp(rxq);
882 : 0 : struct roc_nix *nix = &rxq_sp->dev->nix;
883 : : uint32_t head, tail;
884 : :
885 [ # # ]: 0 : if (rxq_sp->qconf.nb_desc <= offset)
886 : : return -EINVAL;
887 : :
888 : 0 : roc_nix_cq_head_tail_get(nix, rxq_sp->qid, &head, &tail);
889 : :
890 [ # # ]: 0 : if (nix_offset_has_packet(head, tail, offset, 1))
891 : 0 : return RTE_ETH_RX_DESC_DONE;
892 : : else
893 : : return RTE_ETH_RX_DESC_AVAIL;
894 : : }
895 : :
896 : : int
897 : 0 : cnxk_nix_tx_descriptor_status(void *txq, uint16_t offset)
898 : : {
899 : : struct cnxk_eth_txq_sp *txq_sp = cnxk_eth_txq_to_sp(txq);
900 : 0 : struct roc_nix *nix = &txq_sp->dev->nix;
901 : 0 : uint32_t head = 0, tail = 0;
902 : :
903 [ # # ]: 0 : if (txq_sp->qconf.nb_desc <= offset)
904 : : return -EINVAL;
905 : :
906 : 0 : roc_nix_sq_head_tail_get(nix, txq_sp->qid, &head, &tail);
907 : :
908 [ # # ]: 0 : if (nix_offset_has_packet(head, tail, offset, 0))
909 : : return RTE_ETH_TX_DESC_DONE;
910 : : else
911 : 0 : return RTE_ETH_TX_DESC_FULL;
912 : : }
913 : :
914 : : /* It is a NOP for cnxk as HW frees the buffer on xmit */
915 : : int
916 : 0 : cnxk_nix_tx_done_cleanup(void *txq, uint32_t free_cnt)
917 : : {
918 : : RTE_SET_USED(txq);
919 : : RTE_SET_USED(free_cnt);
920 : :
921 : 0 : return 0;
922 : : }
923 : :
924 : : int
925 [ # # ]: 0 : cnxk_nix_dev_get_reg(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
926 : : {
927 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
928 : 0 : struct roc_nix *nix = &dev->nix;
929 : 0 : uint64_t *data = regs->data;
930 : : int rc = -ENOTSUP;
931 : :
932 [ # # ]: 0 : if (data == NULL) {
933 : 0 : rc = roc_nix_lf_get_reg_count(nix);
934 [ # # ]: 0 : if (rc > 0) {
935 : 0 : regs->length = rc;
936 : 0 : regs->width = 8;
937 : : rc = 0;
938 : : }
939 : 0 : return rc;
940 : : }
941 : :
942 [ # # ]: 0 : if (!regs->length ||
943 [ # # ]: 0 : regs->length == (uint32_t)roc_nix_lf_get_reg_count(nix))
944 : 0 : return roc_nix_lf_reg_dump(nix, data);
945 : :
946 : : return rc;
947 : : }
948 : :
949 : : int
950 [ # # ]: 0 : cnxk_nix_reta_update(struct rte_eth_dev *eth_dev,
951 : : struct rte_eth_rss_reta_entry64 *reta_conf,
952 : : uint16_t reta_size)
953 : : {
954 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
955 : : uint16_t reta[ROC_NIX_RSS_RETA_MAX];
956 : 0 : struct roc_nix *nix = &dev->nix;
957 : : int i, j, rc = -EINVAL, idx = 0;
958 : :
959 [ # # ]: 0 : if (reta_size != dev->nix.reta_sz) {
960 : 0 : plt_err("Size of hash lookup table configured (%d) does not "
961 : : "match the number hardware can supported (%d)",
962 : : reta_size, dev->nix.reta_sz);
963 : 0 : goto fail;
964 : : }
965 : :
966 : 0 : roc_nix_rss_reta_get(nix, 0, reta);
967 : :
968 : : /* Copy RETA table */
969 [ # # ]: 0 : for (i = 0; i < (int)(dev->nix.reta_sz / RTE_ETH_RETA_GROUP_SIZE); i++) {
970 [ # # ]: 0 : for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++) {
971 [ # # ]: 0 : if ((reta_conf[i].mask >> j) & 0x01)
972 : 0 : reta[idx] = reta_conf[i].reta[j];
973 : 0 : idx++;
974 : : }
975 : : }
976 : :
977 : 0 : return roc_nix_rss_reta_set(nix, 0, reta);
978 : :
979 : : fail:
980 : 0 : return rc;
981 : : }
982 : :
983 : : int
984 [ # # ]: 0 : cnxk_nix_reta_query(struct rte_eth_dev *eth_dev,
985 : : struct rte_eth_rss_reta_entry64 *reta_conf,
986 : : uint16_t reta_size)
987 : : {
988 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
989 : : uint16_t reta[ROC_NIX_RSS_RETA_MAX];
990 : 0 : struct roc_nix *nix = &dev->nix;
991 : : int rc = -EINVAL, i, j, idx = 0;
992 : :
993 [ # # ]: 0 : if (reta_size != dev->nix.reta_sz) {
994 : 0 : plt_err("Size of hash lookup table configured (%d) does not "
995 : : "match the number hardware can supported (%d)",
996 : : reta_size, dev->nix.reta_sz);
997 : 0 : goto fail;
998 : : }
999 : :
1000 : 0 : rc = roc_nix_rss_reta_get(nix, 0, reta);
1001 [ # # ]: 0 : if (rc)
1002 : 0 : goto fail;
1003 : :
1004 : : /* Copy RETA table */
1005 [ # # ]: 0 : for (i = 0; i < (int)(dev->nix.reta_sz / RTE_ETH_RETA_GROUP_SIZE); i++) {
1006 [ # # ]: 0 : for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++) {
1007 [ # # ]: 0 : if ((reta_conf[i].mask >> j) & 0x01)
1008 : 0 : reta_conf[i].reta[j] = reta[idx];
1009 : 0 : idx++;
1010 : : }
1011 : : }
1012 : :
1013 : : return 0;
1014 : :
1015 : : fail:
1016 : : return rc;
1017 : : }
1018 : :
1019 : : int
1020 : 0 : cnxk_nix_eth_dev_priv_dump(struct rte_eth_dev *eth_dev, FILE *file)
1021 : : {
1022 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1023 : 0 : struct roc_nix *roc_nix = &dev->nix;
1024 : : int i;
1025 : :
1026 : 0 : roc_nix_dump(roc_nix, file);
1027 : :
1028 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_rx_queues; i++)
1029 : 0 : roc_nix_rq_dump(&dev->rqs[i], file);
1030 : :
1031 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_rx_queues; i++)
1032 : 0 : roc_nix_cq_dump(&dev->cqs[i], file);
1033 : :
1034 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
1035 : 0 : roc_nix_sq_dump(&dev->sqs[i], file);
1036 : :
1037 : 0 : roc_nix_queues_ctx_dump(roc_nix, file);
1038 : :
1039 : 0 : roc_nix_tm_dump(roc_nix, file);
1040 : :
1041 : 0 : roc_nix_inl_dev_dump(NULL, file);
1042 : :
1043 : 0 : roc_nix_inl_outb_cpt_lfs_dump(roc_nix, file);
1044 : :
1045 : 0 : return 0;
1046 : : }
1047 : :
1048 : : int
1049 [ # # ]: 0 : cnxk_nix_rss_hash_update(struct rte_eth_dev *eth_dev,
1050 : : struct rte_eth_rss_conf *rss_conf)
1051 : : {
1052 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1053 : 0 : struct roc_nix *nix = &dev->nix;
1054 : : uint8_t rss_hash_level;
1055 : : uint32_t flowkey_cfg;
1056 : : int rc = -EINVAL;
1057 : : uint8_t alg_idx;
1058 : :
1059 [ # # # # ]: 0 : if (rss_conf->rss_key && rss_conf->rss_key_len != ROC_NIX_RSS_KEY_LEN) {
1060 : 0 : plt_err("Hash key size mismatch %d vs %d",
1061 : : rss_conf->rss_key_len, ROC_NIX_RSS_KEY_LEN);
1062 : 0 : goto fail;
1063 : : }
1064 : :
1065 [ # # ]: 0 : if (rss_conf->rss_key)
1066 : 0 : roc_nix_rss_key_set(nix, rss_conf->rss_key);
1067 : :
1068 : 0 : rss_hash_level = RTE_ETH_RSS_LEVEL(rss_conf->rss_hf);
1069 [ # # ]: 0 : if (rss_hash_level)
1070 : 0 : rss_hash_level -= 1;
1071 : : flowkey_cfg =
1072 : 0 : cnxk_rss_ethdev_to_nix(dev, rss_conf->rss_hf, rss_hash_level);
1073 : :
1074 : 0 : rc = roc_nix_rss_flowkey_set(nix, &alg_idx, flowkey_cfg,
1075 : : ROC_NIX_RSS_GROUP_DEFAULT,
1076 : : ROC_NIX_RSS_MCAM_IDX_DEFAULT);
1077 [ # # ]: 0 : if (rc) {
1078 : 0 : plt_err("Failed to set RSS hash function rc=%d", rc);
1079 : 0 : return rc;
1080 : : }
1081 : :
1082 : 0 : fail:
1083 : : return rc;
1084 : : }
1085 : :
1086 : : int
1087 [ # # ]: 0 : cnxk_nix_rss_hash_conf_get(struct rte_eth_dev *eth_dev,
1088 : : struct rte_eth_rss_conf *rss_conf)
1089 : : {
1090 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1091 : :
1092 [ # # ]: 0 : if (rss_conf->rss_key)
1093 : 0 : roc_nix_rss_key_get(&dev->nix, rss_conf->rss_key);
1094 : :
1095 : 0 : rss_conf->rss_key_len = ROC_NIX_RSS_KEY_LEN;
1096 : 0 : rss_conf->rss_hf = dev->ethdev_rss_hf;
1097 : :
1098 : 0 : return 0;
1099 : : }
1100 : :
1101 : : int
1102 : 0 : cnxk_nix_mc_addr_list_configure(struct rte_eth_dev *eth_dev,
1103 : : struct rte_ether_addr *mc_addr_set,
1104 : : uint32_t nb_mc_addr)
1105 : : {
1106 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1107 : : struct rte_eth_dev_data *data = eth_dev->data;
1108 : : struct rte_ether_addr null_mac_addr;
1109 : 0 : struct roc_nix *nix = &dev->nix;
1110 : : int rc, index;
1111 : : uint32_t i;
1112 : :
1113 : : memset(&null_mac_addr, 0, sizeof(null_mac_addr));
1114 : :
1115 : : /* All configured multicast filters should be flushed first */
1116 [ # # ]: 0 : for (i = 0; i < dev->max_mac_entries; i++) {
1117 [ # # ]: 0 : if (rte_is_multicast_ether_addr(&data->mac_addrs[i])) {
1118 : 0 : rc = roc_nix_mac_addr_del(nix, i);
1119 [ # # ]: 0 : if (rc) {
1120 : 0 : plt_err("Failed to flush mcast address, rc=%d",
1121 : : rc);
1122 : 0 : return rc;
1123 : : }
1124 : :
1125 : 0 : dev->dmac_filter_count--;
1126 : : /* Update address in NIC data structure */
1127 : 0 : rte_ether_addr_copy(&null_mac_addr,
1128 : 0 : &data->mac_addrs[i]);
1129 : : }
1130 : : }
1131 : :
1132 [ # # ]: 0 : if (!mc_addr_set || !nb_mc_addr)
1133 : : return 0;
1134 : :
1135 : : /* Check for available space */
1136 : 0 : if (nb_mc_addr >
1137 [ # # ]: 0 : ((uint32_t)(dev->max_mac_entries - dev->dmac_filter_count))) {
1138 : 0 : plt_err("No space is available to add multicast filters");
1139 : 0 : return -ENOSPC;
1140 : : }
1141 : :
1142 : : /* Multicast addresses are to be installed */
1143 [ # # ]: 0 : for (i = 0; i < nb_mc_addr; i++) {
1144 : 0 : index = roc_nix_mac_addr_add(nix, mc_addr_set[i].addr_bytes);
1145 [ # # ]: 0 : if (index < 0) {
1146 : 0 : plt_err("Failed to add mcast mac address, rc=%d",
1147 : : index);
1148 : 0 : return index;
1149 : : }
1150 : :
1151 : 0 : dev->dmac_filter_count++;
1152 : : /* Update address in NIC data structure */
1153 : 0 : rte_ether_addr_copy(&mc_addr_set[i], &data->mac_addrs[index]);
1154 : : }
1155 : :
1156 : 0 : roc_nix_npc_promisc_ena_dis(nix, true);
1157 : 0 : dev->dmac_filter_enable = true;
1158 : 0 : eth_dev->data->promiscuous = false;
1159 : :
1160 : 0 : return 0;
1161 : : }
1162 : :
1163 : : int
1164 [ # # ]: 0 : nix_priority_flow_ctrl_rq_conf(struct rte_eth_dev *eth_dev, uint16_t qid,
1165 : : uint8_t tx_pause, uint8_t tc)
1166 : : {
1167 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1168 : : struct rte_eth_dev_data *data = eth_dev->data;
1169 : : struct cnxk_pfc_cfg *pfc = &dev->pfc_cfg;
1170 : 0 : struct roc_nix *nix = &dev->nix;
1171 : : struct roc_nix_pfc_cfg pfc_cfg;
1172 : : struct roc_nix_fc_cfg fc_cfg;
1173 : : struct cnxk_eth_rxq_sp *rxq;
1174 : : enum roc_nix_fc_mode mode;
1175 : : struct roc_nix_rq *rq;
1176 : : struct roc_nix_cq *cq;
1177 : : int rc, i;
1178 : :
1179 [ # # ]: 0 : if (data->dev_started) {
1180 : : /* RQ should be in disabled state
1181 : : * while setting flow control configuration.
1182 : : */
1183 : 0 : plt_info("Stop the port=%d for setting flow control",
1184 : : data->port_id);
1185 : 0 : return 0;
1186 : : }
1187 : :
1188 [ # # ]: 0 : if (data->rx_queues == NULL)
1189 : : return -EINVAL;
1190 : :
1191 [ # # ]: 0 : if (qid >= eth_dev->data->nb_rx_queues)
1192 : : return -ENOTSUP;
1193 : :
1194 : : /* Configure RQ */
1195 : 0 : rxq = ((struct cnxk_eth_rxq_sp *)data->rx_queues[qid]) - 1;
1196 : 0 : rq = &dev->rqs[qid];
1197 : 0 : cq = &dev->cqs[qid];
1198 : :
1199 : : memset(&fc_cfg, 0, sizeof(struct roc_nix_fc_cfg));
1200 : 0 : fc_cfg.type = ROC_NIX_FC_RQ_CFG;
1201 : 0 : fc_cfg.rq_cfg.tc = tc;
1202 : 0 : fc_cfg.rq_cfg.enable = !!tx_pause;
1203 : 0 : fc_cfg.rq_cfg.rq = rq->qid;
1204 : 0 : fc_cfg.rq_cfg.pool = rxq->qconf.mp->pool_id;
1205 : 0 : fc_cfg.rq_cfg.spb_pool = rq->spb_aura_handle;
1206 : 0 : fc_cfg.rq_cfg.cq_drop = cq->drop_thresh;
1207 : 0 : fc_cfg.rq_cfg.pool_drop_pct = ROC_NIX_AURA_THRESH;
1208 : 0 : rc = roc_nix_fc_config_set(nix, &fc_cfg);
1209 [ # # ]: 0 : if (rc)
1210 : : return rc;
1211 : :
1212 : 0 : rxq->tx_pause = !!tx_pause;
1213 : 0 : rxq->tc = tc;
1214 : : /* Recheck number of RQ's that have PFC enabled */
1215 : 0 : pfc->tx_pause_en = 0;
1216 [ # # ]: 0 : for (i = 0; i < dev->nb_rxq; i++)
1217 [ # # ]: 0 : if (dev->rqs[i].tc != ROC_NIX_PFC_CLASS_INVALID)
1218 : 0 : pfc->tx_pause_en++;
1219 : :
1220 : : /* Skip if PFC already enabled in mac */
1221 [ # # ]: 0 : if (pfc->tx_pause_en > 1)
1222 : : return 0;
1223 : :
1224 : : /* Configure MAC block */
1225 [ # # ]: 0 : pfc->class_en = pfc->tx_pause_en ? 0xFF : 0x0;
1226 : :
1227 [ # # ]: 0 : if (pfc->rx_pause_en)
1228 [ # # ]: 0 : mode = pfc->tx_pause_en ? ROC_NIX_FC_FULL : ROC_NIX_FC_RX;
1229 : : else
1230 [ # # ]: 0 : mode = pfc->tx_pause_en ? ROC_NIX_FC_TX : ROC_NIX_FC_NONE;
1231 : :
1232 : : memset(&pfc_cfg, 0, sizeof(struct roc_nix_pfc_cfg));
1233 : 0 : pfc_cfg.mode = mode;
1234 : 0 : pfc_cfg.tc = pfc->class_en;
1235 : 0 : return roc_nix_pfc_mode_set(nix, &pfc_cfg);
1236 : : }
1237 : :
1238 : : int
1239 [ # # ]: 0 : nix_priority_flow_ctrl_sq_conf(struct rte_eth_dev *eth_dev, uint16_t qid,
1240 : : uint8_t rx_pause, uint8_t tc)
1241 : : {
1242 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1243 : : struct rte_eth_dev_data *data = eth_dev->data;
1244 : : struct cnxk_pfc_cfg *pfc = &dev->pfc_cfg;
1245 : 0 : struct roc_nix *nix = &dev->nix;
1246 : : struct roc_nix_pfc_cfg pfc_cfg;
1247 : : struct roc_nix_fc_cfg fc_cfg;
1248 : : struct cnxk_eth_txq_sp *txq;
1249 : : enum roc_nix_fc_mode mode;
1250 : : struct roc_nix_sq *sq;
1251 : : int rc, i;
1252 : :
1253 [ # # ]: 0 : if (data->tx_queues == NULL)
1254 : : return -EINVAL;
1255 : :
1256 [ # # ]: 0 : if (qid >= eth_dev->data->nb_tx_queues)
1257 : : return -ENOTSUP;
1258 : :
1259 : : /* Check if RX pause frame is enabled or not and
1260 : : * confirm user requested for PFC.
1261 : : */
1262 [ # # # # ]: 0 : if (!pfc->rx_pause_en && rx_pause) {
1263 [ # # ]: 0 : if ((roc_nix_tm_tree_type_get(nix) == ROC_NIX_TM_DEFAULT) &&
1264 [ # # ]: 0 : eth_dev->data->nb_tx_queues > 1) {
1265 : : /*
1266 : : * Disabled xmit will be enabled when
1267 : : * new topology is available.
1268 : : */
1269 : 0 : rc = roc_nix_tm_hierarchy_disable(nix);
1270 [ # # ]: 0 : if (rc)
1271 : 0 : goto exit;
1272 : :
1273 : 0 : rc = roc_nix_tm_pfc_prepare_tree(nix);
1274 [ # # ]: 0 : if (rc)
1275 : 0 : goto exit;
1276 : :
1277 : 0 : rc = roc_nix_tm_hierarchy_enable(nix, ROC_NIX_TM_PFC,
1278 : : true);
1279 [ # # ]: 0 : if (rc)
1280 : 0 : goto exit;
1281 : : }
1282 : : }
1283 : :
1284 : 0 : txq = ((struct cnxk_eth_txq_sp *)data->tx_queues[qid]) - 1;
1285 : 0 : sq = &dev->sqs[txq->qid];
1286 : : memset(&fc_cfg, 0, sizeof(struct roc_nix_fc_cfg));
1287 : 0 : fc_cfg.type = ROC_NIX_FC_TM_CFG;
1288 : 0 : fc_cfg.tm_cfg.sq = sq->qid;
1289 : 0 : fc_cfg.tm_cfg.tc = tc;
1290 : 0 : fc_cfg.tm_cfg.enable = !!rx_pause;
1291 : 0 : rc = roc_nix_fc_config_set(nix, &fc_cfg);
1292 [ # # ]: 0 : if (rc)
1293 : : return rc;
1294 : :
1295 : : /* Recheck number of SQ's that have PFC enabled */
1296 : 0 : pfc->rx_pause_en = 0;
1297 [ # # ]: 0 : for (i = 0; i < dev->nb_txq; i++)
1298 [ # # ]: 0 : if (dev->sqs[i].tc != ROC_NIX_PFC_CLASS_INVALID)
1299 : 0 : pfc->rx_pause_en++;
1300 : :
1301 [ # # ]: 0 : if (pfc->rx_pause_en > 1)
1302 : 0 : goto exit;
1303 : :
1304 [ # # ]: 0 : if (pfc->tx_pause_en)
1305 [ # # ]: 0 : mode = pfc->rx_pause_en ? ROC_NIX_FC_FULL : ROC_NIX_FC_TX;
1306 : : else
1307 : 0 : mode = pfc->rx_pause_en ? ROC_NIX_FC_RX : ROC_NIX_FC_NONE;
1308 : :
1309 : : memset(&pfc_cfg, 0, sizeof(struct roc_nix_pfc_cfg));
1310 : 0 : pfc_cfg.mode = mode;
1311 : 0 : pfc_cfg.tc = pfc->class_en;
1312 : 0 : rc = roc_nix_pfc_mode_set(nix, &pfc_cfg);
1313 : : exit:
1314 : : return rc;
1315 : : }
|