diff --git a/Documentation/ABI/testing/sysfs-class-wakeup b/Documentation/ABI/testing/sysfs-class-wakeup new file mode 100644 index 000000000000..754aab8b6dcd --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-wakeup @@ -0,0 +1,76 @@ +What: /sys/class/wakeup/ +Date: June 2019 +Contact: Tri Vo +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 +Description: + This file contains the name of the wakeup source. + +What: /sys/class/wakeup/.../active_count +Date: June 2019 +Contact: Tri Vo +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 +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 +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 +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 +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 +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 +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 +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 +Description: + The file contains the total amount of time this wakeup source + has been preventing autosleep, in milliseconds. diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 54b6547d32b2..19f5f7cc6311 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -455,7 +455,8 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, goto out; 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.func = func; adev->wakeup.flags.notifier_present = true; diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index e1bb691cf8f1..ec5bb190b9d0 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -1,6 +1,6 @@ # 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_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_GENERIC_DOMAINS) += domain.o domain_governor.o obj-$(CONFIG_HAVE_CLK) += clock_ops.o diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index a4d7b6112a1e..d5008fee9667 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -154,3 +154,21 @@ 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 */ diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index fc036148e63c..48ddeefd6932 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include "power.h" @@ -672,8 +673,13 @@ int dpm_sysfs_add(struct device *dev) if (rc) goto err_wakeup; } + rc = pm_wakeup_source_sysfs_add(dev); + if (rc) + goto err_latency; return 0; + err_latency: + sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group); err_wakeup: sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); err_runtime: diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index c993d6a963cd..a24e66907d30 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -76,22 +76,7 @@ static struct wakeup_source deleted_ws = { .lock = __SPIN_LOCK_UNLOCKED(deleted_ws.lock), }; -/** - * 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); +static DEFINE_IDA(wakeup_ida); /** * 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 *ws; + const char *ws_name; + int id; - ws = kmalloc(sizeof(*ws), GFP_KERNEL); + ws = kzalloc(sizeof(*ws), GFP_KERNEL); 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; + +err_id: + kfree_const(ws->name); +err_name: + kfree(ws); +err_ws: + return NULL; } 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. */ @@ -154,6 +141,13 @@ static void wakeup_source_record(struct wakeup_source *ws) 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. * @ws: Wakeup source to destroy. @@ -165,10 +159,9 @@ void wakeup_source_destroy(struct wakeup_source *ws) if (!ws) return; - wakeup_source_drop(ws); + __pm_relax(ws); wakeup_source_record(ws); - kfree_const(ws->name); - kfree(ws); + wakeup_source_free(ws); } 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. + * @dev: Device this wakeup source is associated with (or NULL if virtual). * @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; + int ret; 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); - + } return ws; } EXPORT_SYMBOL_GPL(wakeup_source_register); @@ -242,6 +245,7 @@ void wakeup_source_unregister(struct wakeup_source *ws) { if (ws) { wakeup_source_remove(ws); + wakeup_source_sysfs_remove(ws); wakeup_source_destroy(ws); } } @@ -285,7 +289,7 @@ int device_wakeup_enable(struct device *dev) if (pm_suspend_target_state != PM_SUSPEND_ON) 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) return -ENOMEM; diff --git a/drivers/base/power/wakeup_stats.c b/drivers/base/power/wakeup_stats.c new file mode 100644 index 000000000000..c7734914d914 --- /dev/null +++ b/drivers/base/power/wakeup_stats.c @@ -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 + * Copyright (c) 2019 Google Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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); diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 883c872eadfa..16a704bca287 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -34,7 +34,6 @@ #include #include #include -#include #include "adsprpc_compat.h" #include "adsprpc_shared.h" #include @@ -75,6 +74,9 @@ #define SENSORS_PDR_SLPI_SERVICE_NAME SENSORS_PDR_ADSP_SERVICE_NAME #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 BALIGN 128 #define NUM_CHANNELS 4 /* adsp, mdsp, slpi, cdsp*/ @@ -148,10 +150,10 @@ #define PERF(enb, cnt, ff) \ {\ - struct timespec startT = {0};\ + struct timespec64 startT = {0};\ int64_t *counter = cnt;\ if (enb && counter) {\ - getnstimeofday(&startT);\ + ktime_get_real_ts64(&startT);\ } \ ff ;\ if (enb && counter) {\ @@ -382,6 +384,11 @@ struct fastrpc_apps { bool legacy_remote_heap; /* Unique job id for each message */ 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 qos_cores silvercores; uint32_t max_size_limit; @@ -468,7 +475,6 @@ struct fastrpc_file { char *debug_buf; /* Flag to enable PM wake/relax voting for every remote invoke */ int wake_enable; - struct wakeup_source *wake_source; uint32_t ws_timeout; }; @@ -542,16 +548,16 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = { static int hlosvm[1] = {VMID_HLOS}; 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; - struct timespec ts, b; + struct timespec64 ts, b; - getnstimeofday(&ts); - b = timespec_sub(ts, *start); - ns = timespec_to_ns(&b); + ktime_get_real_ts64(&ts); + b = timespec64_sub(ts, *start); + ns = timespec64_to_ns(&b); 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, 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; switch (rspFlags) { case NORMAL_RESPONSE: @@ -1934,10 +1940,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) ctx->overps[oix]->mstart, 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); @@ -2094,11 +2097,8 @@ static void inv_args(struct smq_invoke_ctx *ctx) offset, ctx->overps[i]->mend, ctx->overps[i]->mstart, 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: @@ -2174,15 +2174,22 @@ static void fastrpc_init(struct fastrpc_apps *me) 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) - return; + struct fastrpc_apps *me = &gfa; + struct wakeup_source *wake_source = NULL; + /* * Vote with PM to abort any suspend in progress and * 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, @@ -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, - struct timespec *invoket) + struct timespec64 *invoket) { /* update invoke count for dynamic handles */ 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 fastrpc_ioctl_invoke *invoke = &inv->inv; int err = 0, interrupted = 0, cid = fl->cid; - struct timespec invoket = {0}; + struct timespec64 invoket = {0}; int64_t *perf_counter = NULL; if (fl->profile) { perf_counter = getperfcounter(fl, PERF_COUNT); - getnstimeofday(&invoket); + ktime_get_real_ts64(&invoket); } if (!kernel) { @@ -3612,8 +3619,6 @@ static int fastrpc_file_free(struct fastrpc_file *fl) spin_lock(&fl->apps->hlock); hlist_del_init(&fl->hn); spin_unlock(&fl->apps->hlock); - if (fl->wake_source) - wakeup_source_unregister(fl->wake_source); kfree(fl->debug_buf); if (!fl->sctx) { @@ -3963,6 +3968,21 @@ static int fastrpc_channel_open(struct fastrpc_file *fl) 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) { int err = 0; @@ -3986,11 +4006,6 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) if (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); spin_lock_init(&fl->hlock); 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; else fl->ws_timeout = cp->pm.timeout; - fastrpc_pm_awake(fl); + fastrpc_pm_awake(fl, gcinfo[fl->cid].secure); break; case FASTRPC_CONTROL_DSPPROCESS_CLEAN: (void)fastrpc_release_current_dsp_process(fl); @@ -5112,13 +5127,13 @@ static int __init fastrpc_device_init(void) } me->rpmsg_register = 1; - me->wake_source = wakeup_source_register("adsprpc"); - VERIFY(err, !IS_ERR_OR_NULL(me->wake_source)); - if (err) { - pr_err("adsprpc: Error: %s: wakeup_source_register failed with err %d\n", - __func__, PTR_ERR(me->wake_source)); - goto device_create_bail; - } + fastrpc_register_wakeup_source(me->non_secure_dev, + FASTRPC_NON_SECURE_WAKE_SOURCE_CLIENT_NAME, + &me->wake_source); + fastrpc_register_wakeup_source(me->secure_dev, + FASTRPC_SECURE_WAKE_SOURCE_CLIENT_NAME, + &me->wake_source_secure); + return 0; device_create_bail: for (i = 0; i < NUM_CHANNELS; i++) { @@ -5171,6 +5186,8 @@ static void __exit fastrpc_device_exit(void) unregister_rpmsg_driver(&fastrpc_rpmsg_client); if (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); } diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index d5b56fd369ee..2111a5a23e89 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -4379,7 +4379,8 @@ static int diagchar_setup_cdev(dev_t devno) if (!driver->diag_dev) 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; } diff --git a/drivers/i3c/master/i3c-master-qcom-geni.c b/drivers/i3c/master/i3c-master-qcom-geni.c index b278778bbfb2..b45032317d31 100644 --- a/drivers/i3c/master/i3c-master-qcom-geni.c +++ b/drivers/i3c/master/i3c-master-qcom-geni.c @@ -273,7 +273,7 @@ struct geni_i3c_dev { struct geni_ibi ibi; struct workqueue_struct *hj_wq; struct work_struct hj_wd; - struct wakeup_source hj_wl; + struct wakeup_source *hj_wl; 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); 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); 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) qcom_geni_i3c_ibi_unconf(gi3c); 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*/ pm_runtime_force_suspend(gi3c->se.dev); ret = pinctrl_select_state(gi3c->se.i3c_rsc.geni_pinctrl, diff --git a/drivers/input/keycombo.c b/drivers/input/keycombo.c index 2fba451b91d5..bda480a44616 100644 --- a/drivers/input/keycombo.c +++ b/drivers/input/keycombo.c @@ -38,8 +38,8 @@ struct keycombo_state { void (*key_down_fn)(void *); void *priv; int key_is_down; - struct wakeup_source combo_held_wake_source; - struct wakeup_source combo_up_wake_source; + struct wakeup_source *combo_held_wake_source; + struct wakeup_source *combo_up_wake_source; }; 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); if (state->key_up_fn) 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, @@ -92,17 +92,17 @@ static void keycombo_event(struct input_handle *handle, unsigned int type, state->key_down--; } 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; if (queue_delayed_work(state->wq, &state->key_down_work, state->delay)) pr_debug("Key down work already queued!"); } else if (state->key_is_down) { 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); } - __pm_relax(&state->combo_held_wake_source); + __pm_relax(state->combo_held_wake_source); state->key_is_down = 0; } done: @@ -213,8 +213,21 @@ static int keycombo_probe(struct platform_device *pdev) state->key_up_fn = pdata->key_up_fn; INIT_WORK(&state->key_up_work, do_key_up); - wakeup_source_init(&state->combo_held_wake_source, "key combo"); - wakeup_source_init(&state->combo_up_wake_source, "key combo up"); + state->combo_held_wake_source = + 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->input_handler.event = keycombo_event; @@ -225,6 +238,8 @@ static int keycombo_probe(struct platform_device *pdev) ret = input_register_handler(&state->input_handler); if (ret) { kfree(state); + wakeup_source_unregister(state->combo_up_wake_source); + wakeup_source_unregister(state->combo_held_wake_source); return ret; } platform_set_drvdata(pdev, state); @@ -235,6 +250,8 @@ int keycombo_remove(struct platform_device *pdev) { struct keycombo_state *state = platform_get_drvdata(pdev); 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); kfree(state); return 0; diff --git a/drivers/input/misc/gpio_input.c b/drivers/input/misc/gpio_input.c index 5875d739c550..69c0fe7aaaf4 100644 --- a/drivers/input/misc/gpio_input.c +++ b/drivers/input/misc/gpio_input.c @@ -302,7 +302,8 @@ int gpio_event_input_func(struct gpio_event_input_devs *input_devs, input_devs->dev[0]->name, (input_devs->count > 1) ? "..." : ""); - ds->ws = wakeup_source_register(wlname); + ds->ws = wakeup_source_register(&input_devs->dev[0]->dev, + wlname); kfree(wlname); if (!ds->ws) { ret = -ENOMEM; diff --git a/drivers/input/misc/gpio_matrix.c b/drivers/input/misc/gpio_matrix.c index 08769dd88f56..e80885df1424 100644 --- a/drivers/input/misc/gpio_matrix.c +++ b/drivers/input/misc/gpio_matrix.c @@ -24,7 +24,7 @@ struct gpio_kp { struct gpio_event_input_devs *input_devs; struct gpio_event_matrix_info *keypad_info; struct hrtimer timer; - struct wakeup_source wake_src; + struct wakeup_source *wake_src; int current_output; unsigned int use_irq: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++) enable_irq(gpio_to_irq(mi->input_gpios[in])); - __pm_relax(&kp->wake_src); + __pm_relax(kp->wake_src); return HRTIMER_NORESTART; } @@ -241,7 +241,7 @@ static irqreturn_t gpio_keypad_irq_handler(int irq_in, void *dev_id) else 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); 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); 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); 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"); 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); 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); hrtimer_cancel(&kp->timer); - wakeup_source_trash(&kp->wake_src); - for (i = mi->noutputs - 1; i >= 0; i--) { + wakeup_source_unregister(kp->wake_src); +err_wakeup_source_register_failed: + for (i = mi->ninputs - 1; i >= 0; i--) { err_gpio_direction_input_failed: gpio_free(mi->input_gpios[i]); err_request_input_gpio_failed: diff --git a/drivers/input/touchscreen/st/fts.c b/drivers/input/touchscreen/st/fts.c index ea87d1f7ed61..e1dd7887c120 100644 --- a/drivers/input/touchscreen/st/fts.c +++ b/drivers/input/touchscreen/st/fts.c @@ -1596,7 +1596,7 @@ static ssize_t fts_gesture_mask_show(struct device *dev, if (mask[0] == 0) { res = ERROR_OP_NOT_ALLOW; 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 ", tag, __func__); 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 */ - __pm_wakeup_event(&info->wakeup_source, HZ); + __pm_wakeup_event(info->wakeup_source, HZ); regAdd = FIFO_CMD_READONE; 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); - __pm_wakeup_event(&info->wakeup_source, HZ); + __pm_wakeup_event(info->wakeup_source, HZ); 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); - __pm_wakeup_event(&info->wakeup_source, HZ); + __pm_wakeup_event(info->wakeup_source, HZ); 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) { info->sensor_sleep = true; - __pm_stay_awake(&info->wakeup_source); + __pm_stay_awake(info->wakeup_source); } else { 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: if (info->aoi_wake_on_suspend) - __pm_relax(&info->wakeup_source); + __pm_relax(info->wakeup_source); if (!info->sensor_sleep) break; @@ -4710,7 +4710,8 @@ static int fts_probe_internal(struct i2c_client *client, INIT_DELAYED_WORK(&info->fwu_work, fts_fw_update_auto); 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", WQ_UNBOUND|WQ_HIGHPRI|WQ_CPU_INTENSIVE, 1); if (!info->event_wq) { @@ -4963,7 +4964,7 @@ static int fts_probe_internal(struct i2c_client *client, ProbeErrorExit_4: destroy_workqueue(info->fwu_workqueue); - wakeup_source_trash(&info->wakeup_source); + wakeup_source_unregister(info->wakeup_source); ProbeErrorExit_3: if (info->ts_pinctrl) { @@ -5056,7 +5057,7 @@ static int fts_remove(struct i2c_client *client) /* Remove the work thread */ destroy_workqueue(info->event_wq); /* wake_lock_destroy(&info->wakelock); */ - wakeup_source_trash(&info->wakeup_source); + wakeup_source_unregister(info->wakeup_source); destroy_workqueue(info->fwu_workqueue); if (info->ts_pinctrl) { diff --git a/drivers/input/touchscreen/st/fts.h b/drivers/input/touchscreen/st/fts.h index 317007b8891b..b5ab38247e16 100644 --- a/drivers/input/touchscreen/st/fts.h +++ b/drivers/input/touchscreen/st/fts.h @@ -295,7 +295,7 @@ struct fts_ts_info { struct notifier_block notifier; bool sensor_sleep; - struct wakeup_source wakeup_source; + struct wakeup_source *wakeup_source; /* input lock */ struct mutex input_report_mutex; diff --git a/drivers/input/touchscreen/st/fts_lib/ftsTime.c b/drivers/input/touchscreen/st/fts_lib/ftsTime.c index c908a198130b..07d1bf5dba8b 100644 --- a/drivers/input/touchscreen/st/fts_lib/ftsTime.c +++ b/drivers/input/touchscreen/st/fts_lib/ftsTime.c @@ -57,6 +57,7 @@ #include #include #include +#include //#include #include "ftsCrossCompile.h" @@ -65,12 +66,12 @@ void startStopWatch(struct StopWatch *w) { - w->start = current_kernel_time(); + ktime_get_ts(&w->start); } void stopStopWatch(struct StopWatch *w) { - w->end = current_kernel_time(); + ktime_get_ts(&w->end); } int elapsedMillisecond(struct StopWatch *w) diff --git a/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c b/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c index d49d8577a8d8..0eda552934a8 100644 --- a/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c +++ b/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c @@ -78,7 +78,7 @@ struct fpc1020_data { struct pinctrl *fingerprint_pinctrl; struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)]; 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 */ int irq_gpio; int rst_gpio; @@ -384,7 +384,7 @@ static ssize_t handle_wakelock_store(struct device *dev, min(count, strlen(RELEASE_WAKELOCK_W_V)))) { if (fpc1020->nbr_irqs_received_counter_start == fpc1020->nbr_irqs_received) { - __pm_relax(&fpc1020->ttw_wl); + __pm_relax(fpc1020->ttw_wl); } else { dev_dbg(dev, "Ignore releasing of wakelock %d != %d", 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, strlen(RELEASE_WAKELOCK)))) { - __pm_relax(&fpc1020->ttw_wl); + __pm_relax(fpc1020->ttw_wl); } else if (!memcmp(buf, START_IRQS_RECEIVED_CNT, min(count, strlen(START_IRQS_RECEIVED_CNT)))) { fpc1020->nbr_irqs_received_counter_start = @@ -443,7 +443,7 @@ static irqreturn_t fpc1020_irq_handler(int irq, void *handle) mutex_lock(&fpc1020->lock); if (atomic_read(&fpc1020->wakeup_enabled)) { fpc1020->nbr_irqs_received++; - __pm_wakeup_event(&fpc1020->ttw_wl, + __pm_wakeup_event(fpc1020->ttw_wl, msecs_to_jiffies(FPC_TTW_HOLD_TIME)); } 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)); - 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); if (rc) { @@ -570,7 +572,7 @@ static int fpc1020_remove(struct platform_device *pdev) sysfs_remove_group(&pdev->dev.kobj, &attribute_group); 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_io", false); vreg_setup(fpc1020, "vcc_spi", false); diff --git a/drivers/pci/controller/pci-msm.c b/drivers/pci/controller/pci-msm.c index b30331fb33fd..c0e0722a9e39 100644 --- a/drivers/pci/controller/pci-msm.c +++ b/drivers/pci/controller/pci-msm.c @@ -682,7 +682,7 @@ struct msm_pcie_dev_t { bool disable_pc; struct pci_saved_state *saved_state; - struct wakeup_source ws; + struct wakeup_source *ws; struct msm_bus_scale_pdata *bus_scale_table; uint32_t bus_client; @@ -4991,8 +4991,8 @@ static irqreturn_t handle_wake_irq(int irq, void *data) schedule_work(&dev->handle_wake_work); } else { PCIE_DBG2(dev, "Wake up RC%d\n", dev->rc_idx); - __pm_stay_awake(&dev->ws); - __pm_relax(&dev->ws); + __pm_stay_awake(dev->ws); + __pm_relax(dev->ws); if (dev->num_ep > 1) { 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); - if (dev->rc_idx) - wakeup_source_init(&dev->ws, "RC1 pcie_wakeup_source"); - else - wakeup_source_init(&dev->ws, "RC0 pcie_wakeup_source"); + dev->ws = wakeup_source_register(pdev, dev_name(pdev)); + if (!dev->ws) { + PCIE_ERR(dev, + "PCIe: RC%d: failed to register wakeup source\n", + dev->rc_idx); + return -ENOMEM; + } if (dev->irq[MSM_PCIE_INT_GLOBAL_INT].num) { 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); - wakeup_source_trash(&dev->ws); + wakeup_source_unregister(dev->ws); if (dev->wake_n) disable_irq(dev->wake_n); diff --git a/drivers/platform/msm/gsi/gsi_emulation.h b/drivers/platform/msm/gsi/gsi_emulation.h index eead5ef55100..0d10a65bb028 100644 --- a/drivers/platform/msm/gsi/gsi_emulation.h +++ b/drivers/platform/msm/gsi/gsi_emulation.h @@ -1,6 +1,6 @@ /* 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_) @@ -10,7 +10,10 @@ # include "gsi.h" # include "gsi_reg.h" + +#if defined(CONFIG_IPA_EMULATION) # include "gsi_emulation_stubs.h" +#endif # define gsi_emu_readl(c) (readl(c)) # define gsi_emu_writel(v, c) ({ __iowmb(); writel_relaxed((v), (c)); }) diff --git a/drivers/platform/msm/ipa/ipa_rm_inactivity_timer.c b/drivers/platform/msm/ipa/ipa_rm_inactivity_timer.c index 692587a92266..d6b8b946a80d 100644 --- a/drivers/platform/msm/ipa/ipa_rm_inactivity_timer.c +++ b/drivers/platform/msm/ipa/ipa_rm_inactivity_timer.c @@ -1,6 +1,6 @@ // 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 @@ -40,7 +40,7 @@ struct ipa_rm_it_private { bool reschedule_work; bool work_in_progress; unsigned long jiffies; - struct wakeup_source w_lock; + struct wakeup_source *w_lock; char w_lock_name[MAX_WS_NAME]; }; @@ -83,7 +83,7 @@ static void ipa_rm_inactivity_timer_func(struct work_struct *work) } else { IPA_RM_DBG_LOW("calling release_resource on resource %d\n", 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_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, unsigned long msecs) { - struct wakeup_source *pwlock; char *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].reschedule_work = 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; 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, ipa_rm_inactivity_timer_func); 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) { - struct wakeup_source *pwlock; - IPA_RM_DBG_LOW("resource %d\n", resource_name); 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); - pwlock = &(ipa_rm_it_handles[resource_name].w_lock); - wakeup_source_trash(pwlock); + wakeup_source_unregister(ipa_rm_it_handles[resource_name].w_lock); memset(&ipa_rm_it_handles[resource_name], 0, 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].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"); queue_delayed_work(system_unbound_wq, &ipa_rm_it_handles[resource_name].work, diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 7044c1024ad0..78ec187ba5fd 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -5209,7 +5209,7 @@ void ipa3_inc_acquire_wakelock(void) spin_lock_irqsave(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags); ipa3_ctx->wakelock_ref_cnt.cnt++; 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", ipa3_ctx->wakelock_ref_cnt.cnt); 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", ipa3_ctx->wakelock_ref_cnt.cnt); 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); } @@ -6943,8 +6943,14 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, goto fail_device_create; } - /* Create a wakeup source. */ - wakeup_source_init(&ipa3_ctx->w_lock, "IPA_WS"); + /* Register a wakeup source. */ + 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); /* 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: ipa_pm_destroy(); 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); fail_device_create: unregister_chrdev_region(ipa3_ctx->cdev.dev_num, 1); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index a270f44b3a2a..dbb6684db190 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1986,7 +1986,7 @@ struct ipa3_context { bool gsi_ch20_wa; bool s1_bypass_arr[IPA_SMMU_CB_MAX]; u32 wdi_map_cnt; - struct wakeup_source w_lock; + struct wakeup_source *w_lock; struct ipa3_wakelock_ref_cnt wakelock_ref_cnt; /* RMNET_IOCTL_INGRESS_FORMAT_AGG_DATA */ bool ipa_client_apps_wan_cons_agg_gro; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c index f35abd038ef8..c6bfd81bf89d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c @@ -1,6 +1,6 @@ // 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 @@ -149,7 +149,7 @@ struct ipa_pm_client { struct work_struct activate_work; struct delayed_work deactivate_work; 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) { IPA_ACTIVE_CLIENTS_INC_SPECIAL(client->name); if (client->group == IPA_PM_GROUP_APPS) - __pm_stay_awake(&client->wlock); + __pm_stay_awake(client->wlock); } 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) { IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name); 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); @@ -480,7 +480,7 @@ static void delayed_deferred_deactivate_work_func(struct work_struct *work) if (!client->skip_clk_vote) { IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name); if (client->group == IPA_PM_GROUP_APPS) - __pm_relax(&client->wlock); + __pm_relax(client->wlock); } 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) { struct ipa_pm_client *client; - struct wakeup_source *wlock; int elem; 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->hdl = *hdl; client->skip_clk_vote = params->skip_clk_vote; - wlock = &client->wlock; - wakeup_source_init(wlock, client->name); - + client->wlock = wakeup_source_register(NULL, 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); /* 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]) ipa_pm_ctx->clients_by_pipe[i] = NULL; } - wakeup_source_trash(&client->wlock); + wakeup_source_unregister(client->wlock); kfree(client); 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) { client->state = IPA_PM_ACTIVATED; if (client->group == IPA_PM_GROUP_APPS) - __pm_stay_awake(&client->wlock); + __pm_stay_awake(client->wlock); spin_unlock_irqrestore(&client->state_lock, flags); activate_client(client->hdl); if (sync) @@ -1121,7 +1124,7 @@ int ipa_pm_deactivate_all_deferred(void) if (!client->skip_clk_vote) { IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name); if (client->group == IPA_PM_GROUP_APPS) - __pm_relax(&client->wlock); + __pm_relax(client->wlock); } deactivate_client(client->hdl); } else /* if activated or deactivated, we do nothing */ @@ -1176,7 +1179,7 @@ int ipa_pm_deactivate_sync(u32 hdl) if (!client->skip_clk_vote) { IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name); if (client->group == IPA_PM_GROUP_APPS) - __pm_relax(&client->wlock); + __pm_relax(client->wlock); } spin_lock_irqsave(&client->state_lock, flags); diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index 8a119caac50d..0714dad3469d 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -1998,7 +1998,7 @@ int qcom_batt_init(struct charger_param *chg_param) pl_config_init(chip, chg_param->smb_version); 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) goto cleanup; diff --git a/drivers/power/supply/qcom/smb1390-charger-psy.c b/drivers/power/supply/qcom/smb1390-charger-psy.c index 833c8b64c84d..797f0c5c5405 100644 --- a/drivers/power/supply/qcom/smb1390-charger-psy.c +++ b/drivers/power/supply/qcom/smb1390-charger-psy.c @@ -1885,7 +1885,7 @@ static int smb1390_master_probe(struct smb1390 *chip) return rc; } - chip->cp_ws = wakeup_source_register("qcom-chargepump"); + chip->cp_ws = wakeup_source_register(NULL, "qcom-chargepump"); if (!chip->cp_ws) return -ENOMEM; diff --git a/drivers/power/supply/qcom/step-chg-jeita.c b/drivers/power/supply/qcom/step-chg-jeita.c index 5a81e53ed4bd..a2e9bf95918a 100644 --- a/drivers/power/supply/qcom/step-chg-jeita.c +++ b/drivers/power/supply/qcom/step-chg-jeita.c @@ -843,7 +843,7 @@ int qcom_step_chg_init(struct device *dev, if (!chip) 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) return -EINVAL; diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 1df009f84e6f..c56cc908f816 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -1,6 +1,6 @@ // 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 @@ -134,7 +134,7 @@ struct pil_seg { */ struct pil_priv { struct delayed_work proxy; - struct wakeup_source ws; + struct wakeup_source *ws; char wname[32]; struct pil_desc *desc; int num_segs; @@ -581,7 +581,7 @@ static void __pil_proxy_unvote(struct pil_priv *priv) desc->ops->proxy_unvote(desc); notify_proxy_unvote(desc->dev); - __pm_relax(&priv->ws); + __pm_relax(priv->ws); module_put(desc->owner); } @@ -600,10 +600,10 @@ static int pil_proxy_vote(struct pil_desc *desc) struct pil_priv *priv = desc->priv; if (desc->ops->proxy_vote) { - __pm_stay_awake(&priv->ws); + __pm_stay_awake(priv->ws); ret = desc->ops->proxy_vote(desc); if (ret) - __pm_relax(&priv->ws); + __pm_relax(priv->ws); } 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); - 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_LIST_HEAD(&priv->segs); @@ -1597,7 +1603,7 @@ void pil_desc_release(struct pil_desc *desc) if (priv) { ida_simple_remove(&pil_ida, priv->id); flush_delayed_work(&priv->proxy); - wakeup_source_trash(&priv->ws); + wakeup_source_unregister(priv->ws); } desc->priv = NULL; kfree(priv); diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index b8585d13838a..09e549d100bb 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -1,6 +1,6 @@ /* * 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 * it under the terms of the GNU General Public License version 2 and @@ -161,7 +161,7 @@ struct qcom_smp2p { struct regmap *ipc_regmap; int ipc_offset; int ipc_bit; - struct wakeup_source ws; + struct wakeup_source *ws; struct mbox_client mbox_client; struct mbox_chan *mbox_chan; @@ -303,7 +303,7 @@ static irqreturn_t qcom_smp2p_isr(int irq, void *data) { struct qcom_smp2p *smp2p = data; - __pm_stay_awake(&smp2p->ws); + __pm_stay_awake(smp2p->ws); return IRQ_WAKE_THREAD; } @@ -351,7 +351,7 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data) } out: - __pm_relax(&smp2p->ws); + __pm_relax(smp2p->ws); return IRQ_HANDLED; } @@ -648,7 +648,12 @@ static int qcom_smp2p_probe(struct platform_device *pdev) 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 */ qcom_smp2p_kick(smp2p); @@ -659,12 +664,15 @@ static int qcom_smp2p_probe(struct platform_device *pdev) "smp2p", (void *)smp2p); if (ret) { dev_err(&pdev->dev, "failed to request interrupt\n"); - goto unwind_interfaces; + goto unreg_ws; } enable_irq_wake(smp2p->irq); return 0; +unreg_ws: + wakeup_source_unregister(smp2p->ws); + unwind_interfaces: list_for_each_entry(entry, &smp2p->inbound, node) 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 smp2p_entry *entry; + wakeup_source_unregister(smp2p->ws); + list_for_each_entry(entry, &smp2p->inbound, node) irq_domain_remove(entry->domain); diff --git a/drivers/soc/qcom/smp2p_sleepstate.c b/drivers/soc/qcom/smp2p_sleepstate.c index f090415a9a8a..eeae932ab91e 100644 --- a/drivers/soc/qcom/smp2p_sleepstate.c +++ b/drivers/soc/qcom/smp2p_sleepstate.c @@ -1,6 +1,6 @@ // 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 #include @@ -15,7 +15,7 @@ #define PROC_AWAKE_ID 12 /* 12th bit */ #define AWAKE_BIT BIT(PROC_AWAKE_ID) 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. @@ -49,7 +49,7 @@ static struct notifier_block sleepstate_pm_nb = { static irqreturn_t smp2p_sleepstate_handler(int irq, void *ctxt) { - __pm_wakeup_event(¬ify_ws, 200); + __pm_wakeup_event(notify_ws, 200); 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); return ret; } - wakeup_source_init(¬ify_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"); if (irq <= 0) { @@ -89,7 +94,8 @@ static int smp2p_sleepstate_probe(struct platform_device *pdev) } return 0; err: - wakeup_source_trash(¬ify_ws); + wakeup_source_unregister(notify_ws); +err_ws: unregister_pm_notifier(&sleepstate_pm_nb); return ret; } diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c index f8fb03488aea..69f7aa599ee0 100644 --- a/drivers/soc/qcom/subsystem_restart.c +++ b/drivers/soc/qcom/subsystem_restart.c @@ -1,6 +1,6 @@ // 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__ @@ -181,7 +181,7 @@ struct restart_log { struct subsys_device { struct subsys_desc *desc; struct work_struct work; - struct wakeup_source ssr_wlock; + struct wakeup_source *ssr_wlock; char wlname[64]; struct work_struct device_restart_work; 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); track->p_state = SUBSYS_NORMAL; - __pm_relax(&dev->ssr_wlock); + __pm_relax(dev->ssr_wlock); 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) { if (track->p_state != SUBSYS_RESTARTING) { track->p_state = SUBSYS_CRASHED; - __pm_stay_awake(&dev->ssr_wlock); + __pm_stay_awake(dev->ssr_wlock); queue_work(ssr_wq, &dev->work); } else { panic("Subsystem %s crashed during SSR!", name); @@ -1251,7 +1251,7 @@ int subsystem_restart_dev(struct subsys_device *dev) __subsystem_restart_dev(dev); break; case RESET_SOC: - __pm_stay_awake(&dev->ssr_wlock); + __pm_stay_awake(dev->ssr_wlock); schedule_work(&dev->device_restart_work); return 0; default: @@ -1415,7 +1415,7 @@ static void subsys_device_release(struct device *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); ida_simple_remove(&subsys_ida, subsys->id); 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); 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->device_restart_work, device_restart_work_hdlr); 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); if (subsys->id < 0) { - wakeup_source_trash(&subsys->ssr_wlock); + wakeup_source_unregister(subsys->ssr_wlock); ret = subsys->id; kfree(subsys); return ERR_PTR(ret); diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 462ab9a430df..6abde83adfbb 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -182,7 +182,7 @@ struct msm_geni_serial_port { int loopback; int wakeup_irq; unsigned char wakeup_byte; - struct wakeup_source geni_wake; + struct wakeup_source *geni_wake; void *ipc_log_tx; void *ipc_log_rx; void *ipc_log_pwr; @@ -1955,7 +1955,7 @@ static irqreturn_t msm_geni_wakeup_isr(int isr, void *dev) __func__, port->wakeup_byte); port->edge_count = 0; 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) { 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->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS; 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) { ret = uport->irq; 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, @@ -3170,7 +3180,7 @@ static int msm_geni_serial_probe(struct platform_device *pdev) if (ret) { dev_err(uport->dev, "%s: Failed to get IRQ ret %d\n", __func__, ret); - goto exit_geni_serial_probe; + goto exit_wakeup_unregister; } uport->private_data = (void *)drv; @@ -3203,10 +3213,20 @@ static int msm_geni_serial_probe(struct platform_device *pdev) dev_port->port_setup = false; ret = msm_geni_serial_get_ver_info(uport); if (ret) - goto exit_geni_serial_probe; + goto exit_wakeup_unregister; 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: IPC_LOG_MSG(dev_port->ipc_log_misc, "%s: ret:%d\n", __func__, ret); return ret; @@ -3218,7 +3238,8 @@ static int msm_geni_serial_remove(struct platform_device *pdev) struct uart_driver *drv = (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); if (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); } IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__); - __pm_relax(&port->geni_wake); + __pm_relax(port->geni_wake); exit_runtime_suspend: 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 * wake source is activated by the wakeup isr. */ - __pm_relax(&port->geni_wake); - __pm_stay_awake(&port->geni_wake); + __pm_relax(port->geni_wake); + __pm_stay_awake(port->geni_wake); if (port->wakeup_irq > 0) 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); if (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; } start_rx_sequencer(&port->uport); diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 8b4ded92d1e9..4760c2b7ea84 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1383,13 +1383,13 @@ static int ep_create_wakeup_source(struct epitem *epi) struct wakeup_source *ws; if (!epi->ep->ws) { - epi->ep->ws = wakeup_source_register("eventpoll"); + epi->ep->ws = wakeup_source_register(NULL, "eventpoll"); if (!epi->ep->ws) return -ENOMEM; } name = epi->ffd.file->f_path.dentry->d_name.name; - ws = wakeup_source_register(name); + ws = wakeup_source_register(NULL, name); if (!ws) return -ENOMEM; diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index 4238dde0aaf0..6e6a25220c56 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h @@ -34,6 +34,7 @@ struct wake_irq; * struct wakeup_source - Representation of wakeup sources * * @name: Name of the wakeup source + * @id: Wakeup source id * @entry: Wakeup source list entry * @lock: Wakeup source lock * @wakeirq: Optional device specific wakeirq @@ -48,11 +49,13 @@ struct wake_irq; * @relax_count: Number of times the wakeup source was deactivated. * @expire_count: Number of times the wakeup source's timeout has expired. * @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. * @has_timeout: The wakeup source has been activated with a timeout. */ struct wakeup_source { const char *name; + int id; struct list_head entry; spinlock_t lock; struct wake_irq *wakeirq; @@ -68,10 +71,13 @@ struct wakeup_source { unsigned long relax_count; unsigned long expire_count; unsigned long wakeup_count; + struct device *dev; bool active:1; bool autosleep_enabled:1; }; +#define WAKEUP_SOURCE_DEV + #ifdef CONFIG_PM_SLEEP /* @@ -94,13 +100,12 @@ static inline void device_set_wakeup_path(struct device *dev) } /* 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 void wakeup_source_drop(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_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 int device_wakeup_enable(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; } -static inline void wakeup_source_prepare(struct wakeup_source *ws, - const char *name) {} - static inline struct wakeup_source *wakeup_source_create(const char *name) { 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_add(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; } @@ -197,19 +198,6 @@ static inline void pm_wakeup_dev_event(struct device *dev, unsigned int msec, #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) { return pm_wakeup_ws_event(ws, msec, false); diff --git a/kernel/power/autosleep.c b/kernel/power/autosleep.c index 41e83a779e19..9af5a50d3489 100644 --- a/kernel/power/autosleep.c +++ b/kernel/power/autosleep.c @@ -116,7 +116,7 @@ int pm_autosleep_set_state(suspend_state_t state) int __init pm_autosleep_init(void) { - autosleep_ws = wakeup_source_register("autosleep"); + autosleep_ws = wakeup_source_register(NULL, "autosleep"); if (!autosleep_ws) return -ENOMEM; diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c index 4210152e56f0..105df4dfc783 100644 --- a/kernel/power/wakelock.c +++ b/kernel/power/wakelock.c @@ -27,7 +27,7 @@ static DEFINE_MUTEX(wakelocks_lock); struct wakelock { char *name; struct rb_node node; - struct wakeup_source ws; + struct wakeup_source *ws; #ifdef CONFIG_PM_WAKELOCKS_GC struct list_head lru; #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)) { 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); } if (str > buf) @@ -112,16 +112,16 @@ static void __wakelocks_gc(struct work_struct *work) u64 idle_time_ns; bool active; - spin_lock_irq(&wl->ws.lock); - idle_time_ns = ktime_to_ns(ktime_sub(now, wl->ws.last_time)); - active = wl->ws.active; - spin_unlock_irq(&wl->ws.lock); + spin_lock_irq(&wl->ws->lock); + idle_time_ns = ktime_to_ns(ktime_sub(now, wl->ws->last_time)); + active = wl->ws->active; + spin_unlock_irq(&wl->ws->lock); if (idle_time_ns < ((u64)WL_GC_TIME_SEC * NSEC_PER_SEC)) break; if (!active) { - wakeup_source_remove(&wl->ws); + wakeup_source_unregister(wl->ws); rb_erase(&wl->node, &wakelocks_tree); list_del(&wl->lru); kfree(wl->name); @@ -187,9 +187,15 @@ static struct wakelock *wakelock_lookup_add(const char *name, size_t len, kfree(wl); return ERR_PTR(-ENOMEM); } - wl->ws.name = wl->name; - wl->ws.last_time = ktime_get(); - wakeup_source_add(&wl->ws); + + wl->ws = wakeup_source_register(NULL, wl->name); + 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_insert_color(&wl->node, &wakelocks_tree); wakelocks_lru_add(wl); @@ -233,9 +239,9 @@ int pm_wake_lock(const char *buf) u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1; do_div(timeout_ms, NSEC_PER_MSEC); - __pm_wakeup_event(&wl->ws, timeout_ms); + __pm_wakeup_event(wl->ws, timeout_ms); } else { - __pm_stay_awake(&wl->ws); + __pm_stay_awake(wl->ws); } wakelocks_lru_most_recent(wl); @@ -271,7 +277,7 @@ int pm_wake_unlock(const char *buf) ret = PTR_ERR(wl); goto out; } - __pm_relax(&wl->ws); + __pm_relax(wl->ws); wakelocks_lru_most_recent(wl); wakelocks_gc(); diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 9eece67f29f3..4bb158755ef7 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -101,7 +101,7 @@ static int alarmtimer_rtc_add_device(struct device *dev, if (!device_may_wakeup(rtc->dev.parent)) return -1; - __ws = wakeup_source_register("alarmtimer"); + __ws = wakeup_source_register(dev, "alarmtimer"); spin_lock_irqsave(&rtcdev_lock, flags); if (!rtcdev) { diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 6f1f1d5a2440..5871058ea0cf 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -649,7 +649,7 @@ static void qrtr_node_assign(struct qrtr_node *node, unsigned int nid) * cause APPS suspend problems and power drain issue. */ if (!node->ws && (nid == 0 || nid == 3 || nid == 7)) - node->ws = wakeup_source_register(name); + node->ws = wakeup_source_register(NULL, name); } /**