cciss: fix scatter gather cleanup problems
authorStephen M. Cameron <scameron@beardog.cce.hp.com>
Mon, 23 Nov 2009 08:31:48 +0000 (09:31 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Mon, 23 Nov 2009 08:31:48 +0000 (09:31 +0100)
On driver unload, only free up the extra scatter gather data if they were
allocated in the first place (the controller supports it) and don't forget
to free up the sg_cmd_list array of pointers.

Signed-off-by: Don Brace <brace@beardog.cce.hp.com>
Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
drivers/block/cciss.c

index eab81c6c0ca5c066f3881fe45291c0dfc76140e9..873e594860d3571f1cd563791c2d970c506ca348 100644 (file)
@@ -4326,10 +4326,15 @@ clean4:
        for (k = 0; k < hba[i]->nr_cmds; k++)
                kfree(hba[i]->scatter_list[k]);
        kfree(hba[i]->scatter_list);
-       for (j = 0; j < hba[i]->nr_cmds; j++) {
-               if (hba[i]->cmd_sg_list[j])
-                       kfree(hba[i]->cmd_sg_list[j]->sgchain);
-               kfree(hba[i]->cmd_sg_list[j]);
+       /* Only free up extra s/g lists if controller supports them */
+       if (hba[i]->chainsize > 0) {
+               for (j = 0; j < hba[i]->nr_cmds; j++) {
+                       if (hba[i]->cmd_sg_list[j]) {
+                               kfree(hba[i]->cmd_sg_list[j]->sgchain);
+                               kfree(hba[i]->cmd_sg_list[j]);
+                       }
+               }
+               kfree(hba[i]->cmd_sg_list);
        }
        if (hba[i]->cmd_pool)
                pci_free_consistent(hba[i]->pdev,
@@ -4448,9 +4453,15 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
        for (j = 0; j < hba[i]->nr_cmds; j++)
                kfree(hba[i]->scatter_list[j]);
        kfree(hba[i]->scatter_list);
-       for (j = 0; j < hba[i]->nr_cmds; j++) {
-               kfree(hba[i]->cmd_sg_list[j]->sgchain);
-               kfree(hba[i]->cmd_sg_list[j]);
+       /* Only free up extra s/g lists if controller supports them */
+       if (hba[i]->chainsize > 0) {
+               for (j = 0; j < hba[i]->nr_cmds; j++) {
+                       if (hba[i]->cmd_sg_list[j]) {
+                               kfree(hba[i]->cmd_sg_list[j]->sgchain);
+                               kfree(hba[i]->cmd_sg_list[j]);
+                       }
+               }
+               kfree(hba[i]->cmd_sg_list);
        }
        /*
         * Deliberately omit pci_disable_device(): it does something nasty to