diff options
author | Jean Delvare <khali@linux-fr.org> | 2007-11-15 13:24:01 -0500 |
---|---|---|
committer | Jean Delvare <khali@hyperion.delvare> | 2007-11-15 13:24:01 -0500 |
commit | bd4217d8c6ef48425c8d6b28d2e089a83e01af04 (patch) | |
tree | 0c399bdc4497ced5f168fa224a2c4c5ca63cfb5e /drivers/i2c | |
parent | 907135aaa0cc120a347222c8f274ecc5ca0db641 (diff) |
i2c-dev: Unbound new-style i2c clients aren't busy
Let i2c-dev deal properly with new-style i2c clients. Instead of
considering them always busy, it needs to check wether a driver is
bound to them or not.
This is still not completely correct, as the client could become
busy later, but the same problem already existed before new-style
clients were introduced. We'll want to fix it someday.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/i2c-dev.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 7360f9c37256..c21ae20ae362 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
@@ -182,6 +182,29 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c | |||
182 | return ret; | 182 | return ret; |
183 | } | 183 | } |
184 | 184 | ||
185 | /* This address checking function differs from the one in i2c-core | ||
186 | in that it considers an address with a registered device, but no | ||
187 | bounded driver, as NOT busy. */ | ||
188 | static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) | ||
189 | { | ||
190 | struct list_head *item; | ||
191 | struct i2c_client *client; | ||
192 | int res = 0; | ||
193 | |||
194 | mutex_lock(&adapter->clist_lock); | ||
195 | list_for_each(item, &adapter->clients) { | ||
196 | client = list_entry(item, struct i2c_client, list); | ||
197 | if (client->addr == addr) { | ||
198 | if (client->driver) | ||
199 | res = -EBUSY; | ||
200 | break; | ||
201 | } | ||
202 | } | ||
203 | mutex_unlock(&adapter->clist_lock); | ||
204 | |||
205 | return res; | ||
206 | } | ||
207 | |||
185 | static int i2cdev_ioctl(struct inode *inode, struct file *file, | 208 | static int i2cdev_ioctl(struct inode *inode, struct file *file, |
186 | unsigned int cmd, unsigned long arg) | 209 | unsigned int cmd, unsigned long arg) |
187 | { | 210 | { |
@@ -213,8 +236,9 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, | |||
213 | if ((arg > 0x3ff) || | 236 | if ((arg > 0x3ff) || |
214 | (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) | 237 | (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) |
215 | return -EINVAL; | 238 | return -EINVAL; |
216 | if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg)) | 239 | if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg)) |
217 | return -EBUSY; | 240 | return -EBUSY; |
241 | /* REVISIT: address could become busy later */ | ||
218 | client->addr = arg; | 242 | client->addr = arg; |
219 | return 0; | 243 | return 0; |
220 | case I2C_TENBIT: | 244 | case I2C_TENBIT: |