Commit d766247d authored by Russell King's avatar Russell King

[ARM] Fix two Acorn SCSI drivers

ARXESCSI does not have the interrupt routed to the host
machine, so we need to babysit the host interface.  We
do this via a variant of the normal command function in
fas216.c

Fix a bug in the procfs file handling in the EESOX SCSI
driver.
parent 562f3869
...@@ -237,7 +237,7 @@ static const char *arxescsi_info(struct Scsi_Host *host) ...@@ -237,7 +237,7 @@ static const char *arxescsi_info(struct Scsi_Host *host)
*/ */
static int static int
arxescsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, arxescsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length,
int host_no, int inout) int inout)
{ {
struct arxescsi_info *info; struct arxescsi_info *info;
char *p = buffer; char *p = buffer;
...@@ -264,7 +264,7 @@ static Scsi_Host_Template arxescsi_template = { ...@@ -264,7 +264,7 @@ static Scsi_Host_Template arxescsi_template = {
.proc_info = arxescsi_proc_info, .proc_info = arxescsi_proc_info,
.name = "ARXE SCSI card", .name = "ARXE SCSI card",
.info = arxescsi_info, .info = arxescsi_info,
.queuecommand = fas216_queue_command, .queuecommand = fas216_noqueue_command,
.eh_host_reset_handler = fas216_eh_host_reset, .eh_host_reset_handler = fas216_eh_host_reset,
.eh_bus_reset_handler = fas216_eh_bus_reset, .eh_bus_reset_handler = fas216_eh_bus_reset,
.eh_device_reset_handler = fas216_eh_device_reset, .eh_device_reset_handler = fas216_eh_device_reset,
......
...@@ -444,10 +444,11 @@ int eesoxscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_ ...@@ -444,10 +444,11 @@ int eesoxscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_
p += sprintf(p, "Term : o%s\n", p += sprintf(p, "Term : o%s\n",
info->control & EESOX_TERM_ENABLE ? "n" : "ff"); info->control & EESOX_TERM_ENABLE ? "n" : "ff");
pos += fas216_print_stats(&info->info, buffer + pos);
p += fas216_print_stats(&info->info, p); p += fas216_print_stats(&info->info, p);
p += fas216_print_devices(&info->info, p); p += fas216_print_devices(&info->info, p);
*start = buffer + offset;
pos = p - buffer - offset;
if (pos > length) if (pos > length)
pos = length; pos = length;
......
...@@ -225,7 +225,8 @@ static void fas216_dumpinfo(FAS216_Info *info) ...@@ -225,7 +225,8 @@ static void fas216_dumpinfo(FAS216_Info *info)
printk(" dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n", printk(" dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n",
info->dma.transfer_type, info->dma.setup, info->dma.transfer_type, info->dma.setup,
info->dma.pseudo, info->dma.stop); info->dma.pseudo, info->dma.stop);
printk(" magic_end=%lX }\n", info->magic_end); printk(" internal_done=%X magic_end=%lX }\n",
info->internal_done, info->magic_end);
} }
#ifdef CHECK_STRUCTURE #ifdef CHECK_STRUCTURE
...@@ -2252,6 +2253,75 @@ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -2252,6 +2253,75 @@ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
return result; return result;
} }
/**
* fas216_internal_done - trigger restart of a waiting thread in fas216_noqueue_command
* @SCpnt: Command to wake
*
* Trigger restart of a waiting thread in fas216_command
*/
static void fas216_internal_done(Scsi_Cmnd *SCpnt)
{
FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
fas216_checkmagic(info);
info->internal_done = 1;
}
/**
* fas216_noqueue_command - process a command for the adapter.
* @SCpnt: Command to queue
*
* Queue a command for adapter to process.
* Returns: scsi result code.
* Notes: io_request_lock is held, interrupts are disabled.
*/
int fas216_noqueue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{
FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
fas216_checkmagic(info);
/*
* We should only be using this if we don't have an interrupt.
* Provide some "incentive" to use the queueing code.
*/
BUG_ON(info->scsi.irq != NO_IRQ);
info->internal_done = 0;
fas216_queue_command(SCpnt, fas216_internal_done);
/*
* This wastes time, since we can't return until the command is
* complete. We can't sleep either since we may get re-entered!
* However, we must re-enable interrupts, or else we'll be
* waiting forever.
*/
spin_unlock_irq(info->host->host_lock);
while (!info->internal_done) {
/*
* If we don't have an IRQ, then we must poll the card for
* it's interrupt, and use that to call this driver's
* interrupt routine. That way, we keep the command
* progressing. Maybe we can add some inteligence here
* and go to sleep if we know that the device is going
* to be some time (eg, disconnected).
*/
if (fas216_readb(info, REG_STAT) & STAT_INT) {
spin_lock_irq(info->host->host_lock);
fas216_intr(info);
spin_unlock_irq(info->host->host_lock);
}
}
spin_lock_irq(info->host->host_lock);
done(SCpnt);
return 0;
}
/* /*
* Error handler timeout function. Indicate that we timed out, * Error handler timeout function. Indicate that we timed out,
* and wake up any error handler process so it can continue. * and wake up any error handler process so it can continue.
...@@ -2962,7 +3032,7 @@ int fas216_print_devices(FAS216_Info *info, char *buffer) ...@@ -2962,7 +3032,7 @@ int fas216_print_devices(FAS216_Info *info, char *buffer)
EXPORT_SYMBOL(fas216_init); EXPORT_SYMBOL(fas216_init);
EXPORT_SYMBOL(fas216_add); EXPORT_SYMBOL(fas216_add);
EXPORT_SYMBOL(fas216_queue_command); EXPORT_SYMBOL(fas216_queue_command);
EXPORT_SYMBOL(fas216_command); EXPORT_SYMBOL(fas216_noqueue_command);
EXPORT_SYMBOL(fas216_intr); EXPORT_SYMBOL(fas216_intr);
EXPORT_SYMBOL(fas216_remove); EXPORT_SYMBOL(fas216_remove);
EXPORT_SYMBOL(fas216_release); EXPORT_SYMBOL(fas216_release);
......
...@@ -310,6 +310,7 @@ typedef struct { ...@@ -310,6 +310,7 @@ typedef struct {
} dma; } dma;
/* miscellaneous */ /* miscellaneous */
int internal_done; /* flag to indicate request done */
unsigned long magic_end; unsigned long magic_end;
} FAS216_Info; } FAS216_Info;
...@@ -335,6 +336,14 @@ extern int fas216_add (struct Scsi_Host *instance, struct device *dev); ...@@ -335,6 +336,14 @@ extern int fas216_add (struct Scsi_Host *instance, struct device *dev);
*/ */
extern int fas216_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); extern int fas216_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
/* Function: int fas216_noqueue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
* Purpose : queue a command for adapter to process, and process it to completion.
* Params : SCpnt - Command to queue
* done - done function to call once command is complete
* Returns : 0 - success, else error
*/
extern int fas216_noqueue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
/* Function: irqreturn_t fas216_intr (FAS216_Info *info) /* Function: irqreturn_t fas216_intr (FAS216_Info *info)
* Purpose : handle interrupts from the interface to progress a command * Purpose : handle interrupts from the interface to progress a command
* Params : info - interface to service * Params : info - interface to service
......
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