--- a/sys/dev/misc/lpt/lpt.c +++ b/sys/dev/misc/lpt/lpt.c @@ -595,14 +595,28 @@ } callout_stop(&sc->sc_callout); ppb_wctr(ppbus, LPC_NINIT); - kfree(sc->sc_inbuf, M_LPT); - kfree(sc->sc_statbuf, M_LPT); + /* + * NB: the lptout callout (which calls lptintr -> lpt_intr without + * the mplock) may still be executing on another cpu; callout_stop() + * does not wait for it. Defer the frees until after the bus (and + * thus the interrupt handler, torn down by ppb_release_bus) is + * released and the callout has been drained. + */ + callout_drain(&sc->sc_callout); end_close: /* release the bus anyway * unregistration of interrupt forced by release */ lpt_release_ppbus(lptdev); + if (sc->sc_inbuf != NULL) { + kfree(sc->sc_inbuf, M_LPT); + sc->sc_inbuf = NULL; + } + if (sc->sc_statbuf != NULL) { + kfree(sc->sc_statbuf, M_LPT); + sc->sc_statbuf = NULL; + } sc->sc_state = 0; sc->sc_xfercnt = 0;