From patchwork Fri Apr 20 10:18:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Morris <0v3rdr0n3@gmail.com> X-Patchwork-Id: 901951 X-Patchwork-Delegate: davem@davemloft.net 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=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-ide-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="PntOGR9d"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40SHzk1sxSz9s5f for ; Sat, 21 Apr 2018 00:19:30 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755106AbeDTOT1 (ORCPT ); Fri, 20 Apr 2018 10:19:27 -0400 Received: from mail-io0-f195.google.com ([209.85.223.195]:32892 "EHLO mail-io0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755071AbeDTOTY (ORCPT ); Fri, 20 Apr 2018 10:19:24 -0400 Received: by mail-io0-f195.google.com with SMTP id s25-v6so4742049ioa.0; Fri, 20 Apr 2018 07:19:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=g7jlrVhzaLCKcmRSeE/1Afjeb6bN0sQP39iSC635k+s=; b=PntOGR9dlI79pCI8mV8MxkJUvtsJYSZp6fg/yip+8SaOuFjXuRnW/fQ0Gae+HN3a4S VhAM53ShuILjo+gX+WvS0LYg+jeissAqz5o6L7z6/25W0ij92EyNmDEMyxIWMQBlFOzj amlX8vYvefihS4ves+OY2/S3SYjWRC6knadhCOxbSiTwDQU7j/tGs8bsb/tv1qXEoe3O C7lHLloS74h1jEUU4L2of0JLtwrmckqYfdoUTWzU2lAzqbYiM/ML/fy7hOf9ffEvsNHK WDzJrJdOqad3qvG/eBd0DoM3jmacoXdu012+QvWGN2SOQFmmPnJk2Lib+8/WLxui4Wwu Qt6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=g7jlrVhzaLCKcmRSeE/1Afjeb6bN0sQP39iSC635k+s=; b=KTEQB2ASjE0sm0/Dngpxk8rzLdZ62xS35GT4+EAVTP0+QgVhR2gINlQuh2iEr3bs/y m/8ffl9e2YQ+8dFlxYMz2VFakKT0S2JTBsiKAE1xmNnz3TsorTb7o3WXF1H3allCa+no K/XWEsBtAQS+Ea57fVAghBSJCm8wnQZIIJp7oiBeMiHzP9KGN5kiNKoWbUA+XIJPAU8q Bbsb2Ot6P7CftagjhZo5ydp6w2fmC8E9/imQIGkw1GyIcirF5I1c5KSOgPelq3fFZulO ZYp1U1j4GjMPFLKUCtNfIYjUWkJjaK9QqS4zF3rR/VWrPQKvnzjGWEif+WOhSwil6jPZ TuIQ== X-Gm-Message-State: ALQs6tDz0GKBx9v363BMN96yyyH+0cD8Ygx85qiDkgdMWc0RF6Ua92go DNNhRbnSIFNQD+yA5FTcFqzGxQ== X-Google-Smtp-Source: AB8JxZoR7GKOtXyc0N9TPLEQqc8zm/fVz8tRYAHth0NVDE63YMpyhq/txK8AfEcqlNhPDNjb6Bk5ow== X-Received: by 2002:a6b:a4c7:: with SMTP id d68-v6mr11329974ioj.34.1524233963608; Fri, 20 Apr 2018 07:19:23 -0700 (PDT) Received: from pride.cinci.rr.com (cpe-74-136-84-14.kya.res.rr.com. [74.136.84.14]) by smtp.gmail.com with ESMTPSA id f10-v6sm2927833iob.49.2018.04.20.07.19.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 20 Apr 2018 07:19:23 -0700 (PDT) From: 0v3rdr0n3@gmail.com To: linux-pm@vger.kernel.org, linux-ide@vger.kernel.org Cc: samorris@lexmark.com Subject: [PATCH v2 2/3] ata: ahci_platform: allow disabling of hotplug to save power Date: Fri, 20 Apr 2018 10:18:33 +0000 Message-Id: <20180420101834.15783-2-0v3rdr0n3@gmail.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180420101834.15783-1-0v3rdr0n3@gmail.com> References: <20180420101834.15783-1-0v3rdr0n3@gmail.com> Sender: linux-ide-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ide@vger.kernel.org From: Samuel Morris A number of resources remain powered to support hotplug. On platforms I've worked with, allowing the ahci_platform to suspend saves about 150mW. This patch allows the device to be auto suspended if the config parameter is set. Signed-off-by: Samuel Morris --- Changes: -Added missing CONFIG_PM_SLEEP ifdefs --- drivers/ata/Kconfig | 10 ++++ drivers/ata/ahci_platform.c | 13 ++++- drivers/ata/libahci_platform.c | 86 ++++++++++++++++++++++++++++------ include/linux/ahci_platform.h | 2 + 4 files changed, 94 insertions(+), 17 deletions(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 2b16e7c8fff3..866663dd11ab 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -119,6 +119,16 @@ config SATA_AHCI_PLATFORM If unsure, say N. +config AHCI_HOTPLUG_DISABLED + tristate "Platform AHCI SATA hotplug disable" + default n + help + This option allows the AHCI Platform resources usually kept on + to support hotplug to be runtime suspended, effectively disabling + hotplug, but saving power. + + If unsure, say N. + config AHCI_BRCM tristate "Broadcom AHCI SATA support" depends on ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCM_NSP diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 99f9a895a459..e8f160e99ff5 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -68,8 +68,15 @@ static int ahci_probe(struct platform_device *pdev) return rc; } -static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, - ahci_platform_resume); +#ifdef CONFIG_PM_SLEEP +static const struct dev_pm_ops ahci_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ahci_platform_suspend, ahci_platform_resume) +#ifdef CONFIG_AHCI_HOTPLUG_DISABLED + SET_RUNTIME_PM_OPS(ahci_platform_runtime_suspend, + ahci_platform_runtime_resume, NULL) +#endif +}; +#endif static const struct of_device_id ahci_of_match[] = { { .compatible = "generic-ahci", }, @@ -98,7 +105,9 @@ static struct platform_driver ahci_driver = { .name = DRV_NAME, .of_match_table = ahci_of_match, .acpi_match_table = ahci_acpi_match, +#ifdef CONFIG_PM_SLEEP .pm = &ahci_pm_ops, +#endif }, }; module_platform_driver(ahci_driver); diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index 46a762442dc5..17fc4f19a53d 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -268,10 +268,14 @@ static void ahci_platform_put_resources(struct device *dev, void *res) struct ahci_host_priv *hpriv = res; int c; +#ifdef CONFIG_AHCI_HOTPLUG_DISABLED + pm_runtime_disable(dev); +#else if (hpriv->got_runtime_pm) { pm_runtime_put_sync(dev); pm_runtime_disable(dev); } +#endif for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) clk_put(hpriv->clks[c]); @@ -493,9 +497,15 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) if (rc == -EPROBE_DEFER) goto err_out; } + +#ifdef CONFIG_AHCI_HOTPLUG_DISABLED + pm_runtime_set_active(dev); + pm_runtime_enable(dev); +#else pm_runtime_enable(dev); pm_runtime_get_sync(dev); hpriv->got_runtime_pm = true; +#endif devres_remove_group(dev, NULL); return hpriv; @@ -723,6 +733,21 @@ int ahci_platform_resume_host(struct device *dev) } EXPORT_SYMBOL_GPL(ahci_platform_resume_host); +static int _ahci_platform_suspend(struct device *dev) +{ + struct ata_host *host = dev_get_drvdata(dev); + struct ahci_host_priv *hpriv = host->private_data; + int rc; + + rc = ahci_platform_suspend_host(dev); + if (rc) + return rc; + + ahci_platform_disable_resources(hpriv); + + return 0; +} + /** * ahci_platform_suspend - Suspend an ahci-platform device * @dev: the platform device to suspend @@ -734,20 +759,45 @@ EXPORT_SYMBOL_GPL(ahci_platform_resume_host); * 0 on success otherwise a negative error code */ int ahci_platform_suspend(struct device *dev) +{ + return _ahci_platform_suspend(dev); +} +EXPORT_SYMBOL_GPL(ahci_platform_suspend); + +/** + * ahci_platform_runtime_suspend - Runtime suspend an ahci-platform device + * @dev: the platform device to suspend + * + * This function suspends the host associated with the device, followed by + * disabling all the resources of the device. + * + * RETURNS: + * 0 on success otherwise a negative error code + */ +int ahci_platform_runtime_suspend(struct device *dev) +{ + return _ahci_platform_suspend(dev); +} +EXPORT_SYMBOL_GPL(ahci_platform_runtime_suspend); + +static int _ahci_platform_resume(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); struct ahci_host_priv *hpriv = host->private_data; int rc; - rc = ahci_platform_suspend_host(dev); + rc = ahci_platform_enable_resources(hpriv); if (rc) return rc; - ahci_platform_disable_resources(hpriv); + rc = ahci_platform_resume_host(dev); + if (rc) { + ahci_platform_disable_resources(hpriv); + return rc; + } return 0; } -EXPORT_SYMBOL_GPL(ahci_platform_suspend); /** * ahci_platform_resume - Resume an ahci-platform device @@ -761,31 +811,37 @@ EXPORT_SYMBOL_GPL(ahci_platform_suspend); */ int ahci_platform_resume(struct device *dev) { - struct ata_host *host = dev_get_drvdata(dev); - struct ahci_host_priv *hpriv = host->private_data; int rc; - rc = ahci_platform_enable_resources(hpriv); + rc = _ahci_platform_resume(dev); if (rc) return rc; - rc = ahci_platform_resume_host(dev); - if (rc) - goto disable_resources; - /* We resumed so update PM runtime state */ pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); return 0; - -disable_resources: - ahci_platform_disable_resources(hpriv); - - return rc; } EXPORT_SYMBOL_GPL(ahci_platform_resume); + +/** + * ahci_platform_runtime_resume - Runtime resume an ahci-platform device + * @dev: the platform device to resume + * + * This function enables all the resources of the device followed by + * resuming the host associated with the device. + * + * RETURNS: + * 0 on success otherwise a negative error code + */ +int ahci_platform_runtime_resume(struct device *dev) +{ + return _ahci_platform_resume(dev); +} +EXPORT_SYMBOL_GPL(ahci_platform_runtime_resume); + #endif MODULE_DESCRIPTION("AHCI SATA platform library"); diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h index 1b0a17b22cd3..6396e6982103 100644 --- a/include/linux/ahci_platform.h +++ b/include/linux/ahci_platform.h @@ -42,5 +42,7 @@ int ahci_platform_suspend_host(struct device *dev); int ahci_platform_resume_host(struct device *dev); int ahci_platform_suspend(struct device *dev); int ahci_platform_resume(struct device *dev); +int ahci_platform_runtime_suspend(struct device *dev); +int ahci_platform_runtime_resume(struct device *dev); #endif /* _AHCI_PLATFORM_H */