* pm-sleep: PM / wakeirq: remove unnecessary parentheses PM / core: Clean up some function headers in power.h PM / hibernate: memory_bm_find_bit(): Tighten node optimisation * pm-domains: PM / Domains: Convert to dev_to_genpd_safe() in genpd_syscore_switch() mmc: tmio: Avoid boilerplate code in ->runtime_suspend() PM / Domains: Implement the ->start() callback for genpd PM / Domains: Introduce dev_pm_domain_start() * pm-opp: PM / OPP: Support adjusting OPP voltages at runtime * powercap: powercap/intel_rapl: add support for Cometlake desktop powercap/intel_rapl: add support for CometLake Mobile
Unified · Split
| @@ -187,6 +187,26 @@ void dev_pm_domain_detach(struct device *dev, bool power_off) · 186 unmodified lines | ||
| 187 | 187 | } |
| 188 | 188 | EXPORT_SYMBOL_GPL(dev_pm_domain_detach); |
| 189 | 189 | |
| 190 | +/** | |
| 191 | + * dev_pm_domain_start - Start the device through its PM domain. | |
| 192 | + * @dev: Device to start. | |
| 193 | + * | |
| 194 | + * This function should typically be called during probe by a subsystem/driver, | |
| 195 | + * when it needs to start its device from the PM domain's perspective. Note | |
| 196 | + * that, it's assumed that the PM domain is already powered on when this | |
| 197 | + * function is called. | |
| 198 | + * | |
| 199 | + * Returns 0 on success and negative error values on failures. | |
| 200 | + */ | |
| 201 | +int dev_pm_domain_start(struct device *dev) | |
| 202 | +{ | |
| 203 | + if (dev->pm_domain && dev->pm_domain->start) | |
| 204 | + return dev->pm_domain->start(dev); | |
| 205 | + | |
| 206 | + return 0; | |
| 207 | +} | |
| 208 | +EXPORT_SYMBOL_GPL(dev_pm_domain_start); | |
| 209 | + | |
| 190 | 210 | /** |
| 191 | 211 | * dev_pm_domain_set - Set PM domain of a device. |
| 192 | 212 | * @dev: Device whose PM domain is to be set. |
| @@ -634,6 +634,13 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth) · 633 unmodified lines | ||
| 634 | 634 | return ret; |
| 635 | 635 | } |
| 636 | 636 | |
| 637 | +static int genpd_dev_pm_start(struct device *dev) | |
| 638 | +{ | |
| 639 | + struct generic_pm_domain *genpd = dev_to_genpd(dev); | |
| 640 | + | |
| 641 | + return genpd_start_dev(genpd, dev); | |
| 642 | +} | |
| 643 | + | |
| 637 | 644 | static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, |
| 638 | 645 | unsigned long val, void *ptr) |
| 639 | 646 | { |
| @@ -922,24 +929,6 @@ static int __init genpd_power_off_unused(void) · 282 unmodified lines | ||
| 922 | 929 | } |
| 923 | 930 | late_initcall(genpd_power_off_unused); |
| 924 | 931 | |
| 925 | −#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_GENERIC_DOMAINS_OF) | |
| 926 | − | |
| 927 | −static bool genpd_present(const struct generic_pm_domain *genpd) | |
| 928 | −{ | |
| 929 | − const struct generic_pm_domain *gpd; | |
| 930 | − | |
| 931 | − if (IS_ERR_OR_NULL(genpd)) | |
| 932 | − return false; | |
| 933 | − | |
| 934 | − list_for_each_entry(gpd, &gpd_list, gpd_list_node) | |
| 935 | − if (gpd == genpd) | |
| 936 | − return true; | |
| 937 | − | |
| 938 | − return false; | |
| 939 | −} | |
| 940 | − | |
| 941 | −#endif | |
| 942 | − | |
| 943 | 932 | #ifdef CONFIG_PM_SLEEP |
| 944 | 933 | |
| 945 | 934 | /** |
| @@ -1354,8 +1343,8 @@ static void genpd_syscore_switch(struct device *dev, bool suspend) · 408 unmodified lines | ||
| 1354 | 1343 | { |
| 1355 | 1344 | struct generic_pm_domain *genpd; |
| 1356 | 1345 | |
| 1357 | − genpd = dev_to_genpd(dev); | |
| 1358 | − if (!genpd_present(genpd)) | |
| 1346 | + genpd = dev_to_genpd_safe(dev); | |
| 1347 | + if (!genpd) | |
| 1359 | 1348 | return; |
| 1360 | 1349 | |
| 1361 | 1350 | if (suspend) { |
| @@ -1805,6 +1794,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd, · 443 unmodified lines | ||
| 1805 | 1794 | genpd->domain.ops.poweroff_noirq = genpd_poweroff_noirq; |
| 1806 | 1795 | genpd->domain.ops.restore_noirq = genpd_restore_noirq; |
| 1807 | 1796 | genpd->domain.ops.complete = genpd_complete; |
| 1797 | + genpd->domain.start = genpd_dev_pm_start; | |
| 1808 | 1798 | |
| 1809 | 1799 | if (genpd->flags & GENPD_FLAG_PM_CLK) { |
| 1810 | 1800 | genpd->dev_ops.stop = pm_clk_suspend; |
| @@ -2020,6 +2010,16 @@ static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, · 209 unmodified lines | ||
| 2020 | 2010 | return 0; |
| 2021 | 2011 | } |
| 2022 | 2012 | |
| 2013 | +static bool genpd_present(const struct generic_pm_domain *genpd) | |
| 2014 | +{ | |
| 2015 | + const struct generic_pm_domain *gpd; | |
| 2016 | + | |
| 2017 | + list_for_each_entry(gpd, &gpd_list, gpd_list_node) | |
| 2018 | + if (gpd == genpd) | |
| 2019 | + return true; | |
| 2020 | + return false; | |
| 2021 | +} | |
| 2022 | + | |
| 2023 | 2023 | /** |
| 2024 | 2024 | * of_genpd_add_provider_simple() - Register a simple PM domain provider |
| 2025 | 2025 | * @np: Device node pointer associated with the PM domain provider. |
| @@ -117,6 +117,13 @@ static inline bool device_pm_initialized(struct device *dev) · 116 unmodified lines | ||
| 117 | 117 | return dev->power.in_dpm_list; |
| 118 | 118 | } |
| 119 | 119 | |
| 120 | +/* drivers/base/power/wakeup_stats.c */ | |
| 121 | +extern int wakeup_source_sysfs_add(struct device *parent, | |
| 122 | + struct wakeup_source *ws); | |
| 123 | +extern void wakeup_source_sysfs_remove(struct wakeup_source *ws); | |
| 124 | + | |
| 125 | +extern int pm_wakeup_source_sysfs_add(struct device *parent); | |
| 126 | + | |
| 120 | 127 | #else /* !CONFIG_PM_SLEEP */ |
| 121 | 128 | |
| 122 | 129 | static inline void device_pm_sleep_init(struct device *dev) {} |
| @@ -141,6 +148,11 @@ static inline bool device_pm_initialized(struct device *dev) · 18 unmodified lines | ||
| 141 | 148 | return device_is_registered(dev); |
| 142 | 149 | } |
| 143 | 150 | |
| 151 | +static inline int pm_wakeup_source_sysfs_add(struct device *parent) | |
| 152 | +{ | |
| 153 | + return 0; | |
| 154 | +} | |
| 155 | + | |
| 144 | 156 | #endif /* !CONFIG_PM_SLEEP */ |
| 145 | 157 | |
| 146 | 158 | static inline void device_pm_init(struct device *dev) |
| @@ -149,21 +161,3 @@ static inline void device_pm_init(struct device *dev) · 2 unmodified lines | ||
| 149 | 161 | device_pm_sleep_init(dev); |
| 150 | 162 | pm_runtime_init(dev); |
| 151 | 163 | } |
| 152 | − | |
| 153 | −#ifdef CONFIG_PM_SLEEP | |
| 154 | − | |
| 155 | −/* drivers/base/power/wakeup_stats.c */ | |
| 156 | −extern int wakeup_source_sysfs_add(struct device *parent, | |
| 157 | − struct wakeup_source *ws); | |
| 158 | −extern void wakeup_source_sysfs_remove(struct wakeup_source *ws); | |
| 159 | − | |
| 160 | −extern int pm_wakeup_source_sysfs_add(struct device *parent); | |
| 161 | − | |
| 162 | −#else /* !CONFIG_PM_SLEEP */ | |
| 163 | − | |
| 164 | −static inline int pm_wakeup_source_sysfs_add(struct device *parent) | |
| 165 | −{ | |
| 166 | − return 0; | |
| 167 | −} | |
| 168 | − | |
| 169 | −#endif /* CONFIG_PM_SLEEP */ | |
| @@ -272,7 +272,7 @@ void dev_pm_enable_wake_irq_check(struct device *dev, · 271 unmodified lines | ||
| 272 | 272 | { |
| 273 | 273 | struct wake_irq *wirq = dev->power.wakeirq; |
| 274 | 274 | |
| 275 | − if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK))) | |
| 275 | + if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK)) | |
| 276 | 276 | return; |
| 277 | 277 | |
| 278 | 278 | if (likely(wirq->status & WAKE_IRQ_DEDICATED_MANAGED)) { |
| @@ -299,7 +299,7 @@ void dev_pm_disable_wake_irq_check(struct device *dev) · 20 unmodified lines | ||
| 299 | 299 | { |
| 300 | 300 | struct wake_irq *wirq = dev->power.wakeirq; |
| 301 | 301 | |
| 302 | − if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK))) | |
| 302 | + if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK)) | |
| 303 | 303 | return; |
| 304 | 304 | |
| 305 | 305 | if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) |
| @@ -163,7 +163,6 @@ struct tmio_mmc_host { · 162 unmodified lines | ||
| 163 | 163 | unsigned long last_req_ts; |
| 164 | 164 | struct mutex ios_lock; /* protect set_ios() context */ |
| 165 | 165 | bool native_hotplug; |
| 166 | − bool runtime_synced; | |
| 167 | 166 | bool sdio_irq_enabled; |
| 168 | 167 | |
| 169 | 168 | /* Mandatory callback */ |
| @@ -39,6 +39,7 @@ · 38 unmodified lines | ||
| 39 | 39 | #include <linux/module.h> |
| 40 | 40 | #include <linux/pagemap.h> |
| 41 | 41 | #include <linux/platform_device.h> |
| 42 | +#include <linux/pm_domain.h> | |
| 42 | 43 | #include <linux/pm_qos.h> |
| 43 | 44 | #include <linux/pm_runtime.h> |
| 44 | 45 | #include <linux/regulator/consumer.h> |
| @@ -1248,10 +1249,12 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) · 1203 unmodified lines | ||
| 1248 | 1249 | /* See if we also get DMA */ |
| 1249 | 1250 | tmio_mmc_request_dma(_host, pdata); |
| 1250 | 1251 | |
| 1252 | + dev_pm_domain_start(&pdev->dev); | |
| 1253 | + pm_runtime_get_noresume(&pdev->dev); | |
| 1254 | + pm_runtime_set_active(&pdev->dev); | |
| 1251 | 1255 | pm_runtime_set_autosuspend_delay(&pdev->dev, 50); |
| 1252 | 1256 | pm_runtime_use_autosuspend(&pdev->dev); |
| 1253 | 1257 | pm_runtime_enable(&pdev->dev); |
| 1254 | − pm_runtime_get_sync(&pdev->dev); | |
| 1255 | 1258 | |
| 1256 | 1259 | ret = mmc_add_host(mmc); |
| 1257 | 1260 | if (ret) |
| @@ -1333,11 +1336,6 @@ int tmio_mmc_host_runtime_resume(struct device *dev) · 75 unmodified lines | ||
| 1333 | 1336 | { |
| 1334 | 1337 | struct tmio_mmc_host *host = dev_get_drvdata(dev); |
| 1335 | 1338 | |
| 1336 | − if (!host->runtime_synced) { | |
| 1337 | − host->runtime_synced = true; | |
| 1338 | − return 0; | |
| 1339 | − } | |
| 1340 | − | |
| 1341 | 1339 | tmio_mmc_clk_enable(host); |
| 1342 | 1340 | tmio_mmc_hw_reset(host->mmc); |
| 1343 | 1341 | |
| @@ -2102,6 +2102,75 @@ put_table: · 2101 unmodified lines | ||
| 2102 | 2102 | return r; |
| 2103 | 2103 | } |
| 2104 | 2104 | |
| 2105 | +/** | |
| 2106 | + * dev_pm_opp_adjust_voltage() - helper to change the voltage of an OPP | |
| 2107 | + * @dev: device for which we do this operation | |
| 2108 | + * @freq: OPP frequency to adjust voltage of | |
| 2109 | + * @u_volt: new OPP target voltage | |
| 2110 | + * @u_volt_min: new OPP min voltage | |
| 2111 | + * @u_volt_max: new OPP max voltage | |
| 2112 | + * | |
| 2113 | + * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the | |
| 2114 | + * copy operation, returns 0 if no modifcation was done OR modification was | |
| 2115 | + * successful. | |
| 2116 | + */ | |
| 2117 | +int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, | |
| 2118 | + unsigned long u_volt, unsigned long u_volt_min, | |
| 2119 | + unsigned long u_volt_max) | |
| 2120 | + | |
| 2121 | +{ | |
| 2122 | + struct opp_table *opp_table; | |
| 2123 | + struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV); | |
| 2124 | + int r = 0; | |
| 2125 | + | |
| 2126 | + /* Find the opp_table */ | |
| 2127 | + opp_table = _find_opp_table(dev); | |
| 2128 | + if (IS_ERR(opp_table)) { | |
| 2129 | + r = PTR_ERR(opp_table); | |
| 2130 | + dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r); | |
| 2131 | + return r; | |
| 2132 | + } | |
| 2133 | + | |
| 2134 | + mutex_lock(&opp_table->lock); | |
| 2135 | + | |
| 2136 | + /* Do we have the frequency? */ | |
| 2137 | + list_for_each_entry(tmp_opp, &opp_table->opp_list, node) { | |
| 2138 | + if (tmp_opp->rate == freq) { | |
| 2139 | + opp = tmp_opp; | |
| 2140 | + break; | |
| 2141 | + } | |
| 2142 | + } | |
| 2143 | + | |
| 2144 | + if (IS_ERR(opp)) { | |
| 2145 | + r = PTR_ERR(opp); | |
| 2146 | + goto adjust_unlock; | |
| 2147 | + } | |
| 2148 | + | |
| 2149 | + /* Is update really needed? */ | |
| 2150 | + if (opp->supplies->u_volt == u_volt) | |
| 2151 | + goto adjust_unlock; | |
| 2152 | + | |
| 2153 | + opp->supplies->u_volt = u_volt; | |
| 2154 | + opp->supplies->u_volt_min = u_volt_min; | |
| 2155 | + opp->supplies->u_volt_max = u_volt_max; | |
| 2156 | + | |
| 2157 | + dev_pm_opp_get(opp); | |
| 2158 | + mutex_unlock(&opp_table->lock); | |
| 2159 | + | |
| 2160 | + /* Notify the voltage change of the OPP */ | |
| 2161 | + blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADJUST_VOLTAGE, | |
| 2162 | + opp); | |
| 2163 | + | |
| 2164 | + dev_pm_opp_put(opp); | |
| 2165 | + goto adjust_put_table; | |
| 2166 | + | |
| 2167 | +adjust_unlock: | |
| 2168 | + mutex_unlock(&opp_table->lock); | |
| 2169 | +adjust_put_table: | |
| 2170 | + dev_pm_opp_put_opp_table(opp_table); | |
| 2171 | + return r; | |
| 2172 | +} | |
| 2173 | + | |
| 2105 | 2174 | /** |
| 2106 | 2175 | * dev_pm_opp_enable() - Enable a specific OPP |
| 2107 | 2176 | * @dev: device for which we do this operation |
| @@ -978,6 +978,8 @@ static const struct x86_cpu_id rapl_ids[] __initconst = { · 977 unmodified lines | ||
| 978 | 978 | INTEL_CPU_FAM6(ICELAKE_NNPI, rapl_defaults_core), |
| 979 | 979 | INTEL_CPU_FAM6(ICELAKE_X, rapl_defaults_hsw_server), |
| 980 | 980 | INTEL_CPU_FAM6(ICELAKE_D, rapl_defaults_hsw_server), |
| 981 | + INTEL_CPU_FAM6(COMETLAKE_L, rapl_defaults_core), | |
| 982 | + INTEL_CPU_FAM6(COMETLAKE, rapl_defaults_core), | |
| 981 | 983 | |
| 982 | 984 | INTEL_CPU_FAM6(ATOM_SILVERMONT, rapl_defaults_byt), |
| 983 | 985 | INTEL_CPU_FAM6(ATOM_AIRMONT, rapl_defaults_cht), |
| @@ -637,6 +637,7 @@ extern void dev_pm_put_subsys_data(struct device *dev); · 636 unmodified lines | ||
| 637 | 637 | * struct dev_pm_domain - power management domain representation. |
| 638 | 638 | * |
| 639 | 639 | * @ops: Power management operations associated with this domain. |
| 640 | + * @start: Called when a user needs to start the device via the domain. | |
| 640 | 641 | * @detach: Called when removing a device from the domain. |
| 641 | 642 | * @activate: Called before executing probe routines for bus types and drivers. |
| 642 | 643 | * @sync: Called after successful driver probe. |
| @@ -648,6 +649,7 @@ extern void dev_pm_put_subsys_data(struct device *dev); · 5 unmodified lines | ||
| 648 | 649 | */ |
| 649 | 650 | struct dev_pm_domain { |
| 650 | 651 | struct dev_pm_ops ops; |
| 652 | + int (*start)(struct device *dev); | |
| 651 | 653 | void (*detach)(struct device *dev, bool power_off); |
| 652 | 654 | int (*activate)(struct device *dev); |
| 653 | 655 | void (*sync)(struct device *dev); |
| @@ -366,6 +366,7 @@ struct device *dev_pm_domain_attach_by_id(struct device *dev, · 365 unmodified lines | ||
| 366 | 366 | struct device *dev_pm_domain_attach_by_name(struct device *dev, |
| 367 | 367 | const char *name); |
| 368 | 368 | void dev_pm_domain_detach(struct device *dev, bool power_off); |
| 369 | +int dev_pm_domain_start(struct device *dev); | |
| 369 | 370 | void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd); |
| 370 | 371 | #else |
| 371 | 372 | static inline int dev_pm_domain_attach(struct device *dev, bool power_on) |
| @@ -383,6 +384,10 @@ static inline struct device *dev_pm_domain_attach_by_name(struct device *dev, · 11 unmodified lines | ||
| 383 | 384 | return NULL; |
| 384 | 385 | } |
| 385 | 386 | static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {} |
| 387 | +static inline int dev_pm_domain_start(struct device *dev) | |
| 388 | +{ | |
| 389 | + return 0; | |
| 390 | +} | |
| 386 | 391 | static inline void dev_pm_domain_set(struct device *dev, |
| 387 | 392 | struct dev_pm_domain *pd) {} |
| 388 | 393 | #endif |
| @@ -22,6 +22,7 @@ struct opp_table; · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | enum dev_pm_opp_event { |
| 24 | 24 | OPP_EVENT_ADD, OPP_EVENT_REMOVE, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE, |
| 25 | + OPP_EVENT_ADJUST_VOLTAGE, | |
| 25 | 26 | }; |
| 26 | 27 | |
| 27 | 28 | /** |
| @@ -113,6 +114,10 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, · 85 unmodified lines | ||
| 113 | 114 | void dev_pm_opp_remove(struct device *dev, unsigned long freq); |
| 114 | 115 | void dev_pm_opp_remove_all_dynamic(struct device *dev); |
| 115 | 116 | |
| 117 | +int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, | |
| 118 | + unsigned long u_volt, unsigned long u_volt_min, | |
| 119 | + unsigned long u_volt_max); | |
| 120 | + | |
| 116 | 121 | int dev_pm_opp_enable(struct device *dev, unsigned long freq); |
| 117 | 122 | |
| 118 | 123 | int dev_pm_opp_disable(struct device *dev, unsigned long freq); |
| @@ -242,6 +247,14 @@ static inline void dev_pm_opp_remove_all_dynamic(struct device *dev) · 123 unmodified lines | ||
| 242 | 247 | { |
| 243 | 248 | } |
| 244 | 249 | |
| 250 | +static inline int | |
| 251 | +dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, | |
| 252 | + unsigned long u_volt, unsigned long u_volt_min, | |
| 253 | + unsigned long u_volt_max) | |
| 254 | +{ | |
| 255 | + return 0; | |
| 256 | +} | |
| 257 | + | |
| 245 | 258 | static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq) |
| 246 | 259 | { |
| 247 | 260 | return 0; |
| @@ -734,8 +734,15 @@ zone_found: · 733 unmodified lines | ||
| 734 | 734 | * We have found the zone. Now walk the radix tree to find the leaf node |
| 735 | 735 | * for our PFN. |
| 736 | 736 | */ |
| 737 | + | |
| 738 | + /* | |
| 739 | + * If the zone we wish to scan is the the current zone and the | |
| 740 | + * pfn falls into the current node then we do not need to walk | |
| 741 | + * the tree. | |
| 742 | + */ | |
| 737 | 743 | node = bm->cur.node; |
| 738 | − if (((pfn - zone->start_pfn) & ~BM_BLOCK_MASK) == bm->cur.node_pfn) | |
| 744 | + if (zone == bm->cur.zone && | |
| 745 | + ((pfn - zone->start_pfn) & ~BM_BLOCK_MASK) == bm->cur.node_pfn) | |
| 739 | 746 | goto node_found; |
| 740 | 747 | |
| 741 | 748 | node = zone->rtree; |