Re: [PATCH] staging:iio:tsl2563 rewrite probe error handling

From: Grant Grundler
Date: Thu Mar 08 2012 - 22:51:32 EST


Hi Jonathan!

On Wed, Mar 7, 2012 at 3:28 AM, Jonathan Cameron <jic23@xxxxxxxxxx> wrote:
> Fundamentally an excellent patch fixing some real issues,

Thank you! :)

> but just
> because I'm in that sort of mood I'll be fussy about the fact it is
> one patch.
>
> To nitpick, I'd have prefered this to be two patches. First that fixes
> the issues and the second that adds the additional output. ÂActually
> should probably have even had a third making the white space changes.

Yup - I see/understand why. I need to improve my git foo and work
habits so it's not hard to play with a series of smaller patches
rather than one patch that does everything to one function.

> In particular 'device not found' and 'device detect error' are both
> valid explanations. ÂPerhaps it's nice to have everything more
> consistent but that shouldn't have been in the same patch as some out
> and out fixes. ÂFixes will probably get back ported to stable trees,
> error messages won't.
>
> Still,getting the fix in place is the most important thing so if Greg
> is willing to pick this up then it has my Ack.

Thanks!

BTW, the bug(s) I fixed with this patch showed up because 3.2.7 (and
predecessors) didn't have this patch:
Author: Jonathan Cameron <jic23@xxxxxxxxx>
Date: Wed Oct 26 17:27:36 2011 +0100

staging:iio:light:tsl2563 both intensity channels have same chan_spec.

Bug has been fixed for some time in the outofstaging tree, but
didn't propogate back to here.

please consider adding this to linux-stable series.

cheers,
grant

>
> On 03/05/2012 05:15 PM, Grant Grundler wrote:
>> tsl2563 probe function has two minor issues with it's error handling paths:
>> 1) it is silent (did not report errors to dmesg)
>> 2) did not return failure code (mixed up use of ret and err)
>>
>> and two major issues:
>> 3) goto fail2 would corrupt a free memory pool ("double free")
>> 4) device registration failure did NOT cancel/flush delayed work.
>> Â Â(and thus dereference a freed data structure later)
>>
>> The "double free" is subtle and was introduced with this change:
>> Â Â Author: Jonathan Cameron <jic23@xxxxxxxxx>
>> Â Â Date: Â Mon Apr 18 12:58:55 2011 +0100
>> Â Â staging:iio:tsl2563 take advantage of new iio_device_allocate private data.
> oops. ÂThanks for picking up on this one.
>>
>> Originally, chip was allocated seperately. Now it's appended to the
>> indio_dev by iio_allocate_device(sizeof(*chip)). So we only need one
>> kfree call as well (in iio_free_device()).
>>
>> Signed-off-by: Grant Grundler <grundler@xxxxxxxxxxxx>
> Acked-by: Jonathan Cameron <jic23@xxxxxxxxxx>
>> ---
>> ÂGory details of tracking this down are here:
>> Â Â http://crosbug.com/26819
>>
>> ÂDespite iio_device_registration failing, system can at least now boot.
>> ÂWill follow up with a fix to "double register : in_intensity_both_raw"
>> Âerror that is included in the bug report.
>>
>> Âdrivers/staging/iio/light/tsl2563.c | Â 39 +++++++++++++++++++++++-----------
>> Â1 files changed, 26 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
>> index 7e984bc..bf6498b 100644
>> --- a/drivers/staging/iio/light/tsl2563.c
>> +++ b/drivers/staging/iio/light/tsl2563.c
>> @@ -705,7 +705,6 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
>> Â Â Â struct tsl2563_chip *chip;
>> Â Â Â struct tsl2563_platform_data *pdata = client->dev.platform_data;
>> Â Â Â int err = 0;
>> - Â Â int ret;
>> Â Â Â u8 id = 0;
>>
>> Â Â Â indio_dev = iio_allocate_device(sizeof(*chip));
>> @@ -719,13 +718,15 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
>>
>> Â Â Â err = tsl2563_detect(chip);
>> Â Â Â if (err) {
>> - Â Â Â Â Â Â dev_err(&client->dev, "device not found, error %d\n", -err);
>> + Â Â Â Â Â Â dev_err(&client->dev, "detect error %d\n", -err);
>> Â Â Â Â Â Â Â goto fail1;
>> Â Â Â }
>>
>> Â Â Â err = tsl2563_read_id(chip, &id);
>> - Â Â if (err)
>> + Â Â if (err) {
>> + Â Â Â Â Â Â dev_err(&client->dev, "read id error %d\n", -err);
>> Â Â Â Â Â Â Â goto fail1;
>> + Â Â }
>>
>> Â Â Â mutex_init(&chip->lock);
>>
>> @@ -748,40 +749,52 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
>> Â Â Â indio_dev->num_channels = ARRAY_SIZE(tsl2563_channels);
>> Â Â Â indio_dev->dev.parent = &client->dev;
>> Â Â Â indio_dev->modes = INDIO_DIRECT_MODE;
> Certainly no problem with white space here to make the sections of
> code more obvious, but it doesn't belong in a patch with bug fixes.
>> +
>> Â Â Â if (client->irq)
>> Â Â Â Â Â Â Â indio_dev->info = &tsl2563_info;
>> Â Â Â else
>> Â Â Â Â Â Â Â indio_dev->info = &tsl2563_info_no_irq;
>> +
>> Â Â Â if (client->irq) {
>> - Â Â Â Â Â Â ret = request_threaded_irq(client->irq,
>> + Â Â Â Â Â Â err = request_threaded_irq(client->irq,
>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ÂNULL,
>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â&tsl2563_event_handler,
>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ÂIRQF_TRIGGER_RISING | IRQF_ONESHOT,
>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â"tsl2563_event",
>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âindio_dev);
>> - Â Â Â Â Â Â if (ret)
>> - Â Â Â Â Â Â Â Â Â Â goto fail2;
>> + Â Â Â Â Â Â if (err) {
>> + Â Â Â Â Â Â Â Â Â Â dev_err(&client->dev, "irq request error %d\n", -err);
>> + Â Â Â Â Â Â Â Â Â Â goto fail1;
>> + Â Â Â Â Â Â }
>> Â Â Â }
>> +
>> Â Â Â err = tsl2563_configure(chip);
>> - Â Â if (err)
>> - Â Â Â Â Â Â goto fail3;
>> + Â Â if (err) {
>> + Â Â Â Â Â Â dev_err(&client->dev, "configure error %d\n", -err);
>> + Â Â Â Â Â Â goto fail2;
>> + Â Â }
>>
>> Â Â Â INIT_DELAYED_WORK(&chip->poweroff_work, tsl2563_poweroff_work);
>> +
>> Â Â Â /* The interrupt cannot yet be enabled so this is fine without lock */
>> Â Â Â schedule_delayed_work(&chip->poweroff_work, 5 * HZ);
>>
>> - Â Â ret = iio_device_register(indio_dev);
>> - Â Â if (ret)
>> + Â Â err = iio_device_register(indio_dev);
>> + Â Â if (err) {
>> + Â Â Â Â Â Â dev_err(&client->dev, "iio registration error %d\n", -err);
>> Â Â Â Â Â Â Â goto fail3;
>> + Â Â }
>>
>> Â Â Â return 0;
>> +
>> Âfail3:
>> + Â Â cancel_delayed_work(&chip->poweroff_work);
>> + Â Â flush_scheduled_work();
>> +fail2:
>> Â Â Â if (client->irq)
>> Â Â Â Â Â Â Â free_irq(client->irq, indio_dev);
>> -fail2:
>> - Â Â iio_free_device(indio_dev);
>> Âfail1:
>> - Â Â kfree(chip);
>> + Â Â iio_free_device(indio_dev);
>> Â Â Â return err;
>> Â}
>>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/