[PATCH] convert IDE device drivers to driver-model

* add ide_bus_match() and export ide_bus_type
* split ide_remove_driver_from_hwgroup() out of ide_unregister()
* move device cleanup from ide_unregister() to drive_release_dev()
* convert ide_driver_t->name to driver->name
* convert ide_driver_t->{attach,cleanup} to driver->{probe,remove}
* remove ide_driver_t->busy as ide_bus_type->subsys.rwsem
  protects against concurrent ->{probe,remove} calls
* make ide_{un}register_driver() void as it cannot fail now
* use driver_{un}register() directly, remove ide_{un}register_driver()
* use device_register() instead of ata_attach(), remove ata_attach()
* add proc_print_driver() and ide_drivers_show(), remove ide_drivers_op
* fix ide_replace_subdriver() and move it to ide-proc.c
* remove ide_driver_t->drives, ide_drives and drives_lock
* remove ide_driver_t->drivers, drivers and drivers_lock
* remove ide_drive_t->driver and DRIVER() macro
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@elka.pw.edu.pl>
parent bef9c558
...@@ -3255,16 +3255,12 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive) ...@@ -3255,16 +3255,12 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive)
return capacity * sectors_per_frame; return capacity * sectors_per_frame;
} }
static static int ide_cd_remove(struct device *dev)
int ide_cdrom_cleanup(ide_drive_t *drive)
{ {
ide_drive_t *drive = to_ide_device(dev);
struct cdrom_info *info = drive->driver_data; struct cdrom_info *info = drive->driver_data;
if (ide_unregister_subdriver(drive)) { ide_unregister_subdriver(drive, info->driver);
printk(KERN_ERR "%s: %s: failed to ide_unregister_subdriver\n",
__FUNCTION__, drive->name);
return 1;
}
del_gendisk(info->disk); del_gendisk(info->disk);
...@@ -3297,7 +3293,7 @@ static void ide_cd_release(struct kref *kref) ...@@ -3297,7 +3293,7 @@ static void ide_cd_release(struct kref *kref)
kfree(info); kfree(info);
} }
static int ide_cdrom_attach (ide_drive_t *drive); static int ide_cd_probe(struct device *);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int proc_idecd_read_capacity static int proc_idecd_read_capacity
...@@ -3320,19 +3316,20 @@ static ide_proc_entry_t idecd_proc[] = { ...@@ -3320,19 +3316,20 @@ static ide_proc_entry_t idecd_proc[] = {
static ide_driver_t ide_cdrom_driver = { static ide_driver_t ide_cdrom_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "ide-cdrom", .gen_driver = {
.name = "ide-cdrom",
.bus = &ide_bus_type,
.probe = ide_cd_probe,
.remove = ide_cd_remove,
},
.version = IDECD_VERSION, .version = IDECD_VERSION,
.media = ide_cdrom, .media = ide_cdrom,
.busy = 0,
.supports_dsc_overlap = 1, .supports_dsc_overlap = 1,
.cleanup = ide_cdrom_cleanup,
.do_request = ide_do_rw_cdrom, .do_request = ide_do_rw_cdrom,
.end_request = ide_end_request, .end_request = ide_end_request,
.error = __ide_error, .error = __ide_error,
.abort = __ide_abort, .abort = __ide_abort,
.proc = idecd_proc, .proc = idecd_proc,
.attach = ide_cdrom_attach,
.drives = LIST_HEAD_INIT(ide_cdrom_driver.drives),
}; };
static int idecd_open(struct inode * inode, struct file * file) static int idecd_open(struct inode * inode, struct file * file)
...@@ -3418,8 +3415,9 @@ static char *ignore = NULL; ...@@ -3418,8 +3415,9 @@ static char *ignore = NULL;
module_param(ignore, charp, 0400); module_param(ignore, charp, 0400);
MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
static int ide_cdrom_attach (ide_drive_t *drive) static int ide_cd_probe(struct device *dev)
{ {
ide_drive_t *drive = to_ide_device(dev);
struct cdrom_info *info; struct cdrom_info *info;
struct gendisk *g; struct gendisk *g;
struct request_sense sense; struct request_sense sense;
...@@ -3453,11 +3451,8 @@ static int ide_cdrom_attach (ide_drive_t *drive) ...@@ -3453,11 +3451,8 @@ static int ide_cdrom_attach (ide_drive_t *drive)
ide_init_disk(g, drive); ide_init_disk(g, drive);
if (ide_register_subdriver(drive, &ide_cdrom_driver)) { ide_register_subdriver(drive, &ide_cdrom_driver);
printk(KERN_ERR "%s: Failed to register the driver with ide.c\n",
drive->name);
goto out_put_disk;
}
memset(info, 0, sizeof (struct cdrom_info)); memset(info, 0, sizeof (struct cdrom_info));
kref_init(&info->kref); kref_init(&info->kref);
...@@ -3470,7 +3465,6 @@ static int ide_cdrom_attach (ide_drive_t *drive) ...@@ -3470,7 +3465,6 @@ static int ide_cdrom_attach (ide_drive_t *drive)
drive->driver_data = info; drive->driver_data = info;
DRIVER(drive)->busy++;
g->minors = 1; g->minors = 1;
snprintf(g->devfs_name, sizeof(g->devfs_name), snprintf(g->devfs_name, sizeof(g->devfs_name),
"%s/cd", drive->devfs_name); "%s/cd", drive->devfs_name);
...@@ -3478,8 +3472,7 @@ static int ide_cdrom_attach (ide_drive_t *drive) ...@@ -3478,8 +3472,7 @@ static int ide_cdrom_attach (ide_drive_t *drive)
g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
if (ide_cdrom_setup(drive)) { if (ide_cdrom_setup(drive)) {
struct cdrom_device_info *devinfo = &info->devinfo; struct cdrom_device_info *devinfo = &info->devinfo;
DRIVER(drive)->busy--; ide_unregister_subdriver(drive, &ide_cdrom_driver);
ide_unregister_subdriver(drive);
if (info->buffer != NULL) if (info->buffer != NULL)
kfree(info->buffer); kfree(info->buffer);
if (info->toc != NULL) if (info->toc != NULL)
...@@ -3492,7 +3485,6 @@ static int ide_cdrom_attach (ide_drive_t *drive) ...@@ -3492,7 +3485,6 @@ static int ide_cdrom_attach (ide_drive_t *drive)
drive->driver_data = NULL; drive->driver_data = NULL;
goto failed; goto failed;
} }
DRIVER(drive)->busy--;
cdrom_read_toc(drive, &sense); cdrom_read_toc(drive, &sense);
g->fops = &idecd_ops; g->fops = &idecd_ops;
...@@ -3500,23 +3492,20 @@ static int ide_cdrom_attach (ide_drive_t *drive) ...@@ -3500,23 +3492,20 @@ static int ide_cdrom_attach (ide_drive_t *drive)
add_disk(g); add_disk(g);
return 0; return 0;
out_put_disk:
put_disk(g);
out_free_cd: out_free_cd:
kfree(info); kfree(info);
failed: failed:
return 1; return -ENODEV;
} }
static void __exit ide_cdrom_exit(void) static void __exit ide_cdrom_exit(void)
{ {
ide_unregister_driver(&ide_cdrom_driver); driver_unregister(&ide_cdrom_driver.gen_driver);
} }
static int ide_cdrom_init(void) static int ide_cdrom_init(void)
{ {
ide_register_driver(&ide_cdrom_driver); return driver_register(&ide_cdrom_driver.gen_driver);
return 0;
} }
module_init(ide_cdrom_init); module_init(ide_cdrom_init);
......
...@@ -1024,14 +1024,16 @@ static void ide_cacheflush_p(ide_drive_t *drive) ...@@ -1024,14 +1024,16 @@ static void ide_cacheflush_p(ide_drive_t *drive)
printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
} }
static int idedisk_cleanup (ide_drive_t *drive) static int ide_disk_remove(struct device *dev)
{ {
ide_drive_t *drive = to_ide_device(dev);
struct ide_disk_obj *idkp = drive->driver_data; struct ide_disk_obj *idkp = drive->driver_data;
struct gendisk *g = idkp->disk; struct gendisk *g = idkp->disk;
ide_cacheflush_p(drive); ide_cacheflush_p(drive);
if (ide_unregister_subdriver(drive))
return 1; ide_unregister_subdriver(drive, idkp->driver);
del_gendisk(g); del_gendisk(g);
ide_disk_put(idkp); ide_disk_put(idkp);
...@@ -1052,7 +1054,7 @@ static void ide_disk_release(struct kref *kref) ...@@ -1052,7 +1054,7 @@ static void ide_disk_release(struct kref *kref)
kfree(idkp); kfree(idkp);
} }
static int idedisk_attach(ide_drive_t *drive); static int ide_disk_probe(struct device *dev);
static void ide_device_shutdown(struct device *dev) static void ide_device_shutdown(struct device *dev)
{ {
...@@ -1082,27 +1084,23 @@ static void ide_device_shutdown(struct device *dev) ...@@ -1082,27 +1084,23 @@ static void ide_device_shutdown(struct device *dev)
dev->bus->suspend(dev, PMSG_SUSPEND); dev->bus->suspend(dev, PMSG_SUSPEND);
} }
/*
* IDE subdriver functions, registered with ide.c
*/
static ide_driver_t idedisk_driver = { static ide_driver_t idedisk_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.gen_driver = { .gen_driver = {
.name = "ide-disk",
.bus = &ide_bus_type,
.probe = ide_disk_probe,
.remove = ide_disk_remove,
.shutdown = ide_device_shutdown, .shutdown = ide_device_shutdown,
}, },
.name = "ide-disk",
.version = IDEDISK_VERSION, .version = IDEDISK_VERSION,
.media = ide_disk, .media = ide_disk,
.busy = 0,
.supports_dsc_overlap = 0, .supports_dsc_overlap = 0,
.cleanup = idedisk_cleanup,
.do_request = ide_do_rw_disk, .do_request = ide_do_rw_disk,
.end_request = ide_end_request, .end_request = ide_end_request,
.error = __ide_error, .error = __ide_error,
.abort = __ide_abort, .abort = __ide_abort,
.proc = idedisk_proc, .proc = idedisk_proc,
.attach = idedisk_attach,
.drives = LIST_HEAD_INIT(idedisk_driver.drives),
}; };
static int idedisk_open(struct inode *inode, struct file *filp) static int idedisk_open(struct inode *inode, struct file *filp)
...@@ -1199,8 +1197,9 @@ static struct block_device_operations idedisk_ops = { ...@@ -1199,8 +1197,9 @@ static struct block_device_operations idedisk_ops = {
MODULE_DESCRIPTION("ATA DISK Driver"); MODULE_DESCRIPTION("ATA DISK Driver");
static int idedisk_attach(ide_drive_t *drive) static int ide_disk_probe(struct device *dev)
{ {
ide_drive_t *drive = to_ide_device(dev);
struct ide_disk_obj *idkp; struct ide_disk_obj *idkp;
struct gendisk *g; struct gendisk *g;
...@@ -1222,10 +1221,7 @@ static int idedisk_attach(ide_drive_t *drive) ...@@ -1222,10 +1221,7 @@ static int idedisk_attach(ide_drive_t *drive)
ide_init_disk(g, drive); ide_init_disk(g, drive);
if (ide_register_subdriver(drive, &idedisk_driver)) { ide_register_subdriver(drive, &idedisk_driver);
printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
goto out_put_disk;
}
memset(idkp, 0, sizeof(*idkp)); memset(idkp, 0, sizeof(*idkp));
...@@ -1239,7 +1235,6 @@ static int idedisk_attach(ide_drive_t *drive) ...@@ -1239,7 +1235,6 @@ static int idedisk_attach(ide_drive_t *drive)
drive->driver_data = idkp; drive->driver_data = idkp;
DRIVER(drive)->busy++;
idedisk_setup(drive); idedisk_setup(drive);
if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
...@@ -1247,7 +1242,7 @@ static int idedisk_attach(ide_drive_t *drive) ...@@ -1247,7 +1242,7 @@ static int idedisk_attach(ide_drive_t *drive)
drive->attach = 0; drive->attach = 0;
} else } else
drive->attach = 1; drive->attach = 1;
DRIVER(drive)->busy--;
g->minors = 1 << PARTN_BITS; g->minors = 1 << PARTN_BITS;
strcpy(g->devfs_name, drive->devfs_name); strcpy(g->devfs_name, drive->devfs_name);
g->driverfs_dev = &drive->gendev; g->driverfs_dev = &drive->gendev;
...@@ -1257,22 +1252,20 @@ static int idedisk_attach(ide_drive_t *drive) ...@@ -1257,22 +1252,20 @@ static int idedisk_attach(ide_drive_t *drive)
add_disk(g); add_disk(g);
return 0; return 0;
out_put_disk:
put_disk(g);
out_free_idkp: out_free_idkp:
kfree(idkp); kfree(idkp);
failed: failed:
return 1; return -ENODEV;
} }
static void __exit idedisk_exit (void) static void __exit idedisk_exit (void)
{ {
ide_unregister_driver(&idedisk_driver); driver_unregister(&idedisk_driver.gen_driver);
} }
static int idedisk_init (void) static int idedisk_init (void)
{ {
return ide_register_driver(&idedisk_driver); return driver_register(&idedisk_driver.gen_driver);
} }
module_init(idedisk_init); module_init(idedisk_init);
......
...@@ -1865,13 +1865,13 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) ...@@ -1865,13 +1865,13 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
idefloppy_add_settings(drive); idefloppy_add_settings(drive);
} }
static int idefloppy_cleanup (ide_drive_t *drive) static int ide_floppy_remove(struct device *dev)
{ {
ide_drive_t *drive = to_ide_device(dev);
idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_floppy_t *floppy = drive->driver_data;
struct gendisk *g = floppy->disk; struct gendisk *g = floppy->disk;
if (ide_unregister_subdriver(drive)) ide_unregister_subdriver(drive, floppy->driver);
return 1;
del_gendisk(g); del_gendisk(g);
...@@ -1916,26 +1916,24 @@ static ide_proc_entry_t idefloppy_proc[] = { ...@@ -1916,26 +1916,24 @@ static ide_proc_entry_t idefloppy_proc[] = {
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
static int idefloppy_attach(ide_drive_t *drive); static int ide_floppy_probe(struct device *);
/*
* IDE subdriver functions, registered with ide.c
*/
static ide_driver_t idefloppy_driver = { static ide_driver_t idefloppy_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "ide-floppy", .gen_driver = {
.name = "ide-floppy",
.bus = &ide_bus_type,
.probe = ide_floppy_probe,
.remove = ide_floppy_remove,
},
.version = IDEFLOPPY_VERSION, .version = IDEFLOPPY_VERSION,
.media = ide_floppy, .media = ide_floppy,
.busy = 0,
.supports_dsc_overlap = 0, .supports_dsc_overlap = 0,
.cleanup = idefloppy_cleanup,
.do_request = idefloppy_do_request, .do_request = idefloppy_do_request,
.end_request = idefloppy_do_end_request, .end_request = idefloppy_do_end_request,
.error = __ide_error, .error = __ide_error,
.abort = __ide_abort, .abort = __ide_abort,
.proc = idefloppy_proc, .proc = idefloppy_proc,
.attach = idefloppy_attach,
.drives = LIST_HEAD_INIT(idefloppy_driver.drives),
}; };
static int idefloppy_open(struct inode *inode, struct file *filp) static int idefloppy_open(struct inode *inode, struct file *filp)
...@@ -2122,8 +2120,9 @@ static struct block_device_operations idefloppy_ops = { ...@@ -2122,8 +2120,9 @@ static struct block_device_operations idefloppy_ops = {
.revalidate_disk= idefloppy_revalidate_disk .revalidate_disk= idefloppy_revalidate_disk
}; };
static int idefloppy_attach (ide_drive_t *drive) static int ide_floppy_probe(struct device *dev)
{ {
ide_drive_t *drive = to_ide_device(dev);
idefloppy_floppy_t *floppy; idefloppy_floppy_t *floppy;
struct gendisk *g; struct gendisk *g;
...@@ -2152,10 +2151,7 @@ static int idefloppy_attach (ide_drive_t *drive) ...@@ -2152,10 +2151,7 @@ static int idefloppy_attach (ide_drive_t *drive)
ide_init_disk(g, drive); ide_init_disk(g, drive);
if (ide_register_subdriver(drive, &idefloppy_driver)) { ide_register_subdriver(drive, &idefloppy_driver);
printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);
goto out_put_disk;
}
memset(floppy, 0, sizeof(*floppy)); memset(floppy, 0, sizeof(*floppy));
...@@ -2169,9 +2165,8 @@ static int idefloppy_attach (ide_drive_t *drive) ...@@ -2169,9 +2165,8 @@ static int idefloppy_attach (ide_drive_t *drive)
drive->driver_data = floppy; drive->driver_data = floppy;
DRIVER(drive)->busy++;
idefloppy_setup (drive, floppy); idefloppy_setup (drive, floppy);
DRIVER(drive)->busy--;
g->minors = 1 << PARTN_BITS; g->minors = 1 << PARTN_BITS;
g->driverfs_dev = &drive->gendev; g->driverfs_dev = &drive->gendev;
strcpy(g->devfs_name, drive->devfs_name); strcpy(g->devfs_name, drive->devfs_name);
...@@ -2181,19 +2176,17 @@ static int idefloppy_attach (ide_drive_t *drive) ...@@ -2181,19 +2176,17 @@ static int idefloppy_attach (ide_drive_t *drive)
add_disk(g); add_disk(g);
return 0; return 0;
out_put_disk:
put_disk(g);
out_free_floppy: out_free_floppy:
kfree(floppy); kfree(floppy);
failed: failed:
return 1; return -ENODEV;
} }
MODULE_DESCRIPTION("ATAPI FLOPPY Driver"); MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
static void __exit idefloppy_exit (void) static void __exit idefloppy_exit (void)
{ {
ide_unregister_driver(&idefloppy_driver); driver_unregister(&idefloppy_driver.gen_driver);
} }
/* /*
...@@ -2202,8 +2195,7 @@ static void __exit idefloppy_exit (void) ...@@ -2202,8 +2195,7 @@ static void __exit idefloppy_exit (void)
static int idefloppy_init (void) static int idefloppy_init (void)
{ {
printk("ide-floppy driver " IDEFLOPPY_VERSION "\n"); printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
ide_register_driver(&idefloppy_driver); return driver_register(&idefloppy_driver.gen_driver);
return 0;
} }
module_init(idefloppy_init); module_init(idefloppy_init);
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -918,7 +919,7 @@ int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif) ...@@ -918,7 +919,7 @@ int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)
want them on default or a new "empty" class want them on default or a new "empty" class
for hotplug reprobing ? */ for hotplug reprobing ? */
if (drive->present) { if (drive->present) {
ata_attach(drive); device_register(&drive->gendev);
} }
} }
} }
...@@ -1279,10 +1280,51 @@ void ide_init_disk(struct gendisk *disk, ide_drive_t *drive) ...@@ -1279,10 +1280,51 @@ void ide_init_disk(struct gendisk *disk, ide_drive_t *drive)
EXPORT_SYMBOL_GPL(ide_init_disk); EXPORT_SYMBOL_GPL(ide_init_disk);
static void ide_remove_drive_from_hwgroup(ide_drive_t *drive)
{
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
if (drive == drive->next) {
/* special case: last drive from hwgroup. */
BUG_ON(hwgroup->drive != drive);
hwgroup->drive = NULL;
} else {
ide_drive_t *walk;
walk = hwgroup->drive;
while (walk->next != drive)
walk = walk->next;
walk->next = drive->next;
if (hwgroup->drive == drive) {
hwgroup->drive = drive->next;
hwgroup->hwif = hwgroup->drive->hwif;
}
}
BUG_ON(hwgroup->drive == drive);
}
static void drive_release_dev (struct device *dev) static void drive_release_dev (struct device *dev)
{ {
ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
spin_lock_irq(&ide_lock);
if (drive->devfs_name[0] != '\0') {
devfs_remove(drive->devfs_name);
drive->devfs_name[0] = '\0';
}
ide_remove_drive_from_hwgroup(drive);
if (drive->id != NULL) {
kfree(drive->id);
drive->id = NULL;
}
drive->present = 0;
/* Messed up locking ... */
spin_unlock_irq(&ide_lock);
blk_cleanup_queue(drive->queue);
spin_lock_irq(&ide_lock);
drive->queue = NULL;
spin_unlock_irq(&ide_lock);
up(&drive->gendev_rel_sem); up(&drive->gendev_rel_sem);
} }
...@@ -1306,7 +1348,6 @@ static void init_gendisk (ide_hwif_t *hwif) ...@@ -1306,7 +1348,6 @@ static void init_gendisk (ide_hwif_t *hwif)
drive->gendev.driver_data = drive; drive->gendev.driver_data = drive;
drive->gendev.release = drive_release_dev; drive->gendev.release = drive_release_dev;
if (drive->present) { if (drive->present) {
device_register(&drive->gendev);
sprintf(drive->devfs_name, "ide/host%d/bus%d/target%d/lun%d", sprintf(drive->devfs_name, "ide/host%d/bus%d/target%d/lun%d",
(hwif->channel && hwif->mate) ? (hwif->channel && hwif->mate) ?
hwif->mate->index : hwif->index, hwif->mate->index : hwif->index,
...@@ -1412,7 +1453,7 @@ int ideprobe_init (void) ...@@ -1412,7 +1453,7 @@ int ideprobe_init (void)
hwif->chipset = ide_generic; hwif->chipset = ide_generic;
for (unit = 0; unit < MAX_DRIVES; ++unit) for (unit = 0; unit < MAX_DRIVES; ++unit)
if (hwif->drives[unit].present) if (hwif->drives[unit].present)
ata_attach(&hwif->drives[unit]); device_register(&hwif->drives[unit].gendev);
} }
} }
return 0; return 0;
......
...@@ -307,17 +307,41 @@ static int proc_ide_read_driver ...@@ -307,17 +307,41 @@ static int proc_ide_read_driver
(char *page, char **start, off_t off, int count, int *eof, void *data) (char *page, char **start, off_t off, int count, int *eof, void *data)
{ {
ide_drive_t *drive = (ide_drive_t *) data; ide_drive_t *drive = (ide_drive_t *) data;
ide_driver_t *driver = drive->driver; struct device *dev = &drive->gendev;
ide_driver_t *ide_drv;
int len; int len;
if (driver) { down_read(&dev->bus->subsys.rwsem);
if (dev->driver) {
ide_drv = container_of(dev->driver, ide_driver_t, gen_driver);
len = sprintf(page, "%s version %s\n", len = sprintf(page, "%s version %s\n",
driver->name, driver->version); dev->driver->name, ide_drv->version);
} else } else
len = sprintf(page, "ide-default version 0.9.newide\n"); len = sprintf(page, "ide-default version 0.9.newide\n");
up_read(&dev->bus->subsys.rwsem);
PROC_IDE_READ_RETURN(page,start,off,count,eof,len); PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
} }
static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
{
struct device *dev = &drive->gendev;
int ret = 1;
down_write(&dev->bus->subsys.rwsem);
device_release_driver(dev);
/* FIXME: device can still be in use by previous driver */
strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
device_attach(dev);
drive->driver_req[0] = 0;
if (dev->driver == NULL)
device_attach(dev);
if (dev->driver && !strcmp(dev->driver->name, driver))
ret = 0;
up_write(&dev->bus->subsys.rwsem);
return ret;
}
static int proc_ide_write_driver static int proc_ide_write_driver
(struct file *file, const char __user *buffer, unsigned long count, void *data) (struct file *file, const char __user *buffer, unsigned long count, void *data)
{ {
...@@ -488,16 +512,32 @@ void destroy_proc_ide_interface(ide_hwif_t *hwif) ...@@ -488,16 +512,32 @@ void destroy_proc_ide_interface(ide_hwif_t *hwif)
} }
} }
extern struct seq_operations ide_drivers_op; static int proc_print_driver(struct device_driver *drv, void *data)
{
ide_driver_t *ide_drv = container_of(drv, ide_driver_t, gen_driver);
struct seq_file *s = data;
seq_printf(s, "%s version %s\n", drv->name, ide_drv->version);
return 0;
}
static int ide_drivers_show(struct seq_file *s, void *p)
{
bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver);
return 0;
}
static int ide_drivers_open(struct inode *inode, struct file *file) static int ide_drivers_open(struct inode *inode, struct file *file)
{ {
return seq_open(file, &ide_drivers_op); return single_open(file, &ide_drivers_show, NULL);
} }
static struct file_operations ide_drivers_operations = { static struct file_operations ide_drivers_operations = {
.open = ide_drivers_open, .open = ide_drivers_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = seq_release, .release = single_release,
}; };
void proc_ide_create(void) void proc_ide_create(void)
......
...@@ -4681,21 +4681,12 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) ...@@ -4681,21 +4681,12 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
idetape_add_settings(drive); idetape_add_settings(drive);
} }
static int idetape_cleanup (ide_drive_t *drive) static int ide_tape_remove(struct device *dev)
{ {
ide_drive_t *drive = to_ide_device(dev);
idetape_tape_t *tape = drive->driver_data; idetape_tape_t *tape = drive->driver_data;
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
if (test_bit(IDETAPE_BUSY, &tape->flags) || drive->usage ||
tape->first_stage != NULL || tape->merge_stage_size) {
spin_unlock_irqrestore(&ide_lock, flags);
return 1;
}
spin_unlock_irqrestore(&ide_lock, flags); ide_unregister_subdriver(drive, tape->driver);
DRIVER(drive)->busy = 0;
(void) ide_unregister_subdriver(drive);
ide_unregister_region(tape->disk); ide_unregister_region(tape->disk);
...@@ -4710,6 +4701,8 @@ static void ide_tape_release(struct kref *kref) ...@@ -4710,6 +4701,8 @@ static void ide_tape_release(struct kref *kref)
ide_drive_t *drive = tape->drive; ide_drive_t *drive = tape->drive;
struct gendisk *g = tape->disk; struct gendisk *g = tape->disk;
BUG_ON(tape->first_stage != NULL || tape->merge_stage_size);
drive->dsc_overlap = 0; drive->dsc_overlap = 0;
drive->driver_data = NULL; drive->driver_data = NULL;
devfs_remove("%s/mt", drive->devfs_name); devfs_remove("%s/mt", drive->devfs_name);
...@@ -4747,26 +4740,24 @@ static ide_proc_entry_t idetape_proc[] = { ...@@ -4747,26 +4740,24 @@ static ide_proc_entry_t idetape_proc[] = {
#endif #endif
static int idetape_attach(ide_drive_t *drive); static int ide_tape_probe(struct device *);
/*
* IDE subdriver functions, registered with ide.c
*/
static ide_driver_t idetape_driver = { static ide_driver_t idetape_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "ide-tape", .gen_driver = {
.name = "ide-tape",
.bus = &ide_bus_type,
.probe = ide_tape_probe,
.remove = ide_tape_remove,
},
.version = IDETAPE_VERSION, .version = IDETAPE_VERSION,
.media = ide_tape, .media = ide_tape,
.busy = 1,
.supports_dsc_overlap = 1, .supports_dsc_overlap = 1,
.cleanup = idetape_cleanup,
.do_request = idetape_do_request, .do_request = idetape_do_request,
.end_request = idetape_end_request, .end_request = idetape_end_request,
.error = __ide_error, .error = __ide_error,
.abort = __ide_abort, .abort = __ide_abort,
.proc = idetape_proc, .proc = idetape_proc,
.attach = idetape_attach,
.drives = LIST_HEAD_INIT(idetape_driver.drives),
}; };
/* /*
...@@ -4829,8 +4820,9 @@ static struct block_device_operations idetape_block_ops = { ...@@ -4829,8 +4820,9 @@ static struct block_device_operations idetape_block_ops = {
.ioctl = idetape_ioctl, .ioctl = idetape_ioctl,
}; };
static int idetape_attach (ide_drive_t *drive) static int ide_tape_probe(struct device *dev)
{ {
ide_drive_t *drive = to_ide_device(dev);
idetape_tape_t *tape; idetape_tape_t *tape;
struct gendisk *g; struct gendisk *g;
int minor; int minor;
...@@ -4865,10 +4857,7 @@ static int idetape_attach (ide_drive_t *drive) ...@@ -4865,10 +4857,7 @@ static int idetape_attach (ide_drive_t *drive)
ide_init_disk(g, drive); ide_init_disk(g, drive);
if (ide_register_subdriver(drive, &idetape_driver)) { ide_register_subdriver(drive, &idetape_driver);
printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name);
goto out_put_disk;
}
memset(tape, 0, sizeof(*tape)); memset(tape, 0, sizeof(*tape));
...@@ -4902,12 +4891,11 @@ static int idetape_attach (ide_drive_t *drive) ...@@ -4902,12 +4891,11 @@ static int idetape_attach (ide_drive_t *drive)
ide_register_region(g); ide_register_region(g);
return 0; return 0;
out_put_disk:
put_disk(g);
out_free_tape: out_free_tape:
kfree(tape); kfree(tape);
failed: failed:
return 1; return -ENODEV;
} }
MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver"); MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
...@@ -4915,7 +4903,7 @@ MODULE_LICENSE("GPL"); ...@@ -4915,7 +4903,7 @@ MODULE_LICENSE("GPL");
static void __exit idetape_exit (void) static void __exit idetape_exit (void)
{ {
ide_unregister_driver(&idetape_driver); driver_unregister(&idetape_driver.gen_driver);
unregister_chrdev(IDETAPE_MAJOR, "ht"); unregister_chrdev(IDETAPE_MAJOR, "ht");
} }
...@@ -4928,8 +4916,7 @@ static int idetape_init (void) ...@@ -4928,8 +4916,7 @@ static int idetape_init (void)
printk(KERN_ERR "ide-tape: Failed to register character device interface\n"); printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
return -EBUSY; return -EBUSY;
} }
ide_register_driver(&idetape_driver); return driver_register(&idetape_driver.gen_driver);
return 0;
} }
module_init(idetape_init); module_init(idetape_init);
......
This diff is collapsed.
...@@ -713,7 +713,6 @@ static void idescsi_add_settings(ide_drive_t *drive) ...@@ -713,7 +713,6 @@ static void idescsi_add_settings(ide_drive_t *drive)
*/ */
static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
{ {
DRIVER(drive)->busy++;
if (drive->id && (drive->id->config & 0x0060) == 0x20) if (drive->id && (drive->id->config & 0x0060) == 0x20)
set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
set_bit(IDESCSI_TRANSFORM, &scsi->transform); set_bit(IDESCSI_TRANSFORM, &scsi->transform);
...@@ -722,17 +721,16 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) ...@@ -722,17 +721,16 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
set_bit(IDESCSI_LOG_CMD, &scsi->log); set_bit(IDESCSI_LOG_CMD, &scsi->log);
#endif /* IDESCSI_DEBUG_LOG */ #endif /* IDESCSI_DEBUG_LOG */
idescsi_add_settings(drive); idescsi_add_settings(drive);
DRIVER(drive)->busy--;
} }
static int idescsi_cleanup (ide_drive_t *drive) static int ide_scsi_remove(struct device *dev)
{ {
ide_drive_t *drive = to_ide_device(dev);
struct Scsi_Host *scsihost = drive->driver_data; struct Scsi_Host *scsihost = drive->driver_data;
struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);
struct gendisk *g = scsi->disk; struct gendisk *g = scsi->disk;
if (ide_unregister_subdriver(drive)) ide_unregister_subdriver(drive, scsi->driver);
return 1;
ide_unregister_region(g); ide_unregister_region(g);
...@@ -746,7 +744,7 @@ static int idescsi_cleanup (ide_drive_t *drive) ...@@ -746,7 +744,7 @@ static int idescsi_cleanup (ide_drive_t *drive)
return 0; return 0;
} }
static int idescsi_attach(ide_drive_t *drive); static int ide_scsi_probe(struct device *);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static ide_proc_entry_t idescsi_proc[] = { static ide_proc_entry_t idescsi_proc[] = {
...@@ -757,24 +755,22 @@ static ide_proc_entry_t idescsi_proc[] = { ...@@ -757,24 +755,22 @@ static ide_proc_entry_t idescsi_proc[] = {
# define idescsi_proc NULL # define idescsi_proc NULL
#endif #endif
/*
* IDE subdriver functions, registered with ide.c
*/
static ide_driver_t idescsi_driver = { static ide_driver_t idescsi_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "ide-scsi", .gen_driver = {
.name = "ide-scsi",
.bus = &ide_bus_type,
.probe = ide_scsi_probe,
.remove = ide_scsi_remove,
},
.version = IDESCSI_VERSION, .version = IDESCSI_VERSION,
.media = ide_scsi, .media = ide_scsi,
.busy = 0,
.supports_dsc_overlap = 0, .supports_dsc_overlap = 0,
.proc = idescsi_proc, .proc = idescsi_proc,
.attach = idescsi_attach,
.cleanup = idescsi_cleanup,
.do_request = idescsi_do_request, .do_request = idescsi_do_request,
.end_request = idescsi_end_request, .end_request = idescsi_end_request,
.error = idescsi_atapi_error, .error = idescsi_atapi_error,
.abort = idescsi_atapi_abort, .abort = idescsi_atapi_abort,
.drives = LIST_HEAD_INIT(idescsi_driver.drives),
}; };
static int idescsi_ide_open(struct inode *inode, struct file *filp) static int idescsi_ide_open(struct inode *inode, struct file *filp)
...@@ -821,8 +817,6 @@ static struct block_device_operations idescsi_ops = { ...@@ -821,8 +817,6 @@ static struct block_device_operations idescsi_ops = {
.ioctl = idescsi_ide_ioctl, .ioctl = idescsi_ide_ioctl,
}; };
static int idescsi_attach(ide_drive_t *drive);
static int idescsi_slave_configure(struct scsi_device * sdp) static int idescsi_slave_configure(struct scsi_device * sdp)
{ {
/* Configure detected device */ /* Configure detected device */
...@@ -1095,8 +1089,9 @@ static struct scsi_host_template idescsi_template = { ...@@ -1095,8 +1089,9 @@ static struct scsi_host_template idescsi_template = {
.proc_name = "ide-scsi", .proc_name = "ide-scsi",
}; };
static int idescsi_attach(ide_drive_t *drive) static int ide_scsi_probe(struct device *dev)
{ {
ide_drive_t *drive = to_ide_device(dev);
idescsi_scsi_t *idescsi; idescsi_scsi_t *idescsi;
struct Scsi_Host *host; struct Scsi_Host *host;
struct gendisk *g; struct gendisk *g;
...@@ -1112,7 +1107,7 @@ static int idescsi_attach(ide_drive_t *drive) ...@@ -1112,7 +1107,7 @@ static int idescsi_attach(ide_drive_t *drive)
!drive->present || !drive->present ||
drive->media == ide_disk || drive->media == ide_disk ||
!(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t))))
return 1; return -ENODEV;
g = alloc_disk(1 << PARTN_BITS); g = alloc_disk(1 << PARTN_BITS);
if (!g) if (!g)
...@@ -1138,20 +1133,19 @@ static int idescsi_attach(ide_drive_t *drive) ...@@ -1138,20 +1133,19 @@ static int idescsi_attach(ide_drive_t *drive)
idescsi->host = host; idescsi->host = host;
idescsi->disk = g; idescsi->disk = g;
g->private_data = &idescsi->driver; g->private_data = &idescsi->driver;
err = ide_register_subdriver(drive, &idescsi_driver); ide_register_subdriver(drive, &idescsi_driver);
err = 0;
idescsi_setup(drive, idescsi);
g->fops = &idescsi_ops;
ide_register_region(g);
err = scsi_add_host(host, &drive->gendev);
if (!err) { if (!err) {
idescsi_setup (drive, idescsi); scsi_scan_host(host);
g->fops = &idescsi_ops; return 0;
ide_register_region(g);
err = scsi_add_host(host, &drive->gendev);
if (!err) {
scsi_scan_host(host);
return 0;
}
/* fall through on error */
ide_unregister_region(g);
ide_unregister_subdriver(drive);
} }
/* fall through on error */
ide_unregister_region(g);
ide_unregister_subdriver(drive, &idescsi_driver);
put_disk(g); put_disk(g);
out_host_put: out_host_put:
...@@ -1161,12 +1155,12 @@ out_host_put: ...@@ -1161,12 +1155,12 @@ out_host_put:
static int __init init_idescsi_module(void) static int __init init_idescsi_module(void)
{ {
return ide_register_driver(&idescsi_driver); return driver_register(&idescsi_driver.gen_driver);
} }
static void __exit exit_idescsi_module(void) static void __exit exit_idescsi_module(void)
{ {
ide_unregister_driver(&idescsi_driver); driver_unregister(&idescsi_driver.gen_driver);
} }
module_init(init_idescsi_module); module_init(init_idescsi_module);
......
...@@ -664,7 +664,6 @@ typedef struct ide_drive_s { ...@@ -664,7 +664,6 @@ typedef struct ide_drive_s {
struct request *rq; /* current request */ struct request *rq; /* current request */
struct ide_drive_s *next; /* circular list of hwgroup drives */ struct ide_drive_s *next; /* circular list of hwgroup drives */
struct ide_driver_s *driver;/* (ide_driver_t *) */
void *driver_data; /* extra driver data */ void *driver_data; /* extra driver data */
struct hd_driveid *id; /* drive model identification info */ struct hd_driveid *id; /* drive model identification info */
struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ struct proc_dir_entry *proc; /* /proc/ide/ directory entry */
...@@ -758,6 +757,8 @@ typedef struct ide_drive_s { ...@@ -758,6 +757,8 @@ typedef struct ide_drive_s {
struct semaphore gendev_rel_sem; /* to deal with device release() */ struct semaphore gendev_rel_sem; /* to deal with device release() */
} ide_drive_t; } ide_drive_t;
#define to_ide_device(dev)container_of(dev, ide_drive_t, gendev)
#define IDE_CHIPSET_PCI_MASK \ #define IDE_CHIPSET_PCI_MASK \
((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx)) ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
#define IDE_CHIPSET_IS_PCI(c) ((IDE_CHIPSET_PCI_MASK >> (c)) & 1) #define IDE_CHIPSET_IS_PCI(c) ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
...@@ -1086,28 +1087,20 @@ enum { ...@@ -1086,28 +1087,20 @@ enum {
*/ */
typedef struct ide_driver_s { typedef struct ide_driver_s {
struct module *owner; struct module *owner;
const char *name;
const char *version; const char *version;
u8 media; u8 media;
unsigned busy : 1;
unsigned supports_dsc_overlap : 1; unsigned supports_dsc_overlap : 1;
int (*cleanup)(ide_drive_t *);
ide_startstop_t (*do_request)(ide_drive_t *, struct request *, sector_t); ide_startstop_t (*do_request)(ide_drive_t *, struct request *, sector_t);
int (*end_request)(ide_drive_t *, int, int); int (*end_request)(ide_drive_t *, int, int);
ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8); ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8);
ide_startstop_t (*abort)(ide_drive_t *, struct request *rq); ide_startstop_t (*abort)(ide_drive_t *, struct request *rq);
int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long); int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
ide_proc_entry_t *proc; ide_proc_entry_t *proc;
int (*attach)(ide_drive_t *);
void (*ata_prebuilder)(ide_drive_t *); void (*ata_prebuilder)(ide_drive_t *);
void (*atapi_prebuilder)(ide_drive_t *); void (*atapi_prebuilder)(ide_drive_t *);
struct device_driver gen_driver; struct device_driver gen_driver;
struct list_head drives;
struct list_head drivers;
} ide_driver_t; } ide_driver_t;
#define DRIVER(drive) ((drive)->driver)
int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long);
/* /*
...@@ -1328,8 +1321,6 @@ extern void ide_init_subdrivers(void); ...@@ -1328,8 +1321,6 @@ extern void ide_init_subdrivers(void);
void ide_init_disk(struct gendisk *, ide_drive_t *); void ide_init_disk(struct gendisk *, ide_drive_t *);
extern int ata_attach(ide_drive_t *);
extern int ideprobe_init(void); extern int ideprobe_init(void);
extern void ide_scan_pcibus(int scan_direction) __init; extern void ide_scan_pcibus(int scan_direction) __init;
...@@ -1342,11 +1333,8 @@ extern void default_hwif_iops(ide_hwif_t *); ...@@ -1342,11 +1333,8 @@ extern void default_hwif_iops(ide_hwif_t *);
extern void default_hwif_mmiops(ide_hwif_t *); extern void default_hwif_mmiops(ide_hwif_t *);
extern void default_hwif_transport(ide_hwif_t *); extern void default_hwif_transport(ide_hwif_t *);
int ide_register_driver(ide_driver_t *driver); void ide_register_subdriver(ide_drive_t *, ide_driver_t *);
void ide_unregister_driver(ide_driver_t *driver); void ide_unregister_subdriver(ide_drive_t *, ide_driver_t *);
int ide_register_subdriver(ide_drive_t *, ide_driver_t *);
int ide_unregister_subdriver (ide_drive_t *drive);
int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
#define ON_BOARD 1 #define ON_BOARD 1
#define NEVER_BOARD 0 #define NEVER_BOARD 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment