From: Shaohua Li <shaohua.li@intel.com>
To: Pavel Machek <pavel@ucw.cz>
Cc: linux-pm <linux-pm@lists.osdl.org>
Subject: Re: sysdev suspend/resume
Date: Wed, 27 Jul 2005 17:30:10 +0800 [thread overview]
Message-ID: <1122456610.3000.5.camel@linux-hp.sh.intel.com> (raw)
In-Reply-To: <20050727090748.GB4270@elf.ucw.cz>
[-- Attachment #1: Type: text/plain, Size: 5890 bytes --]
Hi,
On Wed, 2005-07-27 at 11:07 +0200, Pavel Machek wrote:
> > > > The return value of sysdev's suspend/resume methods is ignored, is this
> > > > intended (it should not fail?) or just a bug? I'd like to abort the
> > > > suspend process if one device fails.
> > >
> > > I guess patch would be accepted... but please make sure you test those
> > > error paths, and printk name of failing driver.
> > It's a challenge to me, so many loops :). Below patch is a little ugly,
> > but should cover all error paths.
>
> It is indeed quite ugly. Could we get SYSDEV_RESUME inline function
> instead of ugly macro?
It make senses. Thanks for your comments.
>
> > diff -puN drivers/base/sys.c~sysdev drivers/base/sys.c
> > --- linux-2.6.13-rc3/drivers/base/sys.c~sysdev 2005-07-27 10:49:52.831538832 +0800
> > +++ linux-2.6.13-rc3-root/drivers/base/sys.c 2005-07-27 16:25:49.154312008 +0800
> > @@ -288,6 +288,22 @@ void sysdev_shutdown(void)
> > up(&sysdev_drivers_lock);
> > }
> >
> > +#define SYSDEV_RESUME(cls, dev, drv) \
> > + /* First, call the class-specific one */ \
> > + if (cls->resume) \
> > + cls->resume(dev); \
> > + \
> > + /* Call auxillary drivers next. */ \
> > + list_for_each_entry(drv, &cls->drivers, entry) {\
> > + if (drv->resume) \
> > + drv->resume(dev); \
> > + } \
> > + \
> > + /* Call global drivers. */ \
> > + list_for_each_entry(drv, &sysdev_drivers, entry) {\
> > + if (drv->resume) \
> > + drv->resume(dev); \
> > + }
>
> Are you sure you are resuming already-resumed devices?
What's your point? if sysdev_suspend failed, sysdev_resume isn't called,
so it will not be resumed twice.
Thanks,
Shaohua
Signed-off-by: Shaohua Li<shaohua.li@intel.com>
---
linux-2.6.13-rc3-root/drivers/base/sys.c | 107 ++++++++++++++++++++++++-------
1 files changed, 83 insertions(+), 24 deletions(-)
diff -puN drivers/base/sys.c~sysdev drivers/base/sys.c
--- linux-2.6.13-rc3/drivers/base/sys.c~sysdev 2005-07-27 10:49:52.831538832 +0800
+++ linux-2.6.13-rc3-root/drivers/base/sys.c 2005-07-27 17:22:57.447132280 +0800
@@ -288,6 +288,25 @@ void sysdev_shutdown(void)
up(&sysdev_drivers_lock);
}
+static void inline do_sysdev_resume(struct sysdev_class *cls,
+ struct sys_device *dev, struct sysdev_driver *drv)
+{
+ /* First, call the class-specific one */
+ if (cls->resume)
+ cls->resume(dev);
+
+ /* Call auxillary drivers next. */
+ list_for_each_entry(drv, &cls->drivers, entry) {
+ if (drv->resume)
+ drv->resume(dev);
+ }
+
+ /* Call global drivers. */
+ list_for_each_entry(drv, &sysdev_drivers, entry) {
+ if (drv->resume)
+ drv->resume(dev);
+ }
+}
/**
* sysdev_suspend - Suspend all system devices.
@@ -305,38 +324,93 @@ void sysdev_shutdown(void)
int sysdev_suspend(pm_message_t state)
{
struct sysdev_class * cls;
+ struct sys_device *sysdev, *err_dev;
+ struct sysdev_driver *drv, *err_drv;
+ int ret;
pr_debug("Suspending System Devices\n");
list_for_each_entry_reverse(cls, &system_subsys.kset.list,
kset.kobj.entry) {
- struct sys_device * sysdev;
pr_debug("Suspending type '%s':\n",
kobject_name(&cls->kset.kobj));
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
- struct sysdev_driver * drv;
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
/* Call global drivers first. */
list_for_each_entry(drv, &sysdev_drivers, entry) {
- if (drv->suspend)
- drv->suspend(sysdev, state);
+ if (drv->suspend) {
+ ret = drv->suspend(sysdev, state);
+ if (ret)
+ goto gbl_driver;
+ }
}
/* Call auxillary drivers next. */
list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->suspend)
- drv->suspend(sysdev, state);
+ if (drv->suspend) {
+ ret = drv->suspend(sysdev, state);
+ if (ret)
+ goto aux_driver;
+ }
}
/* Now call the generic one */
- if (cls->suspend)
- cls->suspend(sysdev, state);
+ if (cls->suspend) {
+ ret = cls->suspend(sysdev, state);
+ if (ret)
+ goto cls_driver;
+ }
}
}
return 0;
+ /* resume current sysdev */
+cls_driver:
+ drv = NULL;
+ printk(KERN_ERR "Class suspend failed for %s\n",
+ kobject_name(&sysdev->kobj));
+
+aux_driver:
+ if (drv)
+ printk(KERN_ERR "Class driver suspend failed for %s\n",
+ kobject_name(&sysdev->kobj));
+ list_for_each_entry(err_drv, &cls->drivers, entry) {
+ if (err_drv == drv)
+ break;
+ if (err_drv->resume)
+ err_drv->resume(sysdev);
+ }
+ drv = NULL;
+
+gbl_driver:
+ if (drv)
+ printk(KERN_ERR "sysdev driver suspend failed for %s\n",
+ kobject_name(&sysdev->kobj));
+ list_for_each_entry(err_drv, &sysdev_drivers, entry) {
+ if (err_drv == drv)
+ break;
+ if (err_drv->resume)
+ err_drv->resume(sysdev);
+ }
+ /* resume other sysdevs in current class */
+ list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
+ if (err_dev == sysdev)
+ break;
+ pr_debug(" %s\n", kobject_name(&err_dev->kobj));
+ do_sysdev_resume(cls, err_dev, err_drv);
+ }
+
+ /* resume other classes */
+ list_for_each_entry_continue(cls, &system_subsys.kset.list,
+ kset.kobj.entry) {
+ list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
+ pr_debug(" %s\n", kobject_name(&err_dev->kobj));
+ do_sysdev_resume(cls, err_dev, err_drv);
+ }
+ }
+ return ret;
}
@@ -365,22 +439,7 @@ int sysdev_resume(void)
struct sysdev_driver * drv;
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
- /* First, call the class-specific one */
- if (cls->resume)
- cls->resume(sysdev);
-
- /* Call auxillary drivers next. */
- list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->resume)
- drv->resume(sysdev);
- }
-
- /* Call global drivers. */
- list_for_each_entry(drv, &sysdev_drivers, entry) {
- if (drv->resume)
- drv->resume(sysdev);
- }
-
+ do_sysdev_resume(cls, sysdev, drv);
}
}
return 0;
_
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
next prev parent reply other threads:[~2005-07-27 9:30 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-07-26 5:42 sysdev suspend/resume Shaohua Li
2005-07-26 10:14 ` Pavel Machek
2005-07-27 8:50 ` Shaohua Li
2005-07-27 9:07 ` Pavel Machek
2005-07-27 9:30 ` Shaohua Li [this message]
2005-07-27 9:40 ` Pavel Machek
2005-07-27 17:43 ` Patrick Mochel
2005-07-27 18:50 ` Patrick Mochel
2005-07-28 3:10 ` Shaohua Li
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=1122456610.3000.5.camel@linux-hp.sh.intel.com \
--to=shaohua.li@intel.com \
--cc=linux-pm@lists.osdl.org \
--cc=pavel@ucw.cz \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.