]> git.hungrycats.org Git - linux/commitdiff
I2C: fix up driver model programming error.
authorGreg Kroah-Hartman <greg@kroah.com>
Fri, 8 Aug 2003 09:24:32 +0000 (02:24 -0700)
committerGreg Kroah-Hartman <greg@kroah.com>
Fri, 8 Aug 2003 09:24:32 +0000 (02:24 -0700)
There was no release function for the objects.
bad greg, no biscuit...

drivers/i2c/i2c-core.c
include/linux/i2c.h

index 99b9765cf0be194430ca63b881434f51ae1f3719..b4d124c4082fe00f6a04d86c4899d4b7423ea34f 100644 (file)
@@ -55,6 +55,12 @@ int i2c_device_remove(struct device *dev)
        return 0;
 }
 
+static void i2c_adapter_dev_release(struct device *dev)
+{
+       struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
+       complete(&adap->dev_released);
+}
+
 static struct device_driver i2c_adapter_driver = {
        .name = "i2c_adapter",
        .bus = &i2c_bus_type,
@@ -62,10 +68,23 @@ static struct device_driver i2c_adapter_driver = {
        .remove = i2c_device_remove,
 };
 
+static void i2c_adapter_class_dev_release(struct class_device *dev)
+{
+       struct i2c_adapter *adap = class_dev_to_i2c_adapter(dev);
+       complete(&adap->class_dev_released);
+}
+
 static struct class i2c_adapter_class = {
-       .name =         "i2c-adapter"
+       .name =         "i2c-adapter",
+       .release =      &i2c_adapter_class_dev_release,
 };
 
+static void i2c_client_release(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       complete(&client->released);
+}
+
 
 /* ---------------------------------------------------
  * registering functions 
@@ -99,6 +118,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
                adap->dev.parent = &legacy_bus;
        sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
        adap->dev.driver = &i2c_adapter_driver;
+       adap->dev.release = &i2c_adapter_dev_release;
        device_register(&adap->dev);
 
        /* Add this adapter to the i2c_adapter class */
@@ -161,10 +181,16 @@ int i2c_del_adapter(struct i2c_adapter *adap)
        }
 
        /* clean up the sysfs representation */
+       init_completion(&adap->dev_released);
+       init_completion(&adap->class_dev_released);
        class_device_unregister(&adap->class_dev);
        device_unregister(&adap->dev);
        list_del(&adap->list);
 
+       /* wait for sysfs to drop all references */
+       wait_for_completion(&adap->dev_released);
+       wait_for_completion(&adap->class_dev_released);
+
        DEB(dev_dbg(&adap->dev, "adapter unregistered\n"));
 
  out_unlock:
@@ -329,6 +355,7 @@ int i2c_attach_client(struct i2c_client *client)
        client->dev.parent = &client->adapter->dev;
        client->dev.driver = &client->driver->driver;
        client->dev.bus = &i2c_bus_type;
+       client->dev.release = &i2c_client_release;
        
        snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
                "%d-%04x", i2c_adapter_id(adapter), client->addr);
@@ -359,8 +386,10 @@ int i2c_detach_client(struct i2c_client *client)
 
        down(&adapter->clist_lock);
        list_del(&client->list);
+       init_completion(&client->released);
        device_unregister(&client->dev);
        up(&adapter->clist_lock);
+       wait_for_completion(&client->released);
 
  out:
        return res;
index b8b3c6a1d601065d446e5f35bd445170e235fb22..f2dc147bda895d9b82618f466c85e26f972e2cbf 100644 (file)
@@ -167,6 +167,7 @@ struct i2c_client {
        struct device dev;              /* the device structure         */
        struct list_head list;
        char name[DEVICE_NAME_SIZE];
+       struct completion released;
 };
 #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
 
@@ -253,8 +254,11 @@ struct i2c_adapter {
        struct list_head clients;
        struct list_head list;
        char name[DEVICE_NAME_SIZE];
+       struct completion dev_released;
+       struct completion class_dev_released;
 };
-#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
+#define dev_to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
+#define class_dev_to_i2c_adapter(d) container_of(d, struct i2c_adapter, class_dev)
 
 static inline void *i2c_get_adapdata (struct i2c_adapter *dev)
 {