diff options
author | Stephen M. Cameron <scameron@beardog.cce.hp.com> | 2011-05-03 14:54:12 -0500 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2011-05-06 08:23:59 -0600 |
commit | 8a4ec67bd5648beb09d7db988a75835b740e950d (patch) | |
tree | 745a87ec016b79f3cf425f581c38090a4ff8f270 /drivers/block/cciss_scsi.c | |
parent | 063d2cf72ab6101d2dd69bd6fb503b229be70325 (diff) |
cciss: add cciss_tape_cmds module paramter
This is to allow number of commands reserved for use by SCSI tape drives
and medium changers to be adjusted at driver load time via the kernel
parameter cciss_tape_cmds, with a default value of 6, and a range
of 2 - 16 inclusive. Previously, the driver limited the number of
commands which could be queued to the SCSI half of the the driver
to only 2. This is to fix the problem that if you had more than
two tape drives, you couldn't, for example, erase or rewind them all
at the same time.
Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'drivers/block/cciss_scsi.c')
-rw-r--r-- | drivers/block/cciss_scsi.c | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index df793803f5a..696100241a6 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -84,7 +84,6 @@ static struct scsi_host_template cciss_driver_template = { .proc_name = "cciss", .proc_info = cciss_scsi_proc_info, .queuecommand = cciss_scsi_queue_command, - .can_queue = SCSI_CCISS_CAN_QUEUE, .this_id = 7, .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING, @@ -108,16 +107,13 @@ struct cciss_scsi_cmd_stack_elem_t { #pragma pack() -#define CMD_STACK_SIZE (SCSI_CCISS_CAN_QUEUE * \ - CCISS_MAX_SCSI_DEVS_PER_HBA + 2) - // plus two for init time usage - #pragma pack(1) struct cciss_scsi_cmd_stack_t { struct cciss_scsi_cmd_stack_elem_t *pool; - struct cciss_scsi_cmd_stack_elem_t *elem[CMD_STACK_SIZE]; + struct cciss_scsi_cmd_stack_elem_t **elem; dma_addr_t cmd_pool_handle; int top; + int nelems; }; #pragma pack() @@ -191,7 +187,7 @@ scsi_cmd_free(ctlr_info_t *h, CommandList_struct *c) sa = h->scsi_ctlr; stk = &sa->cmd_stack; stk->top++; - if (stk->top >= CMD_STACK_SIZE) { + if (stk->top >= stk->nelems) { dev_err(&h->pdev->dev, "scsi_cmd_free called too many times.\n"); BUG(); @@ -206,13 +202,14 @@ scsi_cmd_stack_setup(ctlr_info_t *h, struct cciss_scsi_adapter_data_t *sa) struct cciss_scsi_cmd_stack_t *stk; size_t size; + stk = &sa->cmd_stack; + stk->nelems = cciss_tape_cmds + 2; sa->cmd_sg_list = cciss_allocate_sg_chain_blocks(h, - h->chainsize, CMD_STACK_SIZE); + h->chainsize, stk->nelems); if (!sa->cmd_sg_list && h->chainsize > 0) return -ENOMEM; - stk = &sa->cmd_stack; - size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; + size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * stk->nelems; /* Check alignment, see cciss_cmd.h near CommandList_struct def. */ BUILD_BUG_ON((sizeof(*stk->pool) % COMMANDLIST_ALIGNMENT) != 0); @@ -221,18 +218,23 @@ scsi_cmd_stack_setup(ctlr_info_t *h, struct cciss_scsi_adapter_data_t *sa) pci_alloc_consistent(h->pdev, size, &stk->cmd_pool_handle); if (stk->pool == NULL) { - cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE); + cciss_free_sg_chain_blocks(sa->cmd_sg_list, stk->nelems); sa->cmd_sg_list = NULL; return -ENOMEM; } - - for (i=0; i<CMD_STACK_SIZE; i++) { + stk->elem = kmalloc(sizeof(stk->elem[0]) * stk->nelems, GFP_KERNEL); + if (!stk->elem) { + pci_free_consistent(h->pdev, size, stk->pool, + stk->cmd_pool_handle); + return -1; + } + for (i = 0; i < stk->nelems; i++) { stk->elem[i] = &stk->pool[i]; stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle + (sizeof(struct cciss_scsi_cmd_stack_elem_t) * i)); stk->elem[i]->cmdindex = i; } - stk->top = CMD_STACK_SIZE-1; + stk->top = stk->nelems-1; return 0; } @@ -245,16 +247,18 @@ scsi_cmd_stack_free(ctlr_info_t *h) sa = h->scsi_ctlr; stk = &sa->cmd_stack; - if (stk->top != CMD_STACK_SIZE-1) { + if (stk->top != stk->nelems-1) { dev_warn(&h->pdev->dev, "bug: %d scsi commands are still outstanding.\n", - CMD_STACK_SIZE - stk->top); + stk->nelems - stk->top); } - size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; + size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * stk->nelems; pci_free_consistent(h->pdev, size, stk->pool, stk->cmd_pool_handle); stk->pool = NULL; - cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE); + cciss_free_sg_chain_blocks(sa->cmd_sg_list, stk->nelems); + kfree(stk->elem); + stk->elem = NULL; } #if 0 @@ -859,6 +863,7 @@ cciss_scsi_detect(ctlr_info_t *h) sh->io_port = 0; // good enough? FIXME, sh->n_io_port = 0; // I don't think we use these two... sh->this_id = SELF_SCSI_ID; + sh->can_queue = cciss_tape_cmds; sh->sg_tablesize = h->maxsgentries; sh->max_cmd_len = MAX_COMMAND_SIZE; |