patch-2.4.0-test9 linux/drivers/scsi/scsi.c

Next file: linux/drivers/scsi/scsi.h
Previous file: linux/drivers/scsi/qlogicpti.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test8/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
@@ -36,6 +36,9 @@
  *  out_of_space hacks, D. Gilbert (dpg) 990608
  */
 
+#define REVISION	"Revision: 1.00"
+#define VERSION		"Id: scsi.c 1.00 2000/09/26"
+
 #include <linux/config.h>
 #include <linux/module.h>
 
@@ -384,7 +387,7 @@
 					 * return NULL.
 					 */
 					SCpnt = NULL;
-					break;
+					goto busy;
 				}
 			}
 			/*
@@ -402,6 +405,7 @@
 		if (SCpnt) {
 			break;
 		}
+      busy:
 		/*
 		 * If we have been asked to wait for a free block, then
 		 * wait here.
@@ -495,30 +499,7 @@
 	return SCpnt;
 }
 
-/*
- * Function:    scsi_release_command
- *
- * Purpose:     Release a command block.
- *
- * Arguments:   SCpnt - command block we are releasing.
- *
- * Notes:       The command block can no longer be used by the caller once
- *              this funciton is called.  This is in effect the inverse
- *              of scsi_allocate_device.  Note that we also must perform
- *              a couple of additional tasks.  We must first wake up any
- *              processes that might have blocked waiting for a command
- *              block, and secondly we must hit the queue handler function
- *              to make sure that the device is busy.
- *
- *              The idea is that a lot of the mid-level internals gunk
- *              gets hidden in this function.  Upper level drivers don't
- *              have any chickens to wave in the air to get things to
- *              work reliably.
- *
- *              This function is deprecated, and drivers should be
- *              rewritten to use Scsi_Request instead of Scsi_Cmnd.
- */
-void scsi_release_command(Scsi_Cmnd * SCpnt)
+inline void __scsi_release_command(Scsi_Cmnd * SCpnt)
 {
 	unsigned long flags;
         Scsi_Device * SDpnt;
@@ -562,6 +543,43 @@
          * they wake up.  
          */
 	wake_up(&SDpnt->scpnt_wait);
+}
+
+/*
+ * Function:    scsi_release_command
+ *
+ * Purpose:     Release a command block.
+ *
+ * Arguments:   SCpnt - command block we are releasing.
+ *
+ * Notes:       The command block can no longer be used by the caller once
+ *              this funciton is called.  This is in effect the inverse
+ *              of scsi_allocate_device.  Note that we also must perform
+ *              a couple of additional tasks.  We must first wake up any
+ *              processes that might have blocked waiting for a command
+ *              block, and secondly we must hit the queue handler function
+ *              to make sure that the device is busy.  Note - there is an
+ *              option to not do this - there were instances where we could
+ *              recurse too deeply and blow the stack if this happened
+ *              when we were indirectly called from the request function
+ *              itself.
+ *
+ *              The idea is that a lot of the mid-level internals gunk
+ *              gets hidden in this function.  Upper level drivers don't
+ *              have any chickens to wave in the air to get things to
+ *              work reliably.
+ *
+ *              This function is deprecated, and drivers should be
+ *              rewritten to use Scsi_Request instead of Scsi_Cmnd.
+ */
+void scsi_release_command(Scsi_Cmnd * SCpnt)
+{
+        request_queue_t *q;
+        Scsi_Device * SDpnt;
+
+        SDpnt = SCpnt->device;
+
+        __scsi_release_command(SCpnt);
 
         /*
          * Finally, hit the queue request function to make sure that
@@ -569,12 +587,8 @@
          * This won't block - if the device cannot take any more, life
          * will go on.  
          */
-        {
-                request_queue_t *q;
-
-                q = &SDpnt->request_queue;
-                scsi_queue_next_request(q, NULL);                
-        }
+        q = &SDpnt->request_queue;
+        scsi_queue_next_request(q, NULL);                
 }
 
 /*
@@ -1361,13 +1375,8 @@
 	SCpnt->done(SCpnt);
 }
 
-#if defined(CONFIG_MODULES) || defined(CONFIG_BLK_DEV_IDESCSI) || defined(CONFIG_USB_STORAGE)
 static int scsi_register_host(Scsi_Host_Template *);
 static void scsi_unregister_host(Scsi_Host_Template *);
-#endif
-
-
-int scsi_loadable_module_flag;	/* Set after we scan builtin drivers */
 
 /*
  * Function:    scsi_release_commandblocks()
@@ -1432,10 +1441,9 @@
 		    kmalloc(sizeof(Scsi_Cmnd),
 				     GFP_ATOMIC |
 				(host->unchecked_isa_dma ? GFP_DMA : 0));
-		memset(SCpnt, 0, sizeof(Scsi_Cmnd));
 		if (NULL == SCpnt)
 			break;	/* If not, the next line will oops ... */
-		memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout));
+		memset(SCpnt, 0, sizeof(Scsi_Cmnd));
 		SCpnt->host = host;
 		SCpnt->device = SDpnt;
 		SCpnt->target = SDpnt->id;
@@ -1499,120 +1507,6 @@
     }
 }
 
-#ifndef MODULE			/* { */
-
-char scsi_host_no_table[20][10] __initdata = {};
-int scsi_host_no_set __initdata = 0;
-
-/*
- * scsi_dev_init() is our initialization routine, which in turn calls host
- * initialization, bus scanning, and sd/st initialization routines.
- * This is only used at boot time.
- */
-int __init scsi_dev_init(void)
-{
-	Scsi_Device *SDpnt;
-	struct Scsi_Host *shpnt;
-	struct Scsi_Device_Template *sdtpnt;
-	struct proc_dir_entry *generic;
-#ifdef FOO_ON_YOU
-	return;
-#endif
-
-        /* Initialize list of host_no if kernel parameter set */
-        if (scsi_host_no_set) {
-		int i;
-                for (i = 0;i < sizeof(scsi_host_no_table)/sizeof(scsi_host_no_table[0]);i++)
-			scsi_host_no_insert(scsi_host_no_table[i], i);
-        }
-
-	/* Yes we're here... */
-
-        scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL);
-	/*
-	 * This makes /proc/scsi and /proc/scsi/scsi visible.
-	 */
-#ifdef CONFIG_PROC_FS
-	proc_scsi = proc_mkdir("scsi", 0);
-	if (!proc_scsi) {
-		printk (KERN_ERR "cannot init /proc/scsi\n");
-		return -ENOMEM;
-	}
-	
-	generic = create_proc_info_entry ("scsi/scsi", 0, 0, scsi_proc_info);
-	if (!generic) {
-		printk (KERN_ERR "cannot init /proc/scsi/scsi\n");
-		remove_proc_entry("scsi", 0);
-		return -ENOMEM;
-	}
-	generic->write_proc = proc_scsi_gen_write;
-#endif
-
-	/* Init a few things so we can "malloc" memory. */
-	scsi_loadable_module_flag = 0;
-
-	/* initialize all hosts */
-	scsi_init();
-
-	/*
-	 * This is where the processing takes place for most everything
-	 * when commands are completed.  Until we do this, we will not be able
-	 * to queue any commands.
-	 */
-	init_bh(SCSI_BH, scsi_bottom_half_handler);
-
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-		scan_scsis(shpnt, 0, 0, 0, 0);	/* scan for scsi devices */
-		if (shpnt->select_queue_depths != NULL)
-			(shpnt->select_queue_depths) (shpnt, shpnt->host_queue);
-	}
-
-	printk("scsi : detected ");
-	for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
-		if (sdtpnt->dev_noticed && sdtpnt->name)
-			printk("%d SCSI %s%s ", sdtpnt->dev_noticed, sdtpnt->name,
-			       (sdtpnt->dev_noticed != 1) ? "s" : "");
-	printk("total.\n");
-
-	for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
-		if (sdtpnt->init && sdtpnt->dev_noticed)
-			(*sdtpnt->init) ();
-
-	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-		for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
-			/* SDpnt->scsi_request_fn = NULL; */
-			for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
-				if (sdtpnt->attach)
-					(*sdtpnt->attach) (SDpnt);
-			if (SDpnt->attached) {
-				scsi_build_commandblocks(SDpnt);
-				if (0 == SDpnt->has_cmdblocks) {
-					printk("scsi_dev_init: DANGER, no command blocks\n");
-					/* What to do now ?? */
-				}
-			}
-		}
-	}
-
-	/*
-	 * This should build the DMA pool.
-	 */
-	scsi_resize_dma_pool();
-
-	/*
-	 * OK, now we finish the initialization by doing spin-up, read
-	 * capacity, etc, etc
-	 */
-	for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
-		if (sdtpnt->finish && sdtpnt->nr_dev)
-			(*sdtpnt->finish) ();
-
-	scsi_loadable_module_flag = 1;
-
-	return 0;
-}
-#endif	/* MODULE */		/* } */
-
 #ifdef CONFIG_PROC_FS
 static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
 {
@@ -1908,15 +1802,8 @@
 #endif
 
 /*
- * Some host adapters that are plugging into other subsystems register
- * their hosts through the modules entrypoints, and don't use the big
- * list in hosts.c.
- */
-#if defined(CONFIG_MODULES) || defined(CONFIG_BLK_DEV_IDESCSI) || defined(CONFIG_USB_STORAGE) || defined(CONFIG_USB_MICROTEK)	/* a big #ifdef block... */
-
-/*
- * This entry point should be called by a loadable module if it is trying
- * add a low level scsi driver to the system.
+ * This entry point should be called by a driver if it is trying
+ * to add a low level scsi driver to the system.
  */
 static int scsi_register_host(Scsi_Host_Template * tpnt)
 {
@@ -1957,8 +1844,8 @@
 				return 1;
 			}
 			/* 
-			 * The low-level driver failed to register a driver.  We
-			 *  can do this now.
+			 * The low-level driver failed to register a driver.
+			 * We can do this now.
 			 */
 			scsi_register(tpnt, 0);
 		}
@@ -2004,9 +1891,6 @@
 			}
 		}
 
-		printk("scsi : %d host%s.\n", next_scsi_host,
-		       (next_scsi_host == 1) ? "" : "s");
-
 		/* The next step is to call scan_scsis here.  This generates the
 		 * Scsi_Devices entries
 		 */
@@ -2084,15 +1968,13 @@
 static void scsi_unregister_host(Scsi_Host_Template * tpnt)
 {
 	int online_status;
-	int pcount;
+	int pcount0, pcount;
 	Scsi_Cmnd *SCpnt;
 	Scsi_Device *SDpnt;
 	Scsi_Device *SDpnt1;
 	struct Scsi_Device_Template *sdtpnt;
 	struct Scsi_Host *sh1;
 	struct Scsi_Host *shpnt;
-	Scsi_Host_Template *SHT;
-	Scsi_Host_Template *SHTp;
 	char name[10];	/* host_no>=10^9? I don't think so. */
 
 	/*
@@ -2226,9 +2108,10 @@
 	/* Next we go through and remove the instances of the individual hosts
 	 * that were detected */
 
+	pcount0 = next_scsi_host;
 	for (shpnt = scsi_hostlist; shpnt; shpnt = sh1) {
 		sh1 = shpnt->next;
-		if (shpnt->hostt != tpnt || !shpnt->loaded_as_module)
+		if (shpnt->hostt != tpnt)
 			continue;
 		pcount = next_scsi_host;
 		/* Remove the /proc/scsi directory entry */
@@ -2242,7 +2125,7 @@
 			 * written host adapters.
 			 */
 			if (shpnt->irq)
-			free_irq(shpnt->irq, NULL);
+				free_irq(shpnt->irq, NULL);
 			if (shpnt->dma_channel != 0xff)
 				free_dma(shpnt->dma_channel);
 			if (shpnt->io_port && shpnt->n_io_port)
@@ -2261,8 +2144,9 @@
 	if (!scsi_hosts)
 		scsi_resize_dma_pool();
 
-	printk("scsi : %d host%s.\n", next_scsi_host,
-	       (next_scsi_host == 1) ? "" : "s");
+	if (pcount0 != next_scsi_host)
+		printk("scsi : %d host%s left.\n", next_scsi_host,
+		       (next_scsi_host == 1) ? "" : "s");
 
 #if defined(USE_STATIC_SCSI_MEMORY)
 	printk("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n",
@@ -2271,24 +2155,21 @@
 	       (scsi_memory_upper_value - scsi_init_memory_start) / 1024);
 #endif
 
-	/* There were some hosts that were loaded at boot time, so we cannot
-	   do any more than this */
-	if (tpnt->present)
-		return;
+	/* Remove it from the linked list and /proc */
+	if (tpnt->present) {
+		Scsi_Host_Template **SHTp = &scsi_hosts;
+		Scsi_Host_Template *SHT;
 
-	/* OK, this is the very last step.  Remove this host adapter from the
-	   linked list. */
-	for (SHTp = NULL, SHT = scsi_hosts; SHT; SHTp = SHT, SHT = SHT->next)
-		if (SHT == tpnt) {
-			if (SHTp)
-				SHTp->next = SHT->next;
-			else
-				scsi_hosts = SHT->next;
-			SHT->next = NULL;
-			break;
+		while ((SHT = *SHTp) != NULL) {
+			if (SHT == tpnt) {
+				*SHTp = SHT->next;
+				break;
+			}
+			SHTp = &SHT->next;
 		}
-	/* Rebuild the /proc/scsi directory entries */
-	remove_proc_entry(tpnt->proc_name, proc_scsi);
+		/* Rebuild the /proc/scsi directory entries */
+		remove_proc_entry(tpnt->proc_name, proc_scsi);
+	}
 	MOD_DEC_USE_COUNT;
 }
 
@@ -2421,6 +2302,10 @@
 }
 
 
+/* This function should be called by drivers which needs to register
+ * with the midlevel scsi system. As of 2.4.0-test9pre3 this is our
+ * main device/hosts register function	/mathiasen
+ */
 int scsi_register_module(int module_type, void *ptr)
 {
 	switch (module_type) {
@@ -2448,6 +2333,8 @@
 	}
 }
 
+/* Reverse the actions taken above
+ */
 void scsi_unregister_module(int module_type, void *ptr)
 {
 	switch (module_type) {
@@ -2466,8 +2353,6 @@
 	return;
 }
 
-#endif				/* CONFIG_MODULES */
-
 #ifdef CONFIG_PROC_FS
 /*
  * Function:    scsi_dump_status
@@ -2574,17 +2459,11 @@
 }
 #endif				/* CONFIG_PROC_FS */
 
-static int scsi_host_no_init (char *str)
+static int __init scsi_host_no_init (char *str)
 {
     static int next_no = 0;
     char *temp;
 
-#ifndef MODULE
-    int len;
-    scsi_host_no_set = 1;
-    memset(scsi_host_no_table, 0, sizeof(scsi_host_no_table));
-#endif /* MODULE */
-
     while (str) {
 	temp = str;
 	while (*temp && (*temp != ':') && (*temp != ','))
@@ -2593,35 +2472,34 @@
 	    temp = NULL;
 	else
 	    *temp++ = 0;
-#ifdef MODULE
 	scsi_host_no_insert(str, next_no);
-#else
-	if (next_no < sizeof(scsi_host_no_table)/sizeof(scsi_host_no_table[0])) {
-	    if ((len = strlen(str)) >= sizeof(scsi_host_no_table[0]))
-		len = sizeof(scsi_host_no_table[0])-1;
-	    strncpy(scsi_host_no_table[next_no], str, len);
-	    scsi_host_no_table[next_no][len] = 0;
-	}
-#endif /* MODULE */
 	str = temp;
 	next_no++;
     }
     return 1;
 }
 
-#ifndef MODULE
-__setup("scsihosts=", scsi_host_no_init);
-#endif
-
-#ifdef MODULE
 static char *scsihosts;
 
 MODULE_PARM(scsihosts, "s");
+MODULE_DESCRIPTION("SCSI core");
+
+#ifndef MODULE
+int __init scsi_setup(char *str)
+{
+	scsihosts = str;
+	return 1;
+}
+
+__setup("scsihosts=", scsi_setup);
+#endif
 
-int init_module(void)
+static int __init init_scsi(void)
 {
 	struct proc_dir_entry *generic;
 
+	printk(KERN_INFO "SCSI subsystem driver " REVISION "\n");
+
         if( scsi_init_minimal_dma_pool() != 0 )
         {
                 return 1;
@@ -2645,10 +2523,10 @@
 	generic->write_proc = proc_scsi_gen_write;
 #endif
 
-	scsi_loadable_module_flag = 1;
-
         scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL);
-        scsi_host_no_init (scsihosts);
+        if (scsihosts)
+		printk("scsi: host order: %s\n", scsihosts);	
+	scsi_host_no_init (scsihosts);
 	/*
 	 * This is where the processing takes place for most everything
 	 * when commands are completed.
@@ -2658,7 +2536,7 @@
 	return 0;
 }
 
-void cleanup_module(void)
+static void __exit exit_scsi(void)
 {
 	Scsi_Host_Name *shn, *shn2 = NULL;
 
@@ -2688,7 +2566,8 @@
 
 }
 
-#endif				/* MODULE */
+module_init(init_scsi);
+module_exit(exit_scsi);
 
 /*
  * Function:    scsi_get_host_dev()

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)