Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e42d9b00 authored by Rama Aparna Mallavarapu's avatar Rama Aparna Mallavarapu
Browse files

devfreq: bwmon: Serialize update_devfreq with governor start/stop()



Currently gov start/stop could run in parallel when update_devfreq()
is in progress. start/stop could disable the clk which is necessary
for update_devfreq() to do its job.

The following is the race condition that could cause a crash.

T0:					T1:

					/* Governor switch from
					 * BWMON to Perf
					 */

update_devfreq()			governor_store()
devfreq_bw_hwmon_get_freq()		df->governor->event_handler(df,
						DEVFREQ_GOV_STOP, NULL);
get_bw_and_set_irq()			gov_stop()
....					hw->stop_hwmon(hw)
if (hw->set_hw_events) {		__stop_bw_hwmon()
    hw->down_cnt = node->down_count;	mon_clk_disable()
    hw->set_hw_events(hw, node->sample_ms);
}
.....
set_hw_events()
__set_hw_events()
mon_enable()

Ensure the two operations do not race by taking the devfreq->lock.

Change-Id: Ieff6d6d7feff98ede1e6673ee208a98a4f493cf9
Signed-off-by: default avatarRama Aparna Mallavarapu <aparnam@codeaurora.org>
parent 3b501c04
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -590,9 +590,11 @@ static int gov_start(struct devfreq *df)
	struct bw_hwmon *hw;
	struct devfreq_dev_status stat;

	mutex_lock(&df->lock);
	node = find_hwmon_node(df);
	if (!node) {
		dev_err(dev, "Unable to find HW monitor!\n");
		mutex_unlock(&df->lock);
		return -ENODEV;
	}
	hw = node->hw;
@@ -617,6 +619,7 @@ static int gov_start(struct devfreq *df)
	if (ret)
		goto err_sysfs;

	mutex_unlock(&df->lock);
	return 0;

err_sysfs:
@@ -626,6 +629,7 @@ static int gov_start(struct devfreq *df)
	node->orig_data = NULL;
	hw->df = NULL;
	node->dev_ab = NULL;
	mutex_unlock(&df->lock);
	return ret;
}

@@ -634,6 +638,7 @@ static void gov_stop(struct devfreq *df)
	struct hwmon_node *node = df->data;
	struct bw_hwmon *hw = node->hw;

	mutex_lock(&df->lock);
	sysfs_remove_group(&df->dev.kobj, node->attr_grp);
	stop_monitor(df, true);
	df->data = node->orig_data;
@@ -648,6 +653,7 @@ static void gov_stop(struct devfreq *df)
	if (node->dev_ab)
		*node->dev_ab = 0;
	node->dev_ab = NULL;
	mutex_unlock(&df->lock);
}

static int gov_suspend(struct devfreq *df)