ide: add warm-plug support for IDE devices (take 2)

* Add 'struct class ide_port_class' ('ide_port' class) and a 'struct
  device *portdev' ('ide_port' class device) in ide_hwif_t.

* Register 'ide_port' class in ide_init() and unregister it in
  cleanup_module().

* Create ->portdev in ide_register_port () and unregister it in
  ide_unregister().

* Add "delete_devices" class device attribute for unregistering IDE devices
  on a port and "scan" one for probing+registering IDE devices on a port.

* Add ide_sysfs_register_port() helper for registering "delete_devices"
  and "scan" attributes with ->portdev.  Call it in ide_device_add_all().

* Document IDE warm-plug support in Documentation/ide/warm-plug-howto.txt.

v2:
* Convert patch from using 'struct class_device' to use 'struct device'.
  (thanks to Kay Sievers for doing it)

Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index cb18ba8..d791b1f 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -78,6 +78,8 @@
 /* default maximum number of failures */
 #define IDE_DEFAULT_MAX_FAILURES 	1
 
+struct class *ide_port_class;
+
 static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
 					IDE2_MAJOR, IDE3_MAJOR,
 					IDE4_MAJOR, IDE5_MAJOR,
@@ -591,6 +593,7 @@
 
 	ide_remove_port_from_hwgroup(hwif);
 
+	device_unregister(hwif->portdev);
 	device_unregister(&hwif->gendev);
 	wait_for_completion(&hwif->gendev_rel_comp);
 
@@ -1590,6 +1593,13 @@
 
 EXPORT_SYMBOL_GPL(ide_bus_type);
 
+static void ide_port_class_release(struct device *portdev)
+{
+	ide_hwif_t *hwif = dev_get_drvdata(portdev);
+
+	put_device(&hwif->gendev);
+}
+
 /*
  * This is gets invoked once during initialization, to set *everything* up
  */
@@ -1610,11 +1620,23 @@
 		return ret;
 	}
 
+	ide_port_class = class_create(THIS_MODULE, "ide_port");
+	if (IS_ERR(ide_port_class)) {
+		ret = PTR_ERR(ide_port_class);
+		goto out_port_class;
+	}
+	ide_port_class->dev_release = ide_port_class_release;
+
 	init_ide_data();
 
 	proc_ide_create();
 
 	return 0;
+
+out_port_class:
+	bus_unregister(&ide_bus_type);
+
+	return ret;
 }
 
 #ifdef MODULE
@@ -1651,6 +1673,8 @@
 
 	proc_ide_destroy();
 
+	class_destroy(ide_port_class);
+
 	bus_unregister(&ide_bus_type);
 }