648ad8c58892ef2b4e92d5df8583e8ed277b28db
[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         SFC_ASSERT(limits.edl_max_txq_count >= limits.edl_min_rxq_count);
207
208         /* Configure the minimum required resources needed for the
209          * driver to operate, and the maximum desired resources that the
210          * driver is capable of using.
211          */
212         efx_nic_set_drv_limits(sa->nic, &limits);
213
214         sfc_log_init(sa, "init nic");
215         rc = efx_nic_init(sa->nic);
216         if (rc != 0)
217                 goto fail_nic_init;
218
219         /* Find resource dimensions assigned by firmware to this function */
220         rc = efx_nic_get_vi_pool(sa->nic, &evq_allocated, &rxq_allocated,
221                                  &txq_allocated);
222         if (rc != 0)
223                 goto fail_get_vi_pool;
224
225         /* It still may allocate more than maximum, ensure limit */
226         evq_allocated = MIN(evq_allocated, limits.edl_max_evq_count);
227         rxq_allocated = MIN(rxq_allocated, limits.edl_max_rxq_count);
228         txq_allocated = MIN(txq_allocated, limits.edl_max_txq_count);
229
230         /* Subtract management EVQ not used for traffic */
231         SFC_ASSERT(evq_allocated > 0);
232         evq_allocated--;
233
234         /* Right now we use separate EVQ for Rx and Tx */
235         sa->rxq_max = MIN(rxq_allocated, evq_allocated / 2);
236         sa->txq_max = MIN(txq_allocated, evq_allocated - sa->rxq_max);
237
238         /* Keep NIC initialized */
239         return 0;
240
241 fail_get_vi_pool:
242 fail_nic_init:
243         efx_nic_fini(sa->nic);
244         return rc;
245 }
246
247 static int
248 sfc_set_drv_limits(struct sfc_adapter *sa)
249 {
250         const struct rte_eth_dev_data *data = sa->eth_dev->data;
251         efx_drv_limits_t lim;
252
253         memset(&lim, 0, sizeof(lim));
254
255         /* Limits are strict since take into account initial estimation */
256         lim.edl_min_evq_count = lim.edl_max_evq_count =
257                 1 + data->nb_rx_queues + data->nb_tx_queues;
258         lim.edl_min_rxq_count = lim.edl_max_rxq_count = data->nb_rx_queues;
259         lim.edl_min_txq_count = lim.edl_max_txq_count = data->nb_tx_queues;
260
261         return efx_nic_set_drv_limits(sa->nic, &lim);
262 }
263
264 int
265 sfc_start(struct sfc_adapter *sa)
266 {
267         int rc;
268
269         sfc_log_init(sa, "entry");
270
271         SFC_ASSERT(sfc_adapter_is_locked(sa));
272
273         switch (sa->state) {
274         case SFC_ADAPTER_CONFIGURED:
275                 break;
276         case SFC_ADAPTER_STARTED:
277                 sfc_info(sa, "already started");
278                 return 0;
279         default:
280                 rc = EINVAL;
281                 goto fail_bad_state;
282         }
283
284         sa->state = SFC_ADAPTER_STARTING;
285
286         sfc_log_init(sa, "set resource limits");
287         rc = sfc_set_drv_limits(sa);
288         if (rc != 0)
289                 goto fail_set_drv_limits;
290
291         sfc_log_init(sa, "init nic");
292         rc = efx_nic_init(sa->nic);
293         if (rc != 0)
294                 goto fail_nic_init;
295
296         rc = sfc_intr_start(sa);
297         if (rc != 0)
298                 goto fail_intr_start;
299
300         rc = sfc_ev_start(sa);
301         if (rc != 0)
302                 goto fail_ev_start;
303
304         rc = sfc_port_start(sa);
305         if (rc != 0)
306                 goto fail_port_start;
307
308         rc = sfc_rx_start(sa);
309         if (rc != 0)
310                 goto fail_rx_start;
311
312         rc = sfc_tx_start(sa);
313         if (rc != 0)
314                 goto fail_tx_start;
315
316         sa->state = SFC_ADAPTER_STARTED;
317         sfc_log_init(sa, "done");
318         return 0;
319
320 fail_tx_start:
321         sfc_rx_stop(sa);
322
323 fail_rx_start:
324         sfc_port_stop(sa);
325
326 fail_port_start:
327         sfc_ev_stop(sa);
328
329 fail_ev_start:
330         sfc_intr_stop(sa);
331
332 fail_intr_start:
333         efx_nic_fini(sa->nic);
334
335 fail_nic_init:
336 fail_set_drv_limits:
337         sa->state = SFC_ADAPTER_CONFIGURED;
338 fail_bad_state:
339         sfc_log_init(sa, "failed %d", rc);
340         return rc;
341 }
342
343 void
344 sfc_stop(struct sfc_adapter *sa)
345 {
346         sfc_log_init(sa, "entry");
347
348         SFC_ASSERT(sfc_adapter_is_locked(sa));
349
350         switch (sa->state) {
351         case SFC_ADAPTER_STARTED:
352                 break;
353         case SFC_ADAPTER_CONFIGURED:
354                 sfc_info(sa, "already stopped");
355                 return;
356         default:
357                 sfc_err(sa, "stop in unexpected state %u", sa->state);
358                 SFC_ASSERT(B_FALSE);
359                 return;
360         }
361
362         sa->state = SFC_ADAPTER_STOPPING;
363
364         sfc_tx_stop(sa);
365         sfc_rx_stop(sa);
366         sfc_port_stop(sa);
367         sfc_ev_stop(sa);
368         sfc_intr_stop(sa);
369         efx_nic_fini(sa->nic);
370
371         sa->state = SFC_ADAPTER_CONFIGURED;
372         sfc_log_init(sa, "done");
373 }
374
375 int
376 sfc_configure(struct sfc_adapter *sa)
377 {
378         int rc;
379
380         sfc_log_init(sa, "entry");
381
382         SFC_ASSERT(sfc_adapter_is_locked(sa));
383
384         SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
385         sa->state = SFC_ADAPTER_CONFIGURING;
386
387         rc = sfc_check_conf(sa);
388         if (rc != 0)
389                 goto fail_check_conf;
390
391         rc = sfc_intr_init(sa);
392         if (rc != 0)
393                 goto fail_intr_init;
394
395         rc = sfc_ev_init(sa);
396         if (rc != 0)
397                 goto fail_ev_init;
398
399         rc = sfc_port_init(sa);
400         if (rc != 0)
401                 goto fail_port_init;
402
403         rc = sfc_rx_init(sa);
404         if (rc != 0)
405                 goto fail_rx_init;
406
407         rc = sfc_tx_init(sa);
408         if (rc != 0)
409                 goto fail_tx_init;
410
411         sa->state = SFC_ADAPTER_CONFIGURED;
412         sfc_log_init(sa, "done");
413         return 0;
414
415 fail_tx_init:
416         sfc_rx_fini(sa);
417
418 fail_rx_init:
419         sfc_port_fini(sa);
420
421 fail_port_init:
422         sfc_ev_fini(sa);
423
424 fail_ev_init:
425         sfc_intr_fini(sa);
426
427 fail_intr_init:
428 fail_check_conf:
429         sa->state = SFC_ADAPTER_INITIALIZED;
430         sfc_log_init(sa, "failed %d", rc);
431         return rc;
432 }
433
434 void
435 sfc_close(struct sfc_adapter *sa)
436 {
437         sfc_log_init(sa, "entry");
438
439         SFC_ASSERT(sfc_adapter_is_locked(sa));
440
441         SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED);
442         sa->state = SFC_ADAPTER_CLOSING;
443
444         sfc_tx_fini(sa);
445         sfc_rx_fini(sa);
446         sfc_port_fini(sa);
447         sfc_ev_fini(sa);
448         sfc_intr_fini(sa);
449
450         sa->state = SFC_ADAPTER_INITIALIZED;
451         sfc_log_init(sa, "done");
452 }
453
454 static int
455 sfc_mem_bar_init(struct sfc_adapter *sa)
456 {
457         struct rte_eth_dev *eth_dev = sa->eth_dev;
458         struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(eth_dev);
459         efsys_bar_t *ebp = &sa->mem_bar;
460         unsigned int i;
461         struct rte_mem_resource *res;
462
463         for (i = 0; i < RTE_DIM(pci_dev->mem_resource); i++) {
464                 res = &pci_dev->mem_resource[i];
465                 if ((res->len != 0) && (res->phys_addr != 0)) {
466                         /* Found first memory BAR */
467                         SFC_BAR_LOCK_INIT(ebp, eth_dev->data->name);
468                         ebp->esb_rid = i;
469                         ebp->esb_dev = pci_dev;
470                         ebp->esb_base = res->addr;
471                         return 0;
472                 }
473         }
474
475         return EFAULT;
476 }
477
478 static void
479 sfc_mem_bar_fini(struct sfc_adapter *sa)
480 {
481         efsys_bar_t *ebp = &sa->mem_bar;
482
483         SFC_BAR_LOCK_DESTROY(ebp);
484         memset(ebp, 0, sizeof(*ebp));
485 }
486
487 #if EFSYS_OPT_RX_SCALE
488 /*
489  * A fixed RSS key which has a property of being symmetric
490  * (symmetrical flows are distributed to the same CPU)
491  * and also known to give a uniform distribution
492  * (a good distribution of traffic between different CPUs)
493  */
494 static const uint8_t default_rss_key[SFC_RSS_KEY_SIZE] = {
495         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
496         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
497         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
498         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
499         0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
500 };
501 #endif
502
503 static int
504 sfc_set_rss_defaults(struct sfc_adapter *sa)
505 {
506 #if EFSYS_OPT_RX_SCALE
507         int rc;
508
509         rc = efx_intr_init(sa->nic, sa->intr.type, NULL);
510         if (rc != 0)
511                 goto fail_intr_init;
512
513         rc = efx_ev_init(sa->nic);
514         if (rc != 0)
515                 goto fail_ev_init;
516
517         rc = efx_rx_init(sa->nic);
518         if (rc != 0)
519                 goto fail_rx_init;
520
521         rc = efx_rx_scale_support_get(sa->nic, &sa->rss_support);
522         if (rc != 0)
523                 goto fail_scale_support_get;
524
525         rc = efx_rx_hash_support_get(sa->nic, &sa->hash_support);
526         if (rc != 0)
527                 goto fail_hash_support_get;
528
529         efx_rx_fini(sa->nic);
530         efx_ev_fini(sa->nic);
531         efx_intr_fini(sa->nic);
532
533         sa->rss_hash_types = sfc_rte_to_efx_hash_type(SFC_RSS_OFFLOADS);
534
535         rte_memcpy(sa->rss_key, default_rss_key, sizeof(sa->rss_key));
536
537         return 0;
538
539 fail_hash_support_get:
540 fail_scale_support_get:
541 fail_rx_init:
542         efx_ev_fini(sa->nic);
543
544 fail_ev_init:
545         efx_intr_fini(sa->nic);
546
547 fail_intr_init:
548         return rc;
549 #else
550         return 0;
551 #endif
552 }
553
554 int
555 sfc_attach(struct sfc_adapter *sa)
556 {
557         struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(sa->eth_dev);
558         const efx_nic_cfg_t *encp;
559         efx_nic_t *enp;
560         int rc;
561
562         sfc_log_init(sa, "entry");
563
564         SFC_ASSERT(sfc_adapter_is_locked(sa));
565
566         sa->socket_id = rte_socket_id();
567
568         sfc_log_init(sa, "init mem bar");
569         rc = sfc_mem_bar_init(sa);
570         if (rc != 0)
571                 goto fail_mem_bar_init;
572
573         sfc_log_init(sa, "get family");
574         rc = efx_family(pci_dev->id.vendor_id, pci_dev->id.device_id,
575                         &sa->family);
576         if (rc != 0)
577                 goto fail_family;
578         sfc_log_init(sa, "family is %u", sa->family);
579
580         sfc_log_init(sa, "create nic");
581         rte_spinlock_init(&sa->nic_lock);
582         rc = efx_nic_create(sa->family, (efsys_identifier_t *)sa,
583                             &sa->mem_bar, &sa->nic_lock, &enp);
584         if (rc != 0)
585                 goto fail_nic_create;
586         sa->nic = enp;
587
588         rc = sfc_mcdi_init(sa);
589         if (rc != 0)
590                 goto fail_mcdi_init;
591
592         sfc_log_init(sa, "probe nic");
593         rc = efx_nic_probe(enp);
594         if (rc != 0)
595                 goto fail_nic_probe;
596
597         efx_mcdi_new_epoch(enp);
598
599         sfc_log_init(sa, "reset nic");
600         rc = efx_nic_reset(enp);
601         if (rc != 0)
602                 goto fail_nic_reset;
603
604         sfc_log_init(sa, "estimate resource limits");
605         rc = sfc_estimate_resource_limits(sa);
606         if (rc != 0)
607                 goto fail_estimate_rsrc_limits;
608
609         encp = efx_nic_cfg_get(sa->nic);
610         sa->txq_max_entries = encp->enc_txq_max_ndescs;
611         SFC_ASSERT(rte_is_power_of_2(sa->txq_max_entries));
612
613         rc = sfc_intr_attach(sa);
614         if (rc != 0)
615                 goto fail_intr_attach;
616
617         efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_PERM,
618                             &sa->port.phy_adv_cap_mask);
619
620         rc = sfc_set_rss_defaults(sa);
621         if (rc != 0)
622                 goto fail_set_rss_defaults;
623
624 #ifdef RTE_LIBRTE_SFC_EFX_TSO
625         sa->tso = efx_nic_cfg_get(sa->nic)->enc_fw_assisted_tso_v2_enabled;
626         if (!sa->tso)
627                 sfc_warn(sa, "TSO support isn't available on this adapter");
628 #else /* !RTE_LIBRTE_SFC_EFX_TSO */
629         sa->tso = B_FALSE;
630 #endif /* RTE_LIBRTE_SFC_EFX_TSO */
631
632         sfc_log_init(sa, "fini nic");
633         efx_nic_fini(enp);
634
635         sa->state = SFC_ADAPTER_INITIALIZED;
636
637         sfc_log_init(sa, "done");
638         return 0;
639
640 fail_set_rss_defaults:
641         sfc_intr_detach(sa);
642
643 fail_intr_attach:
644         efx_nic_fini(sa->nic);
645
646 fail_estimate_rsrc_limits:
647 fail_nic_reset:
648         sfc_log_init(sa, "unprobe nic");
649         efx_nic_unprobe(enp);
650
651 fail_nic_probe:
652         sfc_mcdi_fini(sa);
653
654 fail_mcdi_init:
655         sfc_log_init(sa, "destroy nic");
656         sa->nic = NULL;
657         efx_nic_destroy(enp);
658
659 fail_nic_create:
660 fail_family:
661         sfc_mem_bar_fini(sa);
662
663 fail_mem_bar_init:
664         sfc_log_init(sa, "failed %d", rc);
665         return rc;
666 }
667
668 void
669 sfc_detach(struct sfc_adapter *sa)
670 {
671         efx_nic_t *enp = sa->nic;
672
673         sfc_log_init(sa, "entry");
674
675         SFC_ASSERT(sfc_adapter_is_locked(sa));
676
677         sfc_intr_detach(sa);
678
679         sfc_log_init(sa, "unprobe nic");
680         efx_nic_unprobe(enp);
681
682         sfc_mcdi_fini(sa);
683
684         sfc_log_init(sa, "destroy nic");
685         sa->nic = NULL;
686         efx_nic_destroy(enp);
687
688         sfc_mem_bar_fini(sa);
689
690         sa->state = SFC_ADAPTER_UNINITIALIZED;
691 }