fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / s390 / cio / ccwgroup.c
index 21a75ee..38954f5 100644 (file)
@@ -1,12 +1,11 @@
 /*
  *  drivers/s390/cio/ccwgroup.c
  *  bus driver for ccwgroup
- *   $Revision: 1.29 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                       IBM Corporation
  *    Author(s): Arnd Bergmann (arndb@de.ibm.com)
- *               Cornelia Huck (cohuck@de.ibm.com)
+ *               Cornelia Huck (cornelia.huck@de.ibm.com)
  */
 #include <linux/module.h>
 #include <linux/errno.h>
@@ -45,18 +44,14 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
        return 0;
 }
 static int
-ccwgroup_hotplug (struct device *dev, char **envp, int num_envp, char *buffer,
+ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer,
                  int buffer_size)
 {
        /* TODO */
        return 0;
 }
 
-static struct bus_type ccwgroup_bus_type = {
-       .name    = "ccwgroup",
-       .match   = ccwgroup_bus_match,
-       .hotplug = ccwgroup_hotplug,
-};
+static struct bus_type ccwgroup_bus_type;
 
 static inline void
 __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
@@ -77,7 +72,7 @@ __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
  * longer needed or accidentially created. Saves memory :)
  */
 static ssize_t
-ccwgroup_ungroup_store(struct device *dev, const char *buf, size_t count)
+ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct ccwgroup_device *gdev;
 
@@ -157,19 +152,16 @@ ccwgroup_create(struct device *root,
        struct ccwgroup_device *gdev;
        int i;
        int rc;
-       int del_drvdata;
 
        if (argc > 256) /* disallow dumb users */
                return -EINVAL;
 
-       gdev = kmalloc(sizeof(*gdev) + argc*sizeof(gdev->cdev[0]), GFP_KERNEL);
+       gdev = kzalloc(sizeof(*gdev) + argc*sizeof(gdev->cdev[0]), GFP_KERNEL);
        if (!gdev)
                return -ENOMEM;
 
-       memset(gdev, 0, sizeof(*gdev) + argc*sizeof(gdev->cdev[0]));
        atomic_set(&gdev->onoff, 0);
 
-       del_drvdata = 0;
        for (i = 0; i < argc; i++) {
                gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]);
 
@@ -186,18 +178,14 @@ ccwgroup_create(struct device *root,
                        rc = -EINVAL;
                        goto free_dev;
                }
-       }
-       for (i = 0; i < argc; i++)
                gdev->cdev[i]->dev.driver_data = gdev;
-       del_drvdata = 1;
+       }
 
        gdev->creator_id = creator_id;
        gdev->count = argc;
-       gdev->dev = (struct device ) {
-               .bus = &ccwgroup_bus_type,
-               .parent = root,
-               .release = ccwgroup_release,
-       };
+       gdev->dev.bus = &ccwgroup_bus_type;
+       gdev->dev.parent = root;
+       gdev->dev.release = ccwgroup_release;
 
        snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s",
                        gdev->cdev[0]->dev.bus_id);
@@ -232,9 +220,9 @@ error:
 free_dev:
        for (i = 0; i < argc; i++)
                if (gdev->cdev[i]) {
-                       put_device(&gdev->cdev[i]->dev);
-                       if (del_drvdata)
+                       if (gdev->cdev[i]->dev.driver_data == gdev)
                                gdev->cdev[i]->dev.driver_data = NULL;
+                       put_device(&gdev->cdev[i]->dev);
                }
        kfree(gdev);
        return rc;
@@ -263,7 +251,7 @@ ccwgroup_set_online(struct ccwgroup_device *gdev)
        struct ccwgroup_driver *gdrv;
        int ret;
 
-       if (atomic_compare_and_swap(0, 1, &gdev->onoff))
+       if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
                return -EAGAIN;
        if (gdev->state == CCWGROUP_ONLINE) {
                ret = 0;
@@ -274,7 +262,7 @@ ccwgroup_set_online(struct ccwgroup_device *gdev)
                goto out;
        }
        gdrv = to_ccwgroupdrv (gdev->dev.driver);
-       if ((ret = gdrv->set_online(gdev)))
+       if ((ret = gdrv->set_online ? gdrv->set_online(gdev) : 0))
                goto out;
 
        gdev->state = CCWGROUP_ONLINE;
@@ -289,7 +277,7 @@ ccwgroup_set_offline(struct ccwgroup_device *gdev)
        struct ccwgroup_driver *gdrv;
        int ret;
 
-       if (atomic_compare_and_swap(0, 1, &gdev->onoff))
+       if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
                return -EAGAIN;
        if (gdev->state == CCWGROUP_OFFLINE) {
                ret = 0;
@@ -300,7 +288,7 @@ ccwgroup_set_offline(struct ccwgroup_device *gdev)
                goto out;
        }
        gdrv = to_ccwgroupdrv (gdev->dev.driver);
-       if ((ret = gdrv->set_offline(gdev)))
+       if ((ret = gdrv->set_offline ? gdrv->set_offline(gdev) : 0))
                goto out;
 
        gdev->state = CCWGROUP_OFFLINE;
@@ -310,7 +298,7 @@ ccwgroup_set_offline(struct ccwgroup_device *gdev)
 }
 
 static ssize_t
-ccwgroup_online_store (struct device *dev, const char *buf, size_t count)
+ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct ccwgroup_device *gdev;
        struct ccwgroup_driver *gdrv;
@@ -325,7 +313,7 @@ ccwgroup_online_store (struct device *dev, const char *buf, size_t count)
        if (!try_module_get(gdrv->owner))
                return -EINVAL;
 
-       value = simple_strtoul(buf, 0, 0);
+       value = simple_strtoul(buf, NULL, 0);
        ret = count;
        if (value == 1)
                ccwgroup_set_online(gdev);
@@ -338,7 +326,7 @@ ccwgroup_online_store (struct device *dev, const char *buf, size_t count)
 }
 
 static ssize_t
-ccwgroup_online_show (struct device *dev, char *buf)
+ccwgroup_online_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
        int online;
 
@@ -389,34 +377,28 @@ ccwgroup_remove (struct device *dev)
        return 0;
 }
 
+static struct bus_type ccwgroup_bus_type = {
+       .name   = "ccwgroup",
+       .match  = ccwgroup_bus_match,
+       .uevent = ccwgroup_uevent,
+       .probe  = ccwgroup_probe,
+       .remove = ccwgroup_remove,
+};
+
 int
 ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
 {
        /* register our new driver with the core */
-       cdriver->driver = (struct device_driver) {
-               .bus = &ccwgroup_bus_type,
-               .name = cdriver->name,
-               .probe = ccwgroup_probe,
-               .remove = ccwgroup_remove,
-       };
+       cdriver->driver.bus = &ccwgroup_bus_type;
+       cdriver->driver.name = cdriver->name;
 
        return driver_register(&cdriver->driver);
 }
 
-static inline struct device *
-__get_next_ccwgroup_device(struct device_driver *drv)
+static int
+__ccwgroup_match_all(struct device *dev, void *data)
 {
-       struct device *dev, *d;
-
-       down_read(&drv->bus->subsys.rwsem);
-       dev = NULL;
-       list_for_each_entry(d, &drv->devices, driver_list) {
-               dev = get_device(d);
-               if (dev)
-                       break;
-       }
-       up_read(&drv->bus->subsys.rwsem);
-       return dev;
+       return 1;
 }
 
 void
@@ -426,11 +408,12 @@ ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver)
 
        /* We don't want ccwgroup devices to live longer than their driver. */
        get_driver(&cdriver->driver);
-       while ((dev = __get_next_ccwgroup_device(&cdriver->driver))) {
+       while ((dev = driver_find_device(&cdriver->driver, NULL, NULL,
+                                        __ccwgroup_match_all))) {
                __ccwgroup_remove_symlinks(to_ccwgroupdev(dev));
                device_unregister(dev);
                put_device(dev);
-       };
+       }
        put_driver(&cdriver->driver);
        driver_unregister(&cdriver->driver);
 }
@@ -449,7 +432,7 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
        if (cdev->dev.driver_data) {
                gdev = (struct ccwgroup_device *)cdev->dev.driver_data;
                if (get_device(&gdev->dev)) {
-                       if (!list_empty(&gdev->dev.node))
+                       if (device_is_registered(&gdev->dev))
                                return gdev;
                        put_device(&gdev->dev);
                }