From patchwork Fri Nov 2 08:57:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Axtens X-Patchwork-Id: 992202 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42mbZC59XWzB4Ts; Fri, 2 Nov 2018 19:57:55 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1gIVH4-00055n-N2; Fri, 02 Nov 2018 08:57:50 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1gIVH2-00054T-OM for kernel-team@lists.canonical.com; Fri, 02 Nov 2018 08:57:48 +0000 Received: from mail-qk1-f199.google.com ([209.85.222.199]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1gIVH2-0003DN-ET for kernel-team@lists.canonical.com; Fri, 02 Nov 2018 08:57:48 +0000 Received: by mail-qk1-f199.google.com with SMTP id l7-v6so2773164qkd.5 for ; Fri, 02 Nov 2018 01:57:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=5UnD5U6OVAqb+AN81pBZUpdPtLp07N1vyXgNwxOaMVQ=; b=ULzITWXCN2hXWSt3r/SigcqNEIEKqjR/eU/hl73wrCje4Z/uWpignswql/2b+jMKNt rDWDHjxUFZ7ljdPmuqXGHo0Ctyk61/WEiyO1l5PbcVZCmcIQ4sFyJymNW/Av1KRMhSQW 5B6AC7pxekAlUwTlMjw6jh0YTLnZuC0tltXebOHuzm+RWuCwPM4XZpUclKoPFI0YCqyL 5if0jMK8c+/aoDGMwHUgK9qmEAfbF27ft52NEqjUs/0NKLpkOBlvieD5iGW9K7l2hccl vQDP8jfnDoHkmYEOozC+yN/3rIfI4Uz3dJU+FIj0hTKsUZN7tEQWEeRQik8D1A6sUGni /vbw== X-Gm-Message-State: AGRZ1gJmNVRdcUevdie/lfJ5a5cZuZsMW0aviPXtCHHd7GxZLWFHJ8fv WnEl6kOJa2z/xRI7IXTjGAl9xA2Pv2zr4KOmiWvM6ZvGKi1FAeBBcCZrpJfiJ/1OyONHxoRSOVa oMS7rkvnsgsB7emxniA0GRxS2VLEYMRc/zGNZSbsq37ALD/lp X-Received: by 2002:a37:6389:: with SMTP id x131mr9266126qkb.149.1541149067448; Fri, 02 Nov 2018 01:57:47 -0700 (PDT) X-Google-Smtp-Source: AJdET5fuNPSijgoDNbaDOqYUA9jpfwlAbo+eUmsVm5CyIcYES4qFq45blVWWfufTK6AJh0KIOpNg6Q== X-Received: by 2002:a37:6389:: with SMTP id x131mr9266117qkb.149.1541149067149; Fri, 02 Nov 2018 01:57:47 -0700 (PDT) Received: from linkitivity.iinet.net.au ([2001:67c:1562:8007::aac:4356]) by smtp.gmail.com with ESMTPSA id 38sm12846997qkw.56.2018.11.02.01.57.44 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Nov 2018 01:57:46 -0700 (PDT) From: Daniel Axtens To: kernel-team@lists.canonical.com Subject: [SRU cosmic-aws][PATCH 3/6] xenbus: add freeze/thaw/restore callbacks support Date: Fri, 2 Nov 2018 19:57:29 +1100 Message-Id: <20181102085732.2343-4-daniel.axtens@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181102085732.2343-1-daniel.axtens@canonical.com> References: <20181102085732.2343-1-daniel.axtens@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Munehisa Kamata BugLink: https://bugs.launchpad.net/bugs/1801305 Since commit b3e96c0c7562 ("xen: use freeze/restore/thaw PM events for suspend/resume/chkpt"), xenbus uses PMSG_FREEZE, PMSG_THAW and PMSG_RESTORE events for Xen suspend. However, they're actually assigned to xenbus_dev_suspend(), xenbus_dev_cancel() and xenbus_dev_resume() respectively, and only suspend and resume callbacks are supported at driver level. To support PM suspend and PM hibernation, modify the bus level PM callbacks to invoke not only device driver's suspend/resume but also freeze/thaw/restore. Note that we'll use freeze/restore callbacks even for PM suspend whereas suspend/resume callbacks are normally used in the case, becausae the existing xenbus device drivers already have suspend/resume callbacks specifically designed for Xen suspend. So we can allow the device drivers to keep the existing callbacks wihtout modification. Signed-off-by: Munehisa Kamata Signed-off-by: Anchal Agarwal Reviewed-by: Munehisa Kamata Reviewed-by: Eduardo Valentin CR: https://cr.amazon.com/r/8273200/ (cherry-picked from 0015-xenbus-add-freeze-thaw-restore-callbacks-support.patch in AWS 4.14 kernel SRPM) Signed-off-by: Daniel Axtens --- drivers/xen/xenbus/xenbus_probe.c | 102 +++++++++++++++++++++++++----- include/xen/xenbus.h | 3 + 2 files changed, 89 insertions(+), 16 deletions(-) diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index f2088838f690..809dc380e184 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -588,26 +589,47 @@ int xenbus_dev_suspend(struct device *dev) struct xenbus_driver *drv; struct xenbus_device *xdev = container_of(dev, struct xenbus_device, dev); + int (*cb)(struct xenbus_device *) = NULL; + bool xen_suspend = xen_suspend_mode_is_xen_suspend(); DPRINTK("%s", xdev->nodename); if (dev->driver == NULL) return 0; drv = to_xenbus_driver(dev->driver); - if (drv->suspend) - err = drv->suspend(xdev); - if (err) - pr_warn("suspend %s failed: %i\n", dev_name(dev), err); + + if (xen_suspend) + cb = drv->suspend; + else + cb = drv->freeze; + + if (cb) + err = cb(xdev); + + if (err) { + pr_warn("%s %s failed: %i\n", xen_suspend ? + "suspend" : "freeze", dev_name(dev), err); + return err; + } + + if (!xen_suspend) { + /* Forget otherend since this can become stale after restore */ + free_otherend_watch(xdev); + free_otherend_details(xdev); + } + return 0; } EXPORT_SYMBOL_GPL(xenbus_dev_suspend); int xenbus_dev_resume(struct device *dev) { - int err; + int err = 0; struct xenbus_driver *drv; struct xenbus_device *xdev = container_of(dev, struct xenbus_device, dev); + int (*cb)(struct xenbus_device *) = NULL; + bool xen_suspend = xen_suspend_mode_is_xen_suspend(); DPRINTK("%s", xdev->nodename); @@ -616,24 +638,34 @@ int xenbus_dev_resume(struct device *dev) drv = to_xenbus_driver(dev->driver); err = talk_to_otherend(xdev); if (err) { - pr_warn("resume (talk_to_otherend) %s failed: %i\n", + pr_warn("%s (talk_to_otherend) %s failed: %i\n", + xen_suspend ? "resume" : "restore", dev_name(dev), err); return err; } - xdev->state = XenbusStateInitialising; + if (xen_suspend) + xdev->state = XenbusStateInitialising; - if (drv->resume) { - err = drv->resume(xdev); - if (err) { - pr_warn("resume %s failed: %i\n", dev_name(dev), err); - return err; - } + if (xen_suspend) + cb = drv->resume; + else + cb = drv->restore; + + if (cb) + err = cb(xdev); + + if (err) { + pr_warn("%s %s failed: %i\n", + xen_suspend ? "resume" : "restore", + dev_name(dev), err); + return err; } err = watch_otherend(xdev); if (err) { - pr_warn("resume (watch_otherend) %s failed: %d.\n", + pr_warn("%s (watch_otherend) %s failed: %d.\n", + xen_suspend ? "resume" : "restore", dev_name(dev), err); return err; } @@ -644,8 +676,46 @@ EXPORT_SYMBOL_GPL(xenbus_dev_resume); int xenbus_dev_cancel(struct device *dev) { - /* Do nothing */ - DPRINTK("cancel"); + int err = 0; + struct xenbus_driver *drv; + struct xenbus_device *xdev + = container_of(dev, struct xenbus_device, dev); + bool xen_suspend = xen_suspend_mode_is_xen_suspend(); + + if (xen_suspend) { + /* Do nothing */ + DPRINTK("cancel"); + return 0; + } + + DPRINTK("%s", xdev->nodename); + + if (dev->driver == NULL) + return 0; + drv = to_xenbus_driver(dev->driver); + + err = talk_to_otherend(xdev); + if (err) { + pr_warn("thaw (talk_to_otherend) %s failed: %d.\n", + dev_name(dev), err); + return err; + } + + if (drv->thaw) { + err = drv->thaw(xdev); + if (err) { + pr_warn("thaw %s failed: %i\n", dev_name(dev), err); + return err; + } + } + + err = watch_otherend(xdev); + if (err) { + pr_warn("thaw (watch_otherend) %s failed: %d.\n", + dev_name(dev), err); + return err; + } + return 0; } EXPORT_SYMBOL_GPL(xenbus_dev_cancel); diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h index 869c816d5f8c..20261d5f4e78 100644 --- a/include/xen/xenbus.h +++ b/include/xen/xenbus.h @@ -100,6 +100,9 @@ struct xenbus_driver { int (*remove)(struct xenbus_device *dev); int (*suspend)(struct xenbus_device *dev); int (*resume)(struct xenbus_device *dev); + int (*freeze)(struct xenbus_device *dev); + int (*thaw)(struct xenbus_device *dev); + int (*restore)(struct xenbus_device *dev); int (*uevent)(struct xenbus_device *, struct kobj_uevent_env *); struct device_driver driver; int (*read_otherend_details)(struct xenbus_device *dev);