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:
commit
1ba1a55750
37 changed files with 679 additions and 241 deletions
76
Documentation/ABI/testing/sysfs-class-wakeup
Normal file
76
Documentation/ABI/testing/sysfs-class-wakeup
Normal 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.
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
214
drivers/base/power/wakeup_stats.c
Normal file
214
drivers/base/power/wakeup_stats.c
Normal 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);
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)); })
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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(¬ify_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(¬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");
|
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(¬ify_ws);
|
wakeup_source_unregister(notify_ws);
|
||||||
|
err_ws:
|
||||||
unregister_pm_notifier(&sleepstate_pm_nb);
|
unregister_pm_notifier(&sleepstate_pm_nb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue