diff options
| -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: |
