Merge wakeup_source changes into msm-4.19

* refs/heads/tmp-5da1114:
  Restore "UPSTREAM: PM / wakeup updates"

Change-Id: Ic256d059a99f075b519c4441c8b12fe4da818d62
Signed-off-by: Ivaylo Georgiev <irgeorgiev@codeaurora.org>
This commit is contained in:
Ivaylo Georgiev 2020-05-23 05:19:19 -07:00
commit 1ba1a55750
37 changed files with 679 additions and 241 deletions

View file

@ -0,0 +1,76 @@
What: /sys/class/wakeup/
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
The /sys/class/wakeup/ directory contains pointers to all
wakeup sources in the kernel at that moment in time.
What: /sys/class/wakeup/.../name
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
This file contains the name of the wakeup source.
What: /sys/class/wakeup/.../active_count
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
This file contains the number of times the wakeup source was
activated.
What: /sys/class/wakeup/.../event_count
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
This file contains the number of signaled wakeup events
associated with the wakeup source.
What: /sys/class/wakeup/.../wakeup_count
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
This file contains the number of times the wakeup source might
abort suspend.
What: /sys/class/wakeup/.../expire_count
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
This file contains the number of times the wakeup source's
timeout has expired.
What: /sys/class/wakeup/.../active_time_ms
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
This file contains the amount of time the wakeup source has
been continuously active, in milliseconds. If the wakeup
source is not active, this file contains '0'.
What: /sys/class/wakeup/.../total_time_ms
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
This file contains the total amount of time this wakeup source
has been active, in milliseconds.
What: /sys/class/wakeup/.../max_time_ms
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
This file contains the maximum amount of time this wakeup
source has been continuously active, in milliseconds.
What: /sys/class/wakeup/.../last_change_ms
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
This file contains the monotonic clock time when the wakeup
source was touched last time, in milliseconds.
What: /sys/class/wakeup/.../prevent_suspend_time_ms
Date: June 2019
Contact: Tri Vo <trong@android.com>
Description:
The file contains the total amount of time this wakeup source
has been preventing autosleep, in milliseconds.

View file

@ -455,7 +455,8 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
goto out; goto out;
mutex_lock(&acpi_pm_notifier_lock); mutex_lock(&acpi_pm_notifier_lock);
adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev)); adev->wakeup.ws = wakeup_source_register(&adev->dev,
dev_name(&adev->dev));
adev->wakeup.context.dev = dev; adev->wakeup.context.dev = dev;
adev->wakeup.context.func = func; adev->wakeup.context.func = func;
adev->wakeup.flags.notifier_present = true; adev->wakeup.flags.notifier_present = true;

View file

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o runtime.o wakeirq.o obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o runtime.o wakeirq.o
obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o wakeup_stats.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o obj-$(CONFIG_PM_TRACE_RTC) += trace.o
obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o domain_governor.o obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o domain_governor.o
obj-$(CONFIG_HAVE_CLK) += clock_ops.o obj-$(CONFIG_HAVE_CLK) += clock_ops.o

View file

@ -154,3 +154,21 @@ 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 */

View file

@ -7,6 +7,7 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/pm_qos.h> #include <linux/pm_qos.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/pm_wakeup.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include "power.h" #include "power.h"
@ -672,8 +673,13 @@ int dpm_sysfs_add(struct device *dev)
if (rc) if (rc)
goto err_wakeup; goto err_wakeup;
} }
rc = pm_wakeup_source_sysfs_add(dev);
if (rc)
goto err_latency;
return 0; return 0;
err_latency:
sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group);
err_wakeup: err_wakeup:
sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
err_runtime: err_runtime:

View file

@ -76,22 +76,7 @@ static struct wakeup_source deleted_ws = {
.lock = __SPIN_LOCK_UNLOCKED(deleted_ws.lock), .lock = __SPIN_LOCK_UNLOCKED(deleted_ws.lock),
}; };
/** static DEFINE_IDA(wakeup_ida);
* wakeup_source_prepare - Prepare a new wakeup source for initialization.
* @ws: Wakeup source to prepare.
* @name: Pointer to the name of the new wakeup source.
*
* Callers must ensure that the @name string won't be freed when @ws is still in
* use.
*/
void wakeup_source_prepare(struct wakeup_source *ws, const char *name)
{
if (ws) {
memset(ws, 0, sizeof(*ws));
ws->name = name;
}
}
EXPORT_SYMBOL_GPL(wakeup_source_prepare);
/** /**
* wakeup_source_create - Create a struct wakeup_source object. * wakeup_source_create - Create a struct wakeup_source object.
@ -100,32 +85,34 @@ EXPORT_SYMBOL_GPL(wakeup_source_prepare);
struct wakeup_source *wakeup_source_create(const char *name) struct wakeup_source *wakeup_source_create(const char *name)
{ {
struct wakeup_source *ws; struct wakeup_source *ws;
const char *ws_name;
int id;
ws = kmalloc(sizeof(*ws), GFP_KERNEL); ws = kzalloc(sizeof(*ws), GFP_KERNEL);
if (!ws) if (!ws)
return NULL; goto err_ws;
ws_name = kstrdup_const(name, GFP_KERNEL);
if (!ws_name)
goto err_name;
ws->name = ws_name;
id = ida_alloc(&wakeup_ida, GFP_KERNEL);
if (id < 0)
goto err_id;
ws->id = id;
wakeup_source_prepare(ws, name ? kstrdup_const(name, GFP_KERNEL) : NULL);
return ws; return ws;
err_id:
kfree_const(ws->name);
err_name:
kfree(ws);
err_ws:
return NULL;
} }
EXPORT_SYMBOL_GPL(wakeup_source_create); EXPORT_SYMBOL_GPL(wakeup_source_create);
/**
* wakeup_source_drop - Prepare a struct wakeup_source object for destruction.
* @ws: Wakeup source to prepare for destruction.
*
* Callers must ensure that __pm_stay_awake() or __pm_wakeup_event() will never
* be run in parallel with this function for the same wakeup source object.
*/
void wakeup_source_drop(struct wakeup_source *ws)
{
if (!ws)
return;
__pm_relax(ws);
}
EXPORT_SYMBOL_GPL(wakeup_source_drop);
/* /*
* Record wakeup_source statistics being deleted into a dummy wakeup_source. * Record wakeup_source statistics being deleted into a dummy wakeup_source.
*/ */
@ -154,6 +141,13 @@ static void wakeup_source_record(struct wakeup_source *ws)
spin_unlock_irqrestore(&deleted_ws.lock, flags); spin_unlock_irqrestore(&deleted_ws.lock, flags);
} }
static void wakeup_source_free(struct wakeup_source *ws)
{
ida_free(&wakeup_ida, ws->id);
kfree_const(ws->name);
kfree(ws);
}
/** /**
* wakeup_source_destroy - Destroy a struct wakeup_source object. * wakeup_source_destroy - Destroy a struct wakeup_source object.
* @ws: Wakeup source to destroy. * @ws: Wakeup source to destroy.
@ -165,10 +159,9 @@ void wakeup_source_destroy(struct wakeup_source *ws)
if (!ws) if (!ws)
return; return;
wakeup_source_drop(ws); __pm_relax(ws);
wakeup_source_record(ws); wakeup_source_record(ws);
kfree_const(ws->name); wakeup_source_free(ws);
kfree(ws);
} }
EXPORT_SYMBOL_GPL(wakeup_source_destroy); EXPORT_SYMBOL_GPL(wakeup_source_destroy);
@ -220,16 +213,26 @@ EXPORT_SYMBOL_GPL(wakeup_source_remove);
/** /**
* wakeup_source_register - Create wakeup source and add it to the list. * wakeup_source_register - Create wakeup source and add it to the list.
* @dev: Device this wakeup source is associated with (or NULL if virtual).
* @name: Name of the wakeup source to register. * @name: Name of the wakeup source to register.
*/ */
struct wakeup_source *wakeup_source_register(const char *name) struct wakeup_source *wakeup_source_register(struct device *dev,
const char *name)
{ {
struct wakeup_source *ws; struct wakeup_source *ws;
int ret;
ws = wakeup_source_create(name); ws = wakeup_source_create(name);
if (ws) if (ws) {
if (!dev || device_is_registered(dev)) {
ret = wakeup_source_sysfs_add(dev, ws);
if (ret) {
wakeup_source_free(ws);
return NULL;
}
}
wakeup_source_add(ws); wakeup_source_add(ws);
}
return ws; return ws;
} }
EXPORT_SYMBOL_GPL(wakeup_source_register); EXPORT_SYMBOL_GPL(wakeup_source_register);
@ -242,6 +245,7 @@ void wakeup_source_unregister(struct wakeup_source *ws)
{ {
if (ws) { if (ws) {
wakeup_source_remove(ws); wakeup_source_remove(ws);
wakeup_source_sysfs_remove(ws);
wakeup_source_destroy(ws); wakeup_source_destroy(ws);
} }
} }
@ -285,7 +289,7 @@ int device_wakeup_enable(struct device *dev)
if (pm_suspend_target_state != PM_SUSPEND_ON) if (pm_suspend_target_state != PM_SUSPEND_ON)
dev_dbg(dev, "Suspicious %s() during system transition!\n", __func__); dev_dbg(dev, "Suspicious %s() during system transition!\n", __func__);
ws = wakeup_source_register(dev_name(dev)); ws = wakeup_source_register(dev, dev_name(dev));
if (!ws) if (!ws)
return -ENOMEM; return -ENOMEM;

View file

@ -0,0 +1,214 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Wakeup statistics in sysfs
*
* Copyright (c) 2019 Linux Foundation
* Copyright (c) 2019 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* Copyright (c) 2019 Google Inc.
*/
#include <linux/device.h>
#include <linux/idr.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/slab.h>
#include <linux/timekeeping.h>
#include "power.h"
static struct class *wakeup_class;
#define wakeup_attr(_name) \
static ssize_t _name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct wakeup_source *ws = dev_get_drvdata(dev); \
\
return sprintf(buf, "%lu\n", ws->_name); \
} \
static DEVICE_ATTR_RO(_name)
wakeup_attr(active_count);
wakeup_attr(event_count);
wakeup_attr(wakeup_count);
wakeup_attr(expire_count);
static ssize_t active_time_ms_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct wakeup_source *ws = dev_get_drvdata(dev);
ktime_t active_time =
ws->active ? ktime_sub(ktime_get(), ws->last_time) : 0;
return sprintf(buf, "%lld\n", ktime_to_ms(active_time));
}
static DEVICE_ATTR_RO(active_time_ms);
static ssize_t total_time_ms_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct wakeup_source *ws = dev_get_drvdata(dev);
ktime_t active_time;
ktime_t total_time = ws->total_time;
if (ws->active) {
active_time = ktime_sub(ktime_get(), ws->last_time);
total_time = ktime_add(total_time, active_time);
}
return sprintf(buf, "%lld\n", ktime_to_ms(total_time));
}
static DEVICE_ATTR_RO(total_time_ms);
static ssize_t max_time_ms_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct wakeup_source *ws = dev_get_drvdata(dev);
ktime_t active_time;
ktime_t max_time = ws->max_time;
if (ws->active) {
active_time = ktime_sub(ktime_get(), ws->last_time);
if (active_time > max_time)
max_time = active_time;
}
return sprintf(buf, "%lld\n", ktime_to_ms(max_time));
}
static DEVICE_ATTR_RO(max_time_ms);
static ssize_t last_change_ms_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct wakeup_source *ws = dev_get_drvdata(dev);
return sprintf(buf, "%lld\n", ktime_to_ms(ws->last_time));
}
static DEVICE_ATTR_RO(last_change_ms);
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct wakeup_source *ws = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", ws->name);
}
static DEVICE_ATTR_RO(name);
static ssize_t prevent_suspend_time_ms_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct wakeup_source *ws = dev_get_drvdata(dev);
ktime_t prevent_sleep_time = ws->prevent_sleep_time;
if (ws->active && ws->autosleep_enabled) {
prevent_sleep_time = ktime_add(prevent_sleep_time,
ktime_sub(ktime_get(), ws->start_prevent_time));
}
return sprintf(buf, "%lld\n", ktime_to_ms(prevent_sleep_time));
}
static DEVICE_ATTR_RO(prevent_suspend_time_ms);
static struct attribute *wakeup_source_attrs[] = {
&dev_attr_name.attr,
&dev_attr_active_count.attr,
&dev_attr_event_count.attr,
&dev_attr_wakeup_count.attr,
&dev_attr_expire_count.attr,
&dev_attr_active_time_ms.attr,
&dev_attr_total_time_ms.attr,
&dev_attr_max_time_ms.attr,
&dev_attr_last_change_ms.attr,
&dev_attr_prevent_suspend_time_ms.attr,
NULL,
};
ATTRIBUTE_GROUPS(wakeup_source);
static void device_create_release(struct device *dev)
{
kfree(dev);
}
static struct device *wakeup_source_device_create(struct device *parent,
struct wakeup_source *ws)
{
struct device *dev = NULL;
int retval = -ENODEV;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
retval = -ENOMEM;
goto error;
}
device_initialize(dev);
dev->devt = MKDEV(0, 0);
dev->class = wakeup_class;
dev->parent = parent;
dev->groups = wakeup_source_groups;
dev->release = device_create_release;
dev_set_drvdata(dev, ws);
device_set_pm_not_required(dev);
retval = kobject_set_name(&dev->kobj, "wakeup%d", ws->id);
if (retval)
goto error;
retval = device_add(dev);
if (retval)
goto error;
return dev;
error:
put_device(dev);
return ERR_PTR(retval);
}
/**
* wakeup_source_sysfs_add - Add wakeup_source attributes to sysfs.
* @parent: Device given wakeup source is associated with (or NULL if virtual).
* @ws: Wakeup source to be added in sysfs.
*/
int wakeup_source_sysfs_add(struct device *parent, struct wakeup_source *ws)
{
struct device *dev;
dev = wakeup_source_device_create(parent, ws);
if (IS_ERR(dev))
return PTR_ERR(dev);
ws->dev = dev;
return 0;
}
/**
* pm_wakeup_source_sysfs_add - Add wakeup_source attributes to sysfs
* for a device if they're missing.
* @parent: Device given wakeup source is associated with
*/
int pm_wakeup_source_sysfs_add(struct device *parent)
{
if (!parent->power.wakeup || parent->power.wakeup->dev)
return 0;
return wakeup_source_sysfs_add(parent, parent->power.wakeup);
}
/**
* wakeup_source_sysfs_remove - Remove wakeup_source attributes from sysfs.
* @ws: Wakeup source to be removed from sysfs.
*/
void wakeup_source_sysfs_remove(struct wakeup_source *ws)
{
device_unregister(ws->dev);
}
static int __init wakeup_sources_sysfs_init(void)
{
wakeup_class = class_create(THIS_MODULE, "wakeup");
return PTR_ERR_OR_ZERO(wakeup_class);
}
postcore_initcall(wakeup_sources_sysfs_init);

View file

@ -34,7 +34,6 @@
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/sort.h> #include <linux/sort.h>
#include <linux/msm_dma_iommu_mapping.h> #include <linux/msm_dma_iommu_mapping.h>
#include <asm/dma-iommu.h>
#include "adsprpc_compat.h" #include "adsprpc_compat.h"
#include "adsprpc_shared.h" #include "adsprpc_shared.h"
#include <soc/qcom/ramdump.h> #include <soc/qcom/ramdump.h>
@ -75,6 +74,9 @@
#define SENSORS_PDR_SLPI_SERVICE_NAME SENSORS_PDR_ADSP_SERVICE_NAME #define SENSORS_PDR_SLPI_SERVICE_NAME SENSORS_PDR_ADSP_SERVICE_NAME
#define SLPI_SENSORPD_NAME "msm/slpi/sensor_pd" #define SLPI_SENSORPD_NAME "msm/slpi/sensor_pd"
#define FASTRPC_SECURE_WAKE_SOURCE_CLIENT_NAME "adsprpc-secure"
#define FASTRPC_NON_SECURE_WAKE_SOURCE_CLIENT_NAME "adsprpc-non_secure"
#define RPC_TIMEOUT (5 * HZ) #define RPC_TIMEOUT (5 * HZ)
#define BALIGN 128 #define BALIGN 128
#define NUM_CHANNELS 4 /* adsp, mdsp, slpi, cdsp*/ #define NUM_CHANNELS 4 /* adsp, mdsp, slpi, cdsp*/
@ -148,10 +150,10 @@
#define PERF(enb, cnt, ff) \ #define PERF(enb, cnt, ff) \
{\ {\
struct timespec startT = {0};\ struct timespec64 startT = {0};\
int64_t *counter = cnt;\ int64_t *counter = cnt;\
if (enb && counter) {\ if (enb && counter) {\
getnstimeofday(&startT);\ ktime_get_real_ts64(&startT);\
} \ } \
ff ;\ ff ;\
if (enb && counter) {\ if (enb && counter) {\
@ -382,6 +384,11 @@ struct fastrpc_apps {
bool legacy_remote_heap; bool legacy_remote_heap;
/* Unique job id for each message */ /* Unique job id for each message */
uint64_t jobid[NUM_CHANNELS]; uint64_t jobid[NUM_CHANNELS];
struct device *secure_dev;
struct device *non_secure_dev;
/* Secure subsystems like ADSP/SLPI will use secure client */
struct wakeup_source *wake_source_secure;
/* Non-secure subsystem like CDSP will use regular client */
struct wakeup_source *wake_source; struct wakeup_source *wake_source;
struct qos_cores silvercores; struct qos_cores silvercores;
uint32_t max_size_limit; uint32_t max_size_limit;
@ -468,7 +475,6 @@ struct fastrpc_file {
char *debug_buf; char *debug_buf;
/* Flag to enable PM wake/relax voting for every remote invoke */ /* Flag to enable PM wake/relax voting for every remote invoke */
int wake_enable; int wake_enable;
struct wakeup_source *wake_source;
uint32_t ws_timeout; uint32_t ws_timeout;
}; };
@ -542,16 +548,16 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = {
static int hlosvm[1] = {VMID_HLOS}; static int hlosvm[1] = {VMID_HLOS};
static int hlosvmperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; static int hlosvmperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
static void fastrpc_pm_awake(struct fastrpc_file *fl); static void fastrpc_pm_awake(struct fastrpc_file *fl, int channel_type);
static inline int64_t getnstimediff(struct timespec *start) static inline int64_t getnstimediff(struct timespec64 *start)
{ {
int64_t ns; int64_t ns;
struct timespec ts, b; struct timespec64 ts, b;
getnstimeofday(&ts); ktime_get_real_ts64(&ts);
b = timespec_sub(ts, *start); b = timespec64_sub(ts, *start);
ns = timespec_to_ns(&b); ns = timespec64_to_ns(&b);
return ns; return ns;
} }
@ -1480,7 +1486,7 @@ static void context_free(struct smq_invoke_ctx *ctx)
static void context_notify_user(struct smq_invoke_ctx *ctx, static void context_notify_user(struct smq_invoke_ctx *ctx,
int retval, uint32_t rspFlags, uint32_t earlyWakeTime) int retval, uint32_t rspFlags, uint32_t earlyWakeTime)
{ {
fastrpc_pm_awake(ctx->fl); fastrpc_pm_awake(ctx->fl, gcinfo[ctx->fl->cid].secure);
ctx->retval = retval; ctx->retval = retval;
switch (rspFlags) { switch (rspFlags) {
case NORMAL_RESPONSE: case NORMAL_RESPONSE:
@ -1934,10 +1940,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
ctx->overps[oix]->mstart, ctx->overps[oix]->mstart,
rpra[i].buf.len, map->size); rpra[i].buf.len, map->size);
} }
} else }
dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
uint64_to_ptr(rpra[i].buf.pv
+ rpra[i].buf.len));
} }
} }
PERF_END); PERF_END);
@ -2094,11 +2097,8 @@ static void inv_args(struct smq_invoke_ctx *ctx)
offset, ctx->overps[i]->mend, offset, ctx->overps[i]->mend,
ctx->overps[i]->mstart, ctx->overps[i]->mstart,
rpra[over].buf.len, map->size); rpra[over].buf.len, map->size);
}
} }
} else
dmac_inv_range((char *)uint64_to_ptr(rpra[over].buf.pv),
(char *)uint64_to_ptr(rpra[over].buf.pv
+ rpra[over].buf.len));
} }
} }
bail: bail:
@ -2174,15 +2174,22 @@ static void fastrpc_init(struct fastrpc_apps *me)
me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL; me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL;
} }
static inline void fastrpc_pm_awake(struct fastrpc_file *fl) static inline void fastrpc_pm_awake(struct fastrpc_file *fl, int channel_type)
{ {
if (!fl->wake_enable || !fl->wake_source) struct fastrpc_apps *me = &gfa;
return; struct wakeup_source *wake_source = NULL;
/* /*
* Vote with PM to abort any suspend in progress and * Vote with PM to abort any suspend in progress and
* keep system awake for specified timeout * keep system awake for specified timeout
*/ */
pm_wakeup_ws_event(fl->wake_source, fl->ws_timeout, true); if (channel_type == SECURE_CHANNEL)
wake_source = me->wake_source_secure;
else if (channel_type == NON_SECURE_CHANNEL)
wake_source = me->wake_source;
if (wake_source)
pm_wakeup_ws_event(wake_source, fl->ws_timeout, true);
} }
static inline int fastrpc_wait_for_response(struct smq_invoke_ctx *ctx, static inline int fastrpc_wait_for_response(struct smq_invoke_ctx *ctx,
@ -2278,7 +2285,7 @@ static void fastrpc_wait_for_completion(struct smq_invoke_ctx *ctx,
} }
static void fastrpc_update_invoke_count(uint32_t handle, int64_t *perf_counter, static void fastrpc_update_invoke_count(uint32_t handle, int64_t *perf_counter,
struct timespec *invoket) struct timespec64 *invoket)
{ {
/* update invoke count for dynamic handles */ /* update invoke count for dynamic handles */
if (handle != FASTRPC_STATIC_HANDLE_LISTENER) { if (handle != FASTRPC_STATIC_HANDLE_LISTENER) {
@ -2302,12 +2309,12 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
struct smq_invoke_ctx *ctx = NULL; struct smq_invoke_ctx *ctx = NULL;
struct fastrpc_ioctl_invoke *invoke = &inv->inv; struct fastrpc_ioctl_invoke *invoke = &inv->inv;
int err = 0, interrupted = 0, cid = fl->cid; int err = 0, interrupted = 0, cid = fl->cid;
struct timespec invoket = {0}; struct timespec64 invoket = {0};
int64_t *perf_counter = NULL; int64_t *perf_counter = NULL;
if (fl->profile) { if (fl->profile) {
perf_counter = getperfcounter(fl, PERF_COUNT); perf_counter = getperfcounter(fl, PERF_COUNT);
getnstimeofday(&invoket); ktime_get_real_ts64(&invoket);
} }
if (!kernel) { if (!kernel) {
@ -3612,8 +3619,6 @@ static int fastrpc_file_free(struct fastrpc_file *fl)
spin_lock(&fl->apps->hlock); spin_lock(&fl->apps->hlock);
hlist_del_init(&fl->hn); hlist_del_init(&fl->hn);
spin_unlock(&fl->apps->hlock); spin_unlock(&fl->apps->hlock);
if (fl->wake_source)
wakeup_source_unregister(fl->wake_source);
kfree(fl->debug_buf); kfree(fl->debug_buf);
if (!fl->sctx) { if (!fl->sctx) {
@ -3963,6 +3968,21 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
return err; return err;
} }
static inline void fastrpc_register_wakeup_source(struct device *dev,
const char *client_name, struct wakeup_source **device_wake_source)
{
struct wakeup_source *wake_source = NULL;
wake_source = wakeup_source_register(dev, client_name);
if (IS_ERR_OR_NULL(wake_source)) {
pr_err("adsprpc: Error: %s: %s: wakeup_source_register failed for dev %s, client %s with err %ld\n",
__func__, current->comm, dev_name(dev),
client_name, PTR_ERR(wake_source));
return;
}
*device_wake_source = wake_source;
}
static int fastrpc_device_open(struct inode *inode, struct file *filp) static int fastrpc_device_open(struct inode *inode, struct file *filp)
{ {
int err = 0; int err = 0;
@ -3986,11 +4006,6 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
if (err) if (err)
return err; return err;
fl->wake_source = wakeup_source_register(fl->debug_buf);
if (IS_ERR_OR_NULL(fl->wake_source)) {
pr_err("adsprpc: Error: %s: %s: wakeup_source_register failed with err %ld\n",
current->comm, __func__, PTR_ERR(fl->wake_source));
}
context_list_ctor(&fl->clst); context_list_ctor(&fl->clst);
spin_lock_init(&fl->hlock); spin_lock_init(&fl->hlock);
INIT_HLIST_HEAD(&fl->maps); INIT_HLIST_HEAD(&fl->maps);
@ -4155,7 +4170,7 @@ static int fastrpc_internal_control(struct fastrpc_file *fl,
fl->ws_timeout = MAX_PM_TIMEOUT_MS; fl->ws_timeout = MAX_PM_TIMEOUT_MS;
else else
fl->ws_timeout = cp->pm.timeout; fl->ws_timeout = cp->pm.timeout;
fastrpc_pm_awake(fl); fastrpc_pm_awake(fl, gcinfo[fl->cid].secure);
break; break;
case FASTRPC_CONTROL_DSPPROCESS_CLEAN: case FASTRPC_CONTROL_DSPPROCESS_CLEAN:
(void)fastrpc_release_current_dsp_process(fl); (void)fastrpc_release_current_dsp_process(fl);
@ -5112,13 +5127,13 @@ static int __init fastrpc_device_init(void)
} }
me->rpmsg_register = 1; me->rpmsg_register = 1;
me->wake_source = wakeup_source_register("adsprpc"); fastrpc_register_wakeup_source(me->non_secure_dev,
VERIFY(err, !IS_ERR_OR_NULL(me->wake_source)); FASTRPC_NON_SECURE_WAKE_SOURCE_CLIENT_NAME,
if (err) { &me->wake_source);
pr_err("adsprpc: Error: %s: wakeup_source_register failed with err %d\n", fastrpc_register_wakeup_source(me->secure_dev,
__func__, PTR_ERR(me->wake_source)); FASTRPC_SECURE_WAKE_SOURCE_CLIENT_NAME,
goto device_create_bail; &me->wake_source_secure);
}
return 0; return 0;
device_create_bail: device_create_bail:
for (i = 0; i < NUM_CHANNELS; i++) { for (i = 0; i < NUM_CHANNELS; i++) {
@ -5171,6 +5186,8 @@ static void __exit fastrpc_device_exit(void)
unregister_rpmsg_driver(&fastrpc_rpmsg_client); unregister_rpmsg_driver(&fastrpc_rpmsg_client);
if (me->wake_source) if (me->wake_source)
wakeup_source_unregister(me->wake_source); wakeup_source_unregister(me->wake_source);
if (me->wake_source_secure)
wakeup_source_unregister(me->wake_source_secure);
debugfs_remove_recursive(debugfs_root); debugfs_remove_recursive(debugfs_root);
} }

View file

@ -4379,7 +4379,8 @@ static int diagchar_setup_cdev(dev_t devno)
if (!driver->diag_dev) if (!driver->diag_dev)
return -EIO; return -EIO;
driver->diag_dev->power.wakeup = wakeup_source_register("DIAG_WS"); driver->diag_dev->power.wakeup =
wakeup_source_register(driver->diag_dev, "DIAG_WS");
return 0; return 0;
} }

View file

@ -273,7 +273,7 @@ struct geni_i3c_dev {
struct geni_ibi ibi; struct geni_ibi ibi;
struct workqueue_struct *hj_wq; struct workqueue_struct *hj_wq;
struct work_struct hj_wd; struct work_struct hj_wd;
struct wakeup_source hj_wl; struct wakeup_source *hj_wl;
struct pinctrl_state *i3c_gpio_disable; struct pinctrl_state *i3c_gpio_disable;
}; };
@ -1960,7 +1960,14 @@ static int geni_i3c_probe(struct platform_device *pdev)
geni_se_init(gi3c->se.base, gi3c->tx_wm, tx_depth); geni_se_init(gi3c->se.base, gi3c->tx_wm, tx_depth);
se_config_packing(gi3c->se.base, BITS_PER_BYTE, PACKING_BYTES_PW, true); se_config_packing(gi3c->se.base, BITS_PER_BYTE, PACKING_BYTES_PW, true);
wakeup_source_init(&gi3c->hj_wl, dev_name(gi3c->se.dev)); gi3c->hj_wl = wakeup_source_register(gi3c->se.dev,
dev_name(gi3c->se.dev));
if (!gi3c->hj_wl) {
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev, "wakeup source registration failed\n");
se_geni_resources_off(&gi3c->se.i3c_rsc);
return -ENOMEM;
}
INIT_WORK(&gi3c->hj_wd, geni_i3c_hotjoin); INIT_WORK(&gi3c->hj_wd, geni_i3c_hotjoin);
gi3c->hj_wq = alloc_workqueue("%s", 0, 0, dev_name(gi3c->se.dev)); gi3c->hj_wq = alloc_workqueue("%s", 0, 0, dev_name(gi3c->se.dev));
@ -2007,7 +2014,7 @@ static int geni_i3c_remove(struct platform_device *pdev)
if (gi3c->ibi.is_init) if (gi3c->ibi.is_init)
qcom_geni_i3c_ibi_unconf(gi3c); qcom_geni_i3c_ibi_unconf(gi3c);
destroy_workqueue(gi3c->hj_wq); destroy_workqueue(gi3c->hj_wq);
wakeup_source_trash(&gi3c->hj_wl); wakeup_source_unregister(gi3c->hj_wl);
/*force suspend to avoid the auto suspend caused by driver removal*/ /*force suspend to avoid the auto suspend caused by driver removal*/
pm_runtime_force_suspend(gi3c->se.dev); pm_runtime_force_suspend(gi3c->se.dev);
ret = pinctrl_select_state(gi3c->se.i3c_rsc.geni_pinctrl, ret = pinctrl_select_state(gi3c->se.i3c_rsc.geni_pinctrl,

View file

@ -38,8 +38,8 @@ struct keycombo_state {
void (*key_down_fn)(void *); void (*key_down_fn)(void *);
void *priv; void *priv;
int key_is_down; int key_is_down;
struct wakeup_source combo_held_wake_source; struct wakeup_source *combo_held_wake_source;
struct wakeup_source combo_up_wake_source; struct wakeup_source *combo_up_wake_source;
}; };
static void do_key_down(struct work_struct *work) static void do_key_down(struct work_struct *work)
@ -58,7 +58,7 @@ static void do_key_up(struct work_struct *work)
key_up_work); key_up_work);
if (state->key_up_fn) if (state->key_up_fn)
state->key_up_fn(state->priv); state->key_up_fn(state->priv);
__pm_relax(&state->combo_up_wake_source); __pm_relax(state->combo_up_wake_source);
} }
static void keycombo_event(struct input_handle *handle, unsigned int type, static void keycombo_event(struct input_handle *handle, unsigned int type,
@ -92,17 +92,17 @@ static void keycombo_event(struct input_handle *handle, unsigned int type,
state->key_down--; state->key_down--;
} }
if (state->key_down == state->key_down_target && state->key_up == 0) { if (state->key_down == state->key_down_target && state->key_up == 0) {
__pm_stay_awake(&state->combo_held_wake_source); __pm_stay_awake(state->combo_held_wake_source);
state->key_is_down = 1; state->key_is_down = 1;
if (queue_delayed_work(state->wq, &state->key_down_work, if (queue_delayed_work(state->wq, &state->key_down_work,
state->delay)) state->delay))
pr_debug("Key down work already queued!"); pr_debug("Key down work already queued!");
} else if (state->key_is_down) { } else if (state->key_is_down) {
if (!cancel_delayed_work(&state->key_down_work)) { if (!cancel_delayed_work(&state->key_down_work)) {
__pm_stay_awake(&state->combo_up_wake_source); __pm_stay_awake(state->combo_up_wake_source);
queue_work(state->wq, &state->key_up_work); queue_work(state->wq, &state->key_up_work);
} }
__pm_relax(&state->combo_held_wake_source); __pm_relax(state->combo_held_wake_source);
state->key_is_down = 0; state->key_is_down = 0;
} }
done: done:
@ -213,8 +213,21 @@ static int keycombo_probe(struct platform_device *pdev)
state->key_up_fn = pdata->key_up_fn; state->key_up_fn = pdata->key_up_fn;
INIT_WORK(&state->key_up_work, do_key_up); INIT_WORK(&state->key_up_work, do_key_up);
wakeup_source_init(&state->combo_held_wake_source, "key combo"); state->combo_held_wake_source =
wakeup_source_init(&state->combo_up_wake_source, "key combo up"); wakeup_source_register(&pdev->dev, "key combo");
if (!state->combo_held_wake_source) {
kfree(state);
return -ENOMEM;
}
state->combo_up_wake_source =
wakeup_source_register(&pdev->dev, "key combo up");
if (!state->combo_up_wake_source) {
kfree(state);
wakeup_source_unregister(state->combo_held_wake_source);
return -ENOMEM;
}
state->delay = msecs_to_jiffies(pdata->key_down_delay); state->delay = msecs_to_jiffies(pdata->key_down_delay);
state->input_handler.event = keycombo_event; state->input_handler.event = keycombo_event;
@ -225,6 +238,8 @@ static int keycombo_probe(struct platform_device *pdev)
ret = input_register_handler(&state->input_handler); ret = input_register_handler(&state->input_handler);
if (ret) { if (ret) {
kfree(state); kfree(state);
wakeup_source_unregister(state->combo_up_wake_source);
wakeup_source_unregister(state->combo_held_wake_source);
return ret; return ret;
} }
platform_set_drvdata(pdev, state); platform_set_drvdata(pdev, state);
@ -235,6 +250,8 @@ int keycombo_remove(struct platform_device *pdev)
{ {
struct keycombo_state *state = platform_get_drvdata(pdev); struct keycombo_state *state = platform_get_drvdata(pdev);
input_unregister_handler(&state->input_handler); input_unregister_handler(&state->input_handler);
wakeup_source_unregister(state->combo_up_wake_source);
wakeup_source_unregister(state->combo_held_wake_source);
destroy_workqueue(state->wq); destroy_workqueue(state->wq);
kfree(state); kfree(state);
return 0; return 0;

View file

@ -302,7 +302,8 @@ int gpio_event_input_func(struct gpio_event_input_devs *input_devs,
input_devs->dev[0]->name, input_devs->dev[0]->name,
(input_devs->count > 1) ? "..." : ""); (input_devs->count > 1) ? "..." : "");
ds->ws = wakeup_source_register(wlname); ds->ws = wakeup_source_register(&input_devs->dev[0]->dev,
wlname);
kfree(wlname); kfree(wlname);
if (!ds->ws) { if (!ds->ws) {
ret = -ENOMEM; ret = -ENOMEM;

View file

@ -24,7 +24,7 @@ struct gpio_kp {
struct gpio_event_input_devs *input_devs; struct gpio_event_input_devs *input_devs;
struct gpio_event_matrix_info *keypad_info; struct gpio_event_matrix_info *keypad_info;
struct hrtimer timer; struct hrtimer timer;
struct wakeup_source wake_src; struct wakeup_source *wake_src;
int current_output; int current_output;
unsigned int use_irq:1; unsigned int use_irq:1;
unsigned int key_state_changed:1; unsigned int key_state_changed:1;
@ -214,7 +214,7 @@ static enum hrtimer_restart gpio_keypad_timer_func(struct hrtimer *timer)
} }
for (in = 0; in < mi->ninputs; in++) for (in = 0; in < mi->ninputs; in++)
enable_irq(gpio_to_irq(mi->input_gpios[in])); enable_irq(gpio_to_irq(mi->input_gpios[in]));
__pm_relax(&kp->wake_src); __pm_relax(kp->wake_src);
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
} }
@ -241,7 +241,7 @@ static irqreturn_t gpio_keypad_irq_handler(int irq_in, void *dev_id)
else else
gpio_direction_input(mi->output_gpios[i]); gpio_direction_input(mi->output_gpios[i]);
} }
__pm_stay_awake(&kp->wake_src); __pm_stay_awake(kp->wake_src);
hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -395,7 +395,14 @@ int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
kp->timer.function = gpio_keypad_timer_func; kp->timer.function = gpio_keypad_timer_func;
wakeup_source_init(&kp->wake_src, "gpio_kp");
kp->wake_src =
wakeup_source_register(&input_devs->dev[0]->dev, "gpio_kp");
if (!kp->wake_src) {
err = -ENOMEM;
goto err_wakeup_source_register_failed;
}
err = gpio_keypad_request_irqs(kp); err = gpio_keypad_request_irqs(kp);
kp->use_irq = err == 0; kp->use_irq = err == 0;
@ -405,7 +412,7 @@ int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
kp->use_irq ? "interrupt" : "polling"); kp->use_irq ? "interrupt" : "polling");
if (kp->use_irq) if (kp->use_irq)
__pm_stay_awake(&kp->wake_src); __pm_stay_awake(kp->wake_src);
hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
return 0; return 0;
@ -419,8 +426,9 @@ int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
free_irq(gpio_to_irq(mi->input_gpios[i]), kp); free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
hrtimer_cancel(&kp->timer); hrtimer_cancel(&kp->timer);
wakeup_source_trash(&kp->wake_src); wakeup_source_unregister(kp->wake_src);
for (i = mi->noutputs - 1; i >= 0; i--) { err_wakeup_source_register_failed:
for (i = mi->ninputs - 1; i >= 0; i--) {
err_gpio_direction_input_failed: err_gpio_direction_input_failed:
gpio_free(mi->input_gpios[i]); gpio_free(mi->input_gpios[i]);
err_request_input_gpio_failed: err_request_input_gpio_failed:

View file

@ -1596,7 +1596,7 @@ static ssize_t fts_gesture_mask_show(struct device *dev,
if (mask[0] == 0) { if (mask[0] == 0) {
res = ERROR_OP_NOT_ALLOW; res = ERROR_OP_NOT_ALLOW;
logError(1, "%s %s:Call before echo enable/disable xx xx >", logError(1, "%s %s:Call before echo enable/disable xx xx >",
tag), __func__; tag, __func__);
logError(1, "%s %s: gesture_mask with a correct number of ", logError(1, "%s %s: gesture_mask with a correct number of ",
tag, __func__); tag, __func__);
logError(1, "parameters! ERROR %08X\n", res); logError(1, "parameters! ERROR %08X\n", res);
@ -3263,7 +3263,7 @@ static void fts_event_handler(struct work_struct *work)
* read all the FIFO and parsing events * read all the FIFO and parsing events
*/ */
__pm_wakeup_event(&info->wakeup_source, HZ); __pm_wakeup_event(info->wakeup_source, HZ);
regAdd = FIFO_CMD_READONE; regAdd = FIFO_CMD_READONE;
for (count = 0; count < FIFO_DEPTH; count++) { for (count = 0; count < FIFO_DEPTH; count++) {
@ -4115,7 +4115,7 @@ static void fts_resume_work(struct work_struct *work)
info = container_of(work, struct fts_ts_info, resume_work); info = container_of(work, struct fts_ts_info, resume_work);
__pm_wakeup_event(&info->wakeup_source, HZ); __pm_wakeup_event(info->wakeup_source, HZ);
fts_chip_power_switch(info, true); fts_chip_power_switch(info, true);
@ -4145,7 +4145,7 @@ static void fts_suspend_work(struct work_struct *work)
info = container_of(work, struct fts_ts_info, suspend_work); info = container_of(work, struct fts_ts_info, suspend_work);
__pm_wakeup_event(&info->wakeup_source, HZ); __pm_wakeup_event(info->wakeup_source, HZ);
info->resume_bit = 0; info->resume_bit = 0;
@ -4238,7 +4238,7 @@ static int fts_fb_state_chg_callback(struct notifier_block *nb,
if (info->aoi_wake_on_suspend) { if (info->aoi_wake_on_suspend) {
info->sensor_sleep = true; info->sensor_sleep = true;
__pm_stay_awake(&info->wakeup_source); __pm_stay_awake(info->wakeup_source);
} else { } else {
queue_work(info->event_wq, &info->suspend_work); queue_work(info->event_wq, &info->suspend_work);
} }
@ -4246,7 +4246,7 @@ static int fts_fb_state_chg_callback(struct notifier_block *nb,
case DRM_PANEL_BLANK_UNBLANK: case DRM_PANEL_BLANK_UNBLANK:
if (info->aoi_wake_on_suspend) if (info->aoi_wake_on_suspend)
__pm_relax(&info->wakeup_source); __pm_relax(info->wakeup_source);
if (!info->sensor_sleep) if (!info->sensor_sleep)
break; break;
@ -4710,7 +4710,8 @@ static int fts_probe_internal(struct i2c_client *client,
INIT_DELAYED_WORK(&info->fwu_work, fts_fw_update_auto); INIT_DELAYED_WORK(&info->fwu_work, fts_fw_update_auto);
logError(0, "%s SET Event Handler:\n", tag); logError(0, "%s SET Event Handler:\n", tag);
wakeup_source_init(&info->wakeup_source, "fts_tp"); info->wakeup_source = wakeup_source_register(&client->dev,
dev_name(&client->dev));
info->event_wq = alloc_workqueue("fts-event-queue", info->event_wq = alloc_workqueue("fts-event-queue",
WQ_UNBOUND|WQ_HIGHPRI|WQ_CPU_INTENSIVE, 1); WQ_UNBOUND|WQ_HIGHPRI|WQ_CPU_INTENSIVE, 1);
if (!info->event_wq) { if (!info->event_wq) {
@ -4963,7 +4964,7 @@ static int fts_probe_internal(struct i2c_client *client,
ProbeErrorExit_4: ProbeErrorExit_4:
destroy_workqueue(info->fwu_workqueue); destroy_workqueue(info->fwu_workqueue);
wakeup_source_trash(&info->wakeup_source); wakeup_source_unregister(info->wakeup_source);
ProbeErrorExit_3: ProbeErrorExit_3:
if (info->ts_pinctrl) { if (info->ts_pinctrl) {
@ -5056,7 +5057,7 @@ static int fts_remove(struct i2c_client *client)
/* Remove the work thread */ /* Remove the work thread */
destroy_workqueue(info->event_wq); destroy_workqueue(info->event_wq);
/* wake_lock_destroy(&info->wakelock); */ /* wake_lock_destroy(&info->wakelock); */
wakeup_source_trash(&info->wakeup_source); wakeup_source_unregister(info->wakeup_source);
destroy_workqueue(info->fwu_workqueue); destroy_workqueue(info->fwu_workqueue);
if (info->ts_pinctrl) { if (info->ts_pinctrl) {

View file

@ -295,7 +295,7 @@ struct fts_ts_info {
struct notifier_block notifier; struct notifier_block notifier;
bool sensor_sleep; bool sensor_sleep;
struct wakeup_source wakeup_source; struct wakeup_source *wakeup_source;
/* input lock */ /* input lock */
struct mutex input_report_mutex; struct mutex input_report_mutex;

View file

@ -57,6 +57,7 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/timekeeping.h>
//#include <linux/sec_sysfs.h> //#include <linux/sec_sysfs.h>
#include "ftsCrossCompile.h" #include "ftsCrossCompile.h"
@ -65,12 +66,12 @@
void startStopWatch(struct StopWatch *w) void startStopWatch(struct StopWatch *w)
{ {
w->start = current_kernel_time(); ktime_get_ts(&w->start);
} }
void stopStopWatch(struct StopWatch *w) void stopStopWatch(struct StopWatch *w)
{ {
w->end = current_kernel_time(); ktime_get_ts(&w->end);
} }
int elapsedMillisecond(struct StopWatch *w) int elapsedMillisecond(struct StopWatch *w)

View file

@ -78,7 +78,7 @@ struct fpc1020_data {
struct pinctrl *fingerprint_pinctrl; struct pinctrl *fingerprint_pinctrl;
struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)]; struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)];
struct regulator *vreg[ARRAY_SIZE(vreg_conf)]; struct regulator *vreg[ARRAY_SIZE(vreg_conf)];
struct wakeup_source ttw_wl; struct wakeup_source *ttw_wl;
struct mutex lock; /* To set/get exported values in sysfs */ struct mutex lock; /* To set/get exported values in sysfs */
int irq_gpio; int irq_gpio;
int rst_gpio; int rst_gpio;
@ -384,7 +384,7 @@ static ssize_t handle_wakelock_store(struct device *dev,
min(count, strlen(RELEASE_WAKELOCK_W_V)))) { min(count, strlen(RELEASE_WAKELOCK_W_V)))) {
if (fpc1020->nbr_irqs_received_counter_start == if (fpc1020->nbr_irqs_received_counter_start ==
fpc1020->nbr_irqs_received) { fpc1020->nbr_irqs_received) {
__pm_relax(&fpc1020->ttw_wl); __pm_relax(fpc1020->ttw_wl);
} else { } else {
dev_dbg(dev, "Ignore releasing of wakelock %d != %d", dev_dbg(dev, "Ignore releasing of wakelock %d != %d",
fpc1020->nbr_irqs_received_counter_start, fpc1020->nbr_irqs_received_counter_start,
@ -392,7 +392,7 @@ static ssize_t handle_wakelock_store(struct device *dev,
} }
} else if (!memcmp(buf, RELEASE_WAKELOCK, min(count, } else if (!memcmp(buf, RELEASE_WAKELOCK, min(count,
strlen(RELEASE_WAKELOCK)))) { strlen(RELEASE_WAKELOCK)))) {
__pm_relax(&fpc1020->ttw_wl); __pm_relax(fpc1020->ttw_wl);
} else if (!memcmp(buf, START_IRQS_RECEIVED_CNT, } else if (!memcmp(buf, START_IRQS_RECEIVED_CNT,
min(count, strlen(START_IRQS_RECEIVED_CNT)))) { min(count, strlen(START_IRQS_RECEIVED_CNT)))) {
fpc1020->nbr_irqs_received_counter_start = fpc1020->nbr_irqs_received_counter_start =
@ -443,7 +443,7 @@ static irqreturn_t fpc1020_irq_handler(int irq, void *handle)
mutex_lock(&fpc1020->lock); mutex_lock(&fpc1020->lock);
if (atomic_read(&fpc1020->wakeup_enabled)) { if (atomic_read(&fpc1020->wakeup_enabled)) {
fpc1020->nbr_irqs_received++; fpc1020->nbr_irqs_received++;
__pm_wakeup_event(&fpc1020->ttw_wl, __pm_wakeup_event(fpc1020->ttw_wl,
msecs_to_jiffies(FPC_TTW_HOLD_TIME)); msecs_to_jiffies(FPC_TTW_HOLD_TIME));
} }
mutex_unlock(&fpc1020->lock); mutex_unlock(&fpc1020->lock);
@ -546,7 +546,9 @@ static int fpc1020_probe(struct platform_device *pdev)
enable_irq_wake(gpio_to_irq(fpc1020->irq_gpio)); enable_irq_wake(gpio_to_irq(fpc1020->irq_gpio));
wakeup_source_init(&fpc1020->ttw_wl, "fpc_ttw_wl"); fpc1020->ttw_wl = wakeup_source_register(dev, "fpc_ttw_wl");
if (!fpc1020->ttw_wl)
return -ENOMEM;
rc = sysfs_create_group(&dev->kobj, &attribute_group); rc = sysfs_create_group(&dev->kobj, &attribute_group);
if (rc) { if (rc) {
@ -570,7 +572,7 @@ static int fpc1020_remove(struct platform_device *pdev)
sysfs_remove_group(&pdev->dev.kobj, &attribute_group); sysfs_remove_group(&pdev->dev.kobj, &attribute_group);
mutex_destroy(&fpc1020->lock); mutex_destroy(&fpc1020->lock);
wakeup_source_trash(&fpc1020->ttw_wl); wakeup_source_unregister(fpc1020->ttw_wl);
vreg_setup(fpc1020, "vdd_ana", false); vreg_setup(fpc1020, "vdd_ana", false);
vreg_setup(fpc1020, "vdd_io", false); vreg_setup(fpc1020, "vdd_io", false);
vreg_setup(fpc1020, "vcc_spi", false); vreg_setup(fpc1020, "vcc_spi", false);

View file

@ -682,7 +682,7 @@ struct msm_pcie_dev_t {
bool disable_pc; bool disable_pc;
struct pci_saved_state *saved_state; struct pci_saved_state *saved_state;
struct wakeup_source ws; struct wakeup_source *ws;
struct msm_bus_scale_pdata *bus_scale_table; struct msm_bus_scale_pdata *bus_scale_table;
uint32_t bus_client; uint32_t bus_client;
@ -4991,8 +4991,8 @@ static irqreturn_t handle_wake_irq(int irq, void *data)
schedule_work(&dev->handle_wake_work); schedule_work(&dev->handle_wake_work);
} else { } else {
PCIE_DBG2(dev, "Wake up RC%d\n", dev->rc_idx); PCIE_DBG2(dev, "Wake up RC%d\n", dev->rc_idx);
__pm_stay_awake(&dev->ws); __pm_stay_awake(dev->ws);
__pm_relax(&dev->ws); __pm_relax(dev->ws);
if (dev->num_ep > 1) { if (dev->num_ep > 1) {
for (i = 0; i < MAX_DEVICE_NUM; i++) { for (i = 0; i < MAX_DEVICE_NUM; i++) {
@ -5129,10 +5129,13 @@ static int32_t msm_pcie_irq_init(struct msm_pcie_dev_t *dev)
PCIE_DBG(dev, "RC%d\n", dev->rc_idx); PCIE_DBG(dev, "RC%d\n", dev->rc_idx);
if (dev->rc_idx) dev->ws = wakeup_source_register(pdev, dev_name(pdev));
wakeup_source_init(&dev->ws, "RC1 pcie_wakeup_source"); if (!dev->ws) {
else PCIE_ERR(dev,
wakeup_source_init(&dev->ws, "RC0 pcie_wakeup_source"); "PCIe: RC%d: failed to register wakeup source\n",
dev->rc_idx);
return -ENOMEM;
}
if (dev->irq[MSM_PCIE_INT_GLOBAL_INT].num) { if (dev->irq[MSM_PCIE_INT_GLOBAL_INT].num) {
rc = devm_request_irq(pdev, rc = devm_request_irq(pdev,
@ -5180,7 +5183,7 @@ static void msm_pcie_irq_deinit(struct msm_pcie_dev_t *dev)
{ {
PCIE_DBG(dev, "RC%d\n", dev->rc_idx); PCIE_DBG(dev, "RC%d\n", dev->rc_idx);
wakeup_source_trash(&dev->ws); wakeup_source_unregister(dev->ws);
if (dev->wake_n) if (dev->wake_n)
disable_irq(dev->wake_n); disable_irq(dev->wake_n);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
/* /*
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/ */
#if !defined(_GSI_EMULATION_H_) #if !defined(_GSI_EMULATION_H_)
@ -10,7 +10,10 @@
# include "gsi.h" # include "gsi.h"
# include "gsi_reg.h" # include "gsi_reg.h"
#if defined(CONFIG_IPA_EMULATION)
# include "gsi_emulation_stubs.h" # include "gsi_emulation_stubs.h"
#endif
# define gsi_emu_readl(c) (readl(c)) # define gsi_emu_readl(c) (readl(c))
# define gsi_emu_writel(v, c) ({ __iowmb(); writel_relaxed((v), (c)); }) # define gsi_emu_writel(v, c) ({ __iowmb(); writel_relaxed((v), (c)); })

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2018, 2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/jiffies.h> #include <linux/jiffies.h>
@ -40,7 +40,7 @@ struct ipa_rm_it_private {
bool reschedule_work; bool reschedule_work;
bool work_in_progress; bool work_in_progress;
unsigned long jiffies; unsigned long jiffies;
struct wakeup_source w_lock; struct wakeup_source *w_lock;
char w_lock_name[MAX_WS_NAME]; char w_lock_name[MAX_WS_NAME];
}; };
@ -83,7 +83,7 @@ static void ipa_rm_inactivity_timer_func(struct work_struct *work)
} else { } else {
IPA_RM_DBG_LOW("calling release_resource on resource %d\n", IPA_RM_DBG_LOW("calling release_resource on resource %d\n",
me->resource_name); me->resource_name);
__pm_relax(&ipa_rm_it_handles[me->resource_name].w_lock); __pm_relax(ipa_rm_it_handles[me->resource_name].w_lock);
ipa_rm_release_resource(me->resource_name); ipa_rm_release_resource(me->resource_name);
ipa_rm_it_handles[me->resource_name].work_in_progress = false; ipa_rm_it_handles[me->resource_name].work_in_progress = false;
} }
@ -107,7 +107,6 @@ static void ipa_rm_inactivity_timer_func(struct work_struct *work)
int ipa_rm_inactivity_timer_init(enum ipa_rm_resource_name resource_name, int ipa_rm_inactivity_timer_init(enum ipa_rm_resource_name resource_name,
unsigned long msecs) unsigned long msecs)
{ {
struct wakeup_source *pwlock;
char *name; char *name;
IPA_RM_DBG_LOW("resource %d\n", resource_name); IPA_RM_DBG_LOW("resource %d\n", resource_name);
@ -129,10 +128,16 @@ int ipa_rm_inactivity_timer_init(enum ipa_rm_resource_name resource_name,
ipa_rm_it_handles[resource_name].resource_requested = false; ipa_rm_it_handles[resource_name].resource_requested = false;
ipa_rm_it_handles[resource_name].reschedule_work = false; ipa_rm_it_handles[resource_name].reschedule_work = false;
ipa_rm_it_handles[resource_name].work_in_progress = false; ipa_rm_it_handles[resource_name].work_in_progress = false;
pwlock = &(ipa_rm_it_handles[resource_name].w_lock);
name = ipa_rm_it_handles[resource_name].w_lock_name; name = ipa_rm_it_handles[resource_name].w_lock_name;
snprintf(name, MAX_WS_NAME, "IPA_RM%d\n", resource_name); snprintf(name, MAX_WS_NAME, "IPA_RM%d\n", resource_name);
wakeup_source_init(pwlock, name); ipa_rm_it_handles[resource_name].w_lock =
wakeup_source_register(NULL, name);
if (!ipa_rm_it_handles[resource_name].w_lock) {
IPA_RM_ERR("IPA wakeup source register failed %s\n",
name);
return -ENOMEM;
}
INIT_DELAYED_WORK(&ipa_rm_it_handles[resource_name].work, INIT_DELAYED_WORK(&ipa_rm_it_handles[resource_name].work,
ipa_rm_inactivity_timer_func); ipa_rm_inactivity_timer_func);
ipa_rm_it_handles[resource_name].initied = true; ipa_rm_it_handles[resource_name].initied = true;
@ -151,8 +156,6 @@ EXPORT_SYMBOL(ipa_rm_inactivity_timer_init);
*/ */
int ipa_rm_inactivity_timer_destroy(enum ipa_rm_resource_name resource_name) int ipa_rm_inactivity_timer_destroy(enum ipa_rm_resource_name resource_name)
{ {
struct wakeup_source *pwlock;
IPA_RM_DBG_LOW("resource %d\n", resource_name); IPA_RM_DBG_LOW("resource %d\n", resource_name);
if (resource_name < 0 || if (resource_name < 0 ||
@ -168,8 +171,7 @@ int ipa_rm_inactivity_timer_destroy(enum ipa_rm_resource_name resource_name)
} }
cancel_delayed_work_sync(&ipa_rm_it_handles[resource_name].work); cancel_delayed_work_sync(&ipa_rm_it_handles[resource_name].work);
pwlock = &(ipa_rm_it_handles[resource_name].w_lock); wakeup_source_unregister(ipa_rm_it_handles[resource_name].w_lock);
wakeup_source_trash(pwlock);
memset(&ipa_rm_it_handles[resource_name], 0, memset(&ipa_rm_it_handles[resource_name], 0,
sizeof(struct ipa_rm_it_private)); sizeof(struct ipa_rm_it_private));
@ -264,7 +266,7 @@ int ipa_rm_inactivity_timer_release_resource(
} }
ipa_rm_it_handles[resource_name].work_in_progress = true; ipa_rm_it_handles[resource_name].work_in_progress = true;
ipa_rm_it_handles[resource_name].reschedule_work = false; ipa_rm_it_handles[resource_name].reschedule_work = false;
__pm_stay_awake(&ipa_rm_it_handles[resource_name].w_lock); __pm_stay_awake(ipa_rm_it_handles[resource_name].w_lock);
IPA_RM_DBG_LOW("setting delayed work\n"); IPA_RM_DBG_LOW("setting delayed work\n");
queue_delayed_work(system_unbound_wq, queue_delayed_work(system_unbound_wq,
&ipa_rm_it_handles[resource_name].work, &ipa_rm_it_handles[resource_name].work,

View file

@ -5209,7 +5209,7 @@ void ipa3_inc_acquire_wakelock(void)
spin_lock_irqsave(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags); spin_lock_irqsave(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags);
ipa3_ctx->wakelock_ref_cnt.cnt++; ipa3_ctx->wakelock_ref_cnt.cnt++;
if (ipa3_ctx->wakelock_ref_cnt.cnt == 1) if (ipa3_ctx->wakelock_ref_cnt.cnt == 1)
__pm_stay_awake(&ipa3_ctx->w_lock); __pm_stay_awake(ipa3_ctx->w_lock);
IPADBG_LOW("active wakelock ref cnt = %d\n", IPADBG_LOW("active wakelock ref cnt = %d\n",
ipa3_ctx->wakelock_ref_cnt.cnt); ipa3_ctx->wakelock_ref_cnt.cnt);
spin_unlock_irqrestore(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags); spin_unlock_irqrestore(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags);
@ -5232,7 +5232,7 @@ void ipa3_dec_release_wakelock(void)
IPADBG_LOW("active wakelock ref cnt = %d\n", IPADBG_LOW("active wakelock ref cnt = %d\n",
ipa3_ctx->wakelock_ref_cnt.cnt); ipa3_ctx->wakelock_ref_cnt.cnt);
if (ipa3_ctx->wakelock_ref_cnt.cnt == 0) if (ipa3_ctx->wakelock_ref_cnt.cnt == 0)
__pm_relax(&ipa3_ctx->w_lock); __pm_relax(ipa3_ctx->w_lock);
spin_unlock_irqrestore(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags); spin_unlock_irqrestore(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags);
} }
@ -6943,8 +6943,14 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
goto fail_device_create; goto fail_device_create;
} }
/* Create a wakeup source. */ /* Register a wakeup source. */
wakeup_source_init(&ipa3_ctx->w_lock, "IPA_WS"); ipa3_ctx->w_lock =
wakeup_source_register(&ipa_pdev->dev, "IPA_WS");
if (!ipa3_ctx->w_lock) {
IPAERR("IPA wakeup source register failed\n");
result = -ENOMEM;
goto fail_w_source_register;
}
spin_lock_init(&ipa3_ctx->wakelock_ref_cnt.spinlock); spin_lock_init(&ipa3_ctx->wakelock_ref_cnt.spinlock);
/* Initialize Power Management framework */ /* Initialize Power Management framework */
@ -7037,6 +7043,9 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
fail_ipa_dma_setup: fail_ipa_dma_setup:
ipa_pm_destroy(); ipa_pm_destroy();
fail_ipa_pm_init: fail_ipa_pm_init:
wakeup_source_unregister(ipa3_ctx->w_lock);
ipa3_ctx->w_lock = NULL;
fail_w_source_register:
device_destroy(ipa3_ctx->cdev.class, ipa3_ctx->cdev.dev_num); device_destroy(ipa3_ctx->cdev.class, ipa3_ctx->cdev.dev_num);
fail_device_create: fail_device_create:
unregister_chrdev_region(ipa3_ctx->cdev.dev_num, 1); unregister_chrdev_region(ipa3_ctx->cdev.dev_num, 1);

View file

@ -1986,7 +1986,7 @@ struct ipa3_context {
bool gsi_ch20_wa; bool gsi_ch20_wa;
bool s1_bypass_arr[IPA_SMMU_CB_MAX]; bool s1_bypass_arr[IPA_SMMU_CB_MAX];
u32 wdi_map_cnt; u32 wdi_map_cnt;
struct wakeup_source w_lock; struct wakeup_source *w_lock;
struct ipa3_wakelock_ref_cnt wakelock_ref_cnt; struct ipa3_wakelock_ref_cnt wakelock_ref_cnt;
/* RMNET_IOCTL_INGRESS_FORMAT_AGG_DATA */ /* RMNET_IOCTL_INGRESS_FORMAT_AGG_DATA */
bool ipa_client_apps_wan_cons_agg_gro; bool ipa_client_apps_wan_cons_agg_gro;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/debugfs.h> #include <linux/debugfs.h>
@ -149,7 +149,7 @@ struct ipa_pm_client {
struct work_struct activate_work; struct work_struct activate_work;
struct delayed_work deactivate_work; struct delayed_work deactivate_work;
struct completion complete; struct completion complete;
struct wakeup_source wlock; struct wakeup_source *wlock;
}; };
/* /*
@ -399,7 +399,7 @@ static void activate_work_func(struct work_struct *work)
if (!client->skip_clk_vote) { if (!client->skip_clk_vote) {
IPA_ACTIVE_CLIENTS_INC_SPECIAL(client->name); IPA_ACTIVE_CLIENTS_INC_SPECIAL(client->name);
if (client->group == IPA_PM_GROUP_APPS) if (client->group == IPA_PM_GROUP_APPS)
__pm_stay_awake(&client->wlock); __pm_stay_awake(client->wlock);
} }
spin_lock_irqsave(&client->state_lock, flags); spin_lock_irqsave(&client->state_lock, flags);
@ -421,7 +421,7 @@ static void activate_work_func(struct work_struct *work)
if (!client->skip_clk_vote) { if (!client->skip_clk_vote) {
IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name); IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name);
if (client->group == IPA_PM_GROUP_APPS) if (client->group == IPA_PM_GROUP_APPS)
__pm_relax(&client->wlock); __pm_relax(client->wlock);
} }
IPA_PM_DBG_STATE(client->hdl, client->name, client->state); IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
@ -480,7 +480,7 @@ static void delayed_deferred_deactivate_work_func(struct work_struct *work)
if (!client->skip_clk_vote) { if (!client->skip_clk_vote) {
IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name); IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name);
if (client->group == IPA_PM_GROUP_APPS) if (client->group == IPA_PM_GROUP_APPS)
__pm_relax(&client->wlock); __pm_relax(client->wlock);
} }
deactivate_client(client->hdl); deactivate_client(client->hdl);
@ -704,7 +704,6 @@ int ipa_pm_destroy(void)
int ipa_pm_register(struct ipa_pm_register_params *params, u32 *hdl) int ipa_pm_register(struct ipa_pm_register_params *params, u32 *hdl)
{ {
struct ipa_pm_client *client; struct ipa_pm_client *client;
struct wakeup_source *wlock;
int elem; int elem;
if (ipa_pm_ctx == NULL) { if (ipa_pm_ctx == NULL) {
@ -755,9 +754,13 @@ int ipa_pm_register(struct ipa_pm_register_params *params, u32 *hdl)
client->group = params->group; client->group = params->group;
client->hdl = *hdl; client->hdl = *hdl;
client->skip_clk_vote = params->skip_clk_vote; client->skip_clk_vote = params->skip_clk_vote;
wlock = &client->wlock; client->wlock = wakeup_source_register(NULL, client->name);
wakeup_source_init(wlock, client->name); if (!client->wlock) {
ipa_pm_deregister(*hdl);
IPA_PM_ERR("IPA wakeup source register failed %s\n",
client->name);
return -ENOMEM;
}
init_completion(&client->complete); init_completion(&client->complete);
/* add client to exception list */ /* add client to exception list */
@ -822,7 +825,7 @@ int ipa_pm_deregister(u32 hdl)
if (ipa_pm_ctx->clients_by_pipe[i] == ipa_pm_ctx->clients[hdl]) if (ipa_pm_ctx->clients_by_pipe[i] == ipa_pm_ctx->clients[hdl])
ipa_pm_ctx->clients_by_pipe[i] = NULL; ipa_pm_ctx->clients_by_pipe[i] = NULL;
} }
wakeup_source_trash(&client->wlock); wakeup_source_unregister(client->wlock);
kfree(client); kfree(client);
ipa_pm_ctx->clients[hdl] = NULL; ipa_pm_ctx->clients[hdl] = NULL;
@ -941,7 +944,7 @@ static int ipa_pm_activate_helper(struct ipa_pm_client *client, bool sync)
if (result == 0) { if (result == 0) {
client->state = IPA_PM_ACTIVATED; client->state = IPA_PM_ACTIVATED;
if (client->group == IPA_PM_GROUP_APPS) if (client->group == IPA_PM_GROUP_APPS)
__pm_stay_awake(&client->wlock); __pm_stay_awake(client->wlock);
spin_unlock_irqrestore(&client->state_lock, flags); spin_unlock_irqrestore(&client->state_lock, flags);
activate_client(client->hdl); activate_client(client->hdl);
if (sync) if (sync)
@ -1121,7 +1124,7 @@ int ipa_pm_deactivate_all_deferred(void)
if (!client->skip_clk_vote) { if (!client->skip_clk_vote) {
IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name); IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name);
if (client->group == IPA_PM_GROUP_APPS) if (client->group == IPA_PM_GROUP_APPS)
__pm_relax(&client->wlock); __pm_relax(client->wlock);
} }
deactivate_client(client->hdl); deactivate_client(client->hdl);
} else /* if activated or deactivated, we do nothing */ } else /* if activated or deactivated, we do nothing */
@ -1176,7 +1179,7 @@ int ipa_pm_deactivate_sync(u32 hdl)
if (!client->skip_clk_vote) { if (!client->skip_clk_vote) {
IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name); IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name);
if (client->group == IPA_PM_GROUP_APPS) if (client->group == IPA_PM_GROUP_APPS)
__pm_relax(&client->wlock); __pm_relax(client->wlock);
} }
spin_lock_irqsave(&client->state_lock, flags); spin_lock_irqsave(&client->state_lock, flags);

View file

@ -1998,7 +1998,7 @@ int qcom_batt_init(struct charger_param *chg_param)
pl_config_init(chip, chg_param->smb_version); pl_config_init(chip, chg_param->smb_version);
chip->restricted_current = DEFAULT_RESTRICTED_CURRENT_UA; chip->restricted_current = DEFAULT_RESTRICTED_CURRENT_UA;
chip->pl_ws = wakeup_source_register("qcom-battery"); chip->pl_ws = wakeup_source_register(NULL, "qcom-battery");
if (!chip->pl_ws) if (!chip->pl_ws)
goto cleanup; goto cleanup;

View file

@ -1885,7 +1885,7 @@ static int smb1390_master_probe(struct smb1390 *chip)
return rc; return rc;
} }
chip->cp_ws = wakeup_source_register("qcom-chargepump"); chip->cp_ws = wakeup_source_register(NULL, "qcom-chargepump");
if (!chip->cp_ws) if (!chip->cp_ws)
return -ENOMEM; return -ENOMEM;

View file

@ -843,7 +843,7 @@ int qcom_step_chg_init(struct device *dev,
if (!chip) if (!chip)
return -ENOMEM; return -ENOMEM;
chip->step_chg_ws = wakeup_source_register("qcom-step-chg"); chip->step_chg_ws = wakeup_source_register(dev, "qcom-step-chg");
if (!chip->step_chg_ws) if (!chip->step_chg_ws)
return -EINVAL; return -EINVAL;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2010-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2010-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/module.h> #include <linux/module.h>
@ -134,7 +134,7 @@ struct pil_seg {
*/ */
struct pil_priv { struct pil_priv {
struct delayed_work proxy; struct delayed_work proxy;
struct wakeup_source ws; struct wakeup_source *ws;
char wname[32]; char wname[32];
struct pil_desc *desc; struct pil_desc *desc;
int num_segs; int num_segs;
@ -581,7 +581,7 @@ static void __pil_proxy_unvote(struct pil_priv *priv)
desc->ops->proxy_unvote(desc); desc->ops->proxy_unvote(desc);
notify_proxy_unvote(desc->dev); notify_proxy_unvote(desc->dev);
__pm_relax(&priv->ws); __pm_relax(priv->ws);
module_put(desc->owner); module_put(desc->owner);
} }
@ -600,10 +600,10 @@ static int pil_proxy_vote(struct pil_desc *desc)
struct pil_priv *priv = desc->priv; struct pil_priv *priv = desc->priv;
if (desc->ops->proxy_vote) { if (desc->ops->proxy_vote) {
__pm_stay_awake(&priv->ws); __pm_stay_awake(priv->ws);
ret = desc->ops->proxy_vote(desc); ret = desc->ops->proxy_vote(desc);
if (ret) if (ret)
__pm_relax(&priv->ws); __pm_relax(priv->ws);
} }
if (desc->proxy_unvote_irq) if (desc->proxy_unvote_irq)
@ -1561,7 +1561,13 @@ int pil_desc_init(struct pil_desc *desc)
} }
snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name); snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
wakeup_source_init(&priv->ws, priv->wname);
priv->ws = wakeup_source_register(desc->dev, priv->wname);
if (!priv->ws) {
ret = -ENOMEM;
goto err;
}
INIT_DELAYED_WORK(&priv->proxy, pil_proxy_unvote_work); INIT_DELAYED_WORK(&priv->proxy, pil_proxy_unvote_work);
INIT_LIST_HEAD(&priv->segs); INIT_LIST_HEAD(&priv->segs);
@ -1597,7 +1603,7 @@ void pil_desc_release(struct pil_desc *desc)
if (priv) { if (priv) {
ida_simple_remove(&pil_ida, priv->id); ida_simple_remove(&pil_ida, priv->id);
flush_delayed_work(&priv->proxy); flush_delayed_work(&priv->proxy);
wakeup_source_trash(&priv->ws); wakeup_source_unregister(priv->ws);
} }
desc->priv = NULL; desc->priv = NULL;
kfree(priv); kfree(priv);

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2015, Sony Mobile Communications AB. * Copyright (c) 2015, Sony Mobile Communications AB.
* Copyright (c) 2012-2013, 2018-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2012-2013, 2018-2020 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -161,7 +161,7 @@ struct qcom_smp2p {
struct regmap *ipc_regmap; struct regmap *ipc_regmap;
int ipc_offset; int ipc_offset;
int ipc_bit; int ipc_bit;
struct wakeup_source ws; struct wakeup_source *ws;
struct mbox_client mbox_client; struct mbox_client mbox_client;
struct mbox_chan *mbox_chan; struct mbox_chan *mbox_chan;
@ -303,7 +303,7 @@ static irqreturn_t qcom_smp2p_isr(int irq, void *data)
{ {
struct qcom_smp2p *smp2p = data; struct qcom_smp2p *smp2p = data;
__pm_stay_awake(&smp2p->ws); __pm_stay_awake(smp2p->ws);
return IRQ_WAKE_THREAD; return IRQ_WAKE_THREAD;
} }
@ -351,7 +351,7 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data)
} }
out: out:
__pm_relax(&smp2p->ws); __pm_relax(smp2p->ws);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -648,7 +648,12 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
list_add(&entry->node, &smp2p->outbound); list_add(&entry->node, &smp2p->outbound);
} }
} }
wakeup_source_init(&smp2p->ws, "smp2p");
smp2p->ws = wakeup_source_register(&pdev->dev, "smp2p");
if (!smp2p->ws) {
ret = -ENOMEM;
goto unwind_interfaces;
}
/* Kick the outgoing edge after allocating entries */ /* Kick the outgoing edge after allocating entries */
qcom_smp2p_kick(smp2p); qcom_smp2p_kick(smp2p);
@ -659,12 +664,15 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
"smp2p", (void *)smp2p); "smp2p", (void *)smp2p);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to request interrupt\n"); dev_err(&pdev->dev, "failed to request interrupt\n");
goto unwind_interfaces; goto unreg_ws;
} }
enable_irq_wake(smp2p->irq); enable_irq_wake(smp2p->irq);
return 0; return 0;
unreg_ws:
wakeup_source_unregister(smp2p->ws);
unwind_interfaces: unwind_interfaces:
list_for_each_entry(entry, &smp2p->inbound, node) list_for_each_entry(entry, &smp2p->inbound, node)
irq_domain_remove(entry->domain); irq_domain_remove(entry->domain);
@ -689,6 +697,8 @@ static int qcom_smp2p_remove(struct platform_device *pdev)
struct qcom_smp2p *smp2p = platform_get_drvdata(pdev); struct qcom_smp2p *smp2p = platform_get_drvdata(pdev);
struct smp2p_entry *entry; struct smp2p_entry *entry;
wakeup_source_unregister(smp2p->ws);
list_for_each_entry(entry, &smp2p->inbound, node) list_for_each_entry(entry, &smp2p->inbound, node)
irq_domain_remove(entry->domain); irq_domain_remove(entry->domain);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/suspend.h> #include <linux/suspend.h>
@ -15,7 +15,7 @@
#define PROC_AWAKE_ID 12 /* 12th bit */ #define PROC_AWAKE_ID 12 /* 12th bit */
#define AWAKE_BIT BIT(PROC_AWAKE_ID) #define AWAKE_BIT BIT(PROC_AWAKE_ID)
static struct qcom_smem_state *state; static struct qcom_smem_state *state;
static struct wakeup_source notify_ws; static struct wakeup_source *notify_ws;
/** /**
* sleepstate_pm_notifier() - PM notifier callback function. * sleepstate_pm_notifier() - PM notifier callback function.
@ -49,7 +49,7 @@ static struct notifier_block sleepstate_pm_nb = {
static irqreturn_t smp2p_sleepstate_handler(int irq, void *ctxt) static irqreturn_t smp2p_sleepstate_handler(int irq, void *ctxt)
{ {
__pm_wakeup_event(&notify_ws, 200); __pm_wakeup_event(notify_ws, 200);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -70,7 +70,12 @@ static int smp2p_sleepstate_probe(struct platform_device *pdev)
dev_err(dev, "%s: power state notif error %d\n", __func__, ret); dev_err(dev, "%s: power state notif error %d\n", __func__, ret);
return ret; return ret;
} }
wakeup_source_init(&notify_ws, "smp2p-sleepstate");
notify_ws = wakeup_source_register(&pdev->dev, "smp2p-sleepstate");
if (!notify_ws) {
return -ENOMEM;
goto err_ws;
}
irq = of_irq_get_byname(node, "smp2p-sleepstate-in"); irq = of_irq_get_byname(node, "smp2p-sleepstate-in");
if (irq <= 0) { if (irq <= 0) {
@ -89,7 +94,8 @@ static int smp2p_sleepstate_probe(struct platform_device *pdev)
} }
return 0; return 0;
err: err:
wakeup_source_trash(&notify_ws); wakeup_source_unregister(notify_ws);
err_ws:
unregister_pm_notifier(&sleepstate_pm_nb); unregister_pm_notifier(&sleepstate_pm_nb);
return ret; return ret;
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2011-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved.
*/ */
#define pr_fmt(fmt) "subsys-restart: %s(): " fmt, __func__ #define pr_fmt(fmt) "subsys-restart: %s(): " fmt, __func__
@ -181,7 +181,7 @@ struct restart_log {
struct subsys_device { struct subsys_device {
struct subsys_desc *desc; struct subsys_desc *desc;
struct work_struct work; struct work_struct work;
struct wakeup_source ssr_wlock; struct wakeup_source *ssr_wlock;
char wlname[64]; char wlname[64];
struct work_struct device_restart_work; struct work_struct device_restart_work;
struct subsys_tracking track; struct subsys_tracking track;
@ -1159,7 +1159,7 @@ static void subsystem_restart_wq_func(struct work_struct *work)
spin_lock_irqsave(&track->s_lock, flags); spin_lock_irqsave(&track->s_lock, flags);
track->p_state = SUBSYS_NORMAL; track->p_state = SUBSYS_NORMAL;
__pm_relax(&dev->ssr_wlock); __pm_relax(dev->ssr_wlock);
spin_unlock_irqrestore(&track->s_lock, flags); spin_unlock_irqrestore(&track->s_lock, flags);
} }
@ -1183,7 +1183,7 @@ static void __subsystem_restart_dev(struct subsys_device *dev)
dev->track.state == SUBSYS_ONLINE) { dev->track.state == SUBSYS_ONLINE) {
if (track->p_state != SUBSYS_RESTARTING) { if (track->p_state != SUBSYS_RESTARTING) {
track->p_state = SUBSYS_CRASHED; track->p_state = SUBSYS_CRASHED;
__pm_stay_awake(&dev->ssr_wlock); __pm_stay_awake(dev->ssr_wlock);
queue_work(ssr_wq, &dev->work); queue_work(ssr_wq, &dev->work);
} else { } else {
panic("Subsystem %s crashed during SSR!", name); panic("Subsystem %s crashed during SSR!", name);
@ -1251,7 +1251,7 @@ int subsystem_restart_dev(struct subsys_device *dev)
__subsystem_restart_dev(dev); __subsystem_restart_dev(dev);
break; break;
case RESET_SOC: case RESET_SOC:
__pm_stay_awake(&dev->ssr_wlock); __pm_stay_awake(dev->ssr_wlock);
schedule_work(&dev->device_restart_work); schedule_work(&dev->device_restart_work);
return 0; return 0;
default: default:
@ -1415,7 +1415,7 @@ static void subsys_device_release(struct device *dev)
{ {
struct subsys_device *subsys = to_subsys(dev); struct subsys_device *subsys = to_subsys(dev);
wakeup_source_trash(&subsys->ssr_wlock); wakeup_source_unregister(subsys->ssr_wlock);
mutex_destroy(&subsys->track.lock); mutex_destroy(&subsys->track.lock);
ida_simple_remove(&subsys_ida, subsys->id); ida_simple_remove(&subsys_ida, subsys->id);
kfree(subsys); kfree(subsys);
@ -1830,7 +1830,14 @@ struct subsys_device *subsys_register(struct subsys_desc *desc)
subsys->early_notify = subsys_get_early_notif_info(desc->name); subsys->early_notify = subsys_get_early_notif_info(desc->name);
snprintf(subsys->wlname, sizeof(subsys->wlname), "ssr(%s)", desc->name); snprintf(subsys->wlname, sizeof(subsys->wlname), "ssr(%s)", desc->name);
wakeup_source_init(&subsys->ssr_wlock, subsys->wlname);
subsys->ssr_wlock =
wakeup_source_register(&subsys->dev, subsys->wlname);
if (!subsys->ssr_wlock) {
kfree(subsys);
return ERR_PTR(-ENOMEM);
}
INIT_WORK(&subsys->work, subsystem_restart_wq_func); INIT_WORK(&subsys->work, subsystem_restart_wq_func);
INIT_WORK(&subsys->device_restart_work, device_restart_work_hdlr); INIT_WORK(&subsys->device_restart_work, device_restart_work_hdlr);
spin_lock_init(&subsys->track.s_lock); spin_lock_init(&subsys->track.s_lock);
@ -1838,7 +1845,7 @@ struct subsys_device *subsys_register(struct subsys_desc *desc)
subsys->id = ida_simple_get(&subsys_ida, 0, 0, GFP_KERNEL); subsys->id = ida_simple_get(&subsys_ida, 0, 0, GFP_KERNEL);
if (subsys->id < 0) { if (subsys->id < 0) {
wakeup_source_trash(&subsys->ssr_wlock); wakeup_source_unregister(subsys->ssr_wlock);
ret = subsys->id; ret = subsys->id;
kfree(subsys); kfree(subsys);
return ERR_PTR(ret); return ERR_PTR(ret);

View file

@ -182,7 +182,7 @@ struct msm_geni_serial_port {
int loopback; int loopback;
int wakeup_irq; int wakeup_irq;
unsigned char wakeup_byte; unsigned char wakeup_byte;
struct wakeup_source geni_wake; struct wakeup_source *geni_wake;
void *ipc_log_tx; void *ipc_log_tx;
void *ipc_log_rx; void *ipc_log_rx;
void *ipc_log_pwr; void *ipc_log_pwr;
@ -1955,7 +1955,7 @@ static irqreturn_t msm_geni_wakeup_isr(int isr, void *dev)
__func__, port->wakeup_byte); __func__, port->wakeup_byte);
port->edge_count = 0; port->edge_count = 0;
tty_flip_buffer_push(tty->port); tty_flip_buffer_push(tty->port);
__pm_wakeup_event(&port->geni_wake, WAKEBYTE_TIMEOUT_MSEC); __pm_wakeup_event(port->geni_wake, WAKEBYTE_TIMEOUT_MSEC);
} else if (port->edge_count < 2) { } else if (port->edge_count < 2) {
port->edge_count++; port->edge_count++;
} }
@ -3145,7 +3145,17 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
} }
} }
wakeup_source_init(&dev_port->geni_wake, dev_name(&pdev->dev)); if (!is_console) {
dev_port->geni_wake = wakeup_source_register(uport->dev,
dev_name(&pdev->dev));
if (!dev_port->geni_wake) {
dev_err(&pdev->dev,
"Failed to register wakeup_source\n");
ret = -ENOMEM;
goto exit_geni_serial_probe;
}
}
dev_port->tx_fifo_depth = DEF_FIFO_DEPTH_WORDS; dev_port->tx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
dev_port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS; dev_port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
dev_port->tx_fifo_width = DEF_FIFO_WIDTH_BITS; dev_port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
@ -3159,7 +3169,7 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
if (uport->irq < 0) { if (uport->irq < 0) {
ret = uport->irq; ret = uport->irq;
dev_err(&pdev->dev, "Failed to get IRQ %d\n", ret); dev_err(&pdev->dev, "Failed to get IRQ %d\n", ret);
goto exit_geni_serial_probe; goto exit_wakeup_unregister;
} }
dev_port->name = devm_kasprintf(uport->dev, GFP_KERNEL, dev_port->name = devm_kasprintf(uport->dev, GFP_KERNEL,
@ -3170,7 +3180,7 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(uport->dev, "%s: Failed to get IRQ ret %d\n", dev_err(uport->dev, "%s: Failed to get IRQ ret %d\n",
__func__, ret); __func__, ret);
goto exit_geni_serial_probe; goto exit_wakeup_unregister;
} }
uport->private_data = (void *)drv; uport->private_data = (void *)drv;
@ -3203,10 +3213,20 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
dev_port->port_setup = false; dev_port->port_setup = false;
ret = msm_geni_serial_get_ver_info(uport); ret = msm_geni_serial_get_ver_info(uport);
if (ret) if (ret)
goto exit_geni_serial_probe; goto exit_wakeup_unregister;
ret = uart_add_one_port(drv, uport); ret = uart_add_one_port(drv, uport);
if (ret)
goto exit_wakeup_unregister;
IPC_LOG_MSG(dev_port->ipc_log_misc, "%s: port:%s irq:%d\n", __func__,
uport->name, uport->irq);
return 0;
exit_wakeup_unregister:
if (!is_console)
wakeup_source_unregister(dev_port->geni_wake);
exit_geni_serial_probe: exit_geni_serial_probe:
IPC_LOG_MSG(dev_port->ipc_log_misc, "%s: ret:%d\n", __func__, ret); IPC_LOG_MSG(dev_port->ipc_log_misc, "%s: ret:%d\n", __func__, ret);
return ret; return ret;
@ -3218,7 +3238,8 @@ static int msm_geni_serial_remove(struct platform_device *pdev)
struct uart_driver *drv = struct uart_driver *drv =
(struct uart_driver *)port->uport.private_data; (struct uart_driver *)port->uport.private_data;
wakeup_source_trash(&port->geni_wake); if (!uart_console(&port->uport))
wakeup_source_unregister(port->geni_wake);
uart_remove_one_port(drv, &port->uport); uart_remove_one_port(drv, &port->uport);
if (port->rx_dma) { if (port->rx_dma) {
geni_se_iommu_free_buf(port->wrapper_dev, &port->rx_dma, geni_se_iommu_free_buf(port->wrapper_dev, &port->rx_dma,
@ -3263,7 +3284,7 @@ static int msm_geni_serial_runtime_suspend(struct device *dev)
enable_irq(port->wakeup_irq); enable_irq(port->wakeup_irq);
} }
IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__); IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__);
__pm_relax(&port->geni_wake); __pm_relax(port->geni_wake);
exit_runtime_suspend: exit_runtime_suspend:
return ret; return ret;
} }
@ -3278,8 +3299,8 @@ static int msm_geni_serial_runtime_resume(struct device *dev)
* Do an unconditional relax followed by a stay awake in case the * Do an unconditional relax followed by a stay awake in case the
* wake source is activated by the wakeup isr. * wake source is activated by the wakeup isr.
*/ */
__pm_relax(&port->geni_wake); __pm_relax(port->geni_wake);
__pm_stay_awake(&port->geni_wake); __pm_stay_awake(port->geni_wake);
if (port->wakeup_irq > 0) if (port->wakeup_irq > 0)
disable_irq(port->wakeup_irq); disable_irq(port->wakeup_irq);
/* /*
@ -3291,7 +3312,7 @@ static int msm_geni_serial_runtime_resume(struct device *dev)
ret = se_geni_resources_on(&port->serial_rsc); ret = se_geni_resources_on(&port->serial_rsc);
if (ret) { if (ret) {
dev_err(dev, "%s: Error ret %d\n", __func__, ret); dev_err(dev, "%s: Error ret %d\n", __func__, ret);
__pm_relax(&port->geni_wake); __pm_relax(port->geni_wake);
goto exit_runtime_resume; goto exit_runtime_resume;
} }
start_rx_sequencer(&port->uport); start_rx_sequencer(&port->uport);

View file

@ -1383,13 +1383,13 @@ static int ep_create_wakeup_source(struct epitem *epi)
struct wakeup_source *ws; struct wakeup_source *ws;
if (!epi->ep->ws) { if (!epi->ep->ws) {
epi->ep->ws = wakeup_source_register("eventpoll"); epi->ep->ws = wakeup_source_register(NULL, "eventpoll");
if (!epi->ep->ws) if (!epi->ep->ws)
return -ENOMEM; return -ENOMEM;
} }
name = epi->ffd.file->f_path.dentry->d_name.name; name = epi->ffd.file->f_path.dentry->d_name.name;
ws = wakeup_source_register(name); ws = wakeup_source_register(NULL, name);
if (!ws) if (!ws)
return -ENOMEM; return -ENOMEM;

View file

@ -34,6 +34,7 @@ struct wake_irq;
* struct wakeup_source - Representation of wakeup sources * struct wakeup_source - Representation of wakeup sources
* *
* @name: Name of the wakeup source * @name: Name of the wakeup source
* @id: Wakeup source id
* @entry: Wakeup source list entry * @entry: Wakeup source list entry
* @lock: Wakeup source lock * @lock: Wakeup source lock
* @wakeirq: Optional device specific wakeirq * @wakeirq: Optional device specific wakeirq
@ -48,11 +49,13 @@ struct wake_irq;
* @relax_count: Number of times the wakeup source was deactivated. * @relax_count: Number of times the wakeup source was deactivated.
* @expire_count: Number of times the wakeup source's timeout has expired. * @expire_count: Number of times the wakeup source's timeout has expired.
* @wakeup_count: Number of times the wakeup source might abort suspend. * @wakeup_count: Number of times the wakeup source might abort suspend.
* @dev: Struct device for sysfs statistics about the wakeup source.
* @active: Status of the wakeup source. * @active: Status of the wakeup source.
* @has_timeout: The wakeup source has been activated with a timeout. * @has_timeout: The wakeup source has been activated with a timeout.
*/ */
struct wakeup_source { struct wakeup_source {
const char *name; const char *name;
int id;
struct list_head entry; struct list_head entry;
spinlock_t lock; spinlock_t lock;
struct wake_irq *wakeirq; struct wake_irq *wakeirq;
@ -68,10 +71,13 @@ struct wakeup_source {
unsigned long relax_count; unsigned long relax_count;
unsigned long expire_count; unsigned long expire_count;
unsigned long wakeup_count; unsigned long wakeup_count;
struct device *dev;
bool active:1; bool active:1;
bool autosleep_enabled:1; bool autosleep_enabled:1;
}; };
#define WAKEUP_SOURCE_DEV
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
/* /*
@ -94,13 +100,12 @@ static inline void device_set_wakeup_path(struct device *dev)
} }
/* drivers/base/power/wakeup.c */ /* drivers/base/power/wakeup.c */
extern void wakeup_source_prepare(struct wakeup_source *ws, const char *name);
extern struct wakeup_source *wakeup_source_create(const char *name); extern struct wakeup_source *wakeup_source_create(const char *name);
extern void wakeup_source_drop(struct wakeup_source *ws);
extern void wakeup_source_destroy(struct wakeup_source *ws); extern void wakeup_source_destroy(struct wakeup_source *ws);
extern void wakeup_source_add(struct wakeup_source *ws); extern void wakeup_source_add(struct wakeup_source *ws);
extern void wakeup_source_remove(struct wakeup_source *ws); extern void wakeup_source_remove(struct wakeup_source *ws);
extern struct wakeup_source *wakeup_source_register(const char *name); extern struct wakeup_source *wakeup_source_register(struct device *dev,
const char *name);
extern void wakeup_source_unregister(struct wakeup_source *ws); extern void wakeup_source_unregister(struct wakeup_source *ws);
extern int device_wakeup_enable(struct device *dev); extern int device_wakeup_enable(struct device *dev);
extern int device_wakeup_disable(struct device *dev); extern int device_wakeup_disable(struct device *dev);
@ -126,23 +131,19 @@ static inline bool device_can_wakeup(struct device *dev)
return dev->power.can_wakeup; return dev->power.can_wakeup;
} }
static inline void wakeup_source_prepare(struct wakeup_source *ws,
const char *name) {}
static inline struct wakeup_source *wakeup_source_create(const char *name) static inline struct wakeup_source *wakeup_source_create(const char *name)
{ {
return NULL; return NULL;
} }
static inline void wakeup_source_drop(struct wakeup_source *ws) {}
static inline void wakeup_source_destroy(struct wakeup_source *ws) {} static inline void wakeup_source_destroy(struct wakeup_source *ws) {}
static inline void wakeup_source_add(struct wakeup_source *ws) {} static inline void wakeup_source_add(struct wakeup_source *ws) {}
static inline void wakeup_source_remove(struct wakeup_source *ws) {} static inline void wakeup_source_remove(struct wakeup_source *ws) {}
static inline struct wakeup_source *wakeup_source_register(const char *name) static inline struct wakeup_source *wakeup_source_register(struct device *dev,
const char *name)
{ {
return NULL; return NULL;
} }
@ -197,19 +198,6 @@ static inline void pm_wakeup_dev_event(struct device *dev, unsigned int msec,
#endif /* !CONFIG_PM_SLEEP */ #endif /* !CONFIG_PM_SLEEP */
static inline void wakeup_source_init(struct wakeup_source *ws,
const char *name)
{
wakeup_source_prepare(ws, name);
wakeup_source_add(ws);
}
static inline void wakeup_source_trash(struct wakeup_source *ws)
{
wakeup_source_remove(ws);
wakeup_source_drop(ws);
}
static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
{ {
return pm_wakeup_ws_event(ws, msec, false); return pm_wakeup_ws_event(ws, msec, false);

View file

@ -116,7 +116,7 @@ int pm_autosleep_set_state(suspend_state_t state)
int __init pm_autosleep_init(void) int __init pm_autosleep_init(void)
{ {
autosleep_ws = wakeup_source_register("autosleep"); autosleep_ws = wakeup_source_register(NULL, "autosleep");
if (!autosleep_ws) if (!autosleep_ws)
return -ENOMEM; return -ENOMEM;

View file

@ -27,7 +27,7 @@ static DEFINE_MUTEX(wakelocks_lock);
struct wakelock { struct wakelock {
char *name; char *name;
struct rb_node node; struct rb_node node;
struct wakeup_source ws; struct wakeup_source *ws;
#ifdef CONFIG_PM_WAKELOCKS_GC #ifdef CONFIG_PM_WAKELOCKS_GC
struct list_head lru; struct list_head lru;
#endif #endif
@ -46,7 +46,7 @@ ssize_t pm_show_wakelocks(char *buf, bool show_active)
for (node = rb_first(&wakelocks_tree); node; node = rb_next(node)) { for (node = rb_first(&wakelocks_tree); node; node = rb_next(node)) {
wl = rb_entry(node, struct wakelock, node); wl = rb_entry(node, struct wakelock, node);
if (wl->ws.active == show_active) if (wl->ws->active == show_active)
str += scnprintf(str, end - str, "%s ", wl->name); str += scnprintf(str, end - str, "%s ", wl->name);
} }
if (str > buf) if (str > buf)
@ -112,16 +112,16 @@ static void __wakelocks_gc(struct work_struct *work)
u64 idle_time_ns; u64 idle_time_ns;
bool active; bool active;
spin_lock_irq(&wl->ws.lock); spin_lock_irq(&wl->ws->lock);
idle_time_ns = ktime_to_ns(ktime_sub(now, wl->ws.last_time)); idle_time_ns = ktime_to_ns(ktime_sub(now, wl->ws->last_time));
active = wl->ws.active; active = wl->ws->active;
spin_unlock_irq(&wl->ws.lock); spin_unlock_irq(&wl->ws->lock);
if (idle_time_ns < ((u64)WL_GC_TIME_SEC * NSEC_PER_SEC)) if (idle_time_ns < ((u64)WL_GC_TIME_SEC * NSEC_PER_SEC))
break; break;
if (!active) { if (!active) {
wakeup_source_remove(&wl->ws); wakeup_source_unregister(wl->ws);
rb_erase(&wl->node, &wakelocks_tree); rb_erase(&wl->node, &wakelocks_tree);
list_del(&wl->lru); list_del(&wl->lru);
kfree(wl->name); kfree(wl->name);
@ -187,9 +187,15 @@ static struct wakelock *wakelock_lookup_add(const char *name, size_t len,
kfree(wl); kfree(wl);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
wl->ws.name = wl->name;
wl->ws.last_time = ktime_get(); wl->ws = wakeup_source_register(NULL, wl->name);
wakeup_source_add(&wl->ws); if (!wl->ws) {
kfree(wl->name);
kfree(wl);
return ERR_PTR(-ENOMEM);
}
wl->ws->last_time = ktime_get();
rb_link_node(&wl->node, parent, node); rb_link_node(&wl->node, parent, node);
rb_insert_color(&wl->node, &wakelocks_tree); rb_insert_color(&wl->node, &wakelocks_tree);
wakelocks_lru_add(wl); wakelocks_lru_add(wl);
@ -233,9 +239,9 @@ int pm_wake_lock(const char *buf)
u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1; u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1;
do_div(timeout_ms, NSEC_PER_MSEC); do_div(timeout_ms, NSEC_PER_MSEC);
__pm_wakeup_event(&wl->ws, timeout_ms); __pm_wakeup_event(wl->ws, timeout_ms);
} else { } else {
__pm_stay_awake(&wl->ws); __pm_stay_awake(wl->ws);
} }
wakelocks_lru_most_recent(wl); wakelocks_lru_most_recent(wl);
@ -271,7 +277,7 @@ int pm_wake_unlock(const char *buf)
ret = PTR_ERR(wl); ret = PTR_ERR(wl);
goto out; goto out;
} }
__pm_relax(&wl->ws); __pm_relax(wl->ws);
wakelocks_lru_most_recent(wl); wakelocks_lru_most_recent(wl);
wakelocks_gc(); wakelocks_gc();

View file

@ -101,7 +101,7 @@ static int alarmtimer_rtc_add_device(struct device *dev,
if (!device_may_wakeup(rtc->dev.parent)) if (!device_may_wakeup(rtc->dev.parent))
return -1; return -1;
__ws = wakeup_source_register("alarmtimer"); __ws = wakeup_source_register(dev, "alarmtimer");
spin_lock_irqsave(&rtcdev_lock, flags); spin_lock_irqsave(&rtcdev_lock, flags);
if (!rtcdev) { if (!rtcdev) {

View file

@ -649,7 +649,7 @@ static void qrtr_node_assign(struct qrtr_node *node, unsigned int nid)
* cause APPS suspend problems and power drain issue. * cause APPS suspend problems and power drain issue.
*/ */
if (!node->ws && (nid == 0 || nid == 3 || nid == 7)) if (!node->ws && (nid == 0 || nid == 3 || nid == 7))
node->ws = wakeup_source_register(name); node->ws = wakeup_source_register(NULL, name);
} }
/** /**