diff mbox

[RFC] PM: Make power domain callbacks take precedence over subsystem ones

Message ID 201104130205.26988.rjw@sisk.pl (mailing list archive)
State RFC
Headers show

Commit Message

Rafael Wysocki April 13, 2011, 12:05 a.m. UTC
From: Rafael J. Wysocki <rjw@sisk.pl>

Change the PM core's behavior related to power domains in such a way
that, if a power domain is defined for a given device, its callbacks
will be executed instead of and not in addition to the device
subsystem's PM callbacks.

The idea behind the initial implementation of power domains handling
by the PM core was that power domain callbacks would be executed in
addition to subsystem callbacks, so that it would be possible to
extend the subsystem callbacks by using power domains.  It turns out,
however, that this wouldn't be really convenient in some important
situations.

For example, there are systems in which power can only be removed
from entire power domains.  On those systems it is not desirable to
execute device drivers' PM callbacks until it is known that power is
going to be removed from the devices in question, which means that
they should be executed by power domain callbacks rather then by
subsystem (e.g. bus type) PM callbacks, because subsystems generally
have no information about what devices belong to which power domain.
Thus, for instance, if the bus type in question is the platform bus
type, its PM callbacks generally should not be called in addition to
power domain callbacks, because they run device drivers' callbacks
unconditionally if defined.

While in principle the default subsystem PM callbacks, or a subset of
them, may be replaced with different functions, it doesn't seem
correct to do so, because that would change the subsystem's behavior
with respect to all devices in the system, regardless of whether or
not they belong to any power domains.  Thus, the only remaining
option is to make power domain callbacks take precedence over
subsystem callbacks.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 drivers/base/power/main.c    |   64 ++++++++++++++++++++-----------------------
 drivers/base/power/runtime.c |   29 ++++++-------------
 2 files changed, 41 insertions(+), 52 deletions(-)

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

Comments

'Alan Stern' April 13, 2011, 2:17 p.m. UTC | #1
On Wed, 13 Apr 2011, Rafael J. Wysocki wrote:

> From: Rafael J. Wysocki <rjw@sisk.pl>
> 
> Change the PM core's behavior related to power domains in such a way
> that, if a power domain is defined for a given device, its callbacks
> will be executed instead of and not in addition to the device
> subsystem's PM callbacks.
> 
> The idea behind the initial implementation of power domains handling
> by the PM core was that power domain callbacks would be executed in
> addition to subsystem callbacks, so that it would be possible to
> extend the subsystem callbacks by using power domains.  It turns out,
> however, that this wouldn't be really convenient in some important
> situations.
> 
> For example, there are systems in which power can only be removed
> from entire power domains.  On those systems it is not desirable to
> execute device drivers' PM callbacks until it is known that power is
> going to be removed from the devices in question, which means that
> they should be executed by power domain callbacks rather then by
> subsystem (e.g. bus type) PM callbacks, because subsystems generally
> have no information about what devices belong to which power domain.
> Thus, for instance, if the bus type in question is the platform bus
> type, its PM callbacks generally should not be called in addition to
> power domain callbacks, because they run device drivers' callbacks
> unconditionally if defined.

What about systems where it makes sense to execute the subsystem 
callbacks even if power isn't going to be removed from the device?  
It's quite possible that the subsystem could reduce the device's power 
consumption even when the device isn't powered down completely.

