Skip to content

Commit

Permalink
Merge tag 'iio-fixes-for-5.8a' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/jic23/iio into staging-linus

Jonathan writes:

First set of IIO and counter fixes in the 5.8 cycle.

The buffer alignment fixes continue to trickle through as we get
reviews in.  The rest are the standard mixed bag of long term issues
just discovered an things we missed in this cycle.

IIO fixes

* core
  - Add missing IIO_MOD_H2 and ETHANOL strings. Somehow got missed
    when drivers were added using these in attribute names.
* afe4403, afe4404, ak8974, hdc100x, hts221, ms5611
  - Fix a recently identified issue with alignment when using
    iio_push_to_buffers_with_timestamp which assumes the timestamp
    is 8 byte aligned.
* ad7780
  - Fix a some premature / excess cleanup in an error path.
* adi-axi-adc
  - Fix reference counting on the wrong object.
* ak8974
  - Fix unbalance runtime pm.
* mma8452
  - Fix missing iio_device_unregister in error path.
* zp2326
  - Error handling for pm_runtime_get_sync failing.

counter fixes
* Add lock guards in 104-quad-8 to protect against races - done
  in 2 patches to allow easy back porting.

* tag 'iio-fixes-for-5.8a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio:
  iio: adc: ad7780: Fix a resource handling path in 'ad7780_probe()'
  iio:pressure:ms5611 Fix buffer element alignment
  iio:humidity:hts221 Fix alignment and data leak issues
  iio:humidity:hdc100x Fix alignment and data leak issues
  iio:magnetometer:ak8974: Fix alignment and data leak issues
  iio: adc: adi-axi-adc: Fix object reference counting
  iio: pressure: zpa2326: handle pm_runtime_get_sync failure
  counter: 104-quad-8: Add lock guards - filter clock prescaler
  counter: 104-quad-8: Add lock guards - differential encoder
  iio: core: add missing IIO_MOD_H2/ETHANOL string identifiers
  iio: magnetometer: ak8974: Fix runtime PM imbalance on error
  iio: mma8452: Add missed iio_device_unregister() call in mma8452_probe()
  iio:health:afe4404 Fix timestamp alignment and prevent data leak.
  iio:health:afe4403 Fix timestamp alignment and prevent data leak.
  • Loading branch information
gregkh committed Jul 8, 2020
2 parents 9ebcfad + b0536f9 commit 617894c
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 38 deletions.
22 changes: 19 additions & 3 deletions drivers/counter/104-quad-8.c
Original file line number Diff line number Diff line change
Expand Up @@ -1274,18 +1274,26 @@ static ssize_t quad8_signal_cable_fault_read(struct counter_device *counter,
struct counter_signal *signal,
void *private, char *buf)
{
const struct quad8_iio *const priv = counter->priv;
struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id / 2;
const bool disabled = !(priv->cable_fault_enable & BIT(channel_id));
bool disabled;
unsigned int status;
unsigned int fault;

if (disabled)
mutex_lock(&priv->lock);

disabled = !(priv->cable_fault_enable & BIT(channel_id));

if (disabled) {
mutex_unlock(&priv->lock);
return -EINVAL;
}

/* Logic 0 = cable fault */
status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);

mutex_unlock(&priv->lock);

/* Mask respective channel and invert logic */
fault = !(status & BIT(channel_id));

Expand Down Expand Up @@ -1317,6 +1325,8 @@ static ssize_t quad8_signal_cable_fault_enable_write(
if (ret)
return ret;

mutex_lock(&priv->lock);

if (enable)
priv->cable_fault_enable |= BIT(channel_id);
else
Expand All @@ -1327,6 +1337,8 @@ static ssize_t quad8_signal_cable_fault_enable_write(

outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);

mutex_unlock(&priv->lock);

return len;
}

Expand All @@ -1353,6 +1365,8 @@ static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter,
if (ret)
return ret;

mutex_lock(&priv->lock);

priv->fck_prescaler[channel_id] = prescaler;

/* Reset Byte Pointer */
Expand All @@ -1363,6 +1377,8 @@ static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter,
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
base_offset + 1);

mutex_unlock(&priv->lock);

return len;
}

Expand Down
5 changes: 4 additions & 1 deletion drivers/iio/accel/mma8452.c
Original file line number Diff line number Diff line change
Expand Up @@ -1685,10 +1685,13 @@ static int mma8452_probe(struct i2c_client *client,

ret = mma8452_set_freefall_mode(data, false);
if (ret < 0)
goto buffer_cleanup;
goto unregister_device;

return 0;

unregister_device:
iio_device_unregister(indio_dev);

buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);

Expand Down
2 changes: 1 addition & 1 deletion drivers/iio/adc/ad7780.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ static int ad7780_probe(struct spi_device *spi)

ret = ad7780_init_gpios(&spi->dev, st);
if (ret)
goto error_cleanup_buffer_and_trigger;
return ret;

st->reg = devm_regulator_get(&spi->dev, "avdd");
if (IS_ERR(st->reg))
Expand Down
4 changes: 2 additions & 2 deletions drivers/iio/adc/adi-axi-adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,12 +332,12 @@ static struct adi_axi_adc_client *adi_axi_adc_attach_client(struct device *dev)
if (cl->dev->of_node != cln)
continue;

if (!try_module_get(dev->driver->owner)) {
if (!try_module_get(cl->dev->driver->owner)) {
mutex_unlock(&registered_clients_lock);
return ERR_PTR(-ENODEV);
}

get_device(dev);
get_device(cl->dev);
cl->info = info;
mutex_unlock(&registered_clients_lock);
return cl;
Expand Down
9 changes: 6 additions & 3 deletions drivers/iio/health/afe4403.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static const struct reg_field afe4403_reg_fields[] = {
* @regulator: Pointer to the regulator for the IC
* @trig: IIO trigger for this device
* @irq: ADC_RDY line interrupt number
* @buffer: Used to construct data layout to push into IIO buffer.
*/
struct afe4403_data {
struct device *dev;
Expand All @@ -74,6 +75,8 @@ struct afe4403_data {
struct regulator *regulator;
struct iio_trigger *trig;
int irq;
/* Ensure suitable alignment for timestamp */
s32 buffer[8] __aligned(8);
};

enum afe4403_chan_id {
Expand Down Expand Up @@ -309,7 +312,6 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private)
struct iio_dev *indio_dev = pf->indio_dev;
struct afe4403_data *afe = iio_priv(indio_dev);
int ret, bit, i = 0;
s32 buffer[8];
u8 tx[4] = {AFE440X_CONTROL0, 0x0, 0x0, AFE440X_CONTROL0_READ};
u8 rx[3];

Expand All @@ -326,7 +328,7 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private)
if (ret)
goto err;

buffer[i++] = get_unaligned_be24(&rx[0]);
afe->buffer[i++] = get_unaligned_be24(&rx[0]);
}

/* Disable reading from the device */
Expand All @@ -335,7 +337,8 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private)
if (ret)
goto err;

iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
iio_push_to_buffers_with_timestamp(indio_dev, afe->buffer,
pf->timestamp);
err:
iio_trigger_notify_done(indio_dev->trig);

Expand Down
8 changes: 5 additions & 3 deletions drivers/iio/health/afe4404.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ static const struct reg_field afe4404_reg_fields[] = {
* @regulator: Pointer to the regulator for the IC
* @trig: IIO trigger for this device
* @irq: ADC_RDY line interrupt number
* @buffer: Used to construct a scan to push to the iio buffer.
*/
struct afe4404_data {
struct device *dev;
Expand All @@ -91,6 +92,7 @@ struct afe4404_data {
struct regulator *regulator;
struct iio_trigger *trig;
int irq;
s32 buffer[10] __aligned(8);
};

enum afe4404_chan_id {
Expand Down Expand Up @@ -328,17 +330,17 @@ static irqreturn_t afe4404_trigger_handler(int irq, void *private)
struct iio_dev *indio_dev = pf->indio_dev;
struct afe4404_data *afe = iio_priv(indio_dev);
int ret, bit, i = 0;
s32 buffer[10];

for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength) {
ret = regmap_read(afe->regmap, afe4404_channel_values[bit],
&buffer[i++]);
&afe->buffer[i++]);
if (ret)
goto err;
}

iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
iio_push_to_buffers_with_timestamp(indio_dev, afe->buffer,
pf->timestamp);
err:
iio_trigger_notify_done(indio_dev->trig);

Expand Down
10 changes: 7 additions & 3 deletions drivers/iio/humidity/hdc100x.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ struct hdc100x_data {

/* integration time of the sensor */
int adc_int_us[2];
/* Ensure natural alignment of timestamp */
struct {
__be16 channels[2];
s64 ts __aligned(8);
} scan;
};

/* integration time in us */
Expand Down Expand Up @@ -322,7 +327,6 @@ static irqreturn_t hdc100x_trigger_handler(int irq, void *p)
struct i2c_client *client = data->client;
int delay = data->adc_int_us[0] + data->adc_int_us[1];
int ret;
s16 buf[8]; /* 2x s16 + padding + 8 byte timestamp */

/* dual read starts at temp register */
mutex_lock(&data->lock);
Expand All @@ -333,13 +337,13 @@ static irqreturn_t hdc100x_trigger_handler(int irq, void *p)
}
usleep_range(delay, delay + 1000);

ret = i2c_master_recv(client, (u8 *)buf, 4);
ret = i2c_master_recv(client, (u8 *)data->scan.channels, 4);
if (ret < 0) {
dev_err(&client->dev, "cannot read sensor data\n");
goto err;
}

iio_push_to_buffers_with_timestamp(indio_dev, buf,
iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
iio_get_time_ns(indio_dev));
err:
mutex_unlock(&data->lock);
Expand Down
7 changes: 5 additions & 2 deletions drivers/iio/humidity/hts221.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@

#include <linux/iio/iio.h>

#define HTS221_DATA_SIZE 2

enum hts221_sensor_type {
HTS221_SENSOR_H,
HTS221_SENSOR_T,
Expand All @@ -39,6 +37,11 @@ struct hts221_hw {

bool enabled;
u8 odr;
/* Ensure natural alignment of timestamp */
struct {
__le16 channels[2];
s64 ts __aligned(8);
} scan;
};

extern const struct dev_pm_ops hts221_pm_ops;
Expand Down
9 changes: 5 additions & 4 deletions drivers/iio/humidity/hts221_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@ static const struct iio_buffer_setup_ops hts221_buffer_ops = {

static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)
{
u8 buffer[ALIGN(2 * HTS221_DATA_SIZE, sizeof(s64)) + sizeof(s64)];
struct iio_poll_func *pf = p;
struct iio_dev *iio_dev = pf->indio_dev;
struct hts221_hw *hw = iio_priv(iio_dev);
Expand All @@ -170,18 +169,20 @@ static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)
/* humidity data */
ch = &iio_dev->channels[HTS221_SENSOR_H];
err = regmap_bulk_read(hw->regmap, ch->address,
buffer, HTS221_DATA_SIZE);
&hw->scan.channels[0],
sizeof(hw->scan.channels[0]));
if (err < 0)
goto out;

/* temperature data */
ch = &iio_dev->channels[HTS221_SENSOR_T];
err = regmap_bulk_read(hw->regmap, ch->address,
buffer + HTS221_DATA_SIZE, HTS221_DATA_SIZE);
&hw->scan.channels[1],
sizeof(hw->scan.channels[1]));
if (err < 0)
goto out;

iio_push_to_buffers_with_timestamp(iio_dev, buffer,
iio_push_to_buffers_with_timestamp(iio_dev, &hw->scan,
iio_get_time_ns(iio_dev));

out:
Expand Down
2 changes: 2 additions & 0 deletions drivers/iio/industrialio-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_PM2P5] = "pm2p5",
[IIO_MOD_PM4] = "pm4",
[IIO_MOD_PM10] = "pm10",
[IIO_MOD_ETHANOL] = "ethanol",
[IIO_MOD_H2] = "h2",
};

