From patchwork Tue Dec 15 12:12:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Nikula X-Patchwork-Id: 7854111 Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id D52799F349 for ; Tue, 15 Dec 2015 12:13:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E78CC2034C for ; Tue, 15 Dec 2015 12:13:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 057D52026C for ; Tue, 15 Dec 2015 12:13:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965109AbbLOMNE (ORCPT ); Tue, 15 Dec 2015 07:13:04 -0500 Received: from mga04.intel.com ([192.55.52.120]:64820 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S964921AbbLOMND (ORCPT ); Tue, 15 Dec 2015 07:13:03 -0500 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga104.fm.intel.com with ESMTP; 15 Dec 2015 04:13:02 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,431,1444719600"; d="scan'208";a="841529493" Received: from mylly.fi.intel.com (HELO mylly.fi.intel.com.) ([10.237.72.152]) by orsmga001.jf.intel.com with ESMTP; 15 Dec 2015 04:13:01 -0800 From: Jarkko Nikula To: Wolfram Sang Cc: linux-i2c@vger.kernel.org, linux-pm@vger.kernel.org, "Rafael J . Wysocki" , Andy Shevchenko , Mika Westerberg , Jarkko Nikula Subject: [RFC] i2c: Prevent runtime suspend of parent during adapter registration Date: Tue, 15 Dec 2015 14:12:56 +0200 Message-Id: <1450181576-878-1-git-send-email-jarkko.nikula@linux.intel.com> X-Mailer: git-send-email 2.6.2 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If runtime PM of parent device is enabled before it registers the I2C adapter there can be unnecessary runtime suspend during adapter device registration. This can happen when adapter is registered from parent's probe and if parent device is initially active platform device. In that case power.usage_count of parent device is zero and pm_runtime_get()/pm_runtime_put() cycle during probe could put the parent into runtime suspend. This happens when the i2c_register_adapter() calls the device_register(): i2c_register_adapter device_register device_add bus_probe_device device_initial_probe __device_attach if (dev->parent) pm_runtime_get_sync(dev->parent) ... if (dev->parent) pm_runtime_put(dev->parent) After that i2c_register_adapter() continues registering I2C slave devices. In case slave device probe does I2C transfers the parent will resume again and thus get a needless runtime suspend/resume cycle during adapter registration. Prevent this while retaining the runtime PM status of parent by only incrementing/decrementing parent device power usage count during I2C adapter registration. That makes sure there won't be spurious runtime PM status changes for parent's probe and lets the driver core to idle the device after probe finishes. Signed-off-by: Jarkko Nikula --- I noticed this with i2c-designware-platdrv.c which started to do so after commit 36d48fb5766a ("i2c: designware-platdrv: enable RuntimePM before registering to the core"). I guess the same could happen also with a few other I2C drivers that enable runtime PM similar way. For instance i2c-at91.c, i2c-cadence.c, i2c-hix5hd2.c and i2c-qup.c. That made me thinking if issue might be best to handle in i2c-core.c. Device core drivers/base/dd.c: driver_probe_device() or drivers/base/platform.c: platform_drv_probe() could be other alternatives but that would cause a regression to a driver that purposively tries to suspend the device in its probe(). --- drivers/i2c/i2c-core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index ba8eb087f224..4f8b5c80cf1e 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1556,6 +1556,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap) dev_set_name(&adap->dev, "i2c-%d", adap->nr); adap->dev.bus = &i2c_bus_type; adap->dev.type = &i2c_adapter_type; + if (adap->dev.parent) + pm_runtime_get_noresume(adap->dev.parent); res = device_register(&adap->dev); if (res) goto out_list; @@ -1617,6 +1619,8 @@ exit_recovery: mutex_lock(&core_lock); bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); mutex_unlock(&core_lock); + if (adap->dev.parent) + pm_runtime_put_noidle(adap->dev.parent); return 0; @@ -1624,6 +1628,8 @@ out_list: mutex_lock(&core_lock); idr_remove(&i2c_adapter_idr, adap->nr); mutex_unlock(&core_lock); + if (adap->dev.parent) + pm_runtime_put_noidle(adap->dev.parent); return res; }