diff options
author | Stephen M. Cameron <scameron@beardog.cce.hp.com> | 2010-02-26 17:01:22 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2010-02-28 13:42:31 -0500 |
commit | 49fc5601ea3bf9625d699dc777f80f72e8126c0b (patch) | |
tree | 8d25702d79661c174567ea24c9bf44dd59c7ff28 /drivers | |
parent | 1b7d0d28ad82cbd5650c26ec8e370176b112e407 (diff) |
cciss: factor out scatter gather chain block allocation and freeing
cciss: factor out scatter gather chain block allocation and freeing
Rationale is that I want to use this code from the scsi half of the
driver.
Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers')
-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 |