aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHartmut Knaack <knaack.h@gmx.de>2015-07-09 17:51:31 -0400
committerJonathan Cameron <jic23@kernel.org>2015-08-12 17:16:02 -0400
commit7c7a9eeaa335df03d692ad65e0767020ad1be374 (patch)
tree8cdbccc583152ac8bd2e6689b78362539480e7a4
parentb465fc5499083d0b7086ae590cb852c0052622a0 (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.c59
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
661err_standby:
662 stk3310_set_state(data, STK3310_STATE_STANDBY);
632 return ret; 663 return ret;
633} 664}
634 665