net/failsafe: fix crash on slave queue release
[dpdk.git] / drivers / net / sfc / sfc_port.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright (c) 2016-2018 Solarflare Communications Inc.
4  * All rights reserved.
5  *
6  * This software was jointly developed between OKTET Labs (under contract
7  * for Solarflare) and Solarflare Communications, Inc.
8  */
9
10 #include "efx.h"
11
12 #include "sfc.h"
13 #include "sfc_log.h"
14 #include "sfc_kvargs.h"
15
16 /** Default MAC statistics update period is 1 second */
17 #define SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF      MS_PER_S
18
19 /** The number of microseconds to sleep on attempt to get statistics update */
20 #define SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US  10
21
22 /** The number of attempts to await arrival of freshly generated statistics */
23 #define SFC_MAC_STATS_UPDATE_NB_ATTEMPTS        50
24
25 /**
26  * Update MAC statistics in the buffer.
27  *
28  * @param       sa      Adapter
29  *
30  * @return Status code
31  * @retval      0       Success
32  * @retval      EAGAIN  Try again
33  * @retval      ENOMEM  Memory allocation failure
34  */
35 int
36 sfc_port_update_mac_stats(struct sfc_adapter *sa)
37 {
38         struct sfc_port *port = &sa->port;
39         efsys_mem_t *esmp = &port->mac_stats_dma_mem;
40         uint32_t *genp = NULL;
41         uint32_t gen_old;
42         unsigned int nb_attempts = 0;
43         int rc;
44
45         SFC_ASSERT(rte_spinlock_is_locked(&port->mac_stats_lock));
46
47         if (sa->state != SFC_ADAPTER_STARTED)
48                 return EINVAL;
49
50         /*
51          * If periodic statistics DMA'ing is off or if not supported,
52          * make a manual request and keep an eye on timer if need be
53          */
54         if (!port->mac_stats_periodic_dma_supported ||
55             (port->mac_stats_update_period_ms == 0)) {
56                 if (port->mac_stats_update_period_ms != 0) {
57                         uint64_t timestamp = sfc_get_system_msecs();
58
59                         if ((timestamp -
60                              port->mac_stats_last_request_timestamp) <
61                             port->mac_stats_update_period_ms)
62                                 return 0;
63
64                         port->mac_stats_last_request_timestamp = timestamp;
65                 }
66
67                 rc = efx_mac_stats_upload(sa->nic, esmp);
68                 if (rc != 0)
69                         return rc;
70
71                 genp = &port->mac_stats_update_generation;
72                 gen_old = *genp;
73         }
74
75         do {
76                 if (nb_attempts > 0)
77                         rte_delay_us(SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US);
78
79                 rc = efx_mac_stats_update(sa->nic, esmp,
80                                           port->mac_stats_buf, genp);
81                 if (rc != 0)
82                         return rc;
83
84         } while ((genp != NULL) && (*genp == gen_old) &&
85                  (++nb_attempts < SFC_MAC_STATS_UPDATE_NB_ATTEMPTS));
86
87         return 0;
88 }
89
90 int
91 sfc_port_reset_mac_stats(struct sfc_adapter *sa)
92 {
93         struct sfc_port *port = &sa->port;
94         int rc;
95
96         rte_spinlock_lock(&port->mac_stats_lock);
97         rc = efx_mac_stats_clear(sa->nic);
98         rte_spinlock_unlock(&port->mac_stats_lock);
99
100         return rc;
101 }
102
103 static int
104 sfc_port_init_dev_link(struct sfc_adapter *sa)
105 {
106         struct rte_eth_link *dev_link = &sa->eth_dev->data->dev_link;
107         int rc;
108         efx_link_mode_t link_mode;
109         struct rte_eth_link current_link;
110
111         rc = efx_port_poll(sa->nic, &link_mode);
112         if (rc != 0)
113                 return rc;
114
115         sfc_port_link_mode_to_info(link_mode, &current_link);
116
117         EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
118         rte_atomic64_set((rte_atomic64_t *)dev_link,
119                          *(uint64_t *)&current_link);
120
121         return 0;
122 }
123
124 #if EFSYS_OPT_LOOPBACK
125
126 static efx_link_mode_t
127 sfc_port_phy_caps_to_max_link_speed(uint32_t phy_caps)
128 {
129         if (phy_caps & (1u << EFX_PHY_CAP_100000FDX))
130                 return EFX_LINK_100000FDX;
131         if (phy_caps & (1u << EFX_PHY_CAP_50000FDX))
132                 return EFX_LINK_50000FDX;
133         if (phy_caps & (1u << EFX_PHY_CAP_40000FDX))
134                 return EFX_LINK_40000FDX;
135         if (phy_caps & (1u << EFX_PHY_CAP_25000FDX))
136                 return EFX_LINK_25000FDX;
137         if (phy_caps & (1u << EFX_PHY_CAP_10000FDX))
138                 return EFX_LINK_10000FDX;
139         if (phy_caps & (1u << EFX_PHY_CAP_1000FDX))
140                 return EFX_LINK_1000FDX;
141         return EFX_LINK_UNKNOWN;
142 }
143
144 #endif
145
146 int
147 sfc_port_start(struct sfc_adapter *sa)
148 {
149         struct sfc_port *port = &sa->port;
150         int rc;
151         uint32_t phy_adv_cap;
152         const uint32_t phy_pause_caps =
153                 ((1u << EFX_PHY_CAP_PAUSE) | (1u << EFX_PHY_CAP_ASYM));
154         unsigned int i;
155
156         sfc_log_init(sa, "entry");
157
158         sfc_log_init(sa, "init filters");
159         rc = efx_filter_init(sa->nic);
160         if (rc != 0)
161                 goto fail_filter_init;
162
163         sfc_log_init(sa, "init port");
164         rc = efx_port_init(sa->nic);
165         if (rc != 0)
166                 goto fail_port_init;
167
168 #if EFSYS_OPT_LOOPBACK
169         if (sa->eth_dev->data->dev_conf.lpbk_mode != 0) {
170                 efx_link_mode_t link_mode;
171
172                 link_mode =
173                         sfc_port_phy_caps_to_max_link_speed(port->phy_adv_cap);
174                 sfc_log_init(sa, "set loopback link_mode=%u type=%u", link_mode,
175                              sa->eth_dev->data->dev_conf.lpbk_mode);
176                 rc = efx_port_loopback_set(sa->nic, link_mode,
177                         sa->eth_dev->data->dev_conf.lpbk_mode);
178                 if (rc != 0)
179                         goto fail_loopback_set;
180         }
181 #endif
182
183         sfc_log_init(sa, "set flow control to %#x autoneg=%u",
184                      port->flow_ctrl, port->flow_ctrl_autoneg);
185         rc = efx_mac_fcntl_set(sa->nic, port->flow_ctrl,
186                                port->flow_ctrl_autoneg);
187         if (rc != 0)
188                 goto fail_mac_fcntl_set;
189
190         /* Preserve pause capabilities set by above efx_mac_fcntl_set()  */
191         efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_CURRENT, &phy_adv_cap);
192         SFC_ASSERT((port->phy_adv_cap & phy_pause_caps) == 0);
193         phy_adv_cap = port->phy_adv_cap | (phy_adv_cap & phy_pause_caps);
194
195         /*
196          * No controls for FEC yet. Use default FEC mode.
197          * I.e. advertise everything supported (*_FEC=1), but do not request
198          * anything explicitly (*_FEC_REQUESTED=0).
199          */
200         phy_adv_cap |= port->phy_adv_cap_mask &
201                 (1u << EFX_PHY_CAP_BASER_FEC |
202                  1u << EFX_PHY_CAP_RS_FEC |
203                  1u << EFX_PHY_CAP_25G_BASER_FEC);
204
205         sfc_log_init(sa, "set phy adv caps to %#x", phy_adv_cap);
206         rc = efx_phy_adv_cap_set(sa->nic, phy_adv_cap);
207         if (rc != 0)
208                 goto fail_phy_adv_cap_set;
209
210         sfc_log_init(sa, "set MAC PDU %u", (unsigned int)port->pdu);
211         rc = efx_mac_pdu_set(sa->nic, port->pdu);
212         if (rc != 0)
213                 goto fail_mac_pdu_set;
214
215         if (!port->isolated) {
216                 struct ether_addr *addr = &port->default_mac_addr;
217
218                 sfc_log_init(sa, "set MAC address");
219                 rc = efx_mac_addr_set(sa->nic, addr->addr_bytes);
220                 if (rc != 0)
221                         goto fail_mac_addr_set;
222
223                 sfc_log_init(sa, "set MAC filters");
224                 port->promisc = (sa->eth_dev->data->promiscuous != 0) ?
225                                 B_TRUE : B_FALSE;
226                 port->allmulti = (sa->eth_dev->data->all_multicast != 0) ?
227                                  B_TRUE : B_FALSE;
228                 rc = sfc_set_rx_mode(sa);
229                 if (rc != 0)
230                         goto fail_mac_filter_set;
231
232                 sfc_log_init(sa, "set multicast address list");
233                 rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs,
234                                                 port->nb_mcast_addrs);
235                 if (rc != 0)
236                         goto fail_mcast_address_list_set;
237         }
238
239         if (port->mac_stats_reset_pending) {
240                 rc = sfc_port_reset_mac_stats(sa);
241                 if (rc != 0)
242                         sfc_err(sa, "statistics reset failed (requested "
243                                     "before the port was started)");
244
245                 port->mac_stats_reset_pending = B_FALSE;
246         }
247
248         efx_mac_stats_get_mask(sa->nic, port->mac_stats_mask,
249                                sizeof(port->mac_stats_mask));
250
251         for (i = 0, port->mac_stats_nb_supported = 0; i < EFX_MAC_NSTATS; ++i)
252                 if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i))
253                         port->mac_stats_nb_supported++;
254
255         port->mac_stats_update_generation = 0;
256
257         if (port->mac_stats_update_period_ms != 0) {
258                 /*
259                  * Update MAC stats using periodic DMA;
260                  * any positive update interval different from
261                  * 1000 ms can be set only on SFN8xxx provided
262                  * that FW version is 6.2.1.1033 or higher
263                  */
264                 sfc_log_init(sa, "request MAC stats DMA'ing");
265                 rc = efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem,
266                                             port->mac_stats_update_period_ms,
267                                             B_FALSE);
268                 if (rc == 0) {
269                         port->mac_stats_periodic_dma_supported = B_TRUE;
270                 } else if (rc == EOPNOTSUPP) {
271                         port->mac_stats_periodic_dma_supported = B_FALSE;
272                         port->mac_stats_last_request_timestamp = 0;
273                 } else {
274                         goto fail_mac_stats_periodic;
275                 }
276         }
277
278         if ((port->mac_stats_update_period_ms != 0) &&
279             port->mac_stats_periodic_dma_supported) {
280                 /*
281                  * Request an explicit MAC stats upload immediately to
282                  * preclude bogus figures readback if the user decides
283                  * to read stats before periodic DMA is really started
284                  */
285                 rc = efx_mac_stats_upload(sa->nic, &port->mac_stats_dma_mem);
286                 if (rc != 0)
287                         goto fail_mac_stats_upload;
288         }
289
290         sfc_log_init(sa, "disable MAC drain");
291         rc = efx_mac_drain(sa->nic, B_FALSE);
292         if (rc != 0)
293                 goto fail_mac_drain;
294
295         /* Synchronize link status knowledge */
296         rc = sfc_port_init_dev_link(sa);
297         if (rc != 0)
298                 goto fail_port_init_dev_link;
299
300         sfc_log_init(sa, "done");
301         return 0;
302
303 fail_port_init_dev_link:
304         (void)efx_mac_drain(sa->nic, B_TRUE);
305
306 fail_mac_drain:
307 fail_mac_stats_upload:
308         (void)efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem,
309                                      0, B_FALSE);
310
311 fail_mac_stats_periodic:
312 fail_mcast_address_list_set:
313 fail_mac_filter_set:
314 fail_mac_addr_set:
315 fail_mac_pdu_set:
316 fail_phy_adv_cap_set:
317 fail_mac_fcntl_set:
318 #if EFSYS_OPT_LOOPBACK
319 fail_loopback_set:
320 #endif
321         efx_port_fini(sa->nic);
322
323 fail_port_init:
324         efx_filter_fini(sa->nic);
325
326 fail_filter_init:
327         sfc_log_init(sa, "failed %d", rc);
328         return rc;
329 }
330
331 void
332 sfc_port_stop(struct sfc_adapter *sa)
333 {
334         sfc_log_init(sa, "entry");
335
336         efx_mac_drain(sa->nic, B_TRUE);
337
338         (void)efx_mac_stats_periodic(sa->nic, &sa->port.mac_stats_dma_mem,
339                                      0, B_FALSE);
340
341         efx_port_fini(sa->nic);
342         efx_filter_fini(sa->nic);
343
344         sfc_log_init(sa, "done");
345 }
346
347 int
348 sfc_port_configure(struct sfc_adapter *sa)
349 {
350         const struct rte_eth_dev_data *dev_data = sa->eth_dev->data;
351         struct sfc_port *port = &sa->port;
352         const struct rte_eth_rxmode *rxmode = &dev_data->dev_conf.rxmode;
353
354         sfc_log_init(sa, "entry");
355
356         if (rxmode->offloads & DEV_RX_OFFLOAD_JUMBO_FRAME)
357                 port->pdu = rxmode->max_rx_pkt_len;
358         else
359                 port->pdu = EFX_MAC_PDU(dev_data->mtu);
360
361         return 0;
362 }
363
364 void
365 sfc_port_close(struct sfc_adapter *sa)
366 {
367         sfc_log_init(sa, "entry");
368 }
369
370 int
371 sfc_port_attach(struct sfc_adapter *sa)
372 {
373         struct sfc_port *port = &sa->port;
374         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
375         const struct ether_addr *from;
376         uint32_t mac_nstats;
377         size_t mac_stats_size;
378         long kvarg_stats_update_period_ms;
379         int rc;
380
381         sfc_log_init(sa, "entry");
382
383         efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_PERM, &port->phy_adv_cap_mask);
384
385         /* Enable flow control by default */
386         port->flow_ctrl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
387         port->flow_ctrl_autoneg = B_TRUE;
388
389         RTE_BUILD_BUG_ON(sizeof(encp->enc_mac_addr) != sizeof(*from));
390         from = (const struct ether_addr *)(encp->enc_mac_addr);
391         ether_addr_copy(from, &port->default_mac_addr);
392
393         port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX;
394         port->nb_mcast_addrs = 0;
395         port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf",
396                                               port->max_mcast_addrs,
397                                               EFX_MAC_ADDR_LEN, 0,
398                                               sa->socket_id);
399         if (port->mcast_addrs == NULL) {
400                 rc = ENOMEM;
401                 goto fail_mcast_addr_list_buf_alloc;
402         }
403
404         rte_spinlock_init(&port->mac_stats_lock);
405
406         rc = ENOMEM;
407         port->mac_stats_buf = rte_calloc_socket("mac_stats_buf", EFX_MAC_NSTATS,
408                                                 sizeof(uint64_t), 0,
409                                                 sa->socket_id);
410         if (port->mac_stats_buf == NULL)
411                 goto fail_mac_stats_buf_alloc;
412
413         mac_nstats = efx_nic_cfg_get(sa->nic)->enc_mac_stats_nstats;
414         mac_stats_size = RTE_ALIGN(mac_nstats * sizeof(uint64_t), EFX_BUF_SIZE);
415         rc = sfc_dma_alloc(sa, "mac_stats", 0, mac_stats_size,
416                            sa->socket_id, &port->mac_stats_dma_mem);
417         if (rc != 0)
418                 goto fail_mac_stats_dma_alloc;
419
420         port->mac_stats_reset_pending = B_FALSE;
421
422         kvarg_stats_update_period_ms = SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF;
423
424         rc = sfc_kvargs_process(sa, SFC_KVARG_STATS_UPDATE_PERIOD_MS,
425                                 sfc_kvarg_long_handler,
426                                 &kvarg_stats_update_period_ms);
427         if ((rc == 0) &&
428             ((kvarg_stats_update_period_ms < 0) ||
429              (kvarg_stats_update_period_ms > UINT16_MAX))) {
430                 sfc_err(sa, "wrong '" SFC_KVARG_STATS_UPDATE_PERIOD_MS "' "
431                             "was set (%ld);", kvarg_stats_update_period_ms);
432                 sfc_err(sa, "it must not be less than 0 "
433                             "or greater than %" PRIu16, UINT16_MAX);
434                 rc = EINVAL;
435                 goto fail_kvarg_stats_update_period_ms;
436         } else if (rc != 0) {
437                 goto fail_kvarg_stats_update_period_ms;
438         }
439
440         port->mac_stats_update_period_ms = kvarg_stats_update_period_ms;
441
442         sfc_log_init(sa, "done");
443         return 0;
444
445 fail_kvarg_stats_update_period_ms:
446         sfc_dma_free(sa, &port->mac_stats_dma_mem);
447
448 fail_mac_stats_dma_alloc:
449         rte_free(port->mac_stats_buf);
450
451 fail_mac_stats_buf_alloc:
452         rte_free(port->mcast_addrs);
453
454 fail_mcast_addr_list_buf_alloc:
455         sfc_log_init(sa, "failed %d", rc);
456         return rc;
457 }
458
459 void
460 sfc_port_detach(struct sfc_adapter *sa)
461 {
462         struct sfc_port *port = &sa->port;
463
464         sfc_log_init(sa, "entry");
465
466         sfc_dma_free(sa, &port->mac_stats_dma_mem);
467         rte_free(port->mac_stats_buf);
468
469         rte_free(port->mcast_addrs);
470
471         sfc_log_init(sa, "done");
472 }
473
474 int
475 sfc_set_rx_mode(struct sfc_adapter *sa)
476 {
477         struct sfc_port *port = &sa->port;
478         int rc;
479
480         rc = efx_mac_filter_set(sa->nic, port->promisc, B_TRUE,
481                                 port->promisc || port->allmulti, B_TRUE);
482
483         return rc;
484 }
485
486 void
487 sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
488                            struct rte_eth_link *link_info)
489 {
490         SFC_ASSERT(link_mode < EFX_LINK_NMODES);
491
492         memset(link_info, 0, sizeof(*link_info));
493         if ((link_mode == EFX_LINK_DOWN) || (link_mode == EFX_LINK_UNKNOWN))
494                 link_info->link_status = ETH_LINK_DOWN;
495         else
496                 link_info->link_status = ETH_LINK_UP;
497
498         switch (link_mode) {
499         case EFX_LINK_10HDX:
500                 link_info->link_speed  = ETH_SPEED_NUM_10M;
501                 link_info->link_duplex = ETH_LINK_HALF_DUPLEX;
502                 break;
503         case EFX_LINK_10FDX:
504                 link_info->link_speed  = ETH_SPEED_NUM_10M;
505                 link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
506                 break;
507         case EFX_LINK_100HDX:
508                 link_info->link_speed  = ETH_SPEED_NUM_100M;
509                 link_info->link_duplex = ETH_LINK_HALF_DUPLEX;
510                 break;
511         case EFX_LINK_100FDX:
512                 link_info->link_speed  = ETH_SPEED_NUM_100M;
513                 link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
514                 break;
515         case EFX_LINK_1000HDX:
516                 link_info->link_speed  = ETH_SPEED_NUM_1G;
517                 link_info->link_duplex = ETH_LINK_HALF_DUPLEX;
518                 break;
519         case EFX_LINK_1000FDX:
520                 link_info->link_speed  = ETH_SPEED_NUM_1G;
521                 link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
522                 break;
523         case EFX_LINK_10000FDX:
524                 link_info->link_speed  = ETH_SPEED_NUM_10G;
525                 link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
526                 break;
527         case EFX_LINK_25000FDX:
528                 link_info->link_speed  = ETH_SPEED_NUM_25G;
529                 link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
530                 break;
531         case EFX_LINK_40000FDX:
532                 link_info->link_speed  = ETH_SPEED_NUM_40G;
533                 link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
534                 break;
535         case EFX_LINK_50000FDX:
536                 link_info->link_speed  = ETH_SPEED_NUM_50G;
537                 link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
538                 break;
539         case EFX_LINK_100000FDX:
540                 link_info->link_speed  = ETH_SPEED_NUM_100G;
541                 link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
542                 break;
543         default:
544                 SFC_ASSERT(B_FALSE);
545                 /* FALLTHROUGH */
546         case EFX_LINK_UNKNOWN:
547         case EFX_LINK_DOWN:
548                 link_info->link_speed  = ETH_SPEED_NUM_NONE;
549                 link_info->link_duplex = 0;
550                 break;
551         }
552
553         link_info->link_autoneg = ETH_LINK_AUTONEG;
554 }