public inbox for linux-scsi@vger.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] switch scsi upper driver probing to the driver model
Date: Fri, 16 May 2003 18:20:39 +0200	[thread overview]
Message-ID: <20030516182039.A7369@lst.de> (raw)

Upper drivers now use the LDM ->probe/->remove callbacks and the
core list code.  Note that this means there is only one driver per
scsi device and not multiple, e.g. you can't have sd _and_ sg for
the same device.  Personally I think that's not a problem anymore
with the generic SG_IO in place, but if you scream loud enough I
could come up with a hack that makes the sg nodes a property of the
scsi midlayer instead of a LDM-style driver and we could get the
old behaviour back.


--- 1.64/drivers/scsi/hosts.c	Tue May 13 00:50:42 2003
+++ edited/drivers/scsi/hosts.c	Fri May 16 17:34:35 2003
@@ -229,27 +229,18 @@
 int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
 {
 	Scsi_Host_Template *sht = shost->hostt;
-	struct scsi_device *sdev;
-	int error = 0, saved_error = 0;
+	int error;
 
 	printk(KERN_INFO "scsi%d : %s\n", shost->host_no,
 			sht->info ? sht->info(shost) : sht->name);
 
 	error = scsi_sysfs_add_host(shost, dev);
-	if (error)
-		return error;
-
-	scsi_proc_host_add(shost);
-
-	scsi_scan_host(shost);
+	if (!error) {
+		scsi_proc_host_add(shost);
+		scsi_scan_host(shost);
+	};
 			
-	list_for_each_entry (sdev, &shost->my_devices, siblings) {
-		error = scsi_attach_device(sdev);
-		if (error)
-			saved_error = error;
-	}
-
-	return saved_error;
+	return error;
 }
 
 /**
===== drivers/scsi/hosts.h 1.63 vs edited =====
--- 1.63/drivers/scsi/hosts.h	Thu May  8 20:24:14 2003
+++ edited/drivers/scsi/hosts.h	Fri May 16 17:34:35 2003
@@ -532,25 +532,18 @@
         return shost->host_gendev.parent;
 }
 
-struct Scsi_Device_Template
-{
-    struct list_head list;
-    const char * name;
-    struct module * module;	  /* Used for loadable modules */
-    unsigned char scsi_type;
-    int (*attach)(Scsi_Device *); /* Attach devices to arrays */
-    void (*detach)(Scsi_Device *);
-    int (*init_command)(Scsi_Cmnd *);     /* Used by new queueing code. 
-                                           Selects command for blkdevs */
-    void (*rescan)(Scsi_Device *);
-    struct device_driver scsi_driverfs_driver;
+struct scsi_driver {
+	struct module		*owner;
+	struct device_driver	gendrv;
+
+	int (*init_command)(struct scsi_cmnd *);
+	void (*rescan)(struct device *);
 };
+#define to_scsi_driver(drv) \
+	container_of((drv), struct scsi_driver, gendrv)
 
-/*
- * Highlevel driver registration/unregistration.
- */
-extern int scsi_register_device(struct Scsi_Device_Template *);
-extern int scsi_unregister_device(struct Scsi_Device_Template *);
+extern int scsi_register_driver(struct scsi_driver *);
+extern void scsi_unregister_driver(struct scsi_driver *);
 
 /*
  * HBA allocation/freeing.
===== drivers/scsi/ide-scsi.c 1.23 vs edited =====
--- 1.23/drivers/scsi/ide-scsi.c	Tue Jan 28 18:01:08 2003
+++ edited/drivers/scsi/ide-scsi.c	Fri May 16 17:34:35 2003
@@ -770,8 +770,8 @@
 	struct gendisk *disk = cmd->request->rq_disk;
 
 	if (disk) {
-		struct Scsi_Device_Template **p = disk->private_data;
-		if (strcmp((*p)->scsi_driverfs_driver.name, "sg") == 0)
+		struct scsi_driver **p = disk->private_data;
+		if (strcmp((*p)->gendrv.name, "sg") == 0)
 			return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
 	}
 	return test_bit(IDESCSI_TRANSFORM, &scsi->transform);
===== drivers/scsi/osst.c 1.43 vs edited =====
--- 1.43/drivers/scsi/osst.c	Wed May  7 16:15:37 2003
+++ edited/drivers/scsi/osst.c	Fri May 16 17:34:35 2003
@@ -160,19 +160,15 @@
 static int osst_copy_to_buffer(OSST_buffer *, unsigned char *);
 static int osst_copy_from_buffer(OSST_buffer *, unsigned char *);
 
-static int osst_attach(Scsi_Device *);
-static void osst_detach(Scsi_Device *);
+static int osst_probe(struct device *);
+static int osst_remove(struct device *);
 
-struct Scsi_Device_Template osst_template =
-{
-	.module =       THIS_MODULE,
-	.list =         LIST_HEAD_INIT(osst_template.list),
-	.name =         "OnStream Tape",
-	.scsi_type =    TYPE_TAPE,
-	.attach =       osst_attach,
-	.detach =       osst_detach,
-	.scsi_driverfs_driver = {
-		.name =  "osst",
+struct scsi_driver osst_template = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		=  "osst",
+		.probe		= osst_probe,
+		.remove		= osst_remove,
 	}
 };
 
@@ -5385,8 +5381,9 @@
  * osst startup / cleanup code
  */
 
-static int osst_attach(Scsi_Device * SDp)
+static int osst_probe(struct device *dev)
 {
+	Scsi_Device    * SDp = to_scsi_device(dev);
 	OS_Scsi_Tape   * tpnt;
 	ST_mode        * STm;
 	ST_partstat    * STps;
@@ -5395,12 +5392,12 @@
 	int              i, mode, dev_num;
 
 	if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
-		return 1;
+		return -ENODEV;
 
 	drive = alloc_disk(1);
 	if (!drive) {
 		printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
-		return 1;
+		return -ENODEV;
 	}
 
 	/* if this is the first attach, build the infrastructure */
@@ -5576,16 +5573,17 @@
 
 out_put_disk:
         put_disk(drive);
-        return 1;
+        return -ENODEV;
 };
 
-static void osst_detach(Scsi_Device * SDp)
+static int osst_remove(struct device *dev)
 {
+  Scsi_Device * SDp = to_scsi_device(dev);
   OS_Scsi_Tape * tpnt;
   int i, mode;
 
   if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
-	  return;
+	  return 0;
 
   write_lock(&os_scsi_tapes_lock);
   for(i=0; i < osst_max_dev; i++) {
@@ -5618,11 +5616,11 @@
 			kfree(tpnt->buffer);
 		}
 		kfree(tpnt);
-		return;
+		return 0;
 	}
   }
   write_unlock(&os_scsi_tapes_lock);
