diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 18285305b86f..a076b1dac541 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -595,6 +595,7 @@ static void devfreq_dev_release(struct device *dev) devfreq->profile->exit(devfreq->dev.parent); mutex_destroy(&devfreq->lock); + event_mutex_destroy(devfreq); kfree(devfreq); } @@ -637,6 +638,7 @@ struct devfreq *devfreq_add_device(struct device *dev, } mutex_init(&devfreq->lock); + event_mutex_init(devfreq); mutex_lock(&devfreq->lock); devfreq->dev.parent = dev; devfreq->dev.class = devfreq_class; @@ -1145,12 +1147,13 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, goto out; } + event_mutex_lock(df); if (df->governor) { ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL); if (ret) { dev_warn(dev, "%s: Governor %s not stopped(%d)\n", __func__, df->governor->name, ret); - goto out; + goto gov_stop_out; } } prev_governor = df->governor; @@ -1171,6 +1174,9 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, df->governor = NULL; } } + +gov_stop_out: + event_mutex_unlock(df); out: mutex_unlock(&devfreq_list_lock); @@ -1265,8 +1271,10 @@ static ssize_t polling_interval_store(struct device *dev, if (ret != 1) return -EINVAL; + event_mutex_lock(df); df->governor->event_handler(df, DEVFREQ_GOV_INTERVAL, &value); ret = count; + event_mutex_unlock(df); return ret; } @@ -1283,6 +1291,7 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr, if (ret != 1) return -EINVAL; + event_mutex_lock(df); mutex_lock(&df->lock); if (value) { @@ -1305,6 +1314,7 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr, ret = count; unlock: mutex_unlock(&df->lock); + event_mutex_unlock(df); return ret; } @@ -1327,6 +1337,7 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, if (ret != 1) return -EINVAL; + event_mutex_lock(df); mutex_lock(&df->lock); if (value) { @@ -1349,6 +1360,7 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, ret = count; unlock: mutex_unlock(&df->lock); + event_mutex_unlock(df); return ret; } static DEVICE_ATTR_RW(min_freq); diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index 2bae9ed3c783..d19581dac8da 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -149,6 +149,9 @@ struct devfreq { struct list_head node; struct mutex lock; +#ifdef CONFIG_QCOM_DEVFREQ_ICC + struct mutex event_lock; +#endif struct device dev; struct devfreq_dev_profile *profile; const struct devfreq_governor *governor; @@ -185,6 +188,31 @@ struct devfreq_freqs { unsigned long new; }; +static inline void event_mutex_init(struct devfreq *devfreq) +{ +#ifdef CONFIG_QCOM_DEVFREQ_ICC + mutex_init(&devfreq->event_lock); +#endif +} +static inline void event_mutex_destroy(struct devfreq *devfreq) +{ +#ifdef CONFIG_QCOM_DEVFREQ_ICC + mutex_destroy(&devfreq->event_lock); +#endif +} +static inline void event_mutex_lock(struct devfreq *devfreq) +{ +#ifdef CONFIG_QCOM_DEVFREQ_ICC + mutex_lock(&devfreq->event_lock); +#endif +} +static inline void event_mutex_unlock(struct devfreq *devfreq) +{ +#ifdef CONFIG_QCOM_DEVFREQ_ICC + mutex_unlock(&devfreq->event_lock); +#endif +} + #if defined(CONFIG_PM_DEVFREQ) extern struct devfreq *devfreq_add_device(struct device *dev, struct devfreq_dev_profile *profile,