Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[sfrench/cifs-2.6.git] / drivers / i2c / i2c-core.c
index 29d2a1b4b464f12dfba1e9fc908640e9c7c9a7a7..96da22e9a5a44dbe32b247694a2b72bdea20c0d8 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
 #include <linux/completion.h>
+#include <linux/hardirq.h>
+#include <linux/irqflags.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
 #include "i2c-core.h"
 
 
-static DEFINE_MUTEX(core_lists);
+static DEFINE_MUTEX(core_lock);
 static DEFINE_IDR(i2c_adapter_idr);
 
 #define is_newstyle_driver(d) ((d)->probe || (d)->remove)
@@ -197,6 +199,25 @@ static struct bus_type i2c_bus_type = {
        .resume         = i2c_device_resume,
 };
 
+
+/**
+ * i2c_verify_client - return parameter as i2c_client, or NULL
+ * @dev: device, probably from some driver model iterator
+ *
+ * When traversing the driver model tree, perhaps using driver model
+ * iterators like @device_for_each_child(), you can't assume very much
+ * about the nodes you find.  Use this function to avoid oopses caused
+ * by wrongly treating some non-I2C device as an i2c_client.
+ */
+struct i2c_client *i2c_verify_client(struct device *dev)
+{
+       return (dev->bus == &i2c_bus_type)
+                       ? to_i2c_client(dev)
+                       : NULL;
+}
+EXPORT_SYMBOL(i2c_verify_client);
+
+
 /**
  * i2c_new_device - instantiate an i2c device for use with a new style driver
  * @adap: the adapter managing the device
@@ -275,6 +296,50 @@ void i2c_unregister_device(struct i2c_client *client)
 EXPORT_SYMBOL_GPL(i2c_unregister_device);
 
 
+static int dummy_nop(struct i2c_client *client)
+{
+       return 0;
+}
+
+static struct i2c_driver dummy_driver = {
+       .driver.name    = "dummy",
+       .probe          = dummy_nop,
+       .remove         = dummy_nop,
+};
+
+/**
+ * i2c_new_dummy - return a new i2c device bound to a dummy driver
+ * @adapter: the adapter managing the device
+ * @address: seven bit address to be used
+ * @type: optional label used for i2c_client.name
+ * Context: can sleep
+ *
+ * This returns an I2C client bound to the "dummy" driver, intended for use
+ * with devices that consume multiple addresses.  Examples of such chips
+ * include various EEPROMS (like 24c04 and 24c08 models).
+ *
+ * These dummy devices have two main uses.  First, most I2C and SMBus calls
+ * except i2c_transfer() need a client handle; the dummy will be that handle.
+ * And second, this prevents the specified address from being bound to a
+ * different driver.
+ *
+ * This returns the new i2c client, which should be saved for later use with
+ * i2c_unregister_device(); or NULL to indicate an error.
+ */
+struct i2c_client *
+i2c_new_dummy(struct i2c_adapter *adapter, u16 address, const char *type)
+{
+       struct i2c_board_info info = {
+               .driver_name    = "dummy",
+               .addr           = address,
+       };
+
+       if (type)
+               strlcpy(info.type, type, sizeof info.type);
+       return i2c_new_device(adapter, &info);
+}
+EXPORT_SYMBOL_GPL(i2c_new_dummy);
+
 /* ------------------------------------------------------------------------- */
 
 /* I2C bus adapters -- one roots each I2C or SMBUS segment */
@@ -339,7 +404,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
        mutex_init(&adap->clist_lock);
        INIT_LIST_HEAD(&adap->clients);
 
-       mutex_lock(&core_lists);
+       mutex_lock(&core_lock);
 
        /* Add the adapter to the driver core.
         * If the parent pointer is not set up,
@@ -368,7 +433,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
                                 i2c_do_add_adapter);
 
 out_unlock:
-       mutex_unlock(&core_lists);
+       mutex_unlock(&core_lock);
        return res;
 
 out_list:
@@ -397,11 +462,11 @@ retry:
        if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
                return -ENOMEM;
 
-       mutex_lock(&core_lists);
+       mutex_lock(&core_lock);
        /* "above" here means "above or equal to", sigh */
        res = idr_get_new_above(&i2c_adapter_idr, adapter,
                                __i2c_first_dynamic_bus_num, &id);
-       mutex_unlock(&core_lists);
+       mutex_unlock(&core_lock);
 
        if (res < 0) {
                if (res == -EAGAIN)
@@ -446,7 +511,7 @@ retry:
        if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
                return -ENOMEM;
 
-       mutex_lock(&core_lists);
+       mutex_lock(&core_lock);
        /* "above" here means "above or equal to", sigh;
         * we need the "equal to" result to force the result
         */
@@ -455,7 +520,7 @@ retry:
                status = -EBUSY;
                idr_remove(&i2c_adapter_idr, id);
        }