-  return;
+  return 0;
 }
 
 static int __init init_osst(void) 
@@ -5631,7 +5629,7 @@
 
 	validate_options();
 	
-	if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_device(&osst_template)) {
+	if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_driver(&osst_template)) {
 		printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
 		return 1;
 	}
@@ -5644,7 +5642,7 @@
 	int i;
 	OS_Scsi_Tape * STp;
 
-	scsi_unregister_device(&osst_template);
+	scsi_unregister_driver(&osst_template);
 	unregister_chrdev(OSST_MAJOR, "osst");
 
 	if (os_scsi_tapes) {
===== drivers/scsi/osst.h 1.9 vs edited =====
--- 1.9/drivers/scsi/osst.h	Fri Apr 18 17:57:20 2003
+++ edited/drivers/scsi/osst.h	Fri May 16 17:34:35 2003
@@ -530,7 +530,7 @@
 
 /* The OnStream tape drive descriptor */
 typedef struct {
-  struct Scsi_Device_Template *driver;
+  struct scsi_driver *driver;
   unsigned capacity;
   Scsi_Device* device;
   struct semaphore lock;       /* for serialization */
===== drivers/scsi/scsi.c 1.112 vs edited =====
--- 1.112/drivers/scsi/scsi.c	Thu May  8 20:31:08 2003
+++ edited/drivers/scsi/scsi.c	Fri May 16 17:34:35 2003
@@ -86,12 +86,6 @@
 static unsigned long serial_number;
 
 /*
- * List of all highlevel drivers.
- */
-LIST_HEAD(scsi_devicelist);
-static DECLARE_RWSEM(scsi_devicelist_mutex);
-
-/*
  * Note - the initial logging level can be set here to log events at boot time.
  * After the system is up, you may enable logging via the /proc interface.
  */
@@ -931,50 +925,6 @@
 	return depth;
 }
 
-int scsi_attach_device(struct scsi_device *sdev)
-{
-	struct Scsi_Device_Template *sdt;
-
-	down_read(&scsi_devicelist_mutex);
-	list_for_each_entry(sdt, &scsi_devicelist, list) {
-		if (!try_module_get(sdt->module))
-			continue;
-		(*sdt->attach)(sdev);
-		module_put(sdt->module);
-	}
-	up_read(&scsi_devicelist_mutex);
-	return 0;
-}
-
-void scsi_detach_device(struct scsi_device *sdev)
-{
-	struct Scsi_Device_Template *sdt;
-
-	down_read(&scsi_devicelist_mutex);
-	list_for_each_entry(sdt, &scsi_devicelist, list) {
-		if (!try_module_get(sdt->module))
-			continue;
-		(*sdt->detach)(sdev);
-		module_put(sdt->module);
-	}
-	up_read(&scsi_devicelist_mutex);
-}
-
-void scsi_rescan_device(struct scsi_device *sdev)
-{
-	struct Scsi_Device_Template *sdt;
-
-	down_read(&scsi_devicelist_mutex);
-	list_for_each_entry(sdt, &scsi_devicelist, list) {
-		if (!try_module_get(sdt->module))
-			continue;
-		if (*sdt->rescan)
-			(*sdt->rescan)(sdev);
-		module_put(sdt->module);
-	}
-	up_read(&scsi_devicelist_mutex);
-}
-
 int scsi_device_get(struct scsi_device *sdev)
 {
 	if (!try_module_get(sdev->host->hostt->module))
@@ -1028,71 +978,6 @@
 	} else {
 		/* FIXME: Send online state change hotplug event */
 	}
-}
-
-/*
- * This entry point is called from the upper level module's module_init()
- * routine.  That implies that when this function is called, the
- * scsi_mod module is locked down because of upper module layering and
- * that the high level driver module is locked down by being in it's
- * init routine.  So, the *only* thing we have to do to protect adds 
- * we perform in this function is to make sure that all call's
- * to the high level driver's attach() and detach() call in points, other
- * than via scsi_register_device and scsi_unregister_device which are in
- * the module_init and module_exit code respectively and therefore already
- * locked down by the kernel module loader, are wrapped by try_module_get()
- * and module_put() to avoid races on device adds and removes.
- */
-int scsi_register_device(struct Scsi_Device_Template *tpnt)
-{
-	struct scsi_device *sdev;
-	struct Scsi_Host *shpnt;
-
-#ifdef CONFIG_KMOD
-	if (scsi_host_get_next(NULL) == NULL)
-		request_module("scsi_hostadapter");
-#endif
-
-	if (!list_empty(&tpnt->list))
-		return 1;
-
-	down_write(&scsi_devicelist_mutex);
-	list_add_tail(&tpnt->list, &scsi_devicelist);
-	up_write(&scsi_devicelist_mutex);
-
-	scsi_upper_driver_register(tpnt);
-
-	for (shpnt = scsi_host_get_next(NULL); shpnt;
-	     shpnt = scsi_host_get_next(shpnt)) 
-		list_for_each_entry(sdev, &shpnt->my_devices, siblings)
-			(*tpnt->attach)(sdev);
-
-	return 0;
-}
-
-int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
-{
-	struct scsi_device *sdev;
-	struct Scsi_Host *shpnt;
-
-	/*
-	 * Next, detach the devices from the driver.
-	 */
-	for (shpnt = scsi_host_get_next(NULL); shpnt;
-	     shpnt = scsi_host_get_next(shpnt)) {
-		list_for_each_entry(sdev, &shpnt->my_devices, siblings)
-			(*tpnt->detach)(sdev);
-	}
-
-	/*
-	 * Extract the template from the linked list.
-	 */
-	down_write(&scsi_devicelist_mutex);
-	list_del(&tpnt->list);
-	up_write(&scsi_devicelist_mutex);
-
-	scsi_upper_driver_unregister(tpnt);
-	return 0;
 }
 
 MODULE_DESCRIPTION("SCSI core");
