Commit b32ade12 authored by Finn Thain's avatar Finn Thain Committed by Martin K. Petersen

ncr5380: Introduce NCR5380_poll_politely2

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: default avatarFinn Thain <fthain@telegraphics.com.au>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Tested-by: default avatarOndrej Zary <linux@rainbow-software.org>
Tested-by: default avatarMichael Schmitz <schmitzmic@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent cd400825
...@@ -262,11 +262,14 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) ...@@ -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 * @instance: controller to poll
* @reg: 5380 register to poll * @reg1: 5380 register to poll
* @bit: Bitmask to check * @bit1: Bitmask to check
* @val: Value required to exit * @val1: Expected value
* @reg2: Second 5380 register to poll
* @bit2: Second bitmask to check
* @val2: Second expected value
* @wait: Time-out in jiffies * @wait: Time-out in jiffies
* *
* Polls the chip in a reasonably efficient manner waiting for an * Polls the chip in a reasonably efficient manner waiting for an
...@@ -274,11 +277,12 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) ...@@ -274,11 +277,12 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd)
* (if possible). In irq contexts the time-out is arbitrarily limited. * (if possible). In irq contexts the time-out is arbitrarily limited.
* Callers may hold locks as long as they are held in irq mode. * 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, static int NCR5380_poll_politely2(struct Scsi_Host *instance,
int reg, int bit, int val, int wait) int reg1, int bit1, int val1,
int reg2, int bit2, int val2, int wait)
{ {
struct NCR5380_hostdata *hostdata = shost_priv(instance); struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned long deadline = jiffies + wait; unsigned long deadline = jiffies + wait;
...@@ -287,9 +291,11 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, ...@@ -287,9 +291,11 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance,
/* Busy-wait for up to 10 ms */ /* Busy-wait for up to 10 ms */
n = min(10000U, jiffies_to_usecs(wait)); n = min(10000U, jiffies_to_usecs(wait));
n *= hostdata->accesses_per_ms; n *= hostdata->accesses_per_ms;
n /= 1000; n /= 2000;
do { do {
if ((NCR5380_read(reg) & bit) == val) if ((NCR5380_read(reg1) & bit1) == val1)
return 0;
if ((NCR5380_read(reg2) & bit2) == val2)
return 0; return 0;
cpu_relax(); cpu_relax();
} while (n--); } while (n--);
...@@ -300,13 +306,22 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, ...@@ -300,13 +306,22 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance,
/* Repeatedly sleep for 1 ms until deadline */ /* Repeatedly sleep for 1 ms until deadline */
while (time_is_after_jiffies(deadline)) { while (time_is_after_jiffies(deadline)) {
schedule_timeout_uninterruptible(1); 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 0;
} }
return -ETIMEDOUT; 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 { static struct {
unsigned char value; unsigned char value;
const char *name; const char *name;
...@@ -1101,7 +1116,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) ...@@ -1101,7 +1116,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
unsigned char *data; unsigned char *data;
int len; int len;
int err; int err;
unsigned long timeout;
NCR5380_dprint(NDEBUG_ARBITRATION, instance); NCR5380_dprint(NDEBUG_ARBITRATION, instance);
dprintk(NDEBUG_ARBITRATION, "scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id); 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) ...@@ -1125,23 +1139,19 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
*/ */
spin_unlock_irq(instance->host_lock); spin_unlock_irq(instance->host_lock);
timeout = jiffies + HZ; err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0,
while (1) { INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS,
if (time_is_before_jiffies(timeout)) { ICR_ARBITRATION_PROGRESS, HZ);
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); spin_lock_irq(instance->host_lock);
if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
/* Reselection interrupt */ /* Reselection interrupt */
return -1; return -1;
} }
if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) if (err < 0) {
break; NCR5380_write(MODE_REG, MR_BASE);
spin_unlock_irq(instance->host_lock); shost_printk(KERN_ERR, instance,
"select: arbitration timeout\n");
return -1;
} }
/* The SCSI-2 arbitration delay is 2.4 us */ /* The SCSI-2 arbitration delay is 2.4 us */
......
...@@ -457,11 +457,14 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) ...@@ -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 * @instance: controller to poll
* @reg: 5380 register to poll * @reg1: 5380 register to poll
* @bit: Bitmask to check * @bit1: Bitmask to check
* @val: Value required to exit * @val1: Expected value
* @reg2: Second 5380 register to poll
* @bit2: Second bitmask to check
* @val2: Second expected value
* @wait: Time-out in jiffies * @wait: Time-out in jiffies
* *
* Polls the chip in a reasonably efficient manner waiting for an * Polls the chip in a reasonably efficient manner waiting for an
...@@ -469,11 +472,12 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) ...@@ -469,11 +472,12 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd)
* (if possible). In irq contexts the time-out is arbitrarily limited. * (if possible). In irq contexts the time-out is arbitrarily limited.
* Callers may hold locks as long as they are held in irq mode. * 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, static int NCR5380_poll_politely2(struct Scsi_Host *instance,
int reg, int bit, int val, int wait) int reg1, int bit1, int val1,
int reg2, int bit2, int val2, int wait)
{ {
struct NCR5380_hostdata *hostdata = shost_priv(instance); struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned long deadline = jiffies + wait; unsigned long deadline = jiffies + wait;
...@@ -482,9 +486,11 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, ...@@ -482,9 +486,11 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance,
/* Busy-wait for up to 10 ms */ /* Busy-wait for up to 10 ms */
n = min(10000U, jiffies_to_usecs(wait)); n = min(10000U, jiffies_to_usecs(wait));
n *= hostdata->accesses_per_ms; n *= hostdata->accesses_per_ms;
n /= 1000; n /= 2000;
do { do {
if ((NCR5380_read(reg) & bit) == val) if ((NCR5380_read(reg1) & bit1) == val1)
return 0;
if ((NCR5380_read(reg2) & bit2) == val2)
return 0; return 0;
cpu_relax(); cpu_relax();
} while (n--); } while (n--);
...@@ -495,13 +501,22 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, ...@@ -495,13 +501,22 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance,
/* Repeatedly sleep for 1 ms until deadline */ /* Repeatedly sleep for 1 ms until deadline */
while (time_is_after_jiffies(deadline)) { while (time_is_after_jiffies(deadline)) {
schedule_timeout_uninterruptible(1); 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 0;
} }
return -ETIMEDOUT; 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> #include <linux/delay.h>
#if NDEBUG #if NDEBUG
...@@ -1348,7 +1363,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) ...@@ -1348,7 +1363,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
int len; int len;
int err; int err;
unsigned long flags; unsigned long flags;
unsigned long timeout;
NCR5380_dprint(NDEBUG_ARBITRATION, instance); NCR5380_dprint(NDEBUG_ARBITRATION, instance);
dprintk(NDEBUG_ARBITRATION, "scsi%d: starting arbitration, id = %d\n", HOSTNO, 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) ...@@ -1378,20 +1392,18 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
*/ */
local_irq_restore(flags); local_irq_restore(flags);
timeout = jiffies + HZ; err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0,
while (1) { INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS,
if (time_is_before_jiffies(timeout)) { ICR_ARBITRATION_PROGRESS, HZ);
NCR5380_write(MODE_REG, MR_BASE);
shost_printk(KERN_ERR, instance,
"select: arbitration timeout\n");
return -1;
}
if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
/* Reselection interrupt */ /* Reselection interrupt */
return -1; return -1;
} }
if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) if (err < 0) {
break; 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 */ /* The SCSI-2 arbitration delay is 2.4 us */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment