static int nsmb_dev_load(module_t mod, int cmd, void *arg) { int error = 0; switch (cmd) { case MOD_LOAD: error = smb_sm_init(); if (error) break; error = smb_iod_init(); if (error) { smb_sm_done(); break; } clone_setup(&nsmb_clones); nsmb_dev_tag = EVENTHANDLER_REGISTER(dev_clone, nsmb_dev_clone, 0, 1000); break; case MOD_UNLOAD: smb_iod_done(); error = smb_sm_done(); if (error) break; EVENTHANDLER_DEREGISTER(dev_clone, nsmb_dev_tag); drain_dev_clone_events(); clone_cleanup(&nsmb_clones); destroy_dev_drain(&nsmb_cdevsw); break; default: error = EINVAL; break; } return error; }
/* Called from detach */ void sms1xxx_demux_exit(struct sms1xxx_softc *sc) { /* Wake up readers ! */ if(sc->dvr.state & DVR_SLEEP) { wakeup(&sc->dvr); } if(sc->dvr.state & DVR_POLL) { sc->dvr.state &= ~DVR_POLL; selwakeuppri(&sc->dvr.rsel,PZERO); } /* Devices */ if(sc->dvr.dev != NULL) { TRACE(TRACE_MODULE,"destroying dvr0, addr=%p\n",sc->dvr.dev); destroy_dev(sc->dvr.dev); sc->dvr.dev = NULL; } if(sc->clonetag != NULL) { EVENTHANDLER_DEREGISTER(dev_clone,sc->clonetag); sc->clonetag = NULL; } /* Destroy remaining clones */ for(int i = 0; i < MAX_FILTERS; ++i) { if((sc->filter[i].pid != PIDFREE) && (sc->filter[i].dev != NULL)) { TRACE(TRACE_MODULE,"destroying demux0.%d device, addr=%p\n", i,sc->filter[i].dev); destroy_dev_sched_cb(sc->filter[i].dev, sms1xxx_demux_filter_reset, &sc->filter[i]); } } if(sc->demux_clones != NULL) { drain_dev_clone_events(); clone_cleanup(&sc->demux_clones); destroy_dev_drain(&sms1xxx_demux_cdevsw); sc->demux_clones = NULL; } /* DVR */ sc->dvr.state = 0; sms1xxx_demux_pesbuf_reset(sc, 0, "exit"); if(sc->dvr.buf != NULL) { free(sc->dvr.buf, M_USBDEV); sc->dvr.buf = NULL; } /* Mutexes */ mtx_destroy(&sc->filterlock); mtx_destroy(&sc->dvr.lock); }