-       mutex_unlock(&core_lists);
+       mutex_unlock(&core_lock);
        if (status == -EAGAIN)
                goto retry;
 
@@ -494,7 +559,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
        struct i2c_client *client;
        int res = 0;
 
-       mutex_lock(&core_lists);
+       mutex_lock(&core_lock);
 
        /* First make sure that this adapter was ever added */
        if (idr_find(&i2c_adapter_idr, adap->nr) != adap) {
@@ -546,7 +611,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
        dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
 
  out_unlock:
-       mutex_unlock(&core_lists);
+       mutex_unlock(&core_lock);
        return res;
 }
 EXPORT_SYMBOL(i2c_del_adapter);
@@ -589,7 +654,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
        if (res)
                return res;
 
-       mutex_lock(&core_lists);
+       mutex_lock(&core_lock);
 
        pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
 
@@ -605,7 +670,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
                up(&i2c_adapter_class.sem);
        }
 
-       mutex_unlock(&core_lists);
+       mutex_unlock(&core_lock);
        return 0;
 }
 EXPORT_SYMBOL(i2c_register_driver);
@@ -621,7 +686,7 @@ void i2c_del_driver(struct i2c_driver *driver)
        struct i2c_client  *client;
        struct i2c_adapter *adap;
 
-       mutex_lock(&core_lists);
+       mutex_lock(&core_lock);
 
        /* new-style driver? */
        if (is_newstyle_driver(driver))
@@ -662,34 +727,25 @@ void i2c_del_driver(struct i2c_driver *driver)
        driver_unregister(&driver->driver);
        pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
 
-       mutex_unlock(&core_lists);
+       mutex_unlock(&core_lock);
 }
 EXPORT_SYMBOL(i2c_del_driver);
 
 /* ------------------------------------------------------------------------- */
 
-static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr)
+static int __i2c_check_addr(struct device *dev, void *addrp)
 {
-       struct list_head   *item;
-       struct i2c_client  *client;
+       struct i2c_client       *client = i2c_verify_client(dev);
+       int                     addr = *(int *)addrp;
 
-       list_for_each(item,&adapter->clients) {
-               client = list_entry(item, struct i2c_client, list);
-               if (client->addr == addr)
-                       return -EBUSY;
-       }
+       if (client && client->addr == addr)
+               return -EBUSY;
        return 0;
 }
 
 static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
 {
-       int rval;
-
-       mutex_lock(&adapter->clist_lock);
-       rval = __i2c_check_addr(adapter, addr);
-       mutex_unlock(&adapter->clist_lock);
-
-       return rval;
+       return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
 }
 
 int i2c_attach_client(struct i2c_client *client)
@@ -697,13 +753,6 @@ int i2c_attach_client(struct i2c_client *client)
        struct i2c_adapter *adapter = client->adapter;
        int res = 0;
 
-       mutex_lock(&adapter->clist_lock);
-       if (__i2c_check_addr(client->adapter, client->addr)) {
-               res = -EBUSY;
-               goto out_unlock;
-       }
-       list_add_tail(&client->list,&adapter->clients);
-
        client->dev.parent = &client->adapter->dev;
        client->dev.bus = &i2c_bus_type;
 
@@ -718,13 +767,17 @@ int i2c_attach_client(struct i2c_client *client)
 
        snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
                "%d-%04x", i2c_adapter_id(adapter), client->addr);
-       dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
-               client->name, client->dev.bus_id);
        res = device_register(&client->dev);
        if (res)
-               goto out_list;
+               goto out_err;
+
+       mutex_lock(&adapter->clist_lock);
+       list_add_tail(&client->list, &adapter->clients);
        mutex_unlock(&adapter->clist_lock);
 
+       dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
+               client->name, client->dev.bus_id);
+
        if (adapter->client_register)  {
                if (adapter->client_register(client)) {
                        dev_dbg(&adapter->dev, "client_register "
@@ -735,12 +788,9 @@ int i2c_attach_client(struct i2c_client *client)
 
        return 0;
 
-out_list:
-       list_del(&client->list);
+out_err:
        dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
                "(%d)\n", client->name, client->addr, res);
-out_unlock:
-       mutex_unlock(&adapter->clist_lock);
        return res;
 }
 EXPORT_SYMBOL(i2c_attach_client);
@@ -762,9 +812,10 @@ int i2c_detach_client(struct i2c_client *client)
 
        mutex_lock(&adapter->clist_lock);
        list_del(&client->list);
+       mutex_unlock(&adapter->clist_lock);
+
        init_completion(&client->released);
        device_unregister(&client->dev);
-       mutex_unlock(&adapter->clist_lock);
        wait_for_completion(&client->released);
 
  out:
@@ -802,24 +853,28 @@ void i2c_release_client(struct i2c_client *client)
 }
 EXPORT_SYMBOL(i2c_release_client);
 
