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 [email protected], 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);