power: device_pm: Use spin lock instead of semaphore

Device pm runtime was using semaphore to protect critical section but
enable / disable functions were waiting on the semaphore. So, just
replace it with a spin lock.

Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
This commit is contained in:
Flavio Ceolin 2021-04-28 15:30:25 -07:00 committed by Anas Nashif
commit 54324fd08e
3 changed files with 11 additions and 6 deletions

View file

@ -87,7 +87,7 @@ struct pm_device {
/** Pointer to the device */
const struct device *dev;
/** Lock to synchronize the get/put operations */
struct k_sem lock;
struct k_spinlock lock;
/* Following are packed fields protected by #lock. */
/** Device pm enable flag */
bool enable : 1;

View file

@ -30,7 +30,7 @@ static inline void device_pm_state_init(const struct device *dev)
#ifdef CONFIG_PM_DEVICE
*dev->pm = (struct pm_device){
.usage = ATOMIC_INIT(0),
.lock = Z_SEM_INITIALIZER(dev->pm->lock, 1, 1),
.lock = {},
.condvar = Z_CONDVAR_INITIALIZER(dev->pm->condvar),
};
#endif /* CONFIG_PM_DEVICE */

View file

@ -9,6 +9,7 @@
#include <device.h>
#include <sys/__assert.h>
#include <pm/device_runtime.h>
#include <spinlock.h>
#define LOG_LEVEL CONFIG_PM_LOG_LEVEL /* From power module Kconfig */
#include <logging/log.h>
@ -170,6 +171,8 @@ int pm_device_put_sync(const struct device *dev)
void pm_device_enable(const struct device *dev)
{
k_spinlock_key_t key;
if (k_is_pre_kernel()) {
dev->pm->dev = dev;
dev->pm->enable = true;
@ -178,7 +181,7 @@ void pm_device_enable(const struct device *dev)
return;
}
k_sem_take(&dev->pm->lock, K_FOREVER);
key = k_spin_lock(&dev->pm->lock);
dev->pm->enable = true;
/* During the driver init, device can set the
@ -193,17 +196,19 @@ void pm_device_enable(const struct device *dev)
} else {
k_work_schedule(&dev->pm->work, K_NO_WAIT);
}
k_sem_give(&dev->pm->lock);
k_spin_unlock(&dev->pm->lock, key);
}
void pm_device_disable(const struct device *dev)
{
k_spinlock_key_t key;
__ASSERT(k_is_pre_kernel() == false, "Device should not be disabled "
"before kernel is initialized");
k_sem_take(&dev->pm->lock, K_FOREVER);
key = k_spin_lock(&dev->pm->lock);
dev->pm->enable = false;
/* Bring up the device before disabling the Idle PM */
k_work_schedule(&dev->pm->work, K_NO_WAIT);
k_sem_give(&dev->pm->lock);
k_spin_unlock(&dev->pm->lock, key);
}