diff options
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 81 |
1 files changed, 39 insertions, 42 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 1a2c9ab5d9e3..45e2cdf54736 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -31,12 +31,13 @@ | |||
31 | #include <linux/idr.h> | 31 | #include <linux/idr.h> |
32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
34 | #include <linux/mutex.h> | ||
34 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
35 | 36 | ||
36 | 37 | ||
37 | static LIST_HEAD(adapters); | 38 | static LIST_HEAD(adapters); |
38 | static LIST_HEAD(drivers); | 39 | static LIST_HEAD(drivers); |
39 | static DECLARE_MUTEX(core_lists); | 40 | static DEFINE_MUTEX(core_lists); |
40 | static DEFINE_IDR(i2c_adapter_idr); | 41 | static DEFINE_IDR(i2c_adapter_idr); |
41 | 42 | ||
42 | /* match always succeeds, as we want the probe() to tell if we really accept this match */ | 43 | /* match always succeeds, as we want the probe() to tell if we really accept this match */ |
@@ -153,7 +154,7 @@ int i2c_add_adapter(struct i2c_adapter *adap) | |||
153 | struct list_head *item; | 154 | struct list_head *item; |
154 | struct i2c_driver *driver; | 155 | struct i2c_driver *driver; |
155 | 156 | ||
156 | down(&core_lists); | 157 | mutex_lock(&core_lists); |
157 | 158 | ||
158 | if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { | 159 | if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { |
159 | res = -ENOMEM; | 160 | res = -ENOMEM; |
@@ -168,8 +169,8 @@ int i2c_add_adapter(struct i2c_adapter *adap) | |||
168 | } | 169 | } |
169 | 170 | ||
170 | adap->nr = id & MAX_ID_MASK; | 171 | adap->nr = id & MAX_ID_MASK; |
171 | init_MUTEX(&adap->bus_lock); | 172 | mutex_init(&adap->bus_lock); |
172 | init_MUTEX(&adap->clist_lock); | 173 | mutex_init(&adap->clist_lock); |
173 | list_add_tail(&adap->list,&adapters); | 174 | list_add_tail(&adap->list,&adapters); |
174 | INIT_LIST_HEAD(&adap->clients); | 175 | INIT_LIST_HEAD(&adap->clients); |
175 | 176 | ||
@@ -203,7 +204,7 @@ int i2c_add_adapter(struct i2c_adapter *adap) | |||
203 | } | 204 | } |
204 | 205 | ||
205 | out_unlock: | 206 | out_unlock: |
206 | up(&core_lists); | 207 | mutex_unlock(&core_lists); |
207 | return res; | 208 | return res; |
208 | } | 209 | } |
209 | 210 | ||
@@ -216,7 +217,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
216 | struct i2c_client *client; | 217 | struct i2c_client *client; |
217 | int res = 0; | 218 | int res = 0; |
218 | 219 | ||
219 | down(&core_lists); | 220 | mutex_lock(&core_lists); |
220 | 221 | ||
221 | /* First make sure that this adapter was ever added */ | 222 | /* First make sure that this adapter was ever added */ |
222 | list_for_each_entry(adap_from_list, &adapters, list) { | 223 | list_for_each_entry(adap_from_list, &adapters, list) { |
@@ -272,7 +273,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
272 | dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); | 273 | dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); |
273 | 274 | ||
274 | out_unlock: | 275 | out_unlock: |
275 | up(&core_lists); | 276 | mutex_unlock(&core_lists); |
276 | return res; | 277 | return res; |
277 | } | 278 | } |
278 | 279 | ||
@@ -287,9 +288,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
287 | { | 288 | { |
288 | struct list_head *item; | 289 | struct list_head *item; |
289 | struct i2c_adapter *adapter; | 290 | struct i2c_adapter *adapter; |
290 | int res = 0; | 291 | int res; |
291 | |||
292 | down(&core_lists); | ||
293 | 292 | ||
294 | /* add the driver to the list of i2c drivers in the driver core */ | 293 | /* add the driver to the list of i2c drivers in the driver core */ |
295 | driver->driver.owner = owner; | 294 | driver->driver.owner = owner; |
@@ -297,8 +296,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
297 | 296 | ||
298 | res = driver_register(&driver->driver); | 297 | res = driver_register(&driver->driver); |
299 | if (res) | 298 | if (res) |
300 | goto out_unlock; | 299 | return res; |
301 | 300 | ||
301 | mutex_lock(&core_lists); | ||
302 | |||
302 | list_add_tail(&driver->list,&drivers); | 303 | list_add_tail(&driver->list,&drivers); |
303 | pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); | 304 | pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); |
304 | 305 | ||
@@ -310,9 +311,8 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
310 | } | 311 | } |
311 | } | 312 | } |
312 | 313 | ||
313 | out_unlock: | 314 | mutex_unlock(&core_lists); |
314 | up(&core_lists); | 315 | return 0; |
315 | return res; | ||
316 | } | 316 | } |
317 | EXPORT_SYMBOL(i2c_register_driver); | 317 | EXPORT_SYMBOL(i2c_register_driver); |
318 | 318 | ||
@@ -324,7 +324,7 @@ int i2c_del_driver(struct i2c_driver *driver) | |||
324 | 324 | ||
325 | int res = 0; | 325 | int res = 0; |
326 | 326 | ||
327 | down(&core_lists); | 327 | mutex_lock(&core_lists); |
328 | 328 | ||
329 | /* Have a look at each adapter, if clients of this driver are still | 329 | /* Have a look at each adapter, if clients of this driver are still |
330 | * attached. If so, detach them to be able to kill the driver | 330 | * attached. If so, detach them to be able to kill the driver |
@@ -363,7 +363,7 @@ int i2c_del_driver(struct i2c_driver *driver) | |||
363 | pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); | 363 | pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); |
364 | 364 | ||
365 | out_unlock: | 365 | out_unlock: |
366 | up(&core_lists); | 366 | mutex_unlock(&core_lists); |
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||
@@ -384,9 +384,9 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr) | |||
384 | { | 384 | { |
385 | int rval; | 385 | int rval; |
386 | 386 | ||
387 | down(&adapter->clist_lock); | 387 | mutex_lock(&adapter->clist_lock); |
388 | rval = __i2c_check_addr(adapter, addr); | 388 | rval = __i2c_check_addr(adapter, addr); |
389 | up(&adapter->clist_lock); | 389 | mutex_unlock(&adapter->clist_lock); |
390 | 390 | ||
391 | return rval; | 391 | return rval; |
392 | } | 392 | } |
@@ -395,13 +395,13 @@ int i2c_attach_client(struct i2c_client *client) | |||
395 | { | 395 | { |
396 | struct i2c_adapter *adapter = client->adapter; | 396 | struct i2c_adapter *adapter = client->adapter; |
397 | 397 | ||
398 | down(&adapter->clist_lock); | 398 | mutex_lock(&adapter->clist_lock); |
399 | if (__i2c_check_addr(client->adapter, client->addr)) { | 399 | if (__i2c_check_addr(client->adapter, client->addr)) { |
400 | up(&adapter->clist_lock); | 400 | mutex_unlock(&adapter->clist_lock); |
401 | return -EBUSY; | 401 | return -EBUSY; |
402 | } | 402 | } |
403 | list_add_tail(&client->list,&adapter->clients); | 403 | list_add_tail(&client->list,&adapter->clients); |
404 | up(&adapter->clist_lock); | 404 | mutex_unlock(&adapter->clist_lock); |
405 | 405 | ||
406 | if (adapter->client_register) { | 406 | if (adapter->client_register) { |
407 | if (adapter->client_register(client)) { | 407 | if (adapter->client_register(client)) { |
@@ -450,12 +450,12 @@ int i2c_detach_client(struct i2c_client *client) | |||
450 | } | 450 | } |
451 | } | 451 | } |
452 | 452 | ||
453 | down(&adapter->clist_lock); | 453 | mutex_lock(&adapter->clist_lock); |
454 | list_del(&client->list); | 454 | list_del(&client->list); |
455 | init_completion(&client->released); | 455 | init_completion(&client->released); |
456 | device_remove_file(&client->dev, &dev_attr_client_name); | 456 | device_remove_file(&client->dev, &dev_attr_client_name); |
457 | device_unregister(&client->dev); | 457 | device_unregister(&client->dev); |
458 | up(&adapter->clist_lock); | 458 | mutex_unlock(&adapter->clist_lock); |
459 | wait_for_completion(&client->released); | 459 | wait_for_completion(&client->released); |
460 | 460 | ||
461 | out: | 461 | out: |
@@ -513,19 +513,19 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) | |||
513 | struct list_head *item; | 513 | struct list_head *item; |
514 | struct i2c_client *client; | 514 | struct i2c_client *client; |
515 | 515 | ||
516 | down(&adap->clist_lock); | 516 | mutex_lock(&adap->clist_lock); |
517 | list_for_each(item,&adap->clients) { | 517 | list_for_each(item,&adap->clients) { |
518 | client = list_entry(item, struct i2c_client, list); | 518 | client = list_entry(item, struct i2c_client, list); |
519 | if (!try_module_get(client->driver->driver.owner)) | 519 | if (!try_module_get(client->driver->driver.owner)) |
520 | continue; | 520 | continue; |
521 | if (NULL != client->driver->command) { | 521 | if (NULL != client->driver->command) { |
522 | up(&adap->clist_lock); | 522 | mutex_unlock(&adap->clist_lock); |
523 | client->driver->command(client,cmd,arg); | 523 | client->driver->command(client,cmd,arg); |
524 | down(&adap->clist_lock); | 524 | mutex_lock(&adap->clist_lock); |
525 | } | 525 | } |
526 | module_put(client->driver->driver.owner); | 526 | module_put(client->driver->driver.owner); |
527 | } | 527 | } |
528 | up(&adap->clist_lock); | 528 | mutex_unlock(&adap->clist_lock); |
529 | } | 529 | } |
530 | 530 | ||
531 | static int __init i2c_init(void) | 531 | static int __init i2c_init(void) |
@@ -569,9 +569,9 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) | |||
569 | } | 569 | } |
570 | #endif | 570 | #endif |
571 | 571 | ||
572 | down(&adap->bus_lock); | 572 | mutex_lock(&adap->bus_lock); |
573 | ret = adap->algo->master_xfer(adap,msgs,num); | 573 | ret = adap->algo->master_xfer(adap,msgs,num); |
574 | up(&adap->bus_lock); | 574 | mutex_unlock(&adap->bus_lock); |
575 | 575 | ||
576 | return ret; | 576 | return ret; |
577 | } else { | 577 | } else { |
@@ -779,12 +779,12 @@ struct i2c_adapter* i2c_get_adapter(int id) | |||
779 | { | 779 | { |
780 | struct i2c_adapter *adapter; | 780 | struct i2c_adapter *adapter; |
781 | 781 | ||
782 | down(&core_lists); | 782 | mutex_lock(&core_lists); |
783 | adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); | 783 | adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); |
784 | if (adapter && !try_module_get(adapter->owner)) | 784 | if (adapter && !try_module_get(adapter->owner)) |
785 | adapter = NULL; | 785 | adapter = NULL; |
786 | 786 | ||
787 | up(&core_lists); | 787 | mutex_unlock(&core_lists); |
788 | return adapter; | 788 | return adapter; |
789 | } | 789 | } |
790 | 790 | ||
@@ -919,12 +919,11 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, | |||
919 | u8 length, u8 *values) | 919 | u8 length, u8 *values) |
920 | { | 920 | { |
921 | union i2c_smbus_data data; | 921 | union i2c_smbus_data data; |
922 | int i; | 922 | |
923 | if (length > I2C_SMBUS_BLOCK_MAX) | 923 | if (length > I2C_SMBUS_BLOCK_MAX) |
924 | length = I2C_SMBUS_BLOCK_MAX; | 924 | length = I2C_SMBUS_BLOCK_MAX; |
925 | for (i = 1; i <= length; i++) | ||
926 | data.block[i] = values[i-1]; | ||
927 | data.block[0] = length; | 925 | data.block[0] = length; |
926 | memcpy(&data.block[1], values, length); | ||
928 | return i2c_smbus_xfer(client->adapter,client->addr,client->flags, | 927 | return i2c_smbus_xfer(client->adapter,client->addr,client->flags, |
929 | I2C_SMBUS_WRITE,command, | 928 | I2C_SMBUS_WRITE,command, |
930 | I2C_SMBUS_BLOCK_DATA,&data); | 929 | I2C_SMBUS_BLOCK_DATA,&data); |
@@ -934,16 +933,14 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, | |||
934 | s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) | 933 | s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) |
935 | { | 934 | { |
936 | union i2c_smbus_data data; | 935 | union i2c_smbus_data data; |
937 | int i; | 936 | |
938 | if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, | 937 | if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, |
939 | I2C_SMBUS_READ,command, | 938 | I2C_SMBUS_READ,command, |
940 | I2C_SMBUS_I2C_BLOCK_DATA,&data)) | 939 | I2C_SMBUS_I2C_BLOCK_DATA,&data)) |
941 | return -1; | 940 | return -1; |
942 | else { | 941 | |
943 | for (i = 1; i <= data.block[0]; i++) | 942 | memcpy(values, &data.block[1], data.block[0]); |
944 | values[i-1] = data.block[i]; | 943 | return data.block[0]; |
945 | return data.block[0]; | ||
946 | } | ||
947 | } | 944 | } |
948 | 945 | ||
949 | s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, | 946 | s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, |
@@ -1118,10 +1115,10 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, | |||
1118 | flags &= I2C_M_TEN | I2C_CLIENT_PEC; | 1115 | flags &= I2C_M_TEN | I2C_CLIENT_PEC; |
1119 | 1116 | ||
1120 | if (adapter->algo->smbus_xfer) { | 1117 | if (adapter->algo->smbus_xfer) { |
1121 | down(&adapter->bus_lock); | 1118 | mutex_lock(&adapter->bus_lock); |
1122 | res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, | 1119 | res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, |
1123 | command,size,data); | 1120 | command,size,data); |
1124 | up(&adapter->bus_lock); | 1121 | mutex_unlock(&adapter->bus_lock); |
1125 | } else | 1122 | } else |
1126 | res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, | 1123 | res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, |
1127 | command,size,data); | 1124 | command,size,data); |