summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/w1/slaves/w1_therm.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index a1ef9b5b38cf..ff29ae747ee8 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -175,11 +175,13 @@ static ssize_t w1_therm_read(struct device *device,
{
struct w1_slave *sl = dev_to_w1_slave(device);
struct w1_master *dev = sl->master;
- u8 rom[9], crc, verdict;
+ u8 rom[9], crc, verdict, external_power;
int i, max_trying = 10;
ssize_t c = PAGE_SIZE;
- mutex_lock(&dev->mutex);
+ i = mutex_lock_interruptible(&dev->mutex);
+ if (i != 0)
+ return i;
memset(rom, 0, sizeof(rom));
@@ -190,13 +192,37 @@ static ssize_t w1_therm_read(struct device *device,
if (!w1_reset_select_slave(sl)) {
int count = 0;
unsigned int tm = 750;
+ unsigned long sleep_rem;
+
+ w1_write_8(dev, W1_READ_PSUPPLY);
+ external_power = w1_read_8(dev);
+
+ if (w1_reset_select_slave(sl))
+ continue;
/* 750ms strong pullup (or delay) after the convert */
- if (w1_strong_pullup)
+ if (!external_power && w1_strong_pullup)
w1_next_pullup(dev, tm);
+
w1_write_8(dev, W1_CONVERT_TEMP);
- if (!w1_strong_pullup)
- msleep(tm);
+
+ if (external_power) {
+ mutex_unlock(&dev->mutex);
+
+ sleep_rem = msleep_interruptible(tm);
+ if (sleep_rem != 0)
+ return -EINTR;
+
+ i = mutex_lock_interruptible(&dev->mutex);
+ if (i != 0)
+ return i;
+ } else if (!w1_strong_pullup) {
+ sleep_rem = msleep_interruptible(tm);
+ if (sleep_rem != 0) {
+ mutex_unlock(&dev->mutex);
+ return -EINTR;
+ }
+ }
if (!w1_reset_select_slave(sl)) {