aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/common
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2016-06-29 09:14:42 -0400
committerJonathan Cameron <jic23@kernel.org>2016-07-02 15:40:15 -0400
commit90efe05562921768d34e44c0292703ea3168ba8d (patch)
tree09d4286b51069f1b9595a77bf46fd590afeec2a2 /drivers/iio/common
parentcde4cb5dd4221a3999ea804e85ad3dc48f3f5b78 (diff)
iio: st_sensors: harden interrupt handling
Leonard Crestez observed the following phenomenon: when using hard interrupt triggers (the DRDY line coming out of an ST sensor) sometimes a new value would arrive while reading the previous value, due to latencies in the system. We discovered that the ST hardware as far as can be observed is designed for level interrupts: the DRDY line will be held asserted as long as there are new values coming. The interrupt handler should be re-entered until we're out of values to handle from the sensor. If interrupts were handled as occurring on the edges (usually low-to-high) new values could appear and the line be held asserted after that, and these values would be missed, the interrupt handler would also lock up as new data was available, but as no new edges occurs on the DRDY signal, nothing happens: the edge detector only detects edges. To counter this, do the following: - Accept interrupt lines to be flagged as level interrupts using IRQF_TRIGGER_HIGH and IRQF_TRIGGER_LOW. If the line is marked like this (in the device tree node or ACPI table or similar) it will be utilized as a level IRQ. We mark the line with IRQF_ONESHOT and mask the IRQ while processing a sample, then the top half will be entered again if new values are available. - If we are flagged as using edge interrupts with IRQF_TRIGGER_RISING or IRQF_TRIGGER_FALLING: remove IRQF_ONESHOT so that the interrupt line is not masked while running the thread part of the interrupt. This way we will never miss an interrupt, then introduce a loop that polls the data ready registers repeatedly until no new samples are available, then exit the interrupt handler. This way we know no new values are available when the interrupt handler exits and new (edge) interrupts will be triggered when data arrives. Take some extra care to update the timestamp in the poll loop if this happens. The timestamp will not be 100% perfect, but it will at least be closer to the actual events. Usually the extra poll loop will handle the new samples, but once in a blue moon, we get a new IRQ while exiting the loop, before returning from the thread IRQ bottom half with IRQ_HANDLED. On these rare occasions, the removal of IRQF_ONESHOT means the interrupt will immediately fire again. - If no interrupt type is indicated from the DT/ACPI, choose IRQF_TRIGGER_RISING as default, as this is necessary for legacy boards. Tested successfully on the LIS331DL and L3G4200D by setting sampling frequency to 400Hz/800Hz and stressing the system: extra reads in the threaded interrupt handler occurs. Cc: Giuseppe Barba <giuseppe.barba@st.com> Cc: Denis Ciocca <denis.ciocca@st.com> Tested-by: Crestez Dan Leonard <cdleonard@gmail.com> Reported-by: Crestez Dan Leonard <cdleonard@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/common')
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_buffer.c7
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_trigger.c154
2 files changed, 115 insertions, 46 deletions
diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c
index 7c84e90d8ce8..2371fc875d2d 100644
--- a/drivers/iio/common/st_sensors/st_sensors_buffer.c
+++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c
@@ -58,7 +58,12 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p)
58 struct st_sensor_data *sdata = iio_priv(indio_dev); 58 struct st_sensor_data *sdata = iio_priv(indio_dev);
59 s64 timestamp; 59 s64 timestamp;
60 60
61 /* If we do timetamping here, do it before reading the values */ 61 /*
62 * If we do timetamping here, do it before reading the values, because
63 * once we've read the values, new interrupts can occur (when using
64 * the hardware trigger) and the hw_timestamp may get updated.
65 * By storing it in a local variable first, we are safe.
66 */
62 if (sdata->hw_irq_trigger) 67 if (sdata->hw_irq_trigger)
63 timestamp = sdata->hw_timestamp; 68 timestamp = sdata->hw_timestamp;
64 else 69 else
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
index fab494d71951..e66f12ee8a55 100644
--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
@@ -18,6 +18,50 @@
18#include "st_sensors_core.h" 18#include "st_sensors_core.h"
19 19
20/** 20/**
21 * st_sensors_new_samples_available() - check if more samples came in
22 * returns:
23 * 0 - no new samples available
24 * 1 - new samples available
25 * negative - error or unknown
26 */
27static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
28 struct st_sensor_data *sdata)
29{
30 u8 status;
31 int ret;
32
33 /* How would I know if I can't check it? */
34 if (!sdata->sensor_settings->drdy_irq.addr_stat_drdy)
35 return -EINVAL;
36
37 /* No scan mask, no interrupt */
38 if (!indio_dev->active_scan_mask)
39 return 0;
40
41 ret = sdata->tf->read_byte(&sdata->tb, sdata->dev,
42 sdata->sensor_settings->drdy_irq.addr_stat_drdy,
43 &status);
44 if (ret < 0) {
45 dev_err(sdata->dev,
46 "error checking samples available\n");
47 return ret;
48 }
49 /*
50 * the lower bits of .active_scan_mask[0] is directly mapped
51 * to the channels on the sensor: either bit 0 for
52 * one-dimensional sensors, or e.g. x,y,z for accelerometers,
53 * gyroscopes or magnetometers. No sensor use more than 3
54 * channels, so cut the other status bits here.
55 */
56 status &= 0x07;
57
58 if (status & (u8)indio_dev->active_scan_mask[0])
59 return 1;
60
61 return 0;
62}
63
64/**
21 * st_sensors_irq_handler() - top half of the IRQ-based triggers 65 * st_sensors_irq_handler() - top half of the IRQ-based triggers
22 * @irq: irq number 66 * @irq: irq number
23 * @p: private handler data 67 * @p: private handler data
@@ -43,44 +87,43 @@ irqreturn_t st_sensors_irq_thread(int irq, void *p)
43 struct iio_trigger *trig = p; 87 struct iio_trigger *trig = p;
44 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 88 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
45 struct st_sensor_data *sdata = iio_priv(indio_dev); 89 struct st_sensor_data *sdata = iio_priv(indio_dev);
46 int ret;
47 90
48 /* 91 /*
49 * If this trigger is backed by a hardware interrupt and we have a 92 * If this trigger is backed by a hardware interrupt and we have a
50 * status register, check if this IRQ came from us 93 * status register, check if this IRQ came from us. Notice that
94 * we will process also if st_sensors_new_samples_available()
95 * returns negative: if we can't check status, then poll
96 * unconditionally.
51 */ 97 */
52 if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) { 98 if (sdata->hw_irq_trigger &&
53 u8 status; 99 st_sensors_new_samples_available(indio_dev, sdata)) {
54 100 iio_trigger_poll_chained(p);
55 ret = sdata->tf->read_byte(&sdata->tb, sdata->dev, 101 } else {
56 sdata->sensor_settings->drdy_irq.addr_stat_drdy, 102 dev_dbg(sdata->dev, "spurious IRQ\n");
57 &status); 103 return IRQ_NONE;
58 if (ret < 0) { 104 }
59 dev_err(sdata->dev, "could not read channel status\n");
60 goto out_poll;
61 }
62 /*
63 * the lower bits of .active_scan_mask[0] is directly mapped
64 * to the channels on the sensor: either bit 0 for
65 * one-dimensional sensors, or e.g. x,y,z for accelerometers,
66 * gyroscopes or magnetometers. No sensor use more than 3
67 * channels, so cut the other status bits here.
68 */
69 status &= 0x07;
70 105
71 /* 106 /*
72 * If this was not caused by any channels on this sensor, 107 * If we have proper level IRQs the handler will be re-entered if
73 * return IRQ_NONE 108 * the line is still active, so return here and come back in through
74 */ 109 * the top half if need be.
75 if (!indio_dev->active_scan_mask) 110 */
76 return IRQ_NONE; 111 if (!sdata->edge_irq)
77 if (!(status & (u8)indio_dev->active_scan_mask[0])) 112 return IRQ_HANDLED;
78 return IRQ_NONE; 113
114 /*
115 * If we are using egde IRQs, new samples arrived while processing
116 * the IRQ and those may be missed unless we pick them here, so poll
117 * again. If the sensor delivery frequency is very high, this thread
118 * turns into a polled loop handler.
119 */
120 while (sdata->hw_irq_trigger &&
121 st_sensors_new_samples_available(indio_dev, sdata)) {
122 dev_dbg(sdata->dev, "more samples came in during polling\n");
123 sdata->hw_timestamp = iio_get_time_ns(indio_dev);
124 iio_trigger_poll_chained(p);
79 } 125 }
80 126
81out_poll:
82 /* It's our IRQ: proceed to handle the register polling */
83 iio_trigger_poll_chained(p);
84 return IRQ_HANDLED; 127 return IRQ_HANDLED;
85} 128}
86 129
@@ -107,13 +150,18 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
107 * If the IRQ is triggered on falling edge, we need to mark the 150 * If the IRQ is triggered on falling edge, we need to mark the
108 * interrupt as active low, if the hardware supports this. 151 * interrupt as active low, if the hardware supports this.
109 */ 152 */
110 if (irq_trig == IRQF_TRIGGER_FALLING) { 153 switch(irq_trig) {
154 case IRQF_TRIGGER_FALLING:
155 case IRQF_TRIGGER_LOW:
111 if (!sdata->sensor_settings->drdy_irq.addr_ihl) { 156 if (!sdata->sensor_settings->drdy_irq.addr_ihl) {
112 dev_err(&indio_dev->dev, 157 dev_err(&indio_dev->dev,
113 "falling edge specified for IRQ but hardware " 158 "falling/low specified for IRQ "
114 "only support rising edge, will request " 159 "but hardware only support rising/high: "
115 "rising edge\n"); 160 "will request rising/high\n");
116 irq_trig = IRQF_TRIGGER_RISING; 161 if (irq_trig == IRQF_TRIGGER_FALLING)
162 irq_trig = IRQF_TRIGGER_RISING;
163 if (irq_trig == IRQF_TRIGGER_LOW)
164 irq_trig = IRQF_TRIGGER_HIGH;
117 } else { 165 } else {
118 /* Set up INT active low i.e. falling edge */ 166 /* Set up INT active low i.e. falling edge */
119 err = st_sensors_write_data_with_mask(indio_dev, 167 err = st_sensors_write_data_with_mask(indio_dev,
@@ -122,20 +170,39 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
122 if (err < 0) 170 if (err < 0)
123 goto iio_trigger_free; 171 goto iio_trigger_free;
124 dev_info(&indio_dev->dev, 172 dev_info(&indio_dev->dev,
125 "interrupts on the falling edge\n"); 173 "interrupts on the falling edge or "
174 "active low level\n");
126 } 175 }
127 } else if (irq_trig == IRQF_TRIGGER_RISING) { 176 break;
177 case IRQF_TRIGGER_RISING:
128 dev_info(&indio_dev->dev, 178 dev_info(&indio_dev->dev,
129 "interrupts on the rising edge\n"); 179 "interrupts on the rising edge\n");
130 180 break;
131 } else { 181 case IRQF_TRIGGER_HIGH:
182 dev_info(&indio_dev->dev,
183 "interrupts active high level\n");
184 break;
185 default:
186 /* This is the most preferred mode, if possible */
132 dev_err(&indio_dev->dev, 187 dev_err(&indio_dev->dev,
133 "unsupported IRQ trigger specified (%lx), only " 188 "unsupported IRQ trigger specified (%lx), enforce "
134 "rising and falling edges supported, enforce "
135 "rising edge\n", irq_trig); 189 "rising edge\n", irq_trig);
136 irq_trig = IRQF_TRIGGER_RISING; 190 irq_trig = IRQF_TRIGGER_RISING;
137 } 191 }
138 192
193 /* Tell the interrupt handler that we're dealing with edges */
194 if (irq_trig == IRQF_TRIGGER_FALLING ||
195 irq_trig == IRQF_TRIGGER_RISING)
196 sdata->edge_irq = true;
197 else
198 /*
199 * If we're not using edges (i.e. level interrupts) we
200 * just mask off the IRQ, handle one interrupt, then
201 * if the line is still low, we return to the
202 * interrupt handler top half again and start over.
203 */
204 irq_trig |= IRQF_ONESHOT;
205
139 /* 206 /*
140 * If the interrupt pin is Open Drain, by definition this 207 * If the interrupt pin is Open Drain, by definition this
141 * means that the interrupt line may be shared with other 208 * means that the interrupt line may be shared with other
@@ -148,9 +215,6 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
148 sdata->sensor_settings->drdy_irq.addr_stat_drdy) 215 sdata->sensor_settings->drdy_irq.addr_stat_drdy)
149 irq_trig |= IRQF_SHARED; 216 irq_trig |= IRQF_SHARED;
150 217
151 /* Let's create an interrupt thread masking the hard IRQ here */
152 irq_trig |= IRQF_ONESHOT;
153
154 err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev), 218 err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev),
155 st_sensors_irq_handler, 219 st_sensors_irq_handler,
156 st_sensors_irq_thread, 220 st_sensors_irq_thread,