Pull ec into release branch
[pandora-kernel.git] / drivers / s390 / cio / ccwgroup.c
index 3cba6c9..5aeb68e 100644 (file)
@@ -53,7 +53,7 @@ ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer,
 
 static struct bus_type ccwgroup_bus_type;
 
-static inline void
+static void
 __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
 {
        int i;
@@ -71,19 +71,31 @@ __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
  * Provide an 'ungroup' attribute so the user can remove group devices no
  * longer needed or accidentially created. Saves memory :)
  */
+static void ccwgroup_ungroup_callback(struct device *dev)
+{
+       struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+
+       __ccwgroup_remove_symlinks(gdev);
+       device_unregister(dev);
+}
+
 static ssize_t
 ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct ccwgroup_device *gdev;
+       int rc;
 
        gdev = to_ccwgroupdev(dev);
 
        if (gdev->state != CCWGROUP_OFFLINE)
                return -EINVAL;
 
-       __ccwgroup_remove_symlinks(gdev);
-       device_unregister(dev);
-
+       /* Note that we cannot unregister the device from one of its
+        * attribute methods, so we have to use this roundabout approach.
+        */
+       rc = device_schedule_callback(dev, ccwgroup_ungroup_callback);
+       if (rc)
+               count = rc;
        return count;
 }
 
@@ -104,7 +116,7 @@ ccwgroup_release (struct device *dev)
        kfree(gdev);
 }
 
-static inline int
+static int
 __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
 {
        char str[8];
@@ -183,11 +195,9 @@ ccwgroup_create(struct device *root,
 
        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);
@@ -391,10 +401,8 @@ 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,
-       };
+       cdriver->driver.bus = &ccwgroup_bus_type;
+       cdriver->driver.name = cdriver->name;
 
        return driver_register(&cdriver->driver);
 }
@@ -428,7 +436,7 @@ ccwgroup_probe_ccwdev(struct ccw_device *cdev)
        return 0;
 }
 
-static inline struct ccwgroup_device *
+static struct ccwgroup_device *
 __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
 {
        struct ccwgroup_device *gdev;