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