You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/06/04 14:04:32 UTC

(nuttx) 01/02: pm: remove pm global, make per domain isolated

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 1933f9648da2d45f8af690e920f522ac5fac61c2
Author: buxiasen <bu...@xiaomi.com>
AuthorDate: Fri May 31 17:18:53 2024 +0800

    pm: remove pm global, make per domain isolated
    
    After change, when CONFIG_PM_NDOMAINS > 1,
    the pm_register will not able to get notificaion
    from not PM_IDLE_DOMAIN.
    Should use pm_domain_register as a replacement.
    
    Isolate domains from global callbacks can decrease
    not necessary execution, and reduce the
    lock instruction requirements.
    
    Signed-off-by: buxiasen <bu...@xiaomi.com>
---
 drivers/power/pm/activity_governor.c  |  6 ++---
 drivers/power/pm/greedy_governor.c    |  2 +-
 drivers/power/pm/pm.h                 | 30 ++++++-------------------
 drivers/power/pm/pm_activity.c        | 16 ++++++-------
 drivers/power/pm/pm_autoupdate.c      |  4 ++--
 drivers/power/pm/pm_changestate.c     | 42 ++++++++++++++++++++---------------
 drivers/power/pm/pm_checkstate.c      |  4 ++--
 drivers/power/pm/pm_governor.c        | 12 +++++-----
 drivers/power/pm/pm_initialize.c      | 15 +++----------
 drivers/power/pm/pm_lock.c            |  4 ++--
 drivers/power/pm/pm_procfs.c          | 15 +++++++------
 drivers/power/pm/pm_register.c        | 28 +++++++++--------------
 drivers/power/pm/pm_unregister.c      | 19 ++++++++--------
 drivers/power/pm/stability_governor.c |  2 +-
 include/nuttx/power/pm.h              | 20 +++++++++++------
 15 files changed, 100 insertions(+), 119 deletions(-)

diff --git a/drivers/power/pm/activity_governor.c b/drivers/power/pm/activity_governor.c
index c3fbf0cb4d..a2a7460a79 100644
--- a/drivers/power/pm/activity_governor.c
+++ b/drivers/power/pm/activity_governor.c
@@ -317,7 +317,7 @@ static void governor_update(int domain, int16_t accum)
 
   DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
   pdomstate = &g_pm_activity_governor.domain_states[domain];
-  state     = g_pmglobals.domain[domain].state;
+  state     = g_pmdomains[domain].state;
 
 #if CONFIG_PM_GOVERNOR_MEMORY > 1
   /* We won't bother to do anything until we have accumulated
@@ -469,7 +469,7 @@ static enum pm_state_e governor_checkstate(int domain)
   /* Get a convenience pointer to minimize all of the indexing */
 
   pdomstate = &g_pm_activity_governor.domain_states[domain];
-  pdom      = &g_pmglobals.domain[domain];
+  pdom      = &g_pmdomains[domain];
 
   /* Check for the end of the current time slice.  This must be performed
    * with interrupts disabled so that it does not conflict with the similar
@@ -563,7 +563,7 @@ static void governor_timer(int domain, enum pm_state_e newstate)
     TIME_SLICE_TICKS * CONFIG_PM_GOVERNOR_SLEEPENTER_COUNT
   };
 
-  pdom      = &g_pmglobals.domain[domain];
+  pdom      = &g_pmdomains[domain];
   pdomstate = &g_pm_activity_governor.domain_states[domain];
 
   if (newstate < PM_SLEEP && dq_empty(&pdom->wakelock[newstate]))
diff --git a/drivers/power/pm/greedy_governor.c b/drivers/power/pm/greedy_governor.c
index 621c0cb476..23850502c9 100644
--- a/drivers/power/pm/greedy_governor.c
+++ b/drivers/power/pm/greedy_governor.c
@@ -94,7 +94,7 @@ static enum pm_state_e greedy_governor_checkstate(int domain)
   irqstate_t flags;
   int state;
 
-  pdom = &g_pmglobals.domain[domain];
+  pdom = &g_pmdomains[domain];
   state = PM_NORMAL;
 
   /* We disable interrupts since pm_stay()/pm_relax() could be simultaneously
diff --git a/drivers/power/pm/pm.h b/drivers/power/pm/pm.h
index b934e653b1..bccef012cf 100644
--- a/drivers/power/pm/pm.h
+++ b/drivers/power/pm/pm.h
@@ -53,6 +53,12 @@ struct pm_domain_s
 
   uint8_t state;
 
+  /* Registry is a doubly-linked list of registered power management
+   * callback structures.
+   */
+
+  dq_queue_t registry;
+
   /* The power state lock count */
 
   struct dq_queue_s wakelock[PM_COUNT];
