From patchwork Fri Nov 2 09:00:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Axtens X-Patchwork-Id: 992210 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 42mbdF40ddzB4Tq; Fri, 2 Nov 2018 20:00:33 +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 1gIVJc-0005aY-6i; Fri, 02 Nov 2018 09:00:28 +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 1gIVJa-0005Zc-Cf for kernel-team@lists.canonical.com; Fri, 02 Nov 2018 09:00:26 +0000 Received: from mail-qk1-f197.google.com ([209.85.222.197]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1gIVJa-0003Lt-2J for kernel-team@lists.canonical.com; Fri, 02 Nov 2018 09:00:26 +0000 Received: by mail-qk1-f197.google.com with SMTP id h68so2790151qke.3 for ; Fri, 02 Nov 2018 02:00:26 -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=3ZfY0TJZQ9zqaqIaPAQ+PCsq5SMijwJQd1ZmOEUUVVQ=; b=GKV8kMepDE0+pZUeYoN0H64JobZCmIs5s7Dwy1+cBcDzkxFNdJj/X91LehYP8pcWE1 Y7ZYd1zLbO+GrayRNPUAp7MPDf6dFkiWiG5RbggqN+a9PVaR89oKYdbS3NNaIiQ0QHJo SUMu81zpRMub6jhR/1hbta/xB31L1jEVolUaGmRE8xHyhzzeOyfRwzoBmq1rnY86eDEl g7ajaxBaRtVz+g4LJ4HVfE/60dALTSpx3KWRh8xjFMbtE3D5KiNZpTHuSTPQ5oufYd/X dyOGgD2V702fTO4KDAVTpNClsVAoM2v8ZSXrffbcH0tvf2lKWxN2Tsc+VQVbtWKGXlyF sjSg== X-Gm-Message-State: AGRZ1gIPHEyS36l0hL0X6prpXL3Rh8K/hql2cUncnHaO81WlH6XZqq0/ iDcmgO4EtGcvdD1SIj1+03fL/PZ39MFY3PPA+4VRlV308tYQSMHxlL5BkXP3Exngd62fsRDONU4 SScV7mYtshfnVEPpCOsuvpeUtg+0dhms4r2q+wrXoYvwi8bB6 X-Received: by 2002:ac8:1b34:: with SMTP id y49mr2988555qtj.374.1541149225048; Fri, 02 Nov 2018 02:00:25 -0700 (PDT) X-Google-Smtp-Source: AJdET5diuqmm2nvrdN9KpoQ7RB9z7239/mm8fQa4wF/TbuLVO6q61QuEovgo8G9tIv+tCoCzuoth4Q== X-Received: by 2002:ac8:1b34:: with SMTP id y49mr2988543qtj.374.1541149224816; Fri, 02 Nov 2018 02:00:24 -0700 (PDT) Received: from linkitivity.iinet.net.au ([2001:67c:1562:8007::aac:4356]) by smtp.gmail.com with ESMTPSA id a4-v6sm23521783qkb.62.2018.11.02.02.00.22 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Nov 2018 02:00:24 -0700 (PDT) From: Daniel Axtens To: kernel-team@lists.canonical.com Subject: [SRU bionic-aws][PATCH 3/6] xenbus: add freeze/thaw/restore callbacks support Date: Fri, 2 Nov 2018 20:00:07 +1100 Message-Id: <20181102090010.2643-4-daniel.axtens@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181102090010.2643-1-daniel.axtens@canonical.com> References: <20181102090010.2643-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 ec9eb4fba59c..95b0a6d0acce 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);