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

Configure Feed

Select the types of activity you want to include in your feed.

iio: ad_sigma_delta: Don't put SPI transfer buffer on the stack

Use a heap allocated memory for the SPI transfer buffer. Using stack memory
can corrupt stack memory when using DMA on some systems.

This change moves the buffer from the stack of the trigger handler call to
the heap of the buffer of the state struct. The size increases takes into
account the alignment for the timestamp, which is 8 bytes.

The 'data' buffer is split into 'tx_buf' and 'rx_buf', to make a clearer
separation of which part of the buffer should be used for TX & RX.

Fixes: af3008485ea03 ("iio:adc: Add common code for ADI Sigma Delta devices")
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Link: https://lore.kernel.org/r/20201124123807.19717-1-alexandru.ardelean@analog.com
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Lars-Peter Clausen and committed by
Jonathan Cameron
0fb6ee8d 6d74a3ee

+13 -11
+8 -10
drivers/iio/adc/ad_sigma_delta.c
··· 57 57 int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg, 58 58 unsigned int size, unsigned int val) 59 59 { 60 - uint8_t *data = sigma_delta->data; 60 + uint8_t *data = sigma_delta->tx_buf; 61 61 struct spi_transfer t = { 62 62 .tx_buf = data, 63 63 .len = size + 1, ··· 99 99 static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta, 100 100 unsigned int reg, unsigned int size, uint8_t *val) 101 101 { 102 - uint8_t *data = sigma_delta->data; 102 + uint8_t *data = sigma_delta->tx_buf; 103 103 int ret; 104 104 struct spi_transfer t[] = { 105 105 { ··· 146 146 { 147 147 int ret; 148 148 149 - ret = ad_sd_read_reg_raw(sigma_delta, reg, size, sigma_delta->data); 149 + ret = ad_sd_read_reg_raw(sigma_delta, reg, size, sigma_delta->rx_buf); 150 150 if (ret < 0) 151 151 goto out; 152 152 153 153 switch (size) { 154 154 case 4: 155 - *val = get_unaligned_be32(sigma_delta->data); 155 + *val = get_unaligned_be32(sigma_delta->rx_buf); 156 156 break; 157 157 case 3: 158 - *val = get_unaligned_be24(&sigma_delta->data[0]); 158 + *val = get_unaligned_be24(sigma_delta->rx_buf); 159 159 break; 160 160 case 2: 161 - *val = get_unaligned_be16(sigma_delta->data); 161 + *val = get_unaligned_be16(sigma_delta->rx_buf); 162 162 break; 163 163 case 1: 164 - *val = sigma_delta->data[0]; 164 + *val = sigma_delta->rx_buf[0]; 165 165 break; 166 166 default: 167 167 ret = -EINVAL; ··· 395 395 struct iio_poll_func *pf = p; 396 396 struct iio_dev *indio_dev = pf->indio_dev; 397 397 struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); 398 + uint8_t *data = sigma_delta->rx_buf; 398 399 unsigned int reg_size; 399 400 unsigned int data_reg; 400 - uint8_t data[16]; 401 - 402 - memset(data, 0x00, 16); 403 401 404 402 reg_size = indio_dev->channels[0].scan_type.realbits + 405 403 indio_dev->channels[0].scan_type.shift;
+5 -1
include/linux/iio/adc/ad_sigma_delta.h
··· 79 79 /* 80 80 * DMA (thus cache coherency maintenance) requires the 81 81 * transfer buffers to live in their own cache lines. 82 + * 'tx_buf' is up to 32 bits. 83 + * 'rx_buf' is up to 32 bits per sample + 64 bit timestamp, 84 + * rounded to 16 bytes to take into account padding. 82 85 */ 83 - uint8_t data[4] ____cacheline_aligned; 86 + uint8_t tx_buf[4] ____cacheline_aligned; 87 + uint8_t rx_buf[16] __aligned(8); 84 88 }; 85 89 86 90 static inline int ad_sigma_delta_set_channel(struct ad_sigma_delta *sd,