Commit e2482fa1 authored by Jürgen E. Fischer's avatar Jürgen E. Fischer Committed by James Bottomley

[SCSI] aha152x: fix variable use before initialisation and other bugs

- change interface of the reset functions from Scsi_Cmnd to Scsi_Host.
- add functions with the original interface and rename the new
  functions to reflect the new interface.
- call these from the pcmcia driver, thereby avoiding the need to
  construct a (broken) Scsi_Cmnd from a Scsi_Host.
- just run the bh if the interrupt is from the controller and if so
  ensure that it's only called once per interrupt.
Signed-off-by: default avatarJuergen E. Fischer <fischer@linux-buechse.de>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 23ff51e9
...@@ -1260,16 +1260,15 @@ static void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs) ...@@ -1260,16 +1260,15 @@ static void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs)
* Reset the bus * Reset the bus
* *
*/ */
static int aha152x_bus_reset(Scsi_Cmnd *SCpnt) static int aha152x_bus_reset_host(struct Scsi_Host *shpnt)
{ {
struct Scsi_Host *shpnt = SCpnt->device->host;
unsigned long flags; unsigned long flags;
DO_LOCK(flags); DO_LOCK(flags);
#if defined(AHA152X_DEBUG) #if defined(AHA152X_DEBUG)
if(HOSTDATA(shpnt)->debug & debug_eh) { if(HOSTDATA(shpnt)->debug & debug_eh) {
printk(DEBUG_LEAD "aha152x_bus_reset(%p)", CMDINFO(SCpnt), SCpnt); printk(KERN_DEBUG "scsi%d: bus reset", shpnt->host_no);
show_queues(shpnt); show_queues(shpnt);
} }
#endif #endif
...@@ -1277,14 +1276,14 @@ static int aha152x_bus_reset(Scsi_Cmnd *SCpnt) ...@@ -1277,14 +1276,14 @@ static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
free_hard_reset_SCs(shpnt, &ISSUE_SC); free_hard_reset_SCs(shpnt, &ISSUE_SC);
free_hard_reset_SCs(shpnt, &DISCONNECTED_SC); free_hard_reset_SCs(shpnt, &DISCONNECTED_SC);
DPRINTK(debug_eh, DEBUG_LEAD "resetting bus\n", CMDINFO(SCpnt)); DPRINTK(debug_eh, KERN_DEBUG "scsi%d: resetting bus\n", shpnt->host_no);
SETPORT(SCSISEQ, SCSIRSTO); SETPORT(SCSISEQ, SCSIRSTO);
mdelay(256); mdelay(256);
SETPORT(SCSISEQ, 0); SETPORT(SCSISEQ, 0);
mdelay(DELAY); mdelay(DELAY);
DPRINTK(debug_eh, DEBUG_LEAD "bus resetted\n", CMDINFO(SCpnt)); DPRINTK(debug_eh, KERN_DEBUG "scsi%d: bus resetted\n", shpnt->host_no);
setup_expected_interrupts(shpnt); setup_expected_interrupts(shpnt);
if(HOSTDATA(shpnt)->commands==0) if(HOSTDATA(shpnt)->commands==0)
...@@ -1295,6 +1294,14 @@ static int aha152x_bus_reset(Scsi_Cmnd *SCpnt) ...@@ -1295,6 +1294,14 @@ static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
return SUCCESS; return SUCCESS;
} }
/*
* Reset the bus
*
*/
static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
{
return aha152x_bus_reset_host(SCpnt->device->host);
}
/* /*
* Restore default values to the AIC-6260 registers and reset the fifos * Restore default values to the AIC-6260 registers and reset the fifos
...@@ -1337,22 +1344,27 @@ static void reset_ports(struct Scsi_Host *shpnt) ...@@ -1337,22 +1344,27 @@ static void reset_ports(struct Scsi_Host *shpnt)
* Reset the host (bus and controller) * Reset the host (bus and controller)
* *
*/ */
int aha152x_host_reset(Scsi_Cmnd * SCpnt) int aha152x_host_reset_host(struct Scsi_Host *shpnt)
{ {
#if defined(AHA152X_DEBUG) DPRINTK(debug_eh, KERN_DEBUG "scsi%d: host reset\n", shpnt->host_no);
struct Scsi_Host *shpnt = SCpnt->device->host;
#endif
DPRINTK(debug_eh, DEBUG_LEAD "aha152x_host_reset(%p)\n", CMDINFO(SCpnt), SCpnt);
aha152x_bus_reset(SCpnt); aha152x_bus_reset_host(shpnt);
DPRINTK(debug_eh, DEBUG_LEAD "resetting ports\n", CMDINFO(SCpnt)); DPRINTK(debug_eh, KERN_DEBUG "scsi%d: resetting ports\n", shpnt->host_no);
reset_ports(SCpnt->device->host); reset_ports(shpnt);
return SUCCESS; return SUCCESS;
} }
/*
* Reset the host (bus and controller)
*
*/
static int aha152x_host_reset(Scsi_Cmnd *SCpnt)
{
return aha152x_host_reset_host(SCpnt->device->host);
}
/* /*
* Return the "logical geometry" * Return the "logical geometry"
* *
...@@ -1431,22 +1443,18 @@ static void run(void) ...@@ -1431,22 +1443,18 @@ static void run(void)
{ {
int i; int i;
for (i = 0; i<ARRAY_SIZE(aha152x_host); i++) { for (i = 0; i<ARRAY_SIZE(aha152x_host); i++) {
struct Scsi_Host *shpnt = aha152x_host[i]; is_complete(aha152x_host[i]);
if (shpnt && HOSTDATA(shpnt)->service) {
HOSTDATA(shpnt)->service=0;
is_complete(shpnt);
}
} }
} }
/* /*
* Interrupts handler * Interrupt handler
* *
*/ */
static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs) static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs)
{ {
struct Scsi_Host *shpnt = lookup_irq(irqno); struct Scsi_Host *shpnt = lookup_irq(irqno);
unsigned long flags;
unsigned char rev, dmacntrl0; unsigned char rev, dmacntrl0;
if (!shpnt) { if (!shpnt) {
...@@ -1472,23 +1480,23 @@ static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs) ...@@ -1472,23 +1480,23 @@ static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs)
if ((rev == 0xFF) && (dmacntrl0 == 0xFF)) if ((rev == 0xFF) && (dmacntrl0 == 0xFF))
return IRQ_NONE; return IRQ_NONE;
if( TESTLO(DMASTAT, INTSTAT) )
return IRQ_NONE;
/* no more interrupts from the controller, while we're busy. /* no more interrupts from the controller, while we're busy.
INTEN is restored by the BH handler */ INTEN is restored by the BH handler */
CLRBITS(DMACNTRL0, INTEN); CLRBITS(DMACNTRL0, INTEN);
#if 0 DO_LOCK(flags);
/* check if there is already something to be if( HOSTDATA(shpnt)->service==0 ) {
serviced; should not happen */ HOSTDATA(shpnt)->service=1;
if(HOSTDATA(shpnt)->service) {
printk(KERN_ERR "aha152x%d: lost interrupt (%d)\n", HOSTNO, HOSTDATA(shpnt)->service); /* Poke the BH handler */
show_queues(shpnt); INIT_WORK(&aha152x_tq, (void *) run, NULL);
schedule_work(&aha152x_tq);
} }
#endif DO_UNLOCK(flags);
/* Poke the BH handler */
HOSTDATA(shpnt)->service++;
INIT_WORK(&aha152x_tq, (void *) run, NULL);
schedule_work(&aha152x_tq);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -2527,7 +2535,18 @@ static void is_complete(struct Scsi_Host *shpnt) ...@@ -2527,7 +2535,18 @@ static void is_complete(struct Scsi_Host *shpnt)
unsigned long flags; unsigned long flags;
int pending; int pending;
if(!shpnt)
return;
DO_LOCK(flags); DO_LOCK(flags);
if( HOSTDATA(shpnt)->service==0 ) {
DO_UNLOCK(flags);
return;
}
HOSTDATA(shpnt)->service = 0;
if(HOSTDATA(shpnt)->in_intr) { if(HOSTDATA(shpnt)->in_intr) {
DO_UNLOCK(flags); DO_UNLOCK(flags);
/* aha152x_error never returns.. */ /* aha152x_error never returns.. */
......
...@@ -332,6 +332,6 @@ struct aha152x_setup { ...@@ -332,6 +332,6 @@ struct aha152x_setup {
struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *); struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *);
void aha152x_release(struct Scsi_Host *); void aha152x_release(struct Scsi_Host *);
int aha152x_host_reset(Scsi_Cmnd *); int aha152x_host_reset_host(struct Scsi_Host *);
#endif /* _AHA152X_H */ #endif /* _AHA152X_H */
...@@ -275,10 +275,8 @@ static int aha152x_resume(struct pcmcia_device *dev) ...@@ -275,10 +275,8 @@ static int aha152x_resume(struct pcmcia_device *dev)
link->state &= ~DEV_SUSPEND; link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
Scsi_Cmnd tmp;
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
tmp.device->host = info->host; aha152x_host_reset_host(info->host);
aha152x_host_reset(&tmp);
} }
return 0; return 0;
......
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