zephyr/subsys/pm/policy/policy_device_lock.c
Flavio Ceolin b8ce176109 pm: policy: Fix possible undefined reference
When PM_POLICY_DEVICE_CONSTRAINTS is enabled, we create a list of
devices with the property “zephyr,disabling-power-states” and their
respective states to lock. However, if a device is declared but not
built (e.g., due to a Kconfig option), we have an undefined reference.

This PR changes the code to use the device name instead of the
reference. This increases lookup time (which could be cached at
runtime), and we still have an entry for a non-existent device.

Signed-off-by: Flavio Ceolin <flavio@hubblenetwork.com>
2025-02-08 04:06:29 +01:00

125 lines
4.3 KiB
C

/*
* Copyright (c) 2018 Intel Corporation.
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/pm/policy.h>
#include <zephyr/pm/state.h>
#include <zephyr/sys/util_macro.h>
#include <zephyr/pm/device.h>
struct pm_state_device_constraint {
const char *const dev;
size_t pm_constraints_size;
struct pm_state_constraint *constraints;
};
/**
* @brief Synthesize the name of the object that holds a device pm constraint.
*
* @param dev_id Device identifier.
*/
#define PM_CONSTRAINTS_NAME(node_id) _CONCAT(__devicepmconstraints_, node_id)
/**
* @brief initialize a device pm constraint with information from devicetree.
*
* @param node_id Node identifier.
*/
#define PM_STATE_CONSTRAINT_INIT(node_id) \
{ \
.state = PM_STATE_DT_INIT(node_id), \
.substate_id = DT_PROP_OR(node_id, substate_id, 0), \
}
/**
* @brief Helper macro to define a device pm constraints.
*/
#define PM_STATE_CONSTRAINT_DEFINE(i, node_id) \
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE_BY_IDX(node_id, \
zephyr_disabling_power_states, i)), \
(PM_STATE_CONSTRAINT_INIT(DT_PHANDLE_BY_IDX(node_id, \
zephyr_disabling_power_states, i)),), ())
/**
* @brief Helper macro to generate a list of device pm constraints.
*/
#define PM_STATE_CONSTRAINTS_DEFINE(node_id) \
{ \
LISTIFY(DT_PROP_LEN_OR(node_id, zephyr_disabling_power_states, 0), \
PM_STATE_CONSTRAINT_DEFINE, (), node_id) \
}
/**
* @brief Helper macro to define an array of device pm constraints.
*/
#define CONSTRAINTS_DEFINE(node_id) \
Z_DECL_ALIGN(struct pm_state_constraint) \
PM_CONSTRAINTS_NAME(node_id)[] = \
PM_STATE_CONSTRAINTS_DEFINE(node_id);
#define DEVICE_CONSTRAINTS_DEFINE(node_id) \
COND_CODE_0(DT_NODE_HAS_PROP(node_id, zephyr_disabling_power_states), (), \
(CONSTRAINTS_DEFINE(node_id)))
DT_FOREACH_STATUS_OKAY_NODE(DEVICE_CONSTRAINTS_DEFINE)
/**
* @brief Helper macro to initialize a pm state device constraint
*/
#define PM_STATE_DEVICE_CONSTRAINT_INIT(node_id) \
{ \
.dev = DEVICE_DT_NAME(node_id), \
.pm_constraints_size = DT_PROP_LEN(node_id, zephyr_disabling_power_states), \
.constraints = PM_CONSTRAINTS_NAME(node_id), \
},
/**
* @brief Helper macro to initialize a pm state device constraint
*/
#define PM_STATE_DEVICE_CONSTRAINT_DEFINE(node_id) \
COND_CODE_0(DT_NODE_HAS_PROP(node_id, zephyr_disabling_power_states), (), \
(PM_STATE_DEVICE_CONSTRAINT_INIT(node_id)))
static struct pm_state_device_constraint _devices_constraints[] = {
DT_FOREACH_STATUS_OKAY_NODE(PM_STATE_DEVICE_CONSTRAINT_DEFINE)
};
void pm_policy_device_power_lock_get(const struct device *dev)
{
#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state)
for (size_t i = 0; i < ARRAY_SIZE(_devices_constraints); i++) {
const struct device *device = device_get_binding(_devices_constraints[i].dev);
if ((device != NULL) && (device == dev)) {
for (size_t j = 0; j < _devices_constraints[i].pm_constraints_size; j++) {
pm_policy_state_lock_get(
_devices_constraints[i].constraints[j].state,
_devices_constraints[i].constraints[j].substate_id);
}
break;
}
}
#endif
}
void pm_policy_device_power_lock_put(const struct device *dev)
{
#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state)
for (size_t i = 0; i < ARRAY_SIZE(_devices_constraints); i++) {
const struct device *device = device_get_binding(_devices_constraints[i].dev);
if ((device != NULL) && (device == dev)) {
for (size_t j = 0; j < _devices_constraints[i].pm_constraints_size; j++) {
pm_policy_state_lock_put(
_devices_constraints[i].constraints[j].state,
_devices_constraints[i].constraints[j].substate_id);
}
break;
}
}
#endif
}