===== drivers/scsi/scsi_lib.c 1.90 vs edited =====
--- 1.90/drivers/scsi/scsi_lib.c	Thu May  8 21:14:09 2003
+++ edited/drivers/scsi/scsi_lib.c	Fri May 16 17:34:35 2003
@@ -613,29 +613,6 @@
 }
 
 /*
- * Function:    scsi_get_request_dev()
- *
- * Purpose:     Find the upper-level driver that is responsible for this
- *              request
- *
- * Arguments:   request   - I/O request we are preparing to queue.
- *
- * Lock status: No locks assumed to be held, but as it happens the
- *              q->queue_lock is held when this is called.
- *
- * Returns:     Nothing
- *
- * Notes:       The requests in the request queue may have originated
- *              from any block device driver.  We need to find out which
- *              one so that we can later form the appropriate command.
- */
-static struct Scsi_Device_Template *scsi_get_request_dev(struct request *req)
-{
-	struct gendisk *p = req->rq_disk;
-	return p ? *(struct Scsi_Device_Template **)p->private_data : NULL;
-}
-
-/*
  * Function:    scsi_io_completion()
  *
  * Purpose:     Completion processing for block device I/O requests.
@@ -847,11 +824,7 @@
 		return;
 	}
 	if (result) {
-		struct Scsi_Device_Template *sdt;
-
-		sdt = scsi_get_request_dev(cmd->request);
-		printk("SCSI %s error : <%d %d %d %d> return code = 0x%x\n",
-		       (sdt ? sdt->name : "device"),
+		printk("SCSI error : <%d %d %d %d> return code = 0x%x\n",
 		       cmd->device->host->host_no,
 		       cmd->device->channel,
 		       cmd->device->id,
@@ -945,7 +918,6 @@
 
 static int scsi_prep_fn(struct request_queue *q, struct request *req)
 {
-	struct Scsi_Device_Template *sdt;
 	struct scsi_device *sdev = q->queuedata;
 	struct scsi_cmnd *cmd;
 
@@ -1001,6 +973,7 @@
 	 * happening now.
 	 */
 	if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
+		struct scsi_driver *drv;
 		int ret;
 
 		/*
@@ -1015,8 +988,6 @@
 		 * some kinds of consistency checking may cause the	
 		 * request to be rejected immediately.
 		 */
-		sdt = scsi_get_request_dev(req);
-		BUG_ON(!sdt);
 
 		/* 
 		 * This sets up the scatter-gather table (allocating if
@@ -1029,7 +1000,8 @@
 		/*
 		 * Initialize the actual SCSI command for this request.
 		 */
-		if (unlikely(!sdt->init_command(cmd))) {
+		drv = *(struct scsi_driver **)req->rq_disk->private_data;
+		if (unlikely(!drv->init_command(cmd))) {
 			scsi_release_buffers(cmd);
 			scsi_put_command(cmd);
 			return BLKPREP_KILL;
===== drivers/scsi/scsi_priv.h 1.6 vs edited =====
--- 1.6/drivers/scsi/scsi_priv.h	Mon May 12 00:12:54 2003
+++ edited/drivers/scsi/scsi_priv.h	Fri May 16 17:34:35 2003
@@ -41,9 +41,6 @@
 #define SCSI_SENSE_VALID(scmd) \
 	(((scmd)->sense_buffer[0] & 0x70) == 0x70)
 
-struct Scsi_Device_Template;
-
-
 /*
  * scsi_target: representation of a scsi target, for now, this is only
  * used for single_lun devices. If no one has active IO to the target,
@@ -68,9 +65,6 @@
 extern void scsi_done(struct scsi_cmnd *cmd);
 extern void scsi_finish_command(struct scsi_cmnd *cmd);
 extern int scsi_retry_command(struct scsi_cmnd *cmd);
-extern int scsi_attach_device(struct scsi_device *sdev);
-extern void scsi_detach_device(struct scsi_device *sdev);
-extern void scsi_rescan_device(struct scsi_device *sdev);
 extern int scsi_insert_special_req(struct scsi_request *sreq, int);
 extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
 		struct scsi_request *sreq);
@@ -117,12 +111,11 @@
 extern void scsi_free_sdev(struct scsi_device *);
 extern void scsi_free_shost(struct Scsi_Host *);
 extern void scsi_host_get(struct Scsi_Host *);
+extern void scsi_rescan_device(struct device *dev);
 
 /* scsi_sysfs.c */
 extern int scsi_device_register(struct scsi_device *);
 extern void scsi_device_unregister(struct scsi_device *);
-extern int scsi_upper_driver_register(struct Scsi_Device_Template *);
-extern void scsi_upper_driver_unregister(struct Scsi_Device_Template *);
 extern void scsi_sysfs_init_host(struct Scsi_Host *);
 extern int scsi_sysfs_add_host(struct Scsi_Host *, struct device *);
 extern void scsi_sysfs_remove_host(struct Scsi_Host *);
===== drivers/scsi/scsi_scan.c 1.85 vs edited =====
--- 1.85/drivers/scsi/scsi_scan.c	Thu May  8 20:24:15 2003
+++ edited/drivers/scsi/scsi_scan.c	Fri May 16 17:34:36 2003
@@ -1091,22 +1091,29 @@
 				    uint channel, uint id, uint lun)
 {
 	struct scsi_device *sdev;
-	int error = -ENODEV, res;
+	int res;
 
 	res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev);
-	if (res == SCSI_SCAN_LUN_PRESENT)
-		error = scsi_attach_device(sdev);
-
-	if (error)
-		sdev = ERR_PTR(error);
+	if (res != SCSI_SCAN_LUN_PRESENT)
+		sdev = ERR_PTR(-ENODEV);
 	return sdev;
 }
 
 int scsi_remove_device(struct scsi_device *sdev)
 {
-	scsi_detach_device(sdev);
 	scsi_device_unregister(sdev);
 	return 0;
+}
+
+void scsi_rescan_device(struct device *dev)
+{
+	struct scsi_driver *drv = to_scsi_driver(dev->driver);
+
+	if (try_module_get(drv->owner)) {
+		if (drv->rescan)
+			drv->rescan(dev);
+		module_put(drv->owner);
+	}
 }
 
 /**
===== drivers/scsi/scsi_syms.c 1.36 vs edited =====
--- 1.36/drivers/scsi/scsi_syms.c	Thu May  8 20:24:15 2003
+++ edited/drivers/scsi/scsi_syms.c	Fri May 16 17:34:36 2003
@@ -29,8 +29,8 @@
  * This source file contains the symbol table used by scsi loadable
  * modules.
  */
-EXPORT_SYMBOL(scsi_register_device);
-EXPORT_SYMBOL(scsi_unregister_device);
+EXPORT_SYMBOL(scsi_register_driver);
+EXPORT_SYMBOL(scsi_unregister_driver);
 EXPORT_SYMBOL(scsi_register_host);
 EXPORT_SYMBOL(scsi_unregister_host);
 EXPORT_SYMBOL(scsi_add_host);
===== drivers/scsi/scsi_sysfs.c 1.16 vs edited =====
--- 1.16/drivers/scsi/scsi_sysfs.c	Mon May 12 00:12:40 2003
+++ edited/drivers/scsi/scsi_sysfs.c	Fri May 16 17:34:36 2003
@@ -57,32 +57,12 @@
 	.name		= "scsi_host",
 };
 
