Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8604affd authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz
Browse files

[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
Loading
Loading
Loading
Loading
+18 −29
Original line number Diff line number Diff line
@@ -3255,16 +3255,12 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive)
	return capacity * sectors_per_frame;
}

static
int ide_cdrom_cleanup(ide_drive_t *drive)
static int ide_cd_remove(struct device *dev)
{
	ide_drive_t *drive = to_ide_device(dev);
	struct cdrom_info *info = drive->driver_data;

	if (ide_unregister_subdriver(drive)) {
		printk(KERN_ERR "%s: %s: failed to ide_unregister_subdriver\n",
			__FUNCTION__, drive->name);
		return 1;
	}
	ide_unregister_subdriver(drive, info->driver);

	del_gendisk(info->disk);

@@ -3297,7 +3293,7 @@ static void ide_cd_release(struct kref *kref)
	kfree(info);
}

static int ide_cdrom_attach (ide_drive_t *drive);
static int ide_cd_probe(struct device *);

#ifdef CONFIG_PROC_FS
static int proc_idecd_read_capacity
@@ -3320,19 +3316,20 @@ static ide_proc_entry_t idecd_proc[] = {

static ide_driver_t ide_cdrom_driver = {
	.owner			= THIS_MODULE,
	.gen_driver = {
		.name		= "ide-cdrom",
		.bus		= &ide_bus_type,
		.probe		= ide_cd_probe,
		.remove		= ide_cd_remove,
	},
	.version		= IDECD_VERSION,
	.media			= ide_cdrom,
	.busy			= 0,
	.supports_dsc_overlap	= 1,
	.cleanup		= ide_cdrom_cleanup,
	.do_request		= ide_do_rw_cdrom,
	.end_request		= ide_end_request,
	.error			= __ide_error,
	.abort			= __ide_abort,
	.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)
@@ -3418,8 +3415,9 @@ static char *ignore = NULL;
module_param(ignore, charp, 0400);
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 gendisk *g;
	struct request_sense sense;
@@ -3453,11 +3451,8 @@ static int ide_cdrom_attach (ide_drive_t *drive)

	ide_init_disk(g, drive);

	if (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;
	}
	ide_register_subdriver(drive, &ide_cdrom_driver);

	memset(info, 0, sizeof (struct cdrom_info));

	kref_init(&info->kref);
@@ -3470,7 +3465,6 @@ static int ide_cdrom_attach (ide_drive_t *drive)

	drive->driver_data = info;

	DRIVER(drive)->busy++;
	g->minors = 1;
	snprintf(g->devfs_name, sizeof(g->devfs_name),
			"%s/cd", drive->devfs_name);
@@ -3478,8 +3472,7 @@ static int ide_cdrom_attach (ide_drive_t *drive)
	g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
	if (ide_cdrom_setup(drive)) {
		struct cdrom_device_info *devinfo = &info->devinfo;
		DRIVER(drive)->busy--;
		ide_unregister_subdriver(drive);
		ide_unregister_subdriver(drive, &ide_cdrom_driver);
		if (info->buffer != NULL)
			kfree(info->buffer);
		if (info->toc != NULL)
@@ -3492,7 +3485,6 @@ static int ide_cdrom_attach (ide_drive_t *drive)
		drive->driver_data = NULL;
		goto failed;
	}
	DRIVER(drive)->busy--;

	cdrom_read_toc(drive, &sense);
	g->fops = &idecd_ops;
@@ -3500,23 +3492,20 @@ static int ide_cdrom_attach (ide_drive_t *drive)
	add_disk(g);
	return 0;

out_put_disk:
	put_disk(g);
out_free_cd:
	kfree(info);
failed:
	return 1;
	return -ENODEV;
}

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)
{
	ide_register_driver(&ide_cdrom_driver);
	return 0;
	return driver_register(&ide_cdrom_driver.gen_driver);
}

module_init(ide_cdrom_init);
+17 −24
Original line number Diff line number Diff line
@@ -1024,14 +1024,16 @@ static void ide_cacheflush_p(ide_drive_t *drive)
		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 gendisk *g = idkp->disk;

	ide_cacheflush_p(drive);
	if (ide_unregister_subdriver(drive))
		return 1;

	ide_unregister_subdriver(drive, idkp->driver);

	del_gendisk(g);

	ide_disk_put(idkp);
@@ -1052,7 +1054,7 @@ static void ide_disk_release(struct kref *kref)
	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)
{
@@ -1082,27 +1084,23 @@ static void ide_device_shutdown(struct device *dev)
	dev->bus->suspend(dev, PMSG_SUSPEND);
}

/*
 *      IDE subdriver functions, registered with ide.c
 */
static ide_driver_t idedisk_driver = {
	.owner			= THIS_MODULE,
	.gen_driver = {
		.name		= "ide-disk",
		.bus		= &ide_bus_type,
		.probe		= ide_disk_probe,
		.remove		= ide_disk_remove,
		.shutdown	= ide_device_shutdown,
	},
	.name			= "ide-disk",
	.version		= IDEDISK_VERSION,
	.media			= ide_disk,
	.busy			= 0,
	.supports_dsc_overlap	= 0,
	.cleanup		= idedisk_cleanup,
	.do_request		= ide_do_rw_disk,
	.end_request		= ide_end_request,
	.error			= __ide_error,
	.abort			= __ide_abort,
	.proc			= idedisk_proc,
	.attach			= idedisk_attach,
	.drives			= LIST_HEAD_INIT(idedisk_driver.drives),
};

static int idedisk_open(struct inode *inode, struct file *filp)
@@ -1199,8 +1197,9 @@ static struct block_device_operations idedisk_ops = {

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 gendisk *g;

@@ -1222,10 +1221,7 @@ static int idedisk_attach(ide_drive_t *drive)

	ide_init_disk(g, drive);

	if (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;
	}
	ide_register_subdriver(drive, &idedisk_driver);

	memset(idkp, 0, sizeof(*idkp));

@@ -1239,7 +1235,6 @@ static int idedisk_attach(ide_drive_t *drive)

	drive->driver_data = idkp;

	DRIVER(drive)->busy++;
	idedisk_setup(drive);
	if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
		printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
@@ -1247,7 +1242,7 @@ static int idedisk_attach(ide_drive_t *drive)
		drive->attach = 0;
	} else
		drive->attach = 1;
	DRIVER(drive)->busy--;

	g->minors = 1 << PARTN_BITS;
	strcpy(g->devfs_name, drive->devfs_name);
	g->driverfs_dev = &drive->gendev;
@@ -1257,22 +1252,20 @@ static int idedisk_attach(ide_drive_t *drive)
	add_disk(g);
	return 0;

out_put_disk:
	put_disk(g);
out_free_idkp:
	kfree(idkp);
failed:
	return 1;
	return -ENODEV;
}

static void __exit idedisk_exit (void)
{
	ide_unregister_driver(&idedisk_driver);
	driver_unregister(&idedisk_driver.gen_driver);
}

static int idedisk_init (void)
{
	return ide_register_driver(&idedisk_driver);
	return driver_register(&idedisk_driver.gen_driver);
}

module_init(idedisk_init);
+17 −25
Original line number Diff line number Diff line
@@ -1865,13 +1865,13 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
	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;
	struct gendisk *g = floppy->disk;

	if (ide_unregister_subdriver(drive))
		return 1;
	ide_unregister_subdriver(drive, floppy->driver);

	del_gendisk(g);

@@ -1916,26 +1916,24 @@ static ide_proc_entry_t idefloppy_proc[] = {

#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 = {
	.owner			= THIS_MODULE,
	.gen_driver = {
		.name		= "ide-floppy",
		.bus		= &ide_bus_type,
		.probe		= ide_floppy_probe,
		.remove		= ide_floppy_remove,
	},
	.version		= IDEFLOPPY_VERSION,
	.media			= ide_floppy,
	.busy			= 0,
	.supports_dsc_overlap	= 0,
	.cleanup		= idefloppy_cleanup,
	.do_request		= idefloppy_do_request,
	.end_request		= idefloppy_do_end_request,
	.error			= __ide_error,
	.abort			= __ide_abort,
	.proc			= idefloppy_proc,
	.attach			= idefloppy_attach,
	.drives			= LIST_HEAD_INIT(idefloppy_driver.drives),
};

static int idefloppy_open(struct inode *inode, struct file *filp)
@@ -2122,8 +2120,9 @@ static struct block_device_operations idefloppy_ops = {
	.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;
	struct gendisk *g;

@@ -2152,10 +2151,7 @@ static int idefloppy_attach (ide_drive_t *drive)

	ide_init_disk(g, drive);

	if (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;
	}
	ide_register_subdriver(drive, &idefloppy_driver);

	memset(floppy, 0, sizeof(*floppy));

@@ -2169,9 +2165,8 @@ static int idefloppy_attach (ide_drive_t *drive)

	drive->driver_data = floppy;

	DRIVER(drive)->busy++;
	idefloppy_setup (drive, floppy);
	DRIVER(drive)->busy--;

	g->minors = 1 << PARTN_BITS;
	g->driverfs_dev = &drive->gendev;
	strcpy(g->devfs_name, drive->devfs_name);
@@ -2181,19 +2176,17 @@ static int idefloppy_attach (ide_drive_t *drive)
	add_disk(g);
	return 0;

out_put_disk:
	put_disk(g);
out_free_floppy:
	kfree(floppy);
failed:
	return 1;
	return -ENODEV;
}

MODULE_DESCRIPTION("ATAPI FLOPPY Driver");

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)
static int idefloppy_init (void)
{
	printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
	ide_register_driver(&idefloppy_driver);
	return 0;
	return driver_register(&idefloppy_driver.gen_driver);
}

module_init(idefloppy_init);
+44 −3
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h>
#include <linux/kmod.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)
			   want them on default or a new "empty" class
			   for hotplug reprobing ? */
			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)

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)
{
	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);
}

@@ -1306,7 +1348,6 @@ static void init_gendisk (ide_hwif_t *hwif)
		drive->gendev.driver_data = drive;
		drive->gendev.release = drive_release_dev;
		if (drive->present) {
			device_register(&drive->gendev);
			sprintf(drive->devfs_name, "ide/host%d/bus%d/target%d/lun%d",
				(hwif->channel && hwif->mate) ?
				hwif->mate->index : hwif->index,
@@ -1412,7 +1453,7 @@ int ideprobe_init (void)
				hwif->chipset = ide_generic;
			for (unit = 0; unit < MAX_DRIVES; ++unit)
				if (hwif->drives[unit].present)
					ata_attach(&hwif->drives[unit]);
					device_register(&hwif->drives[unit].gendev);
		}
	}
	return 0;
+46 −6
Original line number Diff line number Diff line
@@ -307,17 +307,41 @@ static int proc_ide_read_driver
	(char *page, char **start, off_t off, int count, int *eof, void *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;

	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",
				driver->name, driver->version);
				dev->driver->name, ide_drv->version);
	} else
		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);
}

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
	(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)
	}
}

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)
{
	return seq_open(file, &ide_drivers_op);
	return single_open(file, &ide_drivers_show, NULL);
}

static struct file_operations ide_drivers_operations = {
	.open		= ide_drivers_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= seq_release,
	.release	= single_release,
};

void proc_ide_create(void)
Loading