aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/w1
diff options
context:
space:
mode:
authorMaciej Szmigiero <mhej@o2.pl>2011-11-15 18:43:16 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-11-17 14:47:56 -0500
commit377195c438fc5e9e4ca59e69382c10771d817d6a (patch)
tree64ae50d55bf8c36ba50ab16e19895ce9e1c985fe /drivers/w1
parent65e6757be42ddf0a9115ec0e6af268fec9727359 (diff)
W1: w1_therm: release the bus during conversion on externally powered devices
w1_therm devices can either be bus powered or externally powered. When device is bus powered during temperature conversion the bus have to be left high to provide necessary power. Some masters also allow strong power-up to be enabled in this case. Naturally, no communication over bus can occur during that time. However, if device has external power then there is no such restriction, and host can talk to other devices during temperature conversion. There is command which allows us to check how device is powered, this patch uses it to release the bus on externally w1_therm powered devices during temperature conversion. Also, this changes uninterruptible sleeps there into interruptible ones to avoid long uninterruptible sleep if w1 subsystem happens to grab bus for scan during w1_therm_read(). Signed-off-by: Maciej Szmigiero <mhej@o2.pl> Acked-by: Evgeniy Polyakov <zbr@ioremap.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/w1')
-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,
175{ 175{
176 struct w1_slave *sl = dev_to_w1_slave(device); 176 struct w1_slave *sl = dev_to_w1_slave(device);
177 struct w1_master *dev = sl->master; 177 struct w1_master *dev = sl->master;
178 u8 rom[9], crc, verdict; 178 u8 rom[9], crc, verdict, external_power;
179 int i, max_trying = 10; 179 int i, max_trying = 10;
180 ssize_t c = PAGE_SIZE; 180 ssize_t c = PAGE_SIZE;
181 181
182 mutex_lock(&dev->mutex); 182 i = mutex_lock_interruptible(&dev->mutex);
183 if (i != 0)
184 return i;
183 185
184 memset(rom, 0, sizeof(rom)); 186 memset(rom, 0, sizeof(rom));
185 187
@@ -190,13 +192,37 @@ static ssize_t w1_therm_read(struct device *device,
190 if (!w1_reset_select_slave(sl)) { 192 if (!w1_reset_select_slave(sl)) {
191 int count = 0; 193 int count = 0;
192 unsigned int tm = 750; 194 unsigned int tm = 750;
195 unsigned long sleep_rem;
196
197 w1_write_8(dev, W1_READ_PSUPPLY);
198 external_power = w1_read_8(dev);
199
200 if (w1_reset_select_slave(sl))
201 continue;
193 202
194 /* 750ms strong pullup (or delay) after the convert */ 203 /* 750ms strong pullup (or delay) after the convert */
195 if (w1_strong_pullup) 204 if (!external_power && w1_strong_pullup)
196 w1_next_pullup(dev, tm); 205 w1_next_pullup(dev, tm);
206
197 w1_write_8(dev, W1_CONVERT_TEMP); 207 w1_write_8(dev, W1_CONVERT_TEMP);
198 if (!w1_strong_pullup) 208
199 msleep(tm); 209 if (external_power) {
210 mutex_unlock(&dev->mutex);
211
212 sleep_rem = msleep_interruptible(tm);
213 if (sleep_rem != 0)
214 return -EINTR;
215
216 i = mutex_lock_interruptible(&dev->mutex);
217 if (i != 0)
218 return i;
219 } else if (!w1_strong_pullup) {
220 sleep_rem = msleep_interruptible(tm);
221 if (sleep_rem != 0) {
222 mutex_unlock(&dev->mutex);
223 return -EINTR;
224 }
225 }
200 226
201 if (!w1_reset_select_slave(sl)) { 227 if (!w1_reset_select_slave(sl)) {
202 228