| 1 | |
| 2 | |
| 3 | * drivers/base/power/wakeup.c - System wakeup events framework
|
| 4 | *
|
| 5 | * Copyright (c) 2010 Rafael J. Wysocki <[email protected]>, Novell Inc.
|
| 6 |
|
| 7 | #define pr_fmt(fmt) "PM: " fmt
|
| 8 |
|
| 9 | #include <linux/device.h>
|
| 10 | #include <linux/slab.h>
|
| 11 | #include <linux/sched/signal.h>
|
| 12 | #include <linux/capability.h>
|
| 13 | #include <linux/export.h>
|
| 14 | #include <linux/suspend.h>
|
| 15 | #include <linux/seq_file.h>
|
| 16 | #include <linux/debugfs.h>
|
| 17 | #include <linux/pm_wakeirq.h>
|
| 18 | #include <trace/events/power.h>
|
| 19 |
|
| 20 | #include "power.h"
|
| 21 |
|
| 22 | #define list_for_each_entry_rcu_locked(pos, head, member) \
|
| 23 | list_for_each_entry_rcu(pos, head, member, \
|
| 24 | srcu_read_lock_held(&wakeup_srcu))
|
| 25 | |
| 26 | * If set, the suspend/hibernate code will abort transitions to a sleep state
|
| 27 | * if wakeup events are registered during or immediately before the transition.
|
| 28 |
|
| 29 | bool events_check_enabled __read_mostly;
|
| 30 |
|
| 31 |
|
| 32 | static unsigned int wakeup_irq[2] __read_mostly;
|
| 33 | static DEFINE_RAW_SPINLOCK(wakeup_irq_lock);
|
| 34 |
|
| 35 |
|
| 36 | static atomic_t pm_abort_suspend __read_mostly;
|
| 37 |
|
| 38 | |
| 39 | * Combined counters of registered wakeup events and wakeup events in progress.
|
| 40 | * They need to be modified together atomically, so it's better to use one
|
| 41 | * atomic variable to hold them both.
|
| 42 |
|
| 43 | static atomic_t combined_event_count = ATOMIC_INIT(0);
|
| 44 |
|
| 45 | #define IN_PROGRESS_BITS (sizeof(int) * 4)
|
| 46 | #define MAX_IN_PROGRESS ((1 << IN_PROGRESS_BITS) - 1)
|
| 47 |
|
| 48 | static void split_counters(unsigned int *cnt, unsigned int *inpr)
|
| 49 | {
|
| 50 | unsigned int comb = atomic_read(&combined_event_count);
|
| 51 |
|
| 52 | *cnt = (comb >> IN_PROGRESS_BITS);
|
| 53 | *inpr = comb & MAX_IN_PROGRESS;
|
| 54 | }
|
| 55 |
|
| 56 |
|
| 57 | static unsigned int saved_count;
|
| 58 |
|
| 59 | static DEFINE_RAW_SPINLOCK(events_lock);
|
| 60 |
|
| 61 | static void pm_wakeup_timer_fn(struct timer_list *t);
|
| 62 |
|
| 63 | static LIST_HEAD(wakeup_sources);
|
| 64 |
|
| 65 | static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);
|
| 66 |
|
| 67 | DEFINE_STATIC_SRCU(wakeup_srcu);
|
| 68 |
|
| 69 | static struct wakeup_source deleted_ws = {
|
| 70 | .name = "deleted",
|
| 71 | .lock = __SPIN_LOCK_UNLOCKED(deleted_ws.lock),
|
| 72 | };
|
| 73 |
|
| 74 | static DEFINE_IDA(wakeup_ida);
|
| 75 |
|
| 76 | |
| 77 | * wakeup_source_create - Create a struct wakeup_source object.
|
| 78 | * @name: Name of the new wakeup source.
|
| 79 |
|
| 80 | static struct wakeup_source *wakeup_source_create(const char *name)
|
| 81 | {
|
| 82 | struct wakeup_source *ws;
|
| 83 | const char *ws_name;
|
| 84 | int id;
|
| 85 |
|
| 86 | ws = kzalloc_obj(*ws);
|
| 87 | if (!ws)
|
| 88 | goto err_ws;
|
| 89 |
|
| 90 | ws_name = kstrdup_const(name, GFP_KERNEL);
|
| 91 | if (!ws_name)
|
| 92 | goto err_name;
|
| 93 | ws->name = ws_name;
|
| 94 |
|
| 95 | id = ida_alloc(&wakeup_ida, GFP_KERNEL);
|
| 96 | if (id < 0)
|
| 97 | goto err_id;
|
| 98 | ws->id = id;
|
| 99 |
|
| 100 | return ws;
|
| 101 |
|
| 102 | err_id:
|
| 103 | kfree_const(ws->name);
|
| 104 | err_name:
|
| 105 | kfree(ws);
|
| 106 | err_ws:
|
| 107 | return NULL;
|
| 108 | }
|
| 109 |
|
| 110 | |
| 111 | * Record wakeup_source statistics being deleted into a dummy wakeup_source.
|
| 112 |
|
| 113 | static void wakeup_source_record(struct wakeup_source *ws)
|
| 114 | {
|
| 115 | unsigned long flags;
|
| 116 |
|
| 117 | spin_lock_irqsave(&deleted_ws.lock, flags);
|
| 118 |
|
| 119 | if (ws->event_count) {
|
| 120 | deleted_ws.total_time =
|
| 121 | ktime_add(deleted_ws.total_time, ws->total_time);
|
| 122 | deleted_ws.prevent_sleep_time =
|
| 123 | ktime_add(deleted_ws.prevent_sleep_time,
|
| 124 | ws->prevent_sleep_time);
|
| 125 | deleted_ws.max_time =
|
| 126 | ktime_compare(deleted_ws.max_time, ws->max_time) > 0 ?
|
| 127 | deleted_ws.max_time : ws->max_time;
|
| 128 | deleted_ws.event_count += ws->event_count;
|
| 129 | deleted_ws.active_count += ws->active_count;
|
| 130 | deleted_ws.relax_count += ws->relax_count;
|
| 131 | deleted_ws.expire_count += ws->expire_count;
|
| 132 | deleted_ws.wakeup_count += ws->wakeup_count;
|
| 133 | }
|
| 134 |
|
| 135 | spin_unlock_irqrestore(&deleted_ws.lock, flags);
|
| 136 | }
|
| 137 |
|
| 138 | static void wakeup_source_free(struct wakeup_source *ws)
|
| 139 | {
|
| 140 | ida_free(&wakeup_ida, ws->id);
|
| 141 | kfree_const(ws->name);
|
| 142 | kfree(ws);
|
| 143 | }
|
| 144 |
|
| 145 | |
| 146 | * wakeup_source_destroy - Destroy a struct wakeup_source object.
|
| 147 | * @ws: Wakeup source to destroy.
|
| 148 | *
|
| 149 | * Use only for wakeup source objects created with wakeup_source_create().
|
| 150 |
|
| 151 | static void wakeup_source_destroy(struct wakeup_source *ws)
|
| 152 | {
|
| 153 | if (!ws)
|
| 154 | return;
|
| 155 |
|
| 156 | __pm_relax(ws);
|
| 157 | wakeup_source_record(ws);
|
| 158 | wakeup_source_free(ws);
|
| 159 | }
|
| 160 |
|
| 161 | |
| 162 | * wakeup_source_add - Add given object to the list of wakeup sources.
|
| 163 | * @ws: Wakeup source object to add to the list.
|
| 164 |
|
| 165 | static void wakeup_source_add(struct wakeup_source *ws)
|
| 166 | {
|
| 167 | unsigned long flags;
|
| 168 |
|
| 169 | if (WARN_ON(!ws))
|
| 170 | return;
|
| 171 |
|
| 172 | spin_lock_init(&ws->lock);
|
| 173 | timer_setup(&ws->timer, pm_wakeup_timer_fn, 0);
|
| 174 | ws->active = false;
|
| 175 |
|
| 176 | raw_spin_lock_irqsave(&events_lock, flags);
|
| 177 | list_add_rcu(&ws->entry, &wakeup_sources);
|
| 178 | raw_spin_unlock_irqrestore(&events_lock, flags);
|
| 179 | }
|
| 180 |
|
| 181 | |
| 182 | * wakeup_source_remove - Remove given object from the wakeup sources list.
|
| 183 | * @ws: Wakeup source object to remove from the list.
|
| 184 |
|
| 185 | static void wakeup_source_remove(struct wakeup_source *ws)
|
| 186 | {
|
| 187 | unsigned long flags;
|
| 188 |
|
| 189 | if (WARN_ON(!ws))
|
| 190 | return;
|
| 191 |
|
| 192 | |
| 193 | * After shutting down the timer, wakeup_source_activate() will warn if
|
| 194 | * the given wakeup source is passed to it.
|
| 195 |
|
| 196 | timer_shutdown_sync(&ws->timer);
|
| 197 |
|
| 198 | raw_spin_lock_irqsave(&events_lock, flags);
|
| 199 | list_del_rcu(&ws->entry);
|
| 200 | raw_spin_unlock_irqrestore(&events_lock, flags);
|
| 201 | synchronize_srcu(&wakeup_srcu);
|
| 202 | }
|
| 203 |
|
| 204 | |
| 205 | * wakeup_source_register - Create wakeup source and add it to the list.
|
| 206 | * @dev: Device this wakeup source is associated with (or NULL if virtual).
|
| 207 | * @name: Name of the wakeup source to register.
|
| 208 |
|
| 209 | struct wakeup_source *wakeup_source_register(struct device *dev,
|
| 210 | const char *name)
|
| 211 | {
|
| 212 | struct wakeup_source *ws;
|
| 213 | int ret;
|
| 214 |
|
| 215 | ws = wakeup_source_create(name);
|
| 216 | if (ws) {
|
| 217 | if (!dev || device_is_registered(dev)) {
|
| 218 | ret = wakeup_source_sysfs_add(dev, ws);
|
| 219 | if (ret) {
|
| 220 | wakeup_source_free(ws);
|
| 221 | return NULL;
|
| 222 | }
|
| 223 | }
|
| 224 | wakeup_source_add(ws);
|
| 225 | }
|
| 226 | return ws;
|
| 227 | }
|
| 228 | EXPORT_SYMBOL_GPL(wakeup_source_register);
|
| 229 |
|
| 230 | |
| 231 | * wakeup_source_unregister - Remove wakeup source from the list and remove it.
|
| 232 | * @ws: Wakeup source object to unregister.
|
| 233 |
|
| 234 | void wakeup_source_unregister(struct wakeup_source *ws)
|
| 235 | {
|
| 236 | if (ws) {
|
| 237 | wakeup_source_remove(ws);
|
| 238 | if (ws->dev)
|
| 239 | wakeup_source_sysfs_remove(ws);
|
| 240 |
|
| 241 | wakeup_source_destroy(ws);
|
| 242 | }
|
| 243 | }
|
| 244 | EXPORT_SYMBOL_GPL(wakeup_source_unregister);
|
| 245 |
|
| 246 | |
| 247 | * wakeup_sources_read_lock - Lock wakeup source list for read.
|
| 248 | *
|
| 249 | * Returns an index of srcu lock for struct wakeup_srcu.
|
| 250 | * This index must be passed to the matching wakeup_sources_read_unlock().
|
| 251 |
|
| 252 | int wakeup_sources_read_lock(void)
|
| 253 | {
|
| 254 | return srcu_read_lock(&wakeup_srcu);
|
| 255 | }
|
| 256 | EXPORT_SYMBOL_GPL(wakeup_sources_read_lock);
|
| 257 |
|
| 258 | |
| 259 | * wakeup_sources_read_unlock - Unlock wakeup source list.
|
| 260 | * @idx: return value from corresponding wakeup_sources_read_lock()
|
| 261 |
|
| 262 | void wakeup_sources_read_unlock(int idx)
|
| 263 | {
|
| 264 | srcu_read_unlock(&wakeup_srcu, idx);
|
| 265 | }
|
| 266 | EXPORT_SYMBOL_GPL(wakeup_sources_read_unlock);
|
| 267 |
|
| 268 | |
| 269 | * wakeup_sources_walk_start - Begin a walk on wakeup source list
|
| 270 | *
|
| 271 | * Returns first object of the list of wakeup sources.
|
| 272 | *
|
| 273 | * Note that to be safe, wakeup sources list needs to be locked by calling
|
| 274 | * wakeup_source_read_lock() for this.
|
| 275 |
|
| 276 | struct wakeup_source *wakeup_sources_walk_start(void)
|
| 277 | {
|
| 278 | return list_first_or_null_rcu(&wakeup_sources, struct wakeup_source, entry);
|
| 279 | }
|
| 280 | EXPORT_SYMBOL_GPL(wakeup_sources_walk_start);
|
| 281 |
|
| 282 | |
| 283 | * wakeup_sources_walk_next - Get next wakeup source from the list
|
| 284 | * @ws: Previous wakeup source object
|
| 285 | *
|
| 286 | * Note that to be safe, wakeup sources list needs to be locked by calling
|
| 287 | * wakeup_source_read_lock() for this.
|
| 288 |
|
| 289 | struct wakeup_source *wakeup_sources_walk_next(struct wakeup_source *ws)
|
| 290 | {
|
| 291 | struct list_head *ws_head = &wakeup_sources;
|
| 292 |
|
| 293 | return list_next_or_null_rcu(ws_head, &ws->entry,
|
| 294 | struct wakeup_source, entry);
|
| 295 | }
|
| 296 | EXPORT_SYMBOL_GPL(wakeup_sources_walk_next);
|
| 297 |
|
| 298 | |
| 299 | * device_wakeup_attach - Attach a wakeup source object to a device object.
|
| 300 | * @dev: Device to handle.
|
| 301 | * @ws: Wakeup source object to attach to @dev.
|
| 302 | *
|
| 303 | * This causes @dev to be treated as a wakeup device.
|
| 304 |
|
| 305 | static int device_wakeup_attach(struct device *dev, struct wakeup_source *ws)
|
| 306 | {
|
| 307 | spin_lock_irq(&dev->power.lock);
|
| 308 | if (dev->power.wakeup) {
|
| 309 | spin_unlock_irq(&dev->power.lock);
|
| 310 | return -EEXIST;
|
| 311 | }
|
| 312 | dev->power.wakeup = ws;
|
| 313 | if (dev->power.wakeirq)
|
| 314 | device_wakeup_attach_irq(dev, dev->power.wakeirq);
|
| 315 | spin_unlock_irq(&dev->power.lock);
|
| 316 | return 0;
|
| 317 | }
|
| 318 |
|
| 319 | |
| 320 | * device_wakeup_enable - Enable given device to be a wakeup source.
|
| 321 | * @dev: Device to handle.
|
| 322 | *
|
| 323 | * Create a wakeup source object, register it and attach it to @dev.
|
| 324 |
|
| 325 | int device_wakeup_enable(struct device *dev)
|
| 326 | {
|
| 327 | struct wakeup_source *ws;
|
| 328 | int ret;
|
| 329 |
|
| 330 | if (!dev || !dev->power.can_wakeup)
|
| 331 | return -EINVAL;
|
| 332 |
|
| 333 | if (pm_sleep_transition_in_progress())
|
| 334 | dev_dbg(dev, "Suspicious %s() during system transition!\n", __func__);
|
| 335 |
|
| 336 | ws = wakeup_source_register(dev, dev_name(dev));
|
| 337 | if (!ws)
|
| 338 | return -ENOMEM;
|
| 339 |
|
| 340 | ret = device_wakeup_attach(dev, ws);
|
| 341 | if (ret)
|
| 342 | wakeup_source_unregister(ws);
|
| 343 |
|
| 344 | return ret;
|
| 345 | }
|
| 346 | EXPORT_SYMBOL_GPL(device_wakeup_enable);
|
| 347 |
|
| 348 | |
| 349 | * device_wakeup_attach_irq - Attach a wakeirq to a wakeup source
|
| 350 | * @dev: Device to handle
|
| 351 | * @wakeirq: Device specific wakeirq entry
|
| 352 | *
|
| 353 | * Attach a device wakeirq to the wakeup source so the device
|
| 354 | * wake IRQ can be configured automatically for suspend and
|
| 355 | * resume.
|
| 356 | *
|
| 357 | * Call under the device's power.lock lock.
|
| 358 |
|
| 359 | void device_wakeup_attach_irq(struct device *dev,
|
| 360 | struct wake_irq *wakeirq)
|
| 361 | {
|
| 362 | struct wakeup_source *ws;
|
| 363 |
|
| 364 | ws = dev->power.wakeup;
|
| 365 | if (!ws)
|
| 366 | return;
|
| 367 |
|
| 368 | if (ws->wakeirq)
|
| 369 | dev_err(dev, "Leftover wakeup IRQ found, overriding\n");
|
| 370 |
|
| 371 | ws->wakeirq = wakeirq;
|
| 372 | }
|
| 373 |
|
| 374 | |
| 375 | * device_wakeup_detach_irq - Detach a wakeirq from a wakeup source
|
| 376 | * @dev: Device to handle
|
| 377 | *
|
| 378 | * Removes a device wakeirq from the wakeup source.
|
| 379 | *
|
| 380 | * Call under the device's power.lock lock.
|
| 381 |
|
| 382 | void device_wakeup_detach_irq(struct device *dev)
|
| 383 | {
|
| 384 | struct wakeup_source *ws;
|
| 385 |
|
| 386 | ws = dev->power.wakeup;
|
| 387 | if (ws)
|
| 388 | ws->wakeirq = NULL;
|
| 389 | }
|
| 390 |
|
| 391 | |
| 392 | * device_wakeup_arm_wake_irqs -
|
| 393 | *
|
| 394 | * Iterates over the list of device wakeirqs to arm them.
|
| 395 |
|
| 396 | void device_wakeup_arm_wake_irqs(void)
|
| 397 | {
|
| 398 | struct wakeup_source *ws;
|
| 399 | int srcuidx;
|
| 400 |
|
| 401 | srcuidx = srcu_read_lock(&wakeup_srcu);
|
| 402 | list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry)
|
| 403 | dev_pm_arm_wake_irq(ws->wakeirq);
|
| 404 | srcu_read_unlock(&wakeup_srcu, srcuidx);
|
| 405 | }
|
| 406 |
|
| 407 | |
| 408 | * device_wakeup_disarm_wake_irqs -
|
| 409 | *
|
| 410 | * Iterates over the list of device wakeirqs to disarm them.
|
| 411 |
|
| 412 | void device_wakeup_disarm_wake_irqs(void)
|
| 413 | {
|
| 414 | struct wakeup_source *ws;
|
| 415 | int srcuidx;
|
| 416 |
|
| 417 | srcuidx = srcu_read_lock(&wakeup_srcu);
|
| 418 | list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry)
|
| 419 | dev_pm_disarm_wake_irq(ws->wakeirq);
|
| 420 | srcu_read_unlock(&wakeup_srcu, srcuidx);
|
| 421 | }
|
| 422 |
|
| 423 | |
| 424 | * device_wakeup_detach - Detach a device's wakeup source object from it.
|
| 425 | * @dev: Device to detach the wakeup source object from.
|
| 426 | *
|
| 427 | * After it returns, @dev will not be treated as a wakeup device any more.
|
| 428 |
|
| 429 | static struct wakeup_source *device_wakeup_detach(struct device *dev)
|
| 430 | {
|
| 431 | struct wakeup_source *ws;
|
| 432 |
|
| 433 | spin_lock_irq(&dev->power.lock);
|
| 434 | ws = dev->power.wakeup;
|
| 435 | dev->power.wakeup = NULL;
|
| 436 | spin_unlock_irq(&dev->power.lock);
|
| 437 | return ws;
|
| 438 | }
|
| 439 |
|
| 440 | |
| 441 | * device_wakeup_disable - Do not regard a device as a wakeup source any more.
|
| 442 | * @dev: Device to handle.
|
| 443 | *
|
| 444 | * Detach the @dev's wakeup source object from it, unregister this wakeup source
|
| 445 | * object and destroy it.
|
| 446 |
|
| 447 | void device_wakeup_disable(struct device *dev)
|
| 448 | {
|
| 449 | struct wakeup_source *ws;
|
| 450 |
|
| 451 | if (!dev || !dev->power.can_wakeup)
|
| 452 | return;
|
| 453 |
|
| 454 | ws = device_wakeup_detach(dev);
|
| 455 | wakeup_source_unregister(ws);
|
| 456 | }
|
| 457 | EXPORT_SYMBOL_GPL(device_wakeup_disable);
|
| 458 |
|
| 459 | |
| 460 | * device_set_wakeup_capable - Set/reset device wakeup capability flag.
|
| 461 | * @dev: Device to handle.
|
| 462 | * @capable: Whether or not @dev is capable of waking up the system from sleep.
|
| 463 | *
|
| 464 | * If @capable is set, set the @dev's power.can_wakeup flag and add its
|
| 465 | * wakeup-related attributes to sysfs. Otherwise, unset the @dev's
|
| 466 | * power.can_wakeup flag and remove its wakeup-related attributes from sysfs.
|
| 467 | *
|
| 468 | * This function may sleep and it can't be called from any context where
|
| 469 | * sleeping is not allowed.
|
| 470 |
|
| 471 | void device_set_wakeup_capable(struct device *dev, bool capable)
|
| 472 | {
|
| 473 | if (!!dev->power.can_wakeup == !!capable)
|
| 474 | return;
|
| 475 |
|
| 476 | dev->power.can_wakeup = capable;
|
| 477 | if (device_is_registered(dev) && !list_empty(&dev->power.entry)) {
|
| 478 | if (capable) {
|
| 479 | int ret = wakeup_sysfs_add(dev);
|
| 480 |
|
| 481 | if (ret)
|
| 482 | dev_info(dev, "Wakeup sysfs attributes not added\n");
|
| 483 | } else {
|
| 484 | wakeup_sysfs_remove(dev);
|
| 485 | }
|
| 486 | }
|
| 487 | }
|
| 488 | EXPORT_SYMBOL_GPL(device_set_wakeup_capable);
|
| 489 |
|
| 490 | |
| 491 | * device_set_wakeup_enable - Enable or disable a device to wake up the system.
|
| 492 | * @dev: Device to handle.
|
| 493 | * @enable: enable/disable flag
|
| 494 |
|
| 495 | int device_set_wakeup_enable(struct device *dev, bool enable)
|
| 496 | {
|
| 497 | if (enable)
|
| 498 | return device_wakeup_enable(dev);
|
| 499 |
|
| 500 | device_wakeup_disable(dev);
|
| 501 | return 0;
|
| 502 | }
|
| 503 | EXPORT_SYMBOL_GPL(device_set_wakeup_enable);
|
| 504 |
|
| 505 | |
| 506 | * wakeup_source_not_usable - validate the given wakeup source.
|
| 507 | * @ws: Wakeup source to be validated.
|
| 508 |
|
| 509 | static bool wakeup_source_not_usable(struct wakeup_source *ws)
|
| 510 | {
|
| 511 | |
| 512 | * Use the timer struct to check if the given wakeup source has been
|
| 513 | * initialized by wakeup_source_add() and it is not going away.
|
| 514 |
|
| 515 | return ws->timer.function != pm_wakeup_timer_fn;
|
| 516 | }
|
| 517 |
|
| 518 | |
| 519 | * The functions below use the observation that each wakeup event starts a
|
| 520 | * period in which the system should not be suspended. The moment this period
|
| 521 | * will end depends on how the wakeup event is going to be processed after being
|
| 522 | * detected and all of the possible cases can be divided into two distinct
|
| 523 | * groups.
|
| 524 | *
|
| 525 | * First, a wakeup event may be detected by the same functional unit that will
|
| 526 | * carry out the entire processing of it and possibly will pass it to user space
|
| 527 | * for further processing. In that case the functional unit that has detected
|
| 528 | * the event may later "close" the "no suspend" period associated with it
|
| 529 | * directly as soon as it has been dealt with. The pair of pm_stay_awake() and
|
| 530 | * pm_relax(), balanced with each other, is supposed to be used in such
|
| 531 | * situations.
|
| 532 | *
|
| 533 | * Second, a wakeup event may be detected by one functional unit and processed
|
| 534 | * by another one. In that case the unit that has detected it cannot really
|
| 535 | * "close" the "no suspend" period associated with it, unless it knows in
|
| 536 | * advance what's going to happen to the event during processing. This
|
| 537 | * knowledge, however, may not be available to it, so it can simply specify time
|
| 538 | * to wait before the system can be suspended and pass it as the second
|
| 539 | * argument of pm_wakeup_event().
|
| 540 | *
|
| 541 | * It is valid to call pm_relax() after pm_wakeup_event(), in which case the
|
| 542 | * "no suspend" period will be ended either by the pm_relax(), or by the timer
|
| 543 | * function executed when the timer expires, whichever comes first.
|
| 544 |
|
| 545 |
|
| 546 | |
| 547 | * wakeup_source_activate - Mark given wakeup source as active.
|
| 548 | * @ws: Wakeup source to handle.
|
| 549 | *
|
| 550 | * Update the @ws' statistics and, if @ws has just been activated, notify the PM
|
| 551 | * core of the event by incrementing the counter of the wakeup events being
|
| 552 | * processed.
|
| 553 |
|
| 554 | static void wakeup_source_activate(struct wakeup_source *ws)
|
| 555 | {
|
| 556 | unsigned int cec;
|
| 557 |
|
| 558 | if (WARN_ONCE(wakeup_source_not_usable(ws), "unusable wakeup source\n"))
|
| 559 | return;
|
| 560 |
|
| 561 | ws->active = true;
|
| 562 | ws->active_count++;
|
| 563 | ws->last_time = ktime_get();
|
| 564 | if (ws->autosleep_enabled)
|
| 565 | ws->start_prevent_time = ws->last_time;
|
| 566 |
|
| 567 |
|
| 568 | cec = atomic_inc_return(&combined_event_count);
|
| 569 |
|
| 570 | trace_wakeup_source_activate(ws->name, cec);
|
| 571 | }
|
| 572 |
|
| 573 | |
| 574 | * wakeup_source_report_event - Report wakeup event using the given source.
|
| 575 | * @ws: Wakeup source to report the event for.
|
| 576 | * @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
|
| 577 |
|
| 578 | static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
|
| 579 | {
|
| 580 | ws->event_count++;
|
| 581 |
|
| 582 | if (events_check_enabled)
|
| 583 | ws->wakeup_count++;
|
| 584 |
|
| 585 | if (!ws->active)
|
| 586 | wakeup_source_activate(ws);
|
| 587 |
|
| 588 | if (hard)
|
| 589 | pm_system_wakeup();
|
| 590 | }
|
| 591 |
|
| 592 | |
| 593 | * __pm_stay_awake - Notify the PM core of a wakeup event.
|
| 594 | * @ws: Wakeup source object associated with the source of the event.
|
| 595 | *
|
| 596 | * It is safe to call this function from interrupt context.
|
| 597 |
|
| 598 | void __pm_stay_awake(struct wakeup_source *ws)
|
| 599 | {
|
| 600 | unsigned long flags;
|
| 601 |
|
| 602 | if (!ws)
|
| 603 | return;
|
| 604 |
|
| 605 | spin_lock_irqsave(&ws->lock, flags);
|
| 606 |
|
| 607 | wakeup_source_report_event(ws, false);
|
| 608 | timer_delete(&ws->timer);
|
| 609 | ws->timer_expires = 0;
|
| 610 |
|
| 611 | spin_unlock_irqrestore(&ws->lock, flags);
|
| 612 | }
|
| 613 | EXPORT_SYMBOL_GPL(__pm_stay_awake);
|
| 614 |
|
| 615 | |
| 616 | * pm_stay_awake - Notify the PM core that a wakeup event is being processed.
|
| 617 | * @dev: Device the wakeup event is related to.
|
| 618 | *
|
| 619 | * Notify the PM core of a wakeup event (signaled by @dev) by calling
|
| 620 | * __pm_stay_awake for the @dev's wakeup source object.
|
| 621 | *
|
| 622 | * Call this function after detecting of a wakeup event if pm_relax() is going
|
| 623 | * to be called directly after processing the event (and possibly passing it to
|
| 624 | * user space for further processing).
|
| 625 |
|
| 626 | void pm_stay_awake(struct device *dev)
|
| 627 | {
|
| 628 | unsigned long flags;
|
| 629 |
|
| 630 | if (!dev)
|
| 631 | return;
|
| 632 |
|
| 633 | spin_lock_irqsave(&dev->power.lock, flags);
|
| 634 | __pm_stay_awake(dev->power.wakeup);
|
| 635 | spin_unlock_irqrestore(&dev->power.lock, flags);
|
| 636 | }
|
| 637 | EXPORT_SYMBOL_GPL(pm_stay_awake);
|
| 638 |
|
| 639 | #ifdef CONFIG_PM_AUTOSLEEP
|
| 640 | static void update_prevent_sleep_time(struct wakeup_source *ws, ktime_t now)
|
| 641 | {
|
| 642 | ktime_t delta = ktime_sub(now, ws->start_prevent_time);
|
| 643 | ws->prevent_sleep_time = ktime_add(ws->prevent_sleep_time, delta);
|
| 644 | }
|
| 645 | #else
|
| 646 | static inline void update_prevent_sleep_time(struct wakeup_source *ws,
|
| 647 | ktime_t now) {}
|
| 648 | #endif
|
| 649 |
|
| 650 | |
| 651 | * wakeup_source_deactivate - Mark given wakeup source as inactive.
|
| 652 | * @ws: Wakeup source to handle.
|
| 653 | *
|
| 654 | * Update the @ws' statistics and notify the PM core that the wakeup source has
|
| 655 | * become inactive by decrementing the counter of wakeup events being processed
|
| 656 | * and incrementing the counter of registered wakeup events.
|
| 657 |
|
| 658 | static void wakeup_source_deactivate(struct wakeup_source *ws)
|
| 659 | {
|
| 660 | unsigned int cnt, inpr, cec;
|
| 661 | ktime_t duration;
|
| 662 | ktime_t now;
|
| 663 |
|
| 664 | ws->relax_count++;
|
| 665 | |
| 666 | * __pm_relax() may be called directly or from a timer function.
|
| 667 | * If it is called directly right after the timer function has been
|
| 668 | * started, but before the timer function calls __pm_relax(), it is
|
| 669 | * possible that __pm_stay_awake() will be called in the meantime and
|
| 670 | * will set ws->active. Then, ws->active may be cleared immediately
|
| 671 | * by the __pm_relax() called from the timer function, but in such a
|
| 672 | * case ws->relax_count will be different from ws->active_count.
|
| 673 |
|
| 674 | if (ws->relax_count != ws->active_count) {
|
| 675 | ws->relax_count--;
|
| 676 | return;
|
| 677 | }
|
| 678 |
|
| 679 | ws->active = false;
|
| 680 |
|
| 681 | now = ktime_get();
|
| 682 | duration = ktime_sub(now, ws->last_time);
|
| 683 | ws->total_time = ktime_add(ws->total_time, duration);
|
| 684 | if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
|
| 685 | ws->max_time = duration;
|
| 686 |
|
| 687 | ws->last_time = now;
|
| 688 | timer_delete(&ws->timer);
|
| 689 | ws->timer_expires = 0;
|
| 690 |
|
| 691 | if (ws->autosleep_enabled)
|
| 692 | update_prevent_sleep_time(ws, now);
|
| 693 |
|
| 694 | |
| 695 | * Increment the counter of registered wakeup events and decrement the
|
| 696 | * counter of wakeup events in progress simultaneously.
|
| 697 |
|
| 698 | cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count);
|
| 699 | trace_wakeup_source_deactivate(ws->name, cec);
|
| 700 |
|
| 701 | split_counters(&cnt, &inpr);
|
| 702 | if (!inpr && waitqueue_active(&wakeup_count_wait_queue))
|
| 703 | wake_up(&wakeup_count_wait_queue);
|
| 704 | }
|
| 705 |
|
| 706 | |
| 707 | * __pm_relax - Notify the PM core that processing of a wakeup event has ended.
|
| 708 | * @ws: Wakeup source object associated with the source of the event.
|
| 709 | *
|
| 710 | * Call this function for wakeup events whose processing started with calling
|
| 711 | * __pm_stay_awake().
|
| 712 | *
|
| 713 | * It is safe to call it from interrupt context.
|
| 714 |
|
| 715 | void __pm_relax(struct wakeup_source *ws)
|
| 716 | {
|
| 717 | unsigned long flags;
|
| 718 |
|
| 719 | if (!ws)
|
| 720 | return;
|
| 721 |
|
| 722 | spin_lock_irqsave(&ws->lock, flags);
|
| 723 | if (ws->active)
|
| 724 | wakeup_source_deactivate(ws);
|
| 725 | spin_unlock_irqrestore(&ws->lock, flags);
|
| 726 | }
|
| 727 | EXPORT_SYMBOL_GPL(__pm_relax);
|
| 728 |
|
| 729 | |
| 730 | * pm_relax - Notify the PM core that processing of a wakeup event has ended.
|
| 731 | * @dev: Device that signaled the event.
|
| 732 | *
|
| 733 | * Execute __pm_relax() for the @dev's wakeup source object.
|
| 734 |
|
| 735 | void pm_relax(struct device *dev)
|
| 736 | {
|
| 737 | unsigned long flags;
|
| 738 |
|
| 739 | if (!dev)
|
| 740 | return;
|
| 741 |
|
| 742 | spin_lock_irqsave(&dev->power.lock, flags);
|
| 743 | __pm_relax(dev->power.wakeup);
|
| 744 | spin_unlock_irqrestore(&dev->power.lock, flags);
|
| 745 | }
|
| 746 | EXPORT_SYMBOL_GPL(pm_relax);
|
| 747 |
|
| 748 | |
| 749 | * pm_wakeup_timer_fn - Delayed finalization of a wakeup event.
|
| 750 | * @t: timer list
|
| 751 | *
|
| 752 | * Call wakeup_source_deactivate() for the wakeup source whose address is stored
|
| 753 | * in @data if it is currently active and its timer has not been canceled and
|
| 754 | * the expiration time of the timer is not in future.
|
| 755 |
|
| 756 | static void pm_wakeup_timer_fn(struct timer_list *t)
|
| 757 | {
|
| 758 | struct wakeup_source *ws = timer_container_of(ws, t, timer);
|
| 759 | unsigned long flags;
|
| 760 |
|
| 761 | spin_lock_irqsave(&ws->lock, flags);
|
| 762 |
|
| 763 | if (ws->active && ws->timer_expires
|
| 764 | && time_after_eq(jiffies, ws->timer_expires)) {
|
| 765 | wakeup_source_deactivate(ws);
|
| 766 | ws->expire_count++;
|
| 767 | }
|
| 768 |
|
| 769 | spin_unlock_irqrestore(&ws->lock, flags);
|
| 770 | }
|
| 771 |
|
| 772 | |
| 773 | * pm_wakeup_ws_event - Notify the PM core of a wakeup event.
|
| 774 | * @ws: Wakeup source object associated with the event source.
|
| 775 | * @msec: Anticipated event processing time (in milliseconds).
|
| 776 | * @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
|
| 777 | *
|
| 778 | * Notify the PM core of a wakeup event whose source is @ws that will take
|
| 779 | * approximately @msec milliseconds to be processed by the kernel. If @ws is
|
| 780 | * not active, activate it. If @msec is nonzero, set up the @ws' timer to
|
| 781 | * execute pm_wakeup_timer_fn() in future.
|
| 782 | *
|
| 783 | * It is safe to call this function from interrupt context.
|
| 784 |
|
| 785 | void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard)
|
| 786 | {
|
| 787 | unsigned long flags;
|
| 788 | unsigned long expires;
|
| 789 |
|
| 790 | if (!ws)
|
| 791 | return;
|
| 792 |
|
| 793 | spin_lock_irqsave(&ws->lock, flags);
|
| 794 |
|
| 795 | wakeup_source_report_event(ws, hard);
|
| 796 |
|
| 797 | if (!msec) {
|
| 798 | wakeup_source_deactivate(ws);
|
| 799 | goto unlock;
|
| 800 | }
|
| 801 |
|
| 802 | expires = jiffies + msecs_to_jiffies(msec);
|
| 803 | if (!expires)
|
| 804 | expires = 1;
|
| 805 |
|
| 806 | if (!ws->timer_expires || time_after(expires, ws->timer_expires)) {
|
| 807 | mod_timer(&ws->timer, expires);
|
| 808 | ws->timer_expires = expires;
|
| 809 | }
|
| 810 |
|
| 811 | unlock:
|
| 812 | spin_unlock_irqrestore(&ws->lock, flags);
|
| 813 | }
|
| 814 | EXPORT_SYMBOL_GPL(pm_wakeup_ws_event);
|
| 815 |
|
| 816 | |
| 817 | * pm_wakeup_dev_event - Notify the PM core of a wakeup event.
|
| 818 | * @dev: Device the wakeup event is related to.
|
| 819 | * @msec: Anticipated event processing time (in milliseconds).
|
| 820 | * @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
|
| 821 | *
|
| 822 | * Call pm_wakeup_ws_event() for the @dev's wakeup source object.
|
| 823 |
|
| 824 | void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard)
|
| 825 | {
|
| 826 | unsigned long flags;
|
| 827 |
|
| 828 | if (!dev)
|
| 829 | return;
|
| 830 |
|
| 831 | spin_lock_irqsave(&dev->power.lock, flags);
|
| 832 | pm_wakeup_ws_event(dev->power.wakeup, msec, hard);
|
| 833 | spin_unlock_irqrestore(&dev->power.lock, flags);
|
| 834 | }
|
| 835 | EXPORT_SYMBOL_GPL(pm_wakeup_dev_event);
|
| 836 |
|
| 837 | void pm_print_active_wakeup_sources(void)
|
| 838 | {
|
| 839 | struct wakeup_source *ws;
|
| 840 | int srcuidx, active = 0;
|
| 841 | struct wakeup_source *last_activity_ws = NULL;
|
| 842 |
|
| 843 | srcuidx = srcu_read_lock(&wakeup_srcu);
|
| 844 | list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) {
|
| 845 | if (ws->active) {
|
| 846 | pm_pr_dbg("active wakeup source: %s\n", ws->name);
|
| 847 | active = 1;
|
| 848 | } else if (!active &&
|
| 849 | (!last_activity_ws ||
|
| 850 | ktime_to_ns(ws->last_time) >
|
| 851 | ktime_to_ns(last_activity_ws->last_time))) {
|
| 852 | last_activity_ws = ws;
|
| 853 | }
|
| 854 | }
|
| 855 |
|
| 856 | if (!active && last_activity_ws)
|
| 857 | pm_pr_dbg("last active wakeup source: %s\n",
|
| 858 | last_activity_ws->name);
|
| 859 | srcu_read_unlock(&wakeup_srcu, srcuidx);
|
| 860 | }
|
| 861 | EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources);
|
| 862 |
|
| 863 | |
| 864 | * pm_wakeup_pending - Check if power transition in progress should be aborted.
|
| 865 | *
|
| 866 | * Compare the current number of registered wakeup events with its preserved
|
| 867 | * value from the past and return true if new wakeup events have been registered
|
| 868 | * since the old value was stored. Also return true if the current number of
|
| 869 | * wakeup events being processed is different from zero.
|
| 870 |
|
| 871 | bool pm_wakeup_pending(void)
|
| 872 | {
|
| 873 | unsigned long flags;
|
| 874 | bool ret = false;
|
| 875 |
|
| 876 | raw_spin_lock_irqsave(&events_lock, flags);
|
| 877 | if (events_check_enabled) {
|
| 878 | unsigned int cnt, inpr;
|
| 879 |
|
| 880 | split_counters(&cnt, &inpr);
|
| 881 | ret = (cnt != saved_count || inpr > 0);
|
| 882 | events_check_enabled = !ret;
|
| 883 | }
|
| 884 | raw_spin_unlock_irqrestore(&events_lock, flags);
|
| 885 |
|
| 886 | if (ret) {
|
| 887 | pm_pr_dbg("Wakeup pending, aborting suspend\n");
|
| 888 | pm_print_active_wakeup_sources();
|
| 889 | }
|
| 890 |
|
| 891 | return ret || atomic_read(&pm_abort_suspend) > 0;
|
| 892 | }
|
| 893 | EXPORT_SYMBOL_GPL(pm_wakeup_pending);
|
| 894 |
|
| 895 | void pm_system_wakeup(void)
|
| 896 | {
|
| 897 | atomic_inc(&pm_abort_suspend);
|
| 898 | s2idle_wake();
|
| 899 | }
|
| 900 | EXPORT_SYMBOL_GPL(pm_system_wakeup);
|
| 901 |
|
| 902 | void pm_system_cancel_wakeup(void)
|
| 903 | {
|
| 904 | atomic_dec_if_positive(&pm_abort_suspend);
|
| 905 | }
|
| 906 |
|
| 907 | void pm_wakeup_clear(unsigned int irq_number)
|
| 908 | {
|
| 909 | raw_spin_lock_irq(&wakeup_irq_lock);
|
| 910 |
|
| 911 | if (irq_number && wakeup_irq[0] == irq_number)
|
| 912 | wakeup_irq[0] = wakeup_irq[1];
|
| 913 | else
|
| 914 | wakeup_irq[0] = 0;
|
| 915 |
|
| 916 | wakeup_irq[1] = 0;
|
| 917 |
|
| 918 | raw_spin_unlock_irq(&wakeup_irq_lock);
|
| 919 |
|
| 920 | if (!irq_number)
|
| 921 | atomic_set(&pm_abort_suspend, 0);
|
| 922 | }
|
| 923 |
|
| 924 | void pm_system_irq_wakeup(unsigned int irq_number)
|
| 925 | {
|
| 926 | unsigned long flags;
|
| 927 |
|
| 928 | raw_spin_lock_irqsave(&wakeup_irq_lock, flags);
|
| 929 |
|
| 930 | if (wakeup_irq[0] == 0)
|
| 931 | wakeup_irq[0] = irq_number;
|
| 932 | else if (wakeup_irq[1] == 0)
|
| 933 | wakeup_irq[1] = irq_number;
|
| 934 | else
|
| 935 | irq_number = 0;
|
| 936 |
|
| 937 | pm_pr_dbg("Triggering wakeup from IRQ %d\n", irq_number);
|
| 938 |
|
| 939 | raw_spin_unlock_irqrestore(&wakeup_irq_lock, flags);
|
| 940 |
|
| 941 | if (irq_number)
|
| 942 | pm_system_wakeup();
|
| 943 | }
|
| 944 |
|
| 945 | unsigned int pm_wakeup_irq(void)
|
| 946 | {
|
| 947 | return wakeup_irq[0];
|
| 948 | }
|
| 949 |
|
| 950 | |
| 951 | * pm_get_wakeup_count - Read the number of registered wakeup events.
|
| 952 | * @count: Address to store the value at.
|
| 953 | * @block: Whether or not to block.
|
| 954 | *
|
| 955 | * Store the number of registered wakeup events at the address in @count. If
|
| 956 | * @block is set, block until the current number of wakeup events being
|
| 957 | * processed is zero.
|
| 958 | *
|
| 959 | * Return 'false' if the current number of wakeup events being processed is
|
| 960 | * nonzero. Otherwise return 'true'.
|
| 961 |
|
| 962 | bool pm_get_wakeup_count(unsigned int *count, bool block)
|
| 963 | {
|
| 964 | unsigned int cnt, inpr;
|
| 965 |
|
| 966 | if (block) {
|
| 967 | DEFINE_WAIT(wait);
|
| 968 |
|
| 969 | for (;;) {
|
| 970 | prepare_to_wait(&wakeup_count_wait_queue, &wait,
|
| 971 | TASK_INTERRUPTIBLE);
|
| 972 | split_counters(&cnt, &inpr);
|
| 973 | if (inpr == 0 || signal_pending(current))
|
| 974 | break;
|
| 975 | pm_print_active_wakeup_sources();
|
| 976 | schedule();
|
| 977 | }
|
| 978 | finish_wait(&wakeup_count_wait_queue, &wait);
|
| 979 | }
|
| 980 |
|
| 981 | split_counters(&cnt, &inpr);
|
| 982 | *count = cnt;
|
| 983 | return !inpr;
|
| 984 | }
|
| 985 |
|
| 986 | |
| 987 | * pm_save_wakeup_count - Save the current number of registered wakeup events.
|
| 988 | * @count: Value to compare with the current number of registered wakeup events.
|
| 989 | *
|
| 990 | * If @count is equal to the current number of registered wakeup events and the
|
| 991 | * current number of wakeup events being processed is zero, store @count as the
|
| 992 | * old number of registered wakeup events for pm_check_wakeup_events(), enable
|
| 993 | * wakeup events detection and return 'true'. Otherwise disable wakeup events
|
| 994 | * detection and return 'false'.
|
| 995 |
|
| 996 | bool pm_save_wakeup_count(unsigned int count)
|
| 997 | {
|
| 998 | unsigned int cnt, inpr;
|
| 999 | unsigned long flags;
|
| 1000 |
|
| 1001 | events_check_enabled = false;
|
| 1002 | raw_spin_lock_irqsave(&events_lock, flags);
|
| 1003 | split_counters(&cnt, &inpr);
|
| 1004 | if (cnt == count && inpr == 0) {
|
| 1005 | saved_count = count;
|
| 1006 | events_check_enabled = true;
|
| 1007 | }
|
| 1008 | raw_spin_unlock_irqrestore(&events_lock, flags);
|
| 1009 | return events_check_enabled;
|
| 1010 | }
|
| 1011 |
|
| 1012 | #ifdef CONFIG_PM_AUTOSLEEP
|
| 1013 | |
| 1014 | * pm_wakep_autosleep_enabled - Modify autosleep_enabled for all wakeup sources.
|
| 1015 | * @set: Whether to set or to clear the autosleep_enabled flags.
|
| 1016 |
|
| 1017 | void pm_wakep_autosleep_enabled(bool set)
|
| 1018 | {
|
| 1019 | struct wakeup_source *ws;
|
| 1020 | ktime_t now = ktime_get();
|
| 1021 | int srcuidx;
|
| 1022 |
|
| 1023 | srcuidx = srcu_read_lock(&wakeup_srcu);
|
| 1024 | list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) {
|
| 1025 | spin_lock_irq(&ws->lock);
|
| 1026 | if (ws->autosleep_enabled != set) {
|
| 1027 | ws->autosleep_enabled = set;
|
| 1028 | if (ws->active) {
|
| 1029 | if (set)
|
| 1030 | ws->start_prevent_time = now;
|
| 1031 | else
|
| 1032 | update_prevent_sleep_time(ws, now);
|
| 1033 | }
|
| 1034 | }
|
| 1035 | spin_unlock_irq(&ws->lock);
|
| 1036 | }
|
| 1037 | srcu_read_unlock(&wakeup_srcu, srcuidx);
|
| 1038 | }
|
| 1039 | #endif
|
| 1040 |
|
| 1041 | |
| 1042 | * print_wakeup_source_stats - Print wakeup source statistics information.
|
| 1043 | * @m: seq_file to print the statistics into.
|
| 1044 | * @ws: Wakeup source object to print the statistics for.
|
| 1045 |
|
| 1046 | static int print_wakeup_source_stats(struct seq_file *m,
|
| 1047 | struct wakeup_source *ws)
|
| 1048 | {
|
| 1049 | unsigned long flags;
|
| 1050 | ktime_t total_time;
|
| 1051 | ktime_t max_time;
|
| 1052 | unsigned long active_count;
|
| 1053 | ktime_t active_time;
|
| 1054 | ktime_t prevent_sleep_time;
|
| 1055 |
|
| 1056 | spin_lock_irqsave(&ws->lock, flags);
|
| 1057 |
|
| 1058 | total_time = ws->total_time;
|
| 1059 | max_time = ws->max_time;
|
| 1060 | prevent_sleep_time = ws->prevent_sleep_time;
|
| 1061 | active_count = ws->active_count;
|
| 1062 | if (ws->active) {
|
| 1063 | ktime_t now = ktime_get();
|
| 1064 |
|
| 1065 | active_time = ktime_sub(now, ws->last_time);
|
| 1066 | total_time = ktime_add(total_time, active_time);
|
| 1067 | if (active_time > max_time)
|
| 1068 | max_time = active_time;
|
| 1069 |
|
| 1070 | if (ws->autosleep_enabled)
|
| 1071 | prevent_sleep_time = ktime_add(prevent_sleep_time,
|
| 1072 | ktime_sub(now, ws->start_prevent_time));
|
| 1073 | } else {
|
| 1074 | active_time = 0;
|
| 1075 | }
|
| 1076 |
|
| 1077 | seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%lld\t\t%lld\t\t%lld\t\t%lld\t\t%lld\n",
|
| 1078 | ws->name, active_count, ws->event_count,
|
| 1079 | ws->wakeup_count, ws->expire_count,
|
| 1080 | ktime_to_ms(active_time), ktime_to_ms(total_time),
|
| 1081 | ktime_to_ms(max_time), ktime_to_ms(ws->last_time),
|
| 1082 | ktime_to_ms(prevent_sleep_time));
|
| 1083 |
|
| 1084 | spin_unlock_irqrestore(&ws->lock, flags);
|
| 1085 |
|
| 1086 | return 0;
|
| 1087 | }
|
| 1088 |
|
| 1089 | static void *wakeup_sources_stats_seq_start(struct seq_file *m,
|
| 1090 | loff_t *pos)
|
| 1091 | {
|
| 1092 | struct wakeup_source *ws;
|
| 1093 | loff_t n = *pos;
|
| 1094 | int *srcuidx = m->private;
|
| 1095 |
|
| 1096 | if (n == 0) {
|
| 1097 | seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
|
| 1098 | "expire_count\tactive_since\ttotal_time\tmax_time\t"
|
| 1099 | "last_change\tprevent_suspend_time\n");
|
| 1100 | }
|
| 1101 |
|
| 1102 | *srcuidx = srcu_read_lock(&wakeup_srcu);
|
| 1103 | list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) {
|
| 1104 | if (n-- <= 0)
|
| 1105 | return ws;
|
| 1106 | }
|
| 1107 |
|
| 1108 | return NULL;
|
| 1109 | }
|
| 1110 |
|
| 1111 | static void *wakeup_sources_stats_seq_next(struct seq_file *m,
|
| 1112 | void *v, loff_t *pos)
|
| 1113 | {
|
| 1114 | struct wakeup_source *ws = v;
|
| 1115 | struct wakeup_source *next_ws = NULL;
|
| 1116 |
|
| 1117 | ++(*pos);
|
| 1118 |
|
| 1119 | list_for_each_entry_continue_rcu(ws, &wakeup_sources, entry) {
|
| 1120 | next_ws = ws;
|
| 1121 | break;
|
| 1122 | }
|
| 1123 |
|
| 1124 | if (!next_ws)
|
| 1125 | print_wakeup_source_stats(m, &deleted_ws);
|
| 1126 |
|
| 1127 | return next_ws;
|
| 1128 | }
|
| 1129 |
|
| 1130 | static void wakeup_sources_stats_seq_stop(struct seq_file *m, void *v)
|
| 1131 | {
|
| 1132 | int *srcuidx = m->private;
|
| 1133 |
|
| 1134 | srcu_read_unlock(&wakeup_srcu, *srcuidx);
|
| 1135 | }
|
| 1136 |
|
| 1137 | |
| 1138 | * wakeup_sources_stats_seq_show - Print wakeup sources statistics information.
|
| 1139 | * @m: seq_file to print the statistics into.
|
| 1140 | * @v: wakeup_source of each iteration
|
| 1141 |
|
| 1142 | static int wakeup_sources_stats_seq_show(struct seq_file *m, void *v)
|
| 1143 | {
|
| 1144 | struct wakeup_source *ws = v;
|
| 1145 |
|
| 1146 | print_wakeup_source_stats(m, ws);
|
| 1147 |
|
| 1148 | return 0;
|
| 1149 | }
|
| 1150 |
|
| 1151 | static const struct seq_operations wakeup_sources_stats_seq_ops = {
|
| 1152 | .start = wakeup_sources_stats_seq_start,
|
| 1153 | .next = wakeup_sources_stats_seq_next,
|
| 1154 | .stop = wakeup_sources_stats_seq_stop,
|
| 1155 | .show = wakeup_sources_stats_seq_show,
|
| 1156 | };
|
| 1157 |
|
| 1158 | static int wakeup_sources_stats_open(struct inode *inode, struct file *file)
|
| 1159 | {
|
| 1160 | return seq_open_private(file, &wakeup_sources_stats_seq_ops, sizeof(int));
|
| 1161 | }
|
| 1162 |
|
| 1163 | static const struct file_operations wakeup_sources_stats_fops = {
|
| 1164 | .owner = THIS_MODULE,
|
| 1165 | .open = wakeup_sources_stats_open,
|
| 1166 | .read = seq_read,
|
| 1167 | .llseek = seq_lseek,
|
| 1168 | .release = seq_release_private,
|
| 1169 | };
|
| 1170 |
|
| 1171 | #ifdef CONFIG_BPF_SYSCALL
|
| 1172 | #include <linux/btf.h>
|
| 1173 |
|
| 1174 | __bpf_kfunc_start_defs();
|
| 1175 |
|
| 1176 | |
| 1177 | * bpf_wakeup_sources_read_lock - Acquire the SRCU lock for wakeup sources
|
| 1178 | *
|
| 1179 | * The underlying SRCU lock returns an integer index. However, the BPF verifier
|
| 1180 | * requires a pointer (PTR_TO_BTF_ID) to strictly track the state of acquired
|
| 1181 | * resources using KF_ACQUIRE and KF_RELEASE semantics. We use an opaque
|
| 1182 | * structure pointer (struct bpf_ws_lock *) to satisfy the verifier while
|
| 1183 | * safely encoding the integer index within the pointer address itself.
|
| 1184 | *
|
| 1185 | * Return: An opaque pointer encoding the SRCU lock index + 1 (to avoid NULL).
|
| 1186 |
|
| 1187 | __bpf_kfunc struct bpf_ws_lock *bpf_wakeup_sources_read_lock(void)
|
| 1188 | {
|
| 1189 | return (struct bpf_ws_lock *)(long)(wakeup_sources_read_lock() + 1);
|
| 1190 | }
|
| 1191 |
|
| 1192 | |
| 1193 | * bpf_wakeup_sources_read_unlock - Release the SRCU lock for wakeup sources
|
| 1194 | * @lock: The opaque pointer returned by bpf_wakeup_sources_read_lock()
|
| 1195 | *
|
| 1196 | * The BPF verifier guarantees that @lock is a valid, unreleased pointer from
|
| 1197 | * the acquire function. We decode the pointer back into the integer SRCU index
|
| 1198 | * by subtracting 1 and release the lock.
|
| 1199 |
|
| 1200 | __bpf_kfunc void bpf_wakeup_sources_read_unlock(struct bpf_ws_lock *lock)
|
| 1201 | {
|
| 1202 | wakeup_sources_read_unlock((int)(long)lock - 1);
|
| 1203 | }
|
| 1204 |
|
| 1205 | |
| 1206 | * bpf_wakeup_sources_get_head - Get the head of the wakeup sources list
|
| 1207 | *
|
| 1208 | * Return: The head of the wakeup sources list.
|
| 1209 |
|
| 1210 | __bpf_kfunc void *bpf_wakeup_sources_get_head(void)
|
| 1211 | {
|
| 1212 | return &wakeup_sources;
|
| 1213 | }
|
| 1214 |
|
| 1215 | __bpf_kfunc_end_defs();
|
| 1216 |
|
| 1217 | BTF_KFUNCS_START(wakeup_source_kfunc_ids)
|
| 1218 | BTF_ID_FLAGS(func, bpf_wakeup_sources_read_lock, KF_ACQUIRE)
|
| 1219 | BTF_ID_FLAGS(func, bpf_wakeup_sources_read_unlock, KF_RELEASE)
|
| 1220 | BTF_ID_FLAGS(func, bpf_wakeup_sources_get_head)
|
| 1221 | BTF_KFUNCS_END(wakeup_source_kfunc_ids)
|
| 1222 |
|
| 1223 | static const struct btf_kfunc_id_set wakeup_source_kfunc_set = {
|
| 1224 | .set = &wakeup_source_kfunc_ids,
|
| 1225 | };
|
| 1226 |
|
| 1227 | static void __init wakeup_sources_bpf_init(void)
|
| 1228 | {
|
| 1229 | if (register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &wakeup_source_kfunc_set))
|
| 1230 | pm_pr_dbg("Wakeup: failed to register BTF kfuncs\n");
|
| 1231 | }
|
| 1232 | #else
|
| 1233 | static inline void wakeup_sources_bpf_init(void) {}
|
| 1234 | #endif
|
| 1235 |
|
| 1236 | static int __init wakeup_sources_init(void)
|
| 1237 | {
|
| 1238 | debugfs_create_file("wakeup_sources", 0444, NULL, NULL,
|
| 1239 | &wakeup_sources_stats_fops);
|
| 1240 | wakeup_sources_bpf_init();
|
| 1241 |
|
| 1242 | return 0;
|
| 1243 | }
|
| 1244 |
|
| 1245 | postcore_initcall(wakeup_sources_init);
|