/* * tunclose - close the device - mark i/f down & delete * routing info */ int tunclose(dev_t dev, int flag, int mode, struct lwp *l) { int s; struct tun_softc *tp; struct ifnet *ifp; s = splnet(); if ((tp = tun_find_zunit(minor(dev))) != NULL) { /* interface was "destroyed" before the close */ seldestroy(&tp->tun_rsel); seldestroy(&tp->tun_wsel); softint_disestablish(tp->tun_osih); softint_disestablish(tp->tun_isih); mutex_destroy(&tp->tun_lock); free(tp, M_DEVBUF); goto out_nolock; } if ((tp = tun_find_unit(dev)) == NULL) goto out_nolock; ifp = &tp->tun_if; tp->tun_flags &= ~TUN_OPEN; tp->tun_pgid = 0; selnotify(&tp->tun_rsel, 0, 0); TUNDEBUG ("%s: closed\n", ifp->if_xname); mutex_exit(&tp->tun_lock); /* * junk all pending output */ IFQ_PURGE(&ifp->if_snd); if (ifp->if_flags & IFF_UP) { if_down(ifp); if (ifp->if_flags & IFF_RUNNING) { /* find internet addresses and delete routes */ struct ifaddr *ifa; IFADDR_FOREACH(ifa, ifp) { #if defined(INET) || defined(INET6) if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) { rtinit(ifa, (int)RTM_DELETE, tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); } #endif } } }
static int tap_dev_close(struct tap_softc *sc) { struct ifnet *ifp; int s; s = splnet(); /* Let tap_start handle packets again */ ifp = &sc->sc_ec.ec_if; ifp->if_flags &= ~IFF_OACTIVE; /* Purge output queue */ if (!(IFQ_IS_EMPTY(&ifp->if_snd))) { struct mbuf *m; for (;;) { IFQ_DEQUEUE(&ifp->if_snd, m); if (m == NULL) break; ifp->if_opackets++; bpf_mtap(ifp, m); m_freem(m); } } splx(s); if (sc->sc_sih != NULL) { softint_disestablish(sc->sc_sih); sc->sc_sih = NULL; } sc->sc_flags &= ~(TAP_INUSE | TAP_ASYNCIO); return (0); }
/* This is necessary when dynamically changing SAIP configuration. */ int sacom_detach(struct device *self, int flags) { struct sacom_softc *sc = (struct sacom_softc *)self; int maj, mn; /* locate the major number */ maj = cdevsw_lookup_major(&sacom_cdevsw); /* Nuke the vnodes for any open instances. */ mn = device_unit(self); vdevgone(maj, mn, mn, VCHR); mn |= COMDIALOUT_MASK; vdevgone(maj, mn, mn, VCHR); /* Free the receive buffer. */ free(sc->sc_rbuf, M_DEVBUF); /* Detach and free the tty. */ tty_detach(sc->sc_tty); ttyfree(sc->sc_tty); /* Unhook the soft interrupt handler. */ softint_disestablish(sc->sc_si); #if NRND > 0 && defined(RND_COM) /* Unhook the entropy source. */ rnd_detach_source(&sc->rnd_source); #endif return 0; }
int testcall(struct lwp *l, void *uap, register_t *retval) { printf("test: initializing\n"); mutex_init(&test_mutex, MUTEX_DEFAULT, IPL_NONE); cv_init(&test_cv, "testcv"); test_sih = softint_establish(SOFTINT_MPSAFE | SOFTINT_SERIAL, test_softint, NULL); callout_init(&test_ch, CALLOUT_MPSAFE); callout_setfunc(&test_ch, test_callout, NULL); printf("test: firing\n"); callout_schedule(&test_ch, hz / 10); printf("test: waiting\n"); mutex_enter(&test_mutex); while (!test_done) { cv_wait(&test_cv, &test_mutex); } mutex_exit(&test_mutex); printf("test: finished\n"); callout_destroy(&test_ch); softint_disestablish(test_sih); mutex_destroy(&test_mutex); cv_destroy(&test_cv); return 0; }
static int tun_clone_destroy(struct ifnet *ifp) { struct tun_softc *tp = (void *)ifp; int s, zombie = 0; IF_PURGE(&ifp->if_snd); ifp->if_flags &= ~IFF_RUNNING; s = splnet(); simple_lock(&tun_softc_lock); mutex_enter(&tp->tun_lock); LIST_REMOVE(tp, tun_list); if (tp->tun_flags & TUN_OPEN) { /* Hang on to storage until last close */ zombie = 1; tp->tun_flags &= ~TUN_INITED; LIST_INSERT_HEAD(&tunz_softc_list, tp, tun_list); } simple_unlock(&tun_softc_lock); if (tp->tun_flags & TUN_RWAIT) { tp->tun_flags &= ~TUN_RWAIT; wakeup((void *)tp); } selnotify(&tp->tun_rsel, 0, 0); mutex_exit(&tp->tun_lock); splx(s); if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid) fownsignal(tp->tun_pgid, SIGIO, POLL_HUP, 0, NULL); bpf_detach(ifp); if_detach(ifp); if (!zombie) { seldestroy(&tp->tun_rsel); seldestroy(&tp->tun_wsel); softint_disestablish(tp->tun_osih); softint_disestablish(tp->tun_isih); mutex_destroy(&tp->tun_lock); free(tp, M_DEVBUF); } return (0); }
static void free_pipe(struct umidi_endpoint *ep) { DPRINTF(("%s: free_pipe %p\n", USBDEVNAME(ep->sc->sc_dev), ep)); usbd_abort_pipe(ep->pipe); usbd_close_pipe(ep->pipe); usbd_free_xfer(ep->xfer); softint_disestablish(ep->solicit_cookie); }
int lpt_detach_subr(device_t self, int flags) { struct lpt_softc *sc = device_private(self); sc->sc_dev_ok = 0; softint_disestablish(sc->sc_sih); callout_destroy(&sc->sc_wakeup_ch); return 0; }
static int btsco_detach(device_t self, int flags) { struct btsco_softc *sc = device_private(self); DPRINTF("sc=%p\n", sc); pmf_device_deregister(self); mutex_enter(bt_lock); if (sc->sc_sco != NULL) { DPRINTF("sc_sco=%p\n", sc->sc_sco); sco_disconnect_pcb(sc->sc_sco, 0); sco_detach_pcb(&sc->sc_sco); sc->sc_sco = NULL; } if (sc->sc_sco_l != NULL) { DPRINTF("sc_sco_l=%p\n", sc->sc_sco_l); sco_detach_pcb(&sc->sc_sco_l); sc->sc_sco_l = NULL; } mutex_exit(bt_lock); if (sc->sc_audio != NULL) { DPRINTF("sc_audio=%p\n", sc->sc_audio); config_detach(sc->sc_audio, flags); sc->sc_audio = NULL; } if (sc->sc_intr != NULL) { softint_disestablish(sc->sc_intr); sc->sc_intr = NULL; } if (sc->sc_rx_mbuf != NULL) { m_freem(sc->sc_rx_mbuf); sc->sc_rx_mbuf = NULL; } if (sc->sc_tx_refcnt > 0) { aprint_error_dev(self, "tx_refcnt=%d!\n", sc->sc_tx_refcnt); if ((flags & DETACH_FORCE) == 0) return EAGAIN; } cv_destroy(&sc->sc_connect); mutex_destroy(&sc->sc_intr_lock); return 0; }
int mididetach(device_t self, int flags) { struct midi_softc *sc = device_private(self); int maj, mn; DPRINTFN(2,("%s: sc=%p flags=%d\n", __func__, sc, flags)); pmf_device_deregister(self); mutex_enter(sc->lock); sc->dying = 1; cv_broadcast(&sc->wchan); cv_broadcast(&sc->rchan); mutex_exit(sc->lock); /* locate the major number */ maj = cdevsw_lookup_major(&midi_cdevsw); /* * Nuke the vnodes for any open instances (calls close). * Will wait until any activity on the device nodes has ceased. * * XXXAD NOT YET. * * XXXAD NEED TO PREVENT NEW REFERENCES THROUGH AUDIO_ENTER(). */ mn = device_unit(self); vdevgone(maj, mn, mn, VCHR); if (!(sc->props & MIDI_PROP_NO_OUTPUT)) { evcnt_detach(&sc->xmt.bytesDiscarded); evcnt_detach(&sc->xmt.incompleteMessages); } if (sc->props & MIDI_PROP_CAN_INPUT) { evcnt_detach(&sc->rcv.bytesDiscarded); evcnt_detach(&sc->rcv.incompleteMessages); } if (sc->sih != NULL) { softint_disestablish(sc->sih); sc->sih = NULL; } cv_destroy(&sc->wchan); cv_destroy(&sc->rchan); return (0); }
static int xennet_xenbus_detach(device_t self, int flags) { struct xennet_xenbus_softc *sc = device_private(self); struct ifnet *ifp = &sc->sc_ethercom.ec_if; int s0, s1; RING_IDX i; DPRINTF(("%s: xennet_xenbus_detach\n", device_xname(self))); s0 = splnet(); xennet_stop(ifp, 1); /* wait for pending TX to complete, and collect pending RX packets */ xennet_handler(sc); while (sc->sc_tx_ring.sring->rsp_prod != sc->sc_tx_ring.rsp_cons) { tsleep(xennet_xenbus_detach, PRIBIO, "xnet_detach", hz/2); xennet_handler(sc); } xennet_free_rx_buffer(sc); s1 = splvm(); for (i = 0; i < NET_RX_RING_SIZE; i++) { struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i]; uvm_km_free(kernel_map, rxreq->rxreq_va, PAGE_SIZE, UVM_KMF_WIRED); } splx(s1); ether_ifdetach(ifp); if_detach(ifp); while (xengnt_status(sc->sc_tx_ring_gntref)) { tsleep(xennet_xenbus_detach, PRIBIO, "xnet_txref", hz/2); } xengnt_revoke_access(sc->sc_tx_ring_gntref); uvm_km_free(kernel_map, (vaddr_t)sc->sc_tx_ring.sring, PAGE_SIZE, UVM_KMF_WIRED); while (xengnt_status(sc->sc_rx_ring_gntref)) { tsleep(xennet_xenbus_detach, PRIBIO, "xnet_rxref", hz/2); } xengnt_revoke_access(sc->sc_rx_ring_gntref); uvm_km_free(kernel_map, (vaddr_t)sc->sc_rx_ring.sring, PAGE_SIZE, UVM_KMF_WIRED); softint_disestablish(sc->sc_softintr); event_remove_handler(sc->sc_evtchn, &xennet_handler, sc); splx(s0); DPRINTF(("%s: xennet_xenbus_detach done\n", device_xname(self))); return 0; }
void gemini_ipm_deregister(void *ipmh) { gemini_ipm_softc_t *sc = gemini_ipm_sc; ipm_dispatch_entry_t *disp = ipmh; int psw; if (sc == NULL) return; psw = disable_interrupts(I32_bit); memset(disp, 0, sizeof(*disp)); #ifdef NOTYET softint_disestablish(sc->sih); #endif restore_interrupts(psw); }
/* * When detaching, we do the inverse of what is done in the attach * routine, in reversed order. */ static int tap_detach(device_t self, int flags) { struct tap_softc *sc = device_private(self); struct ifnet *ifp = &sc->sc_ec.ec_if; #if defined(COMPAT_40) || defined(MODULAR) int error; #endif int s; sc->sc_flags |= TAP_GOING; s = splnet(); tap_stop(ifp, 1); if_down(ifp); splx(s); if (sc->sc_sih != NULL) { softint_disestablish(sc->sc_sih); sc->sc_sih = NULL; } #if defined(COMPAT_40) || defined(MODULAR) /* * Destroying a single leaf is a very straightforward operation using * sysctl_destroyv. One should be sure to always end the path with * CTL_EOL. */ if ((error = sysctl_destroyv(NULL, CTL_NET, AF_LINK, tap_node, device_unit(sc->sc_dev), CTL_EOL)) != 0) aprint_error_dev(self, "sysctl_destroyv returned %d, ignoring\n", error); #endif ether_ifdetach(ifp); if_detach(ifp); ifmedia_delete_instance(&sc->sc_im, IFM_INST_ANY); seldestroy(&sc->sc_rsel); mutex_destroy(&sc->sc_rdlock); mutex_destroy(&sc->sc_kqlock); pmf_device_deregister(self); return (0); }
int ucom_detach(device_t self, int flags) { struct ucom_softc *sc = device_private(self); struct tty *tp = sc->sc_tty; int maj, mn; int s, i; DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p, pipe=%d,%d\n", sc, flags, tp, sc->sc_bulkin_no, sc->sc_bulkout_no)); sc->sc_dying = 1; pmf_device_deregister(self); if (sc->sc_bulkin_pipe != NULL) usbd_abort_pipe(sc->sc_bulkin_pipe); if (sc->sc_bulkout_pipe != NULL) usbd_abort_pipe(sc->sc_bulkout_pipe); s = splusb(); if (--sc->sc_refcnt >= 0) { /* Wake up anyone waiting */ if (tp != NULL) { mutex_spin_enter(&tty_lock); CLR(tp->t_state, TS_CARR_ON); CLR(tp->t_cflag, CLOCAL | MDMBUF); ttyflush(tp, FREAD|FWRITE); mutex_spin_exit(&tty_lock); } /* Wait for processes to go away. */ usb_detach_waitold(sc->sc_dev); } softint_disestablish(sc->sc_si); splx(s); /* locate the major number */ maj = cdevsw_lookup_major(&ucom_cdevsw); /* Nuke the vnodes for any open instances. */ mn = device_unit(self); DPRINTF(("ucom_detach: maj=%d mn=%d\n", maj, mn)); vdevgone(maj, mn, mn, VCHR); vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR); vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR); /* Detach and free the tty. */ if (tp != NULL) { tty_detach(tp); tty_free(tp); sc->sc_tty = NULL; } for (i = 0; i < UCOM_IN_BUFFS; i++) { if (sc->sc_ibuff[i].ub_xfer != NULL) usbd_free_xfer(sc->sc_ibuff[i].ub_xfer); } for (i = 0; i < UCOM_OUT_BUFFS; i++) { if (sc->sc_obuff[i].ub_xfer != NULL) usbd_free_xfer(sc->sc_obuff[i].ub_xfer); } /* Detach the random source */ rnd_detach_source(&sc->sc_rndsource); return (0); }
static int tap_dev_ioctl(int unit, u_long cmd, void *data, struct lwp *l) { struct tap_softc *sc = device_lookup_private(&tap_cd, unit); if (sc == NULL) return ENXIO; switch (cmd) { case FIONREAD: { struct ifnet *ifp = &sc->sc_ec.ec_if; struct mbuf *m; int s; s = splnet(); IFQ_POLL(&ifp->if_snd, m); if (m == NULL) *(int *)data = 0; else *(int *)data = m->m_pkthdr.len; splx(s); return 0; } case TIOCSPGRP: case FIOSETOWN: return fsetown(&sc->sc_pgid, cmd, data); case TIOCGPGRP: case FIOGETOWN: return fgetown(sc->sc_pgid, cmd, data); case FIOASYNC: if (*(int *)data) { if (sc->sc_sih == NULL) { sc->sc_sih = softint_establish(SOFTINT_CLOCK, tap_softintr, sc); if (sc->sc_sih == NULL) return EBUSY; /* XXX */ } sc->sc_flags |= TAP_ASYNCIO; } else { sc->sc_flags &= ~TAP_ASYNCIO; if (sc->sc_sih != NULL) { softint_disestablish(sc->sc_sih); sc->sc_sih = NULL; } } return 0; case FIONBIO: if (*(int *)data) sc->sc_flags |= TAP_NBIO; else sc->sc_flags &= ~TAP_NBIO; return 0; #ifdef OTAPGIFNAME case OTAPGIFNAME: #endif case TAPGIFNAME: { struct ifreq *ifr = (struct ifreq *)data; struct ifnet *ifp = &sc->sc_ec.ec_if; strlcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ); return 0; } default: return ENOTTY; } }