Linux suspend / resume process in Android
The Linux suspend / resume process in Android starts with suspend in the Linux kernel. Whether you use echo MEM > / sys / power / state or use the power key already owned by your development board, you can realize the function of entering suspend. This is the basis of suspend, that is, the opportunity to control the system to execute suspend. I believe you can understand it here, No more explanation.
So how does suspend start to execute step by step when it gets the opportunity to execute? Start the power management journey of our system now:
Let's look at it through echo MEM > / sys / power / state, which is easier to understand. The state under / sys / power can't be justified as a driver. Let's see where the state is created
kernel/kernel/power/suspend.c
Invalid Sign
Invalid Sign
core_ initcall(pm_init); This code is rare but important. What I care about is that it does create a power directory under the sys directory for us. Then, when returning, it creates many interfaces, one of which is state. The following is the interface definition
Invalid Sign
Invalid Sign
static struct attribute_ group attr_ group = { .attrs = g, }; You can see these interfaces above
We call our interface function state in echo MEM > / sys / power / state_ Store and suspend have just begun to take the first step
Invalid Sign
static ssize_ t state_ store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { #ifdef CONfig_SUSPEND #ifdef CONfig_EARLYSUSPEND suspend_state_t state = PM_SUSPEND_ON; #else suspend_state_t state = PM_SUSPEND_STANDBY; #endif const char * const *s; #endif char *p; int len; int error = -EINVAL;
p = memchr(buf, '\n', n); len = p ? p - buf : n;
Invalid Sign
Invalid Sign
Exit: return error ? error : n; } Here we echo MEM > / sys / power / state, and another echo on > / sys / power / state, followed by state_ Store enter reauest_ suspend_ State (state), and then enter late if it is on_ resume_ Work (main_wake_lock will be applied to the system before late_resume_work). If it is MEM, enter early_ suspend_ work。
reauest_ suspend_ State function path: kernel / kernel / power / earlysuspend. C
Invalid Sign
void request_ suspend_ state(suspend_state_t new_state) { unsigned long irqflags; int old_sleep;
Invalid Sign
Invalid Sign
This is the calling method of a work queue. Find early_ suspend_ Definition of work
static DECLARE_ WORK(early_suspend_work, early_suspend);
There are work queue methods here. I don't know. I need to see them myself, so the final call here is actually early_ Suspend this method
Invalid Sign
static void early_ suspend(struct work_struct *work) { struct early_suspend *pos; unsigned long irqflags; int abort = 0;
Invalid Sign
Invalid Sign
Invalid Sign
Invalid Sign
Invalid Sign
early_ The suspend () function will traverse early_ suspend_ Handlers, execute early in turn_ Suspend function, execute all early_ After suspend, release main_ wake_ Lock, enter wake_ Unlock function.
Invalid Sign
Let's talk about it here. This main_ wake_ What is lock? Path: kernel / kernel / power / wakelock. C
struct wake_ lock main_ wake_ lock;
Look at his initialization
Invalid Sign
Invalid Sign
First initialize, then lock and wait for unlock
For a lock, enter wake_ Unlock, first delete the lock from the original linked list (active_wake_locks), and then add inactive_ Locks in the linked list.
Invalid Sign
Invalid Sign
Invalid Sign
It's another work queue. Look at its definition and find its processing process
static DECLARE_ WORK(suspend_work, suspend);
So what he really does is suspend
Invalid Sign
static void suspend(struct work_struct *work) { int ret; int entry_event_num; struct timespec ts_entry, ts_exit;
Invalid Sign
Invalid Sign
Invalid Sign
Invalid Sign
if (suspend_short_count == SUSPEND_BACKOFF_THRESHOLD) { suspend_backoff(); suspend_short_count = 0; } } else { suspend_short_count = 0; }
Invalid Sign
In the suspend function, PM_ Suspend (requested_suspend_state) enters the suspend operation. There is also a wake-up operation in this. You can jump out of PM only after waking up_ Suspend, log: suspend: exit suspend, RET = PM will be printed after jumping out_ Suspend is to judge whether the incoming state complies with suspend, and call enter if it does_ State (state) has not entered the Linux standard suspend process until now.
pm_ Path to suspend: kernel / kernel / power / suspend. C
Invalid Sign
Invalid Sign
Invalid Sign
/** * enter_ state - Do common work of entering low-power state. * @state: pm_ state structure for state we're entering. * * Make sure we're the only ones trying to enter a sleep state. Fail * if someone has beat us to it, since we don't want anything weird to * happen when we wake up. * Then, do the setup for suspend, enter the state, and cleaup (after * we've woken up). */ int enter_ state(suspend_state_t state) { int error;
if (!valid_state(state)) return -ENODEV;
Invalid Sign
printk(KERN_INFO "PM: Syncing filesystems ... "); sys_ sync(); printk("done.\n");
pr_ debug("PM: Preparing system for %s sleep\n", pm_states[state]); error = suspend_ prepare(); if (error) goto Unlock;
if (suspend_test(TEST_FREEZER)) goto Finish;
pr_ debug("PM: Entering %s sleep\n", pm_states[state]); pm_ restrict_ gfp_ mask(); error = suspend_ devices_ and_ enter(state); pm_ restore_ gfp_ mask();
Invalid Sign
suspend_ Prepare do some sleep preparation
suspend_ devices_ and_ Enter is the real device that goes to sleep
suspend_ Finish the operation after wake-up.
Here is an analysis:
suspend_ First pass PM in prepare_ prepare_ Console, which assigns a virtual terminal to suspend to output information; Then through PM_ notifier_ call_ Chain to broadcast the notification of a system entering suspend; Close the helper process in user mode; Finally, through suspend_ freeze_ Processes to freeze user state processes, and finally try to free some memory. In suspend_ freeze_ The freeze_ is called in the processes () function. Processes() function, and free_ Try is called again in the processes () function_ to_ freeze_ Tasks() to complete the frozen task. During the freezing process, it will judge whether the current process has a wake_ Lock, if any, the freezing fails, and the function will give up the freezing.
After performing the above operations, return to enter again_ In the state function, start calling suspend_ devices_ and_ The enter() function puts the peripheral into sleep. In suspend_ devices_ and_ Enter () calls suspend about the platform first_ Ops - > begin, and then suspend_ Console to close the console, or change a flag to invalidate this function. Then call DPM_ suspend_ start。 dpm_ suspend_ Device will be executed in start_ Prepare and device_ Suspend, these two functions call the prepare and suspend functions in the PM interface (in fact, the suspension function of the driver is executed through the bus interface, through bus - > PM - > suspend). Then go back to suspend_ devices_ and_ Calling suspend_ in enter enter(state); In suspend_ In enter, first call the platform related suspend_ Ops - > prepare, and then execute DPM_ suspend_ Noirq() calls PM - > suspend in the PM interface_ Noirq, back to suspend_ Enter, and then call suspend_ ops->prepare_ Later, the non started CPUs in the multi CPUs pass the function disable_ nonboot_ CPUs () is turned off and then called arch_ suspend_ disable_ Irqs() turns off the local interrupt. Later, the operation of the sleep device, sysdev_ Suspend (pmsg_suspend), which will enter sysdev_ Driver.suspend phase. Finally, call suspend_. Ops - > enter(), the last step of sleep is started here, and platform related sleep is executed. In the code of platform sleep, it is mainly through suspend_ in_ IRAM (suspend_param1) to execute a piece of assembly code, and finally sleep in the assembly. The wake-up step is opposite to the sleep step. When the CPU is powered on, it will first get up from the assembly and then return to suspend_ In the enter function, execute suspend_ Some wake-up codes returned by Ops - > enter() are basically operated in the reverse order above.
In my opinion, the above process is still very complex. Power management should study it carefully
Resume process
When waking up, the program starts from suspend_ devices_ and_ When it comes out of the enter function, it starts to suspend_ Finish, and then from the enter_ Exit from state and return PM_ Suspend, and then from PM_ Suspend returns to suspend () in wakelock. C, where "suspend: exit suspend, RET" logs will be printed.
Reproduced at: https://www.cnblogs.com/ITlearning/p/3163496.html