linux/drivers/iio
Linus Walleij 90efe05562 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>
2016-07-02 20:40:15 +01:00
..
accel iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
adc iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
amplifiers spi: Updates for v4.4 2015-11-05 13:15:12 -08:00
buffer iio: buffer-dma: Use ARRAY_SIZE in for loop range 2016-06-27 21:06:40 +01:00
chemical iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
common iio: st_sensors: harden interrupt handling 2016-07-02 20:40:15 +01:00
dac iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
dummy iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
frequency iio: frequency: ad9523: use unsigned int rather then bare unsigned 2016-04-17 10:31:03 +01:00
gyro iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
health First round of IIO new device support, features and cleanups for the 4.8 cycle. 2016-06-09 09:15:58 -07:00
humidity Merge 4.7-rc4 into staging-next 2016-06-20 08:25:44 -07:00
imu iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
light iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
magnetometer iio: magn: ak8975: deploy runtime and system PM 2016-06-30 20:40:16 +01:00
orientation iio: orientation: hid-sensor-rotation: Fix memory leak in probe() 2015-05-17 09:10:25 +01:00
potentiometer iio: max5487: Add support for Maxim digital potentiometers 2016-05-21 20:13:14 +01:00
pressure iio: pressure: bmp280: add reset GPIO line handling 2016-06-30 20:39:40 +01:00
proximity iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
temperature iio: Export I2C module alias information 2016-05-21 20:08:14 +01:00
trigger iio:trigger: Experimental kthread tight loop trigger (thread only) 2016-06-03 13:18:44 +01:00
iio_core_trigger.h
iio_core.h iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
industrialio-buffer.c iio: fix config watermark initial value 2016-03-28 11:00:38 +01:00
industrialio-configfs.c iio:configfs: Introduce iio/configfs.h to provide a location for the configfs_subsystem 2015-12-05 16:25:30 +00:00
industrialio-core.c iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
industrialio-event.c iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
industrialio-sw-device.c iio: Add support for creating IIO devices via configfs 2016-05-04 11:43:54 +01:00
industrialio-sw-trigger.c iio: core: fix ptr_ret.cocci warnings 2016-01-20 17:09:18 -08:00
industrialio-trigger.c iio:core: timestamping clock selection support 2016-06-30 19:41:38 +01:00
industrialio-triggered-event.c iio: Support triggered events 2015-08-27 20:47:09 +01:00
inkern.c iio: core: Add devm_ APIs for iio_channel_{get,release}_all 2016-04-19 19:58:15 +01:00
Kconfig iio: Add support for creating IIO devices via configfs 2016-05-04 11:43:54 +01:00
Makefile iio: Add support for creating IIO devices via configfs 2016-05-04 11:43:54 +01:00