From 7f4064e511d5986116755523daddc23a56580559 Mon Sep 17 00:00:00 2001 From: zhuguangqing Date: Mon, 27 Aug 2018 13:22:11 -0600 Subject: [PATCH] drivers/pm: PM: Decrease the power state in the reverse order. Since the child driver need power off before parent driver. --- drivers/power/pm.h | 4 +- drivers/power/pm_changestate.c | 82 +++++++++++++++++++++++++--------- drivers/power/pm_initialize.c | 2 +- drivers/power/pm_register.c | 2 +- drivers/power/pm_unregister.c | 2 +- include/nuttx/power/pm.h | 2 +- 6 files changed, 68 insertions(+), 26 deletions(-) diff --git a/drivers/power/pm.h b/drivers/power/pm.h index 6d11946b47..ec718ea53c 100644 --- a/drivers/power/pm.h +++ b/drivers/power/pm.h @@ -154,12 +154,12 @@ struct pm_global_s sem_t regsem; - /* registry is a singly-linked list of registered power management + /* registry is a doubly-linked list of registered power management * callback structures. To ensure mutually exclusive access, this list * must be locked by calling pm_lock() before it is accessed. */ - sq_queue_t registry; + dq_queue_t registry; }; /**************************************************************************** diff --git a/drivers/power/pm_changestate.c b/drivers/power/pm_changestate.c index 28280958d0..953c2fac24 100644 --- a/drivers/power/pm_changestate.c +++ b/drivers/power/pm_changestate.c @@ -76,23 +76,45 @@ static int pm_prepall(int domain, enum pm_state_e newstate) { - FAR sq_entry_t *entry; + FAR dq_entry_t *entry; int ret = OK; - /* Visit each registered callback structure. */ - - for (entry = sq_peek(&g_pmglobals.registry); - entry && ret == OK; - entry = sq_next(entry)) + if (newstate <= g_pmglobals.domain[domain].state) { - /* Is the prepare callback supported? */ + /* Visit each registered callback structure in normal order. */ - FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry; - if (cb->prepare) + for (entry = dq_peek(&g_pmglobals.registry); + entry && ret == OK; + entry = dq_next(entry)) { - /* Yes.. prepare the driver */ + /* Is the prepare callback supported? */ - ret = cb->prepare(cb, domain, newstate); + FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry; + if (cb->prepare) + { + /* Yes.. prepare the driver */ + + ret = cb->prepare(cb, domain, newstate); + } + } + } + else + { + /* Visit each registered callback structure in reverse order. */ + + for (entry = dq_tail(&g_pmglobals.registry); + entry && ret == OK; + entry = dq_prev(entry)) + { + /* Is the prepare callback supported? */ + + FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry; + if (cb->prepare) + { + /* Yes.. prepare the driver */ + + ret = cb->prepare(cb, domain, newstate); + } } } @@ -120,20 +142,40 @@ static int pm_prepall(int domain, enum pm_state_e newstate) static inline void pm_changeall(int domain, enum pm_state_e newstate) { - FAR sq_entry_t *entry; + FAR dq_entry_t *entry; - /* Visit each registered callback structure. */ - - for (entry = sq_peek(&g_pmglobals.registry); entry; entry = sq_next(entry)) +if (newstate <= g_pmglobals.domain[domain].state) { - /* Is the notification callback supported? */ + /* Visit each registered callback structure in normal order. */ - FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry; - if (cb->notify) + for (entry = dq_peek(&g_pmglobals.registry); entry; entry = dq_next(entry)) { - /* Yes.. notify the driver */ + /* Is the notification callback supported? */ - cb->notify(cb, domain, newstate); + FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry; + if (cb->notify) + { + /* Yes.. notify the driver */ + + cb->notify(cb, domain, newstate); + } + } + } + else + { + /* Visit each registered callback structure in reverse order. */ + + for (entry = dq_tail(&g_pmglobals.registry); entry; entry = dq_prev(entry)) + { + /* Is the notification callback supported? */ + + FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry; + if (cb->notify) + { + /* Yes.. notify the driver */ + + cb->notify(cb, domain, newstate); + } } } } diff --git a/drivers/power/pm_initialize.c b/drivers/power/pm_initialize.c index 44b7065515..968ae64246 100644 --- a/drivers/power/pm_initialize.c +++ b/drivers/power/pm_initialize.c @@ -86,7 +86,7 @@ void pm_initialize(void) * data structure here. */ - sq_init(&g_pmglobals.registry); + dq_init(&g_pmglobals.registry); nxsem_init(&g_pmglobals.regsem, 0, 1); } diff --git a/drivers/power/pm_register.c b/drivers/power/pm_register.c index 4f200ff572..bebc739dc0 100644 --- a/drivers/power/pm_register.c +++ b/drivers/power/pm_register.c @@ -79,7 +79,7 @@ int pm_register(FAR struct pm_callback_s *callbacks) ret = pm_lock(); if (ret == OK) { - sq_addlast(&callbacks->entry, &g_pmglobals.registry); + dq_addlast(&callbacks->entry, &g_pmglobals.registry); pm_unlock(); } diff --git a/drivers/power/pm_unregister.c b/drivers/power/pm_unregister.c index 7b3d376e2f..63a8e86a33 100644 --- a/drivers/power/pm_unregister.c +++ b/drivers/power/pm_unregister.c @@ -79,7 +79,7 @@ int pm_unregister(FAR struct pm_callback_s *callbacks) ret = pm_lock(); if (ret == OK) { - sq_rem(&callbacks->entry, &g_pmglobals.registry); + dq_rem(&callbacks->entry, &g_pmglobals.registry); pm_unlock(); } diff --git a/include/nuttx/power/pm.h b/include/nuttx/power/pm.h index 09daee2533..4a0e3a02a4 100644 --- a/include/nuttx/power/pm.h +++ b/include/nuttx/power/pm.h @@ -277,7 +277,7 @@ enum pm_state_e struct pm_callback_s { - struct sq_entry_s entry; /* Supports a singly linked list */ + struct dq_entry_s entry; /* Supports a doubly linked list */ /************************************************************************** * Name: prepare