drivers/pm: PM: Decrease the power state in the reverse order. Since the child driver need power off before parent driver.

This commit is contained in:
zhuguangqing 2018-08-27 13:22:11 -06:00 committed by Gregory Nutt
parent af284c1e23
commit 7f4064e511
6 changed files with 68 additions and 26 deletions

View File

@ -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;
};
/****************************************************************************

View File

@ -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);
}
}
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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