Merge branch 'bkl/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[safe/jmp/linux-2.6] / drivers / scsi / 53c700.c
index cb02656..80dc3ac 100644 (file)
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/string.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
@@ -175,7 +176,7 @@ STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
 STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt);
 STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt);
 STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt);
-static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth);
+static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth, int reason);
 static int NCR_700_change_queue_type(struct scsi_device *SDpnt, int depth);
 
 STATIC struct device_attribute *NCR_700_dev_attrs[];
@@ -267,8 +268,6 @@ NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata,
                offset = max_offset;
        }
        if(XFERP < min_xferp) {
-               printk(KERN_WARNING "53c700: XFERP %d is less than minium, setting to %d\n",
-                      XFERP,  min_xferp);
                XFERP =  min_xferp;
        }
        return (offset & 0x0f) | (XFERP & 0x07)<<4;
@@ -585,16 +584,8 @@ NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, struct scsi_cmnd *SCp,
              struct NCR_700_command_slot *slot)
 {
        if(SCp->sc_data_direction != DMA_NONE &&
-          SCp->sc_data_direction != DMA_BIDIRECTIONAL) {
-               if(SCp->use_sg) {
-                       dma_unmap_sg(hostdata->dev, SCp->request_buffer,
-                                    SCp->use_sg, SCp->sc_data_direction);
-               } else {
-                       dma_unmap_single(hostdata->dev, slot->dma_handle,
-                                        SCp->request_bufflen,
-                                        SCp->sc_data_direction);
-               }
-       }
+          SCp->sc_data_direction != DMA_BIDIRECTIONAL)
+               scsi_dma_unmap(SCp);
 }
 
 STATIC inline void
@@ -609,7 +600,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
                        (struct NCR_700_command_slot *)SCp->host_scribble;
                
                dma_unmap_single(hostdata->dev, slot->pCmd,
-                                sizeof(SCp->cmnd), DMA_TO_DEVICE);
+                                MAX_COMMAND_SIZE, DMA_TO_DEVICE);
                if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
                        char *cmnd = NCR_700_get_sense_cmnd(SCp->device);
 #ifdef NCR_700_DEBUG
@@ -618,7 +609,8 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
                        scsi_print_sense("53c700", SCp);
 
 #endif
-                       dma_unmap_single(hostdata->dev, slot->dma_handle, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE);
+                       dma_unmap_single(hostdata->dev, slot->dma_handle,
+                                        SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);
                        /* restore the old result if the request sense was
                         * successful */
                        if (result == 0)
@@ -661,7 +653,6 @@ NCR_700_chip_setup(struct Scsi_Host *host)
 {
        struct NCR_700_Host_Parameters *hostdata = 
                (struct NCR_700_Host_Parameters *)host->hostdata[0];
-       __u32 dcntl_extra = 0;
        __u8 min_period;
        __u8 min_xferp = (hostdata->chip710 ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP);
 
@@ -686,13 +677,14 @@ NCR_700_chip_setup(struct Scsi_Host *host)
                                burst_disable = BURST_DISABLE;
                                break;
                }
-               dcntl_extra = COMPAT_700_MODE;
+               hostdata->dcntl_extra |= COMPAT_700_MODE;
 
-               NCR_700_writeb(dcntl_extra, host, DCNTL_REG);
+               NCR_700_writeb(hostdata->dcntl_extra, host, DCNTL_REG);
                NCR_700_writeb(burst_length | hostdata->dmode_extra,
                               host, DMODE_710_REG);
-               NCR_700_writeb(burst_disable | (hostdata->differential ? 
-                                               DIFF : 0), host, CTEST7_REG);
+               NCR_700_writeb(burst_disable | hostdata->ctest7_extra |
+                              (hostdata->differential ? DIFF : 0),
+                              host, CTEST7_REG);
                NCR_700_writeb(BTB_TIMER_DISABLE, host, CTEST0_REG);
                NCR_700_writeb(FULL_ARBITRATION | ENABLE_PARITY | PARITY
                               | AUTO_ATN, host, SCNTL0_REG);
@@ -727,13 +719,13 @@ NCR_700_chip_setup(struct Scsi_Host *host)
                 * of spec: sync divider 2, async divider 3 */
                DEBUG(("53c700: sync 2 async 3\n"));
                NCR_700_writeb(SYNC_DIV_2_0, host, SBCL_REG);
-               NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);
+               NCR_700_writeb(ASYNC_DIV_3_0 | hostdata->dcntl_extra, host, DCNTL_REG);
                hostdata->sync_clock = hostdata->clock/2;
        } else  if(hostdata->clock > 50  && hostdata->clock <= 75) {
                /* sync divider 1.5, async divider 3 */
                DEBUG(("53c700: sync 1.5 async 3\n"));
                NCR_700_writeb(SYNC_DIV_1_5, host, SBCL_REG);
-               NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);
+               NCR_700_writeb(ASYNC_DIV_3_0 | hostdata->dcntl_extra, host, DCNTL_REG);
                hostdata->sync_clock = hostdata->clock*2;
                hostdata->sync_clock /= 3;
                
@@ -741,18 +733,18 @@ NCR_700_chip_setup(struct Scsi_Host *host)
                /* sync divider 1, async divider 2 */
                DEBUG(("53c700: sync 1 async 2\n"));
                NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
-               NCR_700_writeb(ASYNC_DIV_2_0 | dcntl_extra, host, DCNTL_REG);
+               NCR_700_writeb(ASYNC_DIV_2_0 | hostdata->dcntl_extra, host, DCNTL_REG);
                hostdata->sync_clock = hostdata->clock;
        } else if(hostdata->clock > 25 && hostdata->clock <=37) {
                /* sync divider 1, async divider 1.5 */
                DEBUG(("53c700: sync 1 async 1.5\n"));
                NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
-               NCR_700_writeb(ASYNC_DIV_1_5 | dcntl_extra, host, DCNTL_REG);
+               NCR_700_writeb(ASYNC_DIV_1_5 | hostdata->dcntl_extra, host, DCNTL_REG);
                hostdata->sync_clock = hostdata->clock;
        } else {
                DEBUG(("53c700: sync 1 async 1\n"));
                NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
-               NCR_700_writeb(ASYNC_DIV_1_0 | dcntl_extra, host, DCNTL_REG);
+               NCR_700_writeb(ASYNC_DIV_1_0 | hostdata->dcntl_extra, host, DCNTL_REG);
                /* sync divider 1, async divider 1 */
                hostdata->sync_clock = hostdata->clock;
        }
@@ -1013,14 +1005,14 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
                                 * here */
                                NCR_700_unmap(hostdata, SCp, slot);
                                dma_unmap_single(hostdata->dev, slot->pCmd,
-                                                sizeof(SCp->cmnd),
+                                                MAX_COMMAND_SIZE,
                                                 DMA_TO_DEVICE);
 
                                cmnd[0] = REQUEST_SENSE;
                                cmnd[1] = (SCp->device->lun & 0x7) << 5;
                                cmnd[2] = 0;
                                cmnd[3] = 0;
-                               cmnd[4] = sizeof(SCp->sense_buffer);
+                               cmnd[4] = SCSI_SENSE_BUFFERSIZE;
                                cmnd[5] = 0;
                                /* Here's a quiet hack: the
                                 * REQUEST_SENSE command is six bytes,
@@ -1034,14 +1026,14 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
                                SCp->cmd_len = 6; /* command length for
                                                   * REQUEST_SENSE */
                                slot->pCmd = dma_map_single(hostdata->dev, cmnd, MAX_COMMAND_SIZE, DMA_TO_DEVICE);
-                               slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE);
-                               slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer));
+                               slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);
+                               slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | SCSI_SENSE_BUFFERSIZE);
                                slot->SG[0].pAddr = bS_to_host(slot->dma_handle);
                                slot->SG[1].ins = bS_to_host(SCRIPT_RETURN);
                                slot->SG[1].pAddr = 0;
                                slot->resume_offset = hostdata->pScript;
                                dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG[0])*2, DMA_TO_DEVICE);
-                               dma_cache_sync(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE);
+                               dma_cache_sync(hostdata->dev, SCp->sense_buffer, SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);
 
                                /* queue the command for reissue */
                                slot->state = NCR_700_SLOT_QUEUED;
@@ -1263,14 +1255,13 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
                       host->host_no, pun, lun, NCR_700_condition[i],
                       NCR_700_phase[j], dsp - hostdata->pScript);
                if(SCp != NULL) {
-                       scsi_print_command(SCp);
+                       struct scatterlist *sg;
 
-                       if(SCp->use_sg) {
-                               for(i = 0; i < SCp->use_sg + 1; i++) {
-                                       printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->request_buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
-                               }
+                       scsi_print_command(SCp);
+                       scsi_for_each_sg(SCp, sg, scsi_sg_count(SCp) + 1, i) {
+                               printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, sg->length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
                        }
-               }              
+               }
                NCR_700_internal_bus_reset(host);
        } else if((dsps & 0xfffff000) == A_DEBUG_INTERRUPT) {
                printk(KERN_NOTICE "scsi%d (%d:%d) DEBUG INTERRUPT %d AT %08x[%04x], continuing\n",
@@ -1501,7 +1492,7 @@ NCR_700_intr(int irq, void *dev_id)
        unsigned long flags;
        int handled = 0;
 
-       /* Use the host lock to serialise acess to the 53c700
+       /* Use the host lock to serialise access to the 53c700
         * hardware.  Note: In future, we may need to take the queue
         * lock to enter the done routines.  When that happens, we
         * need to ensure that for this driver, the host lock and the
@@ -1844,8 +1835,8 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
        }
        /* sanity check: some of the commands generated by the mid-layer
         * have an eccentric idea of their sc_data_direction */
-       if(!SCp->use_sg && !SCp->request_bufflen 
-          && SCp->sc_data_direction != DMA_NONE) {
+       if(!scsi_sg_count(SCp) && !scsi_bufflen(SCp) &&
+          SCp->sc_data_direction != DMA_NONE) {
 #ifdef NCR_700_DEBUG
                printk("53c700: Command");
                scsi_print_command(SCp);
@@ -1887,31 +1878,15 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
                int i;
                int sg_count;
                dma_addr_t vPtr = 0;
+               struct scatterlist *sg;
                __u32 count = 0;
 
-               if(SCp->use_sg) {
-                       sg_count = dma_map_sg(hostdata->dev,
-                                             SCp->request_buffer, SCp->use_sg,
-                                             direction);
-               } else {
-                       vPtr = dma_map_single(hostdata->dev,
-                                             SCp->request_buffer, 
-                                             SCp->request_bufflen,
-                                             direction);
-                       count = SCp->request_bufflen;
-                       slot->dma_handle = vPtr;
-                       sg_count = 1;
-               }
-                       
-
-               for(i = 0; i < sg_count; i++) {
-
-                       if(SCp->use_sg) {
-                               struct scatterlist *sg = SCp->request_buffer;
+               sg_count = scsi_dma_map(SCp);
+               BUG_ON(sg_count < 0);
 
-                               vPtr = sg_dma_address(&sg[i]);
-                               count = sg_dma_len(&sg[i]);
-                       }
+               scsi_for_each_sg(SCp, sg, sg_count, i) {
+                       vPtr = sg_dma_address(sg);
+                       count = sg_dma_len(sg);
 
                        slot->SG[i].ins = bS_to_host(move_ins | count);
                        DEBUG((" scatter block %d: move %d[%08x] from 0x%lx\n",
@@ -1927,7 +1902,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
        }
        slot->resume_offset = 0;
        slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd,
-                                   sizeof(SCp->cmnd), DMA_TO_DEVICE);
+                                   MAX_COMMAND_SIZE, DMA_TO_DEVICE);
        NCR_700_start_command(SCp);
        return 0;
 }
@@ -2108,8 +2083,11 @@ NCR_700_slave_destroy(struct scsi_device *SDp)
 }
 
 static int
-NCR_700_change_queue_depth(struct scsi_device *SDp, int depth)
+NCR_700_change_queue_depth(struct scsi_device *SDp, int depth, int reason)
 {
+       if (reason != SCSI_QDEPTH_DEFAULT)
+               return -EOPNOTSUPP;
+
        if (depth > NCR_700_MAX_TAGS)
                depth = NCR_700_MAX_TAGS;