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>
This commit is contained in:
parent
907135aaa0
commit
bd4217d8c6
|
@ -182,6 +182,29 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This address checking function differs from the one in i2c-core
|
||||||
|
in that it considers an address with a registered device, but no
|
||||||
|
bounded driver, as NOT busy. */
|
||||||
|
static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
|
||||||
|
{
|
||||||
|
struct list_head *item;
|
||||||
|
struct i2c_client *client;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
mutex_lock(&adapter->clist_lock);
|
||||||
|
list_for_each(item, &adapter->clients) {
|
||||||
|
client = list_entry(item, struct i2c_client, list);
|
||||||
|
if (client->addr == addr) {
|
||||||
|
if (client->driver)
|
||||||
|
res = -EBUSY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&adapter->clist_lock);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int i2cdev_ioctl(struct inode *inode, struct file *file,
|
static int i2cdev_ioctl(struct inode *inode, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
|
@ -213,8 +236,9 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
|
||||||
if ((arg > 0x3ff) ||
|
if ((arg > 0x3ff) ||
|
||||||
(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
|
(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
|
if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
/* REVISIT: address could become busy later */
|
||||||
client->addr = arg;
|
client->addr = arg;
|
||||||
return 0;
|
return 0;
|
||||||
case I2C_TENBIT:
|
case I2C_TENBIT:
|
||||||
|
|
Loading…
Reference in New Issue