aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorMike Rapoport <mike@compulab.co.il>2008-01-27 12:14:50 -0500
committerJean Delvare <khali@hyperion.delvare>2008-01-27 12:14:50 -0500
commitcea443a81c9c6257bf2d00f1392f7d1d4ce03b75 (patch)
tree1168668b6b8c35be86944eda50be6f0132cafc4c /drivers/i2c
parent5271071b20dee56c01b6b9d8e275611403d3d383 (diff)
i2c: Support i2c_transfer in atomic contexts
Allow i2c_transfer to be called in contexts where sleeping is not allowed. It is the reponsability of the caller to ensure that the underlying i2c bus driver will not sleep either. Signed-off-by: Mike Rapoport <mike@compulab.co.il> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/i2c-core.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 7161f913de14..ddd1b83f44d4 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -33,6 +33,8 @@
33#include <linux/platform_device.h> 33#include <linux/platform_device.h>
34#include <linux/mutex.h> 34#include <linux/mutex.h>
35#include <linux/completion.h> 35#include <linux/completion.h>
36#include <linux/hardirq.h>
37#include <linux/irqflags.h>
36#include <asm/uaccess.h> 38#include <asm/uaccess.h>
37#include <asm/semaphore.h> 39#include <asm/semaphore.h>
38 40
@@ -861,7 +863,15 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
861 } 863 }
862#endif 864#endif
863 865
864 mutex_lock_nested(&adap->bus_lock, adap->level); 866 if (in_atomic() || irqs_disabled()) {
867 ret = mutex_trylock(&adap->bus_lock);
868 if (!ret)
869 /* I2C activity is ongoing. */
870 return -EAGAIN;
871 } else {
872 mutex_lock_nested(&adap->bus_lock, adap->level);
873 }
874
865 ret = adap->algo->master_xfer(adap,msgs,num); 875 ret = adap->algo->master_xfer(adap,msgs,num);
866 mutex_unlock(&adap->bus_lock); 876 mutex_unlock(&adap->bus_lock);
867 877