-/**
- * scsi_bus_match:
- * @dev:
- * @dev_driver:
- *
- * Return value:
- **/
-static int scsi_bus_match(struct device *dev, 
-                          struct device_driver *dev_driver)
+/* all probing is done in the individual ->probe routines */
+static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
 {
-        if (!strcmp("sg", dev_driver->name)) {
-                if (strstr(dev->bus_id, ":gen"))
-                        return 1;
-        } else if (!strcmp("st",dev_driver->name)) {
-                if (strstr(dev->bus_id,":mt"))
-                        return 1;
-        } else if (!strcmp("sd", dev_driver->name)) {
-                if ((!strstr(dev->bus_id, ":gen")) && 
-		    (!strstr(dev->bus_id, ":mt"))) { 
-                        return 1;
-                }
-	}
-        return 0;
+	return 1;
 }
 
-
 static struct bus_type scsi_bus_type = {
         .name		= "scsi",
         .match		= scsi_bus_match,
@@ -109,34 +89,6 @@
 	bus_unregister(&scsi_bus_type);
 }
 
-/**
- * scsi_upper_driver_register - register upper level driver.
- * @sdev_tp:	Upper level driver to register with the scsi bus.
- *
- * Return value:
- * 	0 on Success / non-zero on Failure
- **/
-int scsi_upper_driver_register(struct Scsi_Device_Template *sdev_tp)
-{
-	int error = 0;
-
-	sdev_tp->scsi_driverfs_driver.bus = &scsi_bus_type;
-	error = driver_register(&sdev_tp->scsi_driverfs_driver);
-
-	return error;
-}
-
-/**
- * scsi_upper_driver_unregister - unregister upper level driver 
- * @sdev_tp:	Upper level driver to unregister with the scsi bus.
- *
- **/
-void scsi_upper_driver_unregister(struct Scsi_Device_Template *sdev_tp)
-{
-	driver_unregister(&sdev_tp->scsi_driverfs_driver);
-}
-
-
 /*
  * sdev_show_function: macro to create an attr function that can be used to
  * show a non-bit field.
@@ -237,7 +189,7 @@
 static ssize_t
 store_rescan_field (struct device *dev, const char *buf, size_t count) 
 {
-	scsi_rescan_device(to_scsi_device(dev));
+	scsi_rescan_device(dev);
 	return 0;
 }
 
@@ -310,6 +262,18 @@
 	device_unregister(&sdev->sdev_driverfs_dev);
 }
 
+int scsi_register_driver(struct scsi_driver *drv)
+{
+	drv->gendrv.bus = &scsi_bus_type;
+
+	return driver_register(&drv->gendrv);
+}
+
+void scsi_unregister_driver(struct scsi_driver *drv)
+{
+	driver_unregister(&drv->gendrv);
+}
+
 static void scsi_host_release(struct device *dev)
 {
 	struct Scsi_Host *shost;
@@ -347,7 +311,7 @@
 	int i, error;
 
 	if (!shost->host_gendev.parent)
-		shost->host_gendev.parent = (dev) ? dev : &legacy_bus;
+		shost->host_gendev.parent = dev ? dev : &legacy_bus;
 
 	error = device_add(&shost->host_gendev);
 	if (error)
===== drivers/scsi/sd.c 1.112 vs edited =====
--- 1.112/drivers/scsi/sd.c	Thu May  8 12:16:20 2003
+++ edited/drivers/scsi/sd.c	Fri May 16 17:34:40 2003
@@ -73,8 +73,7 @@
 #define SD_MAX_RETRIES		5
 
 struct scsi_disk {
-	struct list_head list;		/* list of all scsi_disks */
-	struct Scsi_Device_Template *driver;	/* always &sd_template */
+	struct scsi_driver *driver;	/* always &sd_template */
 	struct scsi_device *device;
 	struct gendisk	*disk;
 	sector_t	capacity;	/* size in 512-byte sectors */
@@ -85,37 +84,31 @@
 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
 };
 
-static LIST_HEAD(sd_devlist);
-static spinlock_t sd_devlist_lock = SPIN_LOCK_UNLOCKED;
-
 static unsigned long sd_index_bits[SD_DISKS / BITS_PER_LONG];
 static spinlock_t sd_index_lock = SPIN_LOCK_UNLOCKED;
 
 static void sd_init_onedisk(struct scsi_disk * sdkp, struct gendisk *disk);
 static void sd_rw_intr(struct scsi_cmnd * SCpnt);
 
-static int sd_attach(struct scsi_device *);
-static void sd_detach(struct scsi_device *);
-static void sd_rescan(struct scsi_device *);
+static int sd_probe(struct device *);
+static int sd_remove(struct device *);
+static void sd_shutdown(struct device *dev);
+static void sd_rescan(struct device *);
 static int sd_init_command(struct scsi_cmnd *);
 static int sd_synchronize_cache(struct scsi_disk *, int);
-static int sd_notifier(struct notifier_block *, unsigned long, void *);
 static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
 		 struct scsi_request *SRpnt, unsigned char *buffer);
-static struct notifier_block sd_notifier_block = {sd_notifier, NULL, 0}; 
 
-static struct Scsi_Device_Template sd_template = {
-	.module		= THIS_MODULE,
-	.list		= LIST_HEAD_INIT(sd_template.list),
-	.name		= "disk",
-	.scsi_type	= TYPE_DISK,
-	.attach		= sd_attach,
-	.detach		= sd_detach,
-	.rescan		= sd_rescan,
-	.init_command	= sd_init_command,
-	.scsi_driverfs_driver = {
-		.name   = "sd",
+static struct scsi_driver sd_template = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		= "sd",
+		.probe		= sd_probe,
+		.remove		= sd_remove,
+		.shutdown	= sd_shutdown,
 	},
+	.rescan			= sd_rescan,
+	.init_command		= sd_init_command,
 };
 
 static int sd_major(int major_idx)
@@ -133,36 +126,6 @@
 	}
 }
 
-static struct scsi_disk *sd_find_by_sdev(Scsi_Device *sd)
-{
-	struct scsi_disk *sdkp;
-
-	spin_lock(&sd_devlist_lock);
-	list_for_each_entry(sdkp, &sd_devlist, list) {
-		if (sdkp->device == sd) {
-			spin_unlock(&sd_devlist_lock);
-			return sdkp;
-		}
-	}
-
-	spin_unlock(&sd_devlist_lock);
-	return NULL;
-}
-
-static inline void sd_devlist_insert(struct scsi_disk *sdkp)
-{
-	spin_lock(&sd_devlist_lock);
-	list_add(&sdkp->list, &sd_devlist);
-	spin_unlock(&sd_devlist_lock);
-}
-
-static inline void sd_devlist_remove(struct scsi_disk *sdkp)
-{
-	spin_lock(&sd_devlist_lock);
-	list_del(&sdkp->list);
-	spin_unlock(&sd_devlist_lock);
-}
- 
 static inline struct scsi_disk *scsi_disk(struct gendisk *disk)
 {
 	return container_of(disk->private_data, struct scsi_disk, driver);
@@ -635,12 +598,13 @@
 	return 1;
 }
 
-static void sd_rescan(struct scsi_device * sdp)
+static void sd_rescan(struct device *dev)
 {
-	unsigned char *buffer;
-	struct scsi_disk *sdkp = sd_find_by_sdev(sdp);
+	struct scsi_device *sdp = to_scsi_device(dev);
+	struct scsi_disk *sdkp = dev_get_drvdata(dev);
 	struct gendisk *gd;
 	struct scsi_request *SRpnt;
+	unsigned char *buffer;
 
 	if (!sdkp || sdp->online == FALSE || !sdkp->media_present)
 		return;
@@ -1288,10 +1252,10 @@
 }
 
 /**
- *	sd_attach - called during driver initialization and whenever a
+ *	sd_probe - called during driver initialization and whenever a
  *	new scsi device is attached to the system. It is called once
  *	for each scsi device (not just disks) present.
- *	@sdp: pointer to mid level scsi device object
+ *	@dev: pointer to device object
  *
  *	Returns 0 if successful (or not interested in this scsi device 
  *	(e.g. scanner)); 1 when there is an error.
@@ -1303,17 +1267,19 @@
  *	and minor number that is chosen here.
  *
  *	Assume sd_attach is not re-entrant (for time being)
- *	Also think about sd_attach() and sd_detach() running coincidentally.
+ *	Also think about sd_attach() and sd_remove() running coincidentally.
  **/
-static int sd_attach(struct scsi_device * sdp)
+static int sd_probe(struct device *dev)
 {
+	struct scsi_device *sdp = to_scsi_device(dev);
 	struct scsi_disk *sdkp;
 	struct gendisk *gd;
 	u32 index;
 	int error;
 
+	error = -ENODEV;
 	if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD))
-		return 1;
+		goto out;
 
 	SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", 
 			 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun));
@@ -1365,8 +1331,8 @@
 	gd->private_data = &sdkp->driver;
 	gd->queue = sdkp->device->request_queue;
 
-	sd_devlist_insert(sdkp);
 	set_capacity(gd, sdkp->capacity);
+	dev_set_drvdata(dev, sdkp);
 	add_disk(gd);
 
 	printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, "
@@ -1385,44 +1351,42 @@
 }
 
 /**
- *	sd_detach - called whenever a scsi disk (previously recognized by
- *	sd_attach) is detached from the system. It is called (potentially
+ *	sd_remove - called whenever a scsi disk (previously recognized by
+ *	sd_probe) is detached from the system. It is called (potentially
  *	multiple times) during sd module unload.
  *	@sdp: pointer to mid level scsi device object
  *
  *	Note: this function is invoked from the scsi mid-level.
  *	This function potentially frees up a device name (e.g. /dev/sdc)
- *	that could be re-used by a subsequent sd_attach().
+ *	that could be re-used by a subsequent sd_probe().
  *	This function is not called when the built-in sd driver is "exit-ed".
  **/
-static void sd_detach(struct scsi_device * sdp)
+static int sd_remove(struct device *dev)
 {
-	struct scsi_disk *sdkp;
-
-	SCSI_LOG_HLQUEUE(3, printk("sd_detach: <%d,%d,%d,%d>\n", 
-			    sdp->host->host_no, sdp->channel, sdp->id, 
-			    sdp->lun));
-
-	sdkp = sd_find_by_sdev(sdp);
-	if (!sdkp)
-		return;
+	struct scsi_disk *sdkp = dev_get_drvdata(dev);
 
-	/* check that we actually have a write back cache to synchronize */
-	if (sdkp->WCE) {
-		printk(KERN_NOTICE "Synchronizing SCSI cache: ");
-		sd_synchronize_cache(sdkp, 1);
-		printk("\n");
-	}
-
-	sd_devlist_remove(sdkp);
 	del_gendisk(sdkp->disk);
 
 	spin_lock(&sd_index_lock);
 	clear_bit(sdkp->index, sd_index_bits);
 	spin_unlock(&sd_index_lock);
 
+	sd_shutdown(dev);
 	put_disk(sdkp->disk);
 	kfree(sdkp);
+
+	return 0;
+}
+
+static void sd_shutdown(struct device *dev)
+{
+	struct scsi_disk *sdkp = dev_get_drvdata(dev);
+
+	if (sdkp->WCE) {
+		printk(KERN_NOTICE "Synchronizing SCSI cache: ");
+		sd_synchronize_cache(sdkp, 1);
+		printk("\n");
+	}
 }
 
 /**
@@ -1433,7 +1397,7 @@
  **/
 static int __init init_sd(void)
 {
-	int majors = 0, rc = -ENODEV, i;
+	int majors = 0, i;
 
 	SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
 
@@ -1444,11 +1408,7 @@
 	if (!majors)
 		return -ENODEV;
 
-	rc = scsi_register_device(&sd_template);
-	if (rc)
-		return rc;
-	register_reboot_notifier(&sd_notifier_block);
-	return rc;
+	return scsi_register_driver(&sd_template);
 }
 
 /**
@@ -1462,35 +1422,9 @@
 
 	SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
 
-	unregister_reboot_notifier(&sd_notifier_block);
-	scsi_unregister_device(&sd_template);
+	scsi_unregister_driver(&sd_template);
 	for (i = 0; i < SD_MAJORS; i++)
 		unregister_blkdev(sd_major(i), "sd");
-}
-
-/*
- * XXX: this function does not take sd_devlist_lock to synchronize
- *	access to sd_devlist.  This should be safe as no other reboot
- *	notifier can access it.
- */
-static int sd_notifier(struct notifier_block *n, unsigned long event, void *p)
-{
-	if (event != SYS_RESTART &&
-	    event != SYS_HALT &&
-	    event != SYS_POWER_OFF)
-		return NOTIFY_DONE;
-
-	if (!list_empty(&sd_devlist)) {
-		struct scsi_disk *sdkp;
-
-		printk(KERN_NOTICE "Synchronizing SCSI caches: ");
-		list_for_each_entry(sdkp, &sd_devlist, list)
-			if (sdkp->WCE)
-				sd_synchronize_cache(sdkp, 1);
-		printk("\n");
-	}
-
-	return NOTIFY_OK;
 }
 
 /* send a SYNCHRONIZE CACHE instruction down to the device through the
===== drivers/scsi/sg.c 1.54 vs edited =====
--- 1.54/drivers/scsi/sg.c	Wed May  7 16:15:40 2003
+++ edited/drivers/scsi/sg.c	Fri May 16 17:34:40 2003
@@ -112,23 +112,20 @@
 
 #define SG_DEV_ARR_LUMP 6	/* amount to over allocate sg_dev_arr by */
 
