Commit 73c8ae7c authored by Alan Cox's avatar Alan Cox Committed by James Simmons

[PATCH] first pass over the in2000

- new locking
- new_eh
- use ->page/->offset
parent ff64a6e3
...@@ -317,13 +317,15 @@ uchar result; ...@@ -317,13 +317,15 @@ uchar result;
static void in2000_execute(struct Scsi_Host *instance); static void in2000_execute(struct Scsi_Host *instance);
int in2000_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) static int in2000_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
{ {
struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata; struct IN2000_hostdata *hostdata;
Scsi_Cmnd *tmp; Scsi_Cmnd *tmp;
unsigned long flags; unsigned long flags;
hostdata = (struct IN2000_hostdata *)cmd->host->hostdata; instance = cmd->host;
hostdata = (struct IN2000_hostdata *)instance->hostdata;
DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid)) DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
...@@ -355,7 +357,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid)) ...@@ -355,7 +357,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
if (cmd->use_sg) { if (cmd->use_sg) {
cmd->SCp.buffer = (struct scatterlist *)cmd->buffer; cmd->SCp.buffer = (struct scatterlist *)cmd->buffer;
cmd->SCp.buffers_residual = cmd->use_sg - 1; cmd->SCp.buffers_residual = cmd->use_sg - 1;
cmd->SCp.ptr = (char *)cmd->SCp.buffer->address; cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+cmd->SCp.buffer->offset;
cmd->SCp.this_residual = cmd->SCp.buffer->length; cmd->SCp.this_residual = cmd->SCp.buffer->length;
} }
else { else {
...@@ -391,9 +393,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid)) ...@@ -391,9 +393,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
* queue and calling in2000_execute(). * queue and calling in2000_execute().
*/ */
save_flags(flags); spin_lock_irqsave(instance->host_lock, flags);
cli();
/* /*
* Add the cmd to the end of 'input_Q'. Note that REQUEST_SENSE * Add the cmd to the end of 'input_Q'. Note that REQUEST_SENSE
* commands are added to the head of the queue so that the desired * commands are added to the head of the queue so that the desired
...@@ -418,8 +418,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid)) ...@@ -418,8 +418,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
in2000_execute(cmd->host); in2000_execute(cmd->host);
DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid)) DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
spin_unlock_irqrestore(instance->host_lock, flags);
restore_flags(flags);
return 0; return 0;
} }
...@@ -762,7 +761,7 @@ int i; ...@@ -762,7 +761,7 @@ int i;
++cmd->SCp.buffer; ++cmd->SCp.buffer;
--cmd->SCp.buffers_residual; --cmd->SCp.buffers_residual;
cmd->SCp.this_residual = cmd->SCp.buffer->length; cmd->SCp.this_residual = cmd->SCp.buffer->length;
cmd->SCp.ptr = cmd->SCp.buffer->address; cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
} }
/* Set up hardware registers */ /* Set up hardware registers */
...@@ -855,7 +854,7 @@ unsigned long flags; ...@@ -855,7 +854,7 @@ unsigned long flags;
/* Get the spin_lock and disable further ints, for SMP */ /* Get the spin_lock and disable further ints, for SMP */
CLISPIN_LOCK(instance, flags); spin_lock_irqsave(instance->host_lock, flags);
#ifdef PROC_STATISTICS #ifdef PROC_STATISTICS
hostdata->int_cnt++; hostdata->int_cnt++;
...@@ -993,7 +992,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT))) ...@@ -993,7 +992,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
write1_io(0, IO_LED_OFF); write1_io(0, IO_LED_OFF);
/* release the SMP spin_lock and restore irq state */ /* release the SMP spin_lock and restore irq state */
CLISPIN_UNLOCK(instance, flags); spin_unlock_irqrestore(instance->host_lock, flags);
return; return;
} }
...@@ -1011,7 +1010,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT))) ...@@ -1011,7 +1010,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
write1_io(0, IO_LED_OFF); write1_io(0, IO_LED_OFF);
/* release the SMP spin_lock and restore irq state */ /* release the SMP spin_lock and restore irq state */
CLISPIN_UNLOCK(instance, flags); spin_unlock_irqrestore(instance->host_lock, flags);
return; return;
} }
...@@ -1433,7 +1432,7 @@ DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0])) ...@@ -1433,7 +1432,7 @@ DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
hostdata->state = S_UNCONNECTED; hostdata->state = S_UNCONNECTED;
/* release the SMP spin_lock and restore irq state */ /* release the SMP spin_lock and restore irq state */
CLISPIN_UNLOCK(instance, flags); spin_unlock_irqrestore(instance->host_lock, flags);
return; return;
} }
DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid)) DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
...@@ -1609,7 +1608,7 @@ DB(DB_INTR,printk("-%ld",cmd->pid)) ...@@ -1609,7 +1608,7 @@ DB(DB_INTR,printk("-%ld",cmd->pid))
DB(DB_INTR,printk("} ")) DB(DB_INTR,printk("} "))
/* release the SMP spin_lock and restore irq state */ /* release the SMP spin_lock and restore irq state */
CLISPIN_UNLOCK(instance, flags); spin_unlock_irqrestore(instance->host_lock, flags);
} }
...@@ -1619,11 +1618,14 @@ DB(DB_INTR,printk("} ")) ...@@ -1619,11 +1618,14 @@ DB(DB_INTR,printk("} "))
#define RESET_CARD_AND_BUS 1 #define RESET_CARD_AND_BUS 1
#define B_FLAG 0x80 #define B_FLAG 0x80
/*
* Caller must hold instance lock!
*/
static int reset_hardware(struct Scsi_Host *instance, int type) static int reset_hardware(struct Scsi_Host *instance, int type)
{ {
struct IN2000_hostdata *hostdata; struct IN2000_hostdata *hostdata;
int qt,x; int qt,x;
unsigned long flags;
hostdata = (struct IN2000_hostdata *)instance->hostdata; hostdata = (struct IN2000_hostdata *)instance->hostdata;
...@@ -1638,16 +1640,16 @@ unsigned long flags; ...@@ -1638,16 +1640,16 @@ unsigned long flags;
write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER, write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER,
calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF)); calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF));
save_flags(flags);
cli();
write1_io(0,IO_FIFO_WRITE); /* clear fifo counter */ write1_io(0,IO_FIFO_WRITE); /* clear fifo counter */
write1_io(0,IO_FIFO_READ); /* start fifo out in read mode */ write1_io(0,IO_FIFO_READ); /* start fifo out in read mode */
write_3393(hostdata,WD_COMMAND, WD_CMD_RESET); write_3393(hostdata,WD_COMMAND, WD_CMD_RESET);
/* FIXME: timeout ?? */
while (!(READ_AUX_STAT() & ASR_INT)) while (!(READ_AUX_STAT() & ASR_INT))
; /* wait for RESET to complete */ cpu_relax(); /* wait for RESET to complete */
x = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */ x = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */
restore_flags(flags);
write_3393(hostdata,WD_QUEUE_TAG,0xa5); /* any random number */ write_3393(hostdata,WD_QUEUE_TAG,0xa5); /* any random number */
qt = read_3393(hostdata,WD_QUEUE_TAG); qt = read_3393(hostdata,WD_QUEUE_TAG);
if (qt == 0xa5) { if (qt == 0xa5) {
...@@ -1662,7 +1664,7 @@ unsigned long flags; ...@@ -1662,7 +1664,7 @@ unsigned long flags;
int in2000_reset(Scsi_Cmnd *cmd, unsigned int reset_flags) static int in2000_bus_reset(Scsi_Cmnd *cmd)
{ {
unsigned long flags; unsigned long flags;
struct Scsi_Host *instance; struct Scsi_Host *instance;
...@@ -1672,10 +1674,9 @@ int x; ...@@ -1672,10 +1674,9 @@ int x;
instance = cmd->host; instance = cmd->host;
hostdata = (struct IN2000_hostdata *)instance->hostdata; hostdata = (struct IN2000_hostdata *)instance->hostdata;
printk("scsi%d: Reset. ", instance->host_no); printk(KERN_WARNING "scsi%d: Reset. ", instance->host_no);
save_flags(flags);
cli();
spin_lock_irqsave(instance->host_lock, flags);
/* do scsi-reset here */ /* do scsi-reset here */
reset_hardware(instance, RESET_CARD_AND_BUS); reset_hardware(instance, RESET_CARD_AND_BUS);
...@@ -1694,13 +1695,22 @@ int x; ...@@ -1694,13 +1695,22 @@ int x;
hostdata->outgoing_len = 0; hostdata->outgoing_len = 0;
cmd->result = DID_RESET << 16; cmd->result = DID_RESET << 16;
restore_flags(flags); spin_unlock_irqrestore(instance->host_lock, flags);
return 0; return SUCCESS;
}
static int in2000_host_reset(Scsi_Cmnd *cmd)
{
return FAILED;
} }
static int in2000_device_reset(Scsi_Cmnd *cmd)
{
return FAILED;
}
int in2000_abort (Scsi_Cmnd *cmd) static int in2000_abort (Scsi_Cmnd *cmd)
{ {
struct Scsi_Host *instance; struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata; struct IN2000_hostdata *hostdata;
...@@ -1709,13 +1719,10 @@ unsigned long flags; ...@@ -1709,13 +1719,10 @@ unsigned long flags;
uchar sr, asr; uchar sr, asr;
unsigned long timeout; unsigned long timeout;
save_flags (flags);
cli();
instance = cmd->host; instance = cmd->host;
hostdata = (struct IN2000_hostdata *)instance->hostdata; hostdata = (struct IN2000_hostdata *)instance->hostdata;
printk ("scsi%d: Abort-", instance->host_no); printk(KERN_DEBUG "scsi%d: Abort-", instance->host_no);
printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ", printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ",
READ_AUX_STAT(),read_3393_count(hostdata),cmd->SCp.this_residual,cmd->SCp.buffers_residual, READ_AUX_STAT(),read_3393_count(hostdata),cmd->SCp.this_residual,cmd->SCp.buffers_residual,
cmd->SCp.have_data_in,read1_io(IO_FIFO_COUNT)); cmd->SCp.have_data_in,read1_io(IO_FIFO_COUNT));
...@@ -1725,6 +1732,7 @@ unsigned long timeout; ...@@ -1725,6 +1732,7 @@ unsigned long timeout;
* from the inout_Q. * from the inout_Q.
*/ */
spin_lock_irqsave(instance->host_lock, flags);
tmp = (Scsi_Cmnd *)hostdata->input_Q; tmp = (Scsi_Cmnd *)hostdata->input_Q;
prev = 0; prev = 0;
while (tmp) { while (tmp) {
...@@ -1733,11 +1741,11 @@ unsigned long timeout; ...@@ -1733,11 +1741,11 @@ unsigned long timeout;
prev->host_scribble = cmd->host_scribble; prev->host_scribble = cmd->host_scribble;
cmd->host_scribble = NULL; cmd->host_scribble = NULL;
cmd->result = DID_ABORT << 16; cmd->result = DID_ABORT << 16;
printk("scsi%d: Abort - removing command %ld from input_Q. ", printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ",
instance->host_no, cmd->pid); instance->host_no, cmd->pid);
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
restore_flags(flags); spin_unlock_irqrestore(instance->host_lock, flags);
return SCSI_ABORT_SUCCESS; return SUCCESS;
} }
prev = tmp; prev = tmp;
tmp = (Scsi_Cmnd *)tmp->host_scribble; tmp = (Scsi_Cmnd *)tmp->host_scribble;
...@@ -1756,7 +1764,7 @@ unsigned long timeout; ...@@ -1756,7 +1764,7 @@ unsigned long timeout;
if (hostdata->connected == cmd) { if (hostdata->connected == cmd) {
printk("scsi%d: Aborting connected command %ld - ", printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ",
instance->host_no, cmd->pid); instance->host_no, cmd->pid);
printk("sending wd33c93 ABORT command - "); printk("sending wd33c93 ABORT command - ");
...@@ -1800,7 +1808,6 @@ unsigned long timeout; ...@@ -1800,7 +1808,6 @@ unsigned long timeout;
in2000_execute (instance); in2000_execute (instance);
restore_flags(flags);
return SCSI_ABORT_SUCCESS; return SCSI_ABORT_SUCCESS;
} }
...@@ -1813,9 +1820,9 @@ unsigned long timeout; ...@@ -1813,9 +1820,9 @@ unsigned long timeout;
for (tmp=(Scsi_Cmnd *)hostdata->disconnected_Q; tmp; for (tmp=(Scsi_Cmnd *)hostdata->disconnected_Q; tmp;
tmp=(Scsi_Cmnd *)tmp->host_scribble) tmp=(Scsi_Cmnd *)tmp->host_scribble)
if (cmd == tmp) { if (cmd == tmp) {
restore_flags(flags); spin_unlock_irqrestore(instance->host_lock, flags);
printk("Sending ABORT_SNOOZE. "); printk(KERN_DEBUG "scsi%d: unable to abort disconnected command.\n", instance->host_no);
return SCSI_ABORT_SNOOZE; return FAILED;
} }
/* /*
...@@ -1830,10 +1837,10 @@ unsigned long timeout; ...@@ -1830,10 +1837,10 @@ unsigned long timeout;
in2000_execute (instance); in2000_execute (instance);
restore_flags(flags); spin_unlock_irqrestore(instance->host_lock, flags);
printk("scsi%d: warning : SCSI command probably completed successfully" printk("scsi%d: warning : SCSI command probably completed successfully"
" before abortion. ", instance->host_no); " before abortion. ", instance->host_no);
return SCSI_ABORT_NOT_RUNNING; return SUCCESS;
} }
...@@ -1845,7 +1852,7 @@ static char setup_buffer[SETUP_BUFFER_SIZE]; ...@@ -1845,7 +1852,7 @@ static char setup_buffer[SETUP_BUFFER_SIZE];
static char setup_used[MAX_SETUP_ARGS]; static char setup_used[MAX_SETUP_ARGS];
static int done_setup = 0; static int done_setup = 0;
void __init in2000_setup (char *str, int *ints) static void __init in2000_setup (char *str, int *ints)
{ {
int i; int i;
char *p1,*p2; char *p1,*p2;
...@@ -1931,7 +1938,7 @@ static const int int_tab[] in2000__INITDATA = { ...@@ -1931,7 +1938,7 @@ static const int int_tab[] in2000__INITDATA = {
}; };
int __init in2000_detect(Scsi_Host_Template * tpnt) static int __init in2000_detect(Scsi_Host_Template * tpnt)
{ {
struct Scsi_Host *instance; struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata; struct IN2000_hostdata *hostdata;
...@@ -2115,7 +2122,11 @@ char buf[32]; ...@@ -2115,7 +2122,11 @@ char buf[32];
#endif #endif
/* FIXME: not strictly needed I think but the called code expects
to be locked */
spin_lock_irqsave(instance->host_lock, flags);
x = reset_hardware(instance,(hostdata->args & A_NO_SCSI_RESET)?RESET_CARD:RESET_CARD_AND_BUS); x = reset_hardware(instance,(hostdata->args & A_NO_SCSI_RESET)?RESET_CARD:RESET_CARD_AND_BUS);
spin_unlock_irqrestore(instance->host_lock, flags);
hostdata->microcode = read_3393(hostdata,WD_CDB_1); hostdata->microcode = read_3393(hostdata,WD_CDB_1);
if (x & 0x01) { if (x & 0x01) {
...@@ -2158,7 +2169,7 @@ char buf[32]; ...@@ -2158,7 +2169,7 @@ char buf[32];
* supposed to do... * supposed to do...
*/ */
int in2000_biosparam(Disk *disk, struct block_device *dev, int *iinfo) static int in2000_biosparam(Disk *disk, struct block_device *dev, int *iinfo)
{ {
int size; int size;
...@@ -2190,7 +2201,7 @@ int size; ...@@ -2190,7 +2201,7 @@ int size;
} }
int in2000_proc_info(char *buf, char **start, off_t off, int len, int hn, int in) static int in2000_proc_info(char *buf, char **start, off_t off, int len, int hn, int in)
{ {
#ifdef PROC_INTERFACE #ifdef PROC_INTERFACE
...@@ -2260,8 +2271,7 @@ static int stop = 0; ...@@ -2260,8 +2271,7 @@ static int stop = 0;
return len; return len;
} }
save_flags(flags); spin_lock_irqsave(instance->host_lock, flags);
cli();
bp = buf; bp = buf;
*bp = '\0'; *bp = '\0';
if (hd->proc & PR_VERSION) { if (hd->proc & PR_VERSION) {
...@@ -2340,7 +2350,7 @@ static int stop = 0; ...@@ -2340,7 +2350,7 @@ static int stop = 0;
; /* insert your own custom function here */ ; /* insert your own custom function here */
} }
strcat(bp,"\n"); strcat(bp,"\n");
restore_flags(flags); spin_unlock_irqrestore(instance->host_lock, flags);
*start = buf; *start = buf;
if (stop) { if (stop) {
stop = 0; stop = 0;
......
...@@ -397,13 +397,15 @@ struct IN2000_hostdata { ...@@ -397,13 +397,15 @@ struct IN2000_hostdata {
# define CLISPIN_UNLOCK(host,flags) spin_unlock_irqrestore(host->host_lock, \ # define CLISPIN_UNLOCK(host,flags) spin_unlock_irqrestore(host->host_lock, \
flags) flags)
int in2000_detect(Scsi_Host_Template *) in2000__INIT; static int in2000_detect(Scsi_Host_Template *) in2000__INIT;
int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int in2000_abort(Scsi_Cmnd *); static int in2000_abort(Scsi_Cmnd *);
void in2000_setup(char *, int *) in2000__INIT; static void in2000_setup(char *, int *) in2000__INIT;
int in2000_proc_info(char *, char **, off_t, int, int, int); static int in2000_proc_info(char *, char **, off_t, int, int, int);
int in2000_biosparam(struct scsi_disk *, struct block_device *, int *); static int in2000_biosparam(struct scsi_disk *, struct block_device *, int *);
int in2000_reset(Scsi_Cmnd *, unsigned int); static int in2000_host_reset(Scsi_Cmnd *);
static int in2000_bus_reset(Scsi_Cmnd *);
static int in2000_device_reset(Scsi_Cmnd *);
#define IN2000_CAN_Q 16 #define IN2000_CAN_Q 16
...@@ -416,8 +418,10 @@ int in2000_reset(Scsi_Cmnd *, unsigned int); ...@@ -416,8 +418,10 @@ int in2000_reset(Scsi_Cmnd *, unsigned int);
name: "Always IN2000", /* device name */ \ name: "Always IN2000", /* device name */ \
detect: in2000_detect, /* returns number of in2000's found */ \ detect: in2000_detect, /* returns number of in2000's found */ \
queuecommand: in2000_queuecommand, /* queue scsi command, don't wait */ \ queuecommand: in2000_queuecommand, /* queue scsi command, don't wait */ \
abort: in2000_abort, /* abort current command */ \ eh_abort_handler: in2000_abort, /* abort current command */ \
reset: in2000_reset, /* reset scsi bus */ \ eh_bus_reset_handler: in2000_bus_reset, /* reset scsi bus */ \
eh_device_reset_handler: in2000_device_reset, /* reset scsi device */ \
eh_host_reset_handler: in2000_host_reset, /* reset scsi hba */ \
bios_param: in2000_biosparam, /* figures out BIOS parameters for lilo, etc */ \ bios_param: in2000_biosparam, /* figures out BIOS parameters for lilo, etc */ \
can_queue: IN2000_CAN_Q, /* max commands we can queue up */ \ can_queue: IN2000_CAN_Q, /* max commands we can queue up */ \
this_id: IN2000_HOST_ID, /* host-adapter scsi id */ \ this_id: IN2000_HOST_ID, /* host-adapter scsi id */ \
......
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