public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
From: Hans Verkuil <hverkuil@xs4all.nl>
To: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Dinesh Ram <dinesh.ram@cern.ch>,
	linux-media@vger.kernel.org, edubezval@gmail.com,
	dinesh.ram086@gmail.com
Subject: Re: [REVIEW PATCH 2/9] si4713 : Modified i2c driver to handle cases where interrupts are not used
Date: Tue, 03 Dec 2013 18:06:21 +0100	[thread overview]
Message-ID: <529E0F8D.9030804@xs4all.nl> (raw)
In-Reply-To: <20131203133514.4a4da7d1.m.chehab@samsung.com>

On 12/03/2013 04:35 PM, Mauro Carvalho Chehab wrote:
> Em Tue, 15 Oct 2013 17:24:38 +0200
> Dinesh Ram <dinesh.ram@cern.ch> escreveu:
> 
>> Checks have been introduced at several places in the code to test if an interrupt is set or not.
>> For devices which do not use the interrupt, to get a valid response, within a specified timeout,
>> the device is polled instead.
>>
>> Signed-off-by: Dinesh Ram <dinesh.ram@cern.ch>
>> ---
>>  drivers/media/radio/si4713/si4713.c |  108 +++++++++++++++++++++--------------
>>  1 file changed, 64 insertions(+), 44 deletions(-)
>>
>> diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c
>> index ac727e3..24ae41d 100644
>> --- a/drivers/media/radio/si4713/si4713.c
>> +++ b/drivers/media/radio/si4713/si4713.c
>> @@ -27,11 +27,11 @@
>>  #include <linux/i2c.h>
>>  #include <linux/slab.h>
>>  #include <linux/gpio.h>
>> -#include <linux/regulator/consumer.h>
>>  #include <linux/module.h>
>>  #include <media/v4l2-device.h>
>>  #include <media/v4l2-ioctl.h>
>>  #include <media/v4l2-common.h>
>> +#include <linux/regulator/consumer.h>
>>  
>>  #include "si4713.h"
>>  
>> @@ -213,6 +213,7 @@ static int si4713_send_command(struct si4713_device *sdev, const u8 command,
>>  				u8 response[], const int respn, const int usecs)
>>  {
>>  	struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
>> +	unsigned long until_jiffies;
>>  	u8 data1[MAX_ARGS + 1];
>>  	int err;
>>  
>> @@ -228,30 +229,39 @@ static int si4713_send_command(struct si4713_device *sdev, const u8 command,
>>  	if (err != argn + 1) {
>>  		v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n",
>>  			command);
>> -		return (err > 0) ? -EIO : err;
>> +		return err < 0 ? err : -EIO;
>>  	}
>>  
>> +	until_jiffies = jiffies + usecs_to_jiffies(usecs) + 1;
>> +
>>  	/* Wait response from interrupt */
>> -	if (!wait_for_completion_timeout(&sdev->work,
>> +	if (client->irq) {
>> +		if (!wait_for_completion_timeout(&sdev->work,
>>  				usecs_to_jiffies(usecs) + 1))
>> -		v4l2_warn(&sdev->sd,
>> +			v4l2_warn(&sdev->sd,
>>  				"(%s) Device took too much time to answer.\n",
>>  				__func__);
>> -
>> -	/* Then get the response */
>> -	err = i2c_master_recv(client, response, respn);
>> -	if (err != respn) {
>> -		v4l2_err(&sdev->sd,
>> -			"Error while reading response for command 0x%02x\n",
>> -			command);
>> -		return (err > 0) ? -EIO : err;
>>  	}
>>  
>> -	DBG_BUFFER(&sdev->sd, "Response", response, respn);
>> -	if (check_command_failed(response[0]))
>> -		return -EBUSY;
>> +	do {
>> +		err = i2c_master_recv(client, response, respn);
>> +		if (err != respn) {
>> +			v4l2_err(&sdev->sd,
>> +				"Error %d while reading response for command 0x%02x\n",
>> +				err, command);
>> +			return err < 0 ? err : -EIO;
>> +		}
>> +
>> +		DBG_BUFFER(&sdev->sd, "Response", response, respn);
>> +		if (!check_command_failed(response[0]))
>> +			return 0;
>>  
>> -	return 0;
>> +		if (client->irq)
>> +			return -EBUSY;
>> +		msleep(1);
>> +	} while (jiffies <= until_jiffies);
> 
> This could result on an endless loop due to the limited space for jiffies.
> You should, instead, use the proper macros (time_after, time_before, ...).

True. Can this be done as a separate follow-up patch? I'd really like to get this
driver merged, it's been sitting here for ages.

Dinesh, can you have a go at this?

Regards,

	Hans

> 
>> +
>> +	return -EBUSY;
>>  }
>>  
>>  /*
>> @@ -344,14 +354,15 @@ static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val)
>>   */
>>  static int si4713_powerup(struct si4713_device *sdev)
>>  {
>> +	struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
>>  	int err;
>>  	u8 resp[SI4713_PWUP_NRESP];
>>  	/*
>>  	 * 	.First byte = Enabled interrupts and boot function
>>  	 * 	.Second byte = Input operation mode
>>  	 */
>> -	const u8 args[SI4713_PWUP_NARGS] = {
>> -		SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX,
>> +	u8 args[SI4713_PWUP_NARGS] = {
>> +		SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX,
>>  		SI4713_PWUP_OPMOD_ANALOG,
>>  	};
>>  
>> @@ -369,6 +380,9 @@ static int si4713_powerup(struct si4713_device *sdev)
>>  		gpio_set_value(sdev->gpio_reset, 1);
>>  	}
>>  
>> +	if (client->irq)
>> +		args[0] |= SI4713_PWUP_CTSIEN;
>> +
>>  	err = si4713_send_command(sdev, SI4713_CMD_POWER_UP,
>>  					args, ARRAY_SIZE(args),
>>  					resp, ARRAY_SIZE(resp),
>> @@ -380,7 +394,8 @@ static int si4713_powerup(struct si4713_device *sdev)
>>  		v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n");
>>  		sdev->power_state = POWER_ON;
>>  
>> -		err = si4713_write_property(sdev, SI4713_GPO_IEN,
>> +		if (client->irq)
>> +			err = si4713_write_property(sdev, SI4713_GPO_IEN,
>>  						SI4713_STC_INT | SI4713_CTS);
>>  	} else {
>>  		if (gpio_is_valid(sdev->gpio_reset))
>> @@ -465,33 +480,39 @@ static int si4713_checkrev(struct si4713_device *sdev)
>>   */
>>  static int si4713_wait_stc(struct si4713_device *sdev, const int usecs)
>>  {
>> -	int err;
>> +	struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
>>  	u8 resp[SI4713_GET_STATUS_NRESP];
>> +	unsigned long start_jiffies = jiffies;
>> +	int err;
>>  
>> -	/* Wait response from STC interrupt */
>> -	if (!wait_for_completion_timeout(&sdev->work,
>> -			usecs_to_jiffies(usecs) + 1))
>> +	if (client->irq &&
>> +	    !wait_for_completion_timeout(&sdev->work, usecs_to_jiffies(usecs) + 1))
>>  		v4l2_warn(&sdev->sd,
>> -			"%s: device took too much time to answer (%d usec).\n",
>> -				__func__, usecs);
>> -
>> -	/* Clear status bits */
>> -	err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,
>> -					NULL, 0,
>> -					resp, ARRAY_SIZE(resp),
>> -					DEFAULT_TIMEOUT);
>> -
>> -	if (err < 0)
>> -		goto exit;
>> -
>> -	v4l2_dbg(1, debug, &sdev->sd,
>> -			"%s: status bits: 0x%02x\n", __func__, resp[0]);
>> -
>> -	if (!(resp[0] & SI4713_STC_INT))
>> -		err = -EIO;
>> -
>> -exit:
>> -	return err;
>> +			"(%s) Device took too much time to answer.\n", __func__);
>> +
>> +	for (;;) {
>> +		/* Clear status bits */
>> +		err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,
>> +				NULL, 0,
>> +				resp, ARRAY_SIZE(resp),
>> +				DEFAULT_TIMEOUT);
>> +		/* The USB device returns errors when it waits for the
>> +		 * STC bit to be set. Hence polling */
>> +		if (err >= 0) {
>> +			v4l2_dbg(1, debug, &sdev->sd,
>> +				"%s: status bits: 0x%02x\n", __func__, resp[0]);
>> +
>> +			if (resp[0] & SI4713_STC_INT)
>> +				return 0;
>> +		}
>> +		if (jiffies_to_usecs(jiffies - start_jiffies) > usecs)
> 
> Same here: use the proper macro to check time after/before.
> 
>> +			return err < 0 ? err : -EIO;
>> +		/* We sleep here for 3 ms in order to avoid flooding the device
>> +		 * with USB requests. The si4713 USB driver was developed
>> +		 * by reverse engineering the Windows USB driver. The windows
>> +		 * driver also has a ~2.5 ms delay between responses. */
>> +		msleep(3);
>> +	}
>>  }
>>  
>>  /*
>> @@ -1024,7 +1045,6 @@ static int si4713_initialize(struct si4713_device *sdev)
>>  	if (rval < 0)
>>  		return rval;
>>  
>> -
>>  	sdev->frequency = DEFAULT_FREQUENCY;
>>  	sdev->stereo = 1;
>>  	sdev->tune_rnl = DEFAULT_TUNE_RNL;
> 
> 


  reply	other threads:[~2013-12-03 17:06 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-15 15:24 [Review Patch 0/9] si4713 usb device driver Dinesh Ram
2013-10-15 15:24 ` [REVIEW PATCH 1/9] si4713 : Reorganized drivers/media/radio directory Dinesh Ram
2013-10-15 15:24   ` [REVIEW PATCH 2/9] si4713 : Modified i2c driver to handle cases where interrupts are not used Dinesh Ram
2013-12-03 15:35     ` Mauro Carvalho Chehab
2013-12-03 17:06       ` Hans Verkuil [this message]
     [not found]         ` <1386129496.79520.YahooMailNeo@web190906.mail.sg3.yahoo.com>
2013-12-04 17:42           ` Mauro Carvalho Chehab
2013-12-05  7:39           ` Hans Verkuil
2013-10-15 15:24   ` [REVIEW PATCH 3/9] si4713 : Reorganized includes in si4713.c/h Dinesh Ram
2013-10-15 15:24   ` [REVIEW PATCH 4/9] si4713 : Bug fix for si4713_tx_tune_power() method in the i2c driver Dinesh Ram
2013-10-15 15:24   ` [REVIEW PATCH 5/9] si4713 : HID blacklist Si4713 USB development board Dinesh Ram
2013-10-15 15:24   ` [REVIEW PATCH 6/9] si4713 : Added the USB driver for Si4713 Dinesh Ram
2013-11-05 14:18     ` edubezval
2013-11-07  7:40       ` Hans Verkuil
2013-11-11 12:34         ` edubezval
2013-11-18 14:47       ` edubezval
2013-10-15 15:24   ` [REVIEW PATCH 7/9] si4713 : Added MAINTAINERS entry for radio-usb-si4713 driver Dinesh Ram
2013-10-15 15:24   ` [REVIEW PATCH 8/9] si4713: move supply list to si4713_platform_data Dinesh Ram
2013-11-04 14:07     ` edubezval
2013-11-05  8:38       ` Hans Verkuil
2013-11-05 14:14         ` edubezval
2013-10-15 15:24   ` [REVIEW PATCH 9/9] si4713: si4713_set_rds_radio_text overwrites terminating \0 Dinesh Ram
2013-12-03 15:39   ` [REVIEW PATCH 1/9] si4713 : Reorganized drivers/media/radio directory Mauro Carvalho Chehab
     [not found]     ` <CAP_RhzeRgLir1FGL6UN2-yXXaS-1knsS2BP20MjfMJRAEyDqeg@mail.gmail.com>
2013-12-03 16:06       ` FW: " Dinesh Ram
2013-12-03 16:58     ` Hans Verkuil
2013-12-04 17:41       ` Mauro Carvalho Chehab
2013-10-15 17:37 ` [Review Patch 0/9] si4713 usb device driver edubezval
2013-11-04  9:33   ` Hans Verkuil
2013-11-04 14:09     ` edubezval
2013-11-04 14:13       ` Hans Verkuil
     [not found]         ` <CAP_RhzfWKc8y27uU4VXFu6cAt87NvO=BnLNq9WeGG_kpxihTKQ@mail.gmail.com>
2013-11-04 14:39           ` edubezval
2013-11-18 14:31 ` edubezval

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=529E0F8D.9030804@xs4all.nl \
    --to=hverkuil@xs4all.nl \
    --cc=dinesh.ram086@gmail.com \
    --cc=dinesh.ram@cern.ch \
    --cc=edubezval@gmail.com \
    --cc=linux-media@vger.kernel.org \
    --cc=m.chehab@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox