aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2008-01-27 12:14:51 -0500
committerJean Delvare <khali@hyperion.delvare>2008-01-27 12:14:51 -0500
commit9b766b814d6a5f31ca1e9da1ebc08164b9352941 (patch)
treece6256c11002c356ee8b632f2a7d08793dd30f82
parent0d227a7e724460bddcd603a1feb672267bcb0d6c (diff)
i2c: Stop using the redundant client list
The i2c_adapter.clients list of i2c_client nodes duplicates driver model state. This patch starts removing that list, letting us remove most existing users of those i2c-core lists. * The core I2C code now iterates over the driver model's list instead of the i2c-internal one in some places where it's safe: - Passing a command/ioctl to each client, a mechanims used almost exclusively by DVB adapters; - Device address checking, in both i2c-core and i2c-dev. * Provide i2c_verify_client() to use with driver model iterators. * Flag the relevant i2c_adapter and i2c_client fields as deprecated, to help prevent new users from appearing. For the moment the list needs to stick around, since some issues show up when deleting devices created by legacy I2C drivers. (They don't follow standard driver model rules. Removing those devices can cause self-deadlocks.) Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r--drivers/i2c/i2c-core.c78
-rw-r--r--drivers/i2c/i2c-dev.c29
-rw-r--r--include/linux/i2c.h8
3 files changed, 63 insertions, 52 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index ddd1b83f44d4..c8bbd672226b 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -199,6 +199,25 @@ static struct bus_type i2c_bus_type = {
199 .resume = i2c_device_resume, 199 .resume = i2c_device_resume,
200}; 200};
201 201
202
203/**
204 * i2c_verify_client - return parameter as i2c_client, or NULL
205 * @dev: device, probably from some driver model iterator
206 *
207 * When traversing the driver model tree, perhaps using driver model
208 * iterators like @device_for_each_child(), you can't assume very much
209 * about the nodes you find. Use this function to avoid oopses caused
210 * by wrongly treating some non-I2C device as an i2c_client.
211 */
212struct i2c_client *i2c_verify_client(struct device *dev)
213{
214 return (dev->bus == &i2c_bus_type)
215 ? to_i2c_client(dev)
216 : NULL;
217}
218EXPORT_SYMBOL(i2c_verify_client);
219
220
202/** 221/**
203 * i2c_new_device - instantiate an i2c device for use with a new style driver 222 * i2c_new_device - instantiate an i2c device for use with a new style driver
204 * @adap: the adapter managing the device 223 * @adap: the adapter managing the device
@@ -670,28 +689,19 @@ EXPORT_SYMBOL(i2c_del_driver);
670 689
671/* ------------------------------------------------------------------------- */ 690/* ------------------------------------------------------------------------- */
672 691
673static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) 692static int __i2c_check_addr(struct device *dev, void *addrp)
674{ 693{
675 struct list_head *item; 694 struct i2c_client *client = i2c_verify_client(dev);
676 struct i2c_client *client; 695 int addr = *(int *)addrp;
677 696
678 list_for_each(item,&adapter->clients) { 697 if (client && client->addr == addr)
679 client = list_entry(item, struct i2c_client, list); 698 return -EBUSY;
680 if (client->addr == addr)
681 return -EBUSY;
682 }
683 return 0; 699 return 0;
684} 700}
685 701
686static int i2c_check_addr(struct i2c_adapter *adapter, int addr) 702static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
687{ 703{
688 int rval; 704 return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
689
690 mutex_lock(&adapter->clist_lock);
691 rval = __i2c_check_addr(adapter, addr);
692 mutex_unlock(&adapter->clist_lock);
693
694 return rval;
695} 705}
696 706
697int i2c_attach_client(struct i2c_client *client) 707int i2c_attach_client(struct i2c_client *client)
@@ -700,7 +710,7 @@ int i2c_attach_client(struct i2c_client *client)
700 int res = 0; 710 int res = 0;
701 711
702 mutex_lock(&adapter->clist_lock); 712 mutex_lock(&adapter->clist_lock);
703 if (__i2c_check_addr(client->adapter, client->addr)) { 713 if (i2c_check_addr(client->adapter, client->addr)) {
704 res = -EBUSY; 714 res = -EBUSY;
705 goto out_unlock; 715 goto out_unlock;
706 } 716 }
@@ -804,24 +814,28 @@ void i2c_release_client(struct i2c_client *client)
804} 814}
805EXPORT_SYMBOL(i2c_release_client); 815EXPORT_SYMBOL(i2c_release_client);
806 816
817struct i2c_cmd_arg {
818 unsigned cmd;
819 void *arg;
820};
821
822static int i2c_cmd(struct device *dev, void *_arg)
823{
824 struct i2c_client *client = i2c_verify_client(dev);
825 struct i2c_cmd_arg *arg = _arg;
826
827 if (client && client->driver && client->driver->command)
828 client->driver->command(client, arg->cmd, arg->arg);
829 return 0;
830}
831
807void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) 832void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
808{ 833{
809 struct list_head *item; 834 struct i2c_cmd_arg cmd_arg;
810 struct i2c_client *client;
811 835
812 mutex_lock(&adap->clist_lock); 836 cmd_arg.cmd = cmd;
813 list_for_each(item,&adap->clients) { 837 cmd_arg.arg = arg;
814 client = list_entry(item, struct i2c_client, list); 838 device_for_each_child(&adap->dev, &cmd_arg, i2c_cmd);
815 if (!try_module_get(client->driver->driver.owner))
816 continue;
817 if (NULL != client->driver->command) {
818 mutex_unlock(&adap->clist_lock);
819 client->driver->command(client,cmd,arg);
820 mutex_lock(&adap->clist_lock);
821 }
822 module_put(client->driver->driver.owner);
823 }
824 mutex_unlock(&adap->clist_lock);
825} 839}
826EXPORT_SYMBOL(i2c_clients_command); 840EXPORT_SYMBOL(i2c_clients_command);
827 841
@@ -1087,7 +1101,7 @@ i2c_new_probed_device(struct i2c_adapter *adap,
1087 } 1101 }
1088 1102
1089 /* Check address availability */ 1103 /* Check address availability */
1090 if (__i2c_check_addr(adap, addr_list[i])) { 1104 if (i2c_check_addr(adap, addr_list[i])) {
1091 dev_dbg(&adap->dev, "Address 0x%02x already in " 1105 dev_dbg(&adap->dev, "Address 0x%02x already in "
1092 "use, not probing\n", addr_list[i]); 1106 "use, not probing\n", addr_list[i]);
1093 continue; 1107 continue;
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index df540d5dfaf4..393e679d9faa 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -182,27 +182,22 @@ 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
185static int i2cdev_check(struct device *dev, void *addrp)
186{
187 struct i2c_client *client = i2c_verify_client(dev);
188
189 if (!client || client->addr != *(unsigned int *)addrp)
190 return 0;
191
192 return dev->driver ? -EBUSY : 0;
193}
194
185/* This address checking function differs from the one in i2c-core 195/* This address checking function differs from the one in i2c-core
186 in that it considers an address with a registered device, but no 196 in that it considers an address with a registered device, but no
187 bound driver, as NOT busy. */ 197 driver bound to it, as NOT busy. */
188static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) 198static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
189{ 199{
190 struct list_head *item; 200 return device_for_each_child(&adapter->dev, &addr, i2cdev_check);
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} 201}
207 202
208static int i2cdev_ioctl(struct inode *inode, struct file *file, 203static int i2cdev_ioctl(struct inode *inode, struct file *file,
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 0fc59efd80e4..731928ae972c 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -158,7 +158,7 @@ struct i2c_driver {
158 * @irq: indicates the IRQ generated by this device (if any) 158 * @irq: indicates the IRQ generated by this device (if any)
159 * @driver_name: Identifies new-style driver used with this device; also 159 * @driver_name: Identifies new-style driver used with this device; also
160 * used as the module name for hotplug/coldplug modprobe support. 160 * used as the module name for hotplug/coldplug modprobe support.
161 * @list: list of active/busy clients 161 * @list: list of active/busy clients (DEPRECATED)
162 * @released: used to synchronize client releases & detaches and references 162 * @released: used to synchronize client releases & detaches and references
163 * 163 *
164 * An i2c_client identifies a single device (i.e. chip) connected to an 164 * An i2c_client identifies a single device (i.e. chip) connected to an
@@ -176,11 +176,13 @@ struct i2c_client {
176 struct device dev; /* the device structure */ 176 struct device dev; /* the device structure */
177 int irq; /* irq issued by device (or -1) */ 177 int irq; /* irq issued by device (or -1) */
178 char driver_name[KOBJ_NAME_LEN]; 178 char driver_name[KOBJ_NAME_LEN];
179 struct list_head list; 179 struct list_head list; /* DEPRECATED */
180 struct completion released; 180 struct completion released;
181}; 181};
182#define to_i2c_client(d) container_of(d, struct i2c_client, dev) 182#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
183 183
184extern struct i2c_client *i2c_verify_client(struct device *dev);
185
184static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj) 186static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)
185{ 187{
186 struct device * const dev = container_of(kobj, struct device, kobj); 188 struct device * const dev = container_of(kobj, struct device, kobj);
@@ -315,7 +317,7 @@ struct i2c_adapter {
315 struct device dev; /* the adapter device */ 317 struct device dev; /* the adapter device */
316 318
317 int nr; 319 int nr;
318 struct list_head clients; 320 struct list_head clients; /* DEPRECATED */
319 char name[48]; 321 char name[48];
320 struct completion dev_released; 322 struct completion dev_released;
321}; 323};