/* relies on pairs of these shared then separate */
Expand Down
29 changes: 17 additions & 12 deletions drivers/iio/magnetometer/ak8974.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ struct ak8974 {
bool drdy_irq;
struct completion drdy_complete;
bool drdy_active_low;
/* Ensure timestamp is naturally aligned */
struct {
__le16 channels[3];
s64 ts __aligned(8);
} scan;
};

static const char ak8974_reg_avdd[] = "avdd";
Expand Down Expand Up @@ -657,7 +662,6 @@ static void ak8974_fill_buffer(struct iio_dev *indio_dev)
{
struct ak8974 *ak8974 = iio_priv(indio_dev);
int ret;
__le16 hw_values[8]; /* Three axes + 64bit padding */

pm_runtime_get_sync(&ak8974->i2c->dev);
mutex_lock(&ak8974->lock);
Expand All @@ -667,13 +671,13 @@ static void ak8974_fill_buffer(struct iio_dev *indio_dev)
dev_err(&ak8974->i2c->dev, "error triggering measure\n");
goto out_unlock;
}
ret = ak8974_getresult(ak8974, hw_values);
ret = ak8974_getresult(ak8974, ak8974->scan.channels);
if (ret) {
dev_err(&ak8974->i2c->dev, "error getting measures\n");
goto out_unlock;
}

iio_push_to_buffers_with_timestamp(indio_dev, hw_values,
iio_push_to_buffers_with_timestamp(indio_dev, &ak8974->scan,
iio_get_time_ns(indio_dev));

out_unlock:
Expand Down Expand Up @@ -862,19 +866,21 @@ static int ak8974_probe(struct i2c_client *i2c,
ak8974->map = devm_regmap_init_i2c(i2c, &ak8974_regmap_config);
if (IS_ERR(ak8974->map)) {
dev_err(&i2c->dev, "failed to allocate register map\n");
pm_runtime_put_noidle(&i2c->dev);
pm_runtime_disable(&i2c->dev);
return PTR_ERR(ak8974->map);
}

ret = ak8974_set_power(ak8974, AK8974_PWR_ON);
if (ret) {
dev_err(&i2c->dev, "could not power on\n");
goto power_off;
goto disable_pm;
}

ret = ak8974_detect(ak8974);
if (ret) {
dev_err(&i2c->dev, "neither AK8974 nor AMI30x found\n");
goto power_off;
goto disable_pm;
}

ret = ak8974_selftest(ak8974);
Expand All @@ -884,14 +890,9 @@ static int ak8974_probe(struct i2c_client *i2c,
ret = ak8974_reset(ak8974);
if (ret) {
dev_err(&i2c->dev, "AK8974 reset failed\n");
goto power_off;
goto disable_pm;
}

pm_runtime_set_autosuspend_delay(&i2c->dev,
AK8974_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(&i2c->dev);
pm_runtime_put(&i2c->dev);

indio_dev->dev.parent = &i2c->dev;
switch (ak8974->variant) {
case AK8974_WHOAMI_VALUE_AMI306:
Expand Down Expand Up @@ -957,6 +958,11 @@ static int ak8974_probe(struct i2c_client *i2c,
goto cleanup_buffer;
}

pm_runtime_set_autosuspend_delay(&i2c->dev,
AK8974_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(&i2c->dev);
pm_runtime_put(&i2c->dev);

return 0;

cleanup_buffer:
Expand All @@ -965,7 +971,6 @@ static int ak8974_probe(struct i2c_client *i2c,
pm_runtime_put_noidle(&i2c->dev);
pm_runtime_disable(&i2c->dev);
ak8974_set_power(ak8974, AK8974_PWR_OFF);
power_off:
regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs);

return ret;
Expand Down
Loading

0 comments on commit 617894c

Please sign in to comment.