diff options
| -rw-r--r-- | drivers/block/cciss.c | 108 |
1 files changed, 58 insertions, 50 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index cd8c7c20b1c3..eddb916d2908 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -257,6 +257,59 @@ static inline void removeQ(CommandList_struct *c) | |||
| 257 | hlist_del_init(&c->list); | 257 | hlist_del_init(&c->list); |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | static void cciss_free_sg_chain_blocks(struct Cmd_sg_list **cmd_sg_list, | ||
| 261 | int nr_cmds) | ||
| 262 | { | ||
| 263 | int i; | ||
| 264 | |||
| 265 | if (!cmd_sg_list) | ||
| 266 | return; | ||
| 267 | for (i = 0; i < nr_cmds; i++) { | ||
| 268 | if (cmd_sg_list[i]) { | ||
| 269 | kfree(cmd_sg_list[i]->sgchain); | ||
| 270 | kfree(cmd_sg_list[i]); | ||
| 271 | cmd_sg_list[i] = NULL; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | kfree(cmd_sg_list); | ||
| 275 | } | ||
| 276 | |||
| 277 | static struct Cmd_sg_list **cciss_allocate_sg_chain_blocks(ctlr_info_t *h, | ||
| 278 | int chainsize, int nr_cmds) | ||
| 279 | { | ||
| 280 | int j; | ||
| 281 | struct Cmd_sg_list **cmd_sg_list; | ||
| 282 | |||
| 283 | if (chainsize <= 0) | ||
| 284 | return NULL; | ||
| 285 | |||
| 286 | cmd_sg_list = kmalloc(sizeof(*cmd_sg_list) * nr_cmds, GFP_KERNEL); | ||
| 287 | if (!cmd_sg_list) | ||
| 288 | return NULL; | ||
| 289 | |||
| 290 | /* Build up chain blocks for each command */ | ||
| 291 | for (j = 0; j < nr_cmds; j++) { | ||
| 292 | cmd_sg_list[j] = kmalloc(sizeof(*cmd_sg_list[j]), GFP_KERNEL); | ||
| 293 | if (!cmd_sg_list[j]) { | ||
| 294 | dev_err(&h->pdev->dev, "Cannot get memory " | ||
| 295 | "for chain block.\n"); | ||
| 296 | goto clean; | ||
| 297 | } | ||
| 298 | /* Need a block of chainsized s/g elements. */ | ||
| 299 | cmd_sg_list[j]->sgchain = kmalloc((chainsize * | ||
| 300 | sizeof(SGDescriptor_struct)), GFP_KERNEL); | ||
| 301 | if (!cmd_sg_list[j]->sgchain) { | ||
| 302 | dev_err(&h->pdev->dev, "Cannot get memory " | ||
| 303 | "for s/g chains.\n"); | ||
| 304 | goto clean; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | return cmd_sg_list; | ||
| 308 | clean: | ||
| 309 | cciss_free_sg_chain_blocks(cmd_sg_list, nr_cmds); | ||
| 310 | return NULL; | ||
| 311 | } | ||
| 312 | |||
| 260 | #include "cciss_scsi.c" /* For SCSI tape support */ | 313 | #include "cciss_scsi.c" /* For SCSI tape support */ |
| 261 | 314 | ||
| 262 | static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", | 315 | static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", |
| @@ -4238,37 +4291,10 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
| 4238 | goto clean4; | 4291 | goto clean4; |
| 4239 | } | 4292 | } |
| 4240 | } | 4293 | } |
| 4241 | hba[i]->cmd_sg_list = kmalloc(sizeof(struct Cmd_sg_list *) * | 4294 | hba[i]->cmd_sg_list = cciss_allocate_sg_chain_blocks(hba[i], |
| 4242 | hba[i]->nr_cmds, | 4295 | hba[i]->chainsize, hba[i]->nr_cmds); |
| 4243 | GFP_KERNEL); | 4296 | if (!hba[i]->cmd_sg_list && hba[i]->chainsize > 0) |
| 4244 | if (!hba[i]->cmd_sg_list) { | ||
| 4245 | printk(KERN_ERR "cciss%d: Cannot get memory for " | ||
| 4246 | "s/g chaining.\n", i); | ||
| 4247 | goto clean4; | 4297 | goto clean4; |
| 4248 | } | ||
| 4249 | /* Build up chain blocks for each command */ | ||
| 4250 | if (hba[i]->chainsize > 0) { | ||
| 4251 | for (j = 0; j < hba[i]->nr_cmds; j++) { | ||
| 4252 | hba[i]->cmd_sg_list[j] = | ||
| 4253 | kmalloc(sizeof(struct Cmd_sg_list), | ||
| 4254 | GFP_KERNEL); | ||
| 4255 | if (!hba[i]->cmd_sg_list[j]) { | ||
| 4256 | printk(KERN_ERR "cciss%d: Cannot get memory " | ||
| 4257 | "for chain block.\n", i); | ||
| 4258 | goto clean4; | ||
| 4259 | } | ||
| 4260 | /* Need a block of chainsized s/g elements. */ | ||
| 4261 | hba[i]->cmd_sg_list[j]->sgchain = | ||
| 4262 | kmalloc((hba[i]->chainsize * | ||
| 4263 | sizeof(SGDescriptor_struct)), | ||
| 4264 | GFP_KERNEL); | ||
| 4265 | if (!hba[i]->cmd_sg_list[j]->sgchain) { | ||
| 4266 | printk(KERN_ERR "cciss%d: Cannot get memory " | ||
| 4267 | "for s/g chains\n", i); | ||
| 4268 | goto clean4; | ||
| 4269 | } | ||
| 4270 | } | ||
| 4271 | } | ||
| 4272 | 4298 | ||
| 4273 | spin_lock_init(&hba[i]->lock); | 4299 | spin_lock_init(&hba[i]->lock); |
| 4274 | 4300 | ||
| @@ -4327,16 +4353,7 @@ clean4: | |||
| 4327 | for (k = 0; k < hba[i]->nr_cmds; k++) | 4353 | for (k = 0; k < hba[i]->nr_cmds; k++) |
| 4328 | kfree(hba[i]->scatter_list[k]); | 4354 | kfree(hba[i]->scatter_list[k]); |
| 4329 | kfree(hba[i]->scatter_list); | 4355 | kfree(hba[i]->scatter_list); |
| 4330 | /* Only free up extra s/g lists if controller supports them */ | 4356 | cciss_free_sg_chain_blocks(hba[i]->cmd_sg_list, hba[i]->nr_cmds); |
| 4331 | if (hba[i]->chainsize > 0) { | ||
| 4332 | for (j = 0; j < hba[i]->nr_cmds; j++) { | ||
| 4333 | if (hba[i]->cmd_sg_list[j]) { | ||
| 4334 | kfree(hba[i]->cmd_sg_list[j]->sgchain); | ||
| 4335 | kfree(hba[i]->cmd_sg_list[j]); | ||
| 4336 | } | ||
| 4337 | } | ||
| 4338 | kfree(hba[i]->cmd_sg_list); | ||
| 4339 | } | ||
| 4340 | if (hba[i]->cmd_pool) | 4357 | if (hba[i]->cmd_pool) |
| 4341 | pci_free_consistent(hba[i]->pdev, | 4358 | pci_free_consistent(hba[i]->pdev, |
| 4342 | hba[i]->nr_cmds * sizeof(CommandList_struct), | 4359 | hba[i]->nr_cmds * sizeof(CommandList_struct), |
| @@ -4454,16 +4471,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) | |||
| 4454 | for (j = 0; j < hba[i]->nr_cmds; j++) | 4471 | for (j = 0; j < hba[i]->nr_cmds; j++) |
| 4455 | kfree(hba[i]->scatter_list[j]); | 4472 | kfree(hba[i]->scatter_list[j]); |
| 4456 | kfree(hba[i]->scatter_list); | 4473 | kfree(hba[i]->scatter_list); |
| 4457 | /* Only free up extra s/g lists if controller supports them */ | 4474 | cciss_free_sg_chain_blocks(hba[i]->cmd_sg_list, hba[i]->nr_cmds); |
| 4458 | if (hba[i]->chainsize > 0) { | ||
| 4459 | for (j = 0; j < hba[i]->nr_cmds; j++) { | ||
| 4460 | if (hba[i]->cmd_sg_list[j]) { | ||
| 4461 | kfree(hba[i]->cmd_sg_list[j]->sgchain); | ||
| 4462 | kfree(hba[i]->cmd_sg_list[j]); | ||
| 4463 | } | ||
| 4464 | } | ||
| 4465 | kfree(hba[i]->cmd_sg_list); | ||
| 4466 | } | ||
| 4467 | /* | 4475 | /* |
| 4468 | * Deliberately omit pci_disable_device(): it does something nasty to | 4476 | * Deliberately omit pci_disable_device(): it does something nasty to |
| 4469 | * Smart Array controllers that pci_enable_device does not undo | 4477 | * Smart Array controllers that pci_enable_device does not undo |
