All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@lst.de>
To: James.Bottomley@steeleye.com
Cc: linux-scsi@vger.kernel.org
Subject: [PATCH] revamp legacy host registration
Date: Tue, 3 Jun 2003 22:59:24 +0200	[thread overview]
Message-ID: <20030603205924.GA9262@lst.de> (raw)

The legacy host registration/unregistration is the last user
of the scsi_host_list but it really wants a per-template list
instead, so switch to one that is maintained in
scsi_register/scsi_unregister.  Also the legacy init/exit code
is small enough now to be self-contained in scsi_module.c now.

diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c	Tue Jun  3 01:02:38 2003
+++ b/drivers/scsi/hosts.c	Tue Jun  3 01:02:38 2003
@@ -20,16 +20,8 @@
  *  September 04, 2002 Mike Anderson (andmike@us.ibm.com)
  */
 
-
-/*
- *  This file contains the medium level SCSI
- *  host interface initialization, as well as the scsi_hosts list of SCSI
- *  hosts currently present in the system.
- */
-
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -45,42 +37,9 @@
 #include "scsi_logging.h"
 
 
-static LIST_HEAD(scsi_host_list);
-static spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED;
-
 static int scsi_host_next_hn;		/* host_no for next new host */
 
 /**
- * scsi_tp_for_each_host - call function for each scsi host off a template
- * @shost_tp:	a pointer to a scsi host template
- * @callback:	a pointer to callback function
- *
- * Return value:
- * 	0 on Success / 1 on Failure
- **/
-int scsi_tp_for_each_host(Scsi_Host_Template *shost_tp, int
-			    (*callback)(struct Scsi_Host *shost))
-{
-	struct list_head *lh, *lh_sf;
-	struct Scsi_Host *shost;
-
-	spin_lock(&scsi_host_list_lock);
-
-	list_for_each_safe(lh, lh_sf, &scsi_host_list) {
-		shost = list_entry(lh, struct Scsi_Host, sh_list);
-		if (shost->hostt == shost_tp) {
-			spin_unlock(&scsi_host_list_lock);
-			callback(shost);
-			spin_lock(&scsi_host_list_lock);
-		}
-	}
-
-	spin_unlock(&scsi_host_list_lock);
-
-	return 0;
-}
-
-/**
  * scsi_remove_host - check a scsi host for release and release
  * @shost:	a pointer to a scsi host to release
  *
@@ -103,9 +62,6 @@
 	scsi_forget_host(shost);
 	scsi_sysfs_remove_host(shost);
 
-	if (shost->hostt->release)
-		(*shost->hostt->release)(shost);
-
 	return 0;
 }
 
@@ -129,7 +85,7 @@
 	if (!error) {
 		scsi_proc_host_add(shost);
 		scsi_scan_host(shost);
-	};
+	}
 			
 	return error;
 }
@@ -140,14 +96,6 @@
  **/
 void scsi_free_shost(struct Scsi_Host *shost)
 {
-	/* Remove shost from scsi_host_list */
-	spin_lock(&scsi_host_list_lock);
-	list_del(&shost->sh_list);
-	spin_unlock(&scsi_host_list_lock);
-
-	/*
-	 * Next, kill the kernel error recovery thread for this host.
-	 */
 	if (shost->ehandler) {
 		DECLARE_COMPLETION(sem);
 		shost->eh_notify = &sem;
@@ -255,10 +203,6 @@
 	else
 		shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS;
 
-	spin_lock(&scsi_host_list_lock);
-	list_add_tail(&shost->sh_list, &scsi_host_list);
-	spin_unlock(&scsi_host_list_lock);
-
 	rval = scsi_setup_command_freelist(shost);
 	if (rval)
 		goto fail;
@@ -273,85 +217,29 @@
 	shost->hostt->present++;
 	return shost;
  fail:
-	spin_lock(&scsi_host_list_lock);
-	list_del(&shost->sh_list);
-	spin_unlock(&scsi_host_list_lock);
 	kfree(shost);
 	return NULL;
 }
 
 struct Scsi_Host *scsi_register(Scsi_Host_Template *sht, int privsize)
 {
-	return scsi_host_alloc(sht, privsize);
-}
-
-void scsi_unregister(struct Scsi_Host *shost)
-{
-	scsi_host_put(shost);
-}
-
-/**
- * scsi_register_host - register a low level host driver
- * @shost_tp:	pointer to a scsi host driver template
- *
- * Return value:
- * 	0 on Success / 1 on Failure.
- **/
-int scsi_register_host(Scsi_Host_Template *shost_tp)
-{
-	struct Scsi_Host *shost;
+	struct Scsi_Host *shost = scsi_host_alloc(sht, privsize);
 
-	BUG_ON(!shost_tp->detect);
-
-	if (!shost_tp->release) {
-		printk(KERN_WARNING
-		    "scsi HBA driver %s didn't set a release method, "
-		    "please fix the template\n", shost_tp->name);
+	if (!sht->detect) {
+		printk(KERN_WARNING "scsi_register() called on new-style "
+				    "template for driver %s\n", sht->name);
 		dump_stack();
-		return -EINVAL;
-		
 	}
 
-	shost_tp->detect(shost_tp);
-	if (!shost_tp->present)
-		return 0;
-
-	/*
-	 * XXX(hch) use scsi_tp_for_each_host() once it propagates
-	 *	    error returns properly.
-	 */
-	list_for_each_entry(shost, &scsi_host_list, sh_list)
-		if (shost->hostt == shost_tp)
-			if (scsi_add_host(shost, NULL))
-				goto out_of_space;
-
-	return 0;
-
-out_of_space:
-	scsi_unregister_host(shost_tp); /* easiest way to clean up?? */
-	return 1;
+	if (shost)
+		list_add_tail(&shost->sht_legacy_list, &sht->legacy_hosts);
+	return shost;
 }
 
-/**
- * scsi_unregister_host - unregister a low level host adapter driver
- * @shost_tp:	scsi host template to unregister.
- *
- * Description:
- * 	Similarly, this entry point should be called by a loadable module
- * 	if it is trying to remove a low level scsi driver from the system.
- *
- * Return value:
- * 	0 on Success / 1 on Failure
- *
- * Notes:
- * 	rmmod does not care what we return here the module will be
- * 	removed.
- **/
-int scsi_unregister_host(Scsi_Host_Template *shost_tp)
+void scsi_unregister(struct Scsi_Host *shost)
 {
-	scsi_tp_for_each_host(shost_tp, scsi_remove_host);
-	return 0;
-
+	list_del(&shost->sht_legacy_list);
+	scsi_host_put(shost);
 }
 
 /**
diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
--- a/drivers/scsi/hosts.h	Tue Jun  3 01:02:38 2003
+++ b/drivers/scsi/hosts.h	Tue Jun  3 01:02:38 2003
@@ -366,6 +366,14 @@
      */
     struct device_attribute **sdev_attrs;
 
+    /*
+     * List of hosts per template.
+     *
+     * This is only for use by scsi_module.c for legacy templates.
+     * For these access to it is synchronized implicitly by
+     * module_init/module_exit.
+     */
+    struct list_head legacy_hosts;
 } Scsi_Host_Template;
 
 /*
@@ -384,7 +392,6 @@
      * This information is private to the scsi mid-layer.  Wrapping it in a
      * struct private is a way of marking it in a sort of C++ type of way.
      */
-    struct list_head      sh_list;
     struct list_head	  my_devices;
 
     struct scsi_host_cmd_pool *cmd_pool;
@@ -498,6 +505,15 @@
     struct class_device class_dev;
 
     /*
+     * List of hosts per template.
+     *
+     * This is only for use by scsi_module.c for legacy templates.
+     * For these access to it is synchronized implicitly by
+     * module_init/module_exit.
+     */
+    struct list_head sht_legacy_list;
+
+    /*
      * We should ensure that this is aligned, both for better performance
      * and also because some compilers (m68k) don't automatically force
      * alignment to a long boundary.
@@ -569,11 +585,8 @@
 extern struct Scsi_Host *scsi_host_lookup(unsigned short);
 
 /* legacy interfaces */
-extern int scsi_register_host(Scsi_Host_Template *);
-extern int scsi_unregister_host(Scsi_Host_Template *);
 extern struct Scsi_Host *scsi_register(Scsi_Host_Template *, int);
 extern void scsi_unregister(struct Scsi_Host *);
-
 
 /**
  * scsi_find_device - find a device given the host
diff -Nru a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c
--- a/drivers/scsi/scsi_module.c	Tue Jun  3 01:02:38 2003
+++ b/drivers/scsi/scsi_module.c	Tue Jun  3 01:02:38 2003
@@ -1,71 +1,64 @@
 /*
- *  scsi_module.c Copyright (1994, 1995) Eric Youngdale.
+ * Copyright (C) 2003 Christoph Hellwig.
+ *	Released under GPL v2.
  *
- * Support for loading low-level scsi drivers using the linux kernel loadable
- * module interface.
+ * Support for old-style host templates.
  *
- * To use, the host adapter should first define and initialize the variable
- * driver_template (datatype Scsi_Host_Template), and then include this file.
- * This should also be wrapped in a #ifdef MODULE/#endif.
- *
- * The low -level driver must also define a release function which will
- * free any irq assignments, release any dma channels, release any I/O
- * address space that might be reserved, and otherwise clean up after itself.
- * The idea is that the same driver should be able to be reloaded without
- * any difficulty.  This makes debugging new drivers easier, as you should
- * be able to load the driver, test it, unload, modify and reload.
- *
- * One *very* important caveat.  If the driver may need to do DMA on the
- * ISA bus, you must have unchecked_isa_dma set in the device template,
- * even if this might be changed during the detect routine.  This is
- * because the shpnt structure will be allocated in a special way so that
- * it will be below the appropriate DMA limit - thus if your driver uses
- * the hostdata field of shpnt, and the board must be able to access this
- * via DMA, the shpnt structure must be in a DMA accessible region of
- * memory.  This comment would be relevant for something like the buslogic
- * driver where there are many boards, only some of which do DMA onto the
- * ISA bus.  There is no convenient way of specifying whether the host
- * needs to be in a ISA DMA accessible region of memory when you call
- * scsi_register.
+ * NOTE:  Do not use this for new drivers ever.
  */
 
-#include <linux/module.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "scsi.h"
+#include "hosts.h"
+
 
 static int __init init_this_scsi_driver(void)
 {
-	driver_template.module = THIS_MODULE;
-	scsi_register_host(&driver_template);
-	if (driver_template.present)
-		return 0;
-
-	scsi_unregister_host(&driver_template);
-	return -ENODEV;
+	Scsi_Host_Template *sht = &driver_template;
+	struct Scsi_Host *shost;
+	int error;
+
+	if (!sht->release) {
+		printk(KERN_ERR
+		    "scsi HBA driver %s didn't set a release method.\n",
+		    sht->name);
+		return -EINVAL;
+	}
+
+	sht->module = THIS_MODULE;
+	INIT_LIST_HEAD(&sht->legacy_hosts);
+
+	sht->detect(sht);
+	if (!sht->present)
+		return -ENODEV;
+
+	list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list)
+		error = scsi_add_host(shost, NULL);
+	return error;
 }
 
 static void __exit exit_this_scsi_driver(void)
 {
-	scsi_unregister_host(&driver_template);
+	Scsi_Host_Template *sht = &driver_template;
+	struct Scsi_Host *shost, *s;
+
+	list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list)
+		scsi_remove_host(shost);
+	list_for_each_entry_safe(shost, s, &sht->legacy_hosts, sht_legacy_list)
+		sht->release(shost);
+
+	if (list_empty(&sht->legacy_hosts))
+		return;
+
+	printk(KERN_WARNING "%s did not call scsi_unregister\n", sht->name);
+	dump_stack();
+
+	list_for_each_entry_safe(shost, s, &sht->legacy_hosts, sht_legacy_list)
+		scsi_unregister(shost);
 }
 
 module_init(init_this_scsi_driver);
 module_exit(exit_this_scsi_driver);
-
-/*
- * Overrides for Emacs so that we almost follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
--- a/drivers/scsi/scsi_syms.c	Tue Jun  3 01:02:38 2003
+++ b/drivers/scsi/scsi_syms.c	Tue Jun  3 01:02:38 2003
@@ -31,8 +31,6 @@
  */
 EXPORT_SYMBOL(scsi_register_driver);
 EXPORT_SYMBOL(scsi_register_interface);
-EXPORT_SYMBOL(scsi_register_host);
-EXPORT_SYMBOL(scsi_unregister_host);
 EXPORT_SYMBOL(scsi_host_alloc);
 EXPORT_SYMBOL(scsi_add_host);
 EXPORT_SYMBOL(scsi_remove_host);

             reply	other threads:[~2003-06-03 20:46 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-06-03 20:59 Christoph Hellwig [this message]
2003-06-03 21:01 ` [PATCH] revamp legacy host registration Christoph Hellwig
  -- strict thread matches above, loose matches on Subject: below --
2003-06-06  8:03 Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030603205924.GA9262@lst.de \
    --to=hch@lst.de \
    --cc=James.Bottomley@steeleye.com \
    --cc=linux-scsi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.