]> err.no Git - linux-2.6/blobdiff - drivers/scsi/megaraid.c
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[linux-2.6] / drivers / scsi / megaraid.c
index 6f308ebe3e797857d02baae2679c96db8fd8bfbd..dfea346b00a559975cc83853bafbf4f59dbcebd9 100644 (file)
@@ -362,6 +362,7 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
        adapter_t       *adapter;
        scb_t   *scb;
        int     busy=0;
+       unsigned long flags;
 
        adapter = (adapter_t *)scmd->device->host->hostdata;
 
@@ -377,6 +378,7 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
         * return 0 in that case.
         */
 
+       spin_lock_irqsave(&adapter->lock, flags);
        scb = mega_build_cmd(adapter, scmd, &busy);
 
        if(scb) {
@@ -393,6 +395,7 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
                }
                return 0;
        }
+       spin_unlock_irqrestore(&adapter->lock, flags);
 
        return busy;
 }
@@ -621,8 +624,6 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy)
        if(islogical) {
                switch (cmd->cmnd[0]) {
                case TEST_UNIT_READY:
-                       memset(cmd->request_buffer, 0, cmd->request_bufflen);
-
 #if MEGA_HAVE_CLUSTERING
                        /*
                         * Do we support clustering and is the support enabled
@@ -652,11 +653,28 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy)
                        return NULL;
 #endif
 
-               case MODE_SENSE:
+               case MODE_SENSE: {
+                       char *buf;
+
+                       if (cmd->use_sg) {
+                               struct scatterlist *sg;
+
+                               sg = (struct scatterlist *)cmd->request_buffer;
+                               buf = kmap_atomic(sg->page, KM_IRQ0) +
+                                       sg->offset;
+                       } else
+                               buf = cmd->request_buffer;
                        memset(cmd->request_buffer, 0, cmd->cmnd[4]);
+                       if (cmd->use_sg) {
+                               struct scatterlist *sg;
+
+                               sg = (struct scatterlist *)cmd->request_buffer;
+                               kunmap_atomic(buf - sg->offset, KM_IRQ0);
+                       }
                        cmd->result = (DID_OK << 16);
                        cmd->scsi_done(cmd);
                        return NULL;
+               }
 
                case READ_CAPACITY:
                case INQUIRY:
@@ -1668,7 +1686,7 @@ mega_rundoneq (adapter_t *adapter)
 
        list_for_each(pos, &adapter->completed_list) {
 
-               Scsi_Pointer* spos = (Scsi_Pointer *)pos;
+               struct scsi_pointer* spos = (struct scsi_pointer *)pos;
 
                cmd = list_entry(spos, Scsi_Cmnd, SCp);
                cmd->scsi_done(cmd);
@@ -1685,14 +1703,23 @@ mega_rundoneq (adapter_t *adapter)
 static void
 mega_free_scb(adapter_t *adapter, scb_t *scb)
 {
+       unsigned long length;
+
        switch( scb->dma_type ) {
 
        case MEGA_DMA_TYPE_NONE:
                break;
 
        case MEGA_BULK_DATA:
+               if (scb->cmd->use_sg == 0)
+                       length = scb->cmd->request_bufflen;
+               else {
+                       struct scatterlist *sgl =
+                               (struct scatterlist *)scb->cmd->request_buffer;
+                       length = sgl->length;
+               }
                pci_unmap_page(adapter->dev, scb->dma_h_bulkdata,
-                       scb->cmd->request_bufflen, scb->dma_direction);
+                              length, scb->dma_direction);
                break;
 
        case MEGA_SGLIST:
@@ -1741,6 +1768,7 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
        struct scatterlist      *sgl;
        struct page     *page;
        unsigned long   offset;
+       unsigned int    length;
        Scsi_Cmnd       *cmd;
        int     sgcnt;
        int     idx;
@@ -1748,14 +1776,23 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
        cmd = scb->cmd;
 
        /* Scatter-gather not used */
-       if( !cmd->use_sg ) {
-
-               page = virt_to_page(cmd->request_buffer);
-               offset = offset_in_page(cmd->request_buffer);
+       if( cmd->use_sg == 0 || (cmd->use_sg == 1 && 
+                                !adapter->has_64bit_addr)) {
+
+               if (cmd->use_sg == 0) {
+                       page = virt_to_page(cmd->request_buffer);
+                       offset = offset_in_page(cmd->request_buffer);
+                       length = cmd->request_bufflen;
+               } else {
+                       sgl = (struct scatterlist *)cmd->request_buffer;
+                       page = sgl->page;
+                       offset = sgl->offset;
+                       length = sgl->length;
+               }
 
                scb->dma_h_bulkdata = pci_map_page(adapter->dev,
                                                  page, offset,
-                                                 cmd->request_bufflen,
+                                                 length,
                                                  scb->dma_direction);
                scb->dma_type = MEGA_BULK_DATA;
 
@@ -1765,14 +1802,14 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
                 */
                if( adapter->has_64bit_addr ) {
                        scb->sgl64[0].address = scb->dma_h_bulkdata;
-                       scb->sgl64[0].length = cmd->request_bufflen;
+                       scb->sgl64[0].length = length;
                        *buf = (u32)scb->sgl_dma_addr;
-                       *len = (u32)cmd->request_bufflen;
+                       *len = (u32)length;
                        return 1;
                }
                else {
                        *buf = (u32)scb->dma_h_bulkdata;
-                       *len = (u32)cmd->request_bufflen;
+                       *len = (u32)length;
                }
                return 0;
        }
@@ -1791,27 +1828,23 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
 
        if( sgcnt > adapter->sglen ) BUG();
 
+       *len = 0;
+
        for( idx = 0; idx < sgcnt; idx++, sgl++ ) {
 
                if( adapter->has_64bit_addr ) {
                        scb->sgl64[idx].address = sg_dma_address(sgl);
-                       scb->sgl64[idx].length = sg_dma_len(sgl);
+                       *len += scb->sgl64[idx].length = sg_dma_len(sgl);
                }
                else {
                        scb->sgl[idx].address = sg_dma_address(sgl);
-                       scb->sgl[idx].length = sg_dma_len(sgl);
+                       *len += scb->sgl[idx].length = sg_dma_len(sgl);
                }
        }
 
        /* Reset pointer and length fields */
        *buf = scb->sgl_dma_addr;
 
-       /*
-        * For passthru command, dataxferlen must be set, even for commands
-        * with a sg list
-        */
-       *len = (u32)cmd->request_bufflen;
-
        /* Return count of SG requests */
        return sgcnt;
 }
@@ -1951,7 +1984,7 @@ megaraid_reset(struct scsi_cmnd *cmd)
        mc.cmd = MEGA_CLUSTER_CMD;
        mc.opcode = MEGA_RESET_RESERVATIONS;
 
-       if( mega_internal_command(adapter, LOCK_INT, &mc, NULL) != 0 ) {
+       if( mega_internal_command(adapter, &mc, NULL) != 0 ) {
                printk(KERN_WARNING
                                "megaraid: reservation reset failed.\n");
        }
@@ -2981,7 +3014,7 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end )
                mc.cmd = FC_NEW_CONFIG;
                mc.opcode = OP_DCMD_READ_CONFIG;
 
-               if( mega_internal_command(adapter, LOCK_INT, &mc, NULL) ) {
+               if( mega_internal_command(adapter, &mc, NULL) ) {
 
                        len = sprintf(page, "40LD read config failed.\n");
 
@@ -2999,11 +3032,11 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end )
        else {
                mc.cmd = NEW_READ_CONFIG_8LD;
 
-               if( mega_internal_command(adapter, LOCK_INT, &mc, NULL) ) {
+               if( mega_internal_command(adapter, &mc, NULL) ) {
 
                        mc.cmd = READ_CONFIG_8LD;
 
-                       if( mega_internal_command(adapter, LOCK_INT, &mc,
+                       if( mega_internal_command(adapter, &mc,
                                                NULL) ){
 
                                len = sprintf(page,
@@ -3602,7 +3635,7 @@ megadev_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
                        /*
                         * Issue the command
                         */
-                       mega_internal_command(adapter, LOCK_INT, &mc, pthru);
+                       mega_internal_command(adapter, &mc, pthru);
 
                        rval = mega_n_to_m((void __user *)arg, &mc);
 
@@ -3685,7 +3718,7 @@ freemem_and_return:
                        /*
                         * Issue the command
                         */
-                       mega_internal_command(adapter, LOCK_INT, &mc, NULL);
+                       mega_internal_command(adapter, &mc, NULL);
 
                        rval = mega_n_to_m((void __user *)arg, &mc);
 
@@ -4204,7 +4237,7 @@ mega_do_del_logdrv(adapter_t *adapter, int logdrv)
        mc.opcode = OP_DEL_LOGDRV;
        mc.subopcode = logdrv;
 
-       rval = mega_internal_command(adapter, LOCK_INT, &mc, NULL);
+       rval = mega_internal_command(adapter, &mc, NULL);
 
        /* log this event */
        if(rval) {
@@ -4337,7 +4370,7 @@ mega_adapinq(adapter_t *adapter, dma_addr_t dma_handle)
 
        mc.xferaddr = (u32)dma_handle;
 
-       if ( mega_internal_command(adapter, LOCK_INT, &mc, NULL) != 0 ) {
+       if ( mega_internal_command(adapter, &mc, NULL) != 0 ) {
                return -1;
        }
 
@@ -4405,7 +4438,7 @@ mega_internal_dev_inquiry(adapter_t *adapter, u8 ch, u8 tgt,
        mc.cmd = MEGA_MBOXCMD_PASSTHRU;
        mc.xferaddr = (u32)pthru_dma_handle;
 
-       rval = mega_internal_command(adapter, LOCK_INT, &mc, pthru);
+       rval = mega_internal_command(adapter, &mc, pthru);
 
        pci_free_consistent(pdev, sizeof(mega_passthru), pthru,
                        pthru_dma_handle);
@@ -4419,7 +4452,6 @@ mega_internal_dev_inquiry(adapter_t *adapter, u8 ch, u8 tgt,
 /**
  * mega_internal_command()
  * @adapter - pointer to our soft state
- * @ls - the scope of the exclusion lock.
  * @mc - the mailbox command
  * @pthru - Passthru structure for DCDB commands
  *
@@ -4433,8 +4465,7 @@ mega_internal_dev_inquiry(adapter_t *adapter, u8 ch, u8 tgt,
  * Note: parameter 'pthru' is null for non-passthru commands.
  */
 static int
-mega_internal_command(adapter_t *adapter, lockscope_t ls, megacmd_t *mc,
-               mega_passthru *pthru )
+mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
 {
        Scsi_Cmnd       *scmd;
        struct  scsi_device *sdev;
@@ -4478,15 +4509,8 @@ mega_internal_command(adapter_t *adapter, lockscope_t ls, megacmd_t *mc,
 
        scb->idx = CMDID_INT_CMDS;
 
-       /*
-        * Get the lock only if the caller has not acquired it already
-        */
-       if( ls == LOCK_INT ) spin_lock_irqsave(&adapter->lock, flags);
-
        megaraid_queue(scmd, mega_internal_done);
 
-       if( ls == LOCK_INT ) spin_unlock_irqrestore(&adapter->lock, flags);
-
        wait_for_completion(&adapter->int_waitq);
 
        rval = scmd->result;