Skip to content

Commit

Permalink
Merge branches 'pm-sleep', 'pm-domains', 'pm-opp' and 'powercap'
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Rafael J. Wysocki committed Nov 26, 2019
5 parents fa6a599 + 01ca482 + fe0c2ba + 16c71c5 + f84fdcb commit 5a97aa5
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 48 deletions.
20 changes: 20 additions & 0 deletions drivers/base/power/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,26 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
}
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: Device whose PM domain is to be set.
Expand Down
40 changes: 20 additions & 20 deletions drivers/base/power/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,13 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
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,
unsigned long val, void *ptr)
{
Expand Down Expand Up @@ -922,24 +929,6 @@ static int __init genpd_power_off_unused(void)
}
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

/**
Expand Down Expand Up @@ -1354,8 +1343,8 @@ static void genpd_syscore_switch(struct device *dev, bool suspend)
{
struct generic_pm_domain *genpd;

genpd = dev_to_genpd(dev);
if (!genpd_present(genpd))
genpd = dev_to_genpd_safe(dev);
if (!genpd)
return;

if (suspend) {
Expand Down Expand Up @@ -1805,6 +1794,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
genpd->domain.ops.poweroff_noirq = genpd_poweroff_noirq;
genpd->domain.ops.restore_noirq = genpd_restore_noirq;
genpd->domain.ops.complete = genpd_complete;
genpd->domain.start = genpd_dev_pm_start;

if (genpd->flags & GENPD_FLAG_PM_CLK) {
genpd->dev_ops.stop = pm_clk_suspend;
Expand Down Expand Up @@ -2020,6 +2010,16 @@ static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
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
* @np: Device node pointer associated with the PM domain provider.
Expand Down
30 changes: 12 additions & 18 deletions drivers/base/power/power.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ static inline bool device_pm_initialized(struct device *dev)
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 */

static inline void device_pm_sleep_init(struct device *dev) {}
Expand All @@ -141,6 +148,11 @@ static inline bool device_pm_initialized(struct device *dev)
return device_is_registered(dev);
}

static inline int pm_wakeup_source_sysfs_add(struct device *parent)
{
return 0;
}

#endif /* !CONFIG_PM_SLEEP */

static inline void device_pm_init(struct device *dev)
Expand All @@ -149,21 +161,3 @@ static inline void device_pm_init(struct device *dev)
device_pm_sleep_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 */
4 changes: 2 additions & 2 deletions drivers/base/power/wakeirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ void dev_pm_enable_wake_irq_check(struct device *dev,
{
struct wake_irq *wirq = dev->power.wakeirq;

if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK)))
if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
return;

if (likely(wirq->status & WAKE_IRQ_DEDICATED_MANAGED)) {
Expand All @@ -299,7 +299,7 @@ void dev_pm_disable_wake_irq_check(struct device *dev)
{
struct wake_irq *wirq = dev->power.wakeirq;

if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK)))
if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
return;

if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
Expand Down
1 change: 0 additions & 1 deletion drivers/mmc/host/tmio_mmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ struct tmio_mmc_host {
unsigned long last_req_ts;
struct mutex ios_lock; /* protect set_ios() context */
bool native_hotplug;
bool runtime_synced;
bool sdio_irq_enabled;

/* Mandatory callback */
Expand Down
10 changes: 4 additions & 6 deletions drivers/mmc/host/tmio_mmc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_qos.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
Expand Down Expand Up @@ -1248,10 +1249,12 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
/* See if we also get DMA */
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_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);

ret = mmc_add_host(mmc);
if (ret)
Expand Down Expand Up @@ -1333,11 +1336,6 @@ int tmio_mmc_host_runtime_resume(struct device *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_hw_reset(host->mmc);

Expand Down
69 changes: 69 additions & 0 deletions drivers/opp/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2102,6 +2102,75 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
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: device for which we do this operation
Expand Down
2 changes: 2 additions & 0 deletions drivers/powercap/intel_rapl_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_X, 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_AIRMONT, rapl_defaults_cht),
Expand Down
2 changes: 2 additions & 0 deletions include/linux/pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ extern void dev_pm_put_subsys_data(struct device *dev);
* struct dev_pm_domain - power management domain representation.
*
* @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.
* @activate: Called before executing probe routines for bus types and drivers.
* @sync: Called after successful driver probe.
Expand All @@ -648,6 +649,7 @@ extern void dev_pm_put_subsys_data(struct device *dev);
*/
struct dev_pm_domain {
struct dev_pm_ops ops;
int (*start)(struct device *dev);
void (*detach)(struct device *dev, bool power_off);
int (*activate)(struct device *dev);
void (*sync)(struct device *dev);
Expand Down
5 changes: 5 additions & 0 deletions include/linux/pm_domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
const char *name);
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);
#else
static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
Expand All @@ -383,6 +384,10 @@ static inline struct device *dev_pm_domain_attach_by_name(struct device *dev,
return NULL;
}
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,
struct dev_pm_domain *pd) {}
#endif
Expand Down
13 changes: 13 additions & 0 deletions include/linux/pm_opp.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct opp_table;

enum dev_pm_opp_event {
OPP_EVENT_ADD, OPP_EVENT_REMOVE, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE,
OPP_EVENT_ADJUST_VOLTAGE,
};

/**
Expand Down Expand Up @@ -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_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_disable(struct device *dev, unsigned long freq);
Expand Down Expand Up @@ -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)
{
return 0;
Expand Down
9 changes: 8 additions & 1 deletion kernel/power/snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
* 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;
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;

node = zone->rtree;
Expand Down

0 comments on commit 5a97aa5

Please sign in to comment.