8390: Split 8390 support into a pausing and a non pausing driver core
[safe/jmp/linux-2.6] / drivers / i2c / i2c-core.c
index 7161f91..d0175f4 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
 #include <linux/completion.h>
+#include <linux/hardirq.h>
+#include <linux/irqflags.h>
+#include <linux/semaphore.h>
 #include <asm/uaccess.h>
-#include <asm/semaphore.h>
 
 #include "i2c-core.h"
 
@@ -46,6 +48,17 @@ static DEFINE_IDR(i2c_adapter_idr);
 
 /* ------------------------------------------------------------------------- */
 
+static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
+                                               const struct i2c_client *client)
+{
+       while (id->name[0]) {
+               if (strcmp(client->name, id->name) == 0)
+                       return id;
+               id++;
+       }
+       return NULL;
+}
+
 static int i2c_device_match(struct device *dev, struct device_driver *drv)
 {
        struct i2c_client       *client = to_i2c_client(dev);
@@ -57,10 +70,11 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
        if (!is_newstyle_driver(driver))
                return 0;
 
-       /* new style drivers use the same kind of driver matching policy
-        * as platform devices or SPI:  compare device and driver IDs.
-        */
-       return strcmp(client->driver_name, drv->name) == 0;
+       /* match on an id table if there is one */
+       if (driver->id_table)
+               return i2c_match_id(driver->id_table, client) != NULL;
+
+       return 0;
 }
 
 #ifdef CONFIG_HOTPLUG
@@ -71,10 +85,11 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
        struct i2c_client       *client = to_i2c_client(dev);
 
        /* by definition, legacy drivers can't hotplug */
-       if (dev->driver || !client->driver_name)
+       if (dev->driver)
                return 0;
 
-       if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
+       if (add_uevent_var(env, "MODALIAS=%s%s",
+                          I2C_MODULE_PREFIX, client->name))
                return -ENOMEM;
        dev_dbg(dev, "uevent\n");
        return 0;
@@ -88,12 +103,22 @@ static int i2c_device_probe(struct device *dev)
 {
        struct i2c_client       *client = to_i2c_client(dev);
        struct i2c_driver       *driver = to_i2c_driver(dev->driver);
+       const struct i2c_device_id *id;
+       int status;
 
        if (!driver->probe)
                return -ENODEV;
        client->driver = driver;
        dev_dbg(dev, "probe\n");
-       return driver->probe(client);
+
+       if (driver->id_table)
+               id = i2c_match_id(driver->id_table, client);
+       else
+               id = NULL;
+       status = driver->probe(client, id);
+       if (status)
+               client->driver = NULL;
+       return status;
 }
 
 static int i2c_device_remove(struct device *dev)
@@ -173,9 +198,7 @@ static ssize_t show_client_name(struct device *dev, struct device_attribute *att
 static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct i2c_client *client = to_i2c_client(dev);
-       return client->driver_name
-               ? sprintf(buf, "%s\n", client->driver_name)
-               : 0;
+       return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name);
 }
 
 static struct device_attribute i2c_dev_attrs[] = {
@@ -197,6 +220,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
@@ -230,8 +272,6 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
        client->addr = info->addr;
        client->irq = info->irq;
 
-       strlcpy(client->driver_name, info->driver_name,
-               sizeof(client->driver_name));
        strlcpy(client->name, info->type, sizeof(client->name));
 
        /* a new style driver may be bound to this device when we
@@ -275,6 +315,58 @@ void i2c_unregister_device(struct i2c_client *client)
 EXPORT_SYMBOL_GPL(i2c_unregister_device);
 
 
+static const struct i2c_device_id dummy_id[] = {
+       { "dummy", 0 },
+       { },
+};
+
+static int dummy_probe(struct i2c_client *client,
+                      const struct i2c_device_id *id)
+{
+       return 0;
+}
+
+static int dummy_remove(struct i2c_client *client)
+{
+       return 0;
+}
+
+static struct i2c_driver dummy_driver = {
+       .driver.name    = "dummy",
+       .probe          = dummy_probe,
+       .remove         = dummy_remove,
+       .id_table       = dummy_id,
+};
+
+/**
+ * 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
+ * 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)
+{
+       struct i2c_board_info info = {
+               I2C_BOARD_INFO("dummy", address),
+       };
+
+       return i2c_new_device(adapter, &info);
+}
+EXPORT_SYMBOL_GPL(i2c_new_dummy);
+
 /* ------------------------------------------------------------------------- */
 
 /* I2C bus adapters -- one roots each I2C or SMBUS segment */
@@ -420,8 +512,8 @@ EXPORT_SYMBOL(i2c_add_adapter);
  * Context: can sleep
  *
  * This routine is used to declare an I2C adapter when its bus number
- * matters.  Example: for I2C adapters from system-on-chip CPUs, or
- * otherwise built in to the system's mainboard, and where i2c_board_info
+ * matters.  For example, use it for I2C adapters from system-on-chip CPUs,
+ * or otherwise built in to the system's mainboard, and where i2c_board_info
  * is used to properly configure I2C devices.
  *
  * If no devices have pre-been declared for this bus, then be sure to
@@ -668,28 +760,19 @@ 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 +780,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 +794,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 +815,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 +839,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 +880,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 +912,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 +956,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 +1170,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 +1179,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 +1207,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");
@@ -1428,7 +1529,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                read_write = I2C_SMBUS_READ;
                if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
                        dev_err(&adapter->dev, "%s called with invalid "
-                               "block proc call size (%d)\n", __FUNCTION__,
+                               "block proc call size (%d)\n", __func__,
                                data->block[0]);
                        return -1;
                }