From: Tony Lindgren <tony@atomide.com>
To: Felipe Balbi <balbi@ti.com>
Cc: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>,
Alan Stern <stern@rowland.harvard.edu>,
Andreas Fenkart <afenkart@gmail.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Huiquan Zhong <huiquan.zhong@intel.com>,
Kevin Hilman <khilman@kernel.org>, NeilBrown <neilb@suse.de>,
Mika Westerberg <mika.westerberg@linux.intel.com>,
Nishanth Menon <nm@ti.com>,
Peter Hurley <peter@hurleysoftware.com>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Ulf Hansson <ulf.hansson@linaro.org>,
Thomas Gleixner <tglx@linutronix.de>,
linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-serial@vger.kernel.org, linux-omap@vger.kernel.org
Subject: Re: [PATCH 2/5] PM / Wakeirq: Add automated device wake IRQ handling
Date: Thu, 14 May 2015 08:59:46 -0700 [thread overview]
Message-ID: <20150514155945.GL15563@atomide.com> (raw)
In-Reply-To: <20150514020634.GB20006@saruman.tx.rr.com>
* Felipe Balbi <balbi@ti.com> [150513 19:09]:
> On Wed, May 13, 2015 at 04:36:33PM -0700, Tony Lindgren wrote:
> > --- a/arch/arm/mach-omap2/Kconfig
> > +++ b/arch/arm/mach-omap2/Kconfig
> > @@ -85,6 +85,7 @@ config ARCH_OMAP2PLUS
> > select OMAP_DM_TIMER
> > select OMAP_GPMC
> > select PINCTRL
> > + select PM_WAKEIRQ if PM_SLEEP
> > select SOC_BUS
> > select TI_PRIV_EDMA
> > select OMAP_IRQCHIP
>
> seems like enabling this for OMAP should be a patch of its own.
Sure if people prefer that.
> > --- /dev/null
> > +++ b/drivers/base/power/wakeirq.c
> > +
> > +err_unlock:
> > + spin_unlock_irqrestore(&dev->power.lock, flags);
> > +err_free_mem:
>
> minor nit, there's no memory being freed here :-)
Will fix.
> > +void dev_pm_clear_wake_irq(struct device *dev)
> > +{
> > + struct wake_irq *wirq = dev->power.wakeirq;
> > + unsigned long flags;
> > +
> > + if (!wirq)
>
> WARN() to catch bad users ? Maybe with unlikely() around to give
> compiler a hint that this is likely not going to happen ?
Sure.
> > +static irqreturn_t handle_threaded_wakeirq(int wakeirq, void *_wirq)
> > +{
> > + struct wake_irq *wirq = _wirq;
> > + irqreturn_t ret = IRQ_NONE;
> > +
> > + if (!pm_runtime_suspended(wirq->dev))
>
> should you WARN() here ? Why would this IRQ fire if we're not
> pm_runtime_suspended() ?
Hmm or we could just leave it out. I had it initially to test
things with the wake-up interrupt enabled during runtime also.
> > +int dev_pm_request_wake_irq(struct device *dev,
> > + int irq,
> > + irq_handler_t handler,
> > + unsigned long irqflags,
> > + void *data)
> > +{
> > + struct wake_irq *wirq;
> > + int err;
> > +
> > + wirq = devm_kzalloc(dev, sizeof(*wirq), GFP_KERNEL);
> > + if (!wirq)
> > + return -ENOMEM;
> > +
> > + wirq->dev = dev;
> > + wirq->irq = irq;
> > + wirq->handler = handler;
>
> you need to make sure that IRQF_ONESHOT is set in cases where handler is
> NULL. Either set it by default:
>
> if (!handler)
> irqflags |= IRQF_ONESHOT;
>
> or WARN() about it:
>
> WARN_ON((!handler && !(irqflags & IRQF_ONESHOT));
>
> Actually, after reading more of the code, you have some weird circular
> call chain going on here. If handler is a valid function pointer, you
> use as primary handler, so IRQ core will call it from hardirq context.
> But you also save that pointer as wirq->handler, and call that from
> within handle_threaded_wakeirq(). Essentially, handler() is called
> twice, once with IRQs disabled, one with IRQs (potentially) enabled.
>
> What did you have in mind for handler() anyway, it seems completely
> unnecessary.
Yeah.. Let's just leave it out. You already mentioned it earlier and
there's no use for it.
The device driver can deal with the situation anyways in runtime resume.
And like you said, it must be IRQF_ONESHOT, now there's a chance of
consumer drivers passing other flags too.
The the IO wake-up interrupt vs dedicated wake-up interrupt functions
can be just something like:
int dev_pm_request_wake_irq(struct device *dev, int irq);
int dev_pm_request_wake_irq_managed(struct device *dev, int irq);
> > +void dev_pm_free_wake_irq(struct device *dev)
> > +{
> > + struct wake_irq *wirq = dev->power.wakeirq;
> > + unsigned long flags;
> > +
> > + if (!wirq)
> > + return;
> > +
> > + spin_lock_irqsave(&dev->power.lock, flags);
> > + wirq->manage_irq = false;
> > + spin_unlock_irqrestore(&dev->power.lock, flags);
> > + devm_free_irq(wirq->dev, wirq->irq, wirq);
>
> this seems unnecessary, the IRQ will be freed anyway when the device
> kobj is destroyed, dev_pm_clear_wake_irq() seems important, however.
>
> > + dev_pm_clear_wake_irq(dev);
> > +}
The life cycle of the request and free of the wake irq is not the
same as the life cycle of the device driver. For example, serial
drivers can request interrupts on startup and free them on shutdown.
> > +void dev_pm_enable_wake_irq(struct device *dev)
> > +{
> > + struct wake_irq *wirq = dev->power.wakeirq;
> > +
> > + if (wirq && wirq->manage_irq)
> > + enable_irq(wirq->irq);
> > +}
> > +EXPORT_SYMBOL_GPL(dev_pm_enable_wake_irq);
>
> you probably want to enable dev_pm_enable_wake_irq() automatically for
> from rpm_suspend(). According to runtime_pm documentation, wakeup should
> always be enabled for runtime suspended devices. I didn't really look
> through the whole thing yet to know if you did call it or not.
Yes I think we can also automate that part, I've been playing with an
additional patch doing that for pm runtime. Been still thinking if
there's any need to manage that in the consomer driver, I guess not.
> > +void dev_pm_disable_wake_irq(struct device *dev)
> > +{
> > + struct wake_irq *wirq = dev->power.wakeirq;
> > +
> > + if (wirq && wirq->manage_irq)
> > + disable_irq_nosync(wirq->irq);
> > +}
> > +EXPORT_SYMBOL_GPL(dev_pm_disable_wake_irq);
>
> likewise, call this automatically from rpm_resume().
Right.
> This brings up a question, actually. What to do with devices which were
> already runtime suspended when user initiated suspend-to-ram ? Do we
> leave wakeups enabled, or do we revisit device_may_wakeup() and
> conditionally runtime_resume the device, disable wakeup, and let its
> ->suspend() callback be called ?
I believe that's already handled properly, but implemented in each
consumer driver with the if device_may_wakeup enabled_irq_wake.
Regards,
Tony
next prev parent reply other threads:[~2015-05-14 15:59 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-13 23:36 [PATCHv3 0/5] Linux generic wakeirq handling Tony Lindgren
2015-05-13 23:36 ` [PATCH 1/5] PM / Runtime: Update last_busy in rpm_resume Tony Lindgren
2015-05-20 7:36 ` Ulf Hansson
2015-05-13 23:36 ` [PATCH 2/5] PM / Wakeirq: Add automated device wake IRQ handling Tony Lindgren
2015-05-14 2:06 ` Felipe Balbi
2015-05-14 15:51 ` Alan Stern
2015-05-14 15:54 ` Felipe Balbi
2015-05-14 15:59 ` Tony Lindgren [this message]
2015-05-14 16:09 ` Felipe Balbi
2015-05-14 16:28 ` Tony Lindgren
2015-05-14 17:51 ` Tony Lindgren
2015-05-14 21:15 ` Tony Lindgren
2015-05-14 21:25 ` Felipe Balbi
2015-05-14 22:00 ` Rafael J. Wysocki
2015-05-14 21:59 ` Tony Lindgren
2015-05-15 22:25 ` Tony Lindgren
2015-05-16 1:56 ` Felipe Balbi
2015-05-18 22:05 ` Tony Lindgren
2015-05-18 23:44 ` Tony Lindgren
2015-05-19 14:04 ` Rafael J. Wysocki
2015-05-19 14:26 ` Rafael J. Wysocki
2015-05-19 15:09 ` Tony Lindgren
2015-05-19 18:18 ` Tony Lindgren
2015-05-19 23:01 ` Rafael J. Wysocki
2015-05-19 22:41 ` Thomas Gleixner
2015-05-19 23:31 ` Rafael J. Wysocki
2015-05-19 23:27 ` Tony Lindgren
2015-05-20 0:25 ` Rafael J. Wysocki
2015-05-20 2:10 ` Tony Lindgren
2015-05-21 0:54 ` Rafael J. Wysocki
2015-05-21 0:35 ` Tony Lindgren
2015-05-21 1:40 ` Felipe Balbi
2015-05-19 15:15 ` Tony Lindgren
2015-05-13 23:36 ` [PATCH 3/5] serial: omap: Switch wake-up interrupt to generic wakeirq Tony Lindgren
2015-05-28 14:56 ` Tony Lindgren
2015-05-31 7:16 ` Greg Kroah-Hartman
2015-06-01 22:05 ` Tony Lindgren
2015-05-13 23:36 ` [PATCH 4/5] serial: 8250_omap: Move " Tony Lindgren
2015-05-13 23:36 ` [PATCH 5/5] mmc: omap_hsmmc: Change wake-up interrupt to use " Tony Lindgren
2015-05-25 8:38 ` Ulf Hansson
2015-05-27 22:42 ` Rafael J. Wysocki
2015-05-27 22:45 ` Tony Lindgren
2015-05-28 14:36 ` Tony Lindgren
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=20150514155945.GL15563@atomide.com \
--to=tony@atomide.com \
--cc=afenkart@gmail.com \
--cc=balbi@ti.com \
--cc=bigeasy@linutronix.de \
--cc=gregkh@linuxfoundation.org \
--cc=huiquan.zhong@intel.com \
--cc=khilman@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=mika.westerberg@linux.intel.com \
--cc=neilb@suse.de \
--cc=nm@ti.com \
--cc=peter@hurleysoftware.com \
--cc=rafael.j.wysocki@intel.com \
--cc=stern@rowland.harvard.edu \
--cc=tglx@linutronix.de \
--cc=ulf.hansson@linaro.org \
/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;
as well as URLs for NNTP newsgroup(s).