diff mbox

i2c: ocores: Add missing wake_up() call upon state change to STATE_DONE

Message ID 20170616092317.584-1-sr@denx.de
State Rejected
Headers show

Commit Message

Stefan Roese June 16, 2017, 9:23 a.m. UTC
I've noticed that this driver adds a timeout pause of 1 second after
each xfer. This is due to the wait_event_timeout() call in ocores_xfer()
using a "HZ" timeout value and a missing call to wake_up() in
ocores_process() called by the interrupt handler when the state changes
to STATE_DONE at the end of the frame.

This patch adds the missing call resulting in the removal of this 1
second timeout delay after each xfer.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Wolfram Sang <wsa@the-dreams.de>
---
 drivers/i2c/busses/i2c-ocores.c | 1 +
 1 file changed, 1 insertion(+)

Comments

Peter Korsgaard June 16, 2017, 12:52 p.m. UTC | #1
>>>>> "Stefan" == Stefan Roese <sr@denx.de> writes:

 > I've noticed that this driver adds a timeout pause of 1 second after
 > each xfer. This is due to the wait_event_timeout() call in ocores_xfer()
 > using a "HZ" timeout value and a missing call to wake_up() in
 > ocores_process() called by the interrupt handler when the state changes
 > to STATE_DONE at the end of the frame.

 > This patch adds the missing call resulting in the removal of this 1
 > second timeout delay after each xfer.

 > Signed-off-by: Stefan Roese <sr@denx.de>
 > Cc: Wolfram Sang <wsa@the-dreams.de>
 > ---
 >  drivers/i2c/busses/i2c-ocores.c | 1 +
 >  1 file changed, 1 insertion(+)

 > diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
 > index 34f1889a4073..5f8395ea0106 100644
 > --- a/drivers/i2c/busses/i2c-ocores.c
 > +++ b/drivers/i2c/busses/i2c-ocores.c
 > @@ -191,6 +191,7 @@ static void ocores_process(struct ocores_i2c *i2c)
 >  		} else {
>                       i2c-> state = STATE_DONE;
 >  			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
 > +			wake_up(&i2c->wait);
 >  			return;

It is close to 10 years ago since I last had access to any boards with
the ocores controller, but the logic in ocores_process() indicates that
the controller would generate another interrupt once the stop condition
has been sent:

	if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
		/* stop has been sent */
		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
		wake_up(&i2c->wait);
		return;
	}

Do you not see this interrupt?
Stefan Roese June 16, 2017, 1:04 p.m. UTC | #2
Hi Peter,

On 16.06.2017 14:52, Peter Korsgaard wrote:
>>>>>> "Stefan" == Stefan Roese <sr@denx.de> writes:
> 
>   > I've noticed that this driver adds a timeout pause of 1 second after
>   > each xfer. This is due to the wait_event_timeout() call in ocores_xfer()
>   > using a "HZ" timeout value and a missing call to wake_up() in
>   > ocores_process() called by the interrupt handler when the state changes
>   > to STATE_DONE at the end of the frame.
> 
>   > This patch adds the missing call resulting in the removal of this 1
>   > second timeout delay after each xfer.
> 
>   > Signed-off-by: Stefan Roese <sr@denx.de>
>   > Cc: Wolfram Sang <wsa@the-dreams.de>
>   > ---
>   >  drivers/i2c/busses/i2c-ocores.c | 1 +
>   >  1 file changed, 1 insertion(+)
> 
>   > diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
>   > index 34f1889a4073..5f8395ea0106 100644
>   > --- a/drivers/i2c/busses/i2c-ocores.c
>   > +++ b/drivers/i2c/busses/i2c-ocores.c
>   > @@ -191,6 +191,7 @@ static void ocores_process(struct ocores_i2c *i2c)
>   >  		} else {
>>                        i2c-> state = STATE_DONE;
>   >  			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
>   > +			wake_up(&i2c->wait);
>   >  			return;
> 
> It is close to 10 years ago since I last had access to any boards with
> the ocores controller, but the logic in ocores_process() indicates that
> the controller would generate another interrupt once the stop condition
> has been sent:
> 
> 	if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
> 		/* stop has been sent */
> 		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
> 		wake_up(&i2c->wait);
> 		return;
> 	}
> 
> Do you not see this interrupt?

No. It took me quite some time last week, to notice this misbehavior
in this I2C driver. As the client (Goodix I2C touchscreen) always
returned only after more than 1 second from reading one I2C frame.

Thanks,
Stefan
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Peter Korsgaard June 16, 2017, 1:26 p.m. UTC | #3
>>>>> "Stefan" == Stefan Roese <sr@denx.de> writes:

Hi,

 >> It is close to 10 years ago since I last had access to any boards with
 >> the ocores controller, but the logic in ocores_process() indicates that
 >> the controller would generate another interrupt once the stop condition
 >> has been sent:
 >> 
 >> if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
 >> /* stop has been sent */
 >> oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
 >> wake_up(&i2c->wait);
 >> return;
 >> }
 >> 
 >> Do you not see this interrupt?

 > No. It took me quite some time last week, to notice this misbehavior
 > in this I2C driver. As the client (Goodix I2C touchscreen) always
 > returned only after more than 1 second from reading one I2C frame.

Funky. On what kind of platform / what VHDL source version is this? The
driver has now existed for more than 10 years and has had contributions
from a number of people, but this is the first time I hear about this
missing interrupt.
Stefan Roese June 22, 2017, 10:53 a.m. UTC | #4
Hi Peter,

first sorry for the delay.

On 16.06.2017 15:26, Peter Korsgaard wrote:
>>>>>> "Stefan" == Stefan Roese <sr@denx.de> writes:
> 
> Hi,
> 
>   >> It is close to 10 years ago since I last had access to any boards with
>   >> the ocores controller, but the logic in ocores_process() indicates that
>   >> the controller would generate another interrupt once the stop condition
>   >> has been sent:
>   >>
>   >> if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
>   >> /* stop has been sent */
>   >> oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
>   >> wake_up(&i2c->wait);
>   >> return;
>   >> }
>   >>
>   >> Do you not see this interrupt?
> 
>   > No. It took me quite some time last week, to notice this misbehavior
>   > in this I2C driver. As the client (Goodix I2C touchscreen) always
>   > returned only after more than 1 second from reading one I2C frame.
> 
> Funky. On what kind of platform / what VHDL source version is this?

Thanks for looking into this. It seems that we had a quite old
version of the OpenCores I2C core implemented on our Altera /
Intel Arria V board:

Rev 1.2 (2001/11/10)

> The
> driver has now existed for more than 10 years and has had contributions
> from a number of people, but this is the first time I hear about this
> missing interrupt.

After updating to the latest version from OpenCores, the issue
with the missing interrupt seems to be resolved. So this patch
can be dropped.

Thanks,
Stefan
Wolfram Sang June 23, 2017, 6:29 p.m. UTC | #5
> After updating to the latest version from OpenCores, the issue
> with the missing interrupt seems to be resolved. So this patch
> can be dropped.

Thanks for the heads up and thanks to Peter for looking into this issue!
Peter Korsgaard June 26, 2017, 9:30 p.m. UTC | #6
>>>>> "Wolfram" == Wolfram Sang <wsa@the-dreams.de> writes:

 >> After updating to the latest version from OpenCores, the issue
 >> with the missing interrupt seems to be resolved. So this patch
 >> can be dropped.

 > Thanks for the heads up and thanks to Peter for looking into this issue!

Great, thanks both!
diff mbox

Patch

diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 34f1889a4073..5f8395ea0106 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -191,6 +191,7 @@  static void ocores_process(struct ocores_i2c *i2c)
 		} else {
 			i2c->state = STATE_DONE;
 			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
+			wake_up(&i2c->wait);
 			return;
 		}
 	}