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 [ # # ]: 0 : if (eth_dev->data->promiscuous) {
456 : 0 : rc = roc_nix_mac_promisc_mode_enable(nix, true);
457 [ # # ]: 0 : if (rc)
458 : 0 : plt_err("Failed to setup promisc mode in mac, rc=%d(%s)", rc,
459 : : roc_error_msg_get(rc));
460 : : }
461 : : }
462 : :
463 : : /* Update mac address to cnxk ethernet device */
464 [ # # ]: 0 : rte_memcpy(dev->mac_addr, addr->addr_bytes, RTE_ETHER_ADDR_LEN);
465 : :
466 : 0 : exit:
467 : 0 : return rc;
468 : : }
469 : :
470 : : int
471 : 0 : cnxk_nix_mac_addr_add(struct rte_eth_dev *eth_dev, struct rte_ether_addr *addr,
472 : : uint32_t index, uint32_t pool)
473 : : {
474 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
475 : 0 : struct roc_nix *nix = &dev->nix;
476 : : int rc;
477 : :
478 : : PLT_SET_USED(index);
479 : : PLT_SET_USED(pool);
480 : :
481 : 0 : rc = roc_nix_mac_addr_add(nix, addr->addr_bytes);
482 [ # # ]: 0 : if (rc < 0) {
483 : 0 : plt_err("Failed to add mac address, rc=%d", rc);
484 : 0 : return rc;
485 : : }
486 : :
487 : 0 : dev->dmac_idx_map[index] = rc;
488 : :
489 : : /* Enable promiscuous mode at NIX level */
490 : 0 : roc_nix_npc_promisc_ena_dis(nix, true);
491 : 0 : dev->dmac_filter_enable = true;
492 : 0 : eth_dev->data->promiscuous = false;
493 : 0 : dev->dmac_filter_count++;
494 : :
495 : 0 : return 0;
496 : : }
497 : :
498 : : void
499 : 0 : cnxk_nix_mac_addr_del(struct rte_eth_dev *eth_dev, uint32_t index)
500 : : {
501 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
502 : 0 : struct roc_nix *nix = &dev->nix;
503 : : int rc;
504 : :
505 : 0 : rc = roc_nix_mac_addr_del(nix, dev->dmac_idx_map[index]);
506 [ # # ]: 0 : if (rc)
507 : 0 : plt_err("Failed to delete mac address, rc=%d", rc);
508 : :
509 : 0 : dev->dmac_filter_count--;
510 : 0 : }
511 : :
512 : : int
513 : 0 : cnxk_nix_sq_flush(struct rte_eth_dev *eth_dev)
514 : : {
515 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
516 : : struct rte_eth_dev_data *data = eth_dev->data;
517 : : int i, rc = 0;
518 : :
519 : : /* Flush all tx queues */
520 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
521 : 0 : struct roc_nix_sq *sq = &dev->sqs[i];
522 : :
523 [ # # ]: 0 : if (eth_dev->data->tx_queues[i] == NULL)
524 : 0 : continue;
525 : :
526 : 0 : rc = roc_nix_tm_sq_aura_fc(sq, false);
527 [ # # ]: 0 : if (rc) {
528 : 0 : plt_err("Failed to disable sqb aura fc, rc=%d", rc);
529 : 0 : goto exit;
530 : : }
531 : :
532 : : /* Wait for sq entries to be flushed */
533 : 0 : rc = roc_nix_tm_sq_flush_spin(sq);
534 [ # # ]: 0 : if (rc) {
535 : 0 : plt_err("Failed to drain sq, rc=%d", rc);
536 : 0 : goto exit;
537 : : }
538 [ # # ]: 0 : if (data->tx_queue_state[i] == RTE_ETH_QUEUE_STATE_STARTED) {
539 : 0 : rc = roc_nix_tm_sq_aura_fc(sq, true);
540 [ # # ]: 0 : if (rc) {
541 : 0 : plt_err("Failed to enable sq aura fc, txq=%u, rc=%d", i, rc);
542 : 0 : goto exit;
543 : : }
544 : : }
545 : : }
546 : 0 : exit:
547 : 0 : return rc;
548 : : }
549 : :
550 : : int
551 : 0 : cnxk_nix_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
552 : : {
553 [ # # ]: 0 : uint32_t old_frame_size, frame_size = mtu + CNXK_NIX_L2_OVERHEAD;
554 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
555 : : struct rte_eth_dev_data *data = eth_dev->data;
556 : 0 : struct roc_nix *nix = &dev->nix;
557 : : struct cnxk_eth_rxq_sp *rxq_sp;
558 : : uint32_t buffsz = 0;
559 : : int rc = -EINVAL;
560 : :
561 : 0 : frame_size += CNXK_NIX_TIMESYNC_RX_OFFSET * dev->ptp_en;
562 : :
563 : : /* Check if MTU is within the allowed range */
564 [ # # ]: 0 : if ((frame_size - RTE_ETHER_CRC_LEN) < NIX_MIN_HW_FRS) {
565 : 0 : plt_err("MTU is lesser than minimum");
566 : 0 : goto exit;
567 : : }
568 : :
569 : 0 : if ((frame_size - RTE_ETHER_CRC_LEN) >
570 [ # # ]: 0 : ((uint32_t)roc_nix_max_pkt_len(nix))) {
571 : 0 : plt_err("MTU is greater than maximum");
572 : 0 : goto exit;
573 : : }
574 : :
575 [ # # ]: 0 : if (!eth_dev->data->nb_rx_queues)
576 : 0 : goto skip_buffsz_check;
577 : :
578 : : /* Perform buff size check */
579 [ # # ]: 0 : if (data->min_rx_buf_size) {
580 : : buffsz = data->min_rx_buf_size;
581 [ # # # # ]: 0 : } else if (eth_dev->data->rx_queues && eth_dev->data->rx_queues[0]) {
582 : 0 : rxq_sp = cnxk_eth_rxq_to_sp(data->rx_queues[0]);
583 : :
584 [ # # ]: 0 : if (rxq_sp->qconf.mp)
585 : 0 : buffsz = rte_pktmbuf_data_room_size(rxq_sp->qconf.mp);
586 : : }
587 : :
588 : : /* Skip validation if RQ's are not yet setup */
589 [ # # ]: 0 : if (!buffsz)
590 : 0 : goto skip_buffsz_check;
591 : :
592 : 0 : buffsz -= RTE_PKTMBUF_HEADROOM;
593 : :
594 : : /* Refuse MTU that requires the support of scattered packets
595 : : * when this feature has not been enabled before.
596 : : */
597 [ # # # # ]: 0 : if (data->dev_started && frame_size > buffsz &&
598 [ # # ]: 0 : !(dev->rx_offloads & RTE_ETH_RX_OFFLOAD_SCATTER)) {
599 : 0 : plt_err("Scatter offload is not enabled for mtu");
600 : 0 : goto exit;
601 : : }
602 : :
603 : : /* Check <seg size> * <max_seg> >= max_frame */
604 [ # # ]: 0 : if ((dev->rx_offloads & RTE_ETH_RX_OFFLOAD_SCATTER) &&
605 [ # # ]: 0 : frame_size > (buffsz * CNXK_NIX_RX_NB_SEG_MAX)) {
606 : 0 : plt_err("Greater than maximum supported packet length");
607 : 0 : goto exit;
608 : : }
609 : :
610 : 0 : skip_buffsz_check:
611 : 0 : old_frame_size = data->mtu + CNXK_NIX_L2_OVERHEAD;
612 : : /* if new MTU was smaller than old one, then flush all SQs before MTU change */
613 [ # # ]: 0 : if (old_frame_size > frame_size) {
614 [ # # ]: 0 : if (data->dev_started) {
615 : 0 : plt_err("Reducing MTU is not supported when device started");
616 : 0 : goto exit;
617 : : }
618 : 0 : cnxk_nix_sq_flush(eth_dev);
619 : : }
620 : :
621 : : frame_size -= RTE_ETHER_CRC_LEN;
622 : :
623 : : /* Set frame size on Rx */
624 : 0 : rc = roc_nix_mac_max_rx_len_set(nix, frame_size);
625 [ # # ]: 0 : if (rc) {
626 : 0 : plt_err("Failed to max Rx frame length, rc=%d", rc);
627 : 0 : goto exit;
628 : : }
629 : 0 : exit:
630 : 0 : return rc;
631 : : }
632 : :
633 : : int
634 : 0 : cnxk_nix_promisc_enable(struct rte_eth_dev *eth_dev)
635 : : {
636 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
637 : 0 : struct roc_nix *nix = &dev->nix;
638 : : int rc = 0;
639 : :
640 [ # # ]: 0 : if (roc_nix_is_vf_or_sdp(nix))
641 : : return rc;
642 : :
643 : 0 : rc = roc_nix_npc_promisc_ena_dis(nix, true);
644 [ # # ]: 0 : if (rc) {
645 : 0 : plt_err("Failed to setup promisc mode in npc, rc=%d(%s)", rc,
646 : : roc_error_msg_get(rc));
647 : 0 : return rc;
648 : : }
649 : :
650 : 0 : rc = roc_nix_mac_promisc_mode_enable(nix, true);
651 [ # # ]: 0 : if (rc) {
652 : 0 : plt_err("Failed to setup promisc mode in mac, rc=%d(%s)", rc,
653 : : roc_error_msg_get(rc));
654 : 0 : roc_nix_npc_promisc_ena_dis(nix, false);
655 : 0 : return rc;
656 : : }
657 : :
658 : : return 0;
659 : : }
660 : :
661 : : int
662 : 0 : cnxk_nix_promisc_disable(struct rte_eth_dev *eth_dev)
663 : : {
664 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
665 : 0 : struct roc_nix *nix = &dev->nix;
666 : : int rc = 0;
667 : :
668 [ # # ]: 0 : if (roc_nix_is_vf_or_sdp(nix))
669 : : return rc;
670 : :
671 : 0 : rc = roc_nix_npc_promisc_ena_dis(nix, dev->dmac_filter_enable);
672 [ # # ]: 0 : if (rc) {
673 : 0 : plt_err("Failed to setup promisc mode in npc, rc=%d(%s)", rc,
674 : : roc_error_msg_get(rc));
675 : 0 : return rc;
676 : : }
677 : :
678 : 0 : rc = roc_nix_mac_promisc_mode_enable(nix, false);
679 [ # # ]: 0 : if (rc) {
680 : 0 : plt_err("Failed to setup promisc mode in mac, rc=%d(%s)", rc,
681 : : roc_error_msg_get(rc));
682 : 0 : roc_nix_npc_promisc_ena_dis(nix, !dev->dmac_filter_enable);
683 : 0 : return rc;
684 : : }
685 : :
686 : 0 : dev->dmac_filter_enable = false;
687 : 0 : return 0;
688 : : }
689 : :
690 : : int
691 : 0 : cnxk_nix_allmulticast_enable(struct rte_eth_dev *eth_dev)
692 : : {
693 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
694 : :
695 : 0 : return roc_nix_npc_mcast_config(&dev->nix, true,
696 : 0 : eth_dev->data->promiscuous);
697 : : }
698 : :
699 : : int
700 : 0 : cnxk_nix_allmulticast_disable(struct rte_eth_dev *eth_dev)
701 : : {
702 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
703 : :
704 : 0 : return roc_nix_npc_mcast_config(&dev->nix, false,
705 : 0 : eth_dev->data->promiscuous);
706 : : }
707 : :
708 : : int
709 : 0 : cnxk_nix_set_link_up(struct rte_eth_dev *eth_dev)
710 : : {
711 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
712 : 0 : struct roc_nix *nix = &dev->nix;
713 : : int rc, i;
714 : :
715 [ # # ]: 0 : if (roc_nix_is_vf_or_sdp(nix))
716 : : return -ENOTSUP;
717 : :
718 : 0 : rc = roc_nix_mac_link_state_set(nix, true);
719 [ # # ]: 0 : if (rc)
720 : 0 : goto exit;
721 : :
722 : : /* Start tx queues */
723 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
724 : 0 : rc = cnxk_nix_tx_queue_start(eth_dev, i);
725 [ # # ]: 0 : if (rc)
726 : 0 : goto exit;
727 : : }
728 : :
729 : 0 : exit:
730 : : return rc;
731 : : }
732 : :
733 : : int
734 : 0 : cnxk_nix_set_link_down(struct rte_eth_dev *eth_dev)
735 : : {
736 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
737 : 0 : struct roc_nix *nix = &dev->nix;
738 : : int rc, i;
739 : :
740 [ # # ]: 0 : if (roc_nix_is_vf_or_sdp(nix))
741 : : return -ENOTSUP;
742 : :
743 : : /* Stop tx queues */
744 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
745 : 0 : rc = cnxk_nix_tx_queue_stop(eth_dev, i);
746 [ # # ]: 0 : if (rc)
747 : 0 : goto exit;
748 : : }
749 : :
750 : 0 : rc = roc_nix_mac_link_state_set(nix, false);
751 : : exit:
752 : : return rc;
753 : : }
754 : :
755 : : int
756 : 0 : cnxk_nix_get_module_info(struct rte_eth_dev *eth_dev,
757 : : struct rte_eth_dev_module_info *modinfo)
758 : : {
759 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
760 : 0 : struct roc_nix_eeprom_info eeprom_info = {0};
761 : 0 : struct roc_nix *nix = &dev->nix;
762 : : int rc;
763 : :
764 : 0 : rc = roc_nix_eeprom_info_get(nix, &eeprom_info);
765 [ # # ]: 0 : if (rc)
766 : : return rc;
767 : :
768 : 0 : modinfo->type = eeprom_info.sff_id;
769 : 0 : modinfo->eeprom_len = ROC_NIX_EEPROM_SIZE;
770 : 0 : return 0;
771 : : }
772 : :
773 : : int
774 [ # # ]: 0 : cnxk_nix_get_module_eeprom(struct rte_eth_dev *eth_dev,
775 : : struct rte_dev_eeprom_info *info)
776 : : {
777 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
778 : 0 : struct roc_nix_eeprom_info eeprom_info = {0};
779 : 0 : struct roc_nix *nix = &dev->nix;
780 : : int rc = -EINVAL;
781 : :
782 [ # # # # ]: 0 : if (!info->data || !info->length ||
783 [ # # ]: 0 : (info->offset + info->length > ROC_NIX_EEPROM_SIZE))
784 : : return rc;
785 : :
786 : 0 : rc = roc_nix_eeprom_info_get(nix, &eeprom_info);
787 [ # # ]: 0 : if (rc)
788 : : return rc;
789 : :
790 [ # # ]: 0 : rte_memcpy(info->data, eeprom_info.buf + info->offset, info->length);
791 : : return 0;
792 : : }
793 : :
794 : : int
795 : 0 : cnxk_nix_rx_queue_intr_enable(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
796 : : {
797 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
798 : :
799 : 0 : roc_nix_rx_queue_intr_enable(&dev->nix, rx_queue_id);
800 : 0 : return 0;
801 : : }
802 : :
803 : : int
804 : 0 : cnxk_nix_rx_queue_intr_disable(struct rte_eth_dev *eth_dev,
805 : : uint16_t rx_queue_id)
806 : : {
807 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
808 : :
809 : 0 : roc_nix_rx_queue_intr_disable(&dev->nix, rx_queue_id);
810 : 0 : return 0;
811 : : }
812 : :
813 : : int
814 : 0 : cnxk_nix_pool_ops_supported(struct rte_eth_dev *eth_dev, const char *pool)
815 : : {
816 : : RTE_SET_USED(eth_dev);
817 : :
818 [ # # ]: 0 : if (!strcmp(pool, rte_mbuf_platform_mempool_ops()))
819 : 0 : return 0;
820 : :
821 : : return -ENOTSUP;
822 : : }
823 : :
824 : : int
825 : 0 : cnxk_nix_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
826 : : size_t fw_size)
827 : : {
828 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
829 : 0 : const char *str = roc_npc_profile_name_get(&dev->npc);
830 : 0 : uint32_t size = strlen(str) + 1;
831 : :
832 [ # # ]: 0 : if (fw_size > size)
833 : : fw_size = size;
834 : :
835 : : rte_strlcpy(fw_version, str, fw_size);
836 : :
837 [ # # ]: 0 : if (fw_size < size)
838 : 0 : return size;
839 : :
840 : : return 0;
841 : : }
842 : :
843 : : void
844 : 0 : cnxk_nix_rxq_info_get(struct rte_eth_dev *eth_dev, uint16_t qid,
845 : : struct rte_eth_rxq_info *qinfo)
846 : : {
847 : 0 : void *rxq = eth_dev->data->rx_queues[qid];
848 : : struct cnxk_eth_rxq_sp *rxq_sp = cnxk_eth_rxq_to_sp(rxq);
849 : :
850 : : memset(qinfo, 0, sizeof(*qinfo));
851 : :
852 : 0 : qinfo->mp = rxq_sp->qconf.mp;
853 : 0 : qinfo->scattered_rx = eth_dev->data->scattered_rx;
854 : 0 : qinfo->nb_desc = rxq_sp->qconf.nb_desc;
855 : :
856 : 0 : memcpy(&qinfo->conf, &rxq_sp->qconf.conf.rx, sizeof(qinfo->conf));
857 : 0 : }
858 : :
859 : : void
860 : 0 : cnxk_nix_txq_info_get(struct rte_eth_dev *eth_dev, uint16_t qid,
861 : : struct rte_eth_txq_info *qinfo)
862 : : {
863 : 0 : void *txq = eth_dev->data->tx_queues[qid];
864 : : struct cnxk_eth_txq_sp *txq_sp = cnxk_eth_txq_to_sp(txq);
865 : :
866 : : memset(qinfo, 0, sizeof(*qinfo));
867 : :
868 : 0 : qinfo->nb_desc = txq_sp->qconf.nb_desc;
869 : :
870 : 0 : memcpy(&qinfo->conf, &txq_sp->qconf.conf.tx, sizeof(qinfo->conf));
871 : 0 : }
872 : :
873 : : uint32_t
874 : 0 : cnxk_nix_rx_queue_count(void *rxq)
875 : : {
876 : : struct cnxk_eth_rxq_sp *rxq_sp = cnxk_eth_rxq_to_sp(rxq);
877 : 0 : struct roc_nix *nix = &rxq_sp->dev->nix;
878 : : uint32_t head, tail;
879 : :
880 : 0 : roc_nix_cq_head_tail_get(nix, rxq_sp->qid, &head, &tail);
881 : 0 : return (tail - head) % (rxq_sp->qconf.nb_desc);
882 : : }
883 : :
884 : : static inline int
885 : : nix_offset_has_packet(uint32_t head, uint32_t tail, uint16_t offset, bool is_rx)
886 : : {
887 : : /* Check given offset(queue index) has packet filled/xmit by HW
888 : : * in case of Rx or Tx.
889 : : * Also, checks for wrap around case.
890 : : */
891 [ # # # # : 0 : return ((tail > head && offset <= tail && offset >= head) ||
# # # # #
# # # ]
892 [ # # # # : 0 : (head > tail && (offset >= head || offset <= tail))) ?
# # # # ]
893 : 0 : is_rx :
894 : : !is_rx;
895 : : }
896 : :
897 : : int
898 : 0 : cnxk_nix_rx_descriptor_status(void *rxq, uint16_t offset)
899 : : {
900 : : struct cnxk_eth_rxq_sp *rxq_sp = cnxk_eth_rxq_to_sp(rxq);
901 : 0 : struct roc_nix *nix = &rxq_sp->dev->nix;
902 : : uint32_t head, tail;
903 : :
904 [ # # ]: 0 : if (rxq_sp->qconf.nb_desc <= offset)
905 : : return -EINVAL;
906 : :
907 : 0 : roc_nix_cq_head_tail_get(nix, rxq_sp->qid, &head, &tail);
908 : :
909 [ # # ]: 0 : if (nix_offset_has_packet(head, tail, offset, 1))
910 : 0 : return RTE_ETH_RX_DESC_DONE;
911 : : else
912 : : return RTE_ETH_RX_DESC_AVAIL;
913 : : }
914 : :
915 : : int
916 : 0 : cnxk_nix_tx_descriptor_status(void *txq, uint16_t offset)
917 : : {
918 : : struct cnxk_eth_txq_sp *txq_sp = cnxk_eth_txq_to_sp(txq);
919 : 0 : struct roc_nix *nix = &txq_sp->dev->nix;
920 : 0 : uint32_t head = 0, tail = 0;
921 : :
922 [ # # ]: 0 : if (txq_sp->qconf.nb_desc <= offset)
923 : : return -EINVAL;
924 : :
925 : 0 : roc_nix_sq_head_tail_get(nix, txq_sp->qid, &head, &tail);
926 : :
927 [ # # ]: 0 : if (nix_offset_has_packet(head, tail, offset, 0))
928 : : return RTE_ETH_TX_DESC_DONE;
929 : : else
930 : 0 : return RTE_ETH_TX_DESC_FULL;
931 : : }
932 : :
933 : : /* It is a NOP for cnxk as HW frees the buffer on xmit */
934 : : int
935 : 0 : cnxk_nix_tx_done_cleanup(void *txq, uint32_t free_cnt)
936 : : {
937 : : RTE_SET_USED(txq);
938 : : RTE_SET_USED(free_cnt);
939 : :
940 : 0 : return 0;
941 : : }
942 : :
943 : : int
944 [ # # ]: 0 : cnxk_nix_dev_get_reg(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
945 : : {
946 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
947 : 0 : struct roc_nix *nix = &dev->nix;
948 : 0 : uint64_t *data = regs->data;
949 : : int rc = -ENOTSUP;
950 : :
951 [ # # ]: 0 : if (data == NULL) {
952 : 0 : rc = roc_nix_lf_get_reg_count(nix);
953 [ # # ]: 0 : if (rc > 0) {
954 : 0 : regs->length = rc;
955 : 0 : regs->width = 8;
956 : : rc = 0;
957 : : }
958 : 0 : return rc;
959 : : }
960 : :
961 [ # # ]: 0 : if (!regs->length ||
962 [ # # ]: 0 : regs->length == (uint32_t)roc_nix_lf_get_reg_count(nix))
963 : 0 : return roc_nix_lf_reg_dump(nix, data);
964 : :
965 : : return rc;
966 : : }
967 : :
968 : : int
969 [ # # ]: 0 : cnxk_nix_reta_update(struct rte_eth_dev *eth_dev,
970 : : struct rte_eth_rss_reta_entry64 *reta_conf,
971 : : uint16_t reta_size)
972 : : {
973 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
974 : : uint16_t reta[ROC_NIX_RSS_RETA_MAX];
975 : 0 : struct roc_nix *nix = &dev->nix;
976 : : int i, j, rc = -EINVAL, idx = 0;
977 : :
978 [ # # ]: 0 : if (reta_size != dev->nix.reta_sz) {
979 : 0 : plt_err("Size of hash lookup table configured (%d) does not "
980 : : "match the number hardware can supported (%d)",
981 : : reta_size, dev->nix.reta_sz);
982 : 0 : goto fail;
983 : : }
984 : :
985 : 0 : roc_nix_rss_reta_get(nix, 0, reta);
986 : :
987 : : /* Copy RETA table */
988 [ # # ]: 0 : for (i = 0; i < (int)(dev->nix.reta_sz / RTE_ETH_RETA_GROUP_SIZE); i++) {
989 [ # # ]: 0 : for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++) {
990 [ # # ]: 0 : if ((reta_conf[i].mask >> j) & 0x01)
991 : 0 : reta[idx] = reta_conf[i].reta[j];
992 : 0 : idx++;
993 : : }
994 : : }
995 : :
996 : 0 : return roc_nix_rss_reta_set(nix, 0, reta);
997 : :
998 : : fail:
999 : 0 : return rc;
1000 : : }
1001 : :
1002 : : int
1003 [ # # ]: 0 : cnxk_nix_reta_query(struct rte_eth_dev *eth_dev,
1004 : : struct rte_eth_rss_reta_entry64 *reta_conf,
1005 : : uint16_t reta_size)
1006 : : {
1007 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1008 : : uint16_t reta[ROC_NIX_RSS_RETA_MAX];
1009 : 0 : struct roc_nix *nix = &dev->nix;
1010 : : int rc = -EINVAL, i, j, idx = 0;
1011 : :
1012 [ # # ]: 0 : if (reta_size != dev->nix.reta_sz) {
1013 : 0 : plt_err("Size of hash lookup table configured (%d) does not "
1014 : : "match the number hardware can supported (%d)",
1015 : : reta_size, dev->nix.reta_sz);
1016 : 0 : goto fail;
1017 : : }
1018 : :
1019 : 0 : rc = roc_nix_rss_reta_get(nix, 0, reta);
1020 [ # # ]: 0 : if (rc)
1021 : 0 : goto fail;
1022 : :
1023 : : /* Copy RETA table */
1024 [ # # ]: 0 : for (i = 0; i < (int)(dev->nix.reta_sz / RTE_ETH_RETA_GROUP_SIZE); i++) {
1025 [ # # ]: 0 : for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++) {
1026 [ # # ]: 0 : if ((reta_conf[i].mask >> j) & 0x01)
1027 : 0 : reta_conf[i].reta[j] = reta[idx];
1028 : 0 : idx++;
1029 : : }
1030 : : }
1031 : :
1032 : : return 0;
1033 : :
1034 : : fail:
1035 : : return rc;
1036 : : }
1037 : :
1038 : : int
1039 : 0 : cnxk_nix_eth_dev_priv_dump(struct rte_eth_dev *eth_dev, FILE *file)
1040 : : {
1041 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1042 : 0 : struct roc_nix *roc_nix = &dev->nix;
1043 : : int i;
1044 : :
1045 : 0 : roc_nix_dump(roc_nix, file);
1046 : :
1047 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_rx_queues; i++)
1048 : 0 : roc_nix_rq_dump(&dev->rqs[i], file);
1049 : :
1050 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_rx_queues; i++)
1051 : 0 : roc_nix_cq_dump(&dev->cqs[i], file);
1052 : :
1053 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
1054 : 0 : roc_nix_sq_dump(&dev->sqs[i], file);
1055 : :
1056 : 0 : roc_nix_queues_ctx_dump(roc_nix, file);
1057 : :
1058 : 0 : roc_nix_tm_dump(roc_nix, file);
1059 : :
1060 : 0 : roc_nix_inl_dev_dump(NULL, file);
1061 : :
1062 : 0 : roc_nix_inl_outb_cpt_lfs_dump(roc_nix, file);
1063 : :
1064 : 0 : return 0;
1065 : : }
1066 : :
1067 : : int
1068 [ # # ]: 0 : cnxk_nix_rss_hash_update(struct rte_eth_dev *eth_dev,
1069 : : struct rte_eth_rss_conf *rss_conf)
1070 : : {
1071 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1072 : 0 : struct roc_nix *nix = &dev->nix;
1073 : : uint8_t rss_hash_level;
1074 : : uint32_t flowkey_cfg;
1075 : : int rc = -EINVAL;
1076 : : uint8_t alg_idx;
1077 : :
1078 [ # # # # ]: 0 : if (rss_conf->rss_key && rss_conf->rss_key_len != ROC_NIX_RSS_KEY_LEN) {
1079 : 0 : plt_err("Hash key size mismatch %d vs %d",
1080 : : rss_conf->rss_key_len, ROC_NIX_RSS_KEY_LEN);
1081 : 0 : goto fail;
1082 : : }
1083 : :
1084 [ # # ]: 0 : if (rss_conf->rss_key)
1085 : 0 : roc_nix_rss_key_set(nix, rss_conf->rss_key);
1086 : :
1087 : 0 : rss_hash_level = RTE_ETH_RSS_LEVEL(rss_conf->rss_hf);
1088 [ # # ]: 0 : if (rss_hash_level)
1089 : 0 : rss_hash_level -= 1;
1090 : : flowkey_cfg =
1091 : 0 : cnxk_rss_ethdev_to_nix(dev, rss_conf->rss_hf, rss_hash_level);
1092 : :
1093 : 0 : rc = roc_nix_rss_flowkey_set(nix, &alg_idx, flowkey_cfg,
1094 : : ROC_NIX_RSS_GROUP_DEFAULT,
1095 : : ROC_NIX_RSS_MCAM_IDX_DEFAULT);
1096 [ # # ]: 0 : if (rc) {
1097 : 0 : plt_err("Failed to set RSS hash function rc=%d", rc);
1098 : 0 : return rc;
1099 : : }
1100 : :
1101 : 0 : fail:
1102 : : return rc;
1103 : : }
1104 : :
1105 : : int
1106 [ # # ]: 0 : cnxk_nix_rss_hash_conf_get(struct rte_eth_dev *eth_dev,
1107 : : struct rte_eth_rss_conf *rss_conf)
1108 : : {
1109 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1110 : :
1111 [ # # ]: 0 : if (rss_conf->rss_key)
1112 : 0 : roc_nix_rss_key_get(&dev->nix, rss_conf->rss_key);
1113 : :
1114 : 0 : rss_conf->rss_key_len = ROC_NIX_RSS_KEY_LEN;
1115 : 0 : rss_conf->rss_hf = dev->ethdev_rss_hf;
1116 : :
1117 : 0 : return 0;
1118 : : }
1119 : :
1120 : : int
1121 : 0 : cnxk_nix_mc_addr_list_configure(struct rte_eth_dev *eth_dev,
1122 : : struct rte_ether_addr *mc_addr_set,
1123 : : uint32_t nb_mc_addr)
1124 : : {
1125 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1126 : : struct rte_eth_dev_data *data = eth_dev->data;
1127 : : struct rte_ether_addr null_mac_addr;
1128 : 0 : struct roc_nix *nix = &dev->nix;
1129 : : int rc, index;
1130 : : uint32_t i;
1131 : :
1132 : : memset(&null_mac_addr, 0, sizeof(null_mac_addr));
1133 : :
1134 : : /* All configured multicast filters should be flushed first */
1135 [ # # ]: 0 : for (i = 0; i < dev->max_mac_entries; i++) {
1136 [ # # ]: 0 : if (rte_is_multicast_ether_addr(&data->mac_addrs[i])) {
1137 : 0 : rc = roc_nix_mac_addr_del(nix, i);
1138 [ # # ]: 0 : if (rc) {
1139 : 0 : plt_err("Failed to flush mcast address, rc=%d",
1140 : : rc);
1141 : 0 : return rc;
1142 : : }
1143 : :
1144 : 0 : dev->dmac_filter_count--;
1145 : : /* Update address in NIC data structure */
1146 : 0 : rte_ether_addr_copy(&null_mac_addr,
1147 : 0 : &data->mac_addrs[i]);
1148 : : }
1149 : : }
1150 : :
1151 [ # # ]: 0 : if (!mc_addr_set || !nb_mc_addr)
1152 : : return 0;
1153 : :
1154 : : /* Check for available space */
1155 : 0 : if (nb_mc_addr >
1156 [ # # ]: 0 : ((uint32_t)(dev->max_mac_entries - dev->dmac_filter_count))) {
1157 : 0 : plt_err("No space is available to add multicast filters");
1158 : 0 : return -ENOSPC;
1159 : : }
1160 : :
1161 : : /* Multicast addresses are to be installed */
1162 [ # # ]: 0 : for (i = 0; i < nb_mc_addr; i++) {
1163 : 0 : index = roc_nix_mac_addr_add(nix, mc_addr_set[i].addr_bytes);
1164 [ # # ]: 0 : if (index < 0) {
1165 : 0 : plt_err("Failed to add mcast mac address, rc=%d",
1166 : : index);
1167 : 0 : return index;
1168 : : }
1169 : :
1170 : 0 : dev->dmac_filter_count++;
1171 : : /* Update address in NIC data structure */
1172 : 0 : rte_ether_addr_copy(&mc_addr_set[i], &data->mac_addrs[index]);
1173 : : }
1174 : :
1175 : 0 : roc_nix_npc_promisc_ena_dis(nix, true);
1176 : 0 : dev->dmac_filter_enable = true;
1177 : 0 : eth_dev->data->promiscuous = false;
1178 : :
1179 : 0 : return 0;
1180 : : }
1181 : :
1182 : : int
1183 [ # # ]: 0 : nix_priority_flow_ctrl_rq_conf(struct rte_eth_dev *eth_dev, uint16_t qid,
1184 : : uint8_t tx_pause, uint8_t tc)
1185 : : {
1186 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1187 : : struct rte_eth_dev_data *data = eth_dev->data;
1188 : : struct cnxk_pfc_cfg *pfc = &dev->pfc_cfg;
1189 : 0 : struct roc_nix *nix = &dev->nix;
1190 : : struct roc_nix_pfc_cfg pfc_cfg;
1191 : : struct roc_nix_fc_cfg fc_cfg;
1192 : : struct cnxk_eth_rxq_sp *rxq;
1193 : : enum roc_nix_fc_mode mode;
1194 : : struct roc_nix_rq *rq;
1195 : : struct roc_nix_cq *cq;
1196 : : int rc, i;
1197 : :
1198 [ # # ]: 0 : if (data->dev_started) {
1199 : : /* RQ should be in disabled state
1200 : : * while setting flow control configuration.
1201 : : */
1202 : 0 : plt_info("Stop the port=%d for setting flow control",
1203 : : data->port_id);
1204 : 0 : return 0;
1205 : : }
1206 : :
1207 [ # # ]: 0 : if (data->rx_queues == NULL)
1208 : : return -EINVAL;
1209 : :
1210 [ # # ]: 0 : if (qid >= eth_dev->data->nb_rx_queues)
1211 : : return -ENOTSUP;
1212 : :
1213 : : /* Configure RQ */
1214 : 0 : rxq = ((struct cnxk_eth_rxq_sp *)data->rx_queues[qid]) - 1;
1215 : 0 : rq = &dev->rqs[qid];
1216 : 0 : cq = &dev->cqs[qid];
1217 : :
1218 : : memset(&fc_cfg, 0, sizeof(struct roc_nix_fc_cfg));
1219 : 0 : fc_cfg.type = ROC_NIX_FC_RQ_CFG;
1220 : 0 : fc_cfg.rq_cfg.tc = tc;
1221 : 0 : fc_cfg.rq_cfg.enable = !!tx_pause;
1222 : 0 : fc_cfg.rq_cfg.rq = rq->qid;
1223 : 0 : fc_cfg.rq_cfg.pool = rxq->qconf.mp->pool_id;
1224 : 0 : fc_cfg.rq_cfg.spb_pool = rq->spb_aura_handle;
1225 : 0 : fc_cfg.rq_cfg.cq_drop = cq->drop_thresh;
1226 : 0 : fc_cfg.rq_cfg.pool_drop_pct = ROC_NIX_AURA_THRESH;
1227 : 0 : rc = roc_nix_fc_config_set(nix, &fc_cfg);
1228 [ # # ]: 0 : if (rc)
1229 : : return rc;
1230 : :
1231 : 0 : rxq->tx_pause = !!tx_pause;
1232 : 0 : rxq->tc = tc;
1233 : : /* Recheck number of RQ's that have PFC enabled */
1234 : 0 : pfc->tx_pause_en = 0;
1235 [ # # ]: 0 : for (i = 0; i < dev->nb_rxq; i++)
1236 [ # # ]: 0 : if (dev->rqs[i].tc != ROC_NIX_PFC_CLASS_INVALID)
1237 : 0 : pfc->tx_pause_en++;
1238 : :
1239 : : /* Skip if PFC already enabled in mac */
1240 [ # # ]: 0 : if (pfc->tx_pause_en > 1)
1241 : : return 0;
1242 : :
1243 : : /* Configure MAC block */
1244 [ # # ]: 0 : pfc->class_en = pfc->tx_pause_en ? 0xFF : 0x0;
1245 : :
1246 [ # # ]: 0 : if (pfc->rx_pause_en)
1247 [ # # ]: 0 : mode = pfc->tx_pause_en ? ROC_NIX_FC_FULL : ROC_NIX_FC_RX;
1248 : : else
1249 [ # # ]: 0 : mode = pfc->tx_pause_en ? ROC_NIX_FC_TX : ROC_NIX_FC_NONE;
1250 : :
1251 : : memset(&pfc_cfg, 0, sizeof(struct roc_nix_pfc_cfg));
1252 : 0 : pfc_cfg.mode = mode;
1253 : 0 : pfc_cfg.tc = pfc->class_en;
1254 : 0 : return roc_nix_pfc_mode_set(nix, &pfc_cfg);
1255 : : }
1256 : :
1257 : : int
1258 [ # # ]: 0 : nix_priority_flow_ctrl_sq_conf(struct rte_eth_dev *eth_dev, uint16_t qid,
1259 : : uint8_t rx_pause, uint8_t tc)
1260 : : {
1261 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1262 : : struct rte_eth_dev_data *data = eth_dev->data;
1263 : : struct cnxk_pfc_cfg *pfc = &dev->pfc_cfg;
1264 : 0 : struct roc_nix *nix = &dev->nix;
1265 : : struct roc_nix_pfc_cfg pfc_cfg;
1266 : : struct roc_nix_fc_cfg fc_cfg;
1267 : : struct cnxk_eth_txq_sp *txq;
1268 : : enum roc_nix_fc_mode mode;
1269 : : struct roc_nix_sq *sq;
1270 : : int rc, i;
1271 : :
1272 [ # # ]: 0 : if (data->tx_queues == NULL)
1273 : : return -EINVAL;
1274 : :
1275 [ # # ]: 0 : if (qid >= eth_dev->data->nb_tx_queues)
1276 : : return -ENOTSUP;
1277 : :
1278 : : /* Check if RX pause frame is enabled or not and
1279 : : * confirm user requested for PFC.
1280 : : */
1281 [ # # # # ]: 0 : if (!pfc->rx_pause_en && rx_pause) {
1282 [ # # ]: 0 : if ((roc_nix_tm_tree_type_get(nix) == ROC_NIX_TM_DEFAULT) &&
1283 [ # # ]: 0 : eth_dev->data->nb_tx_queues > 1) {
1284 : : /*
1285 : : * Disabled xmit will be enabled when
1286 : : * new topology is available.
1287 : : */
1288 : 0 : rc = roc_nix_tm_hierarchy_disable(nix);
1289 [ # # ]: 0 : if (rc)
1290 : 0 : goto exit;
1291 : :
1292 : 0 : rc = roc_nix_tm_pfc_prepare_tree(nix);
1293 [ # # ]: 0 : if (rc)
1294 : 0 : goto exit;
1295 : :
1296 : 0 : rc = roc_nix_tm_hierarchy_enable(nix, ROC_NIX_TM_PFC,
1297 : : true);
1298 [ # # ]: 0 : if (rc)
1299 : 0 : goto exit;
1300 : : }
1301 : : }
1302 : :
1303 : 0 : txq = ((struct cnxk_eth_txq_sp *)data->tx_queues[qid]) - 1;
1304 : 0 : sq = &dev->sqs[txq->qid];
1305 : : memset(&fc_cfg, 0, sizeof(struct roc_nix_fc_cfg));
1306 : 0 : fc_cfg.type = ROC_NIX_FC_TM_CFG;
1307 : 0 : fc_cfg.tm_cfg.sq = sq->qid;
1308 : 0 : fc_cfg.tm_cfg.tc = tc;
1309 : 0 : fc_cfg.tm_cfg.enable = !!rx_pause;
1310 : 0 : rc = roc_nix_fc_config_set(nix, &fc_cfg);
1311 [ # # ]: 0 : if (rc)
1312 : : return rc;
1313 : :
1314 : : /* Recheck number of SQ's that have PFC enabled */
1315 : 0 : pfc->rx_pause_en = 0;
1316 [ # # ]: 0 : for (i = 0; i < dev->nb_txq; i++)
1317 [ # # ]: 0 : if (dev->sqs[i].tc != ROC_NIX_PFC_CLASS_INVALID)
1318 : 0 : pfc->rx_pause_en++;
1319 : :
1320 [ # # ]: 0 : if (pfc->rx_pause_en > 1)
1321 : 0 : goto exit;
1322 : :
1323 [ # # ]: 0 : if (pfc->tx_pause_en)
1324 [ # # ]: 0 : mode = pfc->rx_pause_en ? ROC_NIX_FC_FULL : ROC_NIX_FC_TX;
1325 : : else
1326 : 0 : mode = pfc->rx_pause_en ? ROC_NIX_FC_RX : ROC_NIX_FC_NONE;
1327 : :
1328 : : memset(&pfc_cfg, 0, sizeof(struct roc_nix_pfc_cfg));
1329 : 0 : pfc_cfg.mode = mode;
1330 : 0 : pfc_cfg.tc = pfc->class_en;
1331 : 0 : rc = roc_nix_pfc_mode_set(nix, &pfc_cfg);
1332 : : exit:
1333 : : return rc;
1334 : : }
1335 : :
1336 : : int
1337 : 0 : cnxk_nix_tx_descriptor_dump(const struct rte_eth_dev *eth_dev, uint16_t qid, uint16_t offset,
1338 : : uint16_t num, FILE *file)
1339 : : {
1340 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1341 : 0 : struct roc_nix *nix = &dev->nix;
1342 : :
1343 : 0 : return roc_nix_sq_desc_dump(nix, qid, offset, num, file);
1344 : : }
|