Is the extra overhead of invoking the subsystem callback really all 
that troublesome?

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Grant Likely April 13, 2011, 4:15 p.m. UTC | #2
On Wed, Apr 13, 2011 at 8:17 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> On Wed, 13 Apr 2011, Rafael J. Wysocki wrote:
>
>> From: Rafael J. Wysocki <rjw@sisk.pl>
>>
>> Change the PM core's behavior related to power domains in such a way
>> that, if a power domain is defined for a given device, its callbacks
>> will be executed instead of and not in addition to the device
>> subsystem's PM callbacks.
>>
>> The idea behind the initial implementation of power domains handling
>> by the PM core was that power domain callbacks would be executed in
>> addition to subsystem callbacks, so that it would be possible to
>> extend the subsystem callbacks by using power domains.  It turns out,
>> however, that this wouldn't be really convenient in some important
>> situations.
>>
>> For example, there are systems in which power can only be removed
>> from entire power domains.  On those systems it is not desirable to
>> execute device drivers' PM callbacks until it is known that power is
>> going to be removed from the devices in question, which means that
>> they should be executed by power domain callbacks rather then by
>> subsystem (e.g. bus type) PM callbacks, because subsystems generally
>> have no information about what devices belong to which power domain.
>> Thus, for instance, if the bus type in question is the platform bus
>> type, its PM callbacks generally should not be called in addition to
>> power domain callbacks, because they run device drivers' callbacks
>> unconditionally if defined.
>
> What about systems where it makes sense to execute the subsystem
> callbacks even if power isn't going to be removed from the device?
> It's quite possible that the subsystem could reduce the device's power
> consumption even when the device isn't powered down completely.

The understanding Rafael and I came to was that if a power domain is
attached to a device, then the power domain becomes the responsible
party.  Normally this means it will turn around and immediately call
the bus_type pm ops, but it has the option to not call them if for a
particular system it knows better, or to defer calling them.

Basically, if you're using a power domain, it is assumed that the
power domain has particular knowledge about the system, and it should
have the option to override the default behaviour.

>
> Is the extra overhead of invoking the subsystem callback really all
> that troublesome?

It isn't an overhead problem.  It's a control & complexity problem.
We could try to implement a heuristic or api to control when the bus
type PM ops should be overridden, but I think it is cleaner to make it
a rule that if you implement a power domain, then that power domain
becomes responsible for all PM operations.

g.
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Magnus Damm April 14, 2011, 6:20 p.m. UTC | #3
Hi Rafael,

On Wed, Apr 13, 2011 at 9:05 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rjw@sisk.pl>
>
> Change the PM core's behavior related to power domains in such a way
> that, if a power domain is defined for a given device, its callbacks
> will be executed instead of and not in addition to the device
> subsystem's PM callbacks.

Thanks for your work on this! I'm very happy to see a more fine
grained interface for SoC specific code compared to the weak symbols
and other coarse grained alternatives for the platform bus.

My only thought on this is if we really want to limit ourselves to
only control power domains using these callbacks. I can imagine that
some SoCs want to do other non-power domain specific operations with
these callbacks, and if so, perhaps using the term power domain as
name of the pointer in struct device would be somewhat odd. OTOH, I
really dislike naming discussions in general and I can't really think
of any good names. So it all looks more like a set of system specific
PM override hooks.

Or is there something that is really power domain specific with these hooks?

Thanks,

/ magnus
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael Wysocki April 14, 2011, 10:45 p.m. UTC | #4
On Thursday, April 14, 2011, Magnus Damm wrote:
> Hi Rafael,
> 
> On Wed, Apr 13, 2011 at 9:05 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rjw@sisk.pl>
> >
> > Change the PM core's behavior related to power domains in such a way
> > that, if a power domain is defined for a given device, its callbacks
> > will be executed instead of and not in addition to the device
> > subsystem's PM callbacks.
> 
> Thanks for your work on this! I'm very happy to see a more fine
> grained interface for SoC specific code compared to the weak symbols
> and other coarse grained alternatives for the platform bus.
> 
> My only thought on this is if we really want to limit ourselves to
> only control power domains using these callbacks. I can imagine that
> some SoCs want to do other non-power domain specific operations with
> these callbacks, and if so, perhaps using the term power domain as
> name of the pointer in struct device would be somewhat odd. OTOH, I
> really dislike naming discussions in general and I can't really think
> of any good names. So it all looks more like a set of system specific
> PM override hooks.
> 
> Or is there something that is really power domain specific with these hooks?