@@ -87,28 +93,6 @@ struct pm_domain_s
   rmutex_t lock;
 };
 
-/* This structure encapsulates all of the global data used by the PM system */
-
-struct pm_global_s
-{
-  /* This rmutex manages mutually exclusive access to the power management
-   * registry.  It must be initialized to the value 1.
-   */
-
-  rmutex_t reglock;
-
-  /* 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.
-   */
-
-  dq_queue_t registry;
-
-  /* The state information for each PM domain */
-
-  struct pm_domain_s domain[CONFIG_PM_NDOMAINS];
-};
-
 /****************************************************************************
  * Public Data
  ****************************************************************************/
@@ -124,7 +108,7 @@ extern "C"
 
 /* All PM global data: */
 
-EXTERN struct pm_global_s g_pmglobals;
+EXTERN struct pm_domain_s g_pmdomains[CONFIG_PM_NDOMAINS];
 
 /****************************************************************************
  * Public Function Prototypes
diff --git a/drivers/power/pm/pm_activity.c b/drivers/power/pm/pm_activity.c
index 2c51bd05b9..96062be7df 100644
--- a/drivers/power/pm/pm_activity.c
+++ b/drivers/power/pm/pm_activity.c
@@ -54,14 +54,14 @@ static void pm_waklock_cb(wdparm_t arg)
 #ifdef CONFIG_PM_PROCFS
 static void pm_wakelock_stats_rm(FAR struct pm_wakelock_s *wakelock)
 {
-  FAR struct pm_domain_s *pdom = &g_pmglobals.domain[wakelock->domain];
+  FAR struct pm_domain_s *pdom = &g_pmdomains[wakelock->domain];
 
   dq_rem(&wakelock->fsnode, &pdom->wakelockall);
 }
 
 static void pm_wakelock_stats(FAR struct pm_wakelock_s *wakelock, bool stay)
 {
-  FAR struct pm_domain_s *pdom = &g_pmglobals.domain[wakelock->domain];
+  FAR struct pm_domain_s *pdom = &g_pmdomains[wakelock->domain];
   struct timespec ts;
 
   if (stay)
@@ -121,9 +121,9 @@ void pm_activity(int domain, int priority)
 {
   DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
 
-  if (g_pmglobals.domain[domain].governor->activity)
+  if (g_pmdomains[domain].governor->activity)
     {
-      g_pmglobals.domain[domain].governor->activity(domain, priority);
+      g_pmdomains[domain].governor->activity(domain, priority);
     }
 
   pm_auto_updatestate(domain);
@@ -301,7 +301,7 @@ void pm_wakelock_uninit(FAR struct pm_wakelock_s *wakelock)
   /* Get a convenience pointer to minimize all of the indexing */
 
   domain = wakelock->domain;
-  pdom   = &g_pmglobals.domain[domain];
+  pdom   = &g_pmdomains[domain];
   dq     = &pdom->wakelock[wakelock->state];
   wdog   = &wakelock->wdog;
 
@@ -350,7 +350,7 @@ void pm_wakelock_stay(FAR struct pm_wakelock_s *wakelock)
   /* Get a convenience pointer to minimize all of the indexing */
 
   domain = wakelock->domain;
-  pdom   = &g_pmglobals.domain[domain];
+  pdom   = &g_pmdomains[domain];
   dq     = &pdom->wakelock[wakelock->state];
 
   flags = pm_domain_lock(domain);
@@ -397,7 +397,7 @@ void pm_wakelock_relax(FAR struct pm_wakelock_s *wakelock)
   /* Get a convenience pointer to minimize all of the indexing */
 
   domain = wakelock->domain;
