Oops on CF removal and "convert device drivers to driver-model"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dear Bartlomiej:

I would be gratious to you if you expedited the push of the attached
patch from your private tree into the mainline. It was posted back in
February. The 2.6.12-rc3 still oopses upon running "cardctl eject"
with this:

cs: memory probe 0xa0000000-0xa0ffffff: excluding 0xa0000000-0xa00fffff
Probing IDE interface ide2...
hde: SAMSUNG CF/ATA, CFA DISK drive
ide2 at 0x100-0x107,0x10e on irq 3
hde: max request size: 128KiB
hde: 2041200 sectors (1045 MB) w/0KiB Cache, CHS=2025/16/63
hde: cache flushes not supported
 hde: hde1
ide-cs: hde: Vcc = 3.3, Vpp = 0.0
 hde: hde1
 hde: hde1
 hde: hde1
 hde: hde1
 hde: hde1
Unable to handle kernel NULL pointer dereference at virtual address 00000010
 printing eip:
c02b35a2
*pde = 00000000
Oops: 0000 [#1]
Modules linked in: ide_cs udf ub usbmon tun crc32 radeon pcmcia sunrpc md5 ipv6 ipt_REJECT ipt_state ip_conntrack iptable_filter ip_tables video thermal processor fan button battery ac yenta_socket rsrc_nonstatic pcmcia_core uhci_hcd ehci_hcd snd_intel8x0 snd_ac97_codec snd_pcm snd_timer snd soundcore snd_page_alloc tg3 ide_cd cdrom usbcore joydev evdev
CPU:    0
EIP:    0060:[<c02b35a2>]    Not tainted VLI
EFLAGS: 00210292   (2.6.12-rc3-lem) 
EIP is at ide_drive_remove+0x12/0x20
eax: c0404438   ebx: c0404544   ecx: c0404530   edx: 00000000
esi: c0404520   edi: c039a018   ebp: c04043a8   esp: c74efd8c
ds: 007b   es: 007b   ss: 0068
Process cardctl (pid: 7753, threadinfo=c74ee000 task=d9dbcaa0)
Stack: c0404438 c02982e8 c0404520 c0361df5 c0404520 c04048e0 c0404438 c029857c 
       c0404520 c0404520 c0404520 c04048e0 c029738c c0404520 c04043a8 c0404520 
       c0404448 c02973e0 c0404520 00000002 c02b0843 c0404520 daf1a254 c017c0c6 
Call Trace:
 [<c02982e8>] device_release_driver+0x68/0x80
 [<c029857c>] bus_remove_device+0x6c/0xb0
 [<c029738c>] device_del+0x5c/0xa0
 [<c02973e0>] device_unregister+0x10/0x20
 [<c02b0843>] ide_unregister+0x313/0x910
 [<c017c0c6>] __find_get_block+0x96/0xb0
 [<e09cb8e7>] ide_release+0x27/0x70 [ide_cs]
 [<e09cb9ee>] ide_event+0xbe/0xf0 [ide_cs]
 [<e09b6df2>] send_event_callback+0x52/0x60 [pcmcia]
 [<c0297e97>] __bus_for_each_dev+0x67/0xa0
 [<c0297fac>] bus_for_each_dev+0x3c/0x60
 [<e09b6da0>] send_event_callback+0x0/0x60 [pcmcia]
 [<e09b6da0>] send_event_callback+0x0/0x60 [pcmcia]
 [<e09b6e60>] send_event+0x60/0x80 [pcmcia]
 [<e09b6da0>] send_event_callback+0x0/0x60 [pcmcia]
 [<e09b6f0f>] ds_event+0x8f/0x130 [pcmcia]
 [<e0932853>] send_event+0x53/0xa0 [pcmcia_core]
 [<e09328c1>] socket_remove_drivers+0x21/0x30 [pcmcia_core]
 [<e09328e0>] socket_shutdown+0x10/0x40 [pcmcia_core]
 [<e0932e40>] socket_remove+0x10/0x40 [pcmcia_core]
 [<e09350da>] pcmcia_eject_card+0x6a/0x70 [pcmcia_core]
 [<e09b870e>] ds_ioctl+0x3be/0x730 [pcmcia]
 [<c0192241>] do_ioctl+0x81/0x90
 [<c01923b0>] vfs_ioctl+0x60/0x1f0
 [<c01925c8>] sys_ioctl+0x88/0xa0
 [<c0103c3b>] sysenter_past_esp+0x54/0x75
Code: 39 c0 89 44 24 0c b8 13 0b 36 c0 89 44 24 04 e8 75 a5 e6 ff e9 42 fe ff ff 83 ec 04 8b 44 24 08 2d e8 00 00 00 8b 50 1c 89 04 24 <ff> 52 10 31 c0 5a c3 8d b4 26 00 00 00 00 55 57 56 53 83 ec 24 

I appreciate that you spend effort on testing but keeping these fixes in
your private tree makes sure that they are not available in the mainline.

Yours,
-- Pete

diff -urp -X dontdiff linux-2.6.12-rc4/drivers/ide/ide.c linux-2.6.12-rc4-ide/drivers/ide/ide.c
--- linux-2.6.12-rc4/drivers/ide/ide.c	2005-05-14 00:02:35.000000000 -0700
+++ linux-2.6.12-rc4-ide/drivers/ide/ide.c	2005-05-14 10:10:33.000000000 -0700
@@ -196,8 +196,6 @@ ide_hwif_t ide_hwifs[MAX_HWIFS];	/* mast
 
 EXPORT_SYMBOL(ide_hwifs);
 
-static struct list_head ide_drives = LIST_HEAD_INIT(ide_drives);
-
 /*
  * Do not even *think* about calling this!
  */
@@ -358,54 +356,6 @@ static int ide_system_bus_speed(void)
 	return system_bus_speed;
 }
 
-/*
- *	drives_lock protects the list of drives, drivers_lock the
- *	list of drivers.  Currently nobody takes both at once.
- */
-
-static DEFINE_SPINLOCK(drives_lock);
-static DEFINE_SPINLOCK(drivers_lock);
-static LIST_HEAD(drivers);
-
-/* Iterator for the driver list. */
-
-static void *m_start(struct seq_file *m, loff_t *pos)
-{
-	struct list_head *p;
-	loff_t l = *pos;
-	spin_lock(&drivers_lock);
-	list_for_each(p, &drivers)
-		if (!l--)
-			return list_entry(p, ide_driver_t, drivers);
-	return NULL;
-}
-
-static void *m_next(struct seq_file *m, void *v, loff_t *pos)
-{
-	struct list_head *p = ((ide_driver_t *)v)->drivers.next;
-	(*pos)++;
-	return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers);
-}
-
-static void m_stop(struct seq_file *m, void *v)
-{
-	spin_unlock(&drivers_lock);
-}
-
-static int show_driver(struct seq_file *m, void *v)
-{
-	ide_driver_t *driver = v;
-	seq_printf(m, "%s version %s\n", driver->name, driver->version);
-	return 0;
-}
-
-struct seq_operations ide_drivers_op = {
-	.start	= m_start,
-	.next	= m_next,
-	.stop	= m_stop,
-	.show	= show_driver
-};
-
 #ifdef CONFIG_PROC_FS
 struct proc_dir_entry *proc_ide_root;
 #endif
@@ -630,7 +580,7 @@ void ide_unregister(unsigned int index)
 	ide_hwif_t *hwif, *g;
 	static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
 	ide_hwgroup_t *hwgroup;
-	int irq_count = 0, unit, i;
+	int irq_count = 0, unit;
 
 	BUG_ON(index >= MAX_HWIFS);
 
