patch-2.3.46 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.3.45/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
@@ -636,6 +636,8 @@
 	return rtn;
 }
 
+devfs_handle_t scsi_devfs_handle = NULL;
+
 /*
  * scsi_do_cmd sends all the commands out to the low-level driver.  It
  * handles the specifics required for each low level driver - ie queued
@@ -1168,7 +1170,39 @@
 static int proc_scsi_gen_write(struct file * file, const char * buf,
                               unsigned long length, void *data);
 
+void __init scsi_host_no_insert(char *str, int n)
+{
+    Scsi_Host_Name *shn, *shn2;
+    int len;
+    
+    len = strlen(str);
+    if (len && (shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC))) {
+	if ((shn->name = kmalloc(len+1, GFP_ATOMIC))) {
+	    strncpy(shn->name, str, len);
+	    shn->name[len] = 0;
+	    shn->host_no = n;
+	    shn->host_registered = 0;
+	    shn->loaded_as_module = 1; /* numbers shouldn't be freed in any case */
+	    shn->next = NULL;
+	    if (scsi_host_no_list) {
+		for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next)
+		    ;
+		shn2->next = shn;
+	    }
+	    else
+		scsi_host_no_list = shn;
+	    max_scsi_hosts = n+1;
+	}
+	else
+	    kfree((char *) shn);
+    }
+}
+
 #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.
@@ -1184,8 +1218,16 @@
 	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", 4, NULL);
 	/*
 	 * This makes /proc/scsi and /proc/scsi/scsi visible.
 	 */
@@ -1535,6 +1577,7 @@
 			 * Nobody is using this device any more.
 			 * Free all of the command structures.
 			 */
+			devfs_unregister (scd->de);
 			scsi_release_commandblocks(scd);
 
 			/* Now we can remove the device structure */
@@ -1834,6 +1877,7 @@
 				printk("Attached usage count = %d\n", SDpnt->attached);
 				return;
 			}
+			devfs_unregister (SDpnt->de);
 		}
 	}
 
@@ -2193,19 +2237,24 @@
 			/* Now dump the request lists for each block device */
 			printk("Dump of pending block device requests\n");
 			for (i = 0; i < MAX_BLKDEV; i++) {
-				if (blk_dev[i].request_queue.current_request) {
+				struct list_head * queue_head;
+
+				queue_head = &blk_dev[i].request_queue.queue_head;
+				if (!list_empty(queue_head)) {
 					struct request *req;
+					struct list_head * entry;
+
 					printk("%d: ", i);
-					req = blk_dev[i].request_queue.current_request;
-					while (req) {
+					entry = queue_head->next;
+					do {
+						req = blkdev_entry_to_request(entry);
 						printk("(%s %d %ld %ld %ld) ",
 						   kdevname(req->rq_dev),
 						       req->cmd,
 						       req->sector,
 						       req->nr_sectors,
 						req->current_nr_sectors);
-						req = req->next;
-					}
+					} while ((entry = entry->next) != queue_head);
 					printk("\n");
 				}
 			}
@@ -2216,12 +2265,52 @@
 }
 #endif				/* CONFIG_PROC_FS */
 
+static int 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 != ','))
+	    temp++;
+	if (!*temp)
+	    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");
 
 int init_module(void)
 {
-	unsigned long size;
-	int has_space = 0;
 	struct proc_dir_entry *generic;
 
         if( scsi_init_minimal_dma_pool() != 0 )
@@ -2249,6 +2338,8 @@
 
 	scsi_loadable_module_flag = 1;
 
+        scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", 4, NULL);
+        scsi_host_no_init (scsihosts);
 	/*
 	 * This is where the processing takes place for most everything
 	 * when commands are completed.
@@ -2260,7 +2351,20 @@
 
 void cleanup_module(void)
 {
+	Scsi_Host_Name *shn, *shn2 = NULL;
+
 	remove_bh(SCSI_BH);
+
+        devfs_unregister (scsi_devfs_handle);
+        for (shn = scsi_host_no_list;shn;shn = shn->next) {
+		if (shn->name)
+			kfree(shn->name);
+                if (shn2)
+			kfree (shn2);
+                shn2 = shn;
+        }
+        if (shn2)
+		kfree (shn2);
 
 #ifdef CONFIG_PROC_FS
 	/* No, we're not here anymore. Don't show the /proc/scsi files. */

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