diff options
author | Wolfram Sang <w.sang@pengutronix.de> | 2009-03-28 21:34:45 +0100 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-03-28 21:34:45 +0100 |
commit | 2378bc09b91b0702fac7823828a614fd8016a29f (patch) | |
tree | 26539b17077028baba2741cf0e78fc01225a7d36 /drivers/i2c/busses | |
parent | 8e99ada8deaa9033600cd2c7d0a9366b0e99ab68 (diff) |
i2c-algo-pca: Use timeout for checking the state machine
We now timeout also if the state machine does not change within the
given time. For that, the driver-specific completion-functions are
extended to return true or false depending on the timeout. This then
gets checked in the algorithm.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/i2c-pca-isa.c | 18 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-pca-platform.c | 20 |
2 files changed, 23 insertions, 15 deletions
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index b9403fdfb6d8..0ed68e2ccd22 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -23,6 +23,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/delay.h> +#include <linux/jiffies.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/wait.h> @@ -43,6 +44,7 @@ static int irq = -1; * in the actual clock rate */ static int clock = 59000; +static struct i2c_adapter pca_isa_ops; static wait_queue_head_t pca_wait; static void pca_isa_writebyte(void *pd, int reg, int val) @@ -69,16 +71,22 @@ static int pca_isa_readbyte(void *pd, int reg) static int pca_isa_waitforcompletion(void *pd) { - int ret = 0; + long ret = ~0; + unsigned long timeout; if (irq > -1) { - ret = wait_event_interruptible(pca_wait, - pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI); + ret = wait_event_interruptible_timeout(pca_wait, + pca_isa_readbyte(pd, I2C_PCA_CON) + & I2C_PCA_CON_SI, pca_isa_ops.timeout); } else { - while ((pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) + /* Do polling */ + timeout = jiffies + pca_isa_ops.timeout; + while (((pca_isa_readbyte(pd, I2C_PCA_CON) + & I2C_PCA_CON_SI) == 0) + && (ret = time_before(jiffies, timeout))) udelay(100); } - return ret; + return ret > 0; } static void pca_isa_resetchip(void *pd) diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 51d179bbddf9..df5e593a1d76 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/jiffies.h> #include <linux/errno.h> #include <linux/i2c.h> #include <linux/interrupt.h> @@ -81,24 +82,23 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val) static int i2c_pca_pf_waitforcompletion(void *pd) { struct i2c_pca_pf_data *i2c = pd; - int ret = 0; + long ret = ~0; + unsigned long timeout; if (i2c->irq) { - ret = wait_event_interruptible(i2c->wait, + ret = wait_event_interruptible_timeout(i2c->wait, i2c->algo_data.read_byte(i2c, I2C_PCA_CON) - & I2C_PCA_CON_SI); + & I2C_PCA_CON_SI, i2c->adap.timeout); } else { - /* - * Do polling... - * XXX: Could get stuck in extreme cases! - * Maybe add timeout, but using irqs is preferred anyhow. - */ - while ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) + /* Do polling */ + timeout = jiffies + i2c->adap.timeout; + while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) + && (ret = time_before(jiffies, timeout))) udelay(100); } - return ret; + return ret > 0; } static void i2c_pca_pf_dummyreset(void *pd) |