diff options
author | Bai Ping <b51503@freescale.com> | 2015-05-22 22:39:11 +0800 |
---|---|---|
committer | Bai Ping <b51503@freescale.com> | 2015-06-03 00:47:49 +0800 |
commit | 18d5b09e437c25b33eb43e7c65420b5cad26275f (patch) | |
tree | c1f41a440f98940d94e21f9dd6d2b13d25662c74 | |
parent | 306a1b45c88451bcbe289bc911f3c52d1fd80862 (diff) |
MLK-10960 thermal: imx: add a mutex to make sure tempmon setting changed safely
The busfreq notifier and thermal_zone updating run asynchronously. In some critical
situaiton, the notifier callback may be interrupted by thermal_zone kthread, it will
lead to the TEMPMON setting uncompleted when the get_temp function reads the
temp sensor value.
Signed-off-by: Bai Ping <b51503@freescale.com>
-rw-r--r-- | drivers/thermal/imx_thermal.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index db37eec4f6e8..a5e72d7ac996 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -106,6 +106,7 @@ struct imx_thermal_data { bool irq_enabled; int irq; struct clk *thermal_clk; + struct mutex mutex; const struct thermal_soc_data *socdata; }; @@ -144,6 +145,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp) bool wait; u32 val; + mutex_lock(&data->mutex); if (data->mode == THERMAL_DEVICE_ENABLED) { /* Check if a measurement is currently in progress */ regmap_read(map, TEMPSENSE0, &val); @@ -178,6 +180,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp) if ((val & TEMPSENSE0_FINISHED) == 0) { dev_dbg(&tz->device, "temp measurement never finished\n"); + mutex_unlock(&data->mutex); return -EAGAIN; } @@ -205,6 +208,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp) data->irq_enabled = true; enable_irq(data->irq); } + mutex_unlock(&data->mutex); return 0; } @@ -480,6 +484,8 @@ static int thermal_notifier_event(struct notifier_block *this, { struct regmap *map = imx_thermal_data->tempmon; + mutex_lock(&imx_thermal_data->mutex); + switch (event) { /* * In low_bus_freq_mode, the thermal sensor auto measurement @@ -505,6 +511,8 @@ static int thermal_notifier_event(struct notifier_block *this, default: break; } + mutex_unlock(&imx_thermal_data->mutex); + return NOTIFY_OK; } @@ -553,6 +561,7 @@ static int imx_thermal_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "failed to enable thermal clk: %d\n", ret); } + mutex_init(&data->mutex); /* make sure the IRQ flag is clear before enable irq */ regmap_write(map, MISC1 + REG_CLR, MISC1_IRQ_TEMPHIGH); if (data->socdata->version == TEMPMON_V2) { |