diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 59cb812e9132..7c90651e575e 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -590,6 +590,7 @@ struct devfreq *devfreq_add_device(struct device *dev, devfreq->last_status.current_frequency = profile->initial_freq; devfreq->data = data; devfreq->nb.notifier_call = devfreq_notifier_call; + devfreq->dev_suspended = false; if (!devfreq->profile->max_state && !devfreq->profile->freq_table) { mutex_unlock(&devfreq->lock); @@ -794,12 +795,16 @@ int devfreq_suspend_device(struct devfreq *devfreq) if (!devfreq) return -EINVAL; - if (!devfreq->governor) + mutex_lock(&devfreq->event_lock); + if (!devfreq->governor || devfreq->dev_suspended) { + mutex_unlock(&devfreq->event_lock); return 0; + } - mutex_lock(&devfreq->event_lock); ret = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_SUSPEND, NULL); + if (!ret) + devfreq->dev_suspended = true; mutex_unlock(&devfreq->event_lock); return ret; } @@ -820,12 +825,16 @@ int devfreq_resume_device(struct devfreq *devfreq) if (!devfreq) return -EINVAL; - if (!devfreq->governor) + mutex_lock(&devfreq->event_lock); + if (!devfreq->governor) { + mutex_unlock(&devfreq->event_lock); return 0; + } - mutex_lock(&devfreq->event_lock); ret = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_RESUME, NULL); + if (!ret) + devfreq->dev_suspended = false; mutex_unlock(&devfreq->event_lock); return ret; } @@ -988,6 +997,10 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, } mutex_lock(&df->event_lock); + if (df->dev_suspended) { + ret = -EINVAL; + goto gov_stop_out; + } if (df->governor) { ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL); if (ret) { diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index 66de6578b694..1c31e4017af2 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -193,6 +193,7 @@ struct devfreq { unsigned long last_stat_updated; struct srcu_notifier_head transition_notifier_list; + bool dev_suspended; }; struct devfreq_freqs {