diff options
author | Hartmut Knaack <knaack.h@gmx.de> | 2015-07-09 17:51:31 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2015-08-12 17:16:02 -0400 |
commit | 7c7a9eeaa335df03d692ad65e0767020ad1be374 (patch) | |
tree | 8cdbccc583152ac8bd2e6689b78362539480e7a4 | |
parent | b465fc5499083d0b7086ae590cb852c0052622a0 (diff) |
iio:light:stk3310: add more error handling
Check for the following error cases:
* lower boundary for val in _write_event
* return value of regmap_(field_)read
* possible values for chan->type
* return value of stk3310_gpio_probe
Also add an error path in _probe to put the sensor back into stand-by mode
in case of serious errors.
Signed-off-by: Hartmut Knaack <knaack.h@gmx.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r-- | drivers/iio/light/stk3310.c | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index f101bb5bddc7..09f2f6a30b79 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c | |||
@@ -241,8 +241,11 @@ static int stk3310_write_event(struct iio_dev *indio_dev, | |||
241 | struct stk3310_data *data = iio_priv(indio_dev); | 241 | struct stk3310_data *data = iio_priv(indio_dev); |
242 | struct i2c_client *client = data->client; | 242 | struct i2c_client *client = data->client; |
243 | 243 | ||
244 | regmap_field_read(data->reg_ps_gain, &index); | 244 | ret = regmap_field_read(data->reg_ps_gain, &index); |
245 | if (val > stk3310_ps_max[index]) | 245 | if (ret < 0) |
246 | return ret; | ||
247 | |||
248 | if (val < 0 || val > stk3310_ps_max[index]) | ||
246 | return -EINVAL; | 249 | return -EINVAL; |
247 | 250 | ||
248 | if (dir == IIO_EV_DIR_RISING) | 251 | if (dir == IIO_EV_DIR_RISING) |
@@ -266,9 +269,12 @@ static int stk3310_read_event_config(struct iio_dev *indio_dev, | |||
266 | enum iio_event_direction dir) | 269 | enum iio_event_direction dir) |
267 | { | 270 | { |
268 | unsigned int event_val; | 271 | unsigned int event_val; |
272 | int ret; | ||
269 | struct stk3310_data *data = iio_priv(indio_dev); | 273 | struct stk3310_data *data = iio_priv(indio_dev); |
270 | 274 | ||
271 | regmap_field_read(data->reg_int_ps, &event_val); | 275 | ret = regmap_field_read(data->reg_int_ps, &event_val); |
276 | if (ret < 0) | ||
277 | return ret; | ||
272 | 278 | ||
273 | return event_val; | 279 | return event_val; |
274 | } | 280 | } |
@@ -307,14 +313,16 @@ static int stk3310_read_raw(struct iio_dev *indio_dev, | |||
307 | struct stk3310_data *data = iio_priv(indio_dev); | 313 | struct stk3310_data *data = iio_priv(indio_dev); |
308 | struct i2c_client *client = data->client; | 314 | struct i2c_client *client = data->client; |
309 | 315 | ||
316 | if (chan->type != IIO_LIGHT && chan->type != IIO_PROXIMITY) | ||
317 | return -EINVAL; | ||
318 | |||
310 | switch (mask) { | 319 | switch (mask) { |
311 | case IIO_CHAN_INFO_RAW: | 320 | case IIO_CHAN_INFO_RAW: |
312 | if (chan->type == IIO_LIGHT) | 321 | if (chan->type == IIO_LIGHT) |
313 | reg = STK3310_REG_ALS_DATA_MSB; | 322 | reg = STK3310_REG_ALS_DATA_MSB; |
314 | else if (chan->type == IIO_PROXIMITY) | ||
315 | reg = STK3310_REG_PS_DATA_MSB; | ||
316 | else | 323 | else |
317 | return -EINVAL; | 324 | reg = STK3310_REG_PS_DATA_MSB; |
325 | |||
318 | mutex_lock(&data->lock); | 326 | mutex_lock(&data->lock); |
319 | ret = regmap_bulk_read(data->regmap, reg, &buf, 2); | 327 | ret = regmap_bulk_read(data->regmap, reg, &buf, 2); |
320 | if (ret < 0) { | 328 | if (ret < 0) { |
@@ -327,17 +335,23 @@ static int stk3310_read_raw(struct iio_dev *indio_dev, | |||
327 | return IIO_VAL_INT; | 335 | return IIO_VAL_INT; |
328 | case IIO_CHAN_INFO_INT_TIME: | 336 | case IIO_CHAN_INFO_INT_TIME: |
329 | if (chan->type == IIO_LIGHT) | 337 | if (chan->type == IIO_LIGHT) |
330 | regmap_field_read(data->reg_als_it, &index); | 338 | ret = regmap_field_read(data->reg_als_it, &index); |
331 | else | 339 | else |
332 | regmap_field_read(data->reg_ps_it, &index); | 340 | ret = regmap_field_read(data->reg_ps_it, &index); |
341 | if (ret < 0) | ||
342 | return ret; | ||
343 | |||
333 | *val = stk3310_it_table[index][0]; | 344 | *val = stk3310_it_table[index][0]; |
334 | *val2 = stk3310_it_table[index][1]; | 345 | *val2 = stk3310_it_table[index][1]; |
335 | return IIO_VAL_INT_PLUS_MICRO; | 346 | return IIO_VAL_INT_PLUS_MICRO; |
336 | case IIO_CHAN_INFO_SCALE: | 347 | case IIO_CHAN_INFO_SCALE: |
337 | if (chan->type == IIO_LIGHT) | 348 | if (chan->type == IIO_LIGHT) |
338 | regmap_field_read(data->reg_als_gain, &index); | 349 | ret = regmap_field_read(data->reg_als_gain, &index); |
339 | else | 350 | else |
340 | regmap_field_read(data->reg_ps_gain, &index); | 351 | ret = regmap_field_read(data->reg_ps_gain, &index); |
352 | if (ret < 0) | ||
353 | return ret; | ||
354 | |||
341 | *val = stk3310_scale_table[index][0]; | 355 | *val = stk3310_scale_table[index][0]; |
342 | *val2 = stk3310_scale_table[index][1]; | 356 | *val2 = stk3310_scale_table[index][1]; |
343 | return IIO_VAL_INT_PLUS_MICRO; | 357 | return IIO_VAL_INT_PLUS_MICRO; |
@@ -354,6 +368,9 @@ static int stk3310_write_raw(struct iio_dev *indio_dev, | |||
354 | int index; | 368 | int index; |
355 | struct stk3310_data *data = iio_priv(indio_dev); | 369 | struct stk3310_data *data = iio_priv(indio_dev); |
356 | 370 | ||
371 | if (chan->type != IIO_LIGHT && chan->type != IIO_PROXIMITY) | ||
372 | return -EINVAL; | ||
373 | |||
357 | switch (mask) { | 374 | switch (mask) { |
358 | case IIO_CHAN_INFO_INT_TIME: | 375 | case IIO_CHAN_INFO_INT_TIME: |
359 | index = stk3310_get_index(stk3310_it_table, | 376 | index = stk3310_get_index(stk3310_it_table, |
@@ -435,7 +452,10 @@ static int stk3310_init(struct iio_dev *indio_dev) | |||
435 | struct stk3310_data *data = iio_priv(indio_dev); | 452 | struct stk3310_data *data = iio_priv(indio_dev); |
436 | struct i2c_client *client = data->client; | 453 | struct i2c_client *client = data->client; |
437 | 454 | ||
438 | regmap_read(data->regmap, STK3310_REG_ID, &chipid); | 455 | ret = regmap_read(data->regmap, STK3310_REG_ID, &chipid); |
456 | if (ret < 0) | ||
457 | return ret; | ||
458 | |||
439 | if (chipid != STK3310_CHIP_ID_VAL && | 459 | if (chipid != STK3310_CHIP_ID_VAL && |
440 | chipid != STK3311_CHIP_ID_VAL) { | 460 | chipid != STK3311_CHIP_ID_VAL) { |
441 | dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid); | 461 | dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid); |
@@ -608,8 +628,13 @@ static int stk3310_probe(struct i2c_client *client, | |||
608 | if (ret < 0) | 628 | if (ret < 0) |
609 | return ret; | 629 | return ret; |
610 | 630 | ||
611 | if (client->irq < 0) | 631 | if (client->irq < 0) { |
612 | client->irq = stk3310_gpio_probe(client); | 632 | client->irq = stk3310_gpio_probe(client); |
633 | if (client->irq < 0) { | ||
634 | ret = client->irq; | ||
635 | goto err_standby; | ||
636 | } | ||
637 | } | ||
613 | 638 | ||
614 | if (client->irq >= 0) { | 639 | if (client->irq >= 0) { |
615 | ret = devm_request_threaded_irq(&client->dev, client->irq, | 640 | ret = devm_request_threaded_irq(&client->dev, client->irq, |
@@ -618,17 +643,23 @@ static int stk3310_probe(struct i2c_client *client, | |||
618 | IRQF_TRIGGER_FALLING | | 643 | IRQF_TRIGGER_FALLING | |
619 | IRQF_ONESHOT, | 644 | IRQF_ONESHOT, |
620 | STK3310_EVENT, indio_dev); | 645 | STK3310_EVENT, indio_dev); |
621 | if (ret < 0) | 646 | if (ret < 0) { |
622 | dev_err(&client->dev, "request irq %d failed\n", | 647 | dev_err(&client->dev, "request irq %d failed\n", |
623 | client->irq); | 648 | client->irq); |
649 | goto err_standby; | ||
650 | } | ||
624 | } | 651 | } |
625 | 652 | ||
626 | ret = iio_device_register(indio_dev); | 653 | ret = iio_device_register(indio_dev); |
627 | if (ret < 0) { | 654 | if (ret < 0) { |
628 | dev_err(&client->dev, "device_register failed\n"); | 655 | dev_err(&client->dev, "device_register failed\n"); |
629 | stk3310_set_state(data, STK3310_STATE_STANDBY); | 656 | goto err_standby; |
630 | } | 657 | } |
631 | 658 | ||
659 | return 0; | ||
660 | |||
661 | err_standby: | ||
662 | stk3310_set_state(data, STK3310_STATE_STANDBY); | ||
632 | return ret; | 663 | return ret; |
633 | } | 664 | } |
634 | 665 | ||