From mboxrd@z Thu Jan 1 00:00:00 1970 From: Shriram Rajagopalan Subject: Re: [PATCH] Use freeze/thaw/restore PM events for Guest suspend/resume/checkpoint Date: Mon, 14 Feb 2011 08:24:55 -0800 Message-ID: References: <20110214162101.24495.80285.stgit@athos.nss.cs.ubc.ca> Reply-To: rshriram@cs.ubc.ca Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Return-path: In-Reply-To: <20110214162101.24495.80285.stgit@athos.nss.cs.ubc.ca> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org On Mon, Feb 14, 2011 at 8:21 AM, Shriram Rajagopalan w= rote: > Use PM_FREEZE, PM_THAW and PM_RESTORE power events for > suspend/resume functionality, instead of PM_SUSPEND and > PM_RESUME. Use of these pm events also fixes the Xen Guest > hangup when taking checkpoints. When a suspend event is cancelled > (i.e. while taking checkpoints once/continuously), we use PM_THAW > instead of PM_RESUME. PM_RESTORE is used when suspend is not > cancelled. See Documentation/power/devices.txt and linux/pm.h > for more info about freeze, thaw and restore. The sequence of > pm events in a suspend-resume scenario is shown below. > > =A0 =A0 =A0 =A0dpm_suspend_start(PMSG_FREEZE); > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dpm_suspend_noirq(PMSG_FREEZE); > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sysdev_suspend(PMSG_FREEZE); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cancelled =3D suspend_hyperca= ll() > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sysdev_resume(); > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 dpm_resume_noirq(cancelled ? PMSG_THAW : PMSG= _RESTORE); > > =A0 =A0 =A0 dpm_resume_end(cancelled ? PMSG_THAW : PMSG_RESTORE); > > Signed-off-by: Shriram Rajagopalan > --- > =A0drivers/net/xen-netfront.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0 =A02 = +- > =A0drivers/xen/manage.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0= 12 ++++++------ > =A0drivers/xen/xenbus/xenbus_probe.c =A0 =A0 =A0 =A0 =A0| =A0 11 ++++++++= +-- > =A0drivers/xen/xenbus/xenbus_probe.h =A0 =A0 =A0 =A0 =A0| =A0 =A03 ++- > =A0drivers/xen/xenbus/xenbus_probe_frontend.c | =A0 10 ++++++++-- > =A0include/xen/xenbus.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0= =A02 +- > =A06 files changed, 27 insertions(+), 13 deletions(-) > > diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c > index 3f71199..22c6288 100644 > --- a/drivers/net/xen-netfront.c > +++ b/drivers/net/xen-netfront.c > @@ -1293,7 +1293,7 @@ static void xennet_disconnect_backend(struct netfro= nt_info *info) > =A0 =A0 =A0 =A0info->rx.sring =3D NULL; > =A0} > > -static int netfront_suspend(struct xenbus_device *dev, pm_message_t stat= e) > +static int netfront_suspend(struct xenbus_device *dev) > =A0{ > =A0 =A0 =A0 =A0struct netfront_info *info =3D dev_get_drvdata(&dev->dev); > =A0 =A0 =A0 =A0struct hrtimer *timer =3D &info->smart_poll.timer; > diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c > index 0b50906..98c856b 100644 > --- a/drivers/xen/manage.c > +++ b/drivers/xen/manage.c > @@ -60,7 +60,7 @@ static int xen_suspend(void *data) > > =A0 =A0 =A0 =A0BUG_ON(!irqs_disabled()); > > - =A0 =A0 =A0 err =3D sysdev_suspend(PMSG_SUSPEND); > + =A0 =A0 =A0 err =3D sysdev_suspend(PMSG_FREEZE); > =A0 =A0 =A0 =A0if (err) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0printk(KERN_ERR "xen_suspend: sysdev_suspe= nd failed: %d\n", > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0err); > @@ -117,16 +117,16 @@ static void do_suspend(void) > =A0 =A0 =A0 =A0} > =A0#endif > > - =A0 =A0 =A0 err =3D dpm_suspend_start(PMSG_SUSPEND); > + =A0 =A0 =A0 err =3D dpm_suspend_start(PMSG_FREEZE); > =A0 =A0 =A0 =A0if (err) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0printk(KERN_ERR "xen suspend: dpm_suspend_= start %d\n", err); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto out_thaw; > =A0 =A0 =A0 =A0} > > - =A0 =A0 =A0 printk(KERN_DEBUG "suspending xenstore...\n"); > + =A0 =A0 =A0 /* printk(KERN_DEBUG "suspending xenstore...\n"); */ > =A0 =A0 =A0 =A0xs_suspend(); > > - =A0 =A0 =A0 err =3D dpm_suspend_noirq(PMSG_SUSPEND); > + =A0 =A0 =A0 err =3D dpm_suspend_noirq(PMSG_FREEZE); > =A0 =A0 =A0 =A0if (err) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0printk(KERN_ERR "dpm_suspend_noirq failed:= %d\n", err); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto out_resume; > @@ -137,7 +137,7 @@ static void do_suspend(void) > =A0 =A0 =A0 =A0else > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0err =3D stop_machine(xen_suspend, &cancell= ed, cpumask_of(0)); > > - =A0 =A0 =A0 dpm_resume_noirq(PMSG_RESUME); > + =A0 =A0 =A0 dpm_resume_noirq(cancelled ? PMSG_THAW : PMSG_RESTORE); > > =A0 =A0 =A0 =A0if (err) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0printk(KERN_ERR "failed to start xen_suspe= nd: %d\n", err); > @@ -151,7 +151,7 @@ out_resume: > =A0 =A0 =A0 =A0} else > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0xs_suspend_cancel(); > > - =A0 =A0 =A0 dpm_resume_end(PMSG_RESUME); > + =A0 =A0 =A0 dpm_resume_end(cancelled ? PMSG_THAW : PMSG_RESTORE); > > =A0 =A0 =A0 =A0/* Make sure timer events get retriggered on all CPUs */ > =A0 =A0 =A0 =A0clock_was_set(); > diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbu= s_probe.c > index 3a83ba2..b61b9f8 100644 > --- a/drivers/xen/xenbus/xenbus_probe.c > +++ b/drivers/xen/xenbus/xenbus_probe.c > @@ -575,7 +575,7 @@ void xenbus_dev_changed(const char *node, struct xen_= bus_type *bus) > =A0} > =A0EXPORT_SYMBOL_GPL(xenbus_dev_changed); > > -int xenbus_dev_suspend(struct device *dev, pm_message_t state) > +int xenbus_dev_suspend(struct device *dev) > =A0{ > =A0 =A0 =A0 =A0int err =3D 0; > =A0 =A0 =A0 =A0struct xenbus_driver *drv; > @@ -587,7 +587,7 @@ int xenbus_dev_suspend(struct device *dev, pm_message= _t state) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return 0; > =A0 =A0 =A0 =A0drv =3D to_xenbus_driver(dev->driver); > =A0 =A0 =A0 =A0if (drv->suspend) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 err =3D drv->suspend(xdev, state); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 err =3D drv->suspend(xdev); > =A0 =A0 =A0 =A0if (err) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0printk(KERN_WARNING > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "xenbus: suspend %s failed: %= i\n", dev_name(dev), err); > @@ -638,6 +638,13 @@ int xenbus_dev_resume(struct device *dev) > =A0} > =A0EXPORT_SYMBOL_GPL(xenbus_dev_resume); > > +int xenbus_dev_cancel(struct device *dev) > +{ > + =A0 =A0 =A0 /* Do nothing */ > + =A0 =A0 =A0 return 0; > +} > +EXPORT_SYMBOL_GPL(xenbus_dev_cancel); > + > =A0/* A flag to determine if xenstored is 'ready' (i.e. has started) */ > =A0int xenstored_ready =3D 0; > > diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbu= s_probe.h > index 0e5fc4c..4019187 100644 > --- a/drivers/xen/xenbus/xenbus_probe.h > +++ b/drivers/xen/xenbus/xenbus_probe.h > @@ -62,8 +62,9 @@ extern void xenbus_dev_changed(const char *node, struct= xen_bus_type *bus); > > =A0extern void xenbus_dev_shutdown(struct device *_dev); > > -extern int xenbus_dev_suspend(struct device *dev, pm_message_t state); > +extern int xenbus_dev_suspend(struct device *dev); > =A0extern int xenbus_dev_resume(struct device *dev); > +extern int xenbus_dev_cancel(struct device *dev); > > =A0extern void xenbus_otherend_changed(struct xenbus_watch *watch, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0co= nst char **vec, unsigned int len, > diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xen= bus/xenbus_probe_frontend.c > index 5413248..ff32ffb 100644 > --- a/drivers/xen/xenbus/xenbus_probe_frontend.c > +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c > @@ -82,6 +82,13 @@ static struct device_attribute xenbus_frontend_dev_att= rs[] =3D { > =A0 =A0 =A0 =A0__ATTR_NULL > =A0}; > > +static struct dev_pm_ops xenbus_pm_ops =3D { > + =A0 =A0 =A0 .suspend =3D xenbus_dev_suspend, > + =A0 =A0 =A0 .resume =A0=3D xenbus_dev_resume, > + =A0 =A0 =A0 .freeze =A0=3D xenbus_dev_suspend, > + =A0 =A0 =A0 .thaw =A0 =A0=3D xenbus_dev_cancel, > + =A0 =A0 =A0 .restore =3D xenbus_dev_resume, > +}; > > =A0static struct xen_bus_type xenbus_frontend =3D { > =A0 =A0 =A0 =A0.root =3D "device", > @@ -98,8 +105,7 @@ static struct xen_bus_type xenbus_frontend =3D { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0.shutdown =3D xenbus_dev_shutdown, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0.dev_attrs=3D xenbus_frontend_dev_attrs, > > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .suspend =A0=3D xenbus_dev_suspend, > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .resume =A0 =3D xenbus_dev_resume, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .pm =A0 =A0 =A0 =3D &xenbus_pm_ops, > =A0 =A0 =A0 =A0}, > =A0}; > > diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h > index 542ca7c..23e7f25 100644 > --- a/include/xen/xenbus.h > +++ b/include/xen/xenbus.h > @@ -91,7 +91,7 @@ struct xenbus_driver { > =A0 =A0 =A0 =A0void (*otherend_changed)(struct xenbus_device *dev, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 enum xenb= us_state backend_state); > =A0 =A0 =A0 =A0int (*remove)(struct xenbus_device *dev); > - =A0 =A0 =A0 int (*suspend)(struct xenbus_device *dev, pm_message_t stat= e); > + =A0 =A0 =A0 int (*suspend)(struct xenbus_device *dev); > =A0 =A0 =A0 =A0int (*resume)(struct xenbus_device *dev); > =A0 =A0 =A0 =A0int (*uevent)(struct xenbus_device *, struct kobj_uevent_e= nv *); > =A0 =A0 =A0 =A0struct device_driver driver; > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel > parts of this patch were based on Kazuhiro Suzuki's initial patch to fix th= e same issue. Refer to http://lists.xensource.com/archives/html/xen-devel/2011-02/msg00371.html for further details.