drivers qmsi: Fix power management with reentrancy disabled
The new device control API added a 'device_power_state' variable to the driver's data structure to keep track of the current power state set for a device. This member variable is conditionally built into the runtime data structure of each driver, but in some cases the whole data structure is conditional on its respective API_REENTRANCY config variable. In those cases where the runtime data was previously used only for reentrancy protection, the runtime data pointer used for device initialization is NULL, and when power management is enabled, this invalid pointer ends up dereferenced to get the device_power_state member. Make the declaration of the runtime data dependent on any of its conditional members, and NULL only when all of those settings are disabled. Change-Id: I4f41e00ad8551a096db639e31d33f43752b6672f Signed-off-by: Iván Briano <ivan.briano@intel.com>
This commit is contained in:
parent
8d801a5e27
commit
aba245daad
4 changed files with 71 additions and 51 deletions
|
@ -30,53 +30,58 @@ static void aonpt_int_callback(void *user_data);
|
|||
static counter_callback_t user_cb;
|
||||
|
||||
struct aon_data {
|
||||
#ifdef CONFIG_AON_API_REENTRANCY
|
||||
struct nano_sem sem;
|
||||
#endif
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_AON_API_REENTRANCY
|
||||
#define AONPT_HAS_CONTEXT_DATA \
|
||||
(CONFIG_AON_API_REENTRANCY || CONFIG_DEVICE_POWER_MANAGEMENT)
|
||||
|
||||
#if AONPT_HAS_CONTEXT_DATA
|
||||
static struct aon_data aonpt_context;
|
||||
#define AONPT_CONTEXT (&aonpt_context)
|
||||
static const int reentrancy_protection = 1;
|
||||
#else
|
||||
#define AONPT_CONTEXT (NULL)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AON_API_REENTRANCY
|
||||
static const int reentrancy_protection = 1;
|
||||
#define RP_GET(dev) (&((struct aon_data *)(dev->driver_data))->sem)
|
||||
#else
|
||||
static const int reentrancy_protection;
|
||||
#define RP_GET(dev) (NULL)
|
||||
#endif
|
||||
|
||||
static void aon_reentrancy_init(struct device *dev)
|
||||
{
|
||||
struct aon_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_init(&context->sem);
|
||||
nano_sem_give(&context->sem);
|
||||
nano_sem_init(RP_GET(dev));
|
||||
nano_sem_give(RP_GET(dev));
|
||||
}
|
||||
|
||||
static void aon_critical_region_start(struct device *dev)
|
||||
{
|
||||
struct aon_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_take(&context->sem, TICKS_UNLIMITED);
|
||||
nano_sem_take(RP_GET(dev), TICKS_UNLIMITED);
|
||||
}
|
||||
|
||||
static void aon_critical_region_end(struct device *dev)
|
||||
{
|
||||
struct aon_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_give(&context->sem);
|
||||
nano_sem_give(RP_GET(dev));
|
||||
}
|
||||
|
||||
static int aon_timer_qmsi_start(struct device *dev)
|
||||
|
|
|
@ -49,53 +49,58 @@
|
|||
#define DEFAULT_PERIOD 2000
|
||||
|
||||
struct pwm_data {
|
||||
#ifdef CONFIG_PWM_QMSI_API_REENTRANCY
|
||||
struct nano_sem sem;
|
||||
#endif
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PWM_QMSI_API_REENTRANCY
|
||||
#define PWM_HAS_CONTEXT_DATA \
|
||||
(CONFIG_PWM_QMSI_API_REENTRANCY || CONFIG_DEVICE_POWER_MANAGEMENT)
|
||||
|
||||
#if PWM_HAS_CONTEXT_DATA
|
||||
static struct pwm_data pwm_context;
|
||||
#define PWM_CONTEXT (&pwm_context)
|
||||
static const int reentrancy_protection = 1;
|
||||
#else
|
||||
#define PWM_CONTEXT (NULL)
|
||||
#endif /* PWM_HAS_CONTEXT_DATA */
|
||||
|
||||
#ifdef CONFIG_PWM_QMSI_API_REENTRANCY
|
||||
static const int reentrancy_protection = 1;
|
||||
#define RP_GET(dev) (&((struct pwm_data *)(dev->driver_data))->sem)
|
||||
#else
|
||||
static const int reentrancy_protection;
|
||||
#endif /* CONFIG_PWM_QMSI_API_REENTRANCY */
|
||||
#define RP_GET(dev) (NULL)
|
||||
#endif
|
||||
|
||||
static void pwm_reentrancy_init(struct device *dev)
|
||||
{
|
||||
struct pwm_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_init(&context->sem);
|
||||
nano_sem_give(&context->sem);
|
||||
nano_sem_init(RP_GET(dev));
|
||||
nano_sem_give(RP_GET(dev));
|
||||
}
|
||||
|
||||
static void pwm_critical_region_start(struct device *dev)
|
||||
{
|
||||
struct pwm_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_take(&context->sem, TICKS_UNLIMITED);
|
||||
nano_sem_take(RP_GET(dev), TICKS_UNLIMITED);
|
||||
}
|
||||
|
||||
static void pwm_critical_region_end(struct device *dev)
|
||||
{
|
||||
struct pwm_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_give(&context->sem);
|
||||
nano_sem_give(RP_GET(dev));
|
||||
}
|
||||
|
||||
static uint32_t pwm_channel_period[CONFIG_PWM_QMSI_NUM_PORTS];
|
||||
|
|
|
@ -27,20 +27,31 @@
|
|||
#include "qm_rtc.h"
|
||||
|
||||
struct rtc_data {
|
||||
#ifdef CONFIG_RTC_QMSI_API_REENTRANCY
|
||||
struct nano_sem sem;
|
||||
#endif
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RTC_QMSI_API_REENTRANCY
|
||||
#define RTC_HAS_CONTEXT_DATA \
|
||||
(CONFIG_RTC_QMSI_API_REENTRANCY || CONFIG_DEVICE_POWER_MANAGEMENT)
|
||||
|
||||
#if RTC_HAS_CONTEXT_DATA
|
||||
static struct rtc_data rtc_context;
|
||||
#define RTC_CONTEXT (&rtc_context)
|
||||
static const int reentrancy_protection = 1;
|
||||
#else
|
||||
#define RTC_CONTEXT (NULL)
|
||||
#endif /* RTC_HAS_CONTEXT_DATA */
|
||||
|
||||
#ifdef CONFIG_RTC_QMSI_API_REENTRANCY
|
||||
static const int reentrancy_protection = 1;
|
||||
#define RP_GET(dev) (&((struct rtc_data *)(dev->driver_data))->sem)
|
||||
#else
|
||||
static const int reentrancy_protection;
|
||||
#endif /* CONFIG_RTC_QMSI_API_REENTRANCY */
|
||||
#define RP_GET(dev) (NULL)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
|
||||
|
@ -63,36 +74,30 @@ static uint32_t rtc_qmsi_get_power_state(struct device *dev)
|
|||
|
||||
static void rtc_reentrancy_init(struct device *dev)
|
||||
{
|
||||
struct rtc_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_init(&context->sem);
|
||||
nano_sem_give(&context->sem);
|
||||
nano_sem_init(RP_GET(dev));
|
||||
nano_sem_give(RP_GET(dev));
|
||||
}
|
||||
|
||||
static void rtc_critical_region_start(struct device *dev)
|
||||
{
|
||||
struct rtc_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_take(&context->sem, TICKS_UNLIMITED);
|
||||
nano_sem_take(RP_GET(dev), TICKS_UNLIMITED);
|
||||
}
|
||||
|
||||
static void rtc_critical_region_end(struct device *dev)
|
||||
{
|
||||
struct rtc_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_give(&context->sem);
|
||||
nano_sem_give(RP_GET(dev));
|
||||
}
|
||||
|
||||
static void rtc_qmsi_enable(struct device *dev)
|
||||
|
|
|
@ -26,53 +26,58 @@
|
|||
#include "qm_wdt.h"
|
||||
|
||||
struct wdt_data {
|
||||
#ifdef CONFIG_WDT_QMSI_API_REENTRANCY
|
||||
struct nano_sem sem;
|
||||
#endif
|
||||
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
|
||||
uint32_t device_power_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WDT_QMSI_API_REENTRANCY
|
||||
#define WDT_HAS_CONTEXT_DATA \
|
||||
(CONFIG_WDT_QMSI_API_REENTRANCY || CONFIG_DEVICE_POWER_MANAGEMENT)
|
||||
|
||||
#if WDT_HAS_CONTEXT_DATA
|
||||
static struct wdt_data wdt_context;
|
||||
#define WDT_CONTEXT (&wdt_context)
|
||||
static const int reentrancy_protection = 1;
|
||||
#else
|
||||
#define WDT_CONTEXT (NULL)
|
||||
#endif /* WDT_HAS_CONTEXT_DATA */
|
||||
|
||||
#ifdef CONFIG_WDT_QMSI_API_REENTRANCY
|
||||
static const int reentrancy_protection = 1;
|
||||
#define RP_GET(dev) (&((struct wdt_data *)(dev->driver_data))->sem)
|
||||
#else
|
||||
static const int reentrancy_protection;
|
||||
#endif /* CONFIG_WDT_QMSI_API_REENTRANCY */
|
||||
#define RP_GET(dev) (NULL)
|
||||
#endif
|
||||
|
||||
static void wdt_reentrancy_init(struct device *dev)
|
||||
{
|
||||
struct wdt_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_init(&context->sem);
|
||||
nano_sem_give(&context->sem);
|
||||
nano_sem_init(RP_GET(dev));
|
||||
nano_sem_give(RP_GET(dev));
|
||||
}
|
||||
|
||||
static void wdt_critical_region_start(struct device *dev)
|
||||
{
|
||||
struct wdt_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_take(&context->sem, TICKS_UNLIMITED);
|
||||
nano_sem_take(RP_GET(dev), TICKS_UNLIMITED);
|
||||
}
|
||||
|
||||
static void wdt_critical_region_end(struct device *dev)
|
||||
{
|
||||
struct wdt_data *context = dev->driver_data;
|
||||
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_give(&context->sem);
|
||||
nano_sem_give(RP_GET(dev));
|
||||
}
|
||||
|
||||
static void (*user_cb)(struct device *dev);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue