diff mbox

[v3] ARM: OMAP: i2c: fix interrupt flood during resume

Message ID 902E09E6452B0E43903E4F2D568737AB2C8C9F@DNCE04.ent.ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Grygorii Strashko Oct. 12, 2012, 2:46 p.m. UTC
Hi Kevin,

yep, [1] is the same fix - thanks. 

Hi Kalle,

i've applied these changes and PM runtime fix on top of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git (omap2plus_defconfig)
Could you check it with your use case, pls? (just to be sure that idea is right)


- Grygorii

Comments

Kevin Hilman Oct. 12, 2012, 4:43 p.m. UTC | #1
"Strashko, Grygorii" <grygorii.strashko@ti.com> writes:

> Hi Kevin,
>
> yep, [1] is the same fix - thanks. 

> Hi Kalle,
>
> i've applied these changes and PM runtime fix on top of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git (omap2plus_defconfig)
> Could you check it with your use case, pls? (just to be sure that idea is right)

I think the ideas is right, but [1] introduces more potential problems
since it disables the IRQ at the INTC well before being disabled at the
device.  With runtime PM autosuspend timeouts, that means any IRQs
firing during the autosuspend delay will be lost, which basically
nullifies the use of autosuspend.

Since Shubhrajyoti didn't respond to my runtime PM comments on the
original patch, I'll respin this patch by moving the INTC disable/enable
into the runtime PM callbacks and make the changelog a bit more clear.

Grygorii, that pm_runtime_resume() change is needed to.  Can you spin a
patch with just that change with a nice descriptive changelog about why
it is needed?  Thanks.

Kevin


>
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index a0e49f6..cb09e20 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -586,6 +586,9 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
>         if (IS_ERR_VALUE(r))
>                 goto out;
>  
> +       /* We have the bus, enable IRQ */
> +       enable_irq(dev->irq);
> +
>         r = omap_i2c_wait_for_bb(dev);
>         if (r < 0)
>                 goto out;
> @@ -606,6 +609,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
>                 r = num;
>  
>         omap_i2c_wait_for_bb(dev);
> +       disable_irq(dev->irq);
>  out:
>         pm_runtime_put(dev->dev);
>         return r;
> @@ -1060,6 +1064,9 @@ omap_i2c_probe(struct platform_device *pdev)
>                                                                    omap_i2c_isr;
>         r = request_irq(dev->irq, isr, IRQF_NO_SUSPEND, pdev->name, dev);
>  
> +       /* We enable IRQ only when request for I2C from master */
> +        disable_irq(dev->irq);
> +
>         if (r) {
>                 dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
>                 goto err_unuse_clocks;
> @@ -1182,7 +1189,23 @@ static int omap_i2c_runtime_resume(struct device *dev)
>  }
>  #endif /* CONFIG_PM_RUNTIME */
>  
> +static int omap_i2c_suspend(struct device *dev)
> +{
> +       int ret;
> +
> +       /*
> +        *  Enable I2C device, so it will be accessible during
> +        * later stages of suspending when device Runtime PM is disabled.
> +        * I2C device will be turned off at "noirq" suspend stage.
> +        */
> +       ret = pm_runtime_resume(dev);
> +       if (ret < 0)
> +               return ret;
> +       return 0;
> +}
> +
>  static struct dev_pm_ops omap_i2c_pm_ops = {
> +       SET_SYSTEM_SLEEP_PM_OPS(omap_i2c_suspend, NULL)
>         SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend,
>                            omap_i2c_runtime_resume, NULL)
>  };
>
> - Grygorii
> ________________________________________
> From: Kevin Hilman [khilman@deeprootsystems.com]
> Sent: Friday, October 12, 2012 5:34 PM
> To: Strashko, Grygorii
> Cc: Kalle Jokiniemi; linux-i2c@vger.kernel.org; w.sang@pengutronix.de; ben-linux@fluff.org; tony@atomide.com; linux-omap@vger.kernel.org; Datta, Shubhrajyoti; Kankroliwala, Huzefa
> Subject: Re: [PATCH v3] ARM: OMAP: i2c: fix interrupt flood during resume
>
> "Strashko, Grygorii" <grygorii.strashko@ti.com> writes:
>
>> Hi All,
>>
>> Sorry, for the late reply.
>> + CC Huzefa Kankroliwala - who is I2C driver owner on Android Kernel 3.4.
>
> Hi Grygorii, thanks for reviewing.  I was hoping you would have some
> ideas here as this was sounding familiar to something you had
> mentioned elsewhere.
>
>> Regarding this patch -  from my point of view, it fixes corner case and not an issue in general.
>> Let take a look on resume sequence:
>>    - platform resume
>>    - syscore resume
>>    - resume_noirq
>>    - enable IRQs - resume_device_irqs()
>>      |- at this point IRQ handler will be invoked if IRQ state is IRQS_PENDING.
>>      |- so, the I2C device IRQ handler may be called at time when I2C adapter IRQ is still disabled and, as result, the I2C device IRQ-handler may fail. (I2C device and I2C adapter may use different physical IRQ lines)
>>    - resume_late
>>      |- enable I2C bus IRQ
>>
>> Possibly, the better way is to enable/disable I2C bus IRQ when needed - in our case in omap_i2c_xfer().
>> We use such approach in Android kernel 3.4
>> (http://git.omapzoom.org/?p=kernel/omap.git;a=commitdiff;h=1445a4d3b587c164bd30d108b61760aaaa07365e)
>
> I agree, that should work and cover the cases where I2C is used by other
> processors also.  Shubhrajyoti already posted something similar[1] but
> it needed some rework (comments from Russell and myself.)
>
> Huzefa, Shubhrajyoti, who can rework this idea for the upstream and/or
> follow up with the earlier patch[1]?
>
> Wolfram, I guess for now lets hold off on $SUBJECT patch.  Seems we can
> come up with a broader solution.  Thanks.
>
> Kevin
>
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2012-October/124427.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Shubhrajyoti Datta Oct. 12, 2012, 6:11 p.m. UTC | #2
On Fri, Oct 12, 2012 at 10:13 PM, Kevin Hilman
<khilman@deeprootsystems.com> wrote:
> "Strashko, Grygorii" <grygorii.strashko@ti.com> writes:
>
>> Hi Kevin,
>>
>> yep, [1] is the same fix - thanks.
>
>> Hi Kalle,
>>
>> i've applied these changes and PM runtime fix on top of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git (omap2plus_defconfig)
>> Could you check it with your use case, pls? (just to be sure that idea is right)
>
> I think the ideas is right, but [1] introduces more potential problems
> since it disables the IRQ at the INTC well before being disabled at the
> device.
I fail to see this point. Current driver supports master mode only.
So unless there is a msg queued by the core. May be no interrupts should fire.

what I mean

msg -> conf -> intr -> completion/error  -> autosuspend.

>  With runtime PM autosuspend timeouts, that means any IRQs
> firing during the autosuspend delay will be lost, which basically
> nullifies the use of autosuspend.

so I do not expect any interrupts between completion/error -> autosuspend.

>
> Since Shubhrajyoti didn't respond to my runtime PM comments on the
> original patch,

my apologies for the delay.

> I'll respin this patch by moving the INTC disable/enable
> into the runtime PM callbacks and make the changelog a bit more clear.
>
> Grygorii, that pm_runtime_resume() change is needed to.  Can you spin a
> patch with just that change with a nice descriptive changelog about why
> it is needed?  Thanks.
>
> Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kevin Hilman Oct. 12, 2012, 7:04 p.m. UTC | #3
Shubhrajyoti Datta <omaplinuxkernel@gmail.com> writes:

> On Fri, Oct 12, 2012 at 10:13 PM, Kevin Hilman
> <khilman@deeprootsystems.com> wrote:
>> "Strashko, Grygorii" <grygorii.strashko@ti.com> writes:
>>
>>> Hi Kevin,
>>>
>>> yep, [1] is the same fix - thanks.
>>
>>> Hi Kalle,
>>>
>>> i've applied these changes and PM runtime fix on top of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git (omap2plus_defconfig)
>>> Could you check it with your use case, pls? (just to be sure that idea is right)
>>
>> I think the ideas is right, but [1] introduces more potential problems
>> since it disables the IRQ at the INTC well before being disabled at the
>> device.
> I fail to see this point. Current driver supports master mode only.
> So unless there is a msg queued by the core. May be no interrupts should fire.
>
> what I mean
>
> msg -> conf -> intr -> completion/error  -> autosuspend.
>
>>  With runtime PM autosuspend timeouts, that means any IRQs
>> firing during the autosuspend delay will be lost, which basically
>> nullifies the use of autosuspend.
>
> so I do not expect any interrupts between completion/error -> autosuspend.

Runtime PM is designed for concurrent users (hence the usecounting.)
The I2C driver may not fully support this, since there is a single bus
to share, but the usage of runtime PM currently allows multiple users to
do runtime PM get/put (though in this driver they will block in the
wait_for_bb.)

So the fundamental problem in doing the enable/disable IRQ in the xfer
function, and not the runtime PM callbacks is that you're ignoring the
runtime PM usecount.  You're assuming that the 'get' is *always*
incrementing the usecount from zero to 1, and the 'put' is *always* a
transition from 1 to zero.  This may be the case in current usage and
tests, but does not have to be the case.

Even if that never happens in practice, it can in theory, and to me
leads to confusing code.  It simply doesn't make sense in terms of
readability to disable the IRQ at the INTC in xfer, and disable IRQs at
the device level in the runtime PM callback.

To put it more simply: anything that needs to be done when the I2C is
about to be idled/enabled should be done in the runtime PM callbacks.

Please have a look at the patch I just sent[1].  In addition to making
it more readable (IMO), it elminates the need for an extra disable_irq()
in probe.

Kevin

[1] http://marc.info/?l=linux-omap&m=135006723121147&w=2
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Shubhrajyoti Datta Oct. 12, 2012, 7:15 p.m. UTC | #4
On Saturday 13 October 2012 12:34 AM, Kevin Hilman wrote:
> Shubhrajyoti Datta <omaplinuxkernel@gmail.com> writes:
>
>> On Fri, Oct 12, 2012 at 10:13 PM, Kevin Hilman
>> <khilman@deeprootsystems.com> wrote:
>>> "Strashko, Grygorii" <grygorii.strashko@ti.com> writes:
>>>
>>>> Hi Kevin,
>>>>
>>>> yep, [1] is the same fix - thanks.
>>>> Hi Kalle,
>>>>
>>>> i've applied these changes and PM runtime fix on top of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git (omap2plus_defconfig)
>>>> Could you check it with your use case, pls? (just to be sure that idea is right)
>>> I think the ideas is right, but [1] introduces more potential problems
>>> since it disables the IRQ at the INTC well before being disabled at the
>>> device.
>> I fail to see this point. Current driver supports master mode only.
>> So unless there is a msg queued by the core. May be no interrupts should fire.
>>
>> what I mean
>>
>> msg -> conf -> intr -> completion/error  -> autosuspend.
>>
>>>  With runtime PM autosuspend timeouts, that means any IRQs
>>> firing during the autosuspend delay will be lost, which basically
>>> nullifies the use of autosuspend.
>> so I do not expect any interrupts between completion/error -> autosuspend.
> Runtime PM is designed for concurrent users (hence the usecounting.)
> The I2C driver may not fully support this, since there is a single bus
> to share, but the usage of runtime PM currently allows multiple users to
> do runtime PM get/put (though in this driver they will block in the
> wait_for_bb.)
>
> So the fundamental problem in doing the enable/disable IRQ in the xfer
> function, and not the runtime PM callbacks is that you're ignoring the
> runtime PM usecount.  You're assuming that the 'get' is *always*
> incrementing the usecount from zero to 1, and the 'put' is *always* a
> transition from 1 to zero.  This may be the case in current usage and
> tests, but does not have to be the case.
>
> Even if that never happens in practice, it can in theory, and to me
> leads to confusing code.  It simply doesn't make sense in terms of
> readability to disable the IRQ at the INTC in xfer, and disable IRQs at
> the device level in the runtime PM callback.
Agree.
>
> To put it more simply: anything that needs to be done when the I2C is
> about to be idled/enabled should be done in the runtime PM callbacks.
>
> Please have a look at the patch I just sent[1].  In addition to making
> it more readable (IMO), it elminates the need for an extra disable_irq()
> in probe.

 thanks.
>
> Kevin
>
> [1] http://marc.info/?l=linux-omap&m=135006723121147&w=2

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kalle Jokiniemi Oct. 15, 2012, 6:21 a.m. UTC | #5
Hi,

pe, 2012-10-12 kello 14:46 +0000, Strashko, Grygorii kirjoitti:
> Hi Kevin,
> 
> yep, [1] is the same fix - thanks. 
> 
> Hi Kalle,
> 
> i've applied these changes and PM runtime fix on top of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git (omap2plus_defconfig)
> Could you check it with your use case, pls? (just to be sure that idea is right)

Odd, it's not working. I'll add some debug prints to see what happens
there.

- Kalle

> 
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index a0e49f6..cb09e20 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -586,6 +586,9 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
>         if (IS_ERR_VALUE(r))
>                 goto out;
>  
> +       /* We have the bus, enable IRQ */
> +       enable_irq(dev->irq);
> +
>         r = omap_i2c_wait_for_bb(dev);
>         if (r < 0)
>                 goto out;
> @@ -606,6 +609,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
>                 r = num;
>  
>         omap_i2c_wait_for_bb(dev);
> +       disable_irq(dev->irq);
>  out:
>         pm_runtime_put(dev->dev);
>         return r;
> @@ -1060,6 +1064,9 @@ omap_i2c_probe(struct platform_device *pdev)
>                                                                    omap_i2c_isr;
>         r = request_irq(dev->irq, isr, IRQF_NO_SUSPEND, pdev->name, dev);
>  
> +       /* We enable IRQ only when request for I2C from master */
> +        disable_irq(dev->irq);
> +
>         if (r) {
>                 dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
>                 goto err_unuse_clocks;
> @@ -1182,7 +1189,23 @@ static int omap_i2c_runtime_resume(struct device *dev)
>  }
>  #endif /* CONFIG_PM_RUNTIME */
>  
> +static int omap_i2c_suspend(struct device *dev)
> +{
> +       int ret;
> +
> +       /*
> +        *  Enable I2C device, so it will be accessible during
> +        * later stages of suspending when device Runtime PM is disabled.
> +        * I2C device will be turned off at "noirq" suspend stage.
> +        */
> +       ret = pm_runtime_resume(dev);
> +       if (ret < 0)
> +               return ret;
> +       return 0;
> +}
> +
>  static struct dev_pm_ops omap_i2c_pm_ops = {
> +       SET_SYSTEM_SLEEP_PM_OPS(omap_i2c_suspend, NULL)
>         SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend,
>                            omap_i2c_runtime_resume, NULL)
>  };
> 
> - Grygorii
> ________________________________________
> From: Kevin Hilman [khilman@deeprootsystems.com]
> Sent: Friday, October 12, 2012 5:34 PM
> To: Strashko, Grygorii
> Cc: Kalle Jokiniemi; linux-i2c@vger.kernel.org; w.sang@pengutronix.de; ben-linux@fluff.org; tony@atomide.com; linux-omap@vger.kernel.org; Datta, Shubhrajyoti; Kankroliwala, Huzefa
> Subject: Re: [PATCH v3] ARM: OMAP: i2c: fix interrupt flood during resume
> 
> "Strashko, Grygorii" <grygorii.strashko@ti.com> writes:
> 
> > Hi All,
> >
> > Sorry, for the late reply.
> > + CC Huzefa Kankroliwala - who is I2C driver owner on Android Kernel 3.4.
> 
> Hi Grygorii, thanks for reviewing.  I was hoping you would have some
> ideas here as this was sounding familiar to something you had
> mentioned elsewhere.
> 
> > Regarding this patch -  from my point of view, it fixes corner case and not an issue in general.
> > Let take a look on resume sequence:
> >    - platform resume
> >    - syscore resume
> >    - resume_noirq
> >    - enable IRQs - resume_device_irqs()
> >      |- at this point IRQ handler will be invoked if IRQ state is IRQS_PENDING.
> >      |- so, the I2C device IRQ handler may be called at time when I2C adapter IRQ is still disabled and, as result, the I2C device IRQ-handler may fail. (I2C device and I2C adapter may use different physical IRQ lines)
> >    - resume_late
> >      |- enable I2C bus IRQ
> >
> > Possibly, the better way is to enable/disable I2C bus IRQ when needed - in our case in omap_i2c_xfer().
> > We use such approach in Android kernel 3.4
> > (http://git.omapzoom.org/?p=kernel/omap.git;a=commitdiff;h=1445a4d3b587c164bd30d108b61760aaaa07365e)
> 
> I agree, that should work and cover the cases where I2C is used by other
> processors also.  Shubhrajyoti already posted something similar[1] but
> it needed some rework (comments from Russell and myself.)
> 
> Huzefa, Shubhrajyoti, who can rework this idea for the upstream and/or
> follow up with the earlier patch[1]?
> 
> Wolfram, I guess for now lets hold off on $SUBJECT patch.  Seems we can
> come up with a broader solution.  Thanks.
> 
> Kevin
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2012-October/124427.html


--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Shubhrajyoti Datta Oct. 15, 2012, 10:11 a.m. UTC | #6
On Mon, Oct 15, 2012 at 2:46 PM, Kalle Jokiniemi
<kalle.jokiniemi@jollamobile.com> wrote:
> ma, 2012-10-15 kello 09:21 +0300, Kalle Jokiniemi kirjoitti:
>> Hi,
>>
>> pe, 2012-10-12 kello 14:46 +0000, Strashko, Grygorii kirjoitti:
>> > Hi Kevin,
>> >
>> > yep, [1] is the same fix - thanks.
>> >
>> > Hi Kalle,
>> >
>> > i've applied these changes and PM runtime fix on top of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git (omap2plus_defconfig)
>> > Could you check it with your use case, pls? (just to be sure that idea is right)
>>
>> Odd, it's not working. I'll add some debug prints to see what happens
>> there.
>
> Well, seems after enabling irq 23 in the resume_noirq, someone does
> i2c_xfer and there is consequent flood of i2c_xfers and interrupts.
If there is continuous xfers, you could enable debug LL and see who is
queuing the
transfers.

>
> Not sure now how these IRQ numbers get mapped these days, my debug print
> says it's irq number 72 (UART1 from TRM) that is flooding (although it's
> printed from the i2c-omap isr function, so it's still I2C bus irq...).

Can you do a cat /proc/interrupts


>
> The irq enabling (in resume_noirq) is still slightly progressing after
> the flooding starts, but my watchdog kicks in before we get to the
> finish.
>
> Attached my debug prints patch and log. I used also "no_console_suspend"
> boot option.
>
> - Kalle
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kalle Jokiniemi Oct. 15, 2012, 2:10 p.m. UTC | #7
ma, 2012-10-15 kello 15:41 +0530, Shubhrajyoti Datta kirjoitti:
> On Mon, Oct 15, 2012 at 2:46 PM, Kalle Jokiniemi
> <kalle.jokiniemi@jollamobile.com> wrote:
> > ma, 2012-10-15 kello 09:21 +0300, Kalle Jokiniemi kirjoitti:
> >> Hi,
> >>
> >> pe, 2012-10-12 kello 14:46 +0000, Strashko, Grygorii kirjoitti:
> >> > Hi Kevin,
> >> >
> >> > yep, [1] is the same fix - thanks.
> >> >
> >> > Hi Kalle,
> >> >
> >> > i've applied these changes and PM runtime fix on top of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git (omap2plus_defconfig)
> >> > Could you check it with your use case, pls? (just to be sure that idea is right)
> >>
> >> Odd, it's not working. I'll add some debug prints to see what happens
> >> there.
> >
> > Well, seems after enabling irq 23 in the resume_noirq, someone does
> > i2c_xfer and there is consequent flood of i2c_xfers and interrupts.
> If there is continuous xfers, you could enable debug LL and see who is
> queuing the
> transfers.
> 
> >
> > Not sure now how these IRQ numbers get mapped these days, my debug print
> > says it's irq number 72 (UART1 from TRM) that is flooding (although it's
> > printed from the i2c-omap isr function, so it's still I2C bus irq...).
> 
> Can you do a cat /proc/interrupts

Yes :)

[root@localhost proc]# cat
interrupts                                          

CPU0                                                                 
 20:          0      INTC  gpmc
 23:          2      INTC  TWL4030-PIH
 25:          0      INTC  l3-debug-irq
 26:          0      INTC  l3-app-irq
 28:      48157      INTC  DMA
 40:          0      INTC  omap-iommu.0
 52:          0      INTC  dsp_wdt
 53:     807807      INTC  gp_timer
 65:          0      INTC  omap-sham
 72:       5490      INTC  omap_i2c
 73:         85      INTC  omap_i2c
 77:          0      INTC  omap_i2c
 90:       1069      INTC  OMAP UART2
102:      55940      INTC  mmc0
179:       6142      GPIO  omap2-onenand
306:      44666      PRCM  pm_wkup
315:          4      PRCM  hwmod_io, pm_io
338:          0   twl4030  twl4030_gpio
343:          2   twl4030  twl4030_power
346:          0   twl4030  twl4030_pwrbutton
348:          2   twl4030  twl4030_usb
349:          0   twl4030  rtc0

Hmm, I did not notice that PIH handler before, makes sense now that it
triggers the flood (irq 23) as it is really the one that passes the
interrupts to other handlers.

- Kalle

> 
> 
> >
> > The irq enabling (in resume_noirq) is still slightly progressing after
> > the flooding starts, but my watchdog kicks in before we get to the
> > finish.
> >
> > Attached my debug prints patch and log. I used also "no_console_suspend"
> > boot option.
> >
> > - Kalle
> >