@@ -643,23 +593,22 @@ void ide_unregister(unsigned int index)
 		goto abort;
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		drive = &hwif->drives[unit];
-		if (!drive->present)
+		if (!drive->present) {
+			if (drive->devfs_name[0] != '\0') {
+				devfs_remove(drive->devfs_name);
+				drive->devfs_name[0] = '\0';
+			}
 			continue;
-		if (drive->usage || DRIVER(drive)->busy)
-			goto abort;
-		drive->dead = 1;
+		}
+		spin_unlock_irq(&ide_lock);
+		device_unregister(&drive->gendev);
+		down(&drive->gendev_rel_sem);
+		spin_lock_irq(&ide_lock);
 	}
 	hwif->present = 0;
 
 	spin_unlock_irq(&ide_lock);
 
-	for (unit = 0; unit < MAX_DRIVES; ++unit) {
-		drive = &hwif->drives[unit];
-		if (!drive->present)
-			continue;
-		DRIVER(drive)->cleanup(drive);
-	}
-
 	destroy_proc_ide_interface(hwif);
 
 	hwgroup = hwif->hwgroup;
@@ -687,44 +636,6 @@ void ide_unregister(unsigned int index)
 	 * Remove us from the hwgroup, and free
 	 * the hwgroup if we were the only member
 	 */
-	for (i = 0; i < MAX_DRIVES; ++i) {
-		drive = &hwif->drives[i];
-		if (drive->devfs_name[0] != '\0') {
-			devfs_remove(drive->devfs_name);
-			drive->devfs_name[0] = '\0';
-		}
-		if (!drive->present)
-			continue;
-		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 = HWIF(hwgroup->drive);
-			}
-		}
-		BUG_ON(hwgroup->drive == 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);
-		device_unregister(&drive->gendev);
-		down(&drive->gendev_rel_sem);
-		spin_lock_irq(&ide_lock);
-		drive->queue = NULL;
-	}
 	if (hwif->next == hwif) {
 		BUG_ON(hwgroup->hwif != hwif);
 		kfree(hwgroup);
@@ -1304,73 +1215,6 @@ int system_bus_clock (void)
 
 EXPORT_SYMBOL(system_bus_clock);
 
-/*
- *	Locking is badly broken here - since way back.  That sucker is
- * root-only, but that's not an excuse...  The real question is what
- * exclusion rules do we want here.
- */
-int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
-{
-	if (!drive->present || drive->usage || drive->dead)
-		goto abort;
-	if (DRIVER(drive)->cleanup(drive))
-		goto abort;
-	strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
-	if (ata_attach(drive)) {
-		spin_lock(&drives_lock);
-		list_del_init(&drive->list);
-		spin_unlock(&drives_lock);
-		drive->driver_req[0] = 0;
-		ata_attach(drive);
-	} else {
-		drive->driver_req[0] = 0;
-	}
-	if (drive->driver && !strcmp(drive->driver->name, driver))
-		return 0;
-abort:
-	return 1;
-}
-
-/**
- *	ata_attach		-	attach an ATA/ATAPI device
- *	@drive: drive to attach
- *
- *	Takes a drive that is as yet not assigned to any midlayer IDE
- *	driver (or is assigned to the default driver) and figures out
- *	which driver would like to own it. If nobody claims the drive
- *	then it is automatically attached to the default driver used for
- *	unclaimed objects.
- *
- *	A return of zero indicates attachment to a driver, of one
- *	attachment to the default driver.
- *
- *	Takes drivers_lock.
- */
-
-int ata_attach(ide_drive_t *drive)
-{
-	struct list_head *p;
-	spin_lock(&drivers_lock);
-	list_for_each(p, &drivers) {
-		ide_driver_t *driver = list_entry(p, ide_driver_t, drivers);
-		if (!try_module_get(driver->owner))
-			continue;
-		spin_unlock(&drivers_lock);
-		if (driver->attach(drive) == 0) {
-			module_put(driver->owner);
-			drive->gendev.driver = &driver->gen_driver;
-			return 0;
-		}
-		spin_lock(&drivers_lock);
-		module_put(driver->owner);
-	}
-	drive->gendev.driver = NULL;
-	spin_unlock(&drivers_lock);
-	if (ide_register_subdriver(drive, NULL))
-		panic("ide: default attach failed");
-	return 1;
-}
-
 static int generic_ide_suspend(struct device *dev, pm_message_t state)
 {
 	ide_drive_t *drive = dev->driver_data;
@@ -2013,27 +1857,11 @@ static void __init probe_for_hwifs (void
 #endif
 }
 
-int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
+void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&ide_lock, flags);
-	if (!drive->present || drive->driver != NULL ||
-	    drive->usage || drive->dead) {
-		spin_unlock_irqrestore(&ide_lock, flags);
-		return 1;
-	}
-	drive->driver = driver;
-	spin_unlock_irqrestore(&ide_lock, flags);
-	spin_lock(&drives_lock);
-	list_add_tail(&drive->list, driver ? &driver->drives : &ide_drives);
-	spin_unlock(&drives_lock);
-//	printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name);
 #ifdef CONFIG_PROC_FS
-	if (driver)
-		ide_add_proc_entries(drive->proc, driver->proc, drive);
+	ide_add_proc_entries(drive->proc, driver->proc, drive);
 #endif
-	return 0;
 }
 
 EXPORT_SYMBOL(ide_register_subdriver);
