net/sfc: provide a way to check if filter is supported
[dpdk.git] / drivers / net / sfc / sfc.c
1 /*-
2  * Copyright (c) 2016 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * This software was jointly developed between OKTET Labs (under contract
6  * for Solarflare) and Solarflare Communications, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 /* sysconf() */
31 #include <unistd.h>
32
33 #include <rte_errno.h>
34
35 #include "efx.h"
36
37 #include "sfc.h"
38 #include "sfc_log.h"
39 #include "sfc_ev.h"
40 #include "sfc_rx.h"
41 #include "sfc_tx.h"
42
43
44 int
45 sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id,
46               size_t len, int socket_id, efsys_mem_t *esmp)
47 {
48         const struct rte_memzone *mz;
49
50         sfc_log_init(sa, "name=%s id=%u len=%lu socket_id=%d",
51                      name, id, len, socket_id);
52
53         mz = rte_eth_dma_zone_reserve(sa->eth_dev, name, id, len,
54                                       sysconf(_SC_PAGESIZE), socket_id);
55         if (mz == NULL) {
56                 sfc_err(sa, "cannot reserve DMA zone for %s:%u %#x@%d: %s",
57                         name, (unsigned int)id, (unsigned int)len, socket_id,
58                         rte_strerror(rte_errno));
59                 return ENOMEM;
60         }
61
62         esmp->esm_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
63         if (esmp->esm_addr == RTE_BAD_PHYS_ADDR) {
64                 (void)rte_memzone_free(mz);
65                 return EFAULT;
66         }
67
68         esmp->esm_mz = mz;
69         esmp->esm_base = mz->addr;
70
71         return 0;
72 }
73
74 void
75 sfc_dma_free(const struct sfc_adapter *sa, efsys_mem_t *esmp)
76 {
77         int rc;
78
79         sfc_log_init(sa, "name=%s", esmp->esm_mz->name);
80
81         rc = rte_memzone_free(esmp->esm_mz);
82         if (rc != 0)
83                 sfc_err(sa, "rte_memzone_free(() failed: %d", rc);
84
85         memset(esmp, 0, sizeof(*esmp));
86 }
87
88 static uint32_t
89 sfc_phy_cap_from_link_speeds(uint32_t speeds)
90 {
91         uint32_t phy_caps = 0;
92
93         if (~speeds & ETH_LINK_SPEED_FIXED) {
94                 phy_caps |= (1 << EFX_PHY_CAP_AN);
95                 /*
96                  * If no speeds are specified in the mask, any supported
97                  * may be negotiated
98                  */
99                 if (speeds == ETH_LINK_SPEED_AUTONEG)
100                         phy_caps |=
101                                 (1 << EFX_PHY_CAP_1000FDX) |
102                                 (1 << EFX_PHY_CAP_10000FDX) |
103                                 (1 << EFX_PHY_CAP_40000FDX);
104         }
105         if (speeds & ETH_LINK_SPEED_1G)
106                 phy_caps |= (1 << EFX_PHY_CAP_1000FDX);
107         if (speeds & ETH_LINK_SPEED_10G)
108                 phy_caps |= (1 << EFX_PHY_CAP_10000FDX);
109         if (speeds & ETH_LINK_SPEED_40G)
110                 phy_caps |= (1 << EFX_PHY_CAP_40000FDX);
111
112         return phy_caps;
113 }
114
115 /*
116  * Check requested device level configuration.
117  * Receive and transmit configuration is checked in corresponding
118  * modules.
119  */
120 static int
121 sfc_check_conf(struct sfc_adapter *sa)
122 {
123         const struct rte_eth_conf *conf = &sa->eth_dev->data->dev_conf;
124         int rc = 0;
125
126         sa->port.phy_adv_cap =
127                 sfc_phy_cap_from_link_speeds(conf->link_speeds) &
128                 sa->port.phy_adv_cap_mask;
129         if ((sa->port.phy_adv_cap & ~(1 << EFX_PHY_CAP_AN)) == 0) {
130                 sfc_err(sa, "No link speeds from mask %#x are supported",
131                         conf->link_speeds);
132                 rc = EINVAL;
133         }
134
135         if (conf->lpbk_mode != 0) {
136                 sfc_err(sa, "Loopback not supported");
137                 rc = EINVAL;
138         }
139
140         if (conf->dcb_capability_en != 0) {
141                 sfc_err(sa, "Priority-based flow control not supported");
142                 rc = EINVAL;
143         }
144
145         if (conf->fdir_conf.mode != RTE_FDIR_MODE_NONE) {
146                 sfc_err(sa, "Flow Director not supported");
147                 rc = EINVAL;
148         }
149
150         if ((conf->intr_conf.lsc != 0) &&
151             (sa->intr.type != EFX_INTR_LINE) &&
152             (sa->intr.type != EFX_INTR_MESSAGE)) {
153                 sfc_err(sa, "Link status change interrupt not supported");
154                 rc = EINVAL;
155         }
156
157         if (conf->intr_conf.rxq != 0) {
158                 sfc_err(sa, "Receive queue interrupt not supported");
159                 rc = EINVAL;
160         }
161
162         return rc;
163 }
164
165 /*
166  * Find out maximum number of receive and transmit queues which could be
167  * advertised.
168  *
169  * NIC is kept initialized on success to allow other modules acquire
170  * defaults and capabilities.
171  */
172 static int
173 sfc_estimate_resource_limits(struct sfc_adapter *sa)
174 {
175         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
176         efx_drv_limits_t limits;
177         int rc;
178         uint32_t evq_allocated;
179         uint32_t rxq_allocated;
180         uint32_t txq_allocated;
181
182         memset(&limits, 0, sizeof(limits));
183
184         /* Request at least one Rx and Tx queue */
185         limits.edl_min_rxq_count = 1;
186         limits.edl_min_txq_count = 1;
187         /* Management event queue plus event queue for each Tx and Rx queue */
188         limits.edl_min_evq_count =
189                 1 + limits.edl_min_rxq_count + limits.edl_min_txq_count;
190
191         /* Divide by number of functions to guarantee that all functions
192          * will get promised resources
193          */
194         /* FIXME Divide by number of functions (not 2) below */
195         limits.edl_max_evq_count = encp->enc_evq_limit / 2;
196         SFC_ASSERT(limits.edl_max_evq_count >= limits.edl_min_rxq_count);
197
198         /* Split equally between receive and transmit */
199         limits.edl_max_rxq_count =
200                 MIN(encp->enc_rxq_limit, (limits.edl_max_evq_count - 1) / 2);
201         SFC_ASSERT(limits.edl_max_rxq_count >= limits.edl_min_rxq_count);
202
203         limits.edl_max_txq_count =
204                 MIN(encp->enc_txq_limit,
205                     limits.edl_max_evq_count - 1 - limits.edl_max_rxq_count);
206
207         if (sa->tso)
208                 limits.edl_max_txq_count =
209                         MIN(limits.edl_max_txq_count,
210                             encp->enc_fw_assisted_tso_v2_n_contexts /
211                             encp->enc_hw_pf_count);
212
213         SFC_ASSERT(limits.edl_max_txq_count >= limits.edl_min_rxq_count);
214
215         /* Configure the minimum required resources needed for the
216          * driver to operate, and the maximum desired resources that the
217          * driver is capable of using.
218          */
219         efx_nic_set_drv_limits(sa->nic, &limits);
220
221         sfc_log_init(sa, "init nic");
222         rc = efx_nic_init(sa->nic);
223         if (rc != 0)
224                 goto fail_nic_init;
225
226         /* Find resource dimensions assigned by firmware to this function */
227         rc = efx_nic_get_vi_pool(sa->nic, &evq_allocated, &rxq_allocated,
228                                  &txq_allocated);
229         if (rc != 0)
230                 goto fail_get_vi_pool;
231
232         /* It still may allocate more than maximum, ensure limit */
233         evq_allocated = MIN(evq_allocated, limits.edl_max_evq_count);
234         rxq_allocated = MIN(rxq_allocated, limits.edl_max_rxq_count);
235         txq_allocated = MIN(txq_allocated, limits.edl_max_txq_count);
236
237         /* Subtract management EVQ not used for traffic */
238         SFC_ASSERT(evq_allocated > 0);
239         evq_allocated--;
240
241         /* Right now we use separate EVQ for Rx and Tx */
242         sa->rxq_max = MIN(rxq_allocated, evq_allocated / 2);
243         sa->txq_max = MIN(txq_allocated, evq_allocated - sa->rxq_max);
244
245         /* Keep NIC initialized */
246         return 0;
247
248 fail_get_vi_pool:
249 fail_nic_init:
250         efx_nic_fini(sa->nic);
251         return rc;
252 }
253
254 static int
255 sfc_set_drv_limits(struct sfc_adapter *sa)
256 {
257         const struct rte_eth_dev_data *data = sa->eth_dev->data;
258         efx_drv_limits_t lim;
259
260         memset(&lim, 0, sizeof(lim));
261
262         /* Limits are strict since take into account initial estimation */
263         lim.edl_min_evq_count = lim.edl_max_evq_count =
264                 1 + data->nb_rx_queues + data->nb_tx_queues;
265         lim.edl_min_rxq_count = lim.edl_max_rxq_count = data->nb_rx_queues;
266         lim.edl_min_txq_count = lim.edl_max_txq_count = data->nb_tx_queues;
267
268         return efx_nic_set_drv_limits(sa->nic, &lim);
269 }
270
271 int
272 sfc_start(struct sfc_adapter *sa)
273 {
274         int rc;
275
276         sfc_log_init(sa, "entry");
277
278         SFC_ASSERT(sfc_adapter_is_locked(sa));
279
280         switch (sa->state) {
281         case SFC_ADAPTER_CONFIGURED:
282                 break;
283         case SFC_ADAPTER_STARTED:
284                 sfc_info(sa, "already started");
285                 return 0;
286         default:
287                 rc = EINVAL;
288                 goto fail_bad_state;
289         }
290
291         sa->state = SFC_ADAPTER_STARTING;
292
293         sfc_log_init(sa, "set resource limits");
294         rc = sfc_set_drv_limits(sa);
295         if (rc != 0)
296                 goto fail_set_drv_limits;
297
298         sfc_log_init(sa, "init nic");
299         rc = efx_nic_init(sa->nic);
300         if (rc != 0)
301                 goto fail_nic_init;
302
303         rc = sfc_intr_start(sa);
304         if (rc != 0)
305                 goto fail_intr_start;
306
307         rc = sfc_ev_start(sa);
308         if (rc != 0)
309                 goto fail_ev_start;
310
311         rc = sfc_port_start(sa);
312         if (rc != 0)
313                 goto fail_port_start;
314
315         rc = sfc_rx_start(sa);
316         if (rc != 0)
317                 goto fail_rx_start;
318
319         rc = sfc_tx_start(sa);
320         if (rc != 0)
321                 goto fail_tx_start;
322
323         sa->state = SFC_ADAPTER_STARTED;
324         sfc_log_init(sa, "done");
325         return 0;
326
327 fail_tx_start:
328         sfc_rx_stop(sa);
329
330 fail_rx_start:
331         sfc_port_stop(sa);
332
333 fail_port_start:
334         sfc_ev_stop(sa);
335
336 fail_ev_start:
337         sfc_intr_stop(sa);
338
339 fail_intr_start:
340         efx_nic_fini(sa->nic);
341
342 fail_nic_init:
343 fail_set_drv_limits:
344         sa->state = SFC_ADAPTER_CONFIGURED;
345 fail_bad_state:
346         sfc_log_init(sa, "failed %d", rc);
347         return rc;
348 }
349
350 void
351 sfc_stop(struct sfc_adapter *sa)
352 {
353         sfc_log_init(sa, "entry");
354
355         SFC_ASSERT(sfc_adapter_is_locked(sa));
356
357         switch (sa->state) {
358         case SFC_ADAPTER_STARTED:
359                 break;
360         case SFC_ADAPTER_CONFIGURED:
361                 sfc_info(sa, "already stopped");
362                 return;
363         default:
364                 sfc_err(sa, "stop in unexpected state %u", sa->state);
365                 SFC_ASSERT(B_FALSE);
366                 return;
367         }
368
369         sa->state = SFC_ADAPTER_STOPPING;
370
371         sfc_tx_stop(sa);
372         sfc_rx_stop(sa);
373         sfc_port_stop(sa);
374         sfc_ev_stop(sa);
375         sfc_intr_stop(sa);
376         efx_nic_fini(sa->nic);
377
378         sa->state = SFC_ADAPTER_CONFIGURED;
379         sfc_log_init(sa, "done");
380 }
381
382 int
383 sfc_configure(struct sfc_adapter *sa)
384 {
385         int rc;
386
387         sfc_log_init(sa, "entry");
388
389         SFC_ASSERT(sfc_adapter_is_locked(sa));
390
391         SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
392         sa->state = SFC_ADAPTER_CONFIGURING;
393
394         rc = sfc_check_conf(sa);
395         if (rc != 0)
396                 goto fail_check_conf;
397
398         rc = sfc_intr_init(sa);
399         if (rc != 0)
400                 goto fail_intr_init;
401
402         rc = sfc_ev_init(sa);
403         if (rc != 0)
404                 goto fail_ev_init;
405
406         rc = sfc_port_init(sa);
407         if (rc != 0)
408                 goto fail_port_init;
409
410         rc = sfc_rx_init(sa);
411         if (rc != 0)
412                 goto fail_rx_init;
413
414         rc = sfc_tx_init(sa);
415         if (rc != 0)
416                 goto fail_tx_init;
417
418         sa->state = SFC_ADAPTER_CONFIGURED;
419         sfc_log_init(sa, "done");
420         return 0;
421
422 fail_tx_init:
423         sfc_rx_fini(sa);
424
425 fail_rx_init:
426         sfc_port_fini(sa);
427
428 fail_port_init:
429         sfc_ev_fini(sa);
430
431 fail_ev_init:
432         sfc_intr_fini(sa);
433
434 fail_intr_init:
435 fail_check_conf:
436         sa->state = SFC_ADAPTER_INITIALIZED;
437         sfc_log_init(sa, "failed %d", rc);
438         return rc;
439 }
440
441 void
442 sfc_close(struct sfc_adapter *sa)
443 {
444         sfc_log_init(sa, "entry");
445
446         SFC_ASSERT(sfc_adapter_is_locked(sa));
447
448         SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED);
449         sa->state = SFC_ADAPTER_CLOSING;
450
451         sfc_tx_fini(sa);
452         sfc_rx_fini(sa);
453         sfc_port_fini(sa);
454         sfc_ev_fini(sa);
455         sfc_intr_fini(sa);
456
457         sa->state = SFC_ADAPTER_INITIALIZED;
458         sfc_log_init(sa, "done");
459 }
460
461 static int
462 sfc_mem_bar_init(struct sfc_adapter *sa)
463 {
464         struct rte_eth_dev *eth_dev = sa->eth_dev;
465         struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(eth_dev);
466         efsys_bar_t *ebp = &sa->mem_bar;
467         unsigned int i;
468         struct rte_mem_resource *res;
469
470         for (i = 0; i < RTE_DIM(pci_dev->mem_resource); i++) {
471                 res = &pci_dev->mem_resource[i];
472                 if ((res->len != 0) && (res->phys_addr != 0)) {
473                         /* Found first memory BAR */
474                         SFC_BAR_LOCK_INIT(ebp, eth_dev->data->name);
475                         ebp->esb_rid = i;
476                         ebp->esb_dev = pci_dev;
477                         ebp->esb_base = res->addr;
478                         return 0;
479                 }
480         }
481
482         return EFAULT;
483 }
484
485 static void
486 sfc_mem_bar_fini(struct sfc_adapter *sa)
487 {
488         efsys_bar_t *ebp = &sa->mem_bar;
489
490         SFC_BAR_LOCK_DESTROY(ebp);
491         memset(ebp, 0, sizeof(*ebp));
492 }
493
494 #if EFSYS_OPT_RX_SCALE
495 /*
496  * A fixed RSS key which has a property of being symmetric
497  * (symmetrical flows are distributed to the same CPU)
498  * and also known to give a uniform distribution
499  * (a good distribution of traffic between different CPUs)
500  */
501 static const uint8_t default_rss_key[SFC_RSS_KEY_SIZE] = {
502         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
503         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
504         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
505         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
506         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
507 };
508 #endif
509
510 static int
511 sfc_set_rss_defaults(struct sfc_adapter *sa)
512 {
513 #if EFSYS_OPT_RX_SCALE
514         int rc;
515
516         rc = efx_intr_init(sa->nic, sa->intr.type, NULL);
517         if (rc != 0)
518                 goto fail_intr_init;
519
520         rc = efx_ev_init(sa->nic);
521         if (rc != 0)
522                 goto fail_ev_init;
523
524         rc = efx_rx_init(sa->nic);
525         if (rc != 0)
526                 goto fail_rx_init;
527
528         rc = efx_rx_scale_support_get(sa->nic, &sa->rss_support);
529         if (rc != 0)
530                 goto fail_scale_support_get;
531
532         rc = efx_rx_hash_support_get(sa->nic, &sa->hash_support);
533         if (rc != 0)
534                 goto fail_hash_support_get;
535
536         efx_rx_fini(sa->nic);
537         efx_ev_fini(sa->nic);
538         efx_intr_fini(sa->nic);
539
540         sa->rss_hash_types = sfc_rte_to_efx_hash_type(SFC_RSS_OFFLOADS);
541
542         rte_memcpy(sa->rss_key, default_rss_key, sizeof(sa->rss_key));
543
544         return 0;
545
546 fail_hash_support_get:
547 fail_scale_support_get:
548 fail_rx_init:
549         efx_ev_fini(sa->nic);
550
551 fail_ev_init:
552         efx_intr_fini(sa->nic);
553
554 fail_intr_init:
555         return rc;
556 #else
557         return 0;
558 #endif
559 }
560
561 int
562 sfc_attach(struct sfc_adapter *sa)
563 {
564         struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(sa->eth_dev);
565         const efx_nic_cfg_t *encp;
566         efx_nic_t *enp;
567         int rc;
568
569         sfc_log_init(sa, "entry");
570
571         SFC_ASSERT(sfc_adapter_is_locked(sa));
572
573         sa->socket_id = rte_socket_id();
574
575         sfc_log_init(sa, "init mem bar");
576         rc = sfc_mem_bar_init(sa);
577         if (rc != 0)
578                 goto fail_mem_bar_init;
579
580         sfc_log_init(sa, "get family");
581         rc = efx_family(pci_dev->id.vendor_id, pci_dev->id.device_id,
582                         &sa->family);
583         if (rc != 0)
584                 goto fail_family;
585         sfc_log_init(sa, "family is %u", sa->family);
586
587         sfc_log_init(sa, "create nic");
588         rte_spinlock_init(&sa->nic_lock);
589         rc = efx_nic_create(sa->family, (efsys_identifier_t *)sa,
590                             &sa->mem_bar, &sa->nic_lock, &enp);
591         if (rc != 0)
592                 goto fail_nic_create;
593         sa->nic = enp;
594
595         rc = sfc_mcdi_init(sa);
596         if (rc != 0)
597                 goto fail_mcdi_init;
598
599         sfc_log_init(sa, "probe nic");
600         rc = efx_nic_probe(enp);
601         if (rc != 0)
602                 goto fail_nic_probe;
603
604         efx_mcdi_new_epoch(enp);
605
606         sfc_log_init(sa, "reset nic");
607         rc = efx_nic_reset(enp);
608         if (rc != 0)
609                 goto fail_nic_reset;
610
611         encp = efx_nic_cfg_get(sa->nic);
612
613         sa->tso = encp->enc_fw_assisted_tso_v2_enabled;
614         if (!sa->tso)
615                 sfc_warn(sa, "TSO support isn't available on this adapter");
616
617         sfc_log_init(sa, "estimate resource limits");
618         rc = sfc_estimate_resource_limits(sa);
619         if (rc != 0)
620                 goto fail_estimate_rsrc_limits;
621
622         sa->txq_max_entries = encp->enc_txq_max_ndescs;
623         SFC_ASSERT(rte_is_power_of_2(sa->txq_max_entries));
624
625         rc = sfc_intr_attach(sa);
626         if (rc != 0)
627                 goto fail_intr_attach;
628
629         efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_PERM,
630                             &sa->port.phy_adv_cap_mask);
631
632         rc = sfc_set_rss_defaults(sa);
633         if (rc != 0)
634                 goto fail_set_rss_defaults;
635
636         rc = sfc_filter_attach(sa);
637         if (rc != 0)
638                 goto fail_filter_attach;
639
640         sfc_log_init(sa, "fini nic");
641         efx_nic_fini(enp);
642
643         sa->state = SFC_ADAPTER_INITIALIZED;
644
645         sfc_log_init(sa, "done");
646         return 0;
647
648 fail_filter_attach:
649 fail_set_rss_defaults:
650         sfc_intr_detach(sa);
651
652 fail_intr_attach:
653         efx_nic_fini(sa->nic);
654
655 fail_estimate_rsrc_limits:
656 fail_nic_reset:
657         sfc_log_init(sa, "unprobe nic");
658         efx_nic_unprobe(enp);
659
660 fail_nic_probe:
661         sfc_mcdi_fini(sa);
662
663 fail_mcdi_init:
664         sfc_log_init(sa, "destroy nic");
665         sa->nic = NULL;
666         efx_nic_destroy(enp);
667
668 fail_nic_create:
669 fail_family:
670         sfc_mem_bar_fini(sa);
671
672 fail_mem_bar_init:
673         sfc_log_init(sa, "failed %d", rc);
674         return rc;
675 }
676
677 void
678 sfc_detach(struct sfc_adapter *sa)
679 {
680         efx_nic_t *enp = sa->nic;
681
682         sfc_log_init(sa, "entry");
683
684         SFC_ASSERT(sfc_adapter_is_locked(sa));
685
686         sfc_filter_detach(sa);
687
688         sfc_intr_detach(sa);
689
690         sfc_log_init(sa, "unprobe nic");
691         efx_nic_unprobe(enp);
692
693         sfc_mcdi_fini(sa);
694
695         sfc_log_init(sa, "destroy nic");
696         sa->nic = NULL;
697         efx_nic_destroy(enp);
698
699         sfc_mem_bar_fini(sa);
700
701         sa->state = SFC_ADAPTER_UNINITIALIZED;
702 }