Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions drivers/iio/adc/ad_sigma_delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@
}
EXPORT_SYMBOL_NS_GPL(ad_sd_reset, IIO_AD_SIGMA_DELTA);

static bool ad_sd_disable_irq(struct ad_sigma_delta *sigma_delta)

Check warning on line 208 in drivers/iio/adc/ad_sigma_delta.c

View workflow job for this annotation

GitHub Actions / build_gcc_arm / build

kernel_sparse: context imbalance in 'ad_sd_disable_irq' - wrong count at exit
{
guard(spinlock_irqsave)(&sigma_delta->irq_lock);

Expand Down Expand Up @@ -246,23 +246,50 @@

/*
* Read R̅D̅Y̅ pin (if possible) or status register to check if there is an
* old event.
* old event. For devices with neither an RDY GPIO nor registers,
* ad_sd_read_reg() transmits no address byte and clocks raw MISO bytes,
* which is indistinguishable from reading conversion data and would
* partially consume a pending result. Skip the check for such devices.
*
* This is safe for all current registerless devices: ad7191 and ad7780
* (with powerdown GPIO) are reset between conversions by CS deassertion,
* so there is no stale result to drain; ad7780 (without powerdown GPIO)
* and max11205 are continuously-converting and cycle ~DRDY at the output
* data rate regardless of whether the previous result was read, so the
* next falling edge fires naturally.
*
* A future registerless device that holds ~DRDY asserted until data is
* read would be broken by this early return and would need either
* num_resetclks set or a rdy-gpio.
*/
if (sigma_delta->rdy_gpiod) {
pending_event = gpiod_get_value(sigma_delta->rdy_gpiod);
} else {
} else if (sigma_delta->info->has_registers) {
unsigned status_reg;

ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_STATUS, 1, &status_reg);
if (ret)
return ret;

pending_event = !(status_reg & AD_SD_REG_STATUS_RDY);
} else {
return 0;
}

if (!pending_event)
return 0;

/*
* With num_resetclks = 0, data_read_len is 0 and the drain sequence
* below would compute memset(data + 2, 0xff, 0 - 1), underflowing to
* SIZE_MAX and corrupting the heap. There is no safe way to drain the
* stale result without knowing the data register size; it will be
* consumed by the first ad_sd_read_reg() call in
* ad_sigma_delta_single_conversion().
*/
if (!data_read_len)
return 0;

/*
* In general the size of the data register is unknown. It varies from
* device to device, might be one byte longer if CONTROL.DATA_STATUS is
Expand Down Expand Up @@ -428,11 +455,10 @@
out:
ad_sd_disable_irq(sigma_delta);

ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
ad_sigma_delta_disable_one(sigma_delta, chan->address);

out_unlock:
sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
ad_sigma_delta_disable_one(sigma_delta, chan->address);
sigma_delta->bus_locked = false;
spi_bus_unlock(sigma_delta->spi->controller);
out_release:
Expand Down Expand Up @@ -572,6 +598,9 @@
return 0;

err_unlock:
sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
sigma_delta->bus_locked = false;
spi_bus_unlock(sigma_delta->spi->controller);

return ret;
Expand Down Expand Up @@ -662,7 +691,7 @@
if (sigma_delta->status_appended) {
u8 converted_channel;

converted_channel = data[status_pos] & sigma_delta->info->status_ch_mask;

Check warning on line 694 in drivers/iio/adc/ad_sigma_delta.c

View workflow job for this annotation

GitHub Actions / build_gcc_arm / build

gcc_fanalayzer: use of uninitialized value ‘status_pos’ [CWE-457] [-Wanalyzer-use-of-uninitialized-value] 694 | converted_channel = data[status_pos] & sigma_delta->info->status_ch_mask; | ^ ‘ad_sd_trigger_handler’: events 1-9 | | 642 | unsigned int status_pos; | | ^~~~~~~~~~ | | | | | (1) region created on stack here | | (2) capacity: 4 bytes |...... | 661 | switch (reg_size) { | | ~~~~~~ | | | | | (3) following ‘default:’ branch... |...... | 686 | if (sigma_delta->active_slots == 1) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | | | (4) ...to here | | (5) following ‘false’ branch... |...... | 691 | if (sigma_delta->status_appended) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | | | (6) ...to here | | (7) following ‘true’ branch... |...... | 694 | converted_channel = data[status_pos] & sigma_delta->info->status_ch_mask; | | ~ | | | | | (8) ...to here | | (9) use of uninitialized value ‘status_pos’ here |

Check warning on line 694 in drivers/iio/adc/ad_sigma_delta.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Array subscript is undefined [core.uninitialized.ArraySubscript] 694 | converted_channel = data[status_pos] & sigma_delta->info->status_ch_mask; | ^ ~~~~~~~~~~
if (converted_channel != sigma_delta->slots[sigma_delta->current_slot]) {
/*
* Desync occurred during continuous sampling of multiple channels.
Expand Down
Loading