/* * Bus independant device detachment routine. Makes sure all * allocated resources are freed, callouts disabled and waiting * processes unblocked. */ int cmx_detach(device_t dev) { struct cmx_softc *sc = device_get_softc(dev); DEBUG_printf(dev, "called\n"); sc->dying = 1; CMX_LOCK(sc); if (sc->polling) { DEBUG_printf(sc->dev, "disabling polling\n"); callout_stop(&sc->ch); sc->polling = 0; CMX_UNLOCK(sc); KNOTE(&sc->kq.ki_note, 0); } else { CMX_UNLOCK(sc); } wakeup(sc); DEBUG_printf(dev, "releasing resources\n"); cmx_release_resources(dev); dev_ops_remove_minor(&cmx_ops, device_get_unit(dev)); return 0; }
static int urio_detach(device_t self) { DPRINTF(("%s: disconnected\n", device_get_nameunit(self))); dev_ops_remove_minor(&urio_ops, /*-1, */device_get_unit(self)); /* XXX not implemented yet */ device_set_desc(self, NULL); return 0; }
void mps_detach_user(struct mps_softc *sc) { /* XXX: do a purge of pending requests? */ destroy_dev(sc->mps_cdev); dev_ops_remove_minor(&mps_ops, device_get_unit(sc->mps_dev)); }
static void ptdtor(struct cam_periph *periph) { struct pt_softc *softc; softc = (struct pt_softc *)periph->softc; devstat_remove_entry(&softc->device_stats); cam_extend_release(ptperiphs, periph->unit_number); xpt_print(periph->path, "removing device entry\n"); dev_ops_remove_minor(&pt_ops, periph->unit_number); kfree(softc, M_DEVBUF); }
/* * Function name: tw_osli_free_resources * Description: Performs clean-up at the time of going down. * * Input: sc -- ptr to OSL internal ctlr context * Output: None * Return value: None */ static TW_VOID tw_osli_free_resources(struct twa_softc *sc) { struct tw_osli_req_context *req; TW_INT32 error = 0; tw_osli_dbg_dprintf(3, sc, "entered"); /* Detach from CAM */ tw_osli_cam_detach(sc); if (sc->req_ctx_buf) while ((req = tw_osli_req_q_remove_head(sc, TW_OSLI_FREE_Q)) != NULL) { lockuninit(req->ioctl_wake_timeout_lock); if ((error = bus_dmamap_destroy(sc->dma_tag, req->dma_map))) tw_osli_dbg_dprintf(1, sc, "dmamap_destroy(dma) returned %d", error); } if ((sc->ioctl_tag) && (sc->ioctl_map)) if ((error = bus_dmamap_destroy(sc->ioctl_tag, sc->ioctl_map))) tw_osli_dbg_dprintf(1, sc, "dmamap_destroy(ioctl) returned %d", error); /* Free all memory allocated so far. */ if (sc->req_ctx_buf) kfree(sc->req_ctx_buf, TW_OSLI_MALLOC_CLASS); if (sc->non_dma_mem) kfree(sc->non_dma_mem, TW_OSLI_MALLOC_CLASS); if (sc->dma_mem) { bus_dmamap_unload(sc->cmd_tag, sc->cmd_map); bus_dmamem_free(sc->cmd_tag, sc->dma_mem, sc->cmd_map); } if (sc->cmd_tag) if ((error = bus_dma_tag_destroy(sc->cmd_tag))) tw_osli_dbg_dprintf(1, sc, "dma_tag_destroy(cmd) returned %d", error); if (sc->dma_tag) if ((error = bus_dma_tag_destroy(sc->dma_tag))) tw_osli_dbg_dprintf(1, sc, "dma_tag_destroy(dma) returned %d", error); if (sc->ioctl_tag) if ((error = bus_dma_tag_destroy(sc->ioctl_tag))) tw_osli_dbg_dprintf(1, sc, "dma_tag_destroy(ioctl) returned %d", error); if (sc->parent_tag) if ((error = bus_dma_tag_destroy(sc->parent_tag))) tw_osli_dbg_dprintf(1, sc, "dma_tag_destroy(parent) returned %d", error); /* Disconnect the interrupt handler. */ if ((error = twa_teardown_intr(sc))) tw_osli_dbg_dprintf(1, sc, "teardown_intr returned %d", error); if (sc->irq_res != NULL) if ((error = bus_release_resource(sc->bus_dev, SYS_RES_IRQ, sc->irq_res_id, sc->irq_res))) tw_osli_dbg_dprintf(1, sc, "release_resource(irq) returned %d", error); if (sc->irq_type == PCI_INTR_TYPE_MSI) pci_release_msi(sc->bus_dev); /* Release the register window mapping. */ if (sc->reg_res != NULL) if ((error = bus_release_resource(sc->bus_dev, SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res))) tw_osli_dbg_dprintf(1, sc, "release_resource(io) returned %d", error); /* Destroy the control device. */ if (sc->ctrl_dev != NULL) destroy_dev(sc->ctrl_dev); dev_ops_remove_minor(&twa_ops, device_get_unit(sc->bus_dev)); }
static int tws_detach(device_t dev) { struct tws_softc *sc = device_get_softc(dev); int error, i; u_int32_t reg; TWS_TRACE_DEBUG(sc, "entry", 0, 0); lockmgr(&sc->gen_lock, LK_EXCLUSIVE); tws_send_event(sc, TWS_UNINIT_START); lockmgr(&sc->gen_lock, LK_RELEASE); /* needs to disable interrupt before detaching from cam */ tws_turn_off_interrupts(sc); /* clear door bell */ tws_write_reg(sc, TWS_I2O0_HOBDBC, ~0, 4); reg = tws_read_reg(sc, TWS_I2O0_HIMASK, 4); TWS_TRACE_DEBUG(sc, "turn-off-intr", reg, 0); sc->obfl_q_overrun = false; tws_init_connect(sc, 1); /* Teardown the state in our softc created in our attach routine. */ /* Disconnect the interrupt handler. */ for(i=0;i<sc->irqs;i++) { if (sc->intr_handle[i]) { if ((error = bus_teardown_intr(sc->tws_dev, sc->irq_res[i], sc->intr_handle[i]))) TWS_TRACE(sc, "bus teardown intr", 0, error); } } /* Release irq resource */ for(i=0;i<sc->irqs;i++) { if ( sc->irq_res[i] ){ if (bus_release_resource(sc->tws_dev, SYS_RES_IRQ, sc->irq_res_id[i], sc->irq_res[i])) TWS_TRACE(sc, "bus release irq resource", i, sc->irq_res_id[i]); } } if ( sc->intr_type == TWS_MSI ) { pci_release_msi(sc->tws_dev); } tws_cam_detach(sc); /* Release memory resource */ if ( sc->mfa_res ){ if (bus_release_resource(sc->tws_dev, SYS_RES_MEMORY, sc->mfa_res_id, sc->mfa_res)) TWS_TRACE(sc, "bus release mem resource", 0, sc->mfa_res_id); } if ( sc->reg_res ){ if (bus_release_resource(sc->tws_dev, SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res)) TWS_TRACE(sc, "bus release mem resource", 0, sc->reg_res_id); } kfree(sc->reqs, M_TWS); kfree(sc->sense_bufs, M_TWS); kfree(sc->scan_ccb, M_TWS); kfree(sc->aen_q.q, M_TWS); kfree(sc->trace_q.q, M_TWS); lockuninit(&sc->q_lock); lockuninit(&sc->sim_lock); lockuninit(&sc->gen_lock); lockuninit(&sc->io_lock); destroy_dev(sc->tws_cdev); dev_ops_remove_minor(&tws_ops, device_get_unit(sc->tws_dev)); sysctl_ctx_free(&sc->tws_clist); return (0); }
static int tws_attach(device_t dev) { struct tws_softc *sc = device_get_softc(dev); u_int32_t cmd, bar; int error=0,i; /* no tracing yet */ /* Look up our softc and initialize its fields. */ sc->tws_dev = dev; sc->device_id = pci_get_device(dev); sc->subvendor_id = pci_get_subvendor(dev); sc->subdevice_id = pci_get_subdevice(dev); /* Intialize mutexes */ lockinit(&sc->q_lock, "tws_q_lock", 0, LK_CANRECURSE); lockinit(&sc->sim_lock, "tws_sim_lock", 0, LK_CANRECURSE); lockinit(&sc->gen_lock, "tws_gen_lock", 0, LK_CANRECURSE); lockinit(&sc->io_lock, "tws_io_lock", 0, LK_CANRECURSE); if ( tws_init_trace_q(sc) == FAILURE ) kprintf("trace init failure\n"); /* send init event */ lockmgr(&sc->gen_lock, LK_EXCLUSIVE); tws_send_event(sc, TWS_INIT_START); lockmgr(&sc->gen_lock, LK_RELEASE); #if _BYTE_ORDER == _BIG_ENDIAN TWS_TRACE(sc, "BIG endian", 0, 0); #endif /* sysctl context setup */ sysctl_ctx_init(&sc->tws_clist); sc->tws_oidp = SYSCTL_ADD_NODE(&sc->tws_clist, SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, device_get_nameunit(dev), CTLFLAG_RD, 0, ""); if ( sc->tws_oidp == NULL ) { tws_log(sc, SYSCTL_TREE_NODE_ADD); goto attach_fail_1; } SYSCTL_ADD_STRING(&sc->tws_clist, SYSCTL_CHILDREN(sc->tws_oidp), OID_AUTO, "driver_version", CTLFLAG_RD, TWS_DRIVER_VERSION_STRING, 0, "TWS driver version"); cmd = pci_read_config(dev, PCIR_COMMAND, 2); if ( (cmd & PCIM_CMD_PORTEN) == 0) { tws_log(sc, PCI_COMMAND_READ); goto attach_fail_1; } /* Force the busmaster enable bit on. */ cmd |= PCIM_CMD_BUSMASTEREN; pci_write_config(dev, PCIR_COMMAND, cmd, 2); bar = pci_read_config(dev, TWS_PCI_BAR0, 4); TWS_TRACE_DEBUG(sc, "bar0 ", bar, 0); bar = pci_read_config(dev, TWS_PCI_BAR1, 4); bar = bar & ~TWS_BIT2; TWS_TRACE_DEBUG(sc, "bar1 ", bar, 0); /* MFA base address is BAR2 register used for * push mode. Firmware will evatualy move to * pull mode during witch this needs to change */ #ifndef TWS_PULL_MODE_ENABLE sc->mfa_base = (u_int64_t)pci_read_config(dev, TWS_PCI_BAR2, 4); sc->mfa_base = sc->mfa_base & ~TWS_BIT2; TWS_TRACE_DEBUG(sc, "bar2 ", sc->mfa_base, 0); #endif /* allocate MMIO register space */ sc->reg_res_id = TWS_PCI_BAR1; /* BAR1 offset */ if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE)) == NULL) { tws_log(sc, ALLOC_MEMORY_RES); goto attach_fail_1; } sc->bus_tag = rman_get_bustag(sc->reg_res); sc->bus_handle = rman_get_bushandle(sc->reg_res); #ifndef TWS_PULL_MODE_ENABLE /* Allocate bus space for inbound mfa */ sc->mfa_res_id = TWS_PCI_BAR2; /* BAR2 offset */ if ((sc->mfa_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &(sc->mfa_res_id), 0, ~0, 0x100000, RF_ACTIVE)) == NULL) { tws_log(sc, ALLOC_MEMORY_RES); goto attach_fail_2; } sc->bus_mfa_tag = rman_get_bustag(sc->mfa_res); sc->bus_mfa_handle = rman_get_bushandle(sc->mfa_res); #endif /* Allocate and register our interrupt. */ sc->intr_type = TWS_INTx; /* default */ if ( tws_enable_msi ) sc->intr_type = TWS_MSI; if ( tws_setup_irq(sc) == FAILURE ) { tws_log(sc, ALLOC_MEMORY_RES); goto attach_fail_3; } /* Init callouts. */ callout_init(&sc->print_stats_handle); callout_init(&sc->reset_cb_handle); callout_init(&sc->reinit_handle); /* * Create a /dev entry for this device. The kernel will assign us * a major number automatically. We use the unit number of this * device as the minor number and name the character device * "tws<unit>". */ sc->tws_cdev = make_dev(&tws_ops, device_get_unit(dev), UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR, "tws%u", device_get_unit(dev)); sc->tws_cdev->si_drv1 = sc; if ( tws_init(sc) == FAILURE ) { tws_log(sc, TWS_INIT_FAILURE); goto attach_fail_4; } if ( tws_init_ctlr(sc) == FAILURE ) { tws_log(sc, TWS_CTLR_INIT_FAILURE); goto attach_fail_4; } if ((error = tws_cam_attach(sc))) { tws_log(sc, TWS_CAM_ATTACH); goto attach_fail_4; } /* send init complete event */ lockmgr(&sc->gen_lock, LK_EXCLUSIVE); tws_send_event(sc, TWS_INIT_COMPLETE); lockmgr(&sc->gen_lock, LK_RELEASE); TWS_TRACE_DEBUG(sc, "attached successfully", 0, sc->device_id); return(0); attach_fail_4: for(i=0;i<sc->irqs;i++) { if (sc->intr_handle[i]) { if ((error = bus_teardown_intr(sc->tws_dev, sc->irq_res[i], sc->intr_handle[i]))) TWS_TRACE(sc, "bus teardown intr", 0, error); } } destroy_dev(sc->tws_cdev); dev_ops_remove_minor(&tws_ops, device_get_unit(sc->tws_dev)); attach_fail_3: for(i=0;i<sc->irqs;i++) { if ( sc->irq_res[i] ){ if (bus_release_resource(sc->tws_dev, SYS_RES_IRQ, sc->irq_res_id[i], sc->irq_res[i])) TWS_TRACE(sc, "bus irq res", 0, 0); } } #ifndef TWS_PULL_MODE_ENABLE attach_fail_2: #endif if ( sc->mfa_res ){ if (bus_release_resource(sc->tws_dev, SYS_RES_MEMORY, sc->mfa_res_id, sc->mfa_res)) TWS_TRACE(sc, "bus release ", 0, sc->mfa_res_id); } if ( sc->reg_res ){ if (bus_release_resource(sc->tws_dev, SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res)) TWS_TRACE(sc, "bus release2 ", 0, sc->reg_res_id); } attach_fail_1: lockuninit(&sc->q_lock); lockuninit(&sc->sim_lock); lockuninit(&sc->gen_lock); lockuninit(&sc->io_lock); sysctl_ctx_free(&sc->tws_clist); return (ENXIO); }