From mboxrd@z Thu Jan 1 00:00:00 1970 From: Grygorii Strashko Subject: Re: i2c: omap: fix NACK and Arbitration Lost irq handling Date: Mon, 17 Nov 2014 16:41:31 +0200 Message-ID: <546A091B.2080505@ti.com> References: <1416013976-6441-1-git-send-email-al.kochet@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1416013976-6441-1-git-send-email-al.kochet-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> Sender: linux-i2c-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: Alexander Kochetkov , linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Cc: Tony Lindgren , Wolfram Sang , Felipe Balbi List-Id: linux-i2c@vger.kernel.org On 11/15/2014 03:12 AM, Alexander Kochetkov wrote: > commit 1d7afc95946487945cc7f5019b41255b72224b70 (i2c: omap: ack IRQ in parts) > changed the interrupt handler to complete transfers without clearing > XRDY (AL case) and ARDY (NACK case) flags. XRDY or ARDY interrupt will be > fired again (in parallel with omap_i2c_xfer_msg). Interrupt handler will > complete transfers second time. As a result, NACK and AL transfers > terminates with "transfer timeout" and sometimes client code segfault. > > The patch restore original logic of handling NACK and AL interrupts and > fix race between interrupt handler and omap_i2c_xfer_msg (for AL and > NACK case only). > > Tested on Beagleboard XM C. Seems you've got the same issue as I :) long time ago https://lkml.org/lkml/2013/6/7/530 > > Signed-off-by: Alexander Kochetkov > --- > drivers/i2c/busses/i2c-omap.c | 2 -- > 1 file changed, 2 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c > index 90dcc2e..9af7095 100644 > --- a/drivers/i2c/busses/i2c-omap.c > +++ b/drivers/i2c/busses/i2c-omap.c > @@ -926,14 +926,12 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) > if (stat & OMAP_I2C_STAT_NACK) { > err |= OMAP_I2C_STAT_NACK; > omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK); > - break; > } > > if (stat & OMAP_I2C_STAT_AL) { > dev_err(dev->dev, "Arbitration lost\n"); > err |= OMAP_I2C_STAT_AL; > omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL); > - break; > } > > /* >