-  pdom   = &g_pmglobals.domain[domain];
+  pdom   = &g_pmdomains[domain];
   dq     = &pdom->wakelock[wakelock->state];
 
   flags = pm_domain_lock(domain);
@@ -448,7 +448,7 @@ void pm_wakelock_staytimeout(FAR struct pm_wakelock_s *wakelock, int ms)
   /* Get a convenience pointer to minimize all of the indexing */
 
   domain = wakelock->domain;
-  pdom   = &g_pmglobals.domain[domain];
+  pdom   = &g_pmdomains[domain];
   dq     = &pdom->wakelock[wakelock->state];
   wdog   = &wakelock->wdog;
 
diff --git a/drivers/power/pm/pm_autoupdate.c b/drivers/power/pm/pm_autoupdate.c
index d36a90f021..0579c3a32a 100644
--- a/drivers/power/pm/pm_autoupdate.c
+++ b/drivers/power/pm/pm_autoupdate.c
@@ -73,7 +73,7 @@ static void pm_auto_updatestate_cb(FAR void *arg)
 void pm_auto_updatestate(int domain)
 {
   FAR struct pm_domain_s *pdom;
-  pdom = &g_pmglobals.domain[domain];
+  pdom = &g_pmdomains[domain];
 
   if (pdom->auto_update)
     {
@@ -113,7 +113,7 @@ void pm_auto_update(int domain, bool auto_update)
   irqstate_t flags;
 
   DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
-  pdom = &g_pmglobals.domain[domain];
+  pdom = &g_pmdomains[domain];
 
   flags = pm_domain_lock(domain);
   pdom->auto_update = auto_update;
diff --git a/drivers/power/pm/pm_changestate.c b/drivers/power/pm/pm_changestate.c
index 6773508073..0ac3419f7d 100644
--- a/drivers/power/pm/pm_changestate.c
+++ b/drivers/power/pm/pm_changestate.c
@@ -106,7 +106,7 @@ static void pm_stats_preparefail(int domain,
                                  int newstate, int ret)
 {
   struct timespec ts;
-  FAR struct pm_preparefail_s *pf = &callback->preparefail[domain];
+  FAR struct pm_preparefail_s *pf = &callback->preparefail;
 
   if (pf->state != PM_RESTORE)
     {
@@ -153,20 +153,23 @@ static void pm_stats_preparefail(int domain,
 
 static int pm_prepall(int domain, enum pm_state_e newstate, bool restore)
 {
+  FAR struct pm_domain_s *pdom;
+  FAR struct pm_callback_s *cb;
   FAR dq_entry_t *entry;
   int ret = OK;
 
-  if (newstate <= g_pmglobals.domain[domain].state)
+  pdom = &g_pmdomains[domain];
+  if (newstate <= pdom->state)
     {
       /* Visit each registered callback structure in normal order. */
 
-      for (entry = dq_peek(&g_pmglobals.registry);
+      for (entry = dq_peek(&pdom->registry);
            entry && ret == OK;
            entry = dq_next(entry))
         {
           /* Is the prepare callback supported? */
 
-          FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry;
+          cb = (FAR struct pm_callback_s *)entry;
           if (cb->prepare)
             {
               /* Yes.. prepare the driver */
@@ -183,13 +186,13 @@ static int pm_prepall(int domain, enum pm_state_e newstate, bool restore)
     {
       /* Visit each registered callback structure in reverse order. */
 
-      for (entry = dq_tail(&g_pmglobals.registry);
+      for (entry = dq_tail(&pdom->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;
+          cb = (FAR struct pm_callback_s *)entry;
           if (cb->prepare)
             {
               /* Yes.. prepare the driver */
@@ -227,18 +230,21 @@ static int pm_prepall(int domain, enum pm_state_e newstate, bool restore)
 
 static inline void pm_changeall(int domain, enum pm_state_e newstate)
 {
+  FAR struct pm_domain_s *pdom;
+  FAR struct pm_callback_s *cb;
   FAR dq_entry_t *entry;
 
-  if (newstate <= g_pmglobals.domain[domain].state)
+  pdom = &g_pmdomains[domain];
+  if (newstate <= pdom->state)
     {
       /* Visit each registered callback structure in normal order. */
 
-      for (entry = dq_peek(&g_pmglobals.registry);
+      for (entry = dq_peek(&pdom->registry);
            entry; entry = dq_next(entry))
         {
           /* Is the notification callback supported? */
 
-          FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry;
+          cb = (FAR struct pm_callback_s *)entry;
           if (cb->notify)
             {
               /* Yes.. notify the driver */
@@ -251,12 +257,12 @@ static inline void pm_changeall(int domain, enum pm_state_e newstate)
     {
       /* Visit each registered callback structure in reverse order. */
 
-      for (entry = dq_tail(&g_pmglobals.registry);
+      for (entry = dq_tail(&pdom->registry);
            entry; entry = dq_prev(entry))
         {
           /* Is the notification callback supported? */
 
-          FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry;
+          cb = (FAR struct pm_callback_s *)entry;
           if (cb->notify)
             {
               /* Yes.. notify the driver */
@@ -327,15 +333,15 @@ int pm_changestate(int domain, enum pm_state_e newstate)
            * Revert to the preceding state.
            */
 
-          newstate = g_pmglobals.domain[domain].state;
+          newstate = g_pmdomains[domain].state;
           pm_prepall(domain, newstate, true);
         }
     }
 
   /* Statistics */
 
-  pm_stats(&g_pmglobals.domain[domain],
-           g_pmglobals.domain[domain].state, newstate);
+  pm_stats(&g_pmdomains[domain],
+           g_pmdomains[domain].state, newstate);
 
   /* All drivers have agreed to the state change (or, one or more have
    * disagreed and the state has been reverted).  Set the new state.
@@ -345,16 +351,16 @@ int pm_changestate(int domain, enum pm_state_e newstate)
 
   /* Notify governor of (possible) state change */
 
-  if (g_pmglobals.domain[domain].governor->statechanged)
+  if (g_pmdomains[domain].governor->statechanged)
     {
-      g_pmglobals.domain[domain].governor->statechanged(domain, newstate);
+      g_pmdomains[domain].governor->statechanged(domain, newstate);
     }
 
   /* Domain state update after statechanged done */
 
   if (newstate != PM_RESTORE)
     {
-      g_pmglobals.domain[domain].state = newstate;
+      g_pmdomains[domain].state = newstate;
     }
 
   /* Restore the interrupt state */
@@ -380,7 +386,7 @@ int pm_changestate(int domain, enum pm_state_e newstate)
 enum pm_state_e pm_querystate(int domain)
 {
   DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
-  return g_pmglobals.domain[domain].state;
+  return g_pmdomains[domain].state;
 }
 
 #endif /* CONFIG_PM */
diff --git a/drivers/power/pm/pm_checkstate.c b/drivers/power/pm/pm_checkstate.c
index 096d1ceb38..5b4f13bb26 100644
--- a/drivers/power/pm/pm_checkstate.c
+++ b/drivers/power/pm/pm_checkstate.c
@@ -73,9 +73,9 @@ enum pm_state_e pm_checkstate(int domain)
 {
   DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
 
-  if (g_pmglobals.domain[domain].governor->checkstate)
+  if (g_pmdomains[domain].governor->checkstate)
     {
-      return g_pmglobals.domain[domain].governor->checkstate(domain);
+      return g_pmdomains[domain].governor->checkstate(domain);
     }
 
   return PM_NORMAL;
diff --git a/drivers/power/pm/pm_governor.c b/drivers/power/pm/pm_governor.c
index 2c66934a14..9d5a5eb737 100644
--- a/drivers/power/pm/pm_governor.c
+++ b/drivers/power/pm/pm_governor.c
@@ -75,17 +75,17 @@ int pm_set_governor(int domain, FAR const struct pm_governor_s *gov)
       return -EINVAL;
     }
 
-  if (g_pmglobals.domain[domain].governor &&
-      g_pmglobals.domain[domain].governor->deinitialize)
+  if (g_pmdomains[domain].governor &&
+      g_pmdomains[domain].governor->deinitialize)
     {
-      g_pmglobals.domain[domain].governor->deinitialize();
+      g_pmdomains[domain].governor->deinitialize();
     }
 
-  g_pmglobals.domain[domain].governor = gov;
+  g_pmdomains[domain].governor = gov;
 
-  if (g_pmglobals.domain[domain].governor->initialize)
+  if (g_pmdomains[domain].governor->initialize)
     {
-      g_pmglobals.domain[domain].governor->initialize();
+      g_pmdomains[domain].governor->initialize();
     }
 
   return 0;
diff --git a/drivers/power/pm/pm_initialize.c b/drivers/power/pm/pm_initialize.c
index 38488bc820..f44279c4e1 100644
--- a/drivers/power/pm/pm_initialize.c
+++ b/drivers/power/pm/pm_initialize.c
@@ -38,16 +38,7 @@
 
 /* All PM global data: */
 
-/* Initialize the registry and the PM global data structures.  The PM
- * global data structure resides in .data which is zeroed at boot time.  So
- * it is only required to initialize non-zero elements of the PM global
- * data structure here.
- */
-
-struct pm_global_s g_pmglobals =
-{
-  NXRMUTEX_INITIALIZER
-};
+struct pm_domain_s g_pmdomains[CONFIG_PM_NDOMAINS];
 
 /****************************************************************************
  * Public Functions
@@ -98,10 +89,10 @@ void pm_initialize(void)
       pm_set_governor(i, gov);
 
 #if defined(CONFIG_PM_PROCFS)
-      clock_systime_timespec(&g_pmglobals.domain[i].start);
+      clock_systime_timespec(&g_pmdomains[i].start);
 #endif
 
-      nxrmutex_init(&g_pmglobals.domain[i].lock);
+      nxrmutex_init(&g_pmdomains[i].lock);
 
 #if CONFIG_PM_GOVERNOR_EXPLICIT_RELAX
       for (state = 0; state < PM_COUNT; state++)
diff --git a/drivers/power/pm/pm_lock.c b/drivers/power/pm/pm_lock.c
index 54dff8410d..ee945996ab 100644
--- a/drivers/power/pm/pm_lock.c
+++ b/drivers/power/pm/pm_lock.c
@@ -59,12 +59,12 @@ void pm_unlock(FAR rmutex_t *lock, irqstate_t flags)
 
 irqstate_t pm_domain_lock(int domain)
 {
-  return pm_lock(&g_pmglobals.domain[domain].lock);
+  return pm_lock(&g_pmdomains[domain].lock);
 }
 
 void pm_domain_unlock(int domain, irqstate_t flags)
 {
-  pm_unlock(&g_pmglobals.domain[domain].lock, flags);
+  pm_unlock(&g_pmdomains[domain].lock, flags);
 }
 
 #endif /* CONFIG_PM */
diff --git a/drivers/power/pm/pm_procfs.c b/drivers/power/pm/pm_procfs.c
index 5aea817018..199fc41f9e 100644
--- a/drivers/power/pm/pm_procfs.c
+++ b/drivers/power/pm/pm_procfs.c
@@ -288,7 +288,7 @@ static ssize_t pm_read_state(FAR struct file *filep, FAR char *buffer,
   /* Recover our private data from the struct file instance */
 
   pmfile = (FAR struct pm_file_s *)filep->f_priv;
-  dom    = &g_pmglobals.domain[pmfile->domain];
+  dom    = &g_pmdomains[pmfile->domain];
   DEBUGASSERT(pmfile);
   DEBUGASSERT(dom);
 
@@ -378,7 +378,7 @@ static ssize_t pm_read_wakelock(FAR struct file *filep, FAR char *buffer,
   /* Recover our private data from the struct file instance */
 
   pmfile = (FAR struct pm_file_s *)filep->f_priv;
-  dom    = &g_pmglobals.domain[pmfile->domain];
+  dom    = &g_pmdomains[pmfile->domain];
   DEBUGASSERT(pmfile);
   DEBUGASSERT(dom);
 
@@ -464,7 +464,7 @@ static ssize_t pm_read_preparefail(FAR struct file *filep, FAR char *buffer,
   /* Recover our private data from the struct file instance */
 
   pmfile = (FAR struct pm_file_s *)filep->f_priv;
-  dom    = &g_pmglobals.domain[pmfile->domain];
+  dom    = &g_pmdomains[pmfile->domain];
   DEBUGASSERT(pmfile);
   DEBUGASSERT(dom);
 
@@ -480,11 +480,12 @@ static ssize_t pm_read_preparefail(FAR struct file *filep, FAR char *buffer,
   totalsize += copysize;
 
   flags = pm_domain_lock(pmfile->domain);
-  for (entry = dq_peek(&g_pmglobals.registry);
+
+  for (entry = dq_peek(&dom->registry);
        entry; entry = dq_next(entry))
     {
       cb = (FAR struct pm_callback_s *)entry;
-      pf = &cb->preparefail[pmfile->domain];
+      pf = &cb->preparefail;
       for (state = 0; state < PM_COUNT; state++)
         {
           sum +=  pf->duration[state].tv_sec;
@@ -492,13 +493,13 @@ static ssize_t pm_read_preparefail(FAR struct file *filep, FAR char *buffer,
     }
 
   sum = sum ? sum : 1;
-  for (entry = dq_peek(&g_pmglobals.registry);
+  for (entry = dq_peek(&dom->registry);
        entry; entry = dq_next(entry))
     {
       time_t total = 0;
 
       cb = (FAR struct pm_callback_s *)entry;
-      pf = &cb->preparefail[pmfile->domain];
+      pf = &cb->preparefail;
       for (state = 0; state < PM_COUNT; state++)
         {
           total +=  pf->duration[state].tv_sec;
diff --git a/drivers/power/pm/pm_register.c b/drivers/power/pm/pm_register.c
index b671062f67..84e155ac01 100644
--- a/drivers/power/pm/pm_register.c
+++ b/drivers/power/pm/pm_register.c
@@ -39,14 +39,15 @@
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pm_register
+ * Name: pm_domain_register
  *
  * Description:
  *   This function is called by a device driver in order to register to
  *   receive power management event callbacks.
  *
  * Input Parameters:
- *   callbacks - An instance of struct pm_callback_s providing the driver
+ *   domain - Target register domain.
+ *   cb     - An instance of struct pm_callback_s providing the driver
  *               callback functions.
  *
  * Returned Value:
@@ -54,27 +55,20 @@
  *
  ****************************************************************************/
 
-int pm_register(FAR struct pm_callback_s *callbacks)
+int pm_domain_register(int domain, FAR struct pm_callback_s *cb)
 {
   irqstate_t flags;
-
-  DEBUGASSERT(callbacks);
+  FAR struct pm_domain_s *pdom = &g_pmdomains[domain];
+  flags = pm_lock(&pdom->lock);
 
   /* Add the new entry to the end of the list of registered callbacks */
 
-  flags = pm_lock(&g_pmglobals.reglock);
-  dq_addlast(&callbacks->entry, &g_pmglobals.registry);
-
-#ifdef CONFIG_PM_PROCFS
-  for (int domain = 0; domain < CONFIG_PM_NDOMAINS; domain++)
-    {
-      callbacks->preparefail[domain].state = PM_RESTORE;
-    }
+  dq_addlast(&cb->entry, &pdom->registry);
+#if defined (CONFIG_PM_PROCFS)
+  cb->preparefail.state = PM_RESTORE;
 #endif
-
-  pm_unlock(&g_pmglobals.reglock, flags);
-
-  return 0;
+  pm_unlock(&pdom->lock, flags);
+  return OK;
 }
 
 #endif /* CONFIG_PM */
diff --git a/drivers/power/pm/pm_unregister.c b/drivers/power/pm/pm_unregister.c
index f591f1391b..9cb003215a 100644
--- a/drivers/power/pm/pm_unregister.c
+++ b/drivers/power/pm/pm_unregister.c
@@ -38,14 +38,15 @@
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pm_unregister
+ * Name: pm_domain_unregister
  *
  * Description:
  *   This function is called by a device driver in order to unregister
  *   previously registered power management event callbacks.
  *
  * Input parameters:
- *   callbacks - An instance of struct pm_callback_s providing the driver
+ *   domain - Target unregister domain.
+ *   cb     - An instance of struct pm_callback_s providing the driver
  *               callback functions.
  *
  * Returned Value:
@@ -53,19 +54,17 @@
  *
  ****************************************************************************/
 
-int pm_unregister(FAR struct pm_callback_s *callbacks)
+int pm_domain_unregister(int domain, FAR struct pm_callback_s *cb)
 {
   irqstate_t flags;
-
-  DEBUGASSERT(callbacks);
+  struct pm_domain_s *pdom = &g_pmdomains[domain];
+  flags = pm_lock(&pdom->lock);
 
   /* Remove entry from the list of registered callbacks. */
 
-  flags = pm_lock(&g_pmglobals.reglock);
-  dq_rem(&callbacks->entry, &g_pmglobals.registry);
-  pm_unlock(&g_pmglobals.reglock, flags);
-
-  return 0;
+  dq_rem(&cb->entry, &pdom->registry);
+  pm_unlock(&pdom->lock, flags);
+  return OK;
 }
 
 #endif /* CONFIG_PM */
diff --git a/drivers/power/pm/stability_governor.c b/drivers/power/pm/stability_governor.c
index c2fd6ff6f0..66d4fe9db7 100644
--- a/drivers/power/pm/stability_governor.c
+++ b/drivers/power/pm/stability_governor.c
@@ -158,7 +158,7 @@ static enum pm_state_e stability_governor_checkstate(int domain)
   bool wdog_wakeup;
 
   gdom = &g_stability_governor.domain[domain];
-  pdom = &g_pmglobals.domain[domain];
+  pdom = &g_pmdomains[domain];
   state = PM_NORMAL;
 
   /* We disable interrupts since pm_stay()/pm_relax() could be simultaneously
diff --git a/include/nuttx/power/pm.h b/include/nuttx/power/pm.h
index 3bdd491f3e..54d6f16ce5 100644
--- a/include/nuttx/power/pm.h
+++ b/include/nuttx/power/pm.h
@@ -222,7 +222,7 @@ struct pm_callback_s
                       enum pm_state_e pmstate);
 
 #ifdef CONFIG_PM_PROCFS
-  struct pm_preparefail_s preparefail[CONFIG_PM_NDOMAINS];
+  struct pm_preparefail_s preparefail;
 #endif
 };
 
@@ -440,14 +440,15 @@ int pm_set_governor(int domain, FAR const struct pm_governor_s *gov);
 void pm_auto_update(int domain, bool auto_update);
 
 /****************************************************************************
- * Name: pm_register
+ * Name: pm_domain_register
  *
  * Description:
  *   This function is called by a device driver in order to register to
  *   receive power management event callbacks.
  *
  * Input Parameters:
- *   callbacks - An instance of struct pm_callback_s providing the driver
+ *   domain - Target register domain.
+ *   cb     - An instance of struct pm_callback_s providing the driver
  *               callback functions.
  *
  * Returned Value:
@@ -455,17 +456,20 @@ void pm_auto_update(int domain, bool auto_update);
  *
  ****************************************************************************/
 
-int pm_register(FAR struct pm_callback_s *callbacks);
+int pm_domain_register(int domain, FAR struct pm_callback_s *cb);
+
+#define pm_register(cb) pm_domain_register(PM_IDLE_DOMAIN, cb)
 
 /****************************************************************************
- * Name: pm_unregister
+ * Name: pm_domain_unregister
  *
  * Description:
  *   This function is called by a device driver in order to unregister
  *   previously registered power management event callbacks.
  *
  * Input parameters:
- *   callbacks - An instance of struct pm_callback_s providing the driver
+ *   domain - Target unregister domain.
+ *   cb     - An instance of struct pm_callback_s providing the driver
  *               callback functions.
  *
  * Returned Value:
@@ -473,7 +477,9 @@ int pm_register(FAR struct pm_callback_s *callbacks);
  *
  ****************************************************************************/
 
-int pm_unregister(FAR struct pm_callback_s *callbacks);
+int pm_domain_unregister(int domain, FAR struct pm_callback_s *cb);
+
+#define pm_unregister(cb) pm_domain_unregister(PM_IDLE_DOMAIN, cb)
 
 /****************************************************************************
  * Name: pm_activity