From aece27a2f01be4bb7683790f69cd1bed3a0929a2 Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Tue, 29 May 2018 10:06:12 +0000 Subject: ata: ahci_platform: allow disabling of hotplug to save power 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 enables rpm and allows the device to be auto-suspended through sysfs. Signed-off-by: Samuel Morris Signed-off-by: Tejun Heo --- drivers/ata/ahci_platform.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/ata/ahci_platform.c') diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 99f9a895a459..757729376eda 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -68,8 +68,13 @@ disable_resources: 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) + SET_RUNTIME_PM_OPS(ahci_platform_runtime_suspend, + ahci_platform_runtime_resume, NULL) +}; +#endif static const struct of_device_id ahci_of_match[] = { { .compatible = "generic-ahci", }, @@ -98,7 +103,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); -- cgit v1.2.3 From eac7e072d7e99fad1b6e817c608b03c48205241e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 6 Aug 2018 10:22:35 -0700 Subject: Revert "ata: ahci_platform: allow disabling of hotplug to save power" This reverts commit aece27a2f01be4bb7683790f69cd1bed3a0929a2. Causes boot failure on some devices. http://lore.kernel.org/r/CA+G9fYuKW_jCFZPqG4tz=QY9ROfHO38KiCp9XTA+KaDOFVtcqQ@mail.gmail.com Signed-off-by: Tejun Heo --- drivers/ata/ahci_platform.c | 11 ++---- drivers/ata/libahci_platform.c | 82 +++++++++--------------------------------- include/linux/ahci_platform.h | 2 -- 3 files changed, 19 insertions(+), 76 deletions(-) (limited to 'drivers/ata/ahci_platform.c') diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 757729376eda..99f9a895a459 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -68,13 +68,8 @@ disable_resources: return rc; } -#ifdef CONFIG_PM_SLEEP -static const struct dev_pm_ops ahci_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(ahci_platform_suspend, ahci_platform_resume) - SET_RUNTIME_PM_OPS(ahci_platform_runtime_suspend, - ahci_platform_runtime_resume, NULL) -}; -#endif +static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, + ahci_platform_resume); static const struct of_device_id ahci_of_match[] = { { .compatible = "generic-ahci", }, @@ -103,9 +98,7 @@ 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 2ceebaf2ed56..8fbb532b62dd 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -257,7 +257,7 @@ static void ahci_platform_put_resources(struct device *dev, void *res) int c; if (hpriv->got_runtime_pm) { - pm_runtime_allow(dev); + pm_runtime_put_sync(dev); pm_runtime_disable(dev); } @@ -477,10 +477,8 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) if (rc == -EPROBE_DEFER) goto err_out; } - - pm_runtime_set_active(dev); pm_runtime_enable(dev); - pm_runtime_forbid(dev); + pm_runtime_get_sync(dev); hpriv->got_runtime_pm = true; devres_remove_group(dev, NULL); @@ -709,21 +707,6 @@ 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 @@ -735,45 +718,20 @@ static int _ahci_platform_suspend(struct device *dev) * 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_enable_resources(hpriv); + rc = ahci_platform_suspend_host(dev); if (rc) return rc; - rc = ahci_platform_resume_host(dev); - if (rc) { - ahci_platform_disable_resources(hpriv); - return rc; - } + ahci_platform_disable_resources(hpriv); return 0; } +EXPORT_SYMBOL_GPL(ahci_platform_suspend); /** * ahci_platform_resume - Resume an ahci-platform device @@ -787,37 +745,31 @@ static int _ahci_platform_resume(struct device *dev) */ 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_resume(dev); + rc = ahci_platform_enable_resources(hpriv); 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; -} -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); +disable_resources: + ahci_platform_disable_resources(hpriv); + return rc; +} +EXPORT_SYMBOL_GPL(ahci_platform_resume); #endif MODULE_DESCRIPTION("AHCI SATA platform library"); diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h index 6396e6982103..1b0a17b22cd3 100644 --- a/include/linux/ahci_platform.h +++ b/include/linux/ahci_platform.h @@ -42,7 +42,5 @@ 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 */ -- cgit v1.2.3 From 16af2d65842d343c2f95733c3993a0b5baab08f9 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Wed, 22 Aug 2018 21:13:01 +0900 Subject: ata: add an extra argument to ahci_platform_get_resources() Add an extra argument to ahci_platform_get_resources(), that is for the bitmap representing the resource to get in this function. Currently there is no resources to be defined, so all the callers set '0' to the argument. Suggested-by: Hans de Goede Cc: Thierry Reding Cc: Matthias Brugger Cc: Patrice Chotard Cc: Maxime Ripard Signed-off-by: Kunihiko Hayashi Reviewed-by: Hans de Goede Signed-off-by: Tejun Heo --- drivers/ata/ahci_brcm.c | 2 +- drivers/ata/ahci_ceva.c | 2 +- drivers/ata/ahci_da850.c | 2 +- drivers/ata/ahci_dm816.c | 2 +- drivers/ata/ahci_imx.c | 2 +- drivers/ata/ahci_mtk.c | 2 +- drivers/ata/ahci_mvebu.c | 2 +- drivers/ata/ahci_platform.c | 2 +- drivers/ata/ahci_qoriq.c | 2 +- drivers/ata/ahci_seattle.c | 2 +- drivers/ata/ahci_st.c | 2 +- drivers/ata/ahci_sunxi.c | 2 +- drivers/ata/ahci_tegra.c | 2 +- drivers/ata/ahci_xgene.c | 2 +- drivers/ata/libahci_platform.c | 4 +++- include/linux/ahci_platform.h | 2 +- 16 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers/ata/ahci_platform.c') diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index ea430819c80b..f3d557777d82 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -425,7 +425,7 @@ static int brcm_ahci_probe(struct platform_device *pdev) brcm_sata_phys_enable(priv); - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); hpriv->plat_data = priv; diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c index 5ecc9d46cb54..dc78c98cb9f1 100644 --- a/drivers/ata/ahci_ceva.c +++ b/drivers/ata/ahci_ceva.c @@ -213,7 +213,7 @@ static int ceva_ahci_probe(struct platform_device *pdev) cevapriv->ahci_pdev = pdev; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c index 9b34dff64536..ebaa657f28c4 100644 --- a/drivers/ata/ahci_da850.c +++ b/drivers/ata/ahci_da850.c @@ -171,7 +171,7 @@ static int ahci_da850_probe(struct platform_device *pdev) u32 mpy; int rc; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_dm816.c b/drivers/ata/ahci_dm816.c index fbd827c3a75c..89509c3efb01 100644 --- a/drivers/ata/ahci_dm816.c +++ b/drivers/ata/ahci_dm816.c @@ -148,7 +148,7 @@ static int ahci_dm816_probe(struct platform_device *pdev) struct ahci_host_priv *hpriv; int rc; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 6822e2f33f7e..b00799d208f5 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -1127,7 +1127,7 @@ static int imx_ahci_probe(struct platform_device *pdev) return ret; } - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c index 0ae6971c2a4c..8bc1a26ffc31 100644 --- a/drivers/ata/ahci_mtk.c +++ b/drivers/ata/ahci_mtk.c @@ -142,7 +142,7 @@ static int mtk_ahci_probe(struct platform_device *pdev) if (!plat) return -ENOMEM; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c index 0045dacd814b..adbe38fb9c35 100644 --- a/drivers/ata/ahci_mvebu.c +++ b/drivers/ata/ahci_mvebu.c @@ -158,7 +158,7 @@ static int ahci_mvebu_probe(struct platform_device *pdev) const struct mbus_dram_target_info *dram; int rc; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 99f9a895a459..570927316962 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -43,7 +43,7 @@ static int ahci_probe(struct platform_device *pdev) struct ahci_host_priv *hpriv; int rc; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c index cfdef4d44ae9..ce59253ec158 100644 --- a/drivers/ata/ahci_qoriq.c +++ b/drivers/ata/ahci_qoriq.c @@ -250,7 +250,7 @@ static int ahci_qoriq_probe(struct platform_device *pdev) struct resource *res; int rc; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_seattle.c b/drivers/ata/ahci_seattle.c index 1d31c0c0fc20..e57b6f92c288 100644 --- a/drivers/ata/ahci_seattle.c +++ b/drivers/ata/ahci_seattle.c @@ -164,7 +164,7 @@ static int ahci_seattle_probe(struct platform_device *pdev) int rc; struct ahci_host_priv *hpriv; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c index bc345f249555..21c5c44832ef 100644 --- a/drivers/ata/ahci_st.c +++ b/drivers/ata/ahci_st.c @@ -156,7 +156,7 @@ static int st_ahci_probe(struct platform_device *pdev) if (!drv_data) return -ENOMEM; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); hpriv->plat_data = drv_data; diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c index b26437430163..631610b72aa5 100644 --- a/drivers/ata/ahci_sunxi.c +++ b/drivers/ata/ahci_sunxi.c @@ -181,7 +181,7 @@ static int ahci_sunxi_probe(struct platform_device *pdev) struct ahci_host_priv *hpriv; int rc; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_tegra.c b/drivers/ata/ahci_tegra.c index 64d848409fe2..004f2608818e 100644 --- a/drivers/ata/ahci_tegra.c +++ b/drivers/ata/ahci_tegra.c @@ -494,7 +494,7 @@ static int tegra_ahci_probe(struct platform_device *pdev) int ret; unsigned int i; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c index ad58da7c9aff..7e157e1bf65e 100644 --- a/drivers/ata/ahci_xgene.c +++ b/drivers/ata/ahci_xgene.c @@ -759,7 +759,7 @@ static int xgene_ahci_probe(struct platform_device *pdev) &xgene_ahci_v2_port_info }; int rc; - hpriv = ahci_platform_get_resources(pdev); + hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index 8fbb532b62dd..679f763410c0 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -332,6 +332,7 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, /** * ahci_platform_get_resources - Get platform resources * @pdev: platform device to get resources for + * @flags: bitmap representing the resource to get * * This function allocates an ahci_host_priv struct, and gets the following * resources, storing a reference to them inside the returned struct: @@ -345,7 +346,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, * RETURNS: * The allocated ahci_host_priv on success, otherwise an ERR_PTR value */ -struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) +struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, + unsigned int flags) { struct device *dev = &pdev->dev; struct ahci_host_priv *hpriv; diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h index 1b0a17b22cd3..6490be1f8a16 100644 --- a/include/linux/ahci_platform.h +++ b/include/linux/ahci_platform.h @@ -30,7 +30,7 @@ void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv); int ahci_platform_enable_resources(struct ahci_host_priv *hpriv); void ahci_platform_disable_resources(struct ahci_host_priv *hpriv); struct ahci_host_priv *ahci_platform_get_resources( - struct platform_device *pdev); + struct platform_device *pdev, unsigned int flags); int ahci_platform_init_host(struct platform_device *pdev, struct ahci_host_priv *hpriv, const struct ata_port_info *pi_template, -- cgit v1.2.3 From 2d17f460c5d79fa9fc794e813377f3276acf81ce Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Wed, 22 Aug 2018 21:13:03 +0900 Subject: ata: ahci_platform: enable to get and control reset Unlike SoC-specific driver, generic ahci_platform driver doesn't have any chances to control resets. This adds AHCI_PLATFORM_GET_RESETS to ahci_platform_get_resources() on the generic driver to enable reset control support. Suggested-by: Hans de Goede Cc: Thierry Reding Signed-off-by: Kunihiko Hayashi Reviewed-by: Hans de Goede Signed-off-by: Tejun Heo --- drivers/ata/ahci_platform.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/ata/ahci_platform.c') diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 570927316962..ddd930852b2e 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -43,7 +43,8 @@ static int ahci_probe(struct platform_device *pdev) struct ahci_host_priv *hpriv; int rc; - hpriv = ahci_platform_get_resources(pdev, 0); + hpriv = ahci_platform_get_resources(pdev, + AHCI_PLATFORM_GET_RESETS); if (IS_ERR(hpriv)) return PTR_ERR(hpriv); -- cgit v1.2.3