]> git.neil.brown.name Git - history.git/commitdiff
[ARM] Fix two Acorn SCSI drivers
authorRussell King <rmk@flint.arm.linux.org.uk>
Tue, 5 Aug 2003 22:22:57 +0000 (23:22 +0100)
committerRussell King <rmk@flint.arm.linux.org.uk>
Tue, 5 Aug 2003 22:22:57 +0000 (23:22 +0100)
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.

drivers/scsi/arm/arxescsi.c
drivers/scsi/arm/eesox.c
drivers/scsi/arm/fas216.c
drivers/scsi/arm/fas216.h

index 0e25ee7ece65982f3cf00b41e1d3327f77d7e1de..bc733f1e6e8d8be334a6c92877b2dd19578ddd4c 100644 (file)
@@ -237,7 +237,7 @@ static const char *arxescsi_info(struct Scsi_Host *host)
  */
 static int
 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;
        char *p = buffer;
@@ -264,7 +264,7 @@ static Scsi_Host_Template arxescsi_template = {
        .proc_info                      = arxescsi_proc_info,
        .name                           = "ARXE SCSI card",
        .info                           = arxescsi_info,
-       .queuecommand                   = fas216_queue_command,
+       .queuecommand                   = fas216_noqueue_command,
        .eh_host_reset_handler          = fas216_eh_host_reset,
        .eh_bus_reset_handler           = fas216_eh_bus_reset,
        .eh_device_reset_handler        = fas216_eh_device_reset,
index 96ddffdcab7bc5ce938c3e7c02854e776c80252f..443badac1d776008bd4a14e9f6a3f77ab946818f 100644 (file)
@@ -444,10 +444,11 @@ int eesoxscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_
        p += sprintf(p, "Term    : o%s\n",
                        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_devices(&info->info, p);
 
+       *start = buffer + offset;
+       pos = p - buffer - offset;
        if (pos > length)
                pos = length;
 
index 2648c6ee5b3779089207baaccc60f43054ae7fdb..fbda4d4f78a793457586048e01f8cfb1855f6dda 100644 (file)
@@ -225,7 +225,8 @@ static void fas216_dumpinfo(FAS216_Info *info)
        printk("    dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n",
                info->dma.transfer_type, info->dma.setup,
                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
@@ -2252,6 +2253,75 @@ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        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,
  * and wake up any error handler process so it can continue.
@@ -2962,7 +3032,7 @@ int fas216_print_devices(FAS216_Info *info, char *buffer)
 EXPORT_SYMBOL(fas216_init);
 EXPORT_SYMBOL(fas216_add);
 EXPORT_SYMBOL(fas216_queue_command);
-EXPORT_SYMBOL(fas216_command);
+EXPORT_SYMBOL(fas216_noqueue_command);
 EXPORT_SYMBOL(fas216_intr);
 EXPORT_SYMBOL(fas216_remove);
 EXPORT_SYMBOL(fas216_release);
index 7f079292b44cb15d1027238f0ed7d085d512112d..8c80f0f8f5b4d0fdbe22966548cb9350d479a9a6 100644 (file)
@@ -310,6 +310,7 @@ typedef struct {
        } dma;
 
        /* miscellaneous */
+       int                     internal_done;          /* flag to indicate request done */
        unsigned long           magic_end;
 } FAS216_Info;
 
@@ -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 *));
 
+/* 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)
  * Purpose : handle interrupts from the interface to progress a command
  * Params  : info - interface to service