ncr5380: Introduce NCR5380_poll_politely2
authorFinn Thain <fthain@telegraphics.com.au>
Sun, 3 Jan 2016 05:05:41 +0000 (16:05 +1100)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 7 Jan 2016 02:43:01 +0000 (21:43 -0500)
SCSI bus protocol sometimes requires monitoring two related conditions
simultaneously. Enhance NCR5380_poll_politely() for this purpose, and
put it to use in the arbitration algorithm. It will also find use in
pseudo DMA.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Tested-by: Ondrej Zary <linux@rainbow-software.org>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/NCR5380.c
drivers/scsi/atari_NCR5380.c

index 8567d69709ce9e406994db07ec9b559adc4d3884..9c1b69be796c020c416e9c0d4c440dad09c530a3 100644 (file)
@@ -262,11 +262,14 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd)
 }
 
 /**
- * NCR5380_poll_politely - wait for chip register value
+ * NCR5380_poll_politely2 - wait for two chip register values
  * @instance: controller to poll
- * @reg: 5380 register to poll
- * @bit: Bitmask to check
- * @val: Value required to exit
+ * @reg1: 5380 register to poll
+ * @bit1: Bitmask to check
+ * @val1: Expected value
+ * @reg2: Second 5380 register to poll
+ * @bit2: Second bitmask to check
+ * @val2: Second expected value
  * @wait: Time-out in jiffies
  *
  * Polls the chip in a reasonably efficient manner waiting for an
@@ -274,11 +277,12 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd)
  * (if possible). In irq contexts the time-out is arbitrarily limited.
  * Callers may hold locks as long as they are held in irq mode.
  *
- * Returns 0 if event occurred otherwise -ETIMEDOUT.
+ * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT.
  */
 
-static int NCR5380_poll_politely(struct Scsi_Host *instance,
-                                 int reg, int bit, int val, int wait)
+static int NCR5380_poll_politely2(struct Scsi_Host *instance,
+                                  int reg1, int bit1, int val1,
+                                  int reg2, int bit2, int val2, int wait)
 {
        struct NCR5380_hostdata *hostdata = shost_priv(instance);
        unsigned long deadline = jiffies + wait;
@@ -287,9 +291,11 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance,
        /* Busy-wait for up to 10 ms */
        n = min(10000U, jiffies_to_usecs(wait));
        n *= hostdata->accesses_per_ms;
-       n /= 1000;
+       n /= 2000;
        do {
-               if ((NCR5380_read(reg) & bit) == val)
+               if ((NCR5380_read(reg1) & bit1) == val1)
+                       return 0;
+               if ((NCR5380_read(reg2) & bit2) == val2)
                        return 0;
                cpu_relax();
        } while (n--);
@@ -300,13 +306,22 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance,
        /* Repeatedly sleep for 1 ms until deadline */
        while (time_is_after_jiffies(deadline)) {
                schedule_timeout_uninterruptible(1);
-               if ((NCR5380_read(reg) & bit) == val)
+               if ((NCR5380_read(reg1) & bit1) == val1)
+                       return 0;
+               if ((NCR5380_read(reg2) & bit2) == val2)
                        return 0;
        }
 
        return -ETIMEDOUT;
 }
 
+static inline int NCR5380_poll_politely(struct Scsi_Host *instance,
+                                        int reg, int bit, int val, int wait)
+{
+       return NCR5380_poll_politely2(instance, reg, bit, val,
+                                               reg, bit, val, wait);
+}
+
 static struct {
        unsigned char value;
        const char *name;
@@ -1101,7 +1116,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
        unsigned char *data;
        int len;
        int err;
-       unsigned long timeout;
 
        NCR5380_dprint(NDEBUG_ARBITRATION, instance);
        dprintk(NDEBUG_ARBITRATION, "scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id);
@@ -1125,23 +1139,19 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
         */
 
        spin_unlock_irq(instance->host_lock);
-       timeout = jiffies + HZ;
-       while (1) {
-               if (time_is_before_jiffies(timeout)) {
-                       NCR5380_write(MODE_REG, MR_BASE);
-                       shost_printk(KERN_ERR, instance,
-                                    "select: arbitration timeout\n");
-                       spin_lock_irq(instance->host_lock);
-                       return -1;
-               }
-               spin_lock_irq(instance->host_lock);
-               if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
-                       /* Reselection interrupt */
-                       return -1;
-               }
-               if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
-                       break;
-               spin_unlock_irq(instance->host_lock);
+       err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0,
+                       INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS,
+                                              ICR_ARBITRATION_PROGRESS, HZ);
+       spin_lock_irq(instance->host_lock);
+       if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
+               /* Reselection interrupt */
+               return -1;
+       }
+       if (err < 0) {
+               NCR5380_write(MODE_REG, MR_BASE);
+               shost_printk(KERN_ERR, instance,
+                            "select: arbitration timeout\n");
+               return -1;
        }
 
        /* The SCSI-2 arbitration delay is 2.4 us */
index c8c216a9f4488b780e59c994831e6dd2e9a7bacb..70398c61fffc832e9d0391c2fccf09fe2387a18e 100644 (file)
@@ -457,11 +457,14 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd)
 }
 
 /**
- * NCR5380_poll_politely - wait for chip register value
+ * NCR5380_poll_politely2 - wait for two chip register values
  * @instance: controller to poll
- * @reg: 5380 register to poll
- * @bit: Bitmask to check
- * @val: Value required to exit
+ * @reg1: 5380 register to poll
+ * @bit1: Bitmask to check
+ * @val1: Expected value
+ * @reg2: Second 5380 register to poll
+ * @bit2: Second bitmask to check
+ * @val2: Second expected value
  * @wait: Time-out in jiffies
  *
  * Polls the chip in a reasonably efficient manner waiting for an
@@ -469,11 +472,12 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd)
  * (if possible). In irq contexts the time-out is arbitrarily limited.
  * Callers may hold locks as long as they are held in irq mode.
  *
- * Returns 0 if event occurred otherwise -ETIMEDOUT.
+ * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT.
  */
 
-static int NCR5380_poll_politely(struct Scsi_Host *instance,
-                                 int reg, int bit, int val, int wait)
+static int NCR5380_poll_politely2(struct Scsi_Host *instance,
+                                  int reg1, int bit1, int val1,
+                                  int reg2, int bit2, int val2, int wait)
 {
        struct NCR5380_hostdata *hostdata = shost_priv(instance);
        unsigned long deadline = jiffies + wait;
@@ -482,9 +486,11 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance,
        /* Busy-wait for up to 10 ms */
        n = min(10000U, jiffies_to_usecs(wait));
        n *= hostdata->accesses_per_ms;
-       n /= 1000;
+       n /= 2000;
        do {
-               if ((NCR5380_read(reg) & bit) == val)
+               if ((NCR5380_read(reg1) & bit1) == val1)
+                       return 0;
+               if ((NCR5380_read(reg2) & bit2) == val2)
                        return 0;
                cpu_relax();
        } while (n--);
@@ -495,13 +501,22 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance,
        /* Repeatedly sleep for 1 ms until deadline */
        while (time_is_after_jiffies(deadline)) {
                schedule_timeout_uninterruptible(1);
-               if ((NCR5380_read(reg) & bit) == val)
+               if ((NCR5380_read(reg1) & bit1) == val1)
+                       return 0;
+               if ((NCR5380_read(reg2) & bit2) == val2)
                        return 0;
        }
 
        return -ETIMEDOUT;
 }
 
+static inline int NCR5380_poll_politely(struct Scsi_Host *instance,
+                                        int reg, int bit, int val, int wait)
+{
+       return NCR5380_poll_politely2(instance, reg, bit, val,
+                                               reg, bit, val, wait);
+}
+
 #include <linux/delay.h>
 
 #if NDEBUG
@@ -1348,7 +1363,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
        int len;
        int err;
        unsigned long flags;
-       unsigned long timeout;
 
        NCR5380_dprint(NDEBUG_ARBITRATION, instance);
        dprintk(NDEBUG_ARBITRATION, "scsi%d: starting arbitration, id = %d\n", HOSTNO,
@@ -1378,20 +1392,18 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
         */
 
        local_irq_restore(flags);
-       timeout = jiffies + HZ;
-       while (1) {
-               if (time_is_before_jiffies(timeout)) {
-                       NCR5380_write(MODE_REG, MR_BASE);
-                       shost_printk(KERN_ERR, instance,
-                                    "select: arbitration timeout\n");
-                       return -1;
-               }
-               if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
-                       /* Reselection interrupt */
-                       return -1;
-               }
-               if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
-                       break;
+       err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0,
+                       INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS,
+                                              ICR_ARBITRATION_PROGRESS, HZ);
+       if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
+               /* Reselection interrupt */
+               return -1;
+       }
+       if (err < 0) {
+               NCR5380_write(MODE_REG, MR_BASE);
+               shost_printk(KERN_ERR, instance,
+                            "select: arbitration timeout\n");
+               return -1;
        }
 
        /* The SCSI-2 arbitration delay is 2.4 us */