From: Tabrez Ahmed Date: Sat, 2 May 2026 02:08:44 +0000 (+0530) Subject: hwmon: (ads7871) Use DMA-safe buffer for SPI writes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b46e1a0bff3343ad8a50a5d9cdb56a3847ba69ef;p=thirdparty%2Flinux.git hwmon: (ads7871) Use DMA-safe buffer for SPI writes The driver currently passes a stack-allocated buffer to spi_write(), which is incompatible with DMA on systems with CONFIG_VMAP_STACK enabled. Move the transfer buffer into the driver's private data structure to ensure it is DMA-safe. Since this shared buffer now requires serialization, this change depends on the previous commit which migrated the driver to the hwmon 'with_info' API. While moving the logic, also: - Corrected the sign extension for 14-bit data by casting to s16. - Scaled the output to millivolts (2500mV full scale ) to comply with the hwmon ABI. Signed-off-by: Tabrez Ahmed Link: https://lore.kernel.org/r/20260502020844.110038-4-tabreztalks@gmail.com Signed-off-by: Guenter Roeck --- diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c index 805b3657362d1..d1cbff0e85720 100644 --- a/drivers/hwmon/ads7871.c +++ b/drivers/hwmon/ads7871.c @@ -63,6 +63,7 @@ struct ads7871_data { struct spi_device *spi; + u8 tx_buf[2] ____cacheline_aligned; }; static umode_t ads7871_is_visible(const void *data, @@ -95,11 +96,12 @@ static int ads7871_read_reg16(struct spi_device *spi, int reg) return le16_to_cpu((__force __le16)ret); } -static int ads7871_write_reg8(struct spi_device *spi, int reg, u8 val) +static int ads7871_write_reg8(struct ads7871_data *pdata, int reg, u8 val) { - u8 tmp[2] = {reg, val}; + pdata->tx_buf[0] = reg; + pdata->tx_buf[1] = val; - return spi_write(spi, tmp, sizeof(tmp)); + return spi_write(pdata->spi, pdata->tx_buf, 2); } static int ads7871_read(struct device *dev, enum hwmon_sensor_types type, @@ -118,7 +120,7 @@ static int ads7871_read(struct device *dev, enum hwmon_sensor_types type, */ /*MUX_M3_BM forces single ended*/ /*This is also where the gain of the PGA would be set*/ - ret = ads7871_write_reg8(spi, REG_GAIN_MUX, + ret = ads7871_write_reg8(pdata, REG_GAIN_MUX, (MUX_CNV_BM | MUX_M3_BM | channel)); if (ret < 0) return ret; @@ -126,6 +128,7 @@ static int ads7871_read(struct device *dev, enum hwmon_sensor_types type, ret = ads7871_read_reg8(spi, REG_GAIN_MUX); if (ret < 0) return ret; + mux_cnv = ((ret & MUX_CNV_BM) >> MUX_CNV_BV); /* * on 400MHz arm9 platform the conversion @@ -145,8 +148,11 @@ static int ads7871_read(struct device *dev, enum hwmon_sensor_types type, if (raw_val < 0) return raw_val; - /*result in volts*10000 = (val/8192)*2.5*10000*/ - *val = ((raw_val >> 2) * 25000) / 8192; + /* + * Use (s16) to ensure the sign bit is preserved during the shift. + * Report millivolts (2.5V = 2500mV). + */ + *val = ((s16)raw_val >> 2) * 2500 / 8192; return 0; } @@ -183,11 +189,17 @@ static int ads7871_probe(struct spi_device *spi) spi->bits_per_word = 8; spi_setup(spi); - ads7871_write_reg8(spi, REG_SER_CONTROL, 0); - ads7871_write_reg8(spi, REG_AD_CONTROL, 0); + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->spi = spi; + + ads7871_write_reg8(pdata, REG_SER_CONTROL, 0); + ads7871_write_reg8(pdata, REG_AD_CONTROL, 0); val = (OSC_OSCR_BM | OSC_OSCE_BM | OSC_REFE_BM | OSC_BUFE_BM); - ads7871_write_reg8(spi, REG_OSC_CONTROL, val); + ads7871_write_reg8(pdata, REG_OSC_CONTROL, val); ret = ads7871_read_reg8(spi, REG_OSC_CONTROL); dev_dbg(dev, "REG_OSC_CONTROL write:%x, read:%x\n", val, ret); @@ -198,11 +210,6 @@ static int ads7871_probe(struct spi_device *spi) if (val != ret) return -ENODEV; - pdata = devm_kzalloc(dev, sizeof(struct ads7871_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - pdata->spi = spi; hwmon_dev = devm_hwmon_device_register_with_info(dev, spi->modalias, pdata, &ads7871_chip_info,