Not in principle, but I think there is.  Namely, if there are two groups
of devices belonging to the same bus type (e.g. platform) that each require
different PM handling, it is legitimate to call them "power domains" (where
"domain" means "a set of devices related to each other because of the way
they need to be handled"), even if they don't share power resources.

Of course, if they do share power resources, the term is just right. :-)

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael Wysocki April 14, 2011, 11:12 p.m. UTC | #5
On Wednesday, April 13, 2011, Grant Likely wrote:
> On Wed, Apr 13, 2011 at 8:17 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > On Wed, 13 Apr 2011, Rafael J. Wysocki wrote:
> >
> >> From: Rafael J. Wysocki <rjw@sisk.pl>
> >>
> >> Change the PM core's behavior related to power domains in such a way
> >> that, if a power domain is defined for a given device, its callbacks
> >> will be executed instead of and not in addition to the device
> >> subsystem's PM callbacks.
> >>
> >> The idea behind the initial implementation of power domains handling
> >> by the PM core was that power domain callbacks would be executed in
> >> addition to subsystem callbacks, so that it would be possible to
> >> extend the subsystem callbacks by using power domains.  It turns out,
> >> however, that this wouldn't be really convenient in some important
> >> situations.
> >>
> >> For example, there are systems in which power can only be removed
> >> from entire power domains.  On those systems it is not desirable to
> >> execute device drivers' PM callbacks until it is known that power is
> >> going to be removed from the devices in question, which means that
> >> they should be executed by power domain callbacks rather then by
> >> subsystem (e.g. bus type) PM callbacks, because subsystems generally
> >> have no information about what devices belong to which power domain.
> >> Thus, for instance, if the bus type in question is the platform bus
> >> type, its PM callbacks generally should not be called in addition to
> >> power domain callbacks, because they run device drivers' callbacks
> >> unconditionally if defined.
> >
> > What about systems where it makes sense to execute the subsystem
> > callbacks even if power isn't going to be removed from the device?
> > It's quite possible that the subsystem could reduce the device's power
> > consumption even when the device isn't powered down completely.
> 
> The understanding Rafael and I came to was that if a power domain is
> attached to a device, then the power domain becomes the responsible
> party.  Normally this means it will turn around and immediately call
> the bus_type pm ops, but it has the option to not call them if for a
> particular system it knows better, or to defer calling them.
> 
> Basically, if you're using a power domain, it is assumed that the
> power domain has particular knowledge about the system, and it should
> have the option to override the default behaviour.
> 
> >
> > Is the extra overhead of invoking the subsystem callback really all
> > that troublesome?
> 
> It isn't an overhead problem.  It's a control & complexity problem.
> We could try to implement a heuristic or api to control when the bus
> type PM ops should be overridden, but I think it is cleaner to make it
> a rule that if you implement a power domain, then that power domain
> becomes responsible for all PM operations.

Well said. :-)

I'm taking that as an ACK for my patch if you don't mind.

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael Wysocki April 14, 2011, 11:16 p.m. UTC | #6
Hi,

The following two patches are based on top of
https://patchwork.kernel.org/patch/702401/ .

[1/2] converts shmobile (both the ARM and SH flavors) to using a power domain
for overriding the platform bus type's PM callbacks, which makes it possible
to remove the __weak definitions of the runtime PM callbacks from platform.c,
which is done in [2/2].

Comments welcome.

Thanks,
Rafael

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
'Alan Stern' April 15, 2011, 2:34 p.m. UTC | #7
On Fri, 15 Apr 2011, Rafael J. Wysocki wrote:

> On Thursday, April 14, 2011, Magnus Damm wrote:

> > My only thought on this is if we really want to limit ourselves to
> > only control power domains using these callbacks. I can imagine that
> > some SoCs want to do other non-power domain specific operations with
> > these callbacks, and if so, perhaps using the term power domain as
> > name of the pointer in struct device would be somewhat odd. OTOH, I
> > really dislike naming discussions in general and I can't really think
> > of any good names. So it all looks more like a set of system specific
> > PM override hooks.
> > 
> > Or is there something that is really power domain specific with these hooks?
> 
> Not in principle, but I think there is.  Namely, if there are two groups
> of devices belonging to the same bus type (e.g. platform) that each require
> different PM handling, it is legitimate to call them "power domains" (where
> "domain" means "a set of devices related to each other because of the way
> they need to be handled"), even if they don't share power resources.
> 
> Of course, if they do share power resources, the term is just right. :-)

They could be called "PM domains" instead of "power domains".  That's 
legitimate because they do get used by the PM core, even if they don't 
literally involve groups of devices sharing the same power supply.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Grant Likely April 15, 2011, 2:38 p.m. UTC | #8
On Thu, Apr 14, 2011 at 5:12 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Wednesday, April 13, 2011, Grant Likely wrote:
>> On Wed, Apr 13, 2011 at 8:17 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
>> > On Wed, 13 Apr 2011, Rafael J. Wysocki wrote:
>> >
>> >> From: Rafael J. Wysocki <rjw@sisk.pl>
>> >>
>> >> Change the PM core's behavior related to power domains in such a way
>> >> that, if a power domain is defined for a given device, its callbacks
>> >> will be executed instead of and not in addition to the device
>> >> subsystem's PM callbacks.
>> >>
>> >> The idea behind the initial implementation of power domains handling
>> >> by the PM core was that power domain callbacks would be executed in
>> >> addition to subsystem callbacks, so that it would be possible to
>> >> extend the subsystem callbacks by using power domains.  It turns out,
>> >> however, that this wouldn't be really convenient in some important
>> >> situations.
>> >>
>> >> For example, there are systems in which power can only be removed
>> >> from entire power domains.  On those systems it is not desirable to
>> >> execute device drivers' PM callbacks until it is known that power is
>> >> going to be removed from the devices in question, which means that
>> >> they should be executed by power domain callbacks rather then by
>> >> subsystem (e.g. bus type) PM callbacks, because subsystems generally
>> >> have no information about what devices belong to which power domain.
>> >> Thus, for instance, if the bus type in question is the platform bus
>> >> type, its PM callbacks generally should not be called in addition to
>> >> power domain callbacks, because they run device drivers' callbacks
>> >> unconditionally if defined.
>> >
>> > What about systems where it makes sense to execute the subsystem
>> > callbacks even if power isn't going to be removed from the device?
>> > It's quite possible that the subsystem could reduce the device's power
>> > consumption even when the device isn't powered down completely.
>>
>> The understanding Rafael and I came to was that if a power domain is
>> attached to a device, then the power domain becomes the responsible
>> party.  Normally this means it will turn around and immediately call
>> the bus_type pm ops, but it has the option to not call them if for a
>> particular system it knows better, or to defer calling them.
>>
>> Basically, if you're using a power domain, it is assumed that the
>> power domain has particular knowledge about the system, and it should
>> have the option to override the default behaviour.
>>
>> >
>> > Is the extra overhead of invoking the subsystem callback really all
>> > that troublesome?
>>
>> It isn't an overhead problem.  It's a control & complexity problem.
>> We could try to implement a heuristic or api to control when the bus
>> type PM ops should be overridden, but I think it is cleaner to make it
>> a rule that if you implement a power domain, then that power domain
>> becomes responsible for all PM operations.
>
> Well said. :-)
>
> I'm taking that as an ACK for my patch if you don't mind.

And so you should.

g.
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
'Alan Stern' April 15, 2011, 2:39 p.m. UTC | #9
On Fri, 15 Apr 2011, Rafael J. Wysocki wrote:

> On Wednesday, April 13, 2011, Grant Likely wrote:
> > On Wed, Apr 13, 2011 at 8:17 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > > On Wed, 13 Apr 2011, Rafael J. Wysocki wrote:
> > >
> > >> From: Rafael J. Wysocki <rjw@sisk.pl>
> > >>
> > >> Change the PM core's behavior related to power domains in such a way
> > >> that, if a power domain is defined for a given device, its callbacks
> > >> will be executed instead of and not in addition to the device
> > >> subsystem's PM callbacks.
> > >>
> > >> The idea behind the initial implementation of power domains handling
> > >> by the PM core was that power domain callbacks would be executed in
> > >> addition to subsystem callbacks, so that it would be possible to
> > >> extend the subsystem callbacks by using power domains.  It turns out,
> > >> however, that this wouldn't be really convenient in some important
> > >> situations.
> > >>
> > >> For example, there are systems in which power can only be removed
> > >> from entire power domains.  On those systems it is not desirable to
> > >> execute device drivers' PM callbacks until it is known that power is
> > >> going to be removed from the devices in question, which means that
> > >> they should be executed by power domain callbacks rather then by
> > >> subsystem (e.g. bus type) PM callbacks, because subsystems generally
> > >> have no information about what devices belong to which power domain.
> > >> Thus, for instance, if the bus type in question is the platform bus
> > >> type, its PM callbacks generally should not be called in addition to
> > >> power domain callbacks, because they run device drivers' callbacks
> > >> unconditionally if defined.
> > >
> > > What about systems where it makes sense to execute the subsystem
> > > callbacks even if power isn't going to be removed from the device?
> > > It's quite possible that the subsystem could reduce the device's power
> > > consumption even when the device isn't powered down completely.
> > 
> > The understanding Rafael and I came to was that if a power domain is
> > attached to a device, then the power domain becomes the responsible
> > party.  Normally this means it will turn around and immediately call
> > the bus_type pm ops, but it has the option to not call them if for a
> > particular system it knows better, or to defer calling them.
> > 
> > Basically, if you're using a power domain, it is assumed that the
> > power domain has particular knowledge about the system, and it should
> > have the option to override the default behaviour.
> > 
> > >
> > > Is the extra overhead of invoking the subsystem callback really all
> > > that troublesome?
> > 
> > It isn't an overhead problem.  It's a control & complexity problem.
> > We could try to implement a heuristic or api to control when the bus
> > type PM ops should be overridden, but I think it is cleaner to make it
> > a rule that if you implement a power domain, then that power domain
> > becomes responsible for all PM operations.
> 
> Well said. :-)
> 
> I'm taking that as an ACK for my patch if you don't mind.

Grant presented a convincing explanation.  I have no objections.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael Wysocki April 15, 2011, 11:18 p.m. UTC | #10
On Friday, April 15, 2011, Alan Stern wrote:
> On Fri, 15 Apr 2011, Rafael J. Wysocki wrote:
> 
> > On Thursday, April 14, 2011, Magnus Damm wrote:
> 
> > > My only thought on this is if we really want to limit ourselves to
> > > only control power domains using these callbacks. I can imagine that
> > > some SoCs want to do other non-power domain specific operations with
> > > these callbacks, and if so, perhaps using the term power domain as
> > > name of the pointer in struct device would be somewhat odd. OTOH, I
> > > really dislike naming discussions in general and I can't really think
> > > of any good names. So it all looks more like a set of system specific
> > > PM override hooks.
> > > 
> > > Or is there something that is really power domain specific with these hooks?
> > 
> > Not in principle, but I think there is.  Namely, if there are two groups
> > of devices belonging to the same bus type (e.g. platform) that each require
> > different PM handling, it is legitimate to call them "power domains" (where
> > "domain" means "a set of devices related to each other because of the way
> > they need to be handled"), even if they don't share power resources.
> > 
> > Of course, if they do share power resources, the term is just right. :-)
> 
> They could be called "PM domains" instead of "power domains".  That's 
> legitimate because they do get used by the PM core, even if they don't 
> literally involve groups of devices sharing the same power supply.

Well, "power domain" can be regarded as a short form of "power management
domain", which makes the point kind of moot. ;-)

Rafael

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael Wysocki April 24, 2011, 9:30 p.m. UTC | #11
Hi,

Taking the feedback from the last version of the patchset into account
I reworked patches [7/9] and [8/9] so that multiple clocks can be used for
runtime PM.  I also fixed a couple of build issues (the patches have been
built for x86, ARM/shmobile and ARM/OMAP1).

On Sunday, April 17, 2011, Rafael J. Wysocki wrote:
> Hi,
> 
> The following series of patches is my attempt to consolidate the shmobile and
> OMAP runtime PM code using power domains so that it is not necessary to
> replace the platform bus type's runtime PM callbacks any more.
> 
> Some of the patches have already been posted, some are new and some are
> from Kevin. :-)

The high-level description of what the patches do hasn't changed, so:

[1/9] - Make power domain callbacks take precedence over subsystem ones
        (this one has been discussed already).

[2/9] - Export the platform bus type's default PM callbacks so that they
        can be used in power domain objects.

[3/9] - Use a default power domain for runtime PM on shmobile (both ARM
        and SH flavors) instead of replacing the platform bus type's
        runtime PM callbacks (using __weak).

