public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] switch scsi upper driver probing to the driver model
@ 2003-05-16 16:20 Christoph Hellwig
  2003-05-16 23:57 ` Mike Anderson
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Christoph Hellwig @ 2003-05-16 16:20 UTC (permalink / raw)
  To: James.Bottomley; +Cc: linux-scsi

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 */

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-16 16:20 [PATCH] switch scsi upper driver probing to the driver model Christoph Hellwig
@ 2003-05-16 23:57 ` Mike Anderson
  2003-05-17  2:25   ` Willem Riede
                     ` (3 more replies)
  2003-05-17  3:59 ` Douglas Gilbert
  2003-05-19 21:38 ` Patrick Mansfield
  2 siblings, 4 replies; 16+ messages in thread
From: Mike Anderson @ 2003-05-16 23:57 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: James.Bottomley, linux-scsi

Christoph Hellwig [hch@lst.de] wrote:
> 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.
> 
> 

I ran your patch and I dead locked on st_probe. This is due to the code
in st_probe and osst_probe that do device registers on the
sdev_driverfs_dev.bus which is the bus that the probe is being called
from already. I had an old patch that removed these before due the driver
model requirement that objects on the device list must be of one type.
At the time I did not have a place to move these attributes.

We now have /bus/scsi/drivers/{uld} for driver attributes. We also could
create a class for other attributes if needed. We can also use udev for
the creation of special nodes.

ftp://ftp.kernel.org/pub/linux/utils/kernel/hotplug/

In the short term is the st and osst maintainers are ok with it we could
remove them and then create them in there proper home.

-andmike
--
Michael Anderson
andmike@us.ibm.com


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-16 23:57 ` Mike Anderson
@ 2003-05-17  2:25   ` Willem Riede
  2003-05-17  7:16   ` Christoph Hellwig
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: Willem Riede @ 2003-05-17  2:25 UTC (permalink / raw)
  To: linux-scsi

On 2003.05.16 19:57, Mike Anderson wrote:
> 
> I ran your patch and I dead locked on st_probe. This is due to the code
> in st_probe and osst_probe that do device registers on the
> sdev_driverfs_dev.bus which is the bus that the probe is being called
> from already. I had an old patch that removed these before due the driver
> model requirement that objects on the device list must be of one type.
> At the time I did not have a place to move these attributes.
> 
> We now have /bus/scsi/drivers/{uld} for driver attributes. We also could
> create a class for other attributes if needed. We can also use udev for
> the creation of special nodes.
> 
> ftp://ftp.kernel.org/pub/linux/utils/kernel/hotplug/
> 
> In the short term is the st and osst maintainers are ok with it we could
> remove them and then create them in there proper home.

As the osst maintainer I concur. I am going to need a class, I believe, as
I want to export some info from the tape header, i.e. per device (very
useful for me for support purposes). So some re-arrangement is going to
happen anyway.

Thanks, Willem Riede.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-16 16:20 [PATCH] switch scsi upper driver probing to the driver model Christoph Hellwig
  2003-05-16 23:57 ` Mike Anderson
@ 2003-05-17  3:59 ` Douglas Gilbert
  2003-05-17  7:13   ` Christoph Hellwig
                     ` (2 more replies)
  2003-05-19 21:38 ` Patrick Mansfield
  2 siblings, 3 replies; 16+ messages in thread
From: Douglas Gilbert @ 2003-05-17  3:59 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: James.Bottomley, linux-scsi

Christoph Hellwig wrote:
> 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.

Is that "_and_" symmetric? That is, can one have the sg
device in preference to the sd device? If so, how is
that selected?

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

Christoph,
This patch would have some interesting side effects:
   - no generic interface (apart from SCSI_IOCTL_SEND_COMMAND)
     for tape devices (st and osst). While the maintainers of
     st and osst might like this, not all the user apps would :-)
   - the SG_IO ioctl in the block level
      - limits maximum transfer size to 65536 bytes
      - does not support mmap-ed IO [and would need
        something like a reserved buffer concept to do it]
      - does not support direct IO
      - needs work (debuggings)
      - does not support async IO (either does SG_IO
        in sg but it can be done other ways in sg)
   - the extra ioctls that sg defines are either fudged
     or missing. This might upset programs other than
     cdrecord; cdparanoia comes to mind

It was my understanding that the device model has been
recently modified by Greg KH to cope with the dual nature
of the interface that sg causes. Evidently similar situations
occur elsewhere in the kernel.

Whether the sg driver is an upper level SCSI driver or
part of the mid level actually makes little difference.
The sgbind patch that I canvassed the other day
actually fits well into sg's functionality being subsumed
into the mid level with a single virtual device node
(e.g. /dev/scsi or /dev/scsibind ?) for access with each
open file descriptor getting its own state.

But then there is the problem of backward compatibility...

Doug Gilbert




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  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
  2 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2003-05-17  7:13 UTC (permalink / raw)
  To: Douglas Gilbert; +Cc: James.Bottomley, greg, linux-scsi

On Sat, May 17, 2003 at 01:59:52PM +1000, Douglas Gilbert wrote:
> Is that "_and_" symmetric? That is, can one have the sg
> device in preference to the sd device? If so, how is
> that selected?

You can. In fact there's nothing in this patch that preferes sd over sg
except the existing link order.  A better way to control the driver
matching would be nice but that nothing that should be done in the
scsi code but rather a generic driver model thing.

> Christoph,
> This patch would have some interesting side effects:
>    - no generic interface (apart from SCSI_IOCTL_SEND_COMMAND)
>      for tape devices (st and osst). While the maintainers of
>      st and osst might like this, not all the user apps would :-)

I have some WIP code to make parts of drivers/block/scsi_ioctl.c
working for scsi char drivers.

>    - the extra ioctls that sg defines are either fudged
>      or missing. This might upset programs other than
>      cdrecord; cdparanoia comes to mind

Hmm, what does cdparanoia complain about?  And yes, I think we
need to kill all those return 0 ioctls from the block layer -
they might have helped to bring up the SG_IO code with cdrecord
but they are a really stupid idea long term.

> It was my understanding that the device model has been
> recently modified by Greg KH to cope with the dual nature
> of the interface that sg causes. Evidently similar situations
> occur elsewhere in the kernel.

Greg, any comments on this?  I haven't found any code like that
in drivers/base/ and I can't understand how this is supposed to work..`


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-16 23:57 ` 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  9:59   ` Kai Makisara
  3 siblings, 0 replies; 16+ messages in thread
From: Christoph Hellwig @ 2003-05-17  7:16 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi

On Fri, May 16, 2003 at 04:57:18PM -0700, Mike Anderson wrote:
> I ran your patch and I dead locked on st_probe.

Hmm, I loaded st fine here, but st_probe is of course never called when
I have no tapes.`

> This is due to the code
> in st_probe and osst_probe that do device registers on the
> sdev_driverfs_dev.bus which is the bus that the probe is being called
> from already. I had an old patch that removed these before due the driver
> model requirement that objects on the device list must be of one type.
> At the time I did not have a place to move these attributes.

Most of the attrributes should just go away - the code looks like
someone played with the driver model because it looked new and shiny..


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-17  3:59 ` Douglas Gilbert
  2003-05-17  7:13   ` Christoph Hellwig
@ 2003-05-17  8:32   ` Jens Axboe
  2003-05-17 12:52   ` Willem Riede
  2 siblings, 0 replies; 16+ messages in thread
From: Jens Axboe @ 2003-05-17  8:32 UTC (permalink / raw)
  To: Douglas Gilbert; +Cc: Christoph Hellwig, James.Bottomley, linux-scsi

On Sat, May 17 2003, Douglas Gilbert wrote:
>   - the SG_IO ioctl in the block level
>      - limits maximum transfer size to 65536 bytes

Correct, we can remove that though.

>      - does not support mmap-ed IO [and would need
>        something like a reserved buffer concept to do it]

Why should it?

>      - does not support direct IO

False, it uses direct IO all the time if the alignment is correct.

>      - needs work (debuggings)

Know of any bugs?

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-16 23:57 ` 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
  3 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2003-05-17  9:17 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi

On Fri, May 16, 2003 at 04:57:18PM -0700, Mike Anderson wrote:
> I ran your patch and I dead locked on st_probe. This is due to the code
> in st_probe and osst_probe that do device registers on the
> sdev_driverfs_dev.bus which is the bus that the probe is being called
> from already. I had an old patch that removed these before due the driver
> model requirement that objects on the device list must be of one type.
> At the time I did not have a place to move these attributes.

Okay, here's the patch to remove the strange kdev and type attributes
that caused this problems.  All the useful attributes are still left,
they're attributes of the right struct device.


--- 1.44/drivers/scsi/osst.c	Fri May 16 12:15:24 2003
+++ edited/drivers/scsi/osst.c	Fri May 16 13:18:52 2003
@@ -5323,22 +5323,6 @@
 
 #endif
 
-/* Driverfs file support */
-static ssize_t osst_device_kdev_read(struct device *driverfs_dev, char *page)
-{
-	kdev_t kdev; 
-	kdev.value=(int)(long)driverfs_dev->driver_data;
-	return sprintf(page, "%x\n",kdev.value);
-}
-static DEVICE_ATTR(kdev,S_IRUGO,osst_device_kdev_read,NULL);
-
-static ssize_t osst_device_type_read(struct device *driverfs_dev, char *page) 
-{
-	return sprintf (page, "CHR\n");
-}
-static DEVICE_ATTR(type,S_IRUGO,osst_device_type_read,NULL);
-
-
 static struct file_operations osst_fops = {
 	.owner =        THIS_MODULE,
 	.read =         osst_read,
@@ -5519,45 +5503,16 @@
 	write_unlock(&os_scsi_tapes_lock);
 
 	for (mode = 0; mode < ST_NBR_MODES; ++mode) {
-		char name[8], devfs_name[64];
+		char devfs_name[64];
 
 		/*  Rewind entry  */
-		sprintf(name, "ot%s", osst_formats[mode]);
 		sprintf(devfs_name, "%s/ot%s", SDp->devfs_name, osst_formats[mode]);
-
-		sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", 
-				SDp->sdev_driverfs_dev.bus_id, name);
-		sprintf(tpnt->driverfs_dev_r[mode].name, "%s%s", 
-				SDp->sdev_driverfs_dev.name, name);
-		tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev;
-		tpnt->driverfs_dev_r[mode].bus = SDp->sdev_driverfs_dev.bus;
-		tpnt->driverfs_dev_r[mode].driver_data =
-			(void *)(long)__mkdev(OSST_MAJOR, dev_num + (mode << 5));
-		device_register(&tpnt->driverfs_dev_r[mode]);
-		device_create_file(&tpnt->driverfs_dev_r[mode], 
-				&dev_attr_type);
-		device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev);
 		devfs_register(NULL, devfs_name, 0,
 					OSST_MAJOR, dev_num + (mode << 5),
 					S_IFCHR | S_IRUGO | S_IWUGO,
 					&osst_fops, NULL);
 		/*  No-rewind entry  */