@@ -2041,136 +1869,51 @@ EXPORT_SYMBOL(ide_register_subdriver);
 /**
  *	ide_unregister_subdriver	-	disconnect drive from driver
  *	@drive: drive to unplug
+ *	@driver: driver
  *
  *	Disconnect a drive from the driver it was attached to and then
  *	clean up the various proc files and other objects attached to it.
  *
- *	Takes ide_setting_sem, ide_lock and drives_lock.
+ *	Takes ide_setting_sem and ide_lock.
  *	Caller must hold none of the locks.
- *
- *	No locking versus subdriver unload because we are moving to the
- *	default driver anyway. Wants double checking.
  */
 
-int ide_unregister_subdriver (ide_drive_t *drive)
+void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver)
 {
 	unsigned long flags;
 	
 	down(&ide_setting_sem);
 	spin_lock_irqsave(&ide_lock, flags);
-	if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) {
-		spin_unlock_irqrestore(&ide_lock, flags);
-		up(&ide_setting_sem);
-		return 1;
-	}
 #ifdef CONFIG_PROC_FS
-	ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc);
+	ide_remove_proc_entries(drive->proc, driver->proc);
 #endif
 	auto_remove_settings(drive);
-	drive->driver = NULL;
 	spin_unlock_irqrestore(&ide_lock, flags);
 	up(&ide_setting_sem);
-	spin_lock(&drives_lock);
-	list_del_init(&drive->list);
-	spin_unlock(&drives_lock);
-	/* drive will be added to &ide_drives in ata_attach() */
-	return 0;
 }
 
 EXPORT_SYMBOL(ide_unregister_subdriver);
 
-static int ide_drive_remove(struct device * dev)
-{
-	ide_drive_t * drive = container_of(dev,ide_drive_t,gendev);
-	DRIVER(drive)->cleanup(drive);
-	return 0;
-}
-
-/**
- *	ide_register_driver	-	register IDE device driver
- *	@driver: the IDE device driver
- *
- *	Register a new device driver and then scan the devices
- *	on the IDE bus in case any should be attached to the
- *	driver we have just registered.  If so attach them.
- *
- *	Takes drivers_lock and drives_lock.
- */
-
-int ide_register_driver(ide_driver_t *driver)
-{
-	struct list_head list;
-	struct list_head *list_loop;
-	struct list_head *tmp_storage;
-
-	spin_lock(&drivers_lock);
-	list_add(&driver->drivers, &drivers);
-	spin_unlock(&drivers_lock);
-
-	INIT_LIST_HEAD(&list);
-	spin_lock(&drives_lock);
-	list_splice_init(&ide_drives, &list);
-	spin_unlock(&drives_lock);
-
-	list_for_each_safe(list_loop, tmp_storage, &list) {
-		ide_drive_t *drive = container_of(list_loop, ide_drive_t, list);
-		list_del_init(&drive->list);
-		if (drive->present)
-			ata_attach(drive);
-	}
-	driver->gen_driver.name = (char *) driver->name;
-	driver->gen_driver.bus = &ide_bus_type;
-	driver->gen_driver.remove = ide_drive_remove;
-	return driver_register(&driver->gen_driver);
-}
-
-EXPORT_SYMBOL(ide_register_driver);
-
-/**
- *	ide_unregister_driver	-	unregister IDE device driver
- *	@driver: the IDE device driver
- *
- *	Called when a driver module is being unloaded. We reattach any
- *	devices to whatever driver claims them next (typically the default
- *	driver).
- *
- *	Takes drivers_lock and called functions will take ide_setting_sem.
- */
-
-void ide_unregister_driver(ide_driver_t *driver)
-{
-	ide_drive_t *drive;
-
-	spin_lock(&drivers_lock);
-	list_del(&driver->drivers);
-	spin_unlock(&drivers_lock);
-
-	driver_unregister(&driver->gen_driver);
-
-	while(!list_empty(&driver->drives)) {
-		drive = list_entry(driver->drives.next, ide_drive_t, list);
-		if (driver->cleanup(drive)) {
-			printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
-			BUG();
-		}
-		ata_attach(drive);
-	}
-}
-
-EXPORT_SYMBOL(ide_unregister_driver);
-
 /*
  * Probe module
  */
 
 EXPORT_SYMBOL(ide_lock);
 
+static int ide_bus_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
 struct bus_type ide_bus_type = {
 	.name		= "ide",
+	.match		= ide_bus_match,
 	.suspend	= generic_ide_suspend,
 	.resume		= generic_ide_resume,
 };
 
+EXPORT_SYMBOL_GPL(ide_bus_type);
+
 /*
  * This is gets invoked once during initialization, to set *everything* up
  */
diff -urp -X dontdiff linux-2.6.12-rc4/drivers/ide/ide-cd.c linux-2.6.12-rc4-ide/drivers/ide/ide-cd.c
--- linux-2.6.12-rc4/drivers/ide/ide-cd.c	2005-05-14 00:02:35.000000000 -0700
+++ linux-2.6.12-rc4-ide/drivers/ide/ide-cd.c	2005-05-14 09:54:34.000000000 -0700
@@ -3255,16 +3255,12 @@ sector_t ide_cdrom_capacity (ide_drive_t
 	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 *
 	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,
-	.name			= "ide-cdrom",
+	.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
 
 	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->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
 	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->driver_data = NULL;
 		goto failed;
 	}
-	DRIVER(drive)->busy--;
 
 	cdrom_read_toc(drive, &sense);
 	g->fops = &idecd_ops;
@@ -3500,8 +3492,6 @@ static int ide_cdrom_attach (ide_drive_t
 	add_disk(g);
 	return 0;
 
-out_put_disk:
-	put_disk(g);
 out_free_cd:
 	kfree(info);
 failed:
@@ -3510,13 +3500,12 @@ failed:
 
 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);
diff -urp -X dontdiff linux-2.6.12-rc4/drivers/ide/ide-disk.c linux-2.6.12-rc4-ide/drivers/ide/ide-disk.c
--- linux-2.6.12-rc4/drivers/ide/ide-disk.c	2005-05-14 00:02:35.000000000 -0700
+++ linux-2.6.12-rc4-ide/drivers/ide/ide-disk.c	2005-05-14 09:48:06.000000000 -0700
@@ -1024,14 +1024,16 @@ static void ide_cacheflush_p(ide_drive_t
 		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
 	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 d
 	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 id
 
 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 *d
 
 	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 *d
 
 	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 *d
 		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,8 +1252,6 @@ static int idedisk_attach(ide_drive_t *d
 	add_disk(g);
 	return 0;
 
-out_put_disk:
-	put_disk(g);
 out_free_idkp:
 	kfree(idkp);
 failed:
@@ -1267,12 +1260,12 @@ failed:
 
 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);
diff -urp -X dontdiff linux-2.6.12-rc4/drivers/ide/ide-floppy.c linux-2.6.12-rc4-ide/drivers/ide/ide-floppy.c
--- linux-2.6.12-rc4/drivers/ide/ide-floppy.c	2005-05-14 00:02:35.000000000 -0700
+++ linux-2.6.12-rc4-ide/drivers/ide/ide-floppy.c	2005-05-14 09:48:06.000000000 -0700
@@ -1865,13 +1865,13 @@ static void idefloppy_setup (ide_drive_t
 	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,
-	.name			= "ide-floppy",
+	.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 id
 	.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
 
 	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->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,8 +2176,6 @@ static int idefloppy_attach (ide_drive_t
 	add_disk(g);
 	return 0;
 
-out_put_disk:
-	put_disk(g);
 out_free_floppy:
 	kfree(floppy);
 failed:
@@ -2193,7 +2186,7 @@ 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);
diff -urp -X dontdiff linux-2.6.12-rc4/drivers/ide/ide-probe.c linux-2.6.12-rc4-ide/drivers/ide/ide-probe.c
--- linux-2.6.12-rc4/drivers/ide/ide-probe.c	2005-05-14 00:02:35.000000000 -0700
+++ linux-2.6.12-rc4-ide/drivers/ide/ide-probe.c	2005-05-14 09:48:06.000000000 -0700
@@ -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_
 			   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,
 
 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 *hw
 		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;
diff -urp -X dontdiff linux-2.6.12-rc4/drivers/ide/ide-proc.c linux-2.6.12-rc4-ide/drivers/ide/ide-proc.c
--- linux-2.6.12-rc4/drivers/ide/ide-proc.c	2005-05-14 00:02:35.000000000 -0700
+++ linux-2.6.12-rc4-ide/drivers/ide/ide-proc.c	2005-05-14 09:48:06.000000000 -0700
@@ -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
 	}
 }
 
-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)
diff -urp -X dontdiff linux-2.6.12-rc4/drivers/ide/ide-tape.c linux-2.6.12-rc4-ide/drivers/ide/ide-tape.c
--- linux-2.6.12-rc4/drivers/ide/ide-tape.c	2005-05-14 00:02:35.000000000 -0700
+++ linux-2.6.12-rc4-ide/drivers/ide/ide-tape.c	2005-05-14 09:48:06.000000000 -0700
@@ -4681,21 +4681,12 @@ static void idetape_setup (ide_drive_t *
 	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;
-	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);
-	DRIVER(drive)->busy = 0;
-	(void) ide_unregister_subdriver(drive);
+	ide_unregister_subdriver(drive, tape->driver);
 
 	ide_unregister_region(tape->disk);
 
@@ -4710,6 +4701,8 @@ static void ide_tape_release(struct kref
 	ide_drive_t *drive = tape->drive;
 	struct gendisk *g = tape->disk;
 
+	BUG_ON(tape->first_stage != NULL || tape->merge_stage_size);
+
 	drive->dsc_overlap = 0;
 	drive->driver_data = NULL;
 	devfs_remove("%s/mt", drive->devfs_name);
@@ -4747,26 +4740,24 @@ static ide_proc_entry_t idetape_proc[] =
 
 #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 = {
 	.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,
 	.media			= ide_tape,
-	.busy			= 1,
 	.supports_dsc_overlap 	= 1,
-	.cleanup		= idetape_cleanup,
 	.do_request		= idetape_do_request,
 	.end_request		= idetape_end_request,
 	.error			= __ide_error,
 	.abort			= __ide_abort,
 	.proc			= idetape_proc,
-	.attach			= idetape_attach,
-	.drives			= LIST_HEAD_INIT(idetape_driver.drives),
 };
 
 /*
@@ -4829,8 +4820,9 @@ static struct block_device_operations id
 	.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;
 	struct gendisk *g;
 	int minor;
@@ -4865,10 +4857,7 @@ static int idetape_attach (ide_drive_t *
 
 	ide_init_disk(g, drive);
 
-	if (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;
-	}
+	ide_register_subdriver(drive, &idetape_driver);
 
 	memset(tape, 0, sizeof(*tape));
 
@@ -4902,8 +4891,7 @@ static int idetape_attach (ide_drive_t *
 	ide_register_region(g);
 
 	return 0;
-out_put_disk:
-	put_disk(g);
+
 out_free_tape:
 	kfree(tape);
 failed:
@@ -4915,7 +4903,7 @@ MODULE_LICENSE("GPL");
 
 static void __exit idetape_exit (void)
 {
-	ide_unregister_driver(&idetape_driver);
+	driver_unregister(&idetape_driver.gen_driver);
 	unregister_chrdev(IDETAPE_MAJOR, "ht");
 }
 
@@ -4928,8 +4916,7 @@ static int idetape_init (void)
 		printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
 		return -EBUSY;
 	}
-	ide_register_driver(&idetape_driver);
-	return 0;
+	return driver_register(&idetape_driver.gen_driver);
 }
 
 module_init(idetape_init);
diff -urp -X dontdiff linux-2.6.12-rc4/drivers/scsi/ide-scsi.c linux-2.6.12-rc4-ide/drivers/scsi/ide-scsi.c
--- linux-2.6.12-rc4/drivers/scsi/ide-scsi.c	2005-05-14 00:02:44.000000000 -0700
+++ linux-2.6.12-rc4-ide/drivers/scsi/ide-scsi.c	2005-05-14 09:48:06.000000000 -0700
@@ -713,7 +713,6 @@ static void idescsi_add_settings(ide_dri
  */
 static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
 {
-	DRIVER(drive)->busy++;
 	if (drive->id && (drive->id->config & 0x0060) == 0x20)
 		set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
 	set_bit(IDESCSI_TRANSFORM, &scsi->transform);
@@ -722,17 +721,16 @@ static void idescsi_setup (ide_drive_t *
 	set_bit(IDESCSI_LOG_CMD, &scsi->log);
 #endif /* IDESCSI_DEBUG_LOG */
 	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 ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);
 	struct gendisk *g = scsi->disk;
 
-	if (ide_unregister_subdriver(drive))
-		return 1;
+	ide_unregister_subdriver(drive, scsi->driver);
 
 	ide_unregister_region(g);
 
@@ -746,7 +744,7 @@ static int idescsi_cleanup (ide_drive_t 
 	return 0;
 }
 
-static int idescsi_attach(ide_drive_t *drive);
+static int ide_scsi_probe(struct device *);
 
 #ifdef CONFIG_PROC_FS
 static ide_proc_entry_t idescsi_proc[] = {
@@ -757,24 +755,22 @@ static ide_proc_entry_t idescsi_proc[] =
 # define idescsi_proc	NULL
 #endif
 
-/*
- *	IDE subdriver functions, registered with ide.c
- */
 static ide_driver_t idescsi_driver = {
 	.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,
 	.media			= ide_scsi,
-	.busy			= 0,
 	.supports_dsc_overlap	= 0,
 	.proc			= idescsi_proc,
-	.attach			= idescsi_attach,
-	.cleanup		= idescsi_cleanup,
 	.do_request		= idescsi_do_request,
 	.end_request		= idescsi_end_request,
 	.error                  = idescsi_atapi_error,
 	.abort                  = idescsi_atapi_abort,
-	.drives			= LIST_HEAD_INIT(idescsi_driver.drives),
 };
 
 static int idescsi_ide_open(struct inode *inode, struct file *filp)
@@ -821,8 +817,6 @@ static struct block_device_operations id
 	.ioctl		= idescsi_ide_ioctl,
 };
 
-static int idescsi_attach(ide_drive_t *drive);
-
 static int idescsi_slave_configure(struct scsi_device * sdp)
 {
 	/* Configure detected device */
@@ -1095,8 +1089,9 @@ static struct scsi_host_template idescsi
 	.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;
 	struct Scsi_Host *host;
 	struct gendisk *g;
@@ -1138,7 +1133,8 @@ static int idescsi_attach(ide_drive_t *d
 	idescsi->host = host;
 	idescsi->disk = g;
 	g->private_data = &idescsi->driver;
-	err = ide_register_subdriver(drive, &idescsi_driver);
+	ide_register_subdriver(drive, &idescsi_driver);
+	err = 0;
 	if (!err) {
 		idescsi_setup (drive, idescsi);
 		g->fops = &idescsi_ops;
@@ -1150,7 +1146,7 @@ static int idescsi_attach(ide_drive_t *d
 		}
 		/* fall through on error */
 		ide_unregister_region(g);
-		ide_unregister_subdriver(drive);
+		ide_unregister_subdriver(drive, &idescsi_driver);
 	}
 
 	put_disk(g);
@@ -1161,12 +1157,12 @@ out_host_put:
 
 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)
 {
-	ide_unregister_driver(&idescsi_driver);
+	driver_unregister(&idescsi_driver.gen_driver);
 }
 
 module_init(init_idescsi_module);
diff -urp -X dontdiff linux-2.6.12-rc4/include/linux/ide.h linux-2.6.12-rc4-ide/include/linux/ide.h
--- linux-2.6.12-rc4/include/linux/ide.h	2005-05-14 00:03:02.000000000 -0700
+++ linux-2.6.12-rc4-ide/include/linux/ide.h	2005-05-14 09:48:06.000000000 -0700
@@ -664,7 +664,6 @@ typedef struct ide_drive_s {
 
 	struct request		*rq;	/* current request */
 	struct ide_drive_s 	*next;	/* circular list of hwgroup drives */
-	struct ide_driver_s	*driver;/* (ide_driver_t *) */
 	void		*driver_data;	/* extra driver data */
 	struct hd_driveid	*id;	/* drive model identification info */
 	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
@@ -758,6 +757,8 @@ typedef struct ide_drive_s {
 	struct semaphore gendev_rel_sem;	/* to deal with device release() */
 } ide_drive_t;
 
+#define to_ide_device(dev)container_of(dev, ide_drive_t, gendev)
+
 #define IDE_CHIPSET_PCI_MASK	\
     ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
 #define IDE_CHIPSET_IS_PCI(c)	((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
@@ -1086,28 +1087,20 @@ enum {
  */
 typedef struct ide_driver_s {
 	struct module			*owner;
-	const char			*name;
 	const char			*version;
 	u8				media;
-	unsigned busy			: 1;
 	unsigned supports_dsc_overlap	: 1;
-	int		(*cleanup)(ide_drive_t *);
 	ide_startstop_t	(*do_request)(ide_drive_t *, struct request *, sector_t);
 	int		(*end_request)(ide_drive_t *, int, int);
 	ide_startstop_t	(*error)(ide_drive_t *, struct request *rq, u8, u8);
 	ide_startstop_t	(*abort)(ide_drive_t *, struct request *rq);
 	int		(*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
 	ide_proc_entry_t	*proc;
-	int		(*attach)(ide_drive_t *);
 	void		(*ata_prebuilder)(ide_drive_t *);
 	void		(*atapi_prebuilder)(ide_drive_t *);
 	struct device_driver	gen_driver;
-	struct list_head drives;
-	struct list_head drivers;
 } ide_driver_t;
 
-#define DRIVER(drive)		((drive)->driver)
-
 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);
 
 void ide_init_disk(struct gendisk *, ide_drive_t *);
 
-extern int ata_attach(ide_drive_t *);
-
 extern int ideprobe_init(void);
 
 extern void ide_scan_pcibus(int scan_direction) __init;
@@ -1342,11 +1333,8 @@ extern void default_hwif_iops(ide_hwif_t
 extern void default_hwif_mmiops(ide_hwif_t *);
 extern void default_hwif_transport(ide_hwif_t *);
 
-int ide_register_driver(ide_driver_t *driver);
-void ide_unregister_driver(ide_driver_t *driver);
-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);
+void ide_register_subdriver(ide_drive_t *, ide_driver_t *);
+void ide_unregister_subdriver(ide_drive_t *, ide_driver_t *);
 
 #define ON_BOARD		1
 #define NEVER_BOARD		0
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux