aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cce.hp.com>2010-02-26 17:01:22 -0500
committerJens Axboe <jens.axboe@oracle.com>2010-02-28 13:42:31 -0500
commit49fc5601ea3bf9625d699dc777f80f72e8126c0b (patch)
tree8d25702d79661c174567ea24c9bf44dd59c7ff28 /drivers/block
parent1b7d0d28ad82cbd5650c26ec8e370176b112e407 (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/block')
-rw-r--r--drivers/block/cciss.c108
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
260static 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
277static 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;
308clean:
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
262static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", 315static 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