--- a/sys/dev/raid/tws/tws.c +++ b/sys/dev/raid/tws/tws.c @@ -312,6 +312,17 @@ sc->irq_res, sc->intr_handle))) TWS_TRACE(sc, "bus teardown intr", 0, error); } + /* Cancel any pending driver callouts (cf. tws_detach). */ + callout_cancel(&sc->print_stats_handle); + callout_cancel(&sc->reset_cb_handle); + callout_cancel(&sc->reinit_handle); + if (sc->reqs) { + int i; + for (i = 0; i < tws_queue_depth; i++) + callout_cancel(&sc->reqs[i].thandle); + } + if (sc->intr_type == PCI_INTR_TYPE_MSI) + pci_release_msi(sc->tws_dev); destroy_dev(sc->tws_cdev); dev_ops_remove_minor(&tws_ops, device_get_unit(sc->tws_dev)); attach_fail_3: @@ -334,6 +345,49 @@ TWS_TRACE(sc, "bus release2 ", 0, sc->reg_res_id); } attach_fail_1: + /* Free everything allocated so far (tws_init, tws_init_reqs, queues). */ + if (sc->reqs) { + int i; + for (i = 0; i < tws_queue_depth; i++) + if (sc->reqs[i].dma_map) + bus_dmamap_destroy(sc->data_tag, sc->reqs[i].dma_map); + kfree(sc->reqs, M_TWS); + sc->reqs = NULL; + } + if (sc->sense_bufs) { + kfree(sc->sense_bufs, M_TWS); + sc->sense_bufs = NULL; + } + if (sc->scan_ccb) { + xpt_free_ccb(&sc->scan_ccb->ccb_h); + sc->scan_ccb = NULL; + } + if (sc->aen_q.q) { + kfree(sc->aen_q.q, M_TWS); + sc->aen_q.q = NULL; + } + if (sc->trace_q.q) { + kfree(sc->trace_q.q, M_TWS); + sc->trace_q.q = NULL; + } + if (sc->cmd_map) { + bus_dmamap_unload(sc->cmd_tag, sc->cmd_map); + bus_dmamem_free(sc->cmd_tag, sc->dma_mem, sc->cmd_map); + sc->dma_mem = NULL; + sc->cmd_map = NULL; + } + if (sc->data_tag) { + bus_dma_tag_destroy(sc->data_tag); + sc->data_tag = NULL; + } + if (sc->cmd_tag) { + bus_dma_tag_destroy(sc->cmd_tag); + sc->cmd_tag = NULL; + } + if (sc->parent_tag) { + bus_dma_tag_destroy(sc->parent_tag); + sc->parent_tag = NULL; + } lockuninit(&sc->q_lock); lockuninit(&sc->sim_lock); lockuninit(&sc->gen_lock); @@ -348,6 +402,7 @@ { struct tws_softc *sc = device_get_softc(dev); int error; + int i; u_int32_t reg; TWS_TRACE_DEBUG(sc, "entry", 0, 0); @@ -395,11 +450,27 @@ TWS_TRACE(sc, "bus release mem resource", 0, sc->reg_res_id); } - kfree(sc->reqs, M_TWS); + if (sc->reqs) { + for (i = 0; i < tws_queue_depth; i++) + if (sc->reqs[i].dma_map) + bus_dmamap_destroy(sc->data_tag, sc->reqs[i].dma_map); + kfree(sc->reqs, M_TWS); + sc->reqs = NULL; + } kfree(sc->sense_bufs, M_TWS); xpt_free_ccb(&sc->scan_ccb->ccb_h); kfree(sc->aen_q.q, M_TWS); kfree(sc->trace_q.q, M_TWS); + if (sc->cmd_map) { + bus_dmamap_unload(sc->cmd_tag, sc->cmd_map); + bus_dmamem_free(sc->cmd_tag, sc->dma_mem, sc->cmd_map); + } + if (sc->data_tag) + bus_dma_tag_destroy(sc->data_tag); + if (sc->cmd_tag) + bus_dma_tag_destroy(sc->cmd_tag); + if (sc->parent_tag) + bus_dma_tag_destroy(sc->parent_tag); lockuninit(&sc->q_lock); lockuninit(&sc->sim_lock); lockuninit(&sc->gen_lock);