DF-4591 / fix.diff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | --- 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); |