Commit 4e665bdd authored by James Bottomley's avatar James Bottomley

fix NC5380 locking and delayed work handling

From: Christoph Hellwig <hch@lst.de>

 - move delayed workqueue handling to schedule_delayed_work instead
   of the old horrible global list thing
 - add NCR5380_exit to make sure all delayed work is flushed on HBA
   (or module) removal
 - fix locking

Patch fixed up to apply and
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 8651e2bd
...@@ -310,12 +310,8 @@ ...@@ -310,12 +310,8 @@
* possible) function may be used. Before the specific driver initialization * possible) function may be used. Before the specific driver initialization
* code finishes, NCR5380_print_options should be called. * code finishes, NCR5380_print_options should be called.
*/ */
static int do_abort(struct Scsi_Host *host); static int do_abort(struct Scsi_Host *host);
static void do_reset(struct Scsi_Host *host); static void do_reset(struct Scsi_Host *host);
static struct NCR5380_hostdata *first_host = NULL;
static struct NCR5380_hostdata *last_host = NULL;
static struct timer_list usleep_timer;
/* /*
* initialize_SCp - init the scsi pointer field * initialize_SCp - init the scsi pointer field
...@@ -533,9 +529,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) ...@@ -533,9 +529,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
#define USLEEP_WAITLONG USLEEP_SLEEP #define USLEEP_WAITLONG USLEEP_SLEEP
#endif #endif
static struct Scsi_Host *expires_first = NULL;
static spinlock_t timer_lock; /* Guards expires list */
/* /*
* Function : int should_disconnect (unsigned char cmd) * Function : int should_disconnect (unsigned char cmd)
* *
...@@ -578,90 +571,10 @@ static int should_disconnect(unsigned char cmd) ...@@ -578,90 +571,10 @@ static int should_disconnect(unsigned char cmd)
} }
} }
/* static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout)
* Assumes instance->time_expires has been set in higher level code.
* We should move to a timer per host
*
* Locks: Takes the timer queue lock
*/
static int NCR5380_set_timer(struct Scsi_Host *instance)
{ {
struct Scsi_Host *tmp, **prev; hostdata->time_expires = jiffies + timeout;
unsigned long flags; schedule_delayed_work(&hostdata->coroutine, hostdata->time_expires);
if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) {
return -1;
}
spin_lock_irqsave(&timer_lock, flags);
for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
if (((struct NCR5380_hostdata *) instance->hostdata)->time_expires < ((struct NCR5380_hostdata *) tmp->hostdata)->time_expires)
break;
((struct NCR5380_hostdata *) instance->hostdata)->next_timer = tmp;
*prev = instance;
mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires);
spin_unlock_irqrestore(&timer_lock, flags);
return 0;
}
/**
* NCR5380_timer_fn - handle polled timeouts
* @unused: unused
*
* Walk the list of controllers, find which controllers have exceeded
* their expiry timeout and then schedule the processing co-routine to
* do the real work.
*
* Doing something about unwanted reentrancy here might be useful
*
* Locks: disables irqs, takes and frees the timer lock
*/
static void NCR5380_timer_fn(unsigned long unused)
{
struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata;
unsigned long flags;
spin_lock_irqsave(&timer_lock, flags);
for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);)
{
hostdata = (struct NCR5380_hostdata *) expires_first->hostdata;
schedule_work(&hostdata->coroutine);
instance = hostdata->next_timer;
hostdata->next_timer = NULL;
hostdata->time_expires = 0;
expires_first = instance;
}
del_timer(&usleep_timer);
if (expires_first) {
usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires;
add_timer(&usleep_timer);
}
spin_unlock_irqrestore(&timer_lock, flags);
}
/**
* NCR5380_all_init - global setup
*
* Set up the global values and timers needed by the NCR5380 driver
*/
static inline void NCR5380_all_init(void)
{
static int done = 0;
if (!done) {
dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n"));
done = 1;
init_timer(&usleep_timer);
spin_lock_init(&timer_lock);
usleep_timer.function = NCR5380_timer_fn;
}
} }
...@@ -787,22 +700,6 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance) ...@@ -787,22 +700,6 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
} }
} }
/**
* NCR5380_coroutine_running - coroutine status
* @instance: controller to check
*
* Return true if the co-routine for this controller is running
* or scheduled to run
*
* FIXME: this test function belongs in the workqueue code!
*/
static int NCR5380_coroutine_running(struct Scsi_Host *instance)
{
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata;
return test_bit(0, &hostdata->coroutine.pending);
}
/** /**
* NCR5380_print_status - dump controller info * NCR5380_print_status - dump controller info
* @instance: controller to dump * @instance: controller to dump
...@@ -819,8 +716,6 @@ static void NCR5380_print_status(struct Scsi_Host *instance) ...@@ -819,8 +716,6 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
char *start; char *start;
int len; int len;
printk("NCR5380 : coroutine is%s running.\n", NCR5380_coroutine_running(instance)? "" : "n't");
NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint(NDEBUG_ANY, instance);
NCR5380_dprint_phase(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance);
...@@ -900,7 +795,6 @@ int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, of ...@@ -900,7 +795,6 @@ int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, of
SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi); SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi);
#endif #endif
spin_lock_irq(instance->host_lock); spin_lock_irq(instance->host_lock);
SPRINTF("NCR5380 : coroutine is%s running.\n", NCR5380_coroutine_running(instance) ? "" : "n't");
if (!hostdata->connected) if (!hostdata->connected)
SPRINTF("scsi%d: no currently connected command\n", instance->host_no); SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
else else
...@@ -912,7 +806,6 @@ int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, of ...@@ -912,7 +806,6 @@ int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, of
SPRINTF("scsi%d: disconnected_queue\n", instance->host_no); SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length); pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
spin_unlock_irq(instance->host_lock); spin_unlock_irq(instance->host_lock);
*start = buffer; *start = buffer;
...@@ -964,7 +857,7 @@ static char *lprint_opcode(int opcode, char *pos, char *buffer, int length) ...@@ -964,7 +857,7 @@ static char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
* Locks: interrupts must be enabled when we are called * Locks: interrupts must be enabled when we are called
*/ */
static int __init NCR5380_init(struct Scsi_Host *instance, int flags) static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags)
{ {
NCR5380_local_declare(); NCR5380_local_declare();
int i, pass; int i, pass;
...@@ -984,7 +877,6 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -984,7 +877,6 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
#endif #endif
NCR5380_setup(instance); NCR5380_setup(instance);
NCR5380_all_init();
hostdata->aborted = 0; hostdata->aborted = 0;
hostdata->id_mask = 1 << instance->this_id; hostdata->id_mask = 1 << instance->this_id;
...@@ -1021,18 +913,8 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1021,18 +913,8 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
else else
hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags; hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags;
hostdata->next = NULL;
if (!first_host)
first_host = hostdata;
else
last_host->next = hostdata;
last_host = hostdata;
hostdata->host = instance; hostdata->host = instance;
hostdata->time_expires = 0; hostdata->time_expires = 0;
hostdata->next_timer = NULL;
#ifndef AUTOSENSE #ifndef AUTOSENSE
if ((instance->cmd_per_lun > 1) || instance->can_queue > 1) if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
...@@ -1088,6 +970,19 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1088,6 +970,19 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
return 0; return 0;
} }
/**
* NCR5380_exit - remove an NCR5380
* @instance: adapter to remove
*/
static void __devexit NCR5380_exit(struct Scsi_Host *instance)
{
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
cancel_delayed_work(&hostdata->coroutine);
flush_scheduled_work();
}
/** /**
* NCR5380_queue_command - queue a command * NCR5380_queue_command - queue a command
* @cmd: SCSI command * @cmd: SCSI command
...@@ -1169,6 +1064,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1169,6 +1064,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
return 0; return 0;
} }
/** /**
* NCR5380_main - NCR state machines * NCR5380_main - NCR state machines
* *
...@@ -1184,28 +1080,11 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1184,28 +1080,11 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
static void NCR5380_main(void *p) static void NCR5380_main(void *p)
{ {
struct NCR5380_hostdata *hostdata = p; struct NCR5380_hostdata *hostdata = p;
struct Scsi_Host *instance = hostdata->host;
Scsi_Cmnd *tmp, *prev; Scsi_Cmnd *tmp, *prev;
struct Scsi_Host *instance;
int done; int done;
unsigned long flags = 0;
/* spin_lock_irq(instance->host_lock);
* We run (with interrupts disabled) until we're sure that none of
* the host adapters have anything that can be done, at which point
* we can exit
*
* Interrupts are enabled before doing various other internal
* instructions, after we've decided that we need to run through
* the loop again.
*
* this should prevent any race conditions.
*/
instance = hostdata->host;
if(instance->irq != SCSI_IRQ_NONE)
spin_lock_irqsave(instance->host_lock, flags);
do { do {
/* Lock held here */ /* Lock held here */
done = 1; done = 1;
...@@ -1286,8 +1165,7 @@ static void NCR5380_main(void *p) ...@@ -1286,8 +1165,7 @@ static void NCR5380_main(void *p)
LIST(tmp, hostdata->issue_queue); LIST(tmp, hostdata->issue_queue);
tmp->host_scribble = (unsigned char *) hostdata->issue_queue; tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
hostdata->issue_queue = tmp; hostdata->issue_queue = tmp;
hostdata->time_expires = jiffies + USLEEP_WAITLONG; NCR5380_set_timer(hostdata, USLEEP_WAITLONG);
NCR5380_set_timer(instance);
} }
} /* if hostdata->selecting */ } /* if hostdata->selecting */
if (hostdata->connected if (hostdata->connected
...@@ -1304,8 +1182,7 @@ static void NCR5380_main(void *p) ...@@ -1304,8 +1182,7 @@ static void NCR5380_main(void *p)
break; break;
} while (!done); } while (!done);
if(instance->irq != SCSI_IRQ_NONE) spin_unlock_irq(instance->host_lock);
spin_unlock_irqrestore(instance->host_lock, flags);
} }
#ifndef DONT_USE_INTR #ifndef DONT_USE_INTR
...@@ -1330,12 +1207,13 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1330,12 +1207,13 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
int done; int done;
unsigned char basr; unsigned char basr;
unsigned long flags;
dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq)); dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));
do { do {
done = 1; done = 1;
spin_lock_irq(instance->host_lock); spin_lock_irqsave(instance->host_lock, flags);
/* Look for pending interrupts */ /* Look for pending interrupts */
NCR5380_setup(instance); NCR5380_setup(instance);
basr = NCR5380_read(BUS_AND_STATUS_REG); basr = NCR5380_read(BUS_AND_STATUS_REG);
...@@ -1386,7 +1264,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1386,7 +1264,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
#endif #endif
} }
} /* if BASR_IRQ */ } /* if BASR_IRQ */
spin_unlock_irq(instance->host_lock); spin_unlock_irqrestore(instance->host_lock, flags);
if(!done) if(!done)
schedule_work(&hostdata->coroutine); schedule_work(&hostdata->coroutine);
} while (!done); } while (!done);
...@@ -1469,12 +1347,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1469,12 +1347,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
int err; int err;
NCR5380_setup(instance); NCR5380_setup(instance);
if (hostdata->selecting) { if (hostdata->selecting)
if(instance->irq != SCSI_IRQ_NONE) goto part2;
spin_unlock_irq(instance->host_lock);
goto part2; /* RvC: sorry prof. Dijkstra, but it keeps the
rest of the code nearly the same */
}
hostdata->restart_select = 0; hostdata->restart_select = 0;
...@@ -1495,16 +1369,12 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1495,16 +1369,12 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(MODE_REG, MR_ARBITRATE); NCR5380_write(MODE_REG, MR_ARBITRATE);
if(instance->irq != SCSI_IRQ_NONE)
spin_unlock_irq(instance->host_lock);
/* We can be relaxed here, interrupts are on, we are /* We can be relaxed here, interrupts are on, we are
in workqueue context, the birds are singing in the trees */ in workqueue context, the birds are singing in the trees */
spin_unlock_irq(instance->host_lock);
err = NCR5380_poll_politely(instance, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, 5*HZ); err = NCR5380_poll_politely(instance, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, 5*HZ);
if(instance->irq != SCSI_IRQ_NONE) spin_lock_irq(instance->host_lock);
spin_lock_irq(instance->host_lock);
if (err < 0) { if (err < 0) {
printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__); printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__);
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
...@@ -1628,8 +1498,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1628,8 +1498,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
if (!value && (hostdata->select_time < HZ/4)) { if (!value && (hostdata->select_time < HZ/4)) {
/* RvC: we still must wait for a device response */ /* RvC: we still must wait for a device response */
hostdata->select_time++; /* after 25 ticks the device has failed */ hostdata->select_time++; /* after 25 ticks the device has failed */
hostdata->time_expires = jiffies + 1; NCR5380_set_timer(hostdata, 1);
NCR5380_set_timer(instance);
return 0; /* RvC: we return here with hostdata->selecting set, return 0; /* RvC: we return here with hostdata->selecting set,
to go to sleep */ to go to sleep */
} }
...@@ -1638,8 +1507,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1638,8 +1507,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
waiting period */ waiting period */
if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
if(instance->irq != SCSI_IRQ_NONE)
spin_lock_irq(instance->host_lock);
NCR5380_reselect(instance); NCR5380_reselect(instance);
printk("scsi%d : reselection after won arbitration?\n", instance->host_no); printk("scsi%d : reselection after won arbitration?\n", instance->host_no);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
...@@ -1665,8 +1532,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1665,8 +1532,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1; return -1;
} }
if(instance->irq != SCSI_IRQ_NONE)
spin_lock_irq(instance->host_lock);
cmd->result = DID_BAD_TARGET << 16; cmd->result = DID_BAD_TARGET << 16;
collect_stats(hostdata, cmd); collect_stats(hostdata, cmd);
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
...@@ -1693,11 +1558,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1693,11 +1558,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
*/ */
/* Wait for start of REQ/ACK handshake */ /* Wait for start of REQ/ACK handshake */
spin_unlock_irq(instance->host_lock);
err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
spin_lock_irq(instance->host_lock);
if(err) if(err) {
{ printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__); printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
goto failed; goto failed;
} }
...@@ -1705,9 +1572,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1705,9 +1572,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id)); dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id));
tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->device->lun); tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->device->lun);
if(instance->irq != SCSI_IRQ_NONE)
spin_lock_irq(instance->host_lock);
len = 1; len = 1;
cmd->tag = 0; cmd->tag = 0;
...@@ -1728,8 +1592,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1728,8 +1592,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
/* Selection failed */ /* Selection failed */
failed: failed:
if(instance->irq != SCSI_IRQ_NONE)
spin_lock_irq(instance->host_lock);
return -1; return -1;
} }
...@@ -1805,8 +1667,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase ...@@ -1805,8 +1667,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed); while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed);
if (!(tmp & SR_REQ)) { if (!(tmp & SR_REQ)) {
/* timeout condition */ /* timeout condition */
hostdata->time_expires = jiffies + USLEEP_SLEEP; NCR5380_set_timer(hostdata, USLEEP_SLEEP);
NCR5380_set_timer(instance);
break; break;
} }
...@@ -2644,9 +2505,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2644,9 +2505,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
*/ */
NCR5380_transfer_pio(instance, &phase, &len, &data); NCR5380_transfer_pio(instance, &phase, &len, &data);
if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) { if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) {
hostdata->time_expires = jiffies + USLEEP_SLEEP; NCR5380_set_timer(hostdata, USLEEP_SLEEP);
dprintk(NDEBUG_USLEEP, ("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires)); dprintk(NDEBUG_USLEEP, ("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
NCR5380_set_timer(instance);
return; return;
} }
break; break;
...@@ -2665,9 +2525,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2665,9 +2525,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
/* RvC: go to sleep if polling time expired /* RvC: go to sleep if polling time expired
*/ */
if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) { if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) {
hostdata->time_expires = jiffies + USLEEP_SLEEP; NCR5380_set_timer(hostdata, USLEEP_SLEEP);
dprintk(NDEBUG_USLEEP, ("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires)); dprintk(NDEBUG_USLEEP, ("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
NCR5380_set_timer(instance);
return; return;
} }
} }
......
...@@ -251,7 +251,6 @@ ...@@ -251,7 +251,6 @@
struct NCR5380_hostdata { struct NCR5380_hostdata {
NCR5380_implementation_fields; /* implementation specific */ NCR5380_implementation_fields; /* implementation specific */
struct Scsi_Host *host; /* Host backpointer */ struct Scsi_Host *host; /* Host backpointer */
struct NCR5380_hostdata *next; /* Next in our hot chain */
unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */ unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */
unsigned char targets_present; /* targets we have connected unsigned char targets_present; /* targets we have connected
to, so we can call a select to, so we can call a select
...@@ -270,7 +269,6 @@ struct NCR5380_hostdata { ...@@ -270,7 +269,6 @@ struct NCR5380_hostdata {
volatile unsigned aborted:1; /* flag, says aborted */ volatile unsigned aborted:1; /* flag, says aborted */
int flags; int flags;
unsigned long time_expires; /* in jiffies, set prior to sleeping */ unsigned long time_expires; /* in jiffies, set prior to sleeping */
struct Scsi_Host *next_timer;
int select_time; /* timer in select for target response */ int select_time; /* timer in select for target response */
volatile Scsi_Cmnd *selecting; volatile Scsi_Cmnd *selecting;
struct work_struct coroutine; /* our co-routine */ struct work_struct coroutine; /* our co-routine */
...@@ -295,6 +293,7 @@ struct NCR5380_hostdata { ...@@ -295,6 +293,7 @@ struct NCR5380_hostdata {
static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible); static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
#endif #endif
static int NCR5380_init(struct Scsi_Host *instance, int flags); static int NCR5380_init(struct Scsi_Host *instance, int flags);
static void NCR5380_exit(struct Scsi_Host *instance);
static void NCR5380_information_transfer(struct Scsi_Host *instance); static void NCR5380_information_transfer(struct Scsi_Host *instance);
#ifndef DONT_USE_INTR #ifndef DONT_USE_INTR
static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
......
...@@ -321,6 +321,7 @@ static void __devexit cumanascsi1_remove(struct expansion_card *ec) ...@@ -321,6 +321,7 @@ static void __devexit cumanascsi1_remove(struct expansion_card *ec)
scsi_remove_host(host); scsi_remove_host(host);
free_irq(host->irq, host); free_irq(host->irq, host);
NCR5380_exit(host);
release_region(host->io_port, host->n_io_port); release_region(host->io_port, host->n_io_port);
scsi_host_put(host); scsi_host_put(host);
} }
......
...@@ -222,6 +222,7 @@ static void __exit ecoscsi_exit(void) ...@@ -222,6 +222,7 @@ static void __exit ecoscsi_exit(void)
if (shpnt->irq != IRQ_NONE) if (shpnt->irq != IRQ_NONE)
free_irq(shpnt->irq, NULL); free_irq(shpnt->irq, NULL);
NCR5380_exit(host);
if (shpnt->io_port) if (shpnt->io_port)
release_region(shpnt->io_port, shpnt->n_io_port); release_region(shpnt->io_port, shpnt->n_io_port);
......
...@@ -179,6 +179,7 @@ static void __devexit oakscsi_remove(struct expansion_card *ec) ...@@ -179,6 +179,7 @@ static void __devexit oakscsi_remove(struct expansion_card *ec)
ecard_set_drvdata(ec, NULL); ecard_set_drvdata(ec, NULL);
scsi_remove_host(host); scsi_remove_host(host);
NCR5380_exit(host);
release_region(host->io_port, host->n_io_port); release_region(host->io_port, host->n_io_port);
scsi_host_put(host); scsi_host_put(host);
} }
......
...@@ -106,9 +106,10 @@ static const char * dmx3191d_info(struct Scsi_Host *host) { ...@@ -106,9 +106,10 @@ static const char * dmx3191d_info(struct Scsi_Host *host) {
static int dmx3191d_release_resources(struct Scsi_Host *instance) static int dmx3191d_release_resources(struct Scsi_Host *instance)
{ {
release_region(instance->io_port, DMX3191D_REGION);
if(instance->irq!=SCSI_IRQ_NONE) if(instance->irq!=SCSI_IRQ_NONE)
free_irq(instance->irq, instance); free_irq(instance->irq, instance);
NCR5380_exit(instance);
release_region(instance->io_port, DMX3191D_REGION);
return 0; return 0;
} }
......
...@@ -451,6 +451,7 @@ static int dtc_release(struct Scsi_Host *shost) ...@@ -451,6 +451,7 @@ static int dtc_release(struct Scsi_Host *shost)
{ {
if (shost->irq) if (shost->irq)
free_irq(shost->irq, NULL); free_irq(shost->irq, NULL);
NCR5380_exit(shost);
if (shost->io_port && shost->n_io_port) if (shost->io_port && shost->n_io_port)
release_region(shost->io_port, shost->n_io_port); release_region(shost->io_port, shost->n_io_port);
scsi_unregister(shost); scsi_unregister(shost);
......
...@@ -501,6 +501,10 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance) ...@@ -501,6 +501,10 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance)
{ {
NCR5380_local_declare(); NCR5380_local_declare();
NCR5380_setup(instance); NCR5380_setup(instance);
if (instance->irq != SCSI_IRQ_NONE)
free_irq(instance->irq, NULL);
NCR5380_exit(instance);
#ifndef CONFIG_SCSI_G_NCR5380_MEM #ifndef CONFIG_SCSI_G_NCR5380_MEM
release_region(instance->NCR5380_instance_name, instance->n_io_port); release_region(instance->NCR5380_instance_name, instance->n_io_port);
...@@ -508,8 +512,6 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance) ...@@ -508,8 +512,6 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance)
release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size); release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size);
#endif #endif
if (instance->irq != SCSI_IRQ_NONE)
free_irq(instance->irq, NULL);
return 0; return 0;
} }
......
...@@ -326,6 +326,7 @@ int macscsi_release (struct Scsi_Host *shpnt) ...@@ -326,6 +326,7 @@ int macscsi_release (struct Scsi_Host *shpnt)
{ {
if (shpnt->irq != SCSI_IRQ_NONE) if (shpnt->irq != SCSI_IRQ_NONE)
free_irq (shpnt->irq, NCR5380_intr); free_irq (shpnt->irq, NCR5380_intr);
NCR5380_exit(shpnt);
return 0; return 0;
} }
......
...@@ -605,6 +605,7 @@ static int pas16_release(struct Scsi_Host *shost) ...@@ -605,6 +605,7 @@ static int pas16_release(struct Scsi_Host *shost)
{ {
if (shost->irq) if (shost->irq)
free_irq(shost->irq, NULL); free_irq(shost->irq, NULL);
NCR5380_exit(shost);
if (shost->dma_channel != 0xff) if (shost->dma_channel != 0xff)
free_dma(shost->dma_channel); free_dma(shost->dma_channel);
if (shost->io_port && shost->n_io_port) if (shost->io_port && shost->n_io_port)
......
...@@ -284,6 +284,7 @@ static int t128_release(struct Scsi_Host *shost) ...@@ -284,6 +284,7 @@ static int t128_release(struct Scsi_Host *shost)
{ {
if (shost->irq) if (shost->irq)
free_irq(shost->irq, NULL); free_irq(shost->irq, NULL);
NCR5380_exit(shost);
if (shost->io_port && shost->n_io_port) if (shost->io_port && shost->n_io_port)
release_region(shost->io_port, shost->n_io_port); release_region(shost->io_port, shost->n_io_port);
scsi_unregister(shost); scsi_unregister(shost);
......
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