]> Pileus Git - ~andy/linux/blobdiff - drivers/i2c/i2c-core.c
i2c-sibyte: Kip Walker is gone
[~andy/linux] / drivers / i2c / i2c-core.c
index 2b0c555aa0117382a9319a03ec7f84358e5ccb51..36e1214b0b1daa57427dcdc77c7b3b17a73d81dc 100644 (file)
@@ -169,8 +169,8 @@ int i2c_add_adapter(struct i2c_adapter *adap)
        }
 
        adap->nr =  id & MAX_ID_MASK;
-       init_MUTEX(&adap->bus_lock);
-       init_MUTEX(&adap->clist_lock);
+       mutex_init(&adap->bus_lock);
+       mutex_init(&adap->clist_lock);
        list_add_tail(&adap->list,&adapters);
        INIT_LIST_HEAD(&adap->clients);
 
@@ -183,15 +183,21 @@ int i2c_add_adapter(struct i2c_adapter *adap)
        sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
        adap->dev.driver = &i2c_adapter_driver;
        adap->dev.release = &i2c_adapter_dev_release;
-       device_register(&adap->dev);
-       device_create_file(&adap->dev, &dev_attr_name);
+       res = device_register(&adap->dev);
+       if (res)
+               goto out_list;
+       res = device_create_file(&adap->dev, &dev_attr_name);
+       if (res)
+               goto out_unregister;
 
        /* Add this adapter to the i2c_adapter class */
        memset(&adap->class_dev, 0x00, sizeof(struct class_device));
        adap->class_dev.dev = &adap->dev;
        adap->class_dev.class = &i2c_adapter_class;
        strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
-       class_device_register(&adap->class_dev);
+       res = class_device_register(&adap->class_dev);
+       if (res)
+               goto out_remove_name;
 
        dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
@@ -206,6 +212,17 @@ int i2c_add_adapter(struct i2c_adapter *adap)
 out_unlock:
        mutex_unlock(&core_lists);
        return res;
+
+out_remove_name:
+       device_remove_file(&adap->dev, &dev_attr_name);
+out_unregister:
+       init_completion(&adap->dev_released); /* Needed? */
+       device_unregister(&adap->dev);
+       wait_for_completion(&adap->dev_released);
+out_list:
+       list_del(&adap->list);
+       idr_remove(&i2c_adapter_idr, adap->nr);
+       goto out_unlock;
 }
 
 
@@ -288,9 +305,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 {
        struct list_head   *item;
        struct i2c_adapter *adapter;
-       int res = 0;
-
-       mutex_lock(&core_lists);
+       int res;
 
        /* add the driver to the list of i2c drivers in the driver core */
        driver->driver.owner = owner;
@@ -298,8 +313,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 
        res = driver_register(&driver->driver);
        if (res)
-               goto out_unlock;
+               return res;
        
+       mutex_lock(&core_lists);
+
        list_add_tail(&driver->list,&drivers);
        pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
 
@@ -311,9 +328,8 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
                }
        }
 
- out_unlock:
        mutex_unlock(&core_lists);
-       return res;
+       return 0;
 }
 EXPORT_SYMBOL(i2c_register_driver);
 
@@ -385,9 +401,9 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
 {
        int rval;
 
-       down(&adapter->clist_lock);
+       mutex_lock(&adapter->clist_lock);
        rval = __i2c_check_addr(adapter, addr);
-       up(&adapter->clist_lock);
+       mutex_unlock(&adapter->clist_lock);
 
        return rval;
 }
@@ -395,14 +411,14 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
 int i2c_attach_client(struct i2c_client *client)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int res = 0;
 
-       down(&adapter->clist_lock);
+       mutex_lock(&adapter->clist_lock);
        if (__i2c_check_addr(client->adapter, client->addr)) {
-               up(&adapter->clist_lock);
-               return -EBUSY;
+               res = -EBUSY;
+               goto out_unlock;
        }
        list_add_tail(&client->list,&adapter->clients);
-       up(&adapter->clist_lock);
        
        if (adapter->client_register)  {
                if (adapter->client_register(client))  {
@@ -423,10 +439,26 @@ int i2c_attach_client(struct i2c_client *client)
                "%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);
-       device_register(&client->dev);
-       device_create_file(&client->dev, &dev_attr_client_name);
-       
-       return 0;
+       res = device_register(&client->dev);
+       if (res)
+               goto out_list;
+       res = device_create_file(&client->dev, &dev_attr_client_name);
+       if (res)
+               goto out_unregister;
+
+out_unlock:
+       mutex_unlock(&adapter->clist_lock);
+       return res;
+
+out_unregister:
+       init_completion(&client->released); /* Needed? */
+       device_unregister(&client->dev);
+       wait_for_completion(&client->released);
+out_list:
+       list_del(&client->list);
+       dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
+               "(%d)\n", client->name, client->addr, res);
+       goto out_unlock;
 }
 
 
@@ -451,12 +483,12 @@ int i2c_detach_client(struct i2c_client *client)
                }
        }
 
-       down(&adapter->clist_lock);
+       mutex_lock(&adapter->clist_lock);
        list_del(&client->list);
        init_completion(&client->released);
        device_remove_file(&client->dev, &dev_attr_client_name);
        device_unregister(&client->dev);
-       up(&adapter->clist_lock);
+       mutex_unlock(&adapter->clist_lock);
        wait_for_completion(&client->released);
 
  out:
@@ -514,19 +546,19 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
        struct list_head  *item;
        struct i2c_client *client;
 
-       down(&adap->clist_lock);
+       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) {
-                       up(&adap->clist_lock);
+                       mutex_unlock(&adap->clist_lock);
                        client->driver->command(client,cmd,arg);
-                       down(&adap->clist_lock);
+                       mutex_lock(&adap->clist_lock);
                }
                module_put(client->driver->driver.owner);
        }
-       up(&adap->clist_lock);
+       mutex_unlock(&adap->clist_lock);
 }
 
 static int __init i2c_init(void)
@@ -570,9 +602,9 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
                }
 #endif
 
-               down(&adap->bus_lock);
+               mutex_lock(&adap->bus_lock);
                ret = adap->algo->master_xfer(adap,msgs,num);
-               up(&adap->bus_lock);
+               mutex_unlock(&adap->bus_lock);
 
                return ret;
        } else {
@@ -757,9 +789,9 @@ int i2c_probe(struct i2c_adapter *adapter,
                                        "parameter for adapter %d, "
                                        "addr 0x%02x\n", adap_id,
                                        address_data->ignore[j + 1]);
+                               ignore = 1;
+                               break;
                        }
-                       ignore = 1;
-                       break;
                }
                if (ignore)
                        continue;
@@ -917,7 +949,7 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
 }
 
 s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
-                              u8 length, u8 *values)
+                              u8 length, const u8 *values)
 {
        union i2c_smbus_data data;
 
@@ -945,7 +977,7 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val
 }
 
 s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
-                                  u8 length, u8 *values)
+                                  u8 length, const u8 *values)
 {
        union i2c_smbus_data data;
 
@@ -1116,10 +1148,10 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
        flags &= I2C_M_TEN | I2C_CLIENT_PEC;
 
        if (adapter->algo->smbus_xfer) {
-               down(&adapter->bus_lock);
+               mutex_lock(&adapter->bus_lock);
                res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
                                                command,size,data);
-               up(&adapter->bus_lock);
+               mutex_unlock(&adapter->bus_lock);
        } else
                res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
                                              command,size,data);