[i2c] i2c-dev and I2C address business
Jean Delvare
khali at linux-fr.org
Tue Jun 5 10:21:35 CEST 2007
Hi David,
With the introduction of the new-style i2c drivers, we changed the
definition of what a busy I2C address is for i2c-dev. Beforehand,
having an i2c_client registered at a given address meant that this
address was busy. Now, what makes an address busy is having an
i2c_client registered _and_ a driver bound to it.
We can't just change the condition in __i2c_check_addr, because the
other address checks in i2c-core would be affected. So I added a
dedicated address checking function in i2c-dev:
Signed-off-by: Jean Delvare <khali at linux-fr.org>
---
drivers/i2c/i2c-dev.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
--- linux-2.6.22-rc3.orig/drivers/i2c/i2c-dev.c 2007-06-04 10:09:38.000000000 +0200
+++ linux-2.6.22-rc3/drivers/i2c/i2c-dev.c 2007-06-05 09:01:33.000000000 +0200
@@ -154,6 +154,29 @@ static ssize_t i2cdev_write (struct file
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,
unsigned int cmd, unsigned long arg)
{
@@ -175,8 +198,9 @@ static int i2cdev_ioctl(struct inode *in
if ((arg > 0x3ff) ||
(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
return -EINVAL;
- if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
+ if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))
return -EBUSY;
+ /* REVISIT: address could become busy later */
client->addr = arg;
return 0;
case I2C_TENBIT:
Now this made me realize (hence the comment) that this i2c-dev code
isn't safe at all, because it does not register the i2c_client it is
using. Another i2c-dev instance could access the same address without a
notice. Or a driver could later be bound to the I2C device in question.
While this is probably acceptable for I2C_SLAVE_FORCE, as it is unsafe
by design, it isn't acceptable for I2C_SLAVE. It sounds like the right
time to think about it and address the issue.
I see two different cases here. First case, we have an address without
a device. We should instantiate a device, and have a driver ready for
it. Shouldn't be too hard. Second case, we have an address with a
device already declared, but no driver bound to it. We need to somehow
force our driver to attach to this device. The problem is that I don't
know how to do that. I'm not even sure if the device driver model
allows this. David, can you please help with this?
Thanks,
--
Jean Delvare
More information about the i2c
mailing list