Commit 5a97aa5b authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'pm-sleep', 'pm-domains', 'pm-opp' and 'powercap'

* 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
...@@ -187,6 +187,26 @@ void dev_pm_domain_detach(struct device *dev, bool power_off) ...@@ -187,6 +187,26 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
} }
EXPORT_SYMBOL_GPL(dev_pm_domain_detach); EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
/**
* dev_pm_domain_start - Start the device through its PM domain.
* @dev: Device to start.
*
* This function should typically be called during probe by a subsystem/driver,
* when it needs to start its device from the PM domain's perspective. Note
* that, it's assumed that the PM domain is already powered on when this
* function is called.
*
* Returns 0 on success and negative error values on failures.
*/
int dev_pm_domain_start(struct device *dev)
{
if (dev->pm_domain && dev->pm_domain->start)
return dev->pm_domain->start(dev);
return 0;
}
EXPORT_SYMBOL_GPL(dev_pm_domain_start);
/** /**
* dev_pm_domain_set - Set PM domain of a device. * dev_pm_domain_set - Set PM domain of a device.
* @dev: Device whose PM domain is to be set. * @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) ...@@ -634,6 +634,13 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
return ret; return ret;
} }
static int genpd_dev_pm_start(struct device *dev)
{
struct generic_pm_domain *genpd = dev_to_genpd(dev);
return genpd_start_dev(genpd, dev);
}
static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
unsigned long val, void *ptr) unsigned long val, void *ptr)
{ {
...@@ -922,24 +929,6 @@ static int __init genpd_power_off_unused(void) ...@@ -922,24 +929,6 @@ static int __init genpd_power_off_unused(void)
} }
late_initcall(genpd_power_off_unused); late_initcall(genpd_power_off_unused);
#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_GENERIC_DOMAINS_OF)
static bool genpd_present(const struct generic_pm_domain *genpd)
{
const struct generic_pm_domain *gpd;
if (IS_ERR_OR_NULL(genpd))
return false;
list_for_each_entry(gpd, &gpd_list, gpd_list_node)
if (gpd == genpd)
return true;
return false;
}
#endif
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
/** /**
...@@ -1354,8 +1343,8 @@ static void genpd_syscore_switch(struct device *dev, bool suspend) ...@@ -1354,8 +1343,8 @@ static void genpd_syscore_switch(struct device *dev, bool suspend)
{ {
struct generic_pm_domain *genpd; struct generic_pm_domain *genpd;
genpd = dev_to_genpd(dev); genpd = dev_to_genpd_safe(dev);
if (!genpd_present(genpd)) if (!genpd)
return; return;
if (suspend) { if (suspend) {
...@@ -1805,6 +1794,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd, ...@@ -1805,6 +1794,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
genpd->domain.ops.poweroff_noirq = genpd_poweroff_noirq; genpd->domain.ops.poweroff_noirq = genpd_poweroff_noirq;
genpd->domain.ops.restore_noirq = genpd_restore_noirq; genpd->domain.ops.restore_noirq = genpd_restore_noirq;
genpd->domain.ops.complete = genpd_complete; genpd->domain.ops.complete = genpd_complete;
genpd->domain.start = genpd_dev_pm_start;
if (genpd->flags & GENPD_FLAG_PM_CLK) { if (genpd->flags & GENPD_FLAG_PM_CLK) {
genpd->dev_ops.stop = pm_clk_suspend; genpd->dev_ops.stop = pm_clk_suspend;
...@@ -2020,6 +2010,16 @@ static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, ...@@ -2020,6 +2010,16 @@ static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
return 0; return 0;
} }
static bool genpd_present(const struct generic_pm_domain *genpd)
{
const struct generic_pm_domain *gpd;
list_for_each_entry(gpd, &gpd_list, gpd_list_node)
if (gpd == genpd)
return true;
return false;
}
/** /**
* of_genpd_add_provider_simple() - Register a simple PM domain provider * of_genpd_add_provider_simple() - Register a simple PM domain provider
* @np: Device node pointer associated with the PM domain provider. * @np: Device node pointer associated with the PM domain provider.
......
...@@ -117,6 +117,13 @@ static inline bool device_pm_initialized(struct device *dev) ...@@ -117,6 +117,13 @@ static inline bool device_pm_initialized(struct device *dev)
return dev->power.in_dpm_list; return dev->power.in_dpm_list;
} }
/* drivers/base/power/wakeup_stats.c */
extern int wakeup_source_sysfs_add(struct device *parent,
struct wakeup_source *ws);
extern void wakeup_source_sysfs_remove(struct wakeup_source *ws);
extern int pm_wakeup_source_sysfs_add(struct device *parent);
#else /* !CONFIG_PM_SLEEP */ #else /* !CONFIG_PM_SLEEP */
static inline void device_pm_sleep_init(struct device *dev) {} static inline void device_pm_sleep_init(struct device *dev) {}
...@@ -141,6 +148,11 @@ static inline bool device_pm_initialized(struct device *dev) ...@@ -141,6 +148,11 @@ static inline bool device_pm_initialized(struct device *dev)
return device_is_registered(dev); return device_is_registered(dev);
} }
static inline int pm_wakeup_source_sysfs_add(struct device *parent)
{
return 0;
}
#endif /* !CONFIG_PM_SLEEP */ #endif /* !CONFIG_PM_SLEEP */
static inline void device_pm_init(struct device *dev) static inline void device_pm_init(struct device *dev)
...@@ -149,21 +161,3 @@ static inline void device_pm_init(struct device *dev) ...@@ -149,21 +161,3 @@ static inline void device_pm_init(struct device *dev)
device_pm_sleep_init(dev); device_pm_sleep_init(dev);
pm_runtime_init(dev); pm_runtime_init(dev);
} }
#ifdef CONFIG_PM_SLEEP
/* drivers/base/power/wakeup_stats.c */
extern int wakeup_source_sysfs_add(struct device *parent,
struct wakeup_source *ws);
extern void wakeup_source_sysfs_remove(struct wakeup_source *ws);
extern int pm_wakeup_source_sysfs_add(struct device *parent);
#else /* !CONFIG_PM_SLEEP */
static inline int pm_wakeup_source_sysfs_add(struct device *parent)
{
return 0;
}
#endif /* CONFIG_PM_SLEEP */
...@@ -272,7 +272,7 @@ void dev_pm_enable_wake_irq_check(struct device *dev, ...@@ -272,7 +272,7 @@ void dev_pm_enable_wake_irq_check(struct device *dev,
{ {
struct wake_irq *wirq = dev->power.wakeirq; struct wake_irq *wirq = dev->power.wakeirq;
if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK))) if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
return; return;
if (likely(wirq->status & WAKE_IRQ_DEDICATED_MANAGED)) { if (likely(wirq->status & WAKE_IRQ_DEDICATED_MANAGED)) {
...@@ -299,7 +299,7 @@ void dev_pm_disable_wake_irq_check(struct device *dev) ...@@ -299,7 +299,7 @@ void dev_pm_disable_wake_irq_check(struct device *dev)
{ {
struct wake_irq *wirq = dev->power.wakeirq; struct wake_irq *wirq = dev->power.wakeirq;
if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK))) if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
return; return;
if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
......
...@@ -163,7 +163,6 @@ struct tmio_mmc_host { ...@@ -163,7 +163,6 @@ struct tmio_mmc_host {
unsigned long last_req_ts; unsigned long last_req_ts;
struct mutex ios_lock; /* protect set_ios() context */ struct mutex ios_lock; /* protect set_ios() context */
bool native_hotplug; bool native_hotplug;
bool runtime_synced;
bool sdio_irq_enabled; bool sdio_irq_enabled;
/* Mandatory callback */ /* Mandatory callback */
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_qos.h> #include <linux/pm_qos.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
...@@ -1248,10 +1249,12 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) ...@@ -1248,10 +1249,12 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
/* See if we also get DMA */ /* See if we also get DMA */
tmio_mmc_request_dma(_host, pdata); tmio_mmc_request_dma(_host, pdata);
dev_pm_domain_start(&pdev->dev);
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 50); pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
ret = mmc_add_host(mmc); ret = mmc_add_host(mmc);
if (ret) if (ret)
...@@ -1333,11 +1336,6 @@ int tmio_mmc_host_runtime_resume(struct device *dev) ...@@ -1333,11 +1336,6 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
{ {
struct tmio_mmc_host *host = dev_get_drvdata(dev); struct tmio_mmc_host *host = dev_get_drvdata(dev);
if (!host->runtime_synced) {
host->runtime_synced = true;
return 0;
}
tmio_mmc_clk_enable(host); tmio_mmc_clk_enable(host);
tmio_mmc_hw_reset(host->mmc); tmio_mmc_hw_reset(host->mmc);
......
...@@ -2102,6 +2102,75 @@ static int _opp_set_availability(struct device *dev, unsigned long freq, ...@@ -2102,6 +2102,75 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
return r; return r;
} }
/**
* dev_pm_opp_adjust_voltage() - helper to change the voltage of an OPP
* @dev: device for which we do this operation
* @freq: OPP frequency to adjust voltage of
* @u_volt: new OPP target voltage
* @u_volt_min: new OPP min voltage
* @u_volt_max: new OPP max voltage
*
* Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the
* copy operation, returns 0 if no modifcation was done OR modification was
* successful.
*/
int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
unsigned long u_volt, unsigned long u_volt_min,
unsigned long u_volt_max)
{
struct opp_table *opp_table;
struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV);
int r = 0;
/* Find the opp_table */
opp_table = _find_opp_table(dev);
if (IS_ERR(opp_table)) {
r = PTR_ERR(opp_table);
dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
return r;
}
mutex_lock(&opp_table->lock);
/* Do we have the frequency? */
list_for_each_entry(tmp_opp, &opp_table->opp_list, node) {
if (tmp_opp->rate == freq) {
opp = tmp_opp;
break;
}
}
if (IS_ERR(opp)) {
r = PTR_ERR(opp);
goto adjust_unlock;
}
/* Is update really needed? */
if (opp->supplies->u_volt == u_volt)
goto adjust_unlock;
opp->supplies->u_volt = u_volt;
opp->supplies->u_volt_min = u_volt_min;
opp->supplies->u_volt_max = u_volt_max;
dev_pm_opp_get(opp);
mutex_unlock(&opp_table->lock);
/* Notify the voltage change of the OPP */
blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADJUST_VOLTAGE,
opp);
dev_pm_opp_put(opp);
goto adjust_put_table;
adjust_unlock:
mutex_unlock(&opp_table->lock);
adjust_put_table:
dev_pm_opp_put_opp_table(opp_table);
return r;
}
/** /**
* dev_pm_opp_enable() - Enable a specific OPP * dev_pm_opp_enable() - Enable a specific OPP
* @dev: device for which we do this operation * @dev: device for which we do this operation
......
...@@ -978,6 +978,8 @@ static const struct x86_cpu_id rapl_ids[] __initconst = { ...@@ -978,6 +978,8 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
INTEL_CPU_FAM6(ICELAKE_NNPI, rapl_defaults_core), INTEL_CPU_FAM6(ICELAKE_NNPI, rapl_defaults_core),
INTEL_CPU_FAM6(ICELAKE_X, rapl_defaults_hsw_server), INTEL_CPU_FAM6(ICELAKE_X, rapl_defaults_hsw_server),
INTEL_CPU_FAM6(ICELAKE_D, rapl_defaults_hsw_server), INTEL_CPU_FAM6(ICELAKE_D, rapl_defaults_hsw_server),
INTEL_CPU_FAM6(COMETLAKE_L, rapl_defaults_core),
INTEL_CPU_FAM6(COMETLAKE, rapl_defaults_core),
INTEL_CPU_FAM6(ATOM_SILVERMONT, rapl_defaults_byt), INTEL_CPU_FAM6(ATOM_SILVERMONT, rapl_defaults_byt),
INTEL_CPU_FAM6(ATOM_AIRMONT, rapl_defaults_cht), INTEL_CPU_FAM6(ATOM_AIRMONT, rapl_defaults_cht),
......
...@@ -637,6 +637,7 @@ extern void dev_pm_put_subsys_data(struct device *dev); ...@@ -637,6 +637,7 @@ extern void dev_pm_put_subsys_data(struct device *dev);
* struct dev_pm_domain - power management domain representation. * struct dev_pm_domain - power management domain representation.
* *
* @ops: Power management operations associated with this domain. * @ops: Power management operations associated with this domain.
* @start: Called when a user needs to start the device via the domain.
* @detach: Called when removing a device from the domain. * @detach: Called when removing a device from the domain.
* @activate: Called before executing probe routines for bus types and drivers. * @activate: Called before executing probe routines for bus types and drivers.
* @sync: Called after successful driver probe. * @sync: Called after successful driver probe.
...@@ -648,6 +649,7 @@ extern void dev_pm_put_subsys_data(struct device *dev); ...@@ -648,6 +649,7 @@ extern void dev_pm_put_subsys_data(struct device *dev);
*/ */
struct dev_pm_domain { struct dev_pm_domain {
struct dev_pm_ops ops; struct dev_pm_ops ops;
int (*start)(struct device *dev);
void (*detach)(struct device *dev, bool power_off); void (*detach)(struct device *dev, bool power_off);
int (*activate)(struct device *dev); int (*activate)(struct device *dev);
void (*sync)(struct device *dev); void (*sync)(struct device *dev);
......
...@@ -366,6 +366,7 @@ struct device *dev_pm_domain_attach_by_id(struct device *dev, ...@@ -366,6 +366,7 @@ struct device *dev_pm_domain_attach_by_id(struct device *dev,
struct device *dev_pm_domain_attach_by_name(struct device *dev, struct device *dev_pm_domain_attach_by_name(struct device *dev,
const char *name); const char *name);
void dev_pm_domain_detach(struct device *dev, bool power_off); void dev_pm_domain_detach(struct device *dev, bool power_off);
int dev_pm_domain_start(struct device *dev);
void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd); void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd);
#else #else
static inline int dev_pm_domain_attach(struct device *dev, bool power_on) 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, ...@@ -383,6 +384,10 @@ static inline struct device *dev_pm_domain_attach_by_name(struct device *dev,
return NULL; return NULL;
} }
static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {} static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
static inline int dev_pm_domain_start(struct device *dev)
{
return 0;
}
static inline void dev_pm_domain_set(struct device *dev, static inline void dev_pm_domain_set(struct device *dev,
struct dev_pm_domain *pd) {} struct dev_pm_domain *pd) {}
#endif #endif
......
...@@ -22,6 +22,7 @@ struct opp_table; ...@@ -22,6 +22,7 @@ struct opp_table;
enum dev_pm_opp_event { enum dev_pm_opp_event {
OPP_EVENT_ADD, OPP_EVENT_REMOVE, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE, OPP_EVENT_ADD, OPP_EVENT_REMOVE, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE,
OPP_EVENT_ADJUST_VOLTAGE,
}; };
/** /**
...@@ -113,6 +114,10 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, ...@@ -113,6 +114,10 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq,
void dev_pm_opp_remove(struct device *dev, unsigned long freq); void dev_pm_opp_remove(struct device *dev, unsigned long freq);
void dev_pm_opp_remove_all_dynamic(struct device *dev); void dev_pm_opp_remove_all_dynamic(struct device *dev);
int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
unsigned long u_volt, unsigned long u_volt_min,
unsigned long u_volt_max);
int dev_pm_opp_enable(struct device *dev, unsigned long freq); int dev_pm_opp_enable(struct device *dev, unsigned long freq);
int dev_pm_opp_disable(struct device *dev, unsigned long freq); 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) ...@@ -242,6 +247,14 @@ static inline void dev_pm_opp_remove_all_dynamic(struct device *dev)
{ {
} }
static inline int
dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
unsigned long u_volt, unsigned long u_volt_min,
unsigned long u_volt_max)
{
return 0;
}
static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq) static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq)
{ {
return 0; return 0;
......
...@@ -734,8 +734,15 @@ static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, ...@@ -734,8 +734,15 @@ static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
* We have found the zone. Now walk the radix tree to find the leaf node * We have found the zone. Now walk the radix tree to find the leaf node
* for our PFN. * for our PFN.
*/ */
/*
* If the zone we wish to scan is the the current zone and the
* pfn falls into the current node then we do not need to walk
* the tree.
*/
node = bm->cur.node; node = bm->cur.node;
if (((pfn - zone->start_pfn) & ~BM_BLOCK_MASK) == bm->cur.node_pfn) if (zone == bm->cur.zone &&
((pfn - zone->start_pfn) & ~BM_BLOCK_MASK) == bm->cur.node_pfn)
goto node_found; goto node_found;
node = zone->rtree; node = zone->rtree;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment