From 7ef83943fcfaee73e7051b9039cb7f992b243183 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 10 Oct 2003 00:59:18 -0700 Subject: [PATCH] [PATCH] I2C: fix i2c-dev class release function bug. There was no release function, that was the bug :) It caused bad messages to show up in the syslog whenever a i2c driver was removed, and could easily oops. --- drivers/i2c/i2c-dev.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 613effc44f3ad..62d157f0d05e5 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -49,6 +49,7 @@ struct i2c_dev { int minor; struct i2c_adapter *adap; struct class_device class_dev; + struct completion released; /* FIXME, we need a class_device_unregister() */ }; #define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev) @@ -112,7 +113,6 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev) spin_lock(&i2c_dev_array_lock); i2c_dev_array[i2c_dev->minor] = NULL; spin_unlock(&i2c_dev_array_lock); - kfree(i2c_dev); } static ssize_t show_dev(struct class_device *class_dev, char *buf) @@ -421,8 +421,15 @@ static struct file_operations i2cdev_fops = { .release = i2cdev_release, }; +static void release_i2c_dev(struct class_device *dev) +{ + struct i2c_dev *i2c_dev = to_i2c_dev(dev); + complete(&i2c_dev->released); +} + static struct class i2c_dev_class = { - .name = "i2c-dev", + .name = "i2c-dev", + .release = &release_i2c_dev, }; static int i2cdev_attach_adapter(struct i2c_adapter *adap) @@ -453,6 +460,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) return 0; error: return_i2c_dev(i2c_dev); + kfree(i2c_dev); return retval; } @@ -464,9 +472,12 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap) if (!i2c_dev) return -ENODEV; - class_device_unregister(&i2c_dev->class_dev); + init_completion(&i2c_dev->released); devfs_remove("i2c/%d", i2c_dev->minor); return_i2c_dev(i2c_dev); + class_device_unregister(&i2c_dev->class_dev); + wait_for_completion(&i2c_dev->released); + kfree(i2c_dev); dev_dbg(&adap->dev, "Adapter unregistered\n"); return 0; -- 2.53.0