-		sprintf (name, "ot%sn", osst_formats[mode]);
 		sprintf(devfs_name, "%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
-
-		sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", 
-				SDp->sdev_driverfs_dev.bus_id, name);
-		sprintf(tpnt->driverfs_dev_n[mode].name, "%s%s", 
-				SDp->sdev_driverfs_dev.name, name);
-		tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev;
-		tpnt->driverfs_dev_n[mode].bus = SDp->sdev_driverfs_dev.bus;
-		tpnt->driverfs_dev_n[mode].driver_data =
-			(void *)(long)__mkdev(OSST_MAJOR, dev_num + (mode << 5) + 128);
-		device_register(&tpnt->driverfs_dev_n[mode]);
-		device_create_file(&tpnt->driverfs_dev_n[mode], 
-				&dev_attr_type);
-		device_create_file(&tpnt->driverfs_dev_n[mode], 
-				&dev_attr_kdev);
 		devfs_register(NULL, devfs_name, 0,
 					OSST_MAJOR, dev_num + (mode << 5) + 128,
 					S_IFCHR | S_IRUGO | S_IWUGO,
@@ -5598,18 +5553,6 @@
 		os_scsi_tapes[i] = NULL;
 		osst_nr_dev--;
 		write_unlock(&os_scsi_tapes_lock);
-		for (mode = 0; mode < ST_NBR_MODES; ++mode) {
-			device_remove_file(&tpnt->driverfs_dev_r[mode],
-					&dev_attr_type);
-			device_remove_file(&tpnt->driverfs_dev_r[mode],
-					&dev_attr_kdev);
-			device_unregister(&tpnt->driverfs_dev_r[mode]);
-			device_remove_file(&tpnt->driverfs_dev_n[mode],
-					&dev_attr_type);
-			device_remove_file(&tpnt->driverfs_dev_n[mode],
-					&dev_attr_kdev);
-			device_unregister(&tpnt->driverfs_dev_n[mode]);
-			}
 		if (tpnt->header_cache != NULL) vfree(tpnt->header_cache);
 		if (tpnt->buffer) {
 			normalize_buffer(tpnt->buffer);
--- 1.10/drivers/scsi/osst.h	Fri May 16 12:15:25 2003
+++ edited/drivers/scsi/osst.h	Fri May 16 13:17:56 2003
@@ -555,8 +555,6 @@
   /* Mode characteristics */
   ST_mode modes[ST_NBR_MODES];
   int current_mode;
-  struct device driverfs_dev_r[ST_NBR_MODES];
-  struct device driverfs_dev_n[ST_NBR_MODES];
 
   /* Status variables */
   int partition;
--- 1.62/drivers/scsi/st.c	Fri May 16 12:15:25 2003
+++ edited/drivers/scsi/st.c	Fri May 16 13:17:37 2003
@@ -3674,22 +3674,6 @@
 
 #endif
 
-/* Driverfs file support */
-static ssize_t st_device_kdev_read(struct device *dev, char *page)
-{
-	kdev_t kdev; 
-	kdev.value=(unsigned long)dev->driver_data;
-	return sprintf(page, "%x\n",kdev.value);
-}
-static DEVICE_ATTR(kdev,S_IRUGO,st_device_kdev_read,NULL);
-
-static ssize_t st_device_type_read(struct device *ev, char * page)
-{
-	return sprintf (page, "CHR\n");
-}
-static DEVICE_ATTR(type,S_IRUGO,st_device_type_read,NULL);
-
-
 static struct file_operations st_fops =
 {
 	.owner =	THIS_MODULE,
@@ -3860,45 +3844,16 @@
 	write_unlock(&st_dev_arr_lock);
 
 	for (mode = 0; mode < ST_NBR_MODES; ++mode) {
-	    char name[8], devfs_name[64];
+	    char devfs_name[64];
 
 	    /*  Rewind entry  */
-	    sprintf(name, "mt%s", st_formats[mode]);
 	    sprintf(devfs_name, "%s/mt%s", SDp->devfs_name, st_formats[mode]);
-	    
-	    sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", 
-		    SDp->sdev_driverfs_dev.bus_id, name);
-	    sprintf(tpnt->driverfs_dev_r[mode].name, "%s%s", 
-		    SDp->sdev_driverfs_dev.name, name);
-	    tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev;
-	    tpnt->driverfs_dev_r[mode].bus = SDp->sdev_driverfs_dev.bus;
-	    tpnt->driverfs_dev_r[mode].driver_data =
-			(void *)(long)__mkdev(SCSI_TAPE_MAJOR, dev_num + (mode << 5));
-	    device_register(&tpnt->driverfs_dev_r[mode]);
-	    device_create_file(&tpnt->driverfs_dev_r[mode], 
-			       &dev_attr_type);
-	    device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev);
 	    devfs_register(NULL, devfs_name, 0,
 				SCSI_TAPE_MAJOR, dev_num + (mode << 5),
 				S_IFCHR | S_IRUGO | S_IWUGO,
 				&st_fops, NULL);
 	    /*  No-rewind entry  */
-	    sprintf (name, "mt%sn", st_formats[mode]);
 	    sprintf(devfs_name, "%s/mt%sn", SDp->devfs_name, st_formats[mode]);
-
-	    sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", 
-		    SDp->sdev_driverfs_dev.bus_id, name);
-	    sprintf(tpnt->driverfs_dev_n[mode].name, "%s%s", 
-		    SDp->sdev_driverfs_dev.name, name);
-	    tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev;
-	    tpnt->driverfs_dev_n[mode].bus = SDp->sdev_driverfs_dev.bus;
-	    tpnt->driverfs_dev_n[mode].driver_data =
-			(void *)(long)__mkdev(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128);
-	    device_register(&tpnt->driverfs_dev_n[mode]);
-	    device_create_file(&tpnt->driverfs_dev_n[mode], 
-			       &dev_attr_type);
-	    device_create_file(&tpnt->driverfs_dev_n[mode], 
-			       &dev_attr_kdev);
 	    devfs_register(NULL, devfs_name, 0,
 				SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128,
 				S_IFCHR | S_IRUGO | S_IWUGO,
@@ -3939,16 +3894,6 @@
 			for (mode = 0; mode < ST_NBR_MODES; ++mode) {
 				devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[mode]);
 				devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[mode]);
-				device_remove_file(&tpnt->driverfs_dev_r[mode],
-						   &dev_attr_type);
-				device_remove_file(&tpnt->driverfs_dev_r[mode],
-						   &dev_attr_kdev);
-				device_unregister(&tpnt->driverfs_dev_r[mode]);
-				device_remove_file(&tpnt->driverfs_dev_n[mode],
-						   &dev_attr_type);
-				device_remove_file(&tpnt->driverfs_dev_n[mode],
-						   &dev_attr_kdev);
-				device_unregister(&tpnt->driverfs_dev_n[mode]);
 			}
 			tpnt->device = NULL;
 
