cciss: Fix scsi tape io with more than 255 scatter gather elements
[linux-flexiantxendom0.git] / drivers / block / cciss_scsi.c
index 3bfbde8..acda773 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -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,25 +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;
        }
-
        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<CMD_STACK_SIZE; i++) {
+       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;
 }
 
@@ -252,16 +247,16 @@ 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;
 }
@@ -833,13 +828,18 @@ static void complete_scsi_command(CommandList_struct *c, int timeout,
                        break;
                        case CMD_UNSOLICITED_ABORT:
                                cmd->result = DID_ABORT << 16;
-                               dev_warn(&h->pdev->dev, "%p aborted do to an "
+                               dev_warn(&h->pdev->dev, "%p aborted due to an "
                                        "unsolicited abort\n", c);
                        break;
                        case CMD_TIMEOUT:
                                cmd->result = DID_TIME_OUT << 16;
                                dev_warn(&h->pdev->dev, "%p timedout\n", c);
                        break;
+                       case CMD_UNABORTABLE:
+                               cmd->result = DID_ERROR << 16;
+                               dev_warn(&h->pdev->dev, "c %p command "
+                                       "unabortable\n", c);
+                       break;
                        default:
                                cmd->result = DID_ERROR << 16;
                                dev_warn(&h->pdev->dev,
@@ -863,8 +863,10 @@ 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;
+       sh->max_sectors = h->cciss_max_sectors;
 
        ((struct cciss_scsi_adapter_data_t *) 
                h->scsi_ctlr)->scsi_host = sh;
@@ -1016,11 +1018,15 @@ cciss_scsi_interpret_error(ctlr_info_t *h, CommandList_struct *c)
                break;
                case CMD_UNSOLICITED_ABORT:
                        dev_warn(&h->pdev->dev,
-                               "%p aborted do to an unsolicited abort\n", c);
+                               "%p aborted due to an unsolicited abort\n", c);
                break;
                case CMD_TIMEOUT:
                        dev_warn(&h->pdev->dev, "%p timedout\n", c);
                break;
+               case CMD_UNABORTABLE:
+                       dev_warn(&h->pdev->dev,
+                               "%p unabortable\n", c);
+               break;
                default:
                        dev_warn(&h->pdev->dev,
                                "%p returned unknown status %x\n",
@@ -1405,7 +1411,7 @@ static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c,
        /* track how many SG entries we are using */
        if (request_nsgs > h->maxSG)
                h->maxSG = request_nsgs;
-       c->Header.SGTotal = (__u8) request_nsgs + chained;
+       c->Header.SGTotal = (u16) request_nsgs + chained;
        if (request_nsgs > h->max_cmd_sgentries)
                c->Header.SGList = h->max_cmd_sgentries;
        else
@@ -1715,5 +1721,6 @@ static int  cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
 /* If no tape support, then these become defined out of existence */
 
 #define cciss_scsi_setup(cntl_num)
+#define cciss_engage_scsi(h)
 
 #endif /* CONFIG_CISS_SCSI_TAPE */