diff options
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 85e2e919d1cd..5ed622ee65c3 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/idr.h> | 31 | #include <linux/idr.h> |
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
34 | #include <linux/completion.h> | 33 | #include <linux/completion.h> |
35 | #include <linux/hardirq.h> | 34 | #include <linux/hardirq.h> |
@@ -451,16 +450,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap) | |||
451 | 450 | ||
452 | mutex_lock(&core_lock); | 451 | mutex_lock(&core_lock); |
453 | 452 | ||
454 | /* Add the adapter to the driver core. | ||
455 | * If the parent pointer is not set up, | ||
456 | * we add this adapter to the host bus. | ||
457 | */ | ||
458 | if (adap->dev.parent == NULL) { | ||
459 | adap->dev.parent = &platform_bus; | ||
460 | pr_debug("I2C adapter driver [%s] forgot to specify " | ||
461 | "physical device\n", adap->name); | ||
462 | } | ||
463 | |||
464 | /* Set default timeout to 1 second if not already set */ | 453 | /* Set default timeout to 1 second if not already set */ |
465 | if (adap->timeout == 0) | 454 | if (adap->timeout == 0) |
466 | adap->timeout = HZ; | 455 | adap->timeout = HZ; |
@@ -1022,7 +1011,8 @@ module_exit(i2c_exit); | |||
1022 | */ | 1011 | */ |
1023 | int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | 1012 | int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) |
1024 | { | 1013 | { |
1025 | int ret; | 1014 | unsigned long orig_jiffies; |
1015 | int ret, try; | ||
1026 | 1016 | ||
1027 | /* REVISIT the fault reporting model here is weak: | 1017 | /* REVISIT the fault reporting model here is weak: |
1028 | * | 1018 | * |
@@ -1060,7 +1050,15 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | |||
1060 | mutex_lock_nested(&adap->bus_lock, adap->level); | 1050 | mutex_lock_nested(&adap->bus_lock, adap->level); |
1061 | } | 1051 | } |
1062 | 1052 | ||
1063 | ret = adap->algo->master_xfer(adap,msgs,num); | 1053 | /* Retry automatically on arbitration loss */ |
1054 | orig_jiffies = jiffies; | ||
1055 | for (ret = 0, try = 0; try <= adap->retries; try++) { | ||
1056 | ret = adap->algo->master_xfer(adap, msgs, num); | ||
1057 | if (ret != -EAGAIN) | ||
1058 | break; | ||
1059 | if (time_after(jiffies, orig_jiffies + adap->timeout)) | ||
1060 | break; | ||
1061 | } | ||
1064 | mutex_unlock(&adap->bus_lock); | 1062 | mutex_unlock(&adap->bus_lock); |
1065 | 1063 | ||
1066 | return ret; | 1064 | return ret; |
@@ -1509,7 +1507,7 @@ struct i2c_adapter* i2c_get_adapter(int id) | |||
1509 | struct i2c_adapter *adapter; | 1507 | struct i2c_adapter *adapter; |
1510 | 1508 | ||
1511 | mutex_lock(&core_lock); | 1509 | mutex_lock(&core_lock); |
1512 | adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); | 1510 | adapter = idr_find(&i2c_adapter_idr, id); |
1513 | if (adapter && !try_module_get(adapter->owner)) | 1511 | if (adapter && !try_module_get(adapter->owner)) |
1514 | adapter = NULL; | 1512 | adapter = NULL; |
1515 | 1513 | ||
@@ -1995,14 +1993,27 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, | |||
1995 | char read_write, u8 command, int protocol, | 1993 | char read_write, u8 command, int protocol, |
1996 | union i2c_smbus_data *data) | 1994 | union i2c_smbus_data *data) |
1997 | { | 1995 | { |
1996 | unsigned long orig_jiffies; | ||
1997 | int try; | ||
1998 | s32 res; | 1998 | s32 res; |
1999 | 1999 | ||
2000 | flags &= I2C_M_TEN | I2C_CLIENT_PEC; | 2000 | flags &= I2C_M_TEN | I2C_CLIENT_PEC; |
2001 | 2001 | ||
2002 | if (adapter->algo->smbus_xfer) { | 2002 | if (adapter->algo->smbus_xfer) { |
2003 | mutex_lock(&adapter->bus_lock); | 2003 | mutex_lock(&adapter->bus_lock); |
2004 | res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, | 2004 | |
2005 | command, protocol, data); | 2005 | /* Retry automatically on arbitration loss */ |
2006 | orig_jiffies = jiffies; | ||
2007 | for (res = 0, try = 0; try <= adapter->retries; try++) { | ||
2008 | res = adapter->algo->smbus_xfer(adapter, addr, flags, | ||
2009 | read_write, command, | ||
2010 | protocol, data); | ||
2011 | if (res != -EAGAIN) | ||
2012 | break; | ||
2013 | if (time_after(jiffies, | ||
2014 | orig_jiffies + adapter->timeout)) | ||
2015 | break; | ||
2016 | } | ||
2006 | mutex_unlock(&adapter->bus_lock); | 2017 | mutex_unlock(&adapter->bus_lock); |
2007 | } else | 2018 | } else |
2008 | res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, | 2019 | res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, |