0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/capability.h>
0014 #include <linux/ctype.h>
0015 #include <linux/device.h>
0016 #include <linux/err.h>
0017 #include <linux/hrtimer.h>
0018 #include <linux/list.h>
0019 #include <linux/rbtree.h>
0020 #include <linux/slab.h>
0021 #include <linux/workqueue.h>
0022
0023 #include "power.h"
0024
0025 static DEFINE_MUTEX(wakelocks_lock);
0026
0027 struct wakelock {
0028 char *name;
0029 struct rb_node node;
0030 struct wakeup_source *ws;
0031 #ifdef CONFIG_PM_WAKELOCKS_GC
0032 struct list_head lru;
0033 #endif
0034 };
0035
0036 static struct rb_root wakelocks_tree = RB_ROOT;
0037
0038 ssize_t pm_show_wakelocks(char *buf, bool show_active)
0039 {
0040 struct rb_node *node;
0041 struct wakelock *wl;
0042 int len = 0;
0043
0044 mutex_lock(&wakelocks_lock);
0045
0046 for (node = rb_first(&wakelocks_tree); node; node = rb_next(node)) {
0047 wl = rb_entry(node, struct wakelock, node);
0048 if (wl->ws->active == show_active)
0049 len += sysfs_emit_at(buf, len, "%s ", wl->name);
0050 }
0051
0052 len += sysfs_emit_at(buf, len, "\n");
0053
0054 mutex_unlock(&wakelocks_lock);
0055 return len;
0056 }
0057
0058 #if CONFIG_PM_WAKELOCKS_LIMIT > 0
0059 static unsigned int number_of_wakelocks;
0060
0061 static inline bool wakelocks_limit_exceeded(void)
0062 {
0063 return number_of_wakelocks > CONFIG_PM_WAKELOCKS_LIMIT;
0064 }
0065
0066 static inline void increment_wakelocks_number(void)
0067 {
0068 number_of_wakelocks++;
0069 }
0070
0071 static inline void decrement_wakelocks_number(void)
0072 {
0073 number_of_wakelocks--;
0074 }
0075 #else
0076 static inline bool wakelocks_limit_exceeded(void) { return false; }
0077 static inline void increment_wakelocks_number(void) {}
0078 static inline void decrement_wakelocks_number(void) {}
0079 #endif
0080
0081 #ifdef CONFIG_PM_WAKELOCKS_GC
0082 #define WL_GC_COUNT_MAX 100
0083 #define WL_GC_TIME_SEC 300
0084
0085 static void __wakelocks_gc(struct work_struct *work);
0086 static LIST_HEAD(wakelocks_lru_list);
0087 static DECLARE_WORK(wakelock_work, __wakelocks_gc);
0088 static unsigned int wakelocks_gc_count;
0089
0090 static inline void wakelocks_lru_add(struct wakelock *wl)
0091 {
0092 list_add(&wl->lru, &wakelocks_lru_list);
0093 }
0094
0095 static inline void wakelocks_lru_most_recent(struct wakelock *wl)
0096 {
0097 list_move(&wl->lru, &wakelocks_lru_list);
0098 }
0099
0100 static void __wakelocks_gc(struct work_struct *work)
0101 {
0102 struct wakelock *wl, *aux;
0103 ktime_t now;
0104
0105 mutex_lock(&wakelocks_lock);
0106
0107 now = ktime_get();
0108 list_for_each_entry_safe_reverse(wl, aux, &wakelocks_lru_list, lru) {
0109 u64 idle_time_ns;
0110 bool active;
0111
0112 spin_lock_irq(&wl->ws->lock);
0113 idle_time_ns = ktime_to_ns(ktime_sub(now, wl->ws->last_time));
0114 active = wl->ws->active;
0115 spin_unlock_irq(&wl->ws->lock);
0116
0117 if (idle_time_ns < ((u64)WL_GC_TIME_SEC * NSEC_PER_SEC))
0118 break;
0119
0120 if (!active) {
0121 wakeup_source_unregister(wl->ws);
0122 rb_erase(&wl->node, &wakelocks_tree);
0123 list_del(&wl->lru);
0124 kfree(wl->name);
0125 kfree(wl);
0126 decrement_wakelocks_number();
0127 }
0128 }
0129 wakelocks_gc_count = 0;
0130
0131 mutex_unlock(&wakelocks_lock);
0132 }
0133
0134 static void wakelocks_gc(void)
0135 {
0136 if (++wakelocks_gc_count <= WL_GC_COUNT_MAX)
0137 return;
0138
0139 schedule_work(&wakelock_work);
0140 }
0141 #else
0142 static inline void wakelocks_lru_add(struct wakelock *wl) {}
0143 static inline void wakelocks_lru_most_recent(struct wakelock *wl) {}
0144 static inline void wakelocks_gc(void) {}
0145 #endif
0146
0147 static struct wakelock *wakelock_lookup_add(const char *name, size_t len,
0148 bool add_if_not_found)
0149 {
0150 struct rb_node **node = &wakelocks_tree.rb_node;
0151 struct rb_node *parent = *node;
0152 struct wakelock *wl;
0153
0154 while (*node) {
0155 int diff;
0156
0157 parent = *node;
0158 wl = rb_entry(*node, struct wakelock, node);
0159 diff = strncmp(name, wl->name, len);
0160 if (diff == 0) {
0161 if (wl->name[len])
0162 diff = -1;
0163 else
0164 return wl;
0165 }
0166 if (diff < 0)
0167 node = &(*node)->rb_left;
0168 else
0169 node = &(*node)->rb_right;
0170 }
0171 if (!add_if_not_found)
0172 return ERR_PTR(-EINVAL);
0173
0174 if (wakelocks_limit_exceeded())
0175 return ERR_PTR(-ENOSPC);
0176
0177
0178 wl = kzalloc(sizeof(*wl), GFP_KERNEL);
0179 if (!wl)
0180 return ERR_PTR(-ENOMEM);
0181
0182 wl->name = kstrndup(name, len, GFP_KERNEL);
0183 if (!wl->name) {
0184 kfree(wl);
0185 return ERR_PTR(-ENOMEM);
0186 }
0187
0188 wl->ws = wakeup_source_register(NULL, wl->name);
0189 if (!wl->ws) {
0190 kfree(wl->name);
0191 kfree(wl);
0192 return ERR_PTR(-ENOMEM);
0193 }
0194 wl->ws->last_time = ktime_get();
0195
0196 rb_link_node(&wl->node, parent, node);
0197 rb_insert_color(&wl->node, &wakelocks_tree);
0198 wakelocks_lru_add(wl);
0199 increment_wakelocks_number();
0200 return wl;
0201 }
0202
0203 int pm_wake_lock(const char *buf)
0204 {
0205 const char *str = buf;
0206 struct wakelock *wl;
0207 u64 timeout_ns = 0;
0208 size_t len;
0209 int ret = 0;
0210
0211 if (!capable(CAP_BLOCK_SUSPEND))
0212 return -EPERM;
0213
0214 while (*str && !isspace(*str))
0215 str++;
0216
0217 len = str - buf;
0218 if (!len)
0219 return -EINVAL;
0220
0221 if (*str && *str != '\n') {
0222
0223 ret = kstrtou64(skip_spaces(str), 10, &timeout_ns);
0224 if (ret)
0225 return -EINVAL;
0226 }
0227
0228 mutex_lock(&wakelocks_lock);
0229
0230 wl = wakelock_lookup_add(buf, len, true);
0231 if (IS_ERR(wl)) {
0232 ret = PTR_ERR(wl);
0233 goto out;
0234 }
0235 if (timeout_ns) {
0236 u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1;
0237
0238 do_div(timeout_ms, NSEC_PER_MSEC);
0239 __pm_wakeup_event(wl->ws, timeout_ms);
0240 } else {
0241 __pm_stay_awake(wl->ws);
0242 }
0243
0244 wakelocks_lru_most_recent(wl);
0245
0246 out:
0247 mutex_unlock(&wakelocks_lock);
0248 return ret;
0249 }
0250
0251 int pm_wake_unlock(const char *buf)
0252 {
0253 struct wakelock *wl;
0254 size_t len;
0255 int ret = 0;
0256
0257 if (!capable(CAP_BLOCK_SUSPEND))
0258 return -EPERM;
0259
0260 len = strlen(buf);
0261 if (!len)
0262 return -EINVAL;
0263
0264 if (buf[len-1] == '\n')
0265 len--;
0266
0267 if (!len)
0268 return -EINVAL;
0269
0270 mutex_lock(&wakelocks_lock);
0271
0272 wl = wakelock_lookup_add(buf, len, false);
0273 if (IS_ERR(wl)) {
0274 ret = PTR_ERR(wl);
0275 goto out;
0276 }
0277 __pm_relax(wl->ws);
0278
0279 wakelocks_lru_most_recent(wl);
0280 wakelocks_gc();
0281
0282 out:
0283 mutex_unlock(&wakelocks_lock);
0284 return ret;
0285 }