--- 1.14/drivers/scsi/st.h	Fri May 16 12:15:25 2003
+++ edited/drivers/scsi/st.h	Fri May 16 13:15:55 2003
@@ -103,8 +103,6 @@
 	/* Mode characteristics */
 	ST_mode modes[ST_NBR_MODES];
 	int current_mode;
-	struct device driverfs_dev_r[ST_NBR_MODES];
-	struct device driverfs_dev_n[ST_NBR_MODES];
 
 	/* Status variables */
 	int partition;

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-16 23:57 ` Mike Anderson
                     ` (2 preceding siblings ...)
  2003-05-17  9:17   ` Christoph Hellwig
@ 2003-05-17  9:59   ` Kai Makisara
  2003-05-17 15:08     ` Christoph Hellwig
  2003-05-18  9:35     ` Kai Makisara
  3 siblings, 2 replies; 16+ messages in thread
From: Kai Makisara @ 2003-05-17  9:59 UTC (permalink / raw)
  To: Mike Anderson; +Cc: Christoph Hellwig, James.Bottomley, linux-scsi

On Fri, 16 May 2003, Mike Anderson wrote:

> Christoph Hellwig [hch@lst.de] wrote:
> > Upper drivers now use the LDM ->probe/->remove callbacks and the
...
> I ran your patch and I dead locked on st_probe. This is due to the code
> in st_probe and osst_probe that do device registers on the
> sdev_driverfs_dev.bus which is the bus that the probe is being called
> from already. I had an old patch that removed these before due the driver
> model requirement that objects on the device list must be of one type.
> At the time I did not have a place to move these attributes.
>
> We now have /bus/scsi/drivers/{uld} for driver attributes. We also could
> create a class for other attributes if needed. We can also use udev for
> the creation of special nodes.
>
> ftp://ftp.kernel.org/pub/linux/utils/kernel/hotplug/
>
> In the short term is the st and osst maintainers are ok with it we could
> remove them and then create them in there proper home.
>
I don't mind removal of the mt* files. I tested in 2.5.69-bk11 a
modification to st that was essentially what Christoph has just
posted. No problems there (i.e., tape found and works ok, sysfs shows
the tape as SCSI device).

However, when I add to this Christoph's patch to change probing, I don't
find any tapes any more. What I did was to first modprobe aic7xxx.
According to dmesg, the device was found:

(scsi2:A:5): 10.000MB/s transfers (10.000MHz, offset 8)
  Vendor: HP        Model: C1533A            Rev: 9608
  Type:   Sequential-Access                  ANSI SCSI revision: 02
