net/sfc: add representors proxy infrastructure
[dpdk.git] / drivers / net / sfc / sfc.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2021 Xilinx, Inc.
4  * Copyright(c) 2016-2019 Solarflare Communications Inc.
5  *
6  * This software was jointly developed between OKTET Labs (under contract
7  * for Solarflare) and Solarflare Communications, Inc.
8  */
9
10 /* sysconf() */
11 #include <unistd.h>
12
13 #include <rte_errno.h>
14 #include <rte_alarm.h>
15
16 #include "efx.h"
17
18 #include "sfc.h"
19 #include "sfc_debug.h"
20 #include "sfc_log.h"
21 #include "sfc_ev.h"
22 #include "sfc_rx.h"
23 #include "sfc_mae_counter.h"
24 #include "sfc_tx.h"
25 #include "sfc_kvargs.h"
26 #include "sfc_tweak.h"
27 #include "sfc_sw_stats.h"
28
29
30 bool
31 sfc_repr_supported(const struct sfc_adapter *sa)
32 {
33         if (!sa->switchdev)
34                 return false;
35
36         /*
37          * Representor proxy should use service lcore on PF's socket
38          * (sa->socket_id) to be efficient. But the proxy will fall back
39          * to any socket if it is not possible to get the service core
40          * on the same socket. Check that at least service core on any
41          * socket is available.
42          */
43         if (sfc_get_service_lcore(SOCKET_ID_ANY) == RTE_MAX_LCORE)
44                 return false;
45
46         return true;
47 }
48
49 int
50 sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id,
51               size_t len, int socket_id, efsys_mem_t *esmp)
52 {
53         const struct rte_memzone *mz;
54
55         sfc_log_init(sa, "name=%s id=%u len=%zu socket_id=%d",
56                      name, id, len, socket_id);
57
58         mz = rte_eth_dma_zone_reserve(sa->eth_dev, name, id, len,
59                                       sysconf(_SC_PAGESIZE), socket_id);
60         if (mz == NULL) {
61                 sfc_err(sa, "cannot reserve DMA zone for %s:%u %#x@%d: %s",
62                         name, (unsigned int)id, (unsigned int)len, socket_id,
63                         rte_strerror(rte_errno));
64                 return ENOMEM;
65         }
66
67         esmp->esm_addr = mz->iova;
68         if (esmp->esm_addr == RTE_BAD_IOVA) {
69                 (void)rte_memzone_free(mz);
70                 return EFAULT;
71         }
72
73         esmp->esm_mz = mz;
74         esmp->esm_base = mz->addr;
75
76         sfc_info(sa,
77                  "DMA name=%s id=%u len=%lu socket_id=%d => virt=%p iova=%lx",
78                  name, id, len, socket_id, esmp->esm_base,
79                  (unsigned long)esmp->esm_addr);
80
81         return 0;
82 }
83
84 void
85 sfc_dma_free(const struct sfc_adapter *sa, efsys_mem_t *esmp)
86 {
87         int rc;
88
89         sfc_log_init(sa, "name=%s", esmp->esm_mz->name);
90
91         rc = rte_memzone_free(esmp->esm_mz);
92         if (rc != 0)
93                 sfc_err(sa, "rte_memzone_free(() failed: %d", rc);
94
95         memset(esmp, 0, sizeof(*esmp));
96 }
97
98 static uint32_t
99 sfc_phy_cap_from_link_speeds(uint32_t speeds)
100 {
101         uint32_t phy_caps = 0;
102
103         if (~speeds & ETH_LINK_SPEED_FIXED) {
104                 phy_caps |= (1 << EFX_PHY_CAP_AN);
105                 /*
106                  * If no speeds are specified in the mask, any supported
107                  * may be negotiated
108                  */
109                 if (speeds == ETH_LINK_SPEED_AUTONEG)
110                         phy_caps |=
111                                 (1 << EFX_PHY_CAP_1000FDX) |
112                                 (1 << EFX_PHY_CAP_10000FDX) |
113                                 (1 << EFX_PHY_CAP_25000FDX) |
114                                 (1 << EFX_PHY_CAP_40000FDX) |
115                                 (1 << EFX_PHY_CAP_50000FDX) |
116                                 (1 << EFX_PHY_CAP_100000FDX);
117         }
118         if (speeds & ETH_LINK_SPEED_1G)
119                 phy_caps |= (1 << EFX_PHY_CAP_1000FDX);
120         if (speeds & ETH_LINK_SPEED_10G)
121                 phy_caps |= (1 << EFX_PHY_CAP_10000FDX);
122         if (speeds & ETH_LINK_SPEED_25G)
123                 phy_caps |= (1 << EFX_PHY_CAP_25000FDX);
124         if (speeds & ETH_LINK_SPEED_40G)
125                 phy_caps |= (1 << EFX_PHY_CAP_40000FDX);
126         if (speeds & ETH_LINK_SPEED_50G)
127                 phy_caps |= (1 << EFX_PHY_CAP_50000FDX);
128         if (speeds & ETH_LINK_SPEED_100G)
129                 phy_caps |= (1 << EFX_PHY_CAP_100000FDX);
130
131         return phy_caps;
132 }
133
134 /*
135  * Check requested device level configuration.
136  * Receive and transmit configuration is checked in corresponding
137  * modules.
138  */
139 static int
140 sfc_check_conf(struct sfc_adapter *sa)
141 {
142         const struct rte_eth_conf *conf = &sa->eth_dev->data->dev_conf;
143         int rc = 0;
144
145         sa->port.phy_adv_cap =
146                 sfc_phy_cap_from_link_speeds(conf->link_speeds) &
147                 sa->port.phy_adv_cap_mask;
148         if ((sa->port.phy_adv_cap & ~(1 << EFX_PHY_CAP_AN)) == 0) {
149                 sfc_err(sa, "No link speeds from mask %#x are supported",
150                         conf->link_speeds);
151                 rc = EINVAL;
152         }
153
154 #if !EFSYS_OPT_LOOPBACK
155         if (conf->lpbk_mode != 0) {
156                 sfc_err(sa, "Loopback not supported");
157                 rc = EINVAL;
158         }
159 #endif
160
161         if (conf->dcb_capability_en != 0) {
162                 sfc_err(sa, "Priority-based flow control not supported");
163                 rc = EINVAL;
164         }
165
166         if (conf->fdir_conf.mode != RTE_FDIR_MODE_NONE) {
167                 sfc_err(sa, "Flow Director not supported");
168                 rc = EINVAL;
169         }
170
171         if ((conf->intr_conf.lsc != 0) &&
172             (sa->intr.type != EFX_INTR_LINE) &&
173             (sa->intr.type != EFX_INTR_MESSAGE)) {
174                 sfc_err(sa, "Link status change interrupt not supported");
175                 rc = EINVAL;
176         }
177
178         if (conf->intr_conf.rxq != 0 &&
179             (sa->priv.dp_rx->features & SFC_DP_RX_FEAT_INTR) == 0) {
180                 sfc_err(sa, "Receive queue interrupt not supported");
181                 rc = EINVAL;
182         }
183
184         return rc;
185 }
186
187 /*
188  * Find out maximum number of receive and transmit queues which could be
189  * advertised.
190  *
191  * NIC is kept initialized on success to allow other modules acquire
192  * defaults and capabilities.
193  */
194 static int
195 sfc_estimate_resource_limits(struct sfc_adapter *sa)
196 {
197         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
198         struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
199         efx_drv_limits_t limits;
200         int rc;
201         uint32_t evq_allocated;
202         uint32_t rxq_allocated;
203         uint32_t txq_allocated;
204
205         memset(&limits, 0, sizeof(limits));
206
207         /* Request at least one Rx and Tx queue */
208         limits.edl_min_rxq_count = 1;
209         limits.edl_min_txq_count = 1;
210         /* Management event queue plus event queue for each Tx and Rx queue */
211         limits.edl_min_evq_count =
212                 1 + limits.edl_min_rxq_count + limits.edl_min_txq_count;
213
214         /* Divide by number of functions to guarantee that all functions
215          * will get promised resources
216          */
217         /* FIXME Divide by number of functions (not 2) below */
218         limits.edl_max_evq_count = encp->enc_evq_limit / 2;
219         SFC_ASSERT(limits.edl_max_evq_count >= limits.edl_min_rxq_count);
220
221         /* Split equally between receive and transmit */
222         limits.edl_max_rxq_count =
223                 MIN(encp->enc_rxq_limit, (limits.edl_max_evq_count - 1) / 2);
224         SFC_ASSERT(limits.edl_max_rxq_count >= limits.edl_min_rxq_count);
225
226         limits.edl_max_txq_count =
227                 MIN(encp->enc_txq_limit,
228                     limits.edl_max_evq_count - 1 - limits.edl_max_rxq_count);
229
230         if (sa->tso && encp->enc_fw_assisted_tso_v2_enabled)
231                 limits.edl_max_txq_count =
232                         MIN(limits.edl_max_txq_count,
233                             encp->enc_fw_assisted_tso_v2_n_contexts /
234                             encp->enc_hw_pf_count);
235
236         SFC_ASSERT(limits.edl_max_txq_count >= limits.edl_min_rxq_count);
237
238         /* Configure the minimum required resources needed for the
239          * driver to operate, and the maximum desired resources that the
240          * driver is capable of using.
241          */
242         efx_nic_set_drv_limits(sa->nic, &limits);
243
244         sfc_log_init(sa, "init nic");
245         rc = efx_nic_init(sa->nic);
246         if (rc != 0)
247                 goto fail_nic_init;
248
249         /* Find resource dimensions assigned by firmware to this function */
250         rc = efx_nic_get_vi_pool(sa->nic, &evq_allocated, &rxq_allocated,
251                                  &txq_allocated);
252         if (rc != 0)
253                 goto fail_get_vi_pool;
254
255         /* It still may allocate more than maximum, ensure limit */
256         evq_allocated = MIN(evq_allocated, limits.edl_max_evq_count);
257         rxq_allocated = MIN(rxq_allocated, limits.edl_max_rxq_count);
258         txq_allocated = MIN(txq_allocated, limits.edl_max_txq_count);
259
260         /*
261          * Subtract management EVQ not used for traffic
262          * The resource allocation strategy is as follows:
263          * - one EVQ for management
264          * - one EVQ for each ethdev RXQ
265          * - one EVQ for each ethdev TXQ
266          * - one EVQ and one RXQ for optional MAE counters.
267          */
268         if (evq_allocated == 0) {
269                 sfc_err(sa, "count of allocated EvQ is 0");
270                 rc = ENOMEM;
271                 goto fail_allocate_evq;
272         }
273         evq_allocated--;
274
275         /*
276          * Reserve absolutely required minimum.
277          * Right now we use separate EVQ for Rx and Tx.
278          */
279         if (rxq_allocated > 0 && evq_allocated > 0) {
280                 sa->rxq_max = 1;
281                 rxq_allocated--;
282                 evq_allocated--;
283         }
284         if (txq_allocated > 0 && evq_allocated > 0) {
285                 sa->txq_max = 1;
286                 txq_allocated--;
287                 evq_allocated--;
288         }
289
290         if (sfc_mae_counter_rxq_required(sa) &&
291             rxq_allocated > 0 && evq_allocated > 0) {
292                 rxq_allocated--;
293                 evq_allocated--;
294                 sas->counters_rxq_allocated = true;
295         } else {
296                 sas->counters_rxq_allocated = false;
297         }
298
299         /* Add remaining allocated queues */
300         sa->rxq_max += MIN(rxq_allocated, evq_allocated / 2);
301         sa->txq_max += MIN(txq_allocated, evq_allocated - sa->rxq_max);
302
303         /* Keep NIC initialized */
304         return 0;
305
306 fail_allocate_evq:
307 fail_get_vi_pool:
308         efx_nic_fini(sa->nic);
309 fail_nic_init:
310         return rc;
311 }
312
313 static int
314 sfc_set_drv_limits(struct sfc_adapter *sa)
315 {
316         const struct rte_eth_dev_data *data = sa->eth_dev->data;
317         uint32_t rxq_reserved = sfc_nb_reserved_rxq(sfc_sa2shared(sa));
318         efx_drv_limits_t lim;
319
320         memset(&lim, 0, sizeof(lim));
321
322         /*
323          * Limits are strict since take into account initial estimation.
324          * Resource allocation stategy is described in
325          * sfc_estimate_resource_limits().
326          */
327         lim.edl_min_evq_count = lim.edl_max_evq_count =
328                 1 + data->nb_rx_queues + data->nb_tx_queues + rxq_reserved;
329         lim.edl_min_rxq_count = lim.edl_max_rxq_count =
330                 data->nb_rx_queues + rxq_reserved;
331         lim.edl_min_txq_count = lim.edl_max_txq_count = data->nb_tx_queues;
332
333         return efx_nic_set_drv_limits(sa->nic, &lim);
334 }
335
336 static int
337 sfc_set_fw_subvariant(struct sfc_adapter *sa)
338 {
339         struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
340         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
341         uint64_t tx_offloads = sa->eth_dev->data->dev_conf.txmode.offloads;
342         unsigned int txq_index;
343         efx_nic_fw_subvariant_t req_fw_subvariant;
344         efx_nic_fw_subvariant_t cur_fw_subvariant;
345         int rc;
346
347         if (!encp->enc_fw_subvariant_no_tx_csum_supported) {
348                 sfc_info(sa, "no-Tx-checksum subvariant not supported");
349                 return 0;
350         }
351
352         for (txq_index = 0; txq_index < sas->txq_count; ++txq_index) {
353                 struct sfc_txq_info *txq_info = &sas->txq_info[txq_index];
354
355                 if (txq_info->state & SFC_TXQ_INITIALIZED)
356                         tx_offloads |= txq_info->offloads;
357         }
358
359         if (tx_offloads & (DEV_TX_OFFLOAD_IPV4_CKSUM |
360                            DEV_TX_OFFLOAD_TCP_CKSUM |
361                            DEV_TX_OFFLOAD_UDP_CKSUM |
362                            DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM))
363                 req_fw_subvariant = EFX_NIC_FW_SUBVARIANT_DEFAULT;
364         else
365                 req_fw_subvariant = EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM;
366
367         rc = efx_nic_get_fw_subvariant(sa->nic, &cur_fw_subvariant);
368         if (rc != 0) {
369                 sfc_err(sa, "failed to get FW subvariant: %d", rc);
370                 return rc;
371         }
372         sfc_info(sa, "FW subvariant is %u vs required %u",
373                  cur_fw_subvariant, req_fw_subvariant);
374
375         if (cur_fw_subvariant == req_fw_subvariant)
376                 return 0;
377
378         rc = efx_nic_set_fw_subvariant(sa->nic, req_fw_subvariant);
379         if (rc != 0) {
380                 sfc_err(sa, "failed to set FW subvariant %u: %d",
381                         req_fw_subvariant, rc);
382                 return rc;
383         }
384         sfc_info(sa, "FW subvariant set to %u", req_fw_subvariant);
385
386         return 0;
387 }
388
389 static int
390 sfc_try_start(struct sfc_adapter *sa)
391 {
392         const efx_nic_cfg_t *encp;
393         int rc;
394
395         sfc_log_init(sa, "entry");
396
397         SFC_ASSERT(sfc_adapter_is_locked(sa));
398         SFC_ASSERT(sa->state == SFC_ADAPTER_STARTING);
399
400         sfc_log_init(sa, "set FW subvariant");
401         rc = sfc_set_fw_subvariant(sa);
402         if (rc != 0)
403                 goto fail_set_fw_subvariant;
404
405         sfc_log_init(sa, "set resource limits");
406         rc = sfc_set_drv_limits(sa);
407         if (rc != 0)
408                 goto fail_set_drv_limits;
409
410         sfc_log_init(sa, "init nic");
411         rc = efx_nic_init(sa->nic);
412         if (rc != 0)
413                 goto fail_nic_init;
414
415         encp = efx_nic_cfg_get(sa->nic);
416
417         /*
418          * Refresh (since it may change on NIC reset/restart) a copy of
419          * supported tunnel encapsulations in shared memory to be used
420          * on supported Rx packet type classes get.
421          */
422         sa->priv.shared->tunnel_encaps =
423                 encp->enc_tunnel_encapsulations_supported;
424
425         if (encp->enc_tunnel_encapsulations_supported != 0) {
426                 sfc_log_init(sa, "apply tunnel config");
427                 rc = efx_tunnel_reconfigure(sa->nic);
428                 if (rc != 0)
429                         goto fail_tunnel_reconfigure;
430         }
431
432         rc = sfc_intr_start(sa);
433         if (rc != 0)
434                 goto fail_intr_start;
435
436         rc = sfc_ev_start(sa);
437         if (rc != 0)
438                 goto fail_ev_start;
439
440         rc = sfc_port_start(sa);
441         if (rc != 0)
442                 goto fail_port_start;
443
444         rc = sfc_rx_start(sa);
445         if (rc != 0)
446                 goto fail_rx_start;
447
448         rc = sfc_tx_start(sa);
449         if (rc != 0)
450                 goto fail_tx_start;
451
452         rc = sfc_flow_start(sa);
453         if (rc != 0)
454                 goto fail_flows_insert;
455
456         rc = sfc_repr_proxy_start(sa);
457         if (rc != 0)
458                 goto fail_repr_proxy_start;
459
460         sfc_log_init(sa, "done");
461         return 0;
462
463 fail_repr_proxy_start:
464         sfc_flow_stop(sa);
465
466 fail_flows_insert:
467         sfc_tx_stop(sa);
468
469 fail_tx_start:
470         sfc_rx_stop(sa);
471
472 fail_rx_start:
473         sfc_port_stop(sa);
474
475 fail_port_start:
476         sfc_ev_stop(sa);
477
478 fail_ev_start:
479         sfc_intr_stop(sa);
480
481 fail_intr_start:
482 fail_tunnel_reconfigure:
483         efx_nic_fini(sa->nic);
484
485 fail_nic_init:
486 fail_set_drv_limits:
487 fail_set_fw_subvariant:
488         sfc_log_init(sa, "failed %d", rc);
489         return rc;
490 }
491
492 int
493 sfc_start(struct sfc_adapter *sa)
494 {
495         unsigned int start_tries = 3;
496         int rc;
497
498         sfc_log_init(sa, "entry");
499
500         SFC_ASSERT(sfc_adapter_is_locked(sa));
501
502         switch (sa->state) {
503         case SFC_ADAPTER_CONFIGURED:
504                 break;
505         case SFC_ADAPTER_STARTED:
506                 sfc_notice(sa, "already started");
507                 return 0;
508         default:
509                 rc = EINVAL;
510                 goto fail_bad_state;
511         }
512
513         sa->state = SFC_ADAPTER_STARTING;
514
515         rc = 0;
516         do {
517                 /*
518                  * FIXME Try to recreate vSwitch on start retry.
519                  * vSwitch is absent after MC reboot like events and
520                  * we should recreate it. May be we need proper
521                  * indication instead of guessing.
522                  */
523                 if (rc != 0) {
524                         sfc_sriov_vswitch_destroy(sa);
525                         rc = sfc_sriov_vswitch_create(sa);
526                         if (rc != 0)
527                                 goto fail_sriov_vswitch_create;
528                 }
529                 rc = sfc_try_start(sa);
530         } while ((--start_tries > 0) &&
531                  (rc == EIO || rc == EAGAIN || rc == ENOENT || rc == EINVAL));
532
533         if (rc != 0)
534                 goto fail_try_start;
535
536         sa->state = SFC_ADAPTER_STARTED;
537         sfc_log_init(sa, "done");
538         return 0;
539
540 fail_try_start:
541 fail_sriov_vswitch_create:
542         sa->state = SFC_ADAPTER_CONFIGURED;
543 fail_bad_state:
544         sfc_log_init(sa, "failed %d", rc);
545         return rc;
546 }
547
548 void
549 sfc_stop(struct sfc_adapter *sa)
550 {
551         sfc_log_init(sa, "entry");
552
553         SFC_ASSERT(sfc_adapter_is_locked(sa));
554
555         switch (sa->state) {
556         case SFC_ADAPTER_STARTED:
557                 break;
558         case SFC_ADAPTER_CONFIGURED:
559                 sfc_notice(sa, "already stopped");
560                 return;
561         default:
562                 sfc_err(sa, "stop in unexpected state %u", sa->state);
563                 SFC_ASSERT(B_FALSE);
564                 return;
565         }
566
567         sa->state = SFC_ADAPTER_STOPPING;
568
569         sfc_repr_proxy_stop(sa);
570         sfc_flow_stop(sa);
571         sfc_tx_stop(sa);
572         sfc_rx_stop(sa);
573         sfc_port_stop(sa);
574         sfc_ev_stop(sa);
575         sfc_intr_stop(sa);
576         efx_nic_fini(sa->nic);
577
578         sa->state = SFC_ADAPTER_CONFIGURED;
579         sfc_log_init(sa, "done");
580 }
581
582 static int
583 sfc_restart(struct sfc_adapter *sa)
584 {
585         int rc;
586
587         SFC_ASSERT(sfc_adapter_is_locked(sa));
588
589         if (sa->state != SFC_ADAPTER_STARTED)
590                 return EINVAL;
591
592         sfc_stop(sa);
593
594         rc = sfc_start(sa);
595         if (rc != 0)
596                 sfc_err(sa, "restart failed");
597
598         return rc;
599 }
600
601 static void
602 sfc_restart_if_required(void *arg)
603 {
604         struct sfc_adapter *sa = arg;
605
606         /* If restart is scheduled, clear the flag and do it */
607         if (rte_atomic32_cmpset((volatile uint32_t *)&sa->restart_required,
608                                 1, 0)) {
609                 sfc_adapter_lock(sa);
610                 if (sa->state == SFC_ADAPTER_STARTED)
611                         (void)sfc_restart(sa);
612                 sfc_adapter_unlock(sa);
613         }
614 }
615
616 void
617 sfc_schedule_restart(struct sfc_adapter *sa)
618 {
619         int rc;
620
621         /* Schedule restart alarm if it is not scheduled yet */
622         if (!rte_atomic32_test_and_set(&sa->restart_required))
623                 return;
624
625         rc = rte_eal_alarm_set(1, sfc_restart_if_required, sa);
626         if (rc == -ENOTSUP)
627                 sfc_warn(sa, "alarms are not supported, restart is pending");
628         else if (rc != 0)
629                 sfc_err(sa, "cannot arm restart alarm (rc=%d)", rc);
630         else
631                 sfc_notice(sa, "restart scheduled");
632 }
633
634 int
635 sfc_configure(struct sfc_adapter *sa)
636 {
637         int rc;
638
639         sfc_log_init(sa, "entry");
640
641         SFC_ASSERT(sfc_adapter_is_locked(sa));
642
643         SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED ||
644                    sa->state == SFC_ADAPTER_CONFIGURED);
645         sa->state = SFC_ADAPTER_CONFIGURING;
646
647         rc = sfc_check_conf(sa);
648         if (rc != 0)
649                 goto fail_check_conf;
650
651         rc = sfc_intr_configure(sa);
652         if (rc != 0)
653                 goto fail_intr_configure;
654
655         rc = sfc_port_configure(sa);
656         if (rc != 0)
657                 goto fail_port_configure;
658
659         rc = sfc_rx_configure(sa);
660         if (rc != 0)
661                 goto fail_rx_configure;
662
663         rc = sfc_tx_configure(sa);
664         if (rc != 0)
665                 goto fail_tx_configure;
666
667         rc = sfc_sw_xstats_configure(sa);
668         if (rc != 0)
669                 goto fail_sw_xstats_configure;
670
671         sa->state = SFC_ADAPTER_CONFIGURED;
672         sfc_log_init(sa, "done");
673         return 0;
674
675 fail_sw_xstats_configure:
676         sfc_tx_close(sa);
677
678 fail_tx_configure:
679         sfc_rx_close(sa);
680
681 fail_rx_configure:
682         sfc_port_close(sa);
683
684 fail_port_configure:
685         sfc_intr_close(sa);
686
687 fail_intr_configure:
688 fail_check_conf:
689         sa->state = SFC_ADAPTER_INITIALIZED;
690         sfc_log_init(sa, "failed %d", rc);
691         return rc;
692 }
693
694 void
695 sfc_close(struct sfc_adapter *sa)
696 {
697         sfc_log_init(sa, "entry");
698
699         SFC_ASSERT(sfc_adapter_is_locked(sa));
700
701         SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED);
702         sa->state = SFC_ADAPTER_CLOSING;
703
704         sfc_sw_xstats_close(sa);
705         sfc_tx_close(sa);
706         sfc_rx_close(sa);
707         sfc_port_close(sa);
708         sfc_intr_close(sa);
709
710         sa->state = SFC_ADAPTER_INITIALIZED;
711         sfc_log_init(sa, "done");
712 }
713
714 static int
715 sfc_mem_bar_init(struct sfc_adapter *sa, const efx_bar_region_t *mem_ebrp)
716 {
717         struct rte_eth_dev *eth_dev = sa->eth_dev;
718         struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
719         efsys_bar_t *ebp = &sa->mem_bar;
720         struct rte_mem_resource *res =
721                 &pci_dev->mem_resource[mem_ebrp->ebr_index];
722
723         SFC_BAR_LOCK_INIT(ebp, eth_dev->data->name);
724         ebp->esb_rid = mem_ebrp->ebr_index;
725         ebp->esb_dev = pci_dev;
726         ebp->esb_base = res->addr;
727
728         sa->fcw_offset = mem_ebrp->ebr_offset;
729
730         return 0;
731 }
732
733 static void
734 sfc_mem_bar_fini(struct sfc_adapter *sa)
735 {
736         efsys_bar_t *ebp = &sa->mem_bar;
737
738         SFC_BAR_LOCK_DESTROY(ebp);
739         memset(ebp, 0, sizeof(*ebp));
740 }
741
742 /*
743  * A fixed RSS key which has a property of being symmetric
744  * (symmetrical flows are distributed to the same CPU)
745  * and also known to give a uniform distribution
746  * (a good distribution of traffic between different CPUs)
747  */
748 static const uint8_t default_rss_key[EFX_RSS_KEY_SIZE] = {
749         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
750         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
751         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
752         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
753         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
754 };
755
756 static int
757 sfc_rss_attach(struct sfc_adapter *sa)
758 {
759         struct sfc_rss *rss = &sfc_sa2shared(sa)->rss;
760         int rc;
761
762         rc = efx_intr_init(sa->nic, sa->intr.type, NULL);
763         if (rc != 0)
764                 goto fail_intr_init;
765
766         rc = efx_ev_init(sa->nic);
767         if (rc != 0)
768                 goto fail_ev_init;
769
770         rc = efx_rx_init(sa->nic);
771         if (rc != 0)
772                 goto fail_rx_init;
773
774         rc = efx_rx_scale_default_support_get(sa->nic, &rss->context_type);
775         if (rc != 0)
776                 goto fail_scale_support_get;
777
778         rc = efx_rx_hash_default_support_get(sa->nic, &rss->hash_support);
779         if (rc != 0)
780                 goto fail_hash_support_get;
781
782         rc = sfc_rx_hash_init(sa);
783         if (rc != 0)
784                 goto fail_rx_hash_init;
785
786         efx_rx_fini(sa->nic);
787         efx_ev_fini(sa->nic);
788         efx_intr_fini(sa->nic);
789
790         rte_memcpy(rss->key, default_rss_key, sizeof(rss->key));
791         rss->dummy_rss_context = EFX_RSS_CONTEXT_DEFAULT;
792
793         return 0;
794
795 fail_rx_hash_init:
796 fail_hash_support_get:
797 fail_scale_support_get:
798         efx_rx_fini(sa->nic);
799
800 fail_rx_init:
801         efx_ev_fini(sa->nic);
802
803 fail_ev_init:
804         efx_intr_fini(sa->nic);
805
806 fail_intr_init:
807         return rc;
808 }
809
810 static void
811 sfc_rss_detach(struct sfc_adapter *sa)
812 {
813         sfc_rx_hash_fini(sa);
814 }
815
816 int
817 sfc_attach(struct sfc_adapter *sa)
818 {
819         const efx_nic_cfg_t *encp;
820         efx_nic_t *enp = sa->nic;
821         int rc;
822
823         sfc_log_init(sa, "entry");
824
825         SFC_ASSERT(sfc_adapter_is_locked(sa));
826
827         efx_mcdi_new_epoch(enp);
828
829         sfc_log_init(sa, "reset nic");
830         rc = efx_nic_reset(enp);
831         if (rc != 0)
832                 goto fail_nic_reset;
833
834         rc = sfc_sriov_attach(sa);
835         if (rc != 0)
836                 goto fail_sriov_attach;
837
838         /*
839          * Probed NIC is sufficient for tunnel init.
840          * Initialize tunnel support to be able to use libefx
841          * efx_tunnel_config_udp_{add,remove}() in any state and
842          * efx_tunnel_reconfigure() on start up.
843          */
844         rc = efx_tunnel_init(enp);
845         if (rc != 0)
846                 goto fail_tunnel_init;
847
848         encp = efx_nic_cfg_get(sa->nic);
849
850         /*
851          * Make a copy of supported tunnel encapsulations in shared
852          * memory to be used on supported Rx packet type classes get.
853          */
854         sa->priv.shared->tunnel_encaps =
855                 encp->enc_tunnel_encapsulations_supported;
856
857         if (sfc_dp_tx_offload_capa(sa->priv.dp_tx) & DEV_TX_OFFLOAD_TCP_TSO) {
858                 sa->tso = encp->enc_fw_assisted_tso_v2_enabled ||
859                           encp->enc_tso_v3_enabled;
860                 if (!sa->tso)
861                         sfc_info(sa, "TSO support isn't available on this adapter");
862         }
863
864         if (sa->tso &&
865             (sfc_dp_tx_offload_capa(sa->priv.dp_tx) &
866              (DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
867               DEV_TX_OFFLOAD_GENEVE_TNL_TSO)) != 0) {
868                 sa->tso_encap = encp->enc_fw_assisted_tso_v2_encap_enabled ||
869                                 encp->enc_tso_v3_enabled;
870                 if (!sa->tso_encap)
871                         sfc_info(sa, "Encapsulated TSO support isn't available on this adapter");
872         }
873
874         sfc_log_init(sa, "estimate resource limits");
875         rc = sfc_estimate_resource_limits(sa);
876         if (rc != 0)
877                 goto fail_estimate_rsrc_limits;
878
879         sa->evq_max_entries = encp->enc_evq_max_nevs;
880         SFC_ASSERT(rte_is_power_of_2(sa->evq_max_entries));
881
882         sa->evq_min_entries = encp->enc_evq_min_nevs;
883         SFC_ASSERT(rte_is_power_of_2(sa->evq_min_entries));
884
885         sa->rxq_max_entries = encp->enc_rxq_max_ndescs;
886         SFC_ASSERT(rte_is_power_of_2(sa->rxq_max_entries));
887
888         sa->rxq_min_entries = encp->enc_rxq_min_ndescs;
889         SFC_ASSERT(rte_is_power_of_2(sa->rxq_min_entries));
890
891         sa->txq_max_entries = encp->enc_txq_max_ndescs;
892         SFC_ASSERT(rte_is_power_of_2(sa->txq_max_entries));
893
894         sa->txq_min_entries = encp->enc_txq_min_ndescs;
895         SFC_ASSERT(rte_is_power_of_2(sa->txq_min_entries));
896
897         rc = sfc_intr_attach(sa);
898         if (rc != 0)
899                 goto fail_intr_attach;
900
901         rc = sfc_ev_attach(sa);
902         if (rc != 0)
903                 goto fail_ev_attach;
904
905         rc = sfc_port_attach(sa);
906         if (rc != 0)
907                 goto fail_port_attach;
908
909         rc = sfc_rss_attach(sa);
910         if (rc != 0)
911                 goto fail_rss_attach;
912
913         rc = sfc_filter_attach(sa);
914         if (rc != 0)
915                 goto fail_filter_attach;
916
917         rc = sfc_mae_counter_rxq_attach(sa);
918         if (rc != 0)
919                 goto fail_mae_counter_rxq_attach;
920
921         rc = sfc_mae_attach(sa);
922         if (rc != 0)
923                 goto fail_mae_attach;
924
925         rc = sfc_mae_switchdev_init(sa);
926         if (rc != 0)
927                 goto fail_mae_switchdev_init;
928
929         rc = sfc_repr_proxy_attach(sa);
930         if (rc != 0)
931                 goto fail_repr_proxy_attach;
932
933         sfc_log_init(sa, "fini nic");
934         efx_nic_fini(enp);
935
936         sfc_flow_init(sa);
937
938         rc = sfc_sw_xstats_init(sa);
939         if (rc != 0)
940                 goto fail_sw_xstats_init;
941
942         /*
943          * Create vSwitch to be able to use VFs when PF is not started yet
944          * as DPDK port. VFs should be able to talk to each other even
945          * if PF is down.
946          */
947         rc = sfc_sriov_vswitch_create(sa);
948         if (rc != 0)
949                 goto fail_sriov_vswitch_create;
950
951         sa->state = SFC_ADAPTER_INITIALIZED;
952
953         sfc_log_init(sa, "done");
954         return 0;
955
956 fail_sriov_vswitch_create:
957         sfc_sw_xstats_close(sa);
958
959 fail_sw_xstats_init:
960         sfc_flow_fini(sa);
961         sfc_repr_proxy_detach(sa);
962
963 fail_repr_proxy_attach:
964         sfc_mae_switchdev_fini(sa);
965
966 fail_mae_switchdev_init:
967         sfc_mae_detach(sa);
968
969 fail_mae_attach:
970         sfc_mae_counter_rxq_detach(sa);
971
972 fail_mae_counter_rxq_attach:
973         sfc_filter_detach(sa);
974
975 fail_filter_attach:
976         sfc_rss_detach(sa);
977
978 fail_rss_attach:
979         sfc_port_detach(sa);
980
981 fail_port_attach:
982         sfc_ev_detach(sa);
983
984 fail_ev_attach:
985         sfc_intr_detach(sa);
986
987 fail_intr_attach:
988         efx_nic_fini(sa->nic);
989
990 fail_estimate_rsrc_limits:
991 fail_tunnel_init:
992         efx_tunnel_fini(sa->nic);
993         sfc_sriov_detach(sa);
994
995 fail_sriov_attach:
996 fail_nic_reset:
997
998         sfc_log_init(sa, "failed %d", rc);
999         return rc;
1000 }
1001
1002 void
1003 sfc_detach(struct sfc_adapter *sa)
1004 {
1005         sfc_log_init(sa, "entry");
1006
1007         SFC_ASSERT(sfc_adapter_is_locked(sa));
1008
1009         sfc_sriov_vswitch_destroy(sa);
1010
1011         sfc_flow_fini(sa);
1012
1013         sfc_repr_proxy_detach(sa);
1014         sfc_mae_switchdev_fini(sa);
1015         sfc_mae_detach(sa);
1016         sfc_mae_counter_rxq_detach(sa);
1017         sfc_filter_detach(sa);
1018         sfc_rss_detach(sa);
1019         sfc_port_detach(sa);
1020         sfc_ev_detach(sa);
1021         sfc_intr_detach(sa);
1022         efx_tunnel_fini(sa->nic);
1023         sfc_sriov_detach(sa);
1024
1025         sa->state = SFC_ADAPTER_UNINITIALIZED;
1026 }
1027
1028 static int
1029 sfc_kvarg_fv_variant_handler(__rte_unused const char *key,
1030                              const char *value_str, void *opaque)
1031 {
1032         uint32_t *value = opaque;
1033
1034         if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_DONT_CARE) == 0)
1035                 *value = EFX_FW_VARIANT_DONT_CARE;
1036         else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_FULL_FEATURED) == 0)
1037                 *value = EFX_FW_VARIANT_FULL_FEATURED;
1038         else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_LOW_LATENCY) == 0)
1039                 *value = EFX_FW_VARIANT_LOW_LATENCY;
1040         else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_PACKED_STREAM) == 0)
1041                 *value = EFX_FW_VARIANT_PACKED_STREAM;
1042         else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_DPDK) == 0)
1043                 *value = EFX_FW_VARIANT_DPDK;
1044         else
1045                 return -EINVAL;
1046
1047         return 0;
1048 }
1049
1050 static int
1051 sfc_get_fw_variant(struct sfc_adapter *sa, efx_fw_variant_t *efv)
1052 {
1053         efx_nic_fw_info_t enfi;
1054         int rc;
1055
1056         rc = efx_nic_get_fw_version(sa->nic, &enfi);
1057         if (rc != 0)
1058                 return rc;
1059         else if (!enfi.enfi_dpcpu_fw_ids_valid)
1060                 return ENOTSUP;
1061
1062         /*
1063          * Firmware variant can be uniquely identified by the RxDPCPU
1064          * firmware id
1065          */
1066         switch (enfi.enfi_rx_dpcpu_fw_id) {
1067         case EFX_RXDP_FULL_FEATURED_FW_ID:
1068                 *efv = EFX_FW_VARIANT_FULL_FEATURED;
1069                 break;
1070
1071         case EFX_RXDP_LOW_LATENCY_FW_ID:
1072                 *efv = EFX_FW_VARIANT_LOW_LATENCY;
1073                 break;
1074
1075         case EFX_RXDP_PACKED_STREAM_FW_ID:
1076                 *efv = EFX_FW_VARIANT_PACKED_STREAM;
1077                 break;
1078
1079         case EFX_RXDP_DPDK_FW_ID:
1080                 *efv = EFX_FW_VARIANT_DPDK;
1081                 break;
1082
1083         default:
1084                 /*
1085                  * Other firmware variants are not considered, since they are
1086                  * not supported in the device parameters
1087                  */
1088                 *efv = EFX_FW_VARIANT_DONT_CARE;
1089                 break;
1090         }
1091
1092         return 0;
1093 }
1094
1095 static const char *
1096 sfc_fw_variant2str(efx_fw_variant_t efv)
1097 {
1098         switch (efv) {
1099         case EFX_RXDP_FULL_FEATURED_FW_ID:
1100                 return SFC_KVARG_FW_VARIANT_FULL_FEATURED;
1101         case EFX_RXDP_LOW_LATENCY_FW_ID:
1102                 return SFC_KVARG_FW_VARIANT_LOW_LATENCY;
1103         case EFX_RXDP_PACKED_STREAM_FW_ID:
1104                 return SFC_KVARG_FW_VARIANT_PACKED_STREAM;
1105         case EFX_RXDP_DPDK_FW_ID:
1106                 return SFC_KVARG_FW_VARIANT_DPDK;
1107         default:
1108                 return "unknown";
1109         }
1110 }
1111
1112 static int
1113 sfc_kvarg_rxd_wait_timeout_ns(struct sfc_adapter *sa)
1114 {
1115         int rc;
1116         long value;
1117
1118         value = SFC_RXD_WAIT_TIMEOUT_NS_DEF;
1119
1120         rc = sfc_kvargs_process(sa, SFC_KVARG_RXD_WAIT_TIMEOUT_NS,
1121                                 sfc_kvarg_long_handler, &value);
1122         if (rc != 0)
1123                 return rc;
1124
1125         if (value < 0 ||
1126             (unsigned long)value > EFX_RXQ_ES_SUPER_BUFFER_HOL_BLOCK_MAX) {
1127                 sfc_err(sa, "wrong '" SFC_KVARG_RXD_WAIT_TIMEOUT_NS "' "
1128                             "was set (%ld);", value);
1129                 sfc_err(sa, "it must not be less than 0 or greater than %u",
1130                             EFX_RXQ_ES_SUPER_BUFFER_HOL_BLOCK_MAX);
1131                 return EINVAL;
1132         }
1133
1134         sa->rxd_wait_timeout_ns = value;
1135         return 0;
1136 }
1137
1138 static int
1139 sfc_nic_probe(struct sfc_adapter *sa)
1140 {
1141         efx_nic_t *enp = sa->nic;
1142         efx_fw_variant_t preferred_efv;
1143         efx_fw_variant_t efv;
1144         int rc;
1145
1146         preferred_efv = EFX_FW_VARIANT_DONT_CARE;
1147         rc = sfc_kvargs_process(sa, SFC_KVARG_FW_VARIANT,
1148                                 sfc_kvarg_fv_variant_handler,
1149                                 &preferred_efv);
1150         if (rc != 0) {
1151                 sfc_err(sa, "invalid %s parameter value", SFC_KVARG_FW_VARIANT);
1152                 return rc;
1153         }
1154
1155         rc = sfc_kvarg_rxd_wait_timeout_ns(sa);
1156         if (rc != 0)
1157                 return rc;
1158
1159         rc = efx_nic_probe(enp, preferred_efv);
1160         if (rc == EACCES) {
1161                 /* Unprivileged functions cannot set FW variant */
1162                 rc = efx_nic_probe(enp, EFX_FW_VARIANT_DONT_CARE);
1163         }
1164         if (rc != 0)
1165                 return rc;
1166
1167         rc = sfc_get_fw_variant(sa, &efv);
1168         if (rc == ENOTSUP) {
1169                 sfc_warn(sa, "FW variant can not be obtained");
1170                 return 0;
1171         }
1172         if (rc != 0)
1173                 return rc;
1174
1175         /* Check that firmware variant was changed to the requested one */
1176         if (preferred_efv != EFX_FW_VARIANT_DONT_CARE && preferred_efv != efv) {
1177                 sfc_warn(sa, "FW variant has not changed to the requested %s",
1178                          sfc_fw_variant2str(preferred_efv));
1179         }
1180
1181         sfc_notice(sa, "running FW variant is %s", sfc_fw_variant2str(efv));
1182
1183         return 0;
1184 }
1185
1186 int
1187 sfc_probe(struct sfc_adapter *sa)
1188 {
1189         efx_bar_region_t mem_ebrp;
1190         struct rte_eth_dev *eth_dev = sa->eth_dev;
1191         struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
1192         efx_nic_t *enp;
1193         int rc;
1194
1195         sfc_log_init(sa, "entry");
1196
1197         SFC_ASSERT(sfc_adapter_is_locked(sa));
1198
1199         sa->socket_id = rte_socket_id();
1200         rte_atomic32_init(&sa->restart_required);
1201
1202         sfc_log_init(sa, "get family");
1203         rc = sfc_efx_family(pci_dev, &mem_ebrp, &sa->family);
1204
1205         if (rc != 0)
1206                 goto fail_family;
1207         sfc_log_init(sa,
1208                      "family is %u, membar is %u, function control window offset is %lu",
1209                      sa->family, mem_ebrp.ebr_index, mem_ebrp.ebr_offset);
1210
1211         sfc_log_init(sa, "init mem bar");
1212         rc = sfc_mem_bar_init(sa, &mem_ebrp);
1213         if (rc != 0)
1214                 goto fail_mem_bar_init;
1215
1216         sfc_log_init(sa, "create nic");
1217         rte_spinlock_init(&sa->nic_lock);
1218         rc = efx_nic_create(sa->family, (efsys_identifier_t *)sa,
1219                             &sa->mem_bar, mem_ebrp.ebr_offset,
1220                             &sa->nic_lock, &enp);
1221         if (rc != 0)
1222                 goto fail_nic_create;
1223         sa->nic = enp;
1224
1225         rc = sfc_mcdi_init(sa);
1226         if (rc != 0)
1227                 goto fail_mcdi_init;
1228
1229         sfc_log_init(sa, "probe nic");
1230         rc = sfc_nic_probe(sa);
1231         if (rc != 0)
1232                 goto fail_nic_probe;
1233
1234         sfc_log_init(sa, "done");
1235         return 0;
1236
1237 fail_nic_probe:
1238         sfc_mcdi_fini(sa);
1239
1240 fail_mcdi_init:
1241         sfc_log_init(sa, "destroy nic");
1242         sa->nic = NULL;
1243         efx_nic_destroy(enp);
1244
1245 fail_nic_create:
1246         sfc_mem_bar_fini(sa);
1247
1248 fail_mem_bar_init:
1249 fail_family:
1250         sfc_log_init(sa, "failed %d", rc);
1251         return rc;
1252 }
1253
1254 void
1255 sfc_unprobe(struct sfc_adapter *sa)
1256 {
1257         efx_nic_t *enp = sa->nic;
1258
1259         sfc_log_init(sa, "entry");
1260
1261         SFC_ASSERT(sfc_adapter_is_locked(sa));
1262
1263         sfc_log_init(sa, "unprobe nic");
1264         efx_nic_unprobe(enp);
1265
1266         sfc_mcdi_fini(sa);
1267
1268         /*
1269          * Make sure there is no pending alarm to restart since we are
1270          * going to free device private which is passed as the callback
1271          * opaque data. A new alarm cannot be scheduled since MCDI is
1272          * shut down.
1273          */
1274         rte_eal_alarm_cancel(sfc_restart_if_required, sa);
1275
1276         sfc_log_init(sa, "destroy nic");
1277         sa->nic = NULL;
1278         efx_nic_destroy(enp);
1279
1280         sfc_mem_bar_fini(sa);
1281
1282         sfc_flow_fini(sa);
1283         sa->state = SFC_ADAPTER_UNINITIALIZED;
1284 }
1285
1286 uint32_t
1287 sfc_register_logtype(const struct rte_pci_addr *pci_addr,
1288                      const char *lt_prefix_str, uint32_t ll_default)
1289 {
1290         size_t lt_prefix_str_size = strlen(lt_prefix_str);
1291         size_t lt_str_size_max;
1292         char *lt_str = NULL;
1293         int ret;
1294
1295         if (SIZE_MAX - PCI_PRI_STR_SIZE - 1 > lt_prefix_str_size) {
1296                 ++lt_prefix_str_size; /* Reserve space for prefix separator */
1297                 lt_str_size_max = lt_prefix_str_size + PCI_PRI_STR_SIZE + 1;
1298         } else {
1299                 return sfc_logtype_driver;
1300         }
1301
1302         lt_str = rte_zmalloc("logtype_str", lt_str_size_max, 0);
1303         if (lt_str == NULL)
1304                 return sfc_logtype_driver;
1305
1306         strncpy(lt_str, lt_prefix_str, lt_prefix_str_size);
1307         lt_str[lt_prefix_str_size - 1] = '.';
1308         rte_pci_device_name(pci_addr, lt_str + lt_prefix_str_size,
1309                             lt_str_size_max - lt_prefix_str_size);
1310         lt_str[lt_str_size_max - 1] = '\0';
1311
1312         ret = rte_log_register_type_and_pick_level(lt_str, ll_default);
1313         rte_free(lt_str);
1314
1315         if (ret < 0)
1316                 return sfc_logtype_driver;
1317
1318         return ret;
1319 }
1320
1321 struct sfc_hw_switch_id {
1322         char    board_sn[RTE_SIZEOF_FIELD(efx_nic_board_info_t, enbi_serial)];
1323 };
1324
1325 int
1326 sfc_hw_switch_id_init(struct sfc_adapter *sa,
1327                       struct sfc_hw_switch_id **idp)
1328 {
1329         efx_nic_board_info_t board_info;
1330         struct sfc_hw_switch_id *id;
1331         int rc;
1332
1333         if (idp == NULL)
1334                 return EINVAL;
1335
1336         id = rte_zmalloc("sfc_hw_switch_id", sizeof(*id), 0);
1337         if (id == NULL)
1338                 return ENOMEM;
1339
1340         rc = efx_nic_get_board_info(sa->nic, &board_info);
1341         if (rc != 0)
1342                 return rc;
1343
1344         memcpy(id->board_sn, board_info.enbi_serial, sizeof(id->board_sn));
1345
1346         *idp = id;
1347
1348         return 0;
1349 }
1350
1351 void
1352 sfc_hw_switch_id_fini(__rte_unused struct sfc_adapter *sa,
1353                       struct sfc_hw_switch_id *id)
1354 {
1355         rte_free(id);
1356 }
1357
1358 bool
1359 sfc_hw_switch_ids_equal(const struct sfc_hw_switch_id *left,
1360                         const struct sfc_hw_switch_id *right)
1361 {
1362         return strncmp(left->board_sn, right->board_sn,
1363                        sizeof(left->board_sn)) == 0;
1364 }