drivers/power/: PM: Don't update the power state in work thread: (1) Simplify the code logic and remove the work queue dependence, (2) Power calculation is too simple to delay into the work queue
This commit is contained in:
parent
7d9787d530
commit
af284c1e23
@ -47,7 +47,6 @@
|
|||||||
|
|
||||||
#include <nuttx/semaphore.h>
|
#include <nuttx/semaphore.h>
|
||||||
#include <nuttx/clock.h>
|
#include <nuttx/clock.h>
|
||||||
#include <nuttx/wqueue.h>
|
|
||||||
#include <nuttx/power/pm.h>
|
#include <nuttx/power/pm.h>
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
@ -57,10 +56,6 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
/* Configuration ************************************************************/
|
/* Configuration ************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_SCHED_WORKQUEUE
|
|
||||||
# warning "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Convert the time slice interval into system clock ticks.
|
/* Convert the time slice interval into system clock ticks.
|
||||||
*
|
*
|
||||||
* CONFIG_PM_SLICEMS provides the duration of one time slice in milliseconds.
|
* CONFIG_PM_SLICEMS provides the duration of one time slice in milliseconds.
|
||||||
@ -159,10 +154,6 @@ struct pm_global_s
|
|||||||
|
|
||||||
sem_t regsem;
|
sem_t regsem;
|
||||||
|
|
||||||
/* For work that has been deferred to the worker thread */
|
|
||||||
|
|
||||||
struct work_s work;
|
|
||||||
|
|
||||||
/* registry is a singly-linked list of registered power management
|
/* registry is a singly-linked list of registered power management
|
||||||
* callback structures. To ensure mutually exclusive access, this list
|
* callback structures. To ensure mutually exclusive access, this list
|
||||||
* must be locked by calling pm_lock() before it is accessed.
|
* must be locked by calling pm_lock() before it is accessed.
|
||||||
@ -210,8 +201,7 @@ EXTERN struct pm_global_s g_pmglobals;
|
|||||||
* Assumptions:
|
* Assumptions:
|
||||||
* This function may be called from a driver, perhaps even at the interrupt
|
* This function may be called from a driver, perhaps even at the interrupt
|
||||||
* level. It may also be called from the IDLE loop at the lowest possible
|
* level. It may also be called from the IDLE loop at the lowest possible
|
||||||
* priority level. To reconcile these various conditions, all work is
|
* priority level.
|
||||||
* performed on the worker thread at a user-selectable priority.
|
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
@ -137,11 +137,6 @@ void pm_activity(int domain, int priority)
|
|||||||
pdom->stime = now;
|
pdom->stime = now;
|
||||||
pdom->accum = 0;
|
pdom->accum = 0;
|
||||||
|
|
||||||
/* Reassessing the PM state may require some computation. However,
|
|
||||||
* the work will actually be performed on a worker thread at a user-
|
|
||||||
* controlled priority.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(void)pm_update(domain, tmp);
|
(void)pm_update(domain, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,11 +125,6 @@ enum pm_state_e pm_checkstate(int domain)
|
|||||||
pdom->stime = now;
|
pdom->stime = now;
|
||||||
pdom->accum = 0;
|
pdom->accum = 0;
|
||||||
|
|
||||||
/* Reassessing the PM state may require some computation. However,
|
|
||||||
* the work will actually be performed on a worker thread at a user-
|
|
||||||
* controlled priority.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(void)pm_update(domain, accum);
|
(void)pm_update(domain, accum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,12 +141,6 @@ enum pm_state_e pm_checkstate(int domain)
|
|||||||
|
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
|
|
||||||
/* Return the recommended state. Assuming that we are called from the
|
|
||||||
* IDLE thread at the lowest priority level, any updates scheduled on the
|
|
||||||
* worker thread above should have already been peformed and the recommended
|
|
||||||
* state should be current:
|
|
||||||
*/
|
|
||||||
|
|
||||||
return pdom->recommended;
|
return pdom->recommended;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,26 +49,6 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Types
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
struct pm_worker_param_s
|
|
||||||
{
|
|
||||||
uint8_t domndx;
|
|
||||||
int16_t accum;
|
|
||||||
};
|
|
||||||
|
|
||||||
union pm_worker_param_u
|
|
||||||
{
|
|
||||||
struct pm_worker_param_s s;
|
|
||||||
uintptr_t i;
|
|
||||||
};
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Function Prototypes
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -132,38 +112,35 @@ static const uint16_t g_pmcount[3] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Data
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Name: pm_update
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: pm_worker
|
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This worker function is queued at the end of a time slice in order to
|
* This internal function is called at the end of a time slice in order to
|
||||||
* update driver activity metrics and recommended states.
|
* update driver activity metrics and recommended states.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* arg - The value of the activity accumulator at the end of the time
|
* domain - The PM domain associated with the accumulator
|
||||||
|
* accum - The value of the activity accumulator at the end of the time
|
||||||
* slice.
|
* slice.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* None.
|
* None.
|
||||||
*
|
*
|
||||||
* Assumptions:
|
* Assumptions:
|
||||||
* This function runs on the worker thread.
|
* This function may be called from a driver, perhaps even at the interrupt
|
||||||
|
* level. It may also be called from the IDLE loop at the lowest possible
|
||||||
|
* priority level.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void pm_worker(FAR void *arg)
|
void pm_update(int domain, int16_t accum)
|
||||||
{
|
{
|
||||||
union pm_worker_param_u parameter;
|
|
||||||
FAR struct pm_domain_s *pdom;
|
FAR struct pm_domain_s *pdom;
|
||||||
int32_t Y;
|
int32_t Y;
|
||||||
int16_t accum;
|
|
||||||
int index;
|
int index;
|
||||||
#if CONFIG_PM_MEMORY > 1
|
#if CONFIG_PM_MEMORY > 1
|
||||||
int32_t denom;
|
int32_t denom;
|
||||||
@ -171,21 +148,10 @@ void pm_worker(FAR void *arg)
|
|||||||
int j;
|
int j;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Decode the domain and accumulator as a scaler value.
|
|
||||||
*
|
|
||||||
* REVISIT: domain will fit in a uint8_t and accum is int16_t. Assuming
|
|
||||||
* that sizeof(FAR void *) >=3, the following will work. It will not work
|
|
||||||
* for 16-bit addresses!
|
|
||||||
*/
|
|
||||||
|
|
||||||
parameter.i = (uintptr_t)arg;
|
|
||||||
index = parameter.s.domndx;
|
|
||||||
accum = parameter.s.accum;
|
|
||||||
|
|
||||||
/* Get a convenience pointer to minimize all of the indexing */
|
/* Get a convenience pointer to minimize all of the indexing */
|
||||||
|
|
||||||
DEBUGASSERT(index >= 0 && index < CONFIG_PM_NDOMAINS);
|
DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
|
||||||
pdom = &g_pmglobals.domain[index];
|
pdom = &g_pmglobals.domain[domain];
|
||||||
|
|
||||||
#if CONFIG_PM_MEMORY > 1
|
#if CONFIG_PM_MEMORY > 1
|
||||||
/* We won't bother to do anything until we have accumulated
|
/* We won't bother to do anything until we have accumulated
|
||||||
@ -327,55 +293,4 @@ void pm_worker(FAR void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Public Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: pm_update
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This internal function is called at the end of a time slice in order to
|
|
||||||
* update driver activity metrics and recommended states.
|
|
||||||
*
|
|
||||||
* Input Parameters:
|
|
||||||
* domain - The PM domain associated with the accumulator
|
|
||||||
* accum - The value of the activity accumulator at the end of the time
|
|
||||||
* slice.
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* This function may be called from a driver, perhaps even at the interrupt
|
|
||||||
* level. It may also be called from the IDLE loop at the lowest possible
|
|
||||||
* priority level. To reconcile these various conditions, all work is
|
|
||||||
* performed on the worker thread at a user-selectable priority. This will
|
|
||||||
* also serialize all of the updates and eliminate any need for additional
|
|
||||||
* protection.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void pm_update(int domain, int16_t accum)
|
|
||||||
{
|
|
||||||
union pm_worker_param_u parameter;
|
|
||||||
|
|
||||||
/* Encode the domain and accumulator as a scaler value.
|
|
||||||
*
|
|
||||||
* REVISIT: domain will fit in a uint8_t and accum is int16_t. Assuming
|
|
||||||
* that sizeof(FAR void *) >=3, the following will work. It will not work
|
|
||||||
* for 16-bit addresses!
|
|
||||||
*/
|
|
||||||
|
|
||||||
DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
|
|
||||||
parameter.s.domndx = (uint8_t)domain;
|
|
||||||
parameter.s.accum = accum;
|
|
||||||
|
|
||||||
/* The work will be performed on the worker thread */
|
|
||||||
|
|
||||||
DEBUGASSERT(g_pmglobals.work.worker == NULL);
|
|
||||||
(void)work_queue(HPWORK, &g_pmglobals.work, pm_worker,
|
|
||||||
(FAR void *)parameter.i, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user