Attached scsi generic sg0 at scsi2, channel 0, id 5, lun 0,  type 1

It did not appear in /sysfs/bus/scsi/devices (the system disk and the
cdrom were there):

# tree /sysfs/bus/scsi/devices/
/sysfs/bus/scsi/devices/
|-- 0:0:0:0 -> ../../../devices/pci0/00:1e.0/02:02.0/host0/0:0:0:0
`-- 1:0:0:0 -> ../../../devices/ide-scsi/host1/1:0:0:0

Modprobing st did not result in any messages (each attached tape causes
one line to be printed). The tape device does not exist:

# mt status
/dev/nst0: No such device or address

-- 
Kai


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-17  3:59 ` Douglas Gilbert
  2003-05-17  7:13   ` Christoph Hellwig
  2003-05-17  8:32   ` Jens Axboe
@ 2003-05-17 12:52   ` Willem Riede
  2 siblings, 0 replies; 16+ messages in thread
From: Willem Riede @ 2003-05-17 12:52 UTC (permalink / raw)
  To: linux-scsi

On 2003.05.16 23:59, Douglas Gilbert wrote:
> Christoph,
> This patch would have some interesting side effects:
>   - no generic interface (apart from SCSI_IOCTL_SEND_COMMAND)
>     for tape devices (st and osst). While the maintainers of
>     st and osst might like this, not all the user apps would :-)

I would certainly like that sg access could not "interfere" with
osst while it is in control, but there would obviously have to be
a way to assign individual devices to specific drivers (as in tape1
is handled by st and tape2 by sg). And that would have to be dynamic
(as in I did a backup on tape1 with osst and now I want to tinker
with another tape using sg). Such mechanism doesn't exist, I think.

Thanks, Willem Riede.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  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
  1 sibling, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2003-05-17 15:08 UTC (permalink / raw)
  To: Kai Makisara
  Cc: Mike Anderson, Christoph Hellwig, James.Bottomley, linux-scsi

On Sat, May 17, 2003 at 12:59:59PM +0300, Kai Makisara wrote:
> However, when I add to this Christoph's patch to change probing, I don't
> find any tapes any more. What I did was to first modprobe aic7xxx.
> According to dmesg, the device was found:
> 
> (scsi2:A:5): 10.000MB/s transfers (10.000MHz, offset 8)
>   Vendor: HP        Model: C1533A            Rev: 9608
>   Type:   Sequential-Access                  ANSI SCSI revision: 02
> Attached scsi generic sg0 at scsi2, channel 0, id 5, lun 0,  type 1
> 
> It did not appear in /sysfs/bus/scsi/devices (the system disk and the
> cdrom were there):

That exactly what I said in my mail to Douglas before - now there always
is one driver for each device.  If you have sg loaded but not st (yet)
sg will claim your tapes, not st.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-17 15:08     ` Christoph Hellwig
@ 2003-05-17 16:19       ` James Bottomley
  0 siblings, 0 replies; 16+ messages in thread
From: James Bottomley @ 2003-05-17 16:19 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Kai Makisara, Mike Anderson, Christoph Hellwig, SCSI Mailing List

On Sat, 2003-05-17 at 10:08, Christoph Hellwig wrote:
> That exactly what I said in my mail to Douglas before - now there always
> is one driver for each device.  If you have sg loaded but not st (yet)
> sg will claim your tapes, not st.

In principle, I'm not opposed to single attachment.  However, we need
the SG_IO demonstrably working for all devices (including tape) before
we try turning it off.

So, let's look at the SG_IO for cdev patch before considering this one.

James



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-17  9:17   ` Christoph Hellwig
@ 2003-05-17 16:35     ` Mike Anderson
  0 siblings, 0 replies; 16+ messages in thread
From: Mike Anderson @ 2003-05-17 16:35 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: James.Bottomley, linux-scsi

Christoph Hellwig [hch@lst.de] wrote:
> 
> Okay, here's the patch to remove the strange kdev and type attributes
> that caused this problems.  All the useful attributes are still left,
> they're attributes of the right struct device.

Thanks, I am doing insmod / rmmod with sd, sg, sr, and st upper levels
binding and unbinding.

-andmike
--
Michael Anderson
andmike@us.ibm.com


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-17  9:59   ` Kai Makisara
  2003-05-17 15:08     ` Christoph Hellwig
@ 2003-05-18  9:35     ` Kai Makisara
  1 sibling, 0 replies; 16+ messages in thread
From: Kai Makisara @ 2003-05-18  9:35 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-scsi

On Sat, 17 May 2003, Kai Makisara wrote:

...
> I don't mind removal of the mt* files. I tested in 2.5.69-bk11 a
> modification to st that was essentially what Christoph has just
> posted. No problems there (i.e., tape found and works ok, sysfs shows
> the tape as SCSI device).
>
> However, when I add to this Christoph's patch to change probing, I don't
> find any tapes any more. What I did was to first modprobe aic7xxx.
...
> Modprobing st did not result in any messages (each attached tape causes
> one line to be printed). The tape device does not exist:
>
I have done more experiments that may be useful. I used both a SCSI disk
(sd) and a SCSI tape (st) to see if the problems are related to the high
level driver. The behaviour with sd and st was similar, i.e., this problem
is not related to st specifically.

The result from the experiments was that nothing will be recognised
properly after the sg driver is initialised. I had it in the kernel in the
first experiment. The same applies to using sg as a module. If I load
first sd and/or st, the devices will be recognised. If I load sg and then
sd and/or st, the devices will not be recognised. They are not properly
visible as sg devices either. It does not seem to matter if the HBA driver
is in kernel or a module or loaded before or after the high-level driver.

To some extent these results are expected. Your said that only one
high-level driver can be attached to one device. What is not explainable
is why they don't show as sg devices or in the sysfs /bus/scsi/devices
directory.

I think it should be possible to attach several high-level drivers to one
device. It is useful in some cases.

-- 
Kai

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-17  7:13   ` Christoph Hellwig
@ 2003-05-19 19:02     ` Greg KH
  0 siblings, 0 replies; 16+ messages in thread
From: Greg KH @ 2003-05-19 19:02 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Douglas Gilbert, James.Bottomley, linux-scsi

On Sat, May 17, 2003 at 09:13:52AM +0200, Christoph Hellwig wrote:
> On Sat, May 17, 2003 at 01:59:52PM +1000, Douglas Gilbert wrote:
> > It was my understanding that the device model has been
> > recently modified by Greg KH to cope with the dual nature
> > of the interface that sg causes. Evidently similar situations
> > occur elsewhere in the kernel.
> 
> Greg, any comments on this?  I haven't found any code like that
> in drivers/base/ and I can't understand how this is supposed to work..`

I don't really know what you all are talking about here, but...
In talking with Mike Anderson about the driver class code changes, he
and I agreed that sg could just be made a struct class_device.  It could
go under a "scsi" class if you want, and would point to the scsi devices
(in the device tree) that the sg driver is bound to.

Does that make more sense?

thanks,

greg k-h


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] switch scsi upper driver probing to the driver model
  2003-05-16 16:20 [PATCH] switch scsi upper driver probing to the driver model Christoph Hellwig
  2003-05-16 23:57 ` Mike Anderson
  2003-05-17  3:59 ` Douglas Gilbert
@ 2003-05-19 21:38 ` Patrick Mansfield
  2 siblings, 0 replies; 16+ messages in thread
From: Patrick Mansfield @ 2003-05-19 21:38 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: James.Bottomley, linux-scsi

On Fri, May 16, 2003 at 06:20:39PM +0200, Christoph Hellwig wrote:
> 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.

The sg attributes (calls to device_create_file) should be removed (at
least until sg has its own class or place to put the attributes), since
sg_probe creates a "type" attribute, then when we return back into
scsi_device_register and try to create the scsi_device "type" attribute,
we fail and call scsi_device_unregister.

And scsi_scan.c ignores the failure, probably leading to some strangeness
or at best a memory leak.

The end result is that there is no scsi_device under sysfs if sg_probe
attached to the scsi_device.

-- Patrick Mansfield

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2003-05-19 21:29 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-05-16 16:20 [PATCH] switch scsi upper driver probing to the driver model Christoph Hellwig
2003-05-16 23:57 ` 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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox