On 7/27/21 11:50 PM, Viresh Kumar wrote:
On 27-07-21, 11:25, Thara Gopinath wrote:
+static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
+{
+ /* In the unlikely case cpufreq is de-registered do not enable polling or h/w interrupt */
+
+ spin_lock(&data->throttle_lock);
+ if (data->cancel_throttle) {
+ spin_unlock(&data->throttle_lock);
+ return;
+ }
+ spin_unlock(&data->throttle_lock);
+
+ /*
+ * If h/w throttled frequency is higher than what cpufreq has requested for, stop
+ * polling and switch back to interrupt mechanism
+ */
+
+ if (throttled_freq >= qcom_cpufreq_hw_get(cpumask_first(policy->cpus)))
+ /* Clear the existing interrupts and enable it back */
+ enable_irq(data->throttle_irq);
+ else
+ mod_delayed_work(system_highpri_wq, &data->throttle_work,
+ msecs_to_jiffies(10));
+}
+static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data)
+{
+ if (data->throttle_irq <= 0)
+ return;
+
+ spin_lock(&data->throttle_lock);
+ data->cancel_throttle = true;
+ spin_unlock(&data->throttle_lock);
+ cancel_delayed_work_sync(&data->throttle_work);
+ free_irq(data->throttle_irq, data);
+}
Lets see if we can still make it break :)
CPU0 CPU1
qcom_lmh_dcvs_notify() qcom_cpufreq_hw_lmh_exit()
spin_unlock()
spin_lock(),
cancel_throttle = true
spin_unlock()
cancel_delayed_work_sync()
mod_delayed_work()
free_irq()
kfree(data)
qcom_lmh_dcvs_poll()
Uses data.
Sorry, locking is fun :)
Ha! I was too lazy to write this down! So how about I make this a mutex
and put mod_delayed_work() inside the lock. So it will be something like
below
qcom_lmh_dcvs_notify() qcom_cpufreq_hw_lmh_exit()
mutex_lock() mutex_lock()
if (data->cancel_throttle) { cancel_throttle = true
mutex_unlock() mutex_unlock()
return cancel_delayed_work_sync()
} free_irq()
enable_irq() / mod_delayed_work()
mutex_unlock()
I will let you break it!
--
Warm Regards
Thara (She/Her/Hers)