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] 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 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.