+struct i2c_cmd_arg {
+       unsigned        cmd;
+       void            *arg;
+};
+
+static int i2c_cmd(struct device *dev, void *_arg)
+{
+       struct i2c_client       *client = i2c_verify_client(dev);
+       struct i2c_cmd_arg      *arg = _arg;
+
+       if (client && client->driver && client->driver->command)
+               client->driver->command(client, arg->cmd, arg->arg);
+       return 0;
+}
+
 void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
 {
-       struct list_head  *item;
-       struct i2c_client *client;
+       struct i2c_cmd_arg      cmd_arg;
 
-       mutex_lock(&adap->clist_lock);
-       list_for_each(item,&adap->clients) {
-               client = list_entry(item, struct i2c_client, list);
-               if (!try_module_get(client->driver->driver.owner))
-                       continue;
-               if (NULL != client->driver->command) {
-                       mutex_unlock(&adap->clist_lock);
-                       client->driver->command(client,cmd,arg);
-                       mutex_lock(&adap->clist_lock);
-               }
-               module_put(client->driver->driver.owner);
-       }
-       mutex_unlock(&adap->clist_lock);
+       cmd_arg.cmd = cmd;
+       cmd_arg.arg = arg;
+       device_for_each_child(&adap->dev, &cmd_arg, i2c_cmd);
 }
 EXPORT_SYMBOL(i2c_clients_command);
 
@@ -830,11 +885,24 @@ static int __init i2c_init(void)
        retval = bus_register(&i2c_bus_type);
        if (retval)
                return retval;
-       return class_register(&i2c_adapter_class);
+       retval = class_register(&i2c_adapter_class);
+       if (retval)
+               goto bus_err;
+       retval = i2c_add_driver(&dummy_driver);
+       if (retval)
+               goto class_err;
+       return 0;
+
+class_err:
+       class_unregister(&i2c_adapter_class);
+bus_err:
+       bus_unregister(&i2c_bus_type);
+       return retval;
 }
 
 static void __exit i2c_exit(void)
 {
+       i2c_del_driver(&dummy_driver);
        class_unregister(&i2c_adapter_class);
        bus_unregister(&i2c_bus_type);
 }
@@ -861,7 +929,15 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
                }
 #endif
 
-               mutex_lock_nested(&adap->bus_lock, adap->level);
+               if (in_atomic() || irqs_disabled()) {
+                       ret = mutex_trylock(&adap->bus_lock);
+                       if (!ret)
+                               /* I2C activity is ongoing. */
+                               return -EAGAIN;
+               } else {
+                       mutex_lock_nested(&adap->bus_lock, adap->level);
+               }
+
                ret = adap->algo->master_xfer(adap,msgs,num);
                mutex_unlock(&adap->bus_lock);
 
@@ -1067,7 +1143,6 @@ i2c_new_probed_device(struct i2c_adapter *adap,
                return NULL;
        }
 
-       mutex_lock(&adap->clist_lock);
        for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
                /* Check address validity */
                if (addr_list[i] < 0x03 || addr_list[i] > 0x77) {
@@ -1077,7 +1152,7 @@ i2c_new_probed_device(struct i2c_adapter *adap,
                }
 
                /* Check address availability */
-               if (__i2c_check_addr(adap, addr_list[i])) {
+               if (i2c_check_addr(adap, addr_list[i])) {
                        dev_dbg(&adap->dev, "Address 0x%02x already in "
                                "use, not probing\n", addr_list[i]);
                        continue;
@@ -1105,7 +1180,6 @@ i2c_new_probed_device(struct i2c_adapter *adap,
                                break;
                }
        }
-       mutex_unlock(&adap->clist_lock);
 
        if (addr_list[i] == I2C_CLIENT_END) {
                dev_dbg(&adap->dev, "Probing failed, no device found\n");
@@ -1121,12 +1195,12 @@ struct i2c_adapter* i2c_get_adapter(int id)
 {
        struct i2c_adapter *adapter;
 
-       mutex_lock(&core_lists);
+       mutex_lock(&core_lock);
        adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
        if (adapter && !try_module_get(adapter->owner))
                adapter = NULL;
 
-       mutex_unlock(&core_lists);
+       mutex_unlock(&core_lock);
        return adapter;
 }
 EXPORT_SYMBOL(i2c_get_adapter);