summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cce.hp.com>2009-11-23 09:31:48 +0100
committerJens Axboe <jens.axboe@oracle.com>2009-11-23 09:31:48 +0100
commitd61c42690c6e2ff093a3d01338dad49f35b1e27b (patch)
treeb8c419f13c09f7f5cde0b85c3f11e1fe7635a3c8 /drivers/block
parent87038c2d5bda2418fda8b1456a0ae81cc3ff5bd8 (diff)
downloadlinux-d61c42690c6e2ff093a3d01338dad49f35b1e27b.tar.gz
linux-d61c42690c6e2ff093a3d01338dad49f35b1e27b.tar.bz2
linux-d61c42690c6e2ff093a3d01338dad49f35b1e27b.zip
cciss: fix scatter gather cleanup problems
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>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/cciss.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index eab81c6c0ca5..873e594860d3 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -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