[4/9] - Use generic runtime PM callbacks directly in the platform bus type.

[5/9] - Move OMAP2 runtime PM implementation to using a power domain object
        (patch from Kevin rebased on top of [1-4/9]).

[6/9] - Add subsystem data field to struct dev_pm_info.

[7/9] - Introduce generic clock manipulation routines for runtime PM and
        convert ARM shmobile to using them.

[8/9] - Move OMAP1 runtime PM to the new core infrastructure.

[9/9] - Remove platform_bus_set_pm_ops() (patch from Kevin).

If there are no objections (or reports of breakage), I'd like to push these
patches through the suspend-2.6 tree in the 2.6.40 merge window.

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" 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

Index: linux-2.6/drivers/base/power/runtime.c
===================================================================
--- linux-2.6.orig/drivers/base/power/runtime.c
+++ linux-2.6/drivers/base/power/runtime.c
@@ -168,7 +168,6 @@  static int rpm_check_suspend_allowed(str
 static int rpm_idle(struct device *dev, int rpmflags)
 {
 	int (*callback)(struct device *);
-	int (*domain_callback)(struct device *);
 	int retval;
 
 	retval = rpm_check_suspend_allowed(dev);
@@ -214,7 +213,9 @@  static int rpm_idle(struct device *dev,
 
 	dev->power.idle_notification = true;
 
-	if (dev->type && dev->type->pm)
+	if (dev->pwr_domain)
+		callback = dev->pwr_domain->ops.runtime_idle;
+	else if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_idle;
 	else if (dev->class && dev->class->pm)
 		callback = dev->class->pm->runtime_idle;
@@ -223,19 +224,10 @@  static int rpm_idle(struct device *dev,
 	else
 		callback = NULL;
 
-	if (dev->pwr_domain)
-		domain_callback = dev->pwr_domain->ops.runtime_idle;
-	else
-		domain_callback = NULL;
-
-	if (callback || domain_callback) {
+	if (callback) {
 		spin_unlock_irq(&dev->power.lock);
 
-		if (domain_callback)
-			retval = domain_callback(dev);
-
-		if (!retval && callback)
-			callback(dev);
+		callback(dev);
 
 		spin_lock_irq(&dev->power.lock);
 	}
@@ -382,7 +374,9 @@  static int rpm_suspend(struct device *de
 
 	__update_runtime_status(dev, RPM_SUSPENDING);
 
-	if (dev->type && dev->type->pm)
+	if (dev->pwr_domain)
+		callback = dev->pwr_domain->ops.runtime_suspend;
+	else if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_suspend;
 	else if (dev->class && dev->class->pm)
 		callback = dev->class->pm->runtime_suspend;
@@ -400,8 +394,6 @@  static int rpm_suspend(struct device *de
 		else
 			pm_runtime_cancel_pending(dev);
 	} else {
-		if (dev->pwr_domain)
-			rpm_callback(dev->pwr_domain->ops.runtime_suspend, dev);
  no_callback:
 		__update_runtime_status(dev, RPM_SUSPENDED);
 		pm_runtime_deactivate_timer(dev);
@@ -582,9 +574,8 @@  static int rpm_resume(struct device *dev
 	__update_runtime_status(dev, RPM_RESUMING);
 
 	if (dev->pwr_domain)
-		rpm_callback(dev->pwr_domain->ops.runtime_resume, dev);
-
-	if (dev->type && dev->type->pm)
+		callback = dev->pwr_domain->ops.runtime_resume;
+	else if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_resume;
 	else if (dev->class && dev->class->pm)
 		callback = dev->class->pm->runtime_resume;
Index: linux-2.6/drivers/base/power/main.c
===================================================================
--- linux-2.6.orig/drivers/base/power/main.c
+++ linux-2.6/drivers/base/power/main.c
@@ -425,10 +425,8 @@  static int device_resume_noirq(struct de
 
 	if (dev->pwr_domain) {
 		pm_dev_dbg(dev, state, "EARLY power domain ");
-		pm_noirq_op(dev, &dev->pwr_domain->ops, state);
-	}
-
-	if (dev->type && dev->type->pm) {
+		error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+	} else if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "EARLY type ");
 		error = pm_noirq_op(dev, dev->type->pm, state);
 	} else if (dev->class && dev->class->pm) {
@@ -516,7 +514,8 @@  static int device_resume(struct device *
 
 	if (dev->pwr_domain) {
 		pm_dev_dbg(dev, state, "power domain ");
-		pm_op(dev, &dev->pwr_domain->ops, state);
+		error = pm_op(dev, &dev->pwr_domain->ops, state);
+		goto End;
 	}
 
 	if (dev->type && dev->type->pm) {
@@ -628,12 +627,11 @@  static void device_complete(struct devic
 {
 	device_lock(dev);
 
-	if (dev->pwr_domain && dev->pwr_domain->ops.complete) {
+	if (dev->pwr_domain) {
 		pm_dev_dbg(dev, state, "completing power domain ");
-		dev->pwr_domain->ops.complete(dev);
-	}
-
-	if (dev->type && dev->type->pm) {
+		if (dev->pwr_domain->ops.complete)
+			dev->pwr_domain->ops.complete(dev);
+	} else if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "completing type ");
 		if (dev->type->pm->complete)
 			dev->type->pm->complete(dev);
@@ -731,7 +729,12 @@  static int device_suspend_noirq(struct d
 {
 	int error;
 
-	if (dev->type && dev->type->pm) {
+	if (dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "LATE power domain ");
+		error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+		if (error)
+			return error;
+	} else if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "LATE type ");
 		error = pm_noirq_op(dev, dev->type->pm, state);
 		if (error)
@@ -748,11 +751,6 @@  static int device_suspend_noirq(struct d
 			return error;
 	}
 
-	if (dev->pwr_domain) {
-		pm_dev_dbg(dev, state, "LATE power domain ");
-		pm_noirq_op(dev, &dev->pwr_domain->ops, state);
-	}
-
 	return 0;
 }
 
@@ -840,21 +838,27 @@  static int __device_suspend(struct devic
 		goto End;
 	}
 
+	if (dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "power domain ");
+		error = pm_op(dev, &dev->pwr_domain->ops, state);
+		goto End;
+	}
+
 	if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "type ");
 		error = pm_op(dev, dev->type->pm, state);
-		goto Domain;
+		goto End;
 	}
 
 	if (dev->class) {
 		if (dev->class->pm) {
 			pm_dev_dbg(dev, state, "class ");
 			error = pm_op(dev, dev->class->pm, state);
-			goto Domain;
+			goto End;
 		} else if (dev->class->suspend) {
 			pm_dev_dbg(dev, state, "legacy class ");
 			error = legacy_suspend(dev, state, dev->class->suspend);
-			goto Domain;
+			goto End;
 		}
 	}
 
@@ -868,12 +872,6 @@  static int __device_suspend(struct devic
 		}
 	}
 
- Domain:
-	if (!error && dev->pwr_domain) {
-		pm_dev_dbg(dev, state, "power domain ");
-		pm_op(dev, &dev->pwr_domain->ops, state);
-	}
-
  End:
 	device_unlock(dev);
 	complete_all(&dev->power.completion);
@@ -964,7 +962,14 @@  static int device_prepare(struct device
 
 	device_lock(dev);
 
-	if (dev->type && dev->type->pm) {
+	if (dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "preparing power domain ");
+		if (dev->pwr_domain->ops.prepare)
+			error = dev->pwr_domain->ops.prepare(dev);
+		suspend_report_result(dev->pwr_domain->ops.prepare, error);
+		if (error)
+			goto End;
+	} else if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "preparing type ");
 		if (dev->type->pm->prepare)
 			error = dev->type->pm->prepare(dev);
@@ -983,13 +988,6 @@  static int device_prepare(struct device
 		if (dev->bus->pm->prepare)
 			error = dev->bus->pm->prepare(dev);
 		suspend_report_result(dev->bus->pm->prepare, error);
-		if (error)
-			goto End;
-	}
-
-	if (dev->pwr_domain && dev->pwr_domain->ops.prepare) {
-		pm_dev_dbg(dev, state, "preparing power domain ");
-		dev->pwr_domain->ops.prepare(dev);
 	}
 
  End: