/* * pti_done() releases the reference and checks to see if both sides have * been closed on a unix98 pty, allowing us to destroy the device and * release resources. * * We do not release resources on non-unix98 ptys. Those are left * statically allocated. */ static void pti_done(struct pt_ioctl *pti) { lwkt_gettoken(&tty_token); if (--pti->pt_refs == 0) { #ifdef UNIX98_PTYS cdev_t dev; int uminor_no; /* * Only unix09 ptys are freed up */ if ((pti->pt_flags & PF_UNIX98) == 0) { lwkt_reltoken(&tty_token); return; } /* * Interlock open attempts against termination by setting * PF_TERMINATED. This allows us to block while cleaning * out the device infrastructure. * * Do not terminate the tty if it still has a session * association (t_refs). */ if ((pti->pt_flags & (PF_SOPEN|PF_MOPEN)) == 0 && pti->pt_tty.t_refs == 0) { pti->pt_flags |= PF_TERMINATED; uminor_no = pti->pt_uminor; if ((dev = pti->devs) != NULL) { dev->si_drv1 = NULL; pti->devs = NULL; destroy_dev(dev); } if ((dev = pti->devc) != NULL) { dev->si_drv1 = NULL; pti->devc = NULL; destroy_dev(dev); } ttyunregister(&pti->pt_tty); devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(pty), uminor_no); kfree(pti, M_PTY); } #endif } lwkt_reltoken(&tty_token); }
static int vnclose(struct dev_close_args *ap) { cdev_t dev = ap->a_head.a_dev; struct vn_softc *vn; vn = dev->si_drv1; KKASSERT(vn != NULL); vn->sc_flags &= ~VNF_OPENED; /* The disk has been detached and can now be safely destroyed */ if (vn->sc_flags & VNF_DESTROY) { KKASSERT(disk_getopencount(&vn->sc_disk) == 0); disk_destroy(&vn->sc_disk); devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(vn), dkunit(dev)); SLIST_REMOVE(&vn_list, vn, vn_softc, sc_list); kfree(vn, M_VN); } return (0); }
static int snpclose(struct dev_close_args *ap) { cdev_t dev = ap->a_head.a_dev; struct snoop *snp; int ret; lwkt_gettoken(&tty_token); snp = dev->si_drv1; snp->snp_blen = 0; LIST_REMOVE(snp, snp_list); kfree(snp->snp_buf, M_SNP); snp->snp_flags &= ~SNOOP_OPEN; dev->si_drv1 = NULL; if (dev->si_uminor >= SNP_PREALLOCATED_UNITS) { devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(snp), dev->si_uminor); destroy_dev(dev); } ret = snp_detach(snp); lwkt_reltoken(&tty_token); return ret; }
void uether_ifdetach(struct usb_ether *ue) { struct ifnet *ifp; /* wait for any post attach or other command to complete */ usb_proc_drain(&ue->ue_tq); /* read "ifnet" pointer after taskqueue drain */ ifp = uether_getifp(ue); if (ifp != NULL) { /* we are not running any more */ UE_LOCK(ue); ifp->if_flags &= ~IFF_RUNNING; UE_UNLOCK(ue); /* drain any callouts */ usb_callout_drain(&ue->ue_watchdog); /* detach miibus */ if (ue->ue_miibus != NULL) { device_delete_child(ue->ue_dev, ue->ue_miibus); } /* detach ethernet */ ether_ifdetach(ifp); /* free sysctl */ sysctl_ctx_free(&ue->ue_sysctl_ctx); /* free unit */ devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(ue), ue->ue_unit); } /* free taskqueue, if any */ usb_proc_free(&ue->ue_tq); }
static void ue_attach_post_task(struct usb_proc_msg *_task) { struct usb_ether_cfg_task *task = (struct usb_ether_cfg_task *)_task; struct usb_ether *ue = task->ue; struct ifnet *ifp = uether_getifp(ue); int error; char num[14]; /* sufficient for 32 bits */ /* first call driver's post attach routine */ ue->ue_methods->ue_attach_post(ue); UE_UNLOCK(ue); KKASSERT(!lockowned(ue->ue_lock)); ue->ue_unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(ue), 0); usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_lock, 0); sysctl_ctx_init(&ue->ue_sysctl_ctx); KKASSERT(!lockowned(ue->ue_lock)); error = 0; ifp->if_softc = ue; if_initname(ifp, "ue", ue->ue_unit); if (ue->ue_methods->ue_attach_post_sub != NULL) { error = ue->ue_methods->ue_attach_post_sub(ue); KKASSERT(!lockowned(ue->ue_lock)); } else { ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; if (ue->ue_methods->ue_ioctl != NULL) ifp->if_ioctl = ue->ue_methods->ue_ioctl; else ifp->if_ioctl = uether_ioctl; ifp->if_start = ue_start; ifp->if_init = ue_init; ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); ifq_set_ready(&ifp->if_snd); if (ue->ue_methods->ue_mii_upd != NULL && ue->ue_methods->ue_mii_sts != NULL) { error = mii_phy_probe(ue->ue_dev, &ue->ue_miibus, ue_ifmedia_upd, ue->ue_methods->ue_mii_sts); } } if (error) { device_printf(ue->ue_dev, "attaching PHYs failed\n"); goto fail; } if_printf(ifp, "<USB Ethernet> on %s\n", device_get_nameunit(ue->ue_dev)); ether_ifattach(ifp, ue->ue_eaddr, NULL); /* Tell upper layer we support VLAN oversized frames. */ if (ifp->if_capabilities & IFCAP_VLAN_MTU) ifp->if_hdrlen = sizeof(struct ether_vlan_header); ksnprintf(num, sizeof(num), "%u", ue->ue_unit); ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx, &SYSCTL_NODE_CHILDREN(_net, ue), OID_AUTO, num, CTLFLAG_RD, NULL, ""); SYSCTL_ADD_PROC(&ue->ue_sysctl_ctx, SYSCTL_CHILDREN(ue->ue_sysctl_oid), OID_AUTO, "%parent", CTLTYPE_STRING | CTLFLAG_RD, ue, 0, ue_sysctl_parent, "A", "parent device"); KKASSERT(!lockowned(ue->ue_lock)); UE_LOCK(ue); return; fail: devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(ue), ue->ue_unit); UE_LOCK(ue); return; }