From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christoph Hellwig Subject: Re: [PATCH] driver model for scsi upper drivers, take 2 Date: Tue, 27 May 2003 11:43:10 +0200 Sender: linux-scsi-owner@vger.kernel.org Message-ID: <20030527094310.GA12853@lst.de> References: <20030527073218.GA11467@lst.de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-path: Received: from verein.lst.de ([212.34.189.10]:15279 "EHLO mail.lst.de") by vger.kernel.org with ESMTP id S263131AbTE0JaB (ORCPT ); Tue, 27 May 2003 05:30:01 -0400 Content-Disposition: inline In-Reply-To: <20030527073218.GA11467@lst.de> List-Id: linux-scsi@vger.kernel.org To: James.Bottomley@steeleye.com Cc: linux-scsi@vger.kernel.org On Tue, May 27, 2003 at 09:32:18AM +0200, Christoph Hellwig wrote: > - removed the tape sysfs pseudodevice crap that caused hangs > - switched sg to a class_interface. This means sg can be used > on devices already claimed be an upper driver again. This > also means I had to remove the sg sysfs attributes temporarily > because the old mechanism is gone, but I'll restore them > differently in a followon patch. Yikes, this was the old patch again. Here's the right one: --- 1.66/drivers/scsi/hosts.c Fri May 23 14:35:11 2003 +++ edited/drivers/scsi/hosts.c Mon May 26 11:29:03 2003 @@ -233,27 +233,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; } /** --- 1.66/drivers/scsi/hosts.h Mon May 26 23:47:09 2003 +++ edited/drivers/scsi/hosts.h Mon May 26 10:02:43 2003 @@ -542,25 +542,23 @@ 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) + +extern int scsi_register_driver(struct device_driver *); +#define scsi_unregister_driver(drv) \ + driver_unregister(drv); -/* - * 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_interface(struct class_interface *); +#define scsi_unregister_interface(intf) \ + class_interface_unregister(intf) /* * HBA allocation/freeing. --- 1.24/drivers/scsi/ide-scsi.c Thu May 15 04:55:52 2003 +++ edited/drivers/scsi/ide-scsi.c Mon May 26 10:12:22 2003 @@ -771,6 +771,10 @@ static inline int should_transform(ide_drive_t *drive, Scsi_Cmnd *cmd) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); + + /* this was a layering violation and we can't support it + anymore, sorry. */ +#if 0 struct gendisk *disk = cmd->request->rq_disk; if (disk) { @@ -778,6 +782,7 @@ if (strcmp((*p)->scsi_driverfs_driver.name, "sg") == 0) return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); } +#endif return test_bit(IDESCSI_TRANSFORM, &scsi->transform); } --- 1.44/drivers/scsi/osst.c Tue May 13 05:52:55 2003 +++ edited/drivers/scsi/osst.c Mon May 26 11:17: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, } }; @@ -5327,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, @@ -5385,8 +5365,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 +5376,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 */ @@ -5522,45 +5503,12 @@ write_unlock(&os_scsi_tapes_lock); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - char name[8]; - /* Rewind entry */ - sprintf(name, "ot%s", 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_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)), S_IFCHR | S_IRUGO | S_IWUGO, "%s/ot%s", SDp->devfs_name, osst_formats[mode]); /* No-rewind entry */ - sprintf (name, "ot%sn", 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_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128), S_IFCHR | S_IRUGO | S_IWUGO, "%s/ot%sn", SDp->devfs_name, osst_formats[mode]); @@ -5575,16 +5523,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++) { @@ -5599,29 +5548,17 @@ 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); kfree(tpnt->buffer); } kfree(tpnt); - return; + return 0; } } write_unlock(&os_scsi_tapes_lock); - return; + return 0; } static int __init init_osst(void) @@ -5630,7 +5567,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.gendrv)) { printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR); return 1; } @@ -5643,7 +5580,7 @@ int i; OS_Scsi_Tape * STp; - scsi_unregister_device(&osst_template); + scsi_unregister_driver(&osst_template.gendrv); unregister_chrdev(OSST_MAJOR, "osst"); if (os_scsi_tapes) { --- 1.9/drivers/scsi/osst.h Fri Apr 18 17:57:20 2003 +++ edited/drivers/scsi/osst.h Mon May 26 11:17:39 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 */ @@ -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.112/drivers/scsi/scsi.c Thu May 8 20:31:08 2003 +++ edited/drivers/scsi/scsi.c Mon May 26 09:50:43 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"); --- 1.82/drivers/scsi/scsi.h Mon May 26 23:53:23 2003 +++ edited/drivers/scsi/scsi.h Mon May 26 09:50:43 2003 @@ -316,6 +316,7 @@ */ struct scsi_device { + struct class_device sdev_classdev; /* * This information is private to the scsi mid-layer. */ --- 1.91/drivers/scsi/scsi_lib.c Fri May 23 12:02:30 2003 +++ edited/drivers/scsi/scsi_lib.c Mon May 26 09:50:43 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. @@ -849,11 +826,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, @@ -947,7 +920,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; @@ -1003,6 +975,7 @@ * happening now. */ if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { + struct scsi_driver *drv; int ret; /* @@ -1017,8 +990,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 @@ -1031,7 +1002,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; --- 1.8/drivers/scsi/scsi_priv.h Fri May 23 14:35:11 2003 +++ edited/drivers/scsi/scsi_priv.h Mon May 26 09:50:43 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, @@ -70,9 +67,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); @@ -119,12 +113,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 *); --- 1.86/drivers/scsi/scsi_scan.c Fri May 23 13:01:50 2003 +++ edited/drivers/scsi/scsi_scan.c Mon May 26 09:50:43 2003 @@ -1098,22 +1098,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); + } } /** --- 1.37/drivers/scsi/scsi_syms.c Mon May 12 16:26:15 2003 +++ edited/drivers/scsi/scsi_syms.c Mon May 26 10:03:34 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_register_interface); EXPORT_SYMBOL(scsi_register_host); EXPORT_SYMBOL(scsi_unregister_host); EXPORT_SYMBOL(scsi_add_host); --- 1.18/drivers/scsi/scsi_sysfs.c Mon May 26 23:47:09 2003 +++ edited/drivers/scsi/scsi_sysfs.c Mon May 26 11:36:00 2003 @@ -58,32 +58,16 @@ .name = "scsi_host", }; -/** - * scsi_bus_match: - * @dev: - * @dev_driver: - * - * Return value: - **/ -static int scsi_bus_match(struct device *dev, - struct device_driver *dev_driver) +static struct class sdev_class = { + .name = "scsi_device", +}; + +/* 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, @@ -99,45 +83,26 @@ return error; error = class_register(&shost_class); if (error) - return error; + goto bus_unregister; + error = class_register(&sdev_class); + if (error) + goto class_unregister; + return 0; + class_unregister: + class_unregister(&shost_class); + bus_unregister: + bus_unregister(&scsi_bus_type); return error; } void scsi_sysfs_unregister(void) { + class_unregister(&sdev_class); class_unregister(&shost_class); 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. @@ -238,7 +203,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; } @@ -280,15 +245,30 @@ { int error = 0, i; + device_initialize(&sdev->sdev_driverfs_dev); sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); sdev->sdev_driverfs_dev.parent = &sdev->host->host_gendev; sdev->sdev_driverfs_dev.bus = &scsi_bus_type; sdev->sdev_driverfs_dev.release = scsi_device_release; - error = device_register(&sdev->sdev_driverfs_dev); - if (error) + class_device_initialize(&sdev->sdev_classdev); + sdev->sdev_classdev.dev = &sdev->sdev_driverfs_dev; + sdev->sdev_classdev.class = &sdev_class; + snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, "%d:%d:%d:%d", + sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); + + error = device_add(&sdev->sdev_driverfs_dev); + if (error) { + printk(KERN_INFO "error 1\n"); return error; + } + error = class_device_add(&sdev->sdev_classdev); + if (error) { + printk(KERN_INFO "error 2\n"); + device_unregister(&sdev->sdev_driverfs_dev); + return error; + } for (i = 0; !error && sdev->host->hostt->sdev_attrs[i] != NULL; i++) error = device_create_file(&sdev->sdev_driverfs_dev, @@ -310,9 +290,24 @@ for (i = 0; sdev->host->hostt->sdev_attrs[i] != NULL; i++) device_remove_file(&sdev->sdev_driverfs_dev, sdev->host->hostt->sdev_attrs[i]); + class_device_unregister(&sdev->sdev_classdev); device_unregister(&sdev->sdev_driverfs_dev); } +int scsi_register_driver(struct device_driver *drv) +{ + drv->bus = &scsi_bus_type; + + return driver_register(drv); +} + +int scsi_register_interface(struct class_interface *intf) +{ + intf->class = &sdev_class; + + return class_interface_register(intf); +} + static void scsi_host_release(struct device *dev) { struct Scsi_Host *shost; @@ -350,7 +345,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) --- 1.116/drivers/scsi/sd.c Fri May 23 13:01:50 2003 +++ edited/drivers/scsi/sd.c Mon May 26 11:28:14 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); @@ -636,12 +599,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; @@ -1312,10 +1276,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. @@ -1327,17 +1291,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)); @@ -1389,8 +1355,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, " @@ -1409,44 +1375,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"); + } } /** @@ -1457,7 +1421,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")); @@ -1468,11 +1432,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.gendrv); } /** @@ -1486,35 +1446,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.gendrv); 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 --- 1.55/drivers/scsi/sg.c Tue May 13 05:52:57 2003 +++ edited/drivers/scsi/sg.c Mon May 26 11:38:00 2003 @@ -112,24 +112,17 @@ #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_add(struct class_device *); +static void sg_remove(struct class_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 class_interface sg_interface = { + .add = sg_add, + .remove = sg_remove, }; typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */ @@ -180,15 +173,13 @@ } Sg_fd; typedef struct sg_device { /* holds the state of each scsi generic device */ - struct Scsi_Device_Template *driver; - Scsi_Device *device; + 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; @@ -1328,27 +1319,10 @@ .fasync = sg_fasync, }; -/* Driverfs file support */ -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); - return sprintf(page, "%x\n", MKDEV(sdp->disk->major, - sdp->disk->first_minor)); -} -static DEVICE_ATTR(kdev,S_IRUGO,sg_device_kdev_read,NULL); - -static ssize_t -sg_device_type_read(struct device *driverfs_dev, char *page) -{ - return sprintf(page, "CHR\n"); -} - -static DEVICE_ATTR(type,S_IRUGO,sg_device_type_read,NULL); - static int -sg_attach(Scsi_Device * scsidp) +sg_add(struct class_device *cdev) { + struct scsi_device *scsidp = to_scsi_device(cdev->dev); struct gendisk *disk; Sg_device *sdp = NULL; unsigned long iflags; @@ -1416,8 +1390,6 @@ SCSI_LOG_TIMEOUT(3, printk("sg_attach: dev=%d \n", k)); memset(sdp, 0, sizeof(*sdp)); - sdp->driver = &sg_template; - disk->private_data = &sdp->driver; sprintf(disk->disk_name, "sg%d", k); disk->major = SCSI_GENERIC_MAJOR; disk->first_minor = k; @@ -1430,40 +1402,20 @@ 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); - devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "%s/generic", scsidp->devfs_name); - 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); + return 0; out: @@ -1472,8 +1424,9 @@ } static void -sg_detach(Scsi_Device * scsidp) +sg_remove(struct class_device *cdev) { + struct scsi_device *scsidp = to_scsi_device(cdev->dev); Sg_device *sdp = NULL; unsigned long iflags; Sg_fd *sfp; @@ -1524,9 +1477,6 @@ 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); put_disk(sdp->disk); sdp->disk = NULL; if (NULL == sdp->headfp) @@ -1550,64 +1500,6 @@ MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd"); -static ssize_t sg_allow_dio_show(struct device_driver * ddp, char * buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", sg_allow_dio); -} -static ssize_t sg_allow_dio_store(struct device_driver * ddp, - const char * buf, size_t count) -{ - if (1 == sscanf(buf, "%d", &sg_allow_dio)) { - sg_allow_dio = sg_allow_dio ? 1 : 0; - return count; - } - return -EINVAL; -} -DRIVER_ATTR(allow_dio, S_IRUGO | S_IWUSR, sg_allow_dio_show, - sg_allow_dio_store) - -static ssize_t sg_def_reserved_show(struct device_driver * ddp, char * buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", sg_big_buff); -} -static ssize_t sg_def_reserved_store(struct device_driver * ddp, - const char * buf, size_t count) -{ - if (1 == sscanf(buf, "%d", &def_reserved_size)) { - if (def_reserved_size >= 0) { - sg_big_buff = def_reserved_size; - return count; - } - } - return -EINVAL; -} -DRIVER_ATTR(def_reserved_size, S_IRUGO | S_IWUSR, sg_def_reserved_show, - sg_def_reserved_store) - -static ssize_t sg_version_show(struct device_driver * ddp, char * buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", sg_version_str); -} -DRIVER_ATTR(version, S_IRUGO, sg_version_show, NULL) - -static void do_create_driverfs_files(void) -{ - struct device_driver * driverfs = &sg_template.scsi_driverfs_driver; - - driver_create_file(driverfs, &driver_attr_allow_dio); - driver_create_file(driverfs, &driver_attr_def_reserved_size); - driver_create_file(driverfs, &driver_attr_version); -} - -static void do_remove_driverfs_files(void) -{ - struct device_driver * driverfs = &sg_template.scsi_driverfs_driver; - - driver_remove_file(driverfs, &driver_attr_version); - driver_remove_file(driverfs, &driver_attr_def_reserved_size); - driver_remove_file(driverfs, &driver_attr_allow_dio); -} - static int __init init_sg(void) { @@ -1619,24 +1511,22 @@ rc = register_chrdev(SCSI_GENERIC_MAJOR, "sg", &sg_fops); if (rc) return rc; - rc = scsi_register_device(&sg_template); + rc = scsi_register_interface(&sg_interface); if (rc) return rc; #ifdef CONFIG_PROC_FS sg_proc_init(); #endif /* CONFIG_PROC_FS */ - do_create_driverfs_files(); return 0; } static void __exit exit_sg(void) { - do_remove_driverfs_files(); #ifdef CONFIG_PROC_FS sg_proc_cleanup(); #endif /* CONFIG_PROC_FS */ - scsi_unregister_device(&sg_template); + scsi_unregister_interface(&sg_interface); unregister_chrdev(SCSI_GENERIC_MAJOR, "sg"); if (sg_dev_arr != NULL) { vfree((char *) sg_dev_arr); --- 1.79/drivers/scsi/sr.c Fri May 23 12:02:30 2003 +++ edited/drivers/scsi/sr.c Mon May 26 11:24:25 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); @@ -575,8 +540,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", @@ -807,15 +772,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); @@ -825,6 +785,8 @@ put_disk(cd->disk); unregister_cdrom(&cd->cdi); kfree(cd); + + return 0; } static int __init init_sr(void) @@ -834,12 +796,12 @@ rc = register_blkdev(SCSI_CDROM_MAJOR, "sr"); if (rc) return rc; - return scsi_register_device(&sr_template); + return scsi_register_driver(&sr_template.gendrv); } static void __exit exit_sr(void) { - scsi_unregister_device(&sr_template); + scsi_unregister_driver(&sr_template.gendrv); unregister_blkdev(SCSI_CDROM_MAJOR, "sr"); } --- 1.9/drivers/scsi/sr.h Sun Nov 3 14:46:32 2002 +++ edited/drivers/scsi/sr.h Mon May 26 09:50:43 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 */ --- 1.62/drivers/scsi/st.c Tue May 13 05:52:58 2003 +++ edited/drivers/scsi/st.c Mon May 26 11:18:14 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; @@ -3862,43 +3860,11 @@ write_unlock(&st_dev_arr_lock); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - char name[8]; - /* Rewind entry */ - sprintf(name, "mt%s", 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_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5)), S_IFCHR | S_IRUGO | S_IWUGO, "%s/mt%s", SDp->devfs_name, st_formats[mode]); - /* No-rewind entry */ - sprintf (name, "mt%sn", 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_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128), S_IFCHR | S_IRUGO | S_IWUGO, "%s/mt%sn", SDp->devfs_name, st_formats[mode]); @@ -3918,11 +3884,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; @@ -3937,16 +3904,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; @@ -3957,12 +3914,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) @@ -3974,7 +3931,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.gendrv) == 0) { do_create_driverfs_files(); return 0; } @@ -3987,20 +3944,10 @@ static void __exit exit_st(void) { - int i; - do_remove_driverfs_files(); - scsi_unregister_device(&st_template); + scsi_unregister_driver(&st_template.gendrv); 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"); } @@ -4035,7 +3982,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); @@ -4045,7 +3992,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 Mon May 26 11:17:05 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 */ @@ -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;