summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/hosts.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
commit27cfca1ec98e91261b1a5355d10a8996464b63af (patch)
tree8e895a53e372fa682b4c0a585b9377d67ed70d0e /drivers/scsi/hosts.c
parent6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff)
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too o Upgrade to 2.1.89. Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'drivers/scsi/hosts.c')
-rw-r--r--drivers/scsi/hosts.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 4c62c2df4..e9ea1be59 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -16,11 +16,6 @@
* hosts currently present in the system.
*/
-/*
- * Don't import our own symbols, as this would severely mess up our
- * symbol tables.
- */
-#define _SCSI_SYMS_VER_
#define __NO_VERSION__
#include <linux/module.h>
@@ -32,6 +27,10 @@
#include <linux/proc_fs.h>
#include <linux/init.h>
+#define __KERNEL_SYSCALLS__
+
+#include <linux/unistd.h>
+
#include "scsi.h"
#ifndef NULL
@@ -447,7 +446,9 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){
struct Scsi_Host * retval, *shpnt;
retval = (struct Scsi_Host *)scsi_init_malloc(sizeof(struct Scsi_Host) + j,
(tpnt->unchecked_isa_dma && j ? GFP_DMA : 0) | GFP_ATOMIC);
+ atomic_set(&retval->host_active,0);
retval->host_busy = 0;
+ retval->host_failed = 0;
retval->block = NULL;
retval->wish_block = 0;
if(j > 0xffff) panic("Too many extra bytes requested\n");
@@ -470,6 +471,16 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){
retval->io_port = 0;
retval->hostt = tpnt;
retval->next = NULL;
+ retval->in_recovery = 0;
+ retval->ehandler = NULL; /* Initial value until the thing starts up. */
+ retval->eh_notify = NULL; /* Who we notify when we exit. */
+
+ /*
+ * Initialize the fields used for mid-level queueing.
+ */
+ retval->pending_commands = NULL;
+ retval->host_busy = FALSE;
+
#ifdef DEBUG
printk("Register %x %x: %d\n", (int)retval, (int)retval->hostt, j);
#endif
@@ -506,6 +517,32 @@ scsi_register_device(struct Scsi_Device_Template * sdpnt)
return 0;
}
+/*
+ * Why is this a seperate function? Because the kernel_thread code
+ * effectively does a fork, and there is a builtin exit() call when
+ * the child returns. The difficulty is that scsi_init() is
+ * marked __initfunc(), which means the memory is unmapped after bootup
+ * is complete, which means that the thread's exit() call gets wiped.
+ *
+ * The lesson is to *NEVER*, *NEVER* call kernel_thread() from an
+ * __initfunc() function, if that function could ever return.
+ */
+static void launch_error_handler_thread(struct Scsi_Host * shpnt)
+{
+ struct semaphore sem = MUTEX_LOCKED;
+
+ shpnt->eh_notify = &sem;
+
+ kernel_thread((int (*)(void *))scsi_error_handler,
+ (void *) shpnt, 0);
+ /*
+ * Now wait for the kernel error thread to initialize itself
+ * as it might be needed when we scan the bus.
+ */
+ down (&sem);
+ shpnt->eh_notify = NULL;
+}
+
__initfunc(unsigned int scsi_init(void))
{
static int called = 0;
@@ -556,6 +593,14 @@ __initfunc(unsigned int scsi_init(void))
name = shpnt->hostt->name;
printk ("scsi%d : %s\n", /* And print a little message */
shpnt->host_no, name);
+
+ /*
+ * Now start the error recovery thread for the host.
+ */
+ if( shpnt->hostt->use_new_eh_code )
+ {
+ launch_error_handler_thread(shpnt);
+ }
}
printk ("scsi : %d host%s.\n", next_scsi_host,