{"id":818000,"url":"http://patchwork.ozlabs.org/api/patches/818000/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-i2c/patch/7572899.CfQ69SdO4W@aspire.rjw.lan/","project":{"id":35,"url":"http://patchwork.ozlabs.org/api/projects/35/?format=json","name":"Linux I2C development","link_name":"linux-i2c","list_id":"linux-i2c.vger.kernel.org","list_email":"linux-i2c@vger.kernel.org","web_url":"","scm_url":"","webscm_url":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<7572899.CfQ69SdO4W@aspire.rjw.lan>","list_archive_url":null,"date":"2017-09-24T23:30:51","name":"[v4,3/3] PM: i2c-designware-platdrv: Suspend/resume at the late/early stages","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"8d2044ba5cc0827d9c8f094be6dc9fd7f96a287d","submitter":{"id":26536,"url":"http://patchwork.ozlabs.org/api/people/26536/?format=json","name":"Rafael J. Wysocki","email":"rjw@rjwysocki.net"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-i2c/patch/7572899.CfQ69SdO4W@aspire.rjw.lan/mbox/","series":[{"id":4853,"url":"http://patchwork.ozlabs.org/api/series/4853/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-i2c/list/?series=4853","date":"2017-09-24T23:20:35","name":"i2c: designware: Runtime PM aware system sleep handling","version":4,"mbox":"http://patchwork.ozlabs.org/series/4853/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/818000/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/818000/checks/","tags":{},"related":[],"headers":{"Return-Path":"<linux-i2c-owner@vger.kernel.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@bilbo.ozlabs.org","Authentication-Results":"ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=linux-i2c-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)","Received":["from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3y0kHQ4tL0z9t3t\n\tfor <incoming@patchwork.ozlabs.org>;\n\tMon, 25 Sep 2017 09:40:50 +1000 (AEST)","(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S932176AbdIXXko (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tSun, 24 Sep 2017 19:40:44 -0400","from cloudserver094114.home.net.pl ([79.96.170.134]:52647 \"EHLO\n\tcloudserver094114.home.net.pl\" rhost-flags-OK-OK-OK-OK)\n\tby vger.kernel.org with ESMTP id S1753545AbdIXXkm (ORCPT\n\t<rfc822; linux-i2c@vger.kernel.org>); Sun, 24 Sep 2017 19:40:42 -0400","from 79.184.252.54.ipv4.supernova.orange.pl (79.184.252.54) (HELO\n\taspire.rjw.lan)\n\tby serwer1319399.home.pl (79.96.170.134) with SMTP (IdeaSmtpServer\n\t0.82) id e640f15b5aba28c8; Mon, 25 Sep 2017 01:40:40 +0200"],"From":"\"Rafael J. Wysocki\" <rjw@rjwysocki.net>","To":"linux-pm@vger.kernel.org, Wolfram Sang <wsa@the-dreams.de>","Cc":"linux-i2c@vger.kernel.org, linux-acpi@vger.kernel.org,\n\tKevin Hilman <khilman@kernel.org>,\n\tJarkko Nikula <jarkko.nikula@linux.intel.com>,\n\tAndy Shevchenko <andriy.shevchenko@linux.intel.com>,\n\tMika Westerberg <mika.westerberg@linux.intel.com>,\n\tJisheng Zhang <jszhang@marvell.com>,\n\tJohn Stultz <john.stultz@linaro.org>, Guodong Xu <guodong.xu@linaro.org>,\n\tSumit Semwal <sumit.semwal@linaro.org>,\n\tHaojian Zhuang <haojian.zhuang@linaro.org>,\n\tJohannes Stezenbach <js@sig21.net>, Ulf Hansson <ulf.hansson@linaro.org>,\n\tLee Jones <lee.jones@linaro.org>, Rajat Jain <rajatja@google.com>","Subject":"[PATCH v4 3/3] PM: i2c-designware-platdrv: Suspend/resume at the\n\tlate/early stages","Date":"Mon, 25 Sep 2017 01:30:51 +0200","Message-ID":"<7572899.CfQ69SdO4W@aspire.rjw.lan>","In-Reply-To":"<65494652.vEfz4tCBDb@aspire.rjw.lan>","References":"<3023226.l5IfJK6GIc@aspire.rjw.lan>\n\t<3958866.l2qnKDbinI@aspire.rjw.lan>\n\t<65494652.vEfz4tCBDb@aspire.rjw.lan>","MIME-Version":"1.0","Content-Transfer-Encoding":"7Bit","Content-Type":"text/plain; charset=\"us-ascii\"","Sender":"linux-i2c-owner@vger.kernel.org","Precedence":"bulk","List-ID":"<linux-i2c.vger.kernel.org>","X-Mailing-List":"linux-i2c@vger.kernel.org"},"content":"From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>\n\nAs reported by Rajat Jain, there are problems when ACPI operation\nregion handlers or similar, called at the ->resume_early() time, for\nI2C client devices try to access an I2C controller that has already\nbeen suspended at that point.  To avoid that, move the suspend/resume\nof i2c-designware-platdrv to the late/early stages, respectively.\n\nWhile at it, avoid resuming the device from runtime suspend in the\ndriver's ->suspend callback which isn't particularly nice.  [A better\napproach would be to make the driver track the PM state of the device\nso that it doesn't need to resume it in ->suspend, so implement it.]\n\nFirst, drop dw_i2c_plat_suspend() added by commit a23318feeff6 (i2c:\ndesignware: Fix system suspend) and rename dw_i2c_plat_runtime_suspend()\nback to dw_i2c_plat_suspend().\n\nSecond, point the driver's ->late_suspend and ->early_resume\ncallbacks, rather than its ->suspend and ->resume callbacks,\nto dw_i2c_plat_suspend() and dw_i2c_plat_resume(), respectively,\nso that they are not executed in parallel with each other, for\nexample if runtime resume of the device takes place during system\nsuspend.\n\nFinally, add \"suspended\" and \"skip_resume\" flags to struct dw_i2c_dev\nand make dw_i2c_plat_suspend() and dw_i2c_plat_resume() use them to\navoid suspending or resuming the device twice in a row and to avoid\nresuming a previously runtime-suspended device during system resume.\n\nSigned-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>\nTested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>\nTested-by: Mika Westerberg <mika.westerberg@linux.intel.com>\nTested-by: Johannes Stezenbach <js@sig21.net>\nTested-by: Rajat Jain <rajatja@google.com>\n---\n\nv3 ->v4: Modify changelog to mention the problem addressed by this\n  patch, rebase on top of 4.14-rc1 and add Tested-by tags.\n\nv2 -> v3:\n  Do not drop ->prepare and ->complete system sleep callbacks as\n  direct_complete is still useful for helping to avoid resuming\n  the parent of this device in the intel-lpss case.\n\n-> v2:\n  Add the \"suspended\" flag, which is needed, because\n  dw_i2c_plat_suspend() doesn't update the runtime PM status of\n  the device, so dw_i2c_plat_resume() can't rely on this check\n  during system resume.\n\n---\n drivers/i2c/busses/i2c-designware-core.h    |    2 +\n drivers/i2c/busses/i2c-designware-platdrv.c |   33 ++++++++++++++++------------\n 2 files changed, 22 insertions(+), 13 deletions(-)","diff":"Index: linux-pm/drivers/i2c/busses/i2c-designware-core.h\n===================================================================\n--- linux-pm.orig/drivers/i2c/busses/i2c-designware-core.h\n+++ linux-pm/drivers/i2c/busses/i2c-designware-core.h\n@@ -280,6 +280,8 @@ struct dw_i2c_dev {\n \tint\t\t\t(*acquire_lock)(struct dw_i2c_dev *dev);\n \tvoid\t\t\t(*release_lock)(struct dw_i2c_dev *dev);\n \tbool\t\t\tpm_disabled;\n+\tbool\t\t\tsuspended;\n+\tbool\t\t\tskip_resume;\n \tvoid\t\t\t(*disable)(struct dw_i2c_dev *dev);\n \tvoid\t\t\t(*disable_int)(struct dw_i2c_dev *dev);\n \tint\t\t\t(*init)(struct dw_i2c_dev *dev);\nIndex: linux-pm/drivers/i2c/busses/i2c-designware-platdrv.c\n===================================================================\n--- linux-pm.orig/drivers/i2c/busses/i2c-designware-platdrv.c\n+++ linux-pm/drivers/i2c/busses/i2c-designware-platdrv.c\n@@ -451,13 +451,20 @@ static void dw_i2c_plat_complete(struct\n #endif\n \n #ifdef CONFIG_PM\n-static int dw_i2c_plat_runtime_suspend(struct device *dev)\n+static int dw_i2c_plat_suspend(struct device *dev)\n {\n \tstruct dw_i2c_dev *i_dev = dev_get_drvdata(dev);\n \n+\tif (i_dev->suspended) {\n+\t\ti_dev->skip_resume = true;\n+\t\treturn 0;\n+\t}\n+\n \ti_dev->disable(i_dev);\n \ti2c_dw_plat_prepare_clk(i_dev, false);\n \n+\ti_dev->suspended = true;\n+\n \treturn 0;\n }\n \n@@ -465,27 +472,27 @@ static int dw_i2c_plat_resume(struct dev\n {\n \tstruct dw_i2c_dev *i_dev = dev_get_drvdata(dev);\n \n+\tif (!i_dev->suspended)\n+\t\treturn 0;\n+\n+\tif (i_dev->skip_resume) {\n+\t\ti_dev->skip_resume = false;\n+\t\treturn 0;\n+\t}\n+\n \ti2c_dw_plat_prepare_clk(i_dev, true);\n \ti_dev->init(i_dev);\n \n-\treturn 0;\n-}\n+\ti_dev->suspended = false;\n \n-#ifdef CONFIG_PM_SLEEP\n-static int dw_i2c_plat_suspend(struct device *dev)\n-{\n-\tpm_runtime_resume(dev);\n-\treturn dw_i2c_plat_runtime_suspend(dev);\n+\treturn 0;\n }\n-#endif\n \n static const struct dev_pm_ops dw_i2c_dev_pm_ops = {\n \t.prepare = dw_i2c_plat_prepare,\n \t.complete = dw_i2c_plat_complete,\n-\tSET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)\n-\tSET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend,\n-\t\t\t   dw_i2c_plat_resume,\n-\t\t\t   NULL)\n+\tSET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)\n+\tSET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)\n };\n \n #define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)\n","prefixes":["v4","3/3"]}