-static int sg_attach(Scsi_Device *);
-static void sg_detach(Scsi_Device *);
+static int sg_probe(struct device *);
+static int sg_remove(struct device *);
 
 static Scsi_Request *dummy_cmdp;	/* only used for sizeof */
 
 static rwlock_t sg_dev_arr_lock = RW_LOCK_UNLOCKED;	/* Also used to lock
 							   file descriptor list for device */
 
-static struct Scsi_Device_Template sg_template = {
-	.module = THIS_MODULE,
-	.list = LIST_HEAD_INIT(sg_template.list),
-	.name = "generic",
-	.scsi_type = 0xff,
-	.attach = sg_attach,
-	.detach = sg_detach,
-	.scsi_driverfs_driver = {
-		.name = "sg",
+static struct scsi_driver sg_template = {
+	.owner		= THIS_MODULE,
+	.gendrv = {
+		.name	= "sg",
+		.probe	= sg_probe,
+		.remove	= sg_remove,
 	},
 };
 
@@ -180,15 +177,14 @@
 } Sg_fd;
 
 typedef struct sg_device { /* holds the state of each scsi generic device */
-	struct Scsi_Device_Template *driver;
-	Scsi_Device *device;
+	struct scsi_driver *driver;
+	struct scsi_device *device;
 	wait_queue_head_t o_excl_wait;	/* queue open() when O_EXCL in use */
 	int sg_tablesize;	/* adapter's max scatter-gather table size */
 	Sg_fd *headfp;		/* first open fd belonging to this device */
 	volatile char detached;	/* 0->attached, 1->detached pending removal */
 	volatile char exclude;	/* opened for exclusive access */
 	char sgdebug;		/* 0->off, 1->sense, 9->dump dev, 10-> all devs */
-	struct device sg_driverfs_dev;
 	struct gendisk *disk;
 } Sg_device;
 
@@ -1332,7 +1328,7 @@
 static ssize_t
 sg_device_kdev_read(struct device *driverfs_dev, char *page)
 {
-	Sg_device *sdp = list_entry(driverfs_dev, Sg_device, sg_driverfs_dev);
+	Sg_device *sdp = dev_get_drvdata(driverfs_dev);
 	return sprintf(page, "%x\n", MKDEV(sdp->disk->major,
 					   sdp->disk->first_minor));
 }
@@ -1347,8 +1343,9 @@
 static DEVICE_ATTR(type,S_IRUGO,sg_device_type_read,NULL);
 
 static int
-sg_attach(Scsi_Device * scsidp)
+sg_probe(struct device *dev)
 {
+	struct scsi_device *scsidp = to_scsi_device(dev);
 	struct gendisk *disk;
 	Sg_device *sdp = NULL;
 	unsigned long iflags;
@@ -1431,21 +1428,12 @@
 	sdp->detached = 0;
 	sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
 
-	memset(&sdp->sg_driverfs_dev, 0, sizeof (struct device));
-	snprintf(sdp->sg_driverfs_dev.bus_id, BUS_ID_SIZE, "%s:gen",
-		scsidp->sdev_driverfs_dev.bus_id);
-	snprintf(sdp->sg_driverfs_dev.name, DEVICE_NAME_SIZE, "%sgeneric",
-		scsidp->sdev_driverfs_dev.name);
-	sdp->sg_driverfs_dev.parent = &scsidp->sdev_driverfs_dev;
-	sdp->sg_driverfs_dev.bus = scsidp->sdev_driverfs_dev.bus;
-
 	sg_nr_dev++;
 	sg_dev_arr[k] = sdp;
 	write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
 
-	device_register(&sdp->sg_driverfs_dev);
-	device_create_file(&sdp->sg_driverfs_dev, &dev_attr_type);
-	device_create_file(&sdp->sg_driverfs_dev, &dev_attr_kdev);
+	device_create_file(&scsidp->sdev_driverfs_dev, &dev_attr_type);
+	device_create_file(&scsidp->sdev_driverfs_dev, &dev_attr_kdev);
 
 	sprintf(devfs_name, "%s/generic", scsidp->devfs_name);
 	devfs_register(NULL, devfs_name, 0,
@@ -1453,20 +1441,13 @@
 			S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
 			&sg_fops, sdp);
 
-	switch (scsidp->type) {
-	case TYPE_DISK:
-	case TYPE_MOD:
-	case TYPE_ROM:
-	case TYPE_WORM:
-	case TYPE_TAPE:
-		break;
-	default:
-		printk(KERN_NOTICE
-		       "Attached scsi generic sg%d at scsi%d, channel"
-		       " %d, id %d, lun %d,  type %d\n", k,
-		       scsidp->host->host_no, scsidp->channel, scsidp->id,
-		       scsidp->lun, scsidp->type);
-	}
+	printk(KERN_NOTICE
+	       "Attached scsi generic sg%d at scsi%d, channel"
+	       " %d, id %d, lun %d,  type %d\n", k,
+	       scsidp->host->host_no, scsidp->channel, scsidp->id,
+	       scsidp->lun, scsidp->type);
+
+	dev_set_drvdata(dev, sdp);
 	return 0;
 
 out:
@@ -1474,9 +1455,10 @@
 	return error;
 }
 
-static void
-sg_detach(Scsi_Device * scsidp)
+static int
+sg_remove(struct device *dev)
 {
+	struct scsi_device *scsidp = to_scsi_device(dev);
 	Sg_device *sdp = NULL;
 	unsigned long iflags;
 	Sg_fd *sfp;
@@ -1486,7 +1468,7 @@
 	int k, delay;
 
 	if (NULL == sg_dev_arr)
-		return;
+		return 0;
 	delay = 0;
 	write_lock_irqsave(&sg_dev_arr_lock, iflags);
 	for (k = 0; k < sg_dev_max; k++) {
@@ -1527,9 +1509,8 @@
 
 	if (sdp) {
 		devfs_remove("%s/generic", scsidp->devfs_name);
-		device_remove_file(&sdp->sg_driverfs_dev, &dev_attr_type);
-		device_remove_file(&sdp->sg_driverfs_dev, &dev_attr_kdev);
-		device_unregister(&sdp->sg_driverfs_dev);
+		device_remove_file(&scsidp->sdev_driverfs_dev, &dev_attr_type);
+		device_remove_file(&scsidp->sdev_driverfs_dev, &dev_attr_kdev);
 		put_disk(sdp->disk);
 		sdp->disk = NULL;
 		if (NULL == sdp->headfp)
@@ -1538,6 +1519,8 @@
 
 	if (delay)
 		scsi_sleep(2);	/* dirty detach so delay device destruction */
+
+	return 0;
 }
 
 /* Set 'perm' (4th argument) to 0 to disable module_param's definition
@@ -1595,7 +1578,7 @@
 
 static void do_create_driverfs_files(void)
 {
-	struct device_driver * driverfs = &sg_template.scsi_driverfs_driver;
+	struct device_driver * driverfs = &sg_template.gendrv;
 
 	driver_create_file(driverfs, &driver_attr_allow_dio);
 	driver_create_file(driverfs, &driver_attr_def_reserved_size);
@@ -1604,7 +1587,7 @@
 
 static void do_remove_driverfs_files(void)
 {
-	struct device_driver * driverfs = &sg_template.scsi_driverfs_driver;
+	struct device_driver * driverfs = &sg_template.gendrv;
 
 	driver_remove_file(driverfs, &driver_attr_version);
 	driver_remove_file(driverfs, &driver_attr_def_reserved_size);
@@ -1622,7 +1605,7 @@
 	rc = register_chrdev(SCSI_GENERIC_MAJOR, "sg", &sg_fops);
 	if (rc)
 		return rc;
-	rc = scsi_register_device(&sg_template);
+	rc = scsi_register_driver(&sg_template);
 	if (rc)
 		return rc;
 #ifdef CONFIG_PROC_FS
@@ -1639,7 +1622,7 @@
 #ifdef CONFIG_PROC_FS
 	sg_proc_cleanup();
 #endif				/* CONFIG_PROC_FS */
-	scsi_unregister_device(&sg_template);
+	scsi_unregister_driver(&sg_template);
 	unregister_chrdev(SCSI_GENERIC_MAJOR, "sg");
 	if (sg_dev_arr != NULL) {
 		vfree((char *) sg_dev_arr);
===== drivers/scsi/sr.c 1.78 vs edited =====
--- 1.78/drivers/scsi/sr.c	Wed May  7 16:15:41 2003
+++ edited/drivers/scsi/sr.c	Fri May 16 17:34:40 2003
@@ -67,26 +67,20 @@
 	 CDC_PLAY_AUDIO|CDC_RESET|CDC_IOCTLS|CDC_DRIVE_STATUS| \
 	 CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_GENERIC_PACKET)
 
-static int sr_attach(struct scsi_device *);
-static void sr_detach(struct scsi_device *);
+static int sr_probe(struct device *);
+static int sr_remove(struct device *);
 static int sr_init_command(struct scsi_cmnd *);
 
-static struct Scsi_Device_Template sr_template = {
-	.module		= THIS_MODULE,
-	.list		= LIST_HEAD_INIT(sr_template.list),
-	.name		= "cdrom",
-	.scsi_type	= TYPE_ROM,
-	.attach		= sr_attach,
-	.detach		= sr_detach,
-	.init_command	= sr_init_command,
-	.scsi_driverfs_driver = {
-		.name   = "sr",
+static struct scsi_driver sr_template = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name   	= "sr",
+		.probe		= sr_probe,
+		.remove		= sr_remove,
 	},
+	.init_command		= sr_init_command,
 };
 
-static LIST_HEAD(sr_devlist);
-static spinlock_t sr_devlist_lock = SPIN_LOCK_UNLOCKED;
-
 static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG];
 static spinlock_t sr_index_lock = SPIN_LOCK_UNLOCKED;
 
@@ -99,37 +93,6 @@
 static int sr_media_change(struct cdrom_device_info *, int);
 static int sr_packet(struct cdrom_device_info *, struct cdrom_generic_command *);
 
-static Scsi_CD *sr_find_by_sdev(Scsi_Device *sd)
-{
-	struct list_head *p;
-	Scsi_CD *cd;
-
-	spin_lock(&sr_devlist_lock);
-	list_for_each(p, &sr_devlist) {
-		cd = list_entry(p, Scsi_CD, list);
-		if (cd->device == sd) {
-			spin_unlock(&sr_devlist_lock);
-			return cd;
-		}
-	}
-	spin_unlock(&sr_devlist_lock);
-	return NULL;
-}
-
-static inline void sr_devlist_insert(Scsi_CD *cd)
-{
-	spin_lock(&sr_devlist_lock);
-	list_add(&cd->list, &sr_devlist);
-	spin_unlock(&sr_devlist_lock);
-}
-
-static inline void sr_devlist_remove(Scsi_CD *cd)
-{
-	spin_lock(&sr_devlist_lock);
-	list_del(&cd->list);
-	spin_unlock(&sr_devlist_lock);
-}
-
 static struct cdrom_device_ops sr_dops = {
 	.open			= sr_open,
 	.release	 	= sr_release,
@@ -506,14 +469,16 @@
 	scsi_device_put(cd->device);
 }
 
-static int sr_attach(struct scsi_device *sdev)
+static int sr_probe(struct device *dev)
 {
+	struct scsi_device *sdev = to_scsi_device(dev);
 	struct gendisk *disk;
 	struct scsi_cd *cd;
 	int minor, error;
 
+	error = -ENODEV;
 	if (sdev->type != TYPE_ROM && sdev->type != TYPE_WORM)
-		return 1;
+		goto fail;
 
 	error = -ENOMEM;
 	cd = kmalloc(sizeof(*cd), GFP_KERNEL);
@@ -574,8 +539,8 @@
 	disk->private_data = &cd->driver;
 	disk->queue = sdev->request_queue;
 
+	dev_set_drvdata(dev, cd);
 	add_disk(disk);
-	sr_devlist_insert(cd);
 
 	printk(KERN_DEBUG
 	    "Attached scsi CD-ROM %s at scsi%d, channel %d, id %d, lun %d\n",
@@ -806,15 +771,10 @@
 	return cgc->stat;
 }
 
-static void sr_detach(struct scsi_device * SDp)
+static int sr_remove(struct device *dev)
 {
-	struct scsi_cd *cd;
+	struct scsi_cd *cd = dev_get_drvdata(dev);
 
-	cd = sr_find_by_sdev(SDp);
-	if (!cd)
-		return;
-
-	sr_devlist_remove(cd);
 	del_gendisk(cd->disk);
 
 	spin_lock(&sr_index_lock);
@@ -824,6 +784,8 @@
 	put_disk(cd->disk);
 	unregister_cdrom(&cd->cdi);
 	kfree(cd);
+
+	return 0;
 }
 
 static int __init init_sr(void)
@@ -833,12 +795,12 @@
 	rc = register_blkdev(SCSI_CDROM_MAJOR, "sr");
 	if (rc)
 		return rc;
-	return scsi_register_device(&sr_template);
+	return scsi_register_driver(&sr_template);
 }
 
 static void __exit exit_sr(void)
 {
-	scsi_unregister_device(&sr_template);
+	scsi_unregister_driver(&sr_template);
 	unregister_blkdev(SCSI_CDROM_MAJOR, "sr");
 }
 
===== drivers/scsi/sr.h 1.9 vs edited =====
--- 1.9/drivers/scsi/sr.h	Sun Nov  3 14:46:32 2002
+++ edited/drivers/scsi/sr.h	Fri May 16 17:34:40 2003
@@ -25,8 +25,7 @@
 #define IOCTL_TIMEOUT 30*HZ
 
 typedef struct scsi_cd {
-	struct Scsi_Device_Template *driver;
-	struct list_head list;
+	struct scsi_driver *driver;
 	unsigned capacity;	/* size in blocks                       */
 	Scsi_Device *device;
 	unsigned int vendor;	/* vendor code, see sr_vendor.c         */
===== drivers/scsi/st.c 1.61 vs edited =====
--- 1.61/drivers/scsi/st.c	Wed May  7 16:15:41 2003
+++ edited/drivers/scsi/st.c	Fri May 16 17:35:26 2003
@@ -170,22 +170,19 @@
 			      unsigned long, size_t, int);
 static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
 
-static int st_attach(Scsi_Device *);
-static void st_detach(Scsi_Device *);
+static int st_probe(struct device *);
+static int st_remove(struct device *);
 
 static void do_create_driverfs_files(void);
 static void do_remove_driverfs_files(void);
 
 
-static struct Scsi_Device_Template st_template = {
-	.module =	THIS_MODULE,
-	.list =		LIST_HEAD_INIT(st_template.list),
-	.name =		"tape", 
-	.scsi_type =	TYPE_TAPE,
-	.attach =	st_attach, 
-	.detach =	st_detach,
-	.scsi_driverfs_driver = {
-		.name = "st",
+static struct scsi_driver st_template = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		= "st",
+		.probe		= st_probe,
+		.remove		= st_remove,
 	},
 };
 
@@ -3704,8 +3701,9 @@
 	.release =	st_release,
 };
 
-static int st_attach(Scsi_Device * SDp)
+static int st_probe(struct device *dev)
 {
+	struct scsi_device *SDp = to_scsi_device(dev);
 	struct gendisk *disk;
 	Scsi_Tape *tpnt;
 	ST_mode *STm;
@@ -3716,13 +3714,13 @@
 	u64 bounce_limit;
 
 	if (SDp->type != TYPE_TAPE)
-		return 1;
+		return -ENODEV;
 	if ((stp = st_incompatible(SDp))) {
 		printk(KERN_INFO
 		       "st: Found incompatible tape at scsi%d, channel %d, id %d, lun %d\n",
 		       SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
 		printk(KERN_INFO "st: The suggested driver is %s.\n", stp);
-		return 1;
+		return -ENODEV;
 	}
 
 	i = SDp->host->sg_tablesize;
@@ -3921,11 +3919,12 @@
 out_buffer_free:
 	kfree(buffer);
 out:
-	return 1;
+	return -ENODEV;
 };
 
-static void st_detach(Scsi_Device * SDp)
+static int st_remove(struct device *dev)
 {
+	Scsi_Device *SDp = to_scsi_device(dev);
 	Scsi_Tape *tpnt;
 	int i, mode;
 
@@ -3960,12 +3959,12 @@
 			}
 			put_disk(tpnt->disk);
 			kfree(tpnt);
-			return;
+			return 0;
 		}
 	}
 
 	write_unlock(&st_dev_arr_lock);
