Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: dht11: Use new function ktime_get_resolution_ns()

This cleans up the most ugly workaround in this driver. There are no
functional changes yet in the decoding algorithm, but we improve the
following things:
* Get rid of spurious warning messages on systems with fast HRTIMER.
* If the clock is not fast enough for decoding to work, we give
up immediately.
* In that case we return EAGAIN instead of EIO, so it's easier to
discriminate causes of failure.

Returning EAGAIN is somewhat controversial: It's technically correct
as a faster clock might become available. OTOH once all clocks are
enabled this is a permanent error. There is no ECLOCKTOOSLOW error
code.

Signed-off-by: Harald Geyer <harald@ccbib.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

authored by

Harald Geyer and committed by
Jonathan Cameron
081d9740 5fbb0bc4

+22 -20
+22 -20
drivers/iio/humidity/dht11.c
··· 33 33 #include <linux/delay.h> 34 34 #include <linux/gpio.h> 35 35 #include <linux/of_gpio.h> 36 + #include <linux/timekeeping.h> 36 37 37 38 #include <linux/iio/iio.h> 38 39 ··· 90 89 return ret; 91 90 } 92 91 93 - static int dht11_decode(struct dht11 *dht11, int offset) 92 + static int dht11_decode(struct dht11 *dht11, int offset, int timeres) 94 93 { 95 - int i, t, timing[DHT11_BITS_PER_READ], threshold, 96 - timeres = DHT11_SENSOR_RESPONSE; 94 + int i, t, timing[DHT11_BITS_PER_READ], threshold; 97 95 unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum; 98 96 99 - /* Calculate timestamp resolution */ 100 - for (i = 1; i < dht11->num_edges; ++i) { 101 - t = dht11->edges[i].ts - dht11->edges[i - 1].ts; 102 - if (t > 0 && t < timeres) 103 - timeres = t; 104 - } 105 - if (2 * timeres > DHT11_DATA_BIT_HIGH) { 106 - pr_err("dht11: timeresolution %d too bad for decoding\n", 107 - timeres); 108 - return -EIO; 109 - } 110 97 threshold = DHT11_DATA_BIT_HIGH / timeres; 111 98 if (DHT11_DATA_BIT_LOW / timeres + 1 >= threshold) 112 99 pr_err("dht11: WARNING: decoding ambiguous\n"); ··· 117 128 if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) 118 129 return -EIO; 119 130 120 - dht11->timestamp = iio_get_time_ns(); 131 + dht11->timestamp = ktime_get_real_ns(); 121 132 if (hum_int < 20) { /* DHT22 */ 122 133 dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) * 123 134 ((temp_int & 0x80) ? -100 : 100); ··· 145 156 146 157 /* TODO: Consider making the handler safe for IRQ sharing */ 147 158 if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) { 148 - dht11->edges[dht11->num_edges].ts = iio_get_time_ns(); 159 + dht11->edges[dht11->num_edges].ts = ktime_get_real_ns(); 149 160 dht11->edges[dht11->num_edges++].value = 150 161 gpio_get_value(dht11->gpio); 151 162 ··· 161 172 int *val, int *val2, long m) 162 173 { 163 174 struct dht11 *dht11 = iio_priv(iio_dev); 164 - int ret; 175 + int ret, timeres; 165 176 166 177 mutex_lock(&dht11->lock); 167 - if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) { 178 + if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) { 179 + timeres = ktime_get_resolution_ns(); 180 + if (DHT11_DATA_BIT_HIGH < 2 * timeres) { 181 + dev_err(dht11->dev, "timeresolution %dns too low\n", 182 + timeres); 183 + /* In theory a better clock could become available 184 + * at some point ... and there is no error code 185 + * that really fits better. 186 + */ 187 + ret = -EAGAIN; 188 + goto err; 189 + } 190 + 168 191 reinit_completion(&dht11->completion); 169 192 170 193 dht11->num_edges = 0; ··· 211 210 ret = dht11_decode(dht11, 212 211 dht11->num_edges == DHT11_EDGES_PER_READ ? 213 212 DHT11_EDGES_PREAMBLE : 214 - DHT11_EDGES_PREAMBLE - 2); 213 + DHT11_EDGES_PREAMBLE - 2, 214 + timeres); 215 215 if (ret) 216 216 goto err; 217 217 } ··· 279 277 return -EINVAL; 280 278 } 281 279 282 - dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1; 280 + dht11->timestamp = ktime_get_real_ns() - DHT11_DATA_VALID_TIME - 1; 283 281 dht11->num_edges = -1; 284 282 285 283 platform_set_drvdata(pdev, iio);