Module Name: src Committed By: yamaguchi Date: Thu Sep 17 06:34:43 UTC 2020
Modified Files: src/sys/dev/pci: if_iavf.c Log Message: Fix a panic caused while detaching iavf(4) The sequence of the panic is follow: 1. failed to disable queues in iavf_stop() 2. release ec->ec_lock in ether_ifdetach() 3. do reset scheduled at iavf_stop() 4. acquire ec->ec_lock in iavf_reset_finish() - panic reviewed by knakahara@n.o, thanks. To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/sys/dev/pci/if_iavf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_iavf.c diff -u src/sys/dev/pci/if_iavf.c:1.5 src/sys/dev/pci/if_iavf.c:1.6 --- src/sys/dev/pci/if_iavf.c:1.5 Thu Sep 10 03:20:08 2020 +++ src/sys/dev/pci/if_iavf.c Thu Sep 17 06:34:43 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_iavf.c,v 1.5 2020/09/10 03:20:08 yamaguchi Exp $ */ +/* $NetBSD: if_iavf.c,v 1.6 2020/09/17 06:34:43 yamaguchi Exp $ */ /* * Copyright (c) 2013-2015, Intel Corporation @@ -75,7 +75,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_iavf.c,v 1.5 2020/09/10 03:20:08 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_iavf.c,v 1.6 2020/09/17 06:34:43 yamaguchi Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -94,6 +94,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_iavf.c,v #include <sys/queue.h> #include <sys/syslog.h> #include <sys/workqueue.h> +#include <sys/xcall.h> #include <net/bpf.h> #include <net/if.h> @@ -626,6 +627,13 @@ static struct iavf_module_params iavf_pa #define iavf_allqueues(_sc) ((1 << ((_sc)->sc_nqueue_pairs)) - 1) static inline void +iavf_intr_barrier(void) +{ + + /* make all interrupt handler finished */ + xc_barrier(0); +} +static inline void iavf_intr_enable(struct iavf_softc *sc) { @@ -965,38 +973,40 @@ iavf_detach(device_t self, int flags) return 0; iavf_stop(ifp, 1); - ether_ifdetach(ifp); - if_detach(ifp); - ifmedia_fini(&sc->sc_media); - if_percpuq_destroy(sc->sc_ipq); - - iavf_intr_disable(sc); - - mutex_enter(&sc->sc_adminq_lock); - mutex_exit(&sc->sc_adminq_lock); /* * set a dummy function to halt callout safely * even if a workqueue entry calls callout_schedule() */ callout_setfunc(&sc->sc_tick, iavf_tick_halt, sc); - iavf_work_wait(sc->sc_workq, &sc->sc_reset_task); - iavf_work_wait(sc->sc_workq, &sc->sc_arq_refill); iavf_work_wait(sc->sc_workq, &sc->sc_wdto_task); - iavf_workq_destroy(sc->sc_workq); - sc->sc_workq = NULL; callout_halt(&sc->sc_tick, NULL); callout_destroy(&sc->sc_tick); + /* detach the I/F before stop adminq due to callbacks */ + ether_ifdetach(ifp); + if_detach(ifp); + ifmedia_fini(&sc->sc_media); + if_percpuq_destroy(sc->sc_ipq); + + iavf_intr_disable(sc); + iavf_intr_barrier(); + iavf_work_wait(sc->sc_workq, &sc->sc_arq_refill); + + mutex_enter(&sc->sc_adminq_lock); iavf_cleanup_admin_queue(sc); + mutex_exit(&sc->sc_adminq_lock); iavf_aqb_clean(&sc->sc_atq_idle, sc->sc_dmat); iavf_aqb_clean(&sc->sc_arq_idle, sc->sc_dmat); iavf_dmamem_free(sc->sc_dmat, &sc->sc_arq); iavf_dmamem_free(sc->sc_dmat, &sc->sc_atq); cv_destroy(&sc->sc_adminq_cv); + iavf_workq_destroy(sc->sc_workq); + sc->sc_workq = NULL; + iavf_queue_pairs_free(sc); iavf_teardown_interrupts(sc); iavf_teardown_sysctls(sc);