-	return;
+	return 0;
 }
 
 static int __init init_st(void)
@@ -3977,7 +3976,7 @@
 		verstr, st_fixed_buffer_size, st_max_sg_segs);
 
 	if (register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) {
-		if (scsi_register_device(&st_template) == 0) {
+		if (scsi_register_driver(&st_template) == 0) {
 			do_create_driverfs_files();
 			return 0;
 		}
@@ -3990,20 +3989,10 @@
 
 static void __exit exit_st(void)
 {
-	int i;
-
 	do_remove_driverfs_files();
-	scsi_unregister_device(&st_template);
+	scsi_unregister_driver(&st_template);
 	unregister_chrdev(SCSI_TAPE_MAJOR, "st");
-	if (scsi_tapes != NULL) {
-		for (i=0; i < st_dev_max; ++i)
-			if (scsi_tapes[i]) {
-				printk(KERN_WARNING "st: scsi_tapes[] not "
-				    "empty after scsi_unregister_device\n");
-				st_detach(scsi_tapes[i]->device);
-			}
-		kfree(scsi_tapes);
-	}
+	kfree(scsi_tapes);
 	printk(KERN_INFO "st: Unloaded.\n");
 }
 
@@ -4038,7 +4027,7 @@
 
 static void do_create_driverfs_files(void)
 {
-	struct device_driver *driverfs = &st_template.scsi_driverfs_driver;
+	struct device_driver *driverfs = &st_template.gendrv;
 
 	driver_create_file(driverfs, &driver_attr_try_direct_io);
 	driver_create_file(driverfs, &driver_attr_fixed_buffer_size);
@@ -4048,7 +4037,7 @@
 
 static void do_remove_driverfs_files(void)
 {
-	struct device_driver *driverfs = &st_template.scsi_driverfs_driver;
+	struct device_driver *driverfs = &st_template.gendrv;
 
 	driver_remove_file(driverfs, &driver_attr_version);
 	driver_remove_file(driverfs, &driver_attr_max_sg_segs);
===== drivers/scsi/st.h 1.13 vs edited =====
--- 1.13/drivers/scsi/st.h	Fri Apr 18 17:57:20 2003
+++ edited/drivers/scsi/st.h	Fri May 16 17:34:37 2003
@@ -70,7 +70,7 @@
 
 /* The tape drive descriptor */
 typedef struct {
-	struct Scsi_Device_Template *driver;
+	struct scsi_driver *driver;
 	Scsi_Device *device;
 	struct semaphore lock;	/* For serialization */
 	struct completion wait;	/* For SCSI commands */

             reply	other threads:[~2003-05-16 16:08 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-05-16 16:20 Christoph Hellwig [this message]
2003-05-16 23:57 ` [PATCH] switch scsi upper driver probing to the driver model Mike Anderson
2003-05-17  2:25   ` Willem Riede
2003-05-17  7:16   ` Christoph Hellwig
2003-05-17  9:17   ` Christoph Hellwig
2003-05-17 16:35     ` Mike Anderson
2003-05-17  9:59   ` Kai Makisara
2003-05-17 15:08     ` Christoph Hellwig
2003-05-17 16:19       ` James Bottomley
2003-05-18  9:35     ` Kai Makisara
2003-05-17  3:59 ` Douglas Gilbert
2003-05-17  7:13   ` Christoph Hellwig
2003-05-19 19:02     ` Greg KH
2003-05-17  8:32   ` Jens Axboe
2003-05-17 12:52   ` Willem Riede
2003-05-19 21:38 ` Patrick Mansfield

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=20030516182039.A7369@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox