diff mbox series

cpufreq: qcom-hw: Don't do lmh things without a throttle interrupt

Message ID 20220616224531.3139080-1-swboyd@chromium.org
State Accepted
Commit 668a7a12ded7077d4fd7ad1305667e559907e5bb
Headers show
Series cpufreq: qcom-hw: Don't do lmh things without a throttle interrupt | expand

Commit Message

Stephen Boyd June 16, 2022, 10:45 p.m. UTC
Offlining cpu6 and cpu7 and then onlining cpu6 hangs on
sc7180-trogdor-lazor because the throttle interrupt doesn't exist.
Similarly, things go sideways when suspend/resume runs. That's because
the qcom_cpufreq_hw_cpu_online() and qcom_cpufreq_hw_lmh_exit()
functions are calling genirq APIs with an interrupt value of '-6', i.e.
-ENXIO, and that isn't good.

Check the value of the throttle interrupt like we already do in other
functions in this file and bail out early from lmh code to fix the hang.

Reported-by: Rob Clark <robdclark@chromium.org>
Cc: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Fixes: a1eb080a0447 ("cpufreq: qcom-hw: provide online/offline operations")
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/cpufreq/qcom-cpufreq-hw.c | 6 ++++++
 1 file changed, 6 insertions(+)


base-commit: f2906aa863381afb0015a9eb7fefad885d4e5a56

Comments

Vladimir Zapolskiy June 17, 2022, 12:21 a.m. UTC | #1
On 6/17/22 01:45, Stephen Boyd wrote:
> Offlining cpu6 and cpu7 and then onlining cpu6 hangs on
> sc7180-trogdor-lazor because the throttle interrupt doesn't exist.
> Similarly, things go sideways when suspend/resume runs. That's because
> the qcom_cpufreq_hw_cpu_online() and qcom_cpufreq_hw_lmh_exit()
> functions are calling genirq APIs with an interrupt value of '-6', i.e.
> -ENXIO, and that isn't good.
> 
> Check the value of the throttle interrupt like we already do in other
> functions in this file and bail out early from lmh code to fix the hang.
> 
> Reported-by: Rob Clark <robdclark@chromium.org>
> Cc: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
> Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
> Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> Fixes: a1eb080a0447 ("cpufreq: qcom-hw: provide online/offline operations")
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
>   drivers/cpufreq/qcom-cpufreq-hw.c | 6 ++++++
>   1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
> index 0253731d6d25..36c79580fba2 100644
> --- a/drivers/cpufreq/qcom-cpufreq-hw.c
> +++ b/drivers/cpufreq/qcom-cpufreq-hw.c
> @@ -442,6 +442,9 @@ static int qcom_cpufreq_hw_cpu_online(struct cpufreq_policy *policy)
>   	struct platform_device *pdev = cpufreq_get_driver_data();
>   	int ret;
>   
> +	if (data->throttle_irq <= 0)
> +		return 0;
> +
>   	ret = irq_set_affinity_hint(data->throttle_irq, policy->cpus);
>   	if (ret)
>   		dev_err(&pdev->dev, "Failed to set CPU affinity of %s[%d]\n",
> @@ -469,6 +472,9 @@ static int qcom_cpufreq_hw_cpu_offline(struct cpufreq_policy *policy)
>   
>   static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data)
>   {
> +	if (data->throttle_irq <= 0)
> +		return;
> +
>   	free_irq(data->throttle_irq, data);
>   }
>   
> 
Reviewed-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>

--
Best wishes,
Vladimir
diff mbox series

Patch

diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index 0253731d6d25..36c79580fba2 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -442,6 +442,9 @@  static int qcom_cpufreq_hw_cpu_online(struct cpufreq_policy *policy)
 	struct platform_device *pdev = cpufreq_get_driver_data();
 	int ret;
 
+	if (data->throttle_irq <= 0)
+		return 0;
+
 	ret = irq_set_affinity_hint(data->throttle_irq, policy->cpus);
 	if (ret)
 		dev_err(&pdev->dev, "Failed to set CPU affinity of %s[%d]\n",
@@ -469,6 +472,9 @@  static int qcom_cpufreq_hw_cpu_offline(struct cpufreq_policy *policy)
 
 static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data)
 {
+	if (data->throttle_irq <= 0)
+		return;
+
 	free_irq(data->throttle_irq, data);
 }