⬢ DragonFlyBSD Kernel Audit
DF-4591 / fix.diff
← back to finding ↓ download raw
--- 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);