fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / block / viodasd.c
index f63e07b..68592c3 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/iseries/hv_lp_event.h>
 #include <asm/iseries/hv_lp_config.h>
 #include <asm/iseries/vio.h>
+#include <asm/firmware.h>
 
 MODULE_DESCRIPTION("iSeries Virtual DASD");
 MODULE_AUTHOR("Dave Boutcher");
@@ -59,7 +60,6 @@ MODULE_LICENSE("GPL");
  * numbers 0-255 we get a maximum of 32 disks.
  */
 #define VIOD_GENHD_NAME                "iseries/vd"
-#define VIOD_GENHD_DEVFS_NAME  "iseries/disc"
 
 #define VIOD_VERS              "1.64"
 
@@ -523,8 +523,6 @@ retry:
        else
                snprintf(g->disk_name, sizeof(g->disk_name),
                                VIOD_GENHD_NAME "%c", 'a' + (dev_no % 26));
-       snprintf(g->devfs_name, sizeof(g->devfs_name),
-                       "%s%d", VIOD_GENHD_DEVFS_NAME, dev_no);
        g->fops = &viodasd_fops;
        g->queue = q;
        g->private_data = d;
@@ -747,7 +745,7 @@ static int viodasd_remove(struct vio_dev *vdev)
  * support.
  */
 static struct vio_device_id viodasd_device_table[] __devinitdata = {
-       { "viodasd", "" },
+       { "block", "IBM,iSeries-viodasd" },
        { "", "" }
 };
 MODULE_DEVICE_TABLE(vio, viodasd_device_table);
@@ -762,6 +760,8 @@ static struct vio_driver viodasd_driver = {
        }
 };
 
+static int need_delete_probe;
+
 /*
  * Initialize the whole device driver.  Handle module and non-module
  * versions
@@ -770,52 +770,78 @@ static int __init viodasd_init(void)
 {
        int rc;
 
+       if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
+               rc = -ENODEV;
+               goto early_fail;
+       }
+
        /* Try to open to our host lp */
        if (viopath_hostLp == HvLpIndexInvalid)
                vio_set_hostlp();
 
        if (viopath_hostLp == HvLpIndexInvalid) {
                printk(VIOD_KERN_WARNING "invalid hosting partition\n");
-               return -EIO;
+               rc = -EIO;
+               goto early_fail;
        }
 
        printk(VIOD_KERN_INFO "vers " VIOD_VERS ", hosting partition %d\n",
                        viopath_hostLp);
 
         /* register the block device */
-       if (register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME)) {
+       rc =  register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
+       if (rc) {
                printk(VIOD_KERN_WARNING
                                "Unable to get major number %d for %s\n",
                                VIODASD_MAJOR, VIOD_GENHD_NAME);
-               return -EIO;
+               goto early_fail;
        }
        /* Actually open the path to the hosting partition */
-       if (viopath_open(viopath_hostLp, viomajorsubtype_blockio,
-                               VIOMAXREQ + 2)) {
+       rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio,
+                               VIOMAXREQ + 2);
+       if (rc) {
                printk(VIOD_KERN_WARNING
                       "error opening path to host partition %d\n",
                       viopath_hostLp);
-               unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
-               return -EIO;
+               goto unregister_blk;
        }
 
        /* Initialize our request handler */
        vio_setHandler(viomajorsubtype_blockio, handle_block_event);
 
        rc = vio_register_driver(&viodasd_driver);
-       if (rc == 0)
-               driver_create_file(&viodasd_driver.driver, &driver_attr_probe);
+       if (rc) {
+               printk(VIOD_KERN_WARNING "vio_register_driver failed\n");
+               goto unset_handler;
+       }
+
+       /*
+        * If this call fails, it just means that we cannot dynamically
+        * add virtual disks, but the driver will still work fine for
+        * all existing disk, so ignore the failure.
+        */
+       if (!driver_create_file(&viodasd_driver.driver, &driver_attr_probe))
+               need_delete_probe = 1;
+
+       return 0;
+
+unset_handler:
+       vio_clearHandler(viomajorsubtype_blockio);
+       viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2);
+unregister_blk:
+       unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
+early_fail:
        return rc;
 }
 module_init(viodasd_init);
 
-void viodasd_exit(void)
+void __exit viodasd_exit(void)
 {
-       driver_remove_file(&viodasd_driver.driver, &driver_attr_probe);
+       if (need_delete_probe)
+               driver_remove_file(&viodasd_driver.driver, &driver_attr_probe);
        vio_unregister_driver(&viodasd_driver);
        vio_clearHandler(viomajorsubtype_blockio);
-       unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
        viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2);
+       unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
 }
-
 module_exit(viodasd_exit);