device: store device pm busy status in the state structure

Move the busy status from a global atomic bit sequence to atomic flags
in the device PM state.  While this temporarily adds 4 bytes to each
PM structure the whole device PM infrastructure will be refactored and
it's likely the extra memory can be recovered.

Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
Peter Bigot 2021-02-02 10:37:30 -06:00 committed by Anas Nashif
commit d1a0568e11
3 changed files with 26 additions and 43 deletions

View file

@ -270,8 +270,11 @@ struct device_pm {
const struct device *dev;
/** Lock to synchronize the get/put operations */
struct k_sem lock;
/* Following are packed fields protected by #lock. */
/** Device pm enable flag */
bool enable;
bool enable : 1;
/* Following are packed fields accessed with atomic bit operations. */
atomic_t atomic_flags;
/** Device usage count */
atomic_t usage;
/** Device idle internal power state */
@ -284,6 +287,11 @@ struct device_pm {
struct k_poll_signal signal;
};
/** Bit position in device_pm::atomic_flags that records whether the
* device is busy.
*/
#define DEVICE_PM_ATOMIC_FLAGS_BUSY_BIT 0
/**
* @brief Runtime device dynamic structure (in RAM) per driver instance
*

View file

@ -13,27 +13,6 @@
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#endif
/*
* Space for storing per device init status and busy bitmap in case PM is
* enabled. Since we do not know beforehand the number of devices,
* we go through the below mechanism to allocate the required space.
* Both are made of 1 bit per-device instance, so we compute the size of
* of an entire bitfield, aligned on 32bits.
*/
#define DEVICE_COUNT \
((__device_end - __device_start) / _DEVICE_STRUCT_SIZEOF)
#define DEVICE_BITFIELD_SIZE (((DEVICE_COUNT + 31) / 32) * 4)
#ifdef CONFIG_PM_DEVICE
#define DEVICE_BUSY_BITFIELD() \
FILL(0x00); \
__device_busy_start = .; \
. = . + DEVICE_BITFIELD_SIZE; \
__device_busy_end = .;
#else
#define DEVICE_BUSY_BITFIELD()
#endif
SECTION_DATA_PROLOGUE(devices,,)
{
/* link in devices objects, which are tied to the init ones;
@ -47,7 +26,6 @@
CREATE_OBJ_LEVEL(device, APPLICATION)
CREATE_OBJ_LEVEL(device, SMP)
__device_end = .;
DEVICE_BUSY_BITFIELD()
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
SECTION_DATA_PROLOGUE(initshell,,)

View file

@ -25,12 +25,6 @@ extern const struct device __device_end[];
extern uint32_t __device_init_status_start[];
#ifdef CONFIG_PM_DEVICE
extern uint32_t __device_busy_start[];
extern uint32_t __device_busy_end[];
#define DEVICE_BUSY_SIZE (__device_busy_end - __device_busy_start)
#endif
static inline void device_pm_state_init(const struct device *dev)
{
#ifdef CONFIG_PM_DEVICE
@ -180,20 +174,23 @@ int device_pm_control_nop(const struct device *unused_device,
int device_any_busy_check(void)
{
int i = 0;
const struct device *dev = __device_start;
for (i = 0; i < DEVICE_BUSY_SIZE; i++) {
if (__device_busy_start[i] != 0U) {
while (dev < __device_end) {
if (atomic_test_bit(&dev->pm->atomic_flags,
DEVICE_PM_ATOMIC_FLAGS_BUSY_BIT)) {
return -EBUSY;
}
++dev;
}
return 0;
}
int device_busy_check(const struct device *chk_dev)
int device_busy_check(const struct device *dev)
{
if (atomic_test_bit((const atomic_t *)__device_busy_start,
(chk_dev - __device_start))) {
if (atomic_test_bit(&dev->pm->atomic_flags,
DEVICE_PM_ATOMIC_FLAGS_BUSY_BIT)) {
return -EBUSY;
}
return 0;
@ -201,22 +198,22 @@ int device_busy_check(const struct device *chk_dev)
#endif
void device_busy_set(const struct device *busy_dev)
void device_busy_set(const struct device *dev)
{
#ifdef CONFIG_PM_DEVICE
atomic_set_bit((atomic_t *) __device_busy_start,
(busy_dev - __device_start));
atomic_set_bit(&dev->pm->atomic_flags,
DEVICE_PM_ATOMIC_FLAGS_BUSY_BIT);
#else
ARG_UNUSED(busy_dev);
ARG_UNUSED(dev);
#endif
}
void device_busy_clear(const struct device *busy_dev)
void device_busy_clear(const struct device *dev)
{
#ifdef CONFIG_PM_DEVICE
atomic_clear_bit((atomic_t *) __device_busy_start,
(busy_dev - __device_start));
atomic_clear_bit(&dev->pm->atomic_flags,
DEVICE_PM_ATOMIC_FLAGS_BUSY_BIT);
#else
ARG_UNUSED(busy_dev);
ARG_UNUSED(dev);
#endif
}