]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/scsi/NCR5380.c
Merge tag 'kvmgt-vfio-mdev-for-v4.10-rc1' of git://github.com/01org/gvt-linux
[karo-tx-linux.git] / drivers / scsi / NCR5380.c
index 790babc5ef660334c86ecb096e405a15d50bceee..d849ffa378b1ef19f80af760d53ae29774007e7c 100644 (file)
  *
  * Either real DMA *or* pseudo DMA may be implemented
  *
- * NCR5380_dma_write_setup(instance, src, count) - initialize
- * NCR5380_dma_read_setup(instance, dst, count) - initialize
- * NCR5380_dma_residual(instance); - residual count
+ * NCR5380_dma_xfer_len   - determine size of DMA/PDMA transfer
+ * NCR5380_dma_send_setup - execute DMA/PDMA from memory to 5380
+ * NCR5380_dma_recv_setup - execute DMA/PDMA from 5380 to memory
+ * NCR5380_dma_residual   - residual byte count
  *
  * The generic driver is initialized by calling NCR5380_init(instance),
  * after setting the appropriate host specific fields and ID.  If the
@@ -178,7 +179,7 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd)
 
 /**
  * NCR5380_poll_politely2 - wait for two chip register values
- * @instance: controller to poll
+ * @hostdata: host private data
  * @reg1: 5380 register to poll
  * @bit1: Bitmask to check
  * @val1: Expected value
@@ -195,18 +196,14 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd)
  * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT.
  */
 
-static int NCR5380_poll_politely2(struct Scsi_Host *instance,
-                                  int reg1, int bit1, int val1,
-                                  int reg2, int bit2, int val2, int wait)
+static int NCR5380_poll_politely2(struct NCR5380_hostdata *hostdata,
+                                  unsigned int reg1, u8 bit1, u8 val1,
+                                  unsigned int reg2, u8 bit2, u8 val2,
+                                  unsigned long wait)
 {
-       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+       unsigned long n = hostdata->poll_loops;
        unsigned long deadline = jiffies + wait;
-       unsigned long n;
 
-       /* Busy-wait for up to 10 ms */
-       n = min(10000U, jiffies_to_usecs(wait));
-       n *= hostdata->accesses_per_ms;
-       n /= 2000;
        do {
                if ((NCR5380_read(reg1) & bit1) == val1)
                        return 0;
@@ -288,6 +285,7 @@ mrs[] = {
 
 static void NCR5380_print(struct Scsi_Host *instance)
 {
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
        unsigned char status, data, basr, mr, icr, i;
 
        data = NCR5380_read(CURRENT_SCSI_DATA_REG);
@@ -337,6 +335,7 @@ static struct {
 
 static void NCR5380_print_phase(struct Scsi_Host *instance)
 {
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
        unsigned char status;
        int i;
 
@@ -441,14 +440,14 @@ static void prepare_info(struct Scsi_Host *instance)
        struct NCR5380_hostdata *hostdata = shost_priv(instance);
 
        snprintf(hostdata->info, sizeof(hostdata->info),
-                "%s, io_port 0x%lx, n_io_port %d, "
-                "base 0x%lx, irq %d, "
+                "%s, irq %d, "
+                "io_port 0x%lx, base 0x%lx, "
                 "can_queue %d, cmd_per_lun %d, "
                 "sg_tablesize %d, this_id %d, "
                 "flags { %s%s%s}, "
                 "options { %s} ",
-                instance->hostt->name, instance->io_port, instance->n_io_port,
-                instance->base, instance->irq,
+                instance->hostt->name, instance->irq,
+                hostdata->io_port, hostdata->base,
                 instance->can_queue, instance->cmd_per_lun,
                 instance->sg_tablesize, instance->this_id,
                 hostdata->flags & FLAG_DMA_FIXUP     ? "DMA_FIXUP "     : "",
@@ -482,6 +481,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
        struct NCR5380_hostdata *hostdata = shost_priv(instance);
        int i;
        unsigned long deadline;
+       unsigned long accesses_per_ms;
 
        instance->max_lun = 7;
 
@@ -530,7 +530,8 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
                ++i;
                cpu_relax();
        } while (time_is_after_jiffies(deadline));
-       hostdata->accesses_per_ms = i / 256;
+       accesses_per_ms = i / 256;
+       hostdata->poll_loops = NCR5380_REG_POLL_TIME * accesses_per_ms / 2;
 
        return 0;
 }
@@ -560,7 +561,7 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance)
                case 3:
                case 5:
                        shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n");
-                       NCR5380_poll_politely(instance,
+                       NCR5380_poll_politely(hostdata,
                                              STATUS_REG, SR_BSY, 0, 5 * HZ);
                        break;
                case 2:
@@ -871,7 +872,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
        NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 
-       transferred = hostdata->dma_len - NCR5380_dma_residual(instance);
+       transferred = hostdata->dma_len - NCR5380_dma_residual(hostdata);
        hostdata->dma_len = 0;
 
        data = (unsigned char **)&hostdata->connected->SCp.ptr;
@@ -994,7 +995,7 @@ static irqreturn_t __maybe_unused NCR5380_intr(int irq, void *dev_id)
                }
                handled = 1;
        } else {
-               shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n");
+               dsprintk(NDEBUG_INTR, instance, "interrupt without IRQ bit\n");
 #ifdef SUN3_SCSI_VME
                dregs->csr |= CSR_DMA_ENABLE;
 #endif
@@ -1075,7 +1076,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
         */
 
        spin_unlock_irq(&hostdata->lock);
-       err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0,
+       err = NCR5380_poll_politely2(hostdata, MODE_REG, MR_ARBITRATE, 0,
                        INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS,
                                               ICR_ARBITRATION_PROGRESS, HZ);
        spin_lock_irq(&hostdata->lock);
@@ -1201,7 +1202,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
         * selection.
         */
 
-       err = NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, SR_BSY,
+       err = NCR5380_poll_politely(hostdata, STATUS_REG, SR_BSY, SR_BSY,
                                    msecs_to_jiffies(250));
 
        if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
@@ -1247,7 +1248,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
 
        /* Wait for start of REQ/ACK handshake */
 
-       err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
+       err = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ);
        spin_lock_irq(&hostdata->lock);
        if (err < 0) {
                shost_printk(KERN_ERR, instance, "select: REQ timeout\n");
@@ -1318,6 +1319,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
                                unsigned char *phase, int *count,
                                unsigned char **data)
 {
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
        unsigned char p = *phase, tmp;
        int c = *count;
        unsigned char *d = *data;
@@ -1336,7 +1338,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
                 * valid
                 */
 
-               if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0)
+               if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0)
                        break;
 
                dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n");
@@ -1381,7 +1383,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
                        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
                }
 
-               if (NCR5380_poll_politely(instance,
+               if (NCR5380_poll_politely(hostdata,
                                          STATUS_REG, SR_REQ, 0, 5 * HZ) < 0)
                        break;
 
@@ -1440,6 +1442,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
 
 static void do_reset(struct Scsi_Host *instance)
 {
+       struct NCR5380_hostdata __maybe_unused *hostdata = shost_priv(instance);
        unsigned long flags;
 
        local_irq_save(flags);
@@ -1462,6 +1465,7 @@ static void do_reset(struct Scsi_Host *instance)
 
 static int do_abort(struct Scsi_Host *instance)
 {
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
        unsigned char *msgptr, phase, tmp;
        int len;
        int rc;
@@ -1479,7 +1483,7 @@ static int do_abort(struct Scsi_Host *instance)
         * the target sees, so we just handshake.
         */
 
-       rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ);
+       rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ);
        if (rc < 0)
                goto timeout;
 
@@ -1490,7 +1494,7 @@ static int do_abort(struct Scsi_Host *instance)
        if (tmp != PHASE_MSGOUT) {
                NCR5380_write(INITIATOR_COMMAND_REG,
                              ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
-               rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ);
+               rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, 0, 3 * HZ);
                if (rc < 0)
                        goto timeout;
                NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
@@ -1575,9 +1579,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
                 * starting the NCR. This is also the cleaner way for the TT.
                 */
                if (p & SR_IO)
-                       result = NCR5380_dma_recv_setup(instance, d, c);
+                       result = NCR5380_dma_recv_setup(hostdata, d, c);
                else
-                       result = NCR5380_dma_send_setup(instance, d, c);
+                       result = NCR5380_dma_send_setup(hostdata, d, c);
        }
 
        /*
@@ -1609,9 +1613,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
                 * NCR access, else the DMA setup gets trashed!
                 */
                if (p & SR_IO)
-                       result = NCR5380_dma_recv_setup(instance, d, c);
+                       result = NCR5380_dma_recv_setup(hostdata, d, c);
                else
-                       result = NCR5380_dma_send_setup(instance, d, c);
+                       result = NCR5380_dma_send_setup(hostdata, d, c);
        }
 
        /* On failure, NCR5380_dma_xxxx_setup() returns a negative int. */
@@ -1678,12 +1682,12 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
                         * byte.
                         */
 
-                       if (NCR5380_poll_politely(instance, BUS_AND_STATUS_REG,
+                       if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
                                                  BASR_DRQ, BASR_DRQ, HZ) < 0) {
                                result = -1;
                                shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n");
                        }
-                       if (NCR5380_poll_politely(instance, STATUS_REG,
+                       if (NCR5380_poll_politely(hostdata, STATUS_REG,
                                                  SR_REQ, 0, HZ) < 0) {
                                result = -1;
                                shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n");
@@ -1694,7 +1698,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
                         * Wait for the last byte to be sent.  If REQ is being asserted for
                         * the byte we're interested, we'll ACK it and it will go false.
                         */
-                       if (NCR5380_poll_politely2(instance,
+                       if (NCR5380_poll_politely2(hostdata,
                             BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ,
                             BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ) < 0) {
                                result = -1;
@@ -1751,22 +1755,26 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
                        }
 #ifdef CONFIG_SUN3
-                       if (phase == PHASE_CMDOUT) {
-                               void *d;
-                               unsigned long count;
+                       if (phase == PHASE_CMDOUT &&
+                           sun3_dma_setup_done != cmd) {
+                               int count;
 
                                if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
-                                       count = cmd->SCp.buffer->length;
-                                       d = sg_virt(cmd->SCp.buffer);
-                               } else {
-                                       count = cmd->SCp.this_residual;
-                                       d = cmd->SCp.ptr;
+                                       ++cmd->SCp.buffer;
+                                       --cmd->SCp.buffers_residual;
+                                       cmd->SCp.this_residual = cmd->SCp.buffer->length;
+                                       cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
                                }
 
-                               if (sun3_dma_setup_done != cmd &&
-                                   sun3scsi_dma_xfer_len(count, cmd) > 0) {
-                                       sun3scsi_dma_setup(instance, d, count,
-                                                          rq_data_dir(cmd->request));
+                               count = sun3scsi_dma_xfer_len(hostdata, cmd);
+
+                               if (count > 0) {
+                                       if (rq_data_dir(cmd->request))
+                                               sun3scsi_dma_send_setup(hostdata,
+                                                                       cmd->SCp.ptr, count);
+                                       else
+                                               sun3scsi_dma_recv_setup(hostdata,
+                                                                       cmd->SCp.ptr, count);
                                        sun3_dma_setup_done = cmd;
                                }
 #ifdef SUN3_SCSI_VME
@@ -1827,7 +1835,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
 
                                transfersize = 0;
                                if (!cmd->device->borken)
-                                       transfersize = NCR5380_dma_xfer_len(instance, cmd, phase);
+                                       transfersize = NCR5380_dma_xfer_len(hostdata, cmd);
 
                                if (transfersize > 0) {
                                        len = transfersize;
@@ -2073,7 +2081,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                        } /* switch(phase) */
                } else {
                        spin_unlock_irq(&hostdata->lock);
-                       NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
+                       NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ);
                        spin_lock_irq(&hostdata->lock);
                }
        }
@@ -2119,7 +2127,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
         */
 
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
-       if (NCR5380_poll_politely(instance,
+       if (NCR5380_poll_politely(hostdata,
                                  STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) {
                NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
                return;
@@ -2130,7 +2138,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
         * Wait for target to go into MSGIN.
         */
 
-       if (NCR5380_poll_politely(instance,
+       if (NCR5380_poll_politely(hostdata,
                                  STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) {
                do_abort(instance);
                return;
@@ -2204,22 +2212,25 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
        }
 
 #ifdef CONFIG_SUN3
-       {
-               void *d;
-               unsigned long count;
+       if (sun3_dma_setup_done != tmp) {
+               int count;
 
                if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) {
-                       count = tmp->SCp.buffer->length;
-                       d = sg_virt(tmp->SCp.buffer);
-               } else {
-                       count = tmp->SCp.this_residual;
-                       d = tmp->SCp.ptr;
+                       ++tmp->SCp.buffer;
+                       --tmp->SCp.buffers_residual;
+                       tmp->SCp.this_residual = tmp->SCp.buffer->length;
+                       tmp->SCp.ptr = sg_virt(tmp->SCp.buffer);
                }
 
-               if (sun3_dma_setup_done != tmp &&
-                   sun3scsi_dma_xfer_len(count, tmp) > 0) {
-                       sun3scsi_dma_setup(instance, d, count,
-                                          rq_data_dir(tmp->request));
+               count = sun3scsi_dma_xfer_len(hostdata, tmp);
+
+               if (count > 0) {
+                       if (rq_data_dir(tmp->request))
+                               sun3scsi_dma_send_setup(hostdata,
+                                                       tmp->SCp.ptr, count);
+                       else
+                               sun3scsi_dma_recv_setup(hostdata,
+                                                       tmp->SCp.ptr, count);
                        sun3_dma_setup_done = tmp;
                }
        }