--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index a0e49f6..cb09e20 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -586,6 +586,9 @@  omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        if (IS_ERR_VALUE(r))
                goto out;
 
+       /* We have the bus, enable IRQ */
+       enable_irq(dev->irq);
+
        r = omap_i2c_wait_for_bb(dev);
        if (r < 0)
                goto out;
@@ -606,6 +609,7 @@  omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
                r = num;
 
        omap_i2c_wait_for_bb(dev);
+       disable_irq(dev->irq);
 out:
        pm_runtime_put(dev->dev);
        return r;
@@ -1060,6 +1064,9 @@  omap_i2c_probe(struct platform_device *pdev)
                                                                   omap_i2c_isr;
        r = request_irq(dev->irq, isr, IRQF_NO_SUSPEND, pdev->name, dev);
 
+       /* We enable IRQ only when request for I2C from master */
+        disable_irq(dev->irq);
+
        if (r) {
                dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
                goto err_unuse_clocks;
@@ -1182,7 +1189,23 @@  static int omap_i2c_runtime_resume(struct device *dev)
 }
 #endif /* CONFIG_PM_RUNTIME */
 
+static int omap_i2c_suspend(struct device *dev)
+{
+       int ret;
+
+       /*
+        *  Enable I2C device, so it will be accessible during
+        * later stages of suspending when device Runtime PM is disabled.
+        * I2C device will be turned off at "noirq" suspend stage.
+        */
+       ret = pm_runtime_resume(dev);
+       if (ret < 0)
+               return ret;
+       return 0;
+}
+
 static struct dev_pm_ops omap_i2c_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(omap_i2c_suspend, NULL)
        SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend,
                           omap_i2c_runtime_resume, NULL)
 };