From 787e1853ae8a951233ceab1b01c862d9c668358b Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 8 Jan 2018 07:47:36 +0100 Subject: [PATCH 1/7] iio: adc: aspeed: Fix error handling path The labels and branching order of the error path of 'aspeed_adc_probe()' are broken. Re-order the labels and goto statements. Signed-off-by: Christophe JAILLET Signed-off-by: Jonathan Cameron --- drivers/iio/adc/aspeed_adc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index 327a49ba1991..9515ca165dfd 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -243,7 +243,7 @@ static int aspeed_adc_probe(struct platform_device *pdev) ASPEED_ADC_INIT_POLLING_TIME, ASPEED_ADC_INIT_TIMEOUT); if (ret) - goto scaler_error; + goto poll_timeout_error; } /* Start all channels in normal mode. */ @@ -274,9 +274,10 @@ iio_register_error: writel(ASPEED_OPERATION_MODE_POWER_DOWN, data->base + ASPEED_REG_ENGINE_CONTROL); clk_disable_unprepare(data->clk_scaler->clk); -reset_error: - reset_control_assert(data->rst); clk_enable_error: +poll_timeout_error: + reset_control_assert(data->rst); +reset_error: clk_hw_unregister_divider(data->clk_scaler); scaler_error: clk_hw_unregister_divider(data->clk_prescaler); From e31b617d0a63c6558485aaa730fd162faa95a766 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 22 Jan 2018 11:53:12 +0200 Subject: [PATCH 2/7] staging: iio: adc: ad7192: fix external frequency setting The external clock frequency was set only when selecting the internal clock, which is fixed at 4.9152 Mhz. This is incorrect, since it should be set when any of the external clock or crystal settings is selected. Added range validation for the external (crystal/clock) frequency setting. Valid values are between 2.4576 and 5.12 Mhz. Signed-off-by: Alexandru Ardelean Cc: Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index f01595593ce2..425e8b82533b 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -141,6 +141,8 @@ #define AD7192_GPOCON_P1DAT BIT(1) /* P1 state */ #define AD7192_GPOCON_P0DAT BIT(0) /* P0 state */ +#define AD7192_EXT_FREQ_MHZ_MIN 2457600 +#define AD7192_EXT_FREQ_MHZ_MAX 5120000 #define AD7192_INT_FREQ_MHZ 4915200 /* NOTE: @@ -218,6 +220,12 @@ static int ad7192_calibrate_all(struct ad7192_state *st) ARRAY_SIZE(ad7192_calib_arr)); } +static inline bool ad7192_valid_external_frequency(u32 freq) +{ + return (freq >= AD7192_EXT_FREQ_MHZ_MIN && + freq <= AD7192_EXT_FREQ_MHZ_MAX); +} + static int ad7192_setup(struct ad7192_state *st, const struct ad7192_platform_data *pdata) { @@ -243,17 +251,20 @@ static int ad7192_setup(struct ad7192_state *st, id); switch (pdata->clock_source_sel) { - case AD7192_CLK_EXT_MCLK1_2: - case AD7192_CLK_EXT_MCLK2: - st->mclk = AD7192_INT_FREQ_MHZ; - break; case AD7192_CLK_INT: case AD7192_CLK_INT_CO: - if (pdata->ext_clk_hz) - st->mclk = pdata->ext_clk_hz; - else - st->mclk = AD7192_INT_FREQ_MHZ; + st->mclk = AD7192_INT_FREQ_MHZ; break; + case AD7192_CLK_EXT_MCLK1_2: + case AD7192_CLK_EXT_MCLK2: + if (ad7192_valid_external_frequency(pdata->ext_clk_hz)) { + st->mclk = pdata->ext_clk_hz; + break; + } + dev_err(&st->sd.spi->dev, "Invalid frequency setting %u\n", + pdata->ext_clk_hz); + ret = -EINVAL; + goto out; default: ret = -EINVAL; goto out; From a3b5655ebdb501a98a45c0d3265dca9f2fe0218a Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Tue, 23 Jan 2018 17:04:56 +0100 Subject: [PATCH 3/7] iio: adc: stm32: fix stm32h7_adc_enable error handling Error handling in stm32h7_adc_enable routine doesn't unwind enable sequence correctly. ADEN can only be cleared by hardware (e.g. by writing one to ADDIS). It's also better to clear ADRDY just after it's been set by hardware. Fixes: 95e339b6e85d ("iio: adc: stm32: add support for STM32H7") Signed-off-by: Fabrice Gasnier Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 7f5def465340..9a2583caedaa 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -722,8 +722,6 @@ static int stm32h7_adc_enable(struct stm32_adc *adc) int ret; u32 val; - /* Clear ADRDY by writing one, then enable ADC */ - stm32_adc_set_bits(adc, STM32H7_ADC_ISR, STM32H7_ADRDY); stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN); /* Poll for ADRDY to be set (after adc startup time) */ @@ -731,8 +729,11 @@ static int stm32h7_adc_enable(struct stm32_adc *adc) val & STM32H7_ADRDY, 100, STM32_ADC_TIMEOUT_US); if (ret) { - stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN); + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS); dev_err(&indio_dev->dev, "Failed to enable ADC\n"); + } else { + /* Clear ADRDY by writing one */ + stm32_adc_set_bits(adc, STM32H7_ADC_ISR, STM32H7_ADRDY); } return ret; From 7d2b8e6aaf9ee87910c2337e1c59bb5d3e3ba8c5 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Thu, 25 Jan 2018 14:30:45 +0200 Subject: [PATCH 4/7] staging: iio: ad5933: switch buffer mode to software Since commit 152a6a884ae1 ("staging:iio:accel:sca3000 move to hybrid hard / soft buffer design.") the buffer mechanism has changed and the INDIO_BUFFER_HARDWARE flag has been unused. Since commit 2d6ca60f3284 ("iio: Add a DMAengine framework based buffer") the INDIO_BUFFER_HARDWARE flag has been re-purposed for DMA buffers. This driver has lagged behind these changes, and in order for buffers to work, the INDIO_BUFFER_SOFTWARE needs to be used. Signed-off-by: Alexandru Ardelean Fixes: 2d6ca60f3284 ("iio: Add a DMAengine framework based buffer") Cc: Signed-off-by: Jonathan Cameron --- drivers/staging/iio/impedance-analyzer/ad5933.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 2b28fb9c0048..3bcf49466361 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -648,8 +648,6 @@ static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) /* Ring buffer functions - here trigger setup related */ indio_dev->setup_ops = &ad5933_ring_setup_ops; - indio_dev->modes |= INDIO_BUFFER_HARDWARE; - return 0; } @@ -762,7 +760,7 @@ static int ad5933_probe(struct i2c_client *client, indio_dev->dev.parent = &client->dev; indio_dev->info = &ad5933_info; indio_dev->name = id->name; - indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE); indio_dev->channels = ad5933_channels; indio_dev->num_channels = ARRAY_SIZE(ad5933_channels); From 511051d509ec54642dd6d30fdf2caa33c23619cc Mon Sep 17 00:00:00 2001 From: Andreas Klinger Date: Thu, 1 Feb 2018 21:49:24 +0100 Subject: [PATCH 5/7] iio: srf08: fix link error "devm_iio_triggered_buffer_setup" undefined Functions for triggered buffer support are needed by this module. If they are not defined accidentally by another driver, there's an error thrown out while linking. Add a select of IIO_BUFFER and IIO_TRIGGERED_BUFFER in the Kconfig file. Signed-off-by: Andreas Klinger Fixes: a83195937151 ("iio: srf08: add triggered buffer support") Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index fcb1c4ba5e41..f726f9427602 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -68,6 +68,8 @@ config SX9500 config SRF08 tristate "Devantech SRF02/SRF08/SRF10 ultrasonic ranger sensor" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER depends on I2C help Say Y here to build a driver for Devantech SRF02/SRF08/SRF10 From f027e0b3a774e10302207e91d304bbf99e3a8b36 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 14 Feb 2018 15:43:00 +0100 Subject: [PATCH 6/7] iio: adis_lib: Initialize trigger before requesting interrupt The adis_probe_trigger() creates a new IIO trigger and requests an interrupt associated with the trigger. The interrupt uses the generic iio_trigger_generic_data_rdy_poll() function as its interrupt handler. Currently the driver initializes some fields of the trigger structure after the interrupt has been requested. But an interrupt can fire as soon as it has been requested. This opens up a race condition. iio_trigger_generic_data_rdy_poll() will access the trigger data structure and dereference the ops field. If the ops field is not yet initialized this will result in a NULL pointer deref. It is not expected that the device generates an interrupt at this point, so typically this issue did not surface unless e.g. due to a hardware misconfiguration (wrong interrupt number, wrong polarity, etc.). But some newer devices from the ADIS family start to generate periodic interrupts in their power-on reset configuration and unfortunately the interrupt can not be masked in the device. This makes the race condition much more visible and the following crash has been observed occasionally when booting a system using the ADIS16460. Unable to handle kernel NULL pointer dereference at virtual address 00000008 pgd = c0004000 [00000008] *pgd=00000000 Internal error: Oops: 5 [#1] PREEMPT SMP ARM Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.9.0-04126-gf9739f0-dirty #257 Hardware name: Xilinx Zynq Platform task: ef04f640 task.stack: ef050000 PC is at iio_trigger_notify_done+0x30/0x68 LR is at iio_trigger_generic_data_rdy_poll+0x18/0x20 pc : [] lr : [] psr: 60000193 sp : ef051bb8 ip : 00000000 fp : ef106400 r10: c081d80a r9 : ef3bfa00 r8 : 00000087 r7 : ef051bec r6 : 00000000 r5 : ef3bfa00 r4 : ee92ab00 r3 : 00000000 r2 : 00000000 r1 : 00000000 r0 : ee97e400 Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment none Control: 18c5387d Table: 0000404a DAC: 00000051 Process swapper/0 (pid: 1, stack limit = 0xef050210) [] (iio_trigger_notify_done) from [] (__handle_irq_event_percpu+0x88/0x118) [] (__handle_irq_event_percpu) from [] (handle_irq_event_percpu+0x1c/0x58) [] (handle_irq_event_percpu) from [] (handle_irq_event+0x38/0x5c) [] (handle_irq_event) from [] (handle_level_irq+0xa4/0x130) [] (handle_level_irq) from [] (generic_handle_irq+0x24/0x34) [] (generic_handle_irq) from [] (zynq_gpio_irqhandler+0xb8/0x13c) [] (zynq_gpio_irqhandler) from [] (generic_handle_irq+0x24/0x34) [] (generic_handle_irq) from [] (__handle_domain_irq+0x5c/0xb4) [] (__handle_domain_irq) from [] (gic_handle_irq+0x48/0x8c) [] (gic_handle_irq) from [] (__irq_svc+0x6c/0xa8) To fix this make sure that the trigger is fully initialized before requesting the interrupt. Fixes: ccd2b52f4ac6 ("staging:iio: Add common ADIS library") Reported-by: Robin Getz Signed-off-by: Lars-Peter Clausen Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis_trigger.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c index 0dd5a381be64..457372f36791 100644 --- a/drivers/iio/imu/adis_trigger.c +++ b/drivers/iio/imu/adis_trigger.c @@ -46,6 +46,10 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) if (adis->trig == NULL) return -ENOMEM; + adis->trig->dev.parent = &adis->spi->dev; + adis->trig->ops = &adis_trigger_ops; + iio_trigger_set_drvdata(adis->trig, adis); + ret = request_irq(adis->spi->irq, &iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, @@ -54,9 +58,6 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) if (ret) goto error_free_trig; - adis->trig->dev.parent = &adis->spi->dev; - adis->trig->ops = &adis_trigger_ops; - iio_trigger_set_drvdata(adis->trig, adis); ret = iio_trigger_register(adis->trig); indio_dev->trig = iio_trigger_get(adis->trig); From 4cd140bda6494543f1c1b0ccceceaa44b676eef6 Mon Sep 17 00:00:00 2001 From: Stefan Windfeldt-Prytz Date: Thu, 15 Feb 2018 15:02:53 +0100 Subject: [PATCH 7/7] iio: buffer: check if a buffer has been set up when poll is called If no iio buffer has been set up and poll is called return 0. Without this check there will be a null pointer dereference when calling poll on a iio driver without an iio buffer. Cc: stable@vger.kernel.org Signed-off-by: Stefan Windfeldt-Prytz Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index eda2a0f1658f..c7499c8bd69f 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -175,7 +175,7 @@ unsigned int iio_buffer_poll(struct file *filp, struct iio_dev *indio_dev = filp->private_data; struct iio_buffer *rb = indio_dev->buffer; - if (!indio_dev->info) + if (!indio_dev->info || rb == NULL) return 0; poll_wait(filp, &rb->pollq, wait);