Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Netronome Systems, Inc.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <nfp_platform.h>
7 : :
8 : : #include "nfp_logs.h"
9 : : #include "nfp_nsp.h"
10 : :
11 : : #define NSP_ETH_NBI_PORT_COUNT 24
12 : : #define NSP_ETH_MAX_COUNT (2 * NSP_ETH_NBI_PORT_COUNT)
13 : : #define NSP_ETH_TABLE_SIZE (NSP_ETH_MAX_COUNT * sizeof(union eth_table_entry))
14 : :
15 : : #define NSP_ETH_PORT_LANES GENMASK_ULL(3, 0)
16 : : #define NSP_ETH_PORT_INDEX GENMASK_ULL(15, 8)
17 : : #define NSP_ETH_PORT_LABEL GENMASK_ULL(53, 48)
18 : : #define NSP_ETH_PORT_PHYLABEL GENMASK_ULL(59, 54)
19 : : #define NSP_ETH_PORT_FEC_SUPP_BASER RTE_BIT64(60)
20 : : #define NSP_ETH_PORT_FEC_SUPP_RS RTE_BIT64(61)
21 : : #define NSP_ETH_PORT_SUPP_ANEG RTE_BIT64(63)
22 : :
23 : : #define NSP_ETH_PORT_LANES_MASK rte_cpu_to_le_64(NSP_ETH_PORT_LANES)
24 : :
25 : : #define NSP_ETH_STATE_CONFIGURED RTE_BIT64(0)
26 : : #define NSP_ETH_STATE_ENABLED RTE_BIT64(1)
27 : : #define NSP_ETH_STATE_TX_ENABLED RTE_BIT64(2)
28 : : #define NSP_ETH_STATE_RX_ENABLED RTE_BIT64(3)
29 : : #define NSP_ETH_STATE_RATE GENMASK_ULL(11, 8)
30 : : #define NSP_ETH_STATE_INTERFACE GENMASK_ULL(19, 12)
31 : : #define NSP_ETH_STATE_MEDIA GENMASK_ULL(21, 20)
32 : : #define NSP_ETH_STATE_OVRD_CHNG RTE_BIT64(22)
33 : : #define NSP_ETH_STATE_ANEG GENMASK_ULL(25, 23)
34 : : #define NSP_ETH_STATE_FEC GENMASK_ULL(27, 26)
35 : : #define NSP_ETH_STATE_ACT_FEC GENMASK_ULL(29, 28)
36 : : #define NSP_ETH_STATE_TX_PAUSE RTE_BIT64(31)
37 : : #define NSP_ETH_STATE_RX_PAUSE RTE_BIT64(32)
38 : :
39 : : #define NSP_ETH_CTRL_CONFIGURED RTE_BIT64(0)
40 : : #define NSP_ETH_CTRL_ENABLED RTE_BIT64(1)
41 : : #define NSP_ETH_CTRL_TX_ENABLED RTE_BIT64(2)
42 : : #define NSP_ETH_CTRL_RX_ENABLED RTE_BIT64(3)
43 : : #define NSP_ETH_CTRL_SET_RATE RTE_BIT64(4)
44 : : #define NSP_ETH_CTRL_SET_LANES RTE_BIT64(5)
45 : : #define NSP_ETH_CTRL_SET_ANEG RTE_BIT64(6)
46 : : #define NSP_ETH_CTRL_SET_FEC RTE_BIT64(7)
47 : : #define NSP_ETH_CTRL_SET_TX_PAUSE RTE_BIT64(10)
48 : : #define NSP_ETH_CTRL_SET_RX_PAUSE RTE_BIT64(11)
49 : :
50 : : /* Which connector port. */
51 : : #define PORT_TP 0x00
52 : : #define PORT_AUI 0x01
53 : : #define PORT_MII 0x02
54 : : #define PORT_FIBRE 0x03
55 : : #define PORT_BNC 0x04
56 : : #define PORT_DA 0x05
57 : : #define PORT_NONE 0xef
58 : : #define PORT_OTHER 0xff
59 : :
60 : : enum nfp_eth_raw {
61 : : NSP_ETH_RAW_PORT = 0,
62 : : NSP_ETH_RAW_STATE,
63 : : NSP_ETH_RAW_MAC,
64 : : NSP_ETH_RAW_CONTROL,
65 : : NSP_ETH_NUM_RAW,
66 : : };
67 : :
68 : : enum nfp_eth_rate {
69 : : RATE_INVALID = 0,
70 : : RATE_10M,
71 : : RATE_100M,
72 : : RATE_1G,
73 : : RATE_10G,
74 : : RATE_25G,
75 : : };
76 : :
77 : : union eth_table_entry {
78 : : struct {
79 : : uint64_t port;
80 : : uint64_t state;
81 : : uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
82 : : uint8_t resv[2];
83 : : uint64_t control;
84 : : };
85 : : uint64_t raw[NSP_ETH_NUM_RAW];
86 : : };
87 : :
88 : : static const struct {
89 : : enum nfp_eth_rate rate;
90 : : uint32_t speed;
91 : : } nsp_eth_rate_tbl[] = {
92 : : { RATE_INVALID, RTE_ETH_SPEED_NUM_NONE, },
93 : : { RATE_10M, RTE_ETH_SPEED_NUM_10M, },
94 : : { RATE_100M, RTE_ETH_SPEED_NUM_100M, },
95 : : { RATE_1G, RTE_ETH_SPEED_NUM_1G, },
96 : : { RATE_10G, RTE_ETH_SPEED_NUM_10G, },
97 : : { RATE_25G, RTE_ETH_SPEED_NUM_25G, },
98 : : };
99 : :
100 : : static uint32_t
101 : : nfp_eth_rate2speed(enum nfp_eth_rate rate)
102 : : {
103 : : uint32_t i;
104 : :
105 [ # # ]: 0 : for (i = 0; i < RTE_DIM(nsp_eth_rate_tbl); i++)
106 [ # # ]: 0 : if (nsp_eth_rate_tbl[i].rate == rate)
107 : 0 : return nsp_eth_rate_tbl[i].speed;
108 : :
109 : : return 0;
110 : : }
111 : :
112 : : static enum nfp_eth_rate
113 : : nfp_eth_speed2rate(uint32_t speed)
114 : : {
115 : : uint32_t i;
116 : :
117 [ # # ]: 0 : for (i = 0; i < RTE_DIM(nsp_eth_rate_tbl); i++)
118 [ # # ]: 0 : if (nsp_eth_rate_tbl[i].speed == speed)
119 : 0 : return nsp_eth_rate_tbl[i].rate;
120 : :
121 : : return RATE_INVALID;
122 : : }
123 : :
124 : : static void
125 : : nfp_eth_copy_mac_reverse(uint8_t *dst,
126 : : const uint8_t *src)
127 : : {
128 : : uint32_t i;
129 : :
130 [ # # ]: 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
131 : 0 : dst[RTE_ETHER_ADDR_LEN - i - 1] = src[i];
132 : : }
133 : :
134 : : static void
135 : 0 : nfp_eth_port_translate(struct nfp_nsp *nsp,
136 : : const union eth_table_entry *src,
137 : : uint32_t index,
138 : : struct nfp_eth_table_port *dst)
139 : : {
140 : : uint32_t fec;
141 : : uint64_t port;
142 : : uint32_t rate;
143 : : uint64_t state;
144 : :
145 : 0 : port = rte_le_to_cpu_64(src->port);
146 : 0 : state = rte_le_to_cpu_64(src->state);
147 : :
148 : 0 : dst->eth_index = FIELD_GET(NSP_ETH_PORT_INDEX, port);
149 : 0 : dst->index = index;
150 : 0 : dst->nbi = index / NSP_ETH_NBI_PORT_COUNT;
151 : 0 : dst->base = index % NSP_ETH_NBI_PORT_COUNT;
152 : 0 : dst->lanes = FIELD_GET(NSP_ETH_PORT_LANES, port);
153 : :
154 : 0 : dst->enabled = FIELD_GET(NSP_ETH_STATE_ENABLED, state);
155 : 0 : dst->tx_enabled = FIELD_GET(NSP_ETH_STATE_TX_ENABLED, state);
156 : 0 : dst->rx_enabled = FIELD_GET(NSP_ETH_STATE_RX_ENABLED, state);
157 : :
158 : 0 : rate = nfp_eth_rate2speed(FIELD_GET(NSP_ETH_STATE_RATE, state));
159 : 0 : dst->speed = dst->lanes * rate;
160 : :
161 : 0 : dst->interface = FIELD_GET(NSP_ETH_STATE_INTERFACE, state);
162 : 0 : dst->media = FIELD_GET(NSP_ETH_STATE_MEDIA, state);
163 : :
164 : 0 : nfp_eth_copy_mac_reverse(&dst->mac_addr.addr_bytes[0], src->mac_addr);
165 : :
166 : 0 : dst->label_port = FIELD_GET(NSP_ETH_PORT_PHYLABEL, port);
167 : 0 : dst->label_subport = FIELD_GET(NSP_ETH_PORT_LABEL, port);
168 : :
169 [ # # ]: 0 : if (nfp_nsp_get_abi_ver_minor(nsp) < 17)
170 : : return;
171 : :
172 : 0 : dst->override_changed = FIELD_GET(NSP_ETH_STATE_OVRD_CHNG, state);
173 : 0 : dst->aneg = FIELD_GET(NSP_ETH_STATE_ANEG, state);
174 : :
175 [ # # ]: 0 : if (nfp_nsp_get_abi_ver_minor(nsp) < 22)
176 : : return;
177 : :
178 : 0 : fec = FIELD_GET(NSP_ETH_PORT_FEC_SUPP_BASER, port);
179 : 0 : dst->fec_modes_supported |= fec << NFP_FEC_BASER_BIT;
180 : 0 : fec = FIELD_GET(NSP_ETH_PORT_FEC_SUPP_RS, port);
181 : 0 : dst->fec_modes_supported |= fec << NFP_FEC_REED_SOLOMON_BIT;
182 [ # # ]: 0 : if (dst->fec_modes_supported != 0)
183 : 0 : dst->fec_modes_supported |= NFP_FEC_AUTO | NFP_FEC_DISABLED;
184 : :
185 : 0 : dst->fec = FIELD_GET(NSP_ETH_STATE_FEC, state);
186 : 0 : dst->act_fec = dst->fec;
187 : :
188 [ # # ]: 0 : if (nfp_nsp_get_abi_ver_minor(nsp) < 33)
189 : : return;
190 : :
191 : 0 : dst->act_fec = FIELD_GET(NSP_ETH_STATE_ACT_FEC, state);
192 : 0 : dst->supp_aneg = FIELD_GET(NSP_ETH_PORT_SUPP_ANEG, port);
193 : :
194 [ # # ]: 0 : if (nfp_nsp_get_abi_ver_minor(nsp) < 37) {
195 : 0 : dst->tx_pause_enabled = true;
196 : 0 : dst->rx_pause_enabled = true;
197 : 0 : return;
198 : : }
199 : :
200 : 0 : dst->tx_pause_enabled = FIELD_GET(NSP_ETH_STATE_TX_PAUSE, state);
201 : 0 : dst->rx_pause_enabled = FIELD_GET(NSP_ETH_STATE_RX_PAUSE, state);
202 : : }
203 : :
204 : : static void
205 : 0 : nfp_eth_calc_port_geometry(struct nfp_eth_table *table)
206 : : {
207 : : uint32_t i;
208 : : uint32_t j;
209 : :
210 [ # # ]: 0 : for (i = 0; i < table->count; i++) {
211 : 0 : table->max_index = RTE_MAX(table->max_index,
212 : : table->ports[i].index);
213 : :
214 [ # # ]: 0 : for (j = 0; j < table->count; j++) {
215 : 0 : if (table->ports[i].label_port !=
216 [ # # ]: 0 : table->ports[j].label_port)
217 : 0 : continue;
218 : :
219 : 0 : table->ports[i].port_lanes += table->ports[j].lanes;
220 : :
221 [ # # ]: 0 : if (i == j)
222 : 0 : continue;
223 : :
224 : 0 : if (table->ports[i].label_subport ==
225 [ # # ]: 0 : table->ports[j].label_subport)
226 : 0 : PMD_DRV_LOG(DEBUG, "Port %d subport %d is a duplicate",
227 : : table->ports[i].label_port,
228 : : table->ports[i].label_subport);
229 : :
230 : 0 : table->ports[i].is_split = true;
231 : : }
232 : : }
233 : 0 : }
234 : :
235 : : static void
236 : : nfp_eth_calc_port_type(struct nfp_eth_table_port *entry)
237 : : {
238 [ # # ]: 0 : if (entry->interface == NFP_INTERFACE_NONE) {
239 : 0 : entry->port_type = PORT_NONE;
240 : 0 : return;
241 [ # # ]: 0 : } else if (entry->interface == NFP_INTERFACE_RJ45) {
242 : 0 : entry->port_type = PORT_TP;
243 : 0 : return;
244 : : }
245 : :
246 [ # # ]: 0 : if (entry->media == NFP_MEDIA_FIBRE)
247 : 0 : entry->port_type = PORT_FIBRE;
248 : : else
249 : 0 : entry->port_type = PORT_DA;
250 : : }
251 : :
252 : : static struct nfp_eth_table *
253 : 0 : nfp_eth_read_ports_real(struct nfp_nsp *nsp)
254 : : {
255 : : int ret;
256 : : uint32_t i;
257 : : uint32_t j;
258 : : int cnt = 0;
259 : : uint32_t table_sz;
260 : : struct nfp_eth_table *table;
261 : : union eth_table_entry *entries;
262 : :
263 : 0 : entries = malloc(NSP_ETH_TABLE_SIZE);
264 [ # # ]: 0 : if (entries == NULL)
265 : : return NULL;
266 : :
267 : : memset(entries, 0, NSP_ETH_TABLE_SIZE);
268 : 0 : ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
269 [ # # ]: 0 : if (ret < 0) {
270 : 0 : PMD_DRV_LOG(ERR, "Reading port table failed %d", ret);
271 : 0 : goto err;
272 : : }
273 : :
274 [ # # ]: 0 : for (i = 0; i < NSP_ETH_MAX_COUNT; i++)
275 [ # # ]: 0 : if ((entries[i].port & NSP_ETH_PORT_LANES_MASK) != 0)
276 : 0 : cnt++;
277 : :
278 : : /*
279 : : * Some versions of flash will give us 0 instead of port count. For
280 : : * those that give a port count, verify it against the value calculated
281 : : * above.
282 : : */
283 [ # # ]: 0 : if (ret != 0 && ret != cnt) {
284 : 0 : PMD_DRV_LOG(ERR, "Table entry count (%d) unmatch entries present (%d)",
285 : : ret, cnt);
286 : 0 : goto err;
287 : : }
288 : :
289 : 0 : table_sz = sizeof(*table) + sizeof(struct nfp_eth_table_port) * cnt;
290 : 0 : table = malloc(table_sz);
291 [ # # ]: 0 : if (table == NULL)
292 : 0 : goto err;
293 : :
294 : : memset(table, 0, table_sz);
295 : 0 : table->count = cnt;
296 [ # # ]: 0 : for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++) {
297 [ # # ]: 0 : if ((entries[i].port & NSP_ETH_PORT_LANES_MASK) != 0)
298 : 0 : nfp_eth_port_translate(nsp, &entries[i], i, &table->ports[j++]);
299 : : }
300 : :
301 : 0 : nfp_eth_calc_port_geometry(table);
302 [ # # ]: 0 : for (i = 0; i < table->count; i++)
303 : : nfp_eth_calc_port_type(&table->ports[i]);
304 : :
305 : 0 : free(entries);
306 : :
307 : 0 : return table;
308 : :
309 : 0 : err:
310 : 0 : free(entries);
311 : 0 : return NULL;
312 : : }
313 : :
314 : : /**
315 : : * Read the port information from the device.
316 : : *
317 : : * Returned structure should be freed once no longer needed.
318 : : *
319 : : * @param cpp
320 : : * NFP CPP handle
321 : : *
322 : : * @return
323 : : * Populated ETH table or NULL on error.
324 : : */
325 : : struct nfp_eth_table *
326 : 0 : nfp_eth_read_ports(struct nfp_cpp *cpp)
327 : : {
328 : : struct nfp_nsp *nsp;
329 : : struct nfp_eth_table *ret;
330 : :
331 : 0 : nsp = nfp_nsp_open(cpp);
332 [ # # ]: 0 : if (nsp == NULL)
333 : : return NULL;
334 : :
335 : 0 : ret = nfp_eth_read_ports_real(nsp);
336 : 0 : nfp_nsp_close(nsp);
337 : :
338 : 0 : return ret;
339 : : }
340 : :
341 : : struct nfp_nsp *
342 : 0 : nfp_eth_config_start(struct nfp_cpp *cpp,
343 : : uint32_t idx)
344 : : {
345 : : int ret;
346 : : struct nfp_nsp *nsp;
347 : : union eth_table_entry *entries;
348 : :
349 : 0 : entries = malloc(NSP_ETH_TABLE_SIZE);
350 [ # # ]: 0 : if (entries == NULL)
351 : : return NULL;
352 : :
353 : : memset(entries, 0, NSP_ETH_TABLE_SIZE);
354 : 0 : nsp = nfp_nsp_open(cpp);
355 [ # # ]: 0 : if (nsp == NULL) {
356 : 0 : free(entries);
357 : 0 : return nsp;
358 : : }
359 : :
360 : 0 : ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
361 [ # # ]: 0 : if (ret < 0) {
362 : 0 : PMD_DRV_LOG(ERR, "Reading port table failed %d", ret);
363 : 0 : goto err;
364 : : }
365 : :
366 [ # # ]: 0 : if ((entries[idx].port & NSP_ETH_PORT_LANES_MASK) == 0) {
367 : 0 : PMD_DRV_LOG(ERR, "Trying to set port state on disabled port %d", idx);
368 : 0 : goto err;
369 : : }
370 : :
371 : 0 : nfp_nsp_config_set_state(nsp, entries, idx);
372 : 0 : return nsp;
373 : :
374 : 0 : err:
375 : 0 : nfp_nsp_close(nsp);
376 : 0 : free(entries);
377 : 0 : return NULL;
378 : : }
379 : :
380 : : void
381 : 0 : nfp_eth_config_cleanup_end(struct nfp_nsp *nsp)
382 : : {
383 : 0 : union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
384 : :
385 : 0 : nfp_nsp_config_set_modified(nsp, 0);
386 : 0 : nfp_nsp_config_clear_state(nsp);
387 : 0 : nfp_nsp_close(nsp);
388 : 0 : free(entries);
389 : 0 : }
390 : :
391 : : /**
392 : : * Perform the configuration which was requested with __nfp_eth_set_*()
393 : : * helpers and recorded in @nsp state. If device was already configured
394 : : * as requested or no __nfp_eth_set_*() operations were made, no NSP command
395 : : * will be performed.
396 : : *
397 : : * @param nsp
398 : : * NFP NSP handle returned from nfp_eth_config_start()
399 : : *
400 : : * @return
401 : : * - (0) Configuration successful
402 : : * - (1) No changes were needed
403 : : * - (-ERRNO) Configuration failed
404 : : */
405 : : int
406 : 0 : nfp_eth_config_commit_end(struct nfp_nsp *nsp)
407 : : {
408 : : int ret = 1;
409 : 0 : union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
410 : :
411 [ # # ]: 0 : if (nfp_nsp_config_modified(nsp)) {
412 : 0 : ret = nfp_nsp_write_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
413 : 0 : ret = ret < 0 ? ret : 0;
414 : : }
415 : :
416 : 0 : nfp_eth_config_cleanup_end(nsp);
417 : :
418 : 0 : return ret;
419 : : }
420 : :
421 : : /**
422 : : * Enable or disable PHY module (this usually means setting the TX lanes
423 : : * disable bits).
424 : : *
425 : : * @param cpp
426 : : * NFP CPP handle
427 : : * @param idx
428 : : * NFP chip-wide port index
429 : : * @param enable
430 : : * Desired state
431 : : *
432 : : * @return
433 : : * - (0) Configuration successful
434 : : * - (1) No changes were needed
435 : : * - (-ERRNO) Configuration failed
436 : : */
437 : : int
438 : 0 : nfp_eth_set_mod_enable(struct nfp_cpp *cpp,
439 : : uint32_t idx,
440 : : bool enable)
441 : : {
442 : : uint64_t reg;
443 : : struct nfp_nsp *nsp;
444 : : union eth_table_entry *entries;
445 : :
446 : 0 : nsp = nfp_eth_config_start(cpp, idx);
447 [ # # ]: 0 : if (nsp == NULL)
448 : : return -EIO;
449 : :
450 : 0 : entries = nfp_nsp_config_entries(nsp);
451 : :
452 : : /* Check if we are already in requested state */
453 : 0 : reg = rte_le_to_cpu_64(entries[idx].state);
454 [ # # ]: 0 : if (enable != (int)FIELD_GET(NSP_ETH_CTRL_ENABLED, reg)) {
455 : 0 : reg = rte_le_to_cpu_64(entries[idx].control);
456 : 0 : reg &= ~NSP_ETH_CTRL_ENABLED;
457 : 0 : reg |= FIELD_PREP(NSP_ETH_CTRL_ENABLED, enable);
458 : 0 : entries[idx].control = rte_cpu_to_le_64(reg);
459 : :
460 : 0 : nfp_nsp_config_set_modified(nsp, true);
461 : : }
462 : :
463 : 0 : return nfp_eth_config_commit_end(nsp);
464 : : }
465 : :
466 : : /**
467 : : * Set the ifup/ifdown state on the PHY.
468 : : *
469 : : * @param cpp
470 : : * NFP CPP handle
471 : : * @param idx
472 : : * NFP chip-wide port index
473 : : * @param configured
474 : : * Desired state
475 : : *
476 : : * @return
477 : : * - (0) Configuration successful
478 : : * - (1) No changes were needed
479 : : * - (-ERRNO) Configuration failed
480 : : */
481 : : int
482 : 0 : nfp_eth_set_configured(struct nfp_cpp *cpp,
483 : : uint32_t idx,
484 : : bool configured)
485 : : {
486 : : uint64_t reg;
487 : : struct nfp_nsp *nsp;
488 : : union eth_table_entry *entries;
489 : :
490 : 0 : nsp = nfp_eth_config_start(cpp, idx);
491 [ # # ]: 0 : if (nsp == NULL)
492 : : return -EIO;
493 : :
494 : : /*
495 : : * Older ABI versions did support this feature, however this has only
496 : : * been reliable since ABI 20.
497 : : */
498 [ # # ]: 0 : if (nfp_nsp_get_abi_ver_minor(nsp) < 20) {
499 : 0 : nfp_eth_config_cleanup_end(nsp);
500 : 0 : return -EOPNOTSUPP;
501 : : }
502 : :
503 : 0 : entries = nfp_nsp_config_entries(nsp);
504 : :
505 : : /* Check if we are already in requested state */
506 : 0 : reg = rte_le_to_cpu_64(entries[idx].state);
507 [ # # ]: 0 : if (configured != (int)FIELD_GET(NSP_ETH_STATE_CONFIGURED, reg)) {
508 : 0 : reg = rte_le_to_cpu_64(entries[idx].control);
509 : 0 : reg &= ~NSP_ETH_CTRL_CONFIGURED;
510 : 0 : reg |= FIELD_PREP(NSP_ETH_CTRL_CONFIGURED, configured);
511 : 0 : entries[idx].control = rte_cpu_to_le_64(reg);
512 : :
513 : 0 : nfp_nsp_config_set_modified(nsp, true);
514 : : }
515 : :
516 : 0 : return nfp_eth_config_commit_end(nsp);
517 : : }
518 : :
519 : : static int
520 : 0 : nfp_eth_set_bit_config(struct nfp_nsp *nsp,
521 : : uint32_t raw_idx,
522 : : const uint64_t mask,
523 : : const uint32_t shift,
524 : : uint64_t val,
525 : : const uint64_t ctrl_bit)
526 : : {
527 : : uint64_t reg;
528 : 0 : uint32_t idx = nfp_nsp_config_idx(nsp);
529 : 0 : union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
530 : :
531 : : /*
532 : : * Note: set features were added in ABI 0.14 but the error
533 : : * codes were initially not populated correctly.
534 : : */
535 [ # # ]: 0 : if (nfp_nsp_get_abi_ver_minor(nsp) < 17) {
536 : 0 : PMD_DRV_LOG(ERR, "set operations not supported, please update flash");
537 : 0 : return -EOPNOTSUPP;
538 : : }
539 : :
540 : : /* Check if we are already in requested state */
541 : 0 : reg = rte_le_to_cpu_64(entries[idx].raw[raw_idx]);
542 [ # # ]: 0 : if (val == (reg & mask) >> shift)
543 : : return 0;
544 : :
545 : : reg &= ~mask;
546 : 0 : reg |= (val << shift) & mask;
547 : 0 : entries[idx].raw[raw_idx] = rte_cpu_to_le_64(reg);
548 : :
549 : 0 : entries[idx].control |= rte_cpu_to_le_64(ctrl_bit);
550 : :
551 : 0 : nfp_nsp_config_set_modified(nsp, true);
552 : :
553 : 0 : return 0;
554 : : }
555 : :
556 : : #define NFP_ETH_SET_BIT_CONFIG(nsp, raw_idx, mask, val, ctrl_bit) \
557 : : (__extension__ ({ \
558 : : typeof(mask) _x = (mask); \
559 : : nfp_eth_set_bit_config(nsp, raw_idx, _x, __bf_shf(_x), \
560 : : val, ctrl_bit); \
561 : : }))
562 : :
563 : : /**
564 : : * Allow/disallow PHY module to advertise/perform autonegotiation.
565 : : * Will write to hwinfo overrides in the flash (persistent config).
566 : : *
567 : : * @param nsp
568 : : * NFP NSP handle returned from nfp_eth_config_start()
569 : : * @param mode
570 : : * Desired autonegotiation mode
571 : : *
572 : : * @return
573 : : * 0 or -ERRNO
574 : : */
575 : : int
576 : 0 : nfp_eth_set_aneg(struct nfp_nsp *nsp,
577 : : enum nfp_eth_aneg mode)
578 : : {
579 : 0 : return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
580 : : NSP_ETH_STATE_ANEG, mode, NSP_ETH_CTRL_SET_ANEG);
581 : : }
582 : :
583 : : /**
584 : : * Set the PHY module forward error correction mode.
585 : : * Will write to hwinfo overrides in the flash (persistent config).
586 : : *
587 : : * @param nsp
588 : : * NFP NSP handle returned from nfp_eth_config_start()
589 : : * @param mode
590 : : * Desired fec mode
591 : : *
592 : : * @return
593 : : * 0 or -ERRNO
594 : : */
595 : : static int
596 : : nfp_eth_set_fec_real(struct nfp_nsp *nsp,
597 : : enum nfp_eth_fec mode)
598 : : {
599 : 0 : return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
600 : : NSP_ETH_STATE_FEC, mode, NSP_ETH_CTRL_SET_FEC);
601 : : }
602 : :
603 : : /**
604 : : * Set PHY forward error correction control mode
605 : : *
606 : : * @param cpp
607 : : * NFP CPP handle
608 : : * @param idx
609 : : * NFP chip-wide port index
610 : : * @param mode
611 : : * Desired fec mode
612 : : *
613 : : * @return
614 : : * - (0) Configuration successful
615 : : * - (1) No changes were needed
616 : : * - (-ERRNO) Configuration failed
617 : : */
618 : : int
619 : 0 : nfp_eth_set_fec(struct nfp_cpp *cpp,
620 : : uint32_t idx,
621 : : enum nfp_eth_fec mode)
622 : : {
623 : : int err;
624 : : struct nfp_nsp *nsp;
625 : :
626 : 0 : nsp = nfp_eth_config_start(cpp, idx);
627 [ # # ]: 0 : if (nsp == NULL)
628 : : return -EIO;
629 : :
630 : : err = nfp_eth_set_fec_real(nsp, mode);
631 [ # # ]: 0 : if (err != 0) {
632 : 0 : nfp_eth_config_cleanup_end(nsp);
633 : 0 : return err;
634 : : }
635 : :
636 : 0 : return nfp_eth_config_commit_end(nsp);
637 : : }
638 : :
639 : : /**
640 : : * Set lane speed.
641 : : * Provided @speed value should be subport speed divided by number of
642 : : * lanes this subport is spanning (i.e. 10000 for 40G, 25000 for 50G, etc.)
643 : : * Will write to hwinfo overrides in the flash (persistent config).
644 : : *
645 : : * @param nsp
646 : : * NFP NSP handle returned from nfp_eth_config_start()
647 : : * @param speed
648 : : * Desired speed (per lane)
649 : : *
650 : : * @return
651 : : * 0 or -ERRNO
652 : : */
653 : : int
654 : 0 : nfp_eth_set_speed(struct nfp_nsp *nsp,
655 : : uint32_t speed)
656 : : {
657 : : enum nfp_eth_rate rate;
658 : :
659 : : rate = nfp_eth_speed2rate(speed);
660 [ # # ]: 0 : if (rate == RATE_INVALID) {
661 : 0 : PMD_DRV_LOG(ERR, "Could not find matching lane rate for speed %u", speed);
662 : 0 : return -EINVAL;
663 : : }
664 : :
665 : 0 : return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
666 : : NSP_ETH_STATE_RATE, rate, NSP_ETH_CTRL_SET_RATE);
667 : : }
668 : :
669 : : /**
670 : : * Set number of lanes in the port.
671 : : * Will write to hwinfo overrides in the flash (persistent config).
672 : : *
673 : : * @param nsp
674 : : * NFP NSP handle returned from nfp_eth_config_start()
675 : : * @param lanes
676 : : * Desired lanes per port
677 : : *
678 : : * @return
679 : : * 0 or -ERRNO
680 : : */
681 : : int
682 : 0 : nfp_eth_set_split(struct nfp_nsp *nsp,
683 : : uint32_t lanes)
684 : : {
685 : 0 : return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_PORT,
686 : : NSP_ETH_PORT_LANES, lanes, NSP_ETH_CTRL_SET_LANES);
687 : : }
688 : :
689 : : /**
690 : : * Set TX pause switch.
691 : : *
692 : : * @param nsp
693 : : * NFP NSP handle returned from nfp_eth_config_start()
694 : : * @param tx_pause
695 : : * TX pause switch
696 : : *
697 : : * @return
698 : : * 0 or -ERRNO
699 : : */
700 : : int
701 : 0 : nfp_eth_set_tx_pause(struct nfp_nsp *nsp,
702 : : bool tx_pause)
703 : : {
704 [ # # ]: 0 : if (nfp_nsp_get_abi_ver_minor(nsp) < 37) {
705 : 0 : PMD_DRV_LOG(ERR, "Set frame pause operation not supported, please update flash.");
706 : 0 : return -EOPNOTSUPP;
707 : : }
708 : :
709 : 0 : return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
710 : : NSP_ETH_STATE_TX_PAUSE, tx_pause, NSP_ETH_CTRL_SET_TX_PAUSE);
711 : : }
712 : :
713 : : /**
714 : : * Set RX pause switch.
715 : : *
716 : : * @param nsp
717 : : * NFP NSP handle returned from nfp_eth_config_start()
718 : : * @param rx_pause
719 : : * RX pause switch
720 : : *
721 : : * @return
722 : : * 0 or -ERRNO
723 : : */
724 : : int
725 : 0 : nfp_eth_set_rx_pause(struct nfp_nsp *nsp,
726 : : bool rx_pause)
727 : : {
728 [ # # ]: 0 : if (nfp_nsp_get_abi_ver_minor(nsp) < 37) {
729 : 0 : PMD_DRV_LOG(ERR, "Set frame pause operation not supported, please update flash.");
730 : 0 : return -EOPNOTSUPP;
731 : : }
732 : :
733 : 0 : return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
734 : : NSP_ETH_STATE_RX_PAUSE, rx_pause, NSP_ETH_CTRL_SET_RX_PAUSE);
735 : : }
|