X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Fbrcm2708%2Fpatches-4.19%2F950-0757-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch;fp=target%2Flinux%2Fbrcm2708%2Fpatches-4.19%2F950-0757-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch;h=0000000000000000000000000000000000000000;hb=7d7aa2fd924c27829ec25f825481554dd81bce97;hp=acdb00fd48d63a101887d09273b5f9ec6c638983;hpb=e7bfda2c243e66a75ff966ba04c28b1590b5d24c;p=openwrt%2Fstaging%2Fchunkeey.git diff --git a/target/linux/brcm2708/patches-4.19/950-0757-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch b/target/linux/brcm2708/patches-4.19/950-0757-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch deleted file mode 100644 index acdb00fd48..0000000000 --- a/target/linux/brcm2708/patches-4.19/950-0757-cpufreq-scpi-scmi-Fix-freeing-of-dynamic-OPPs.patch +++ /dev/null @@ -1,197 +0,0 @@ -From 84a8cbf64731568c0750137ec38091a46b81d502 Mon Sep 17 00:00:00 2001 -From: Viresh Kumar -Date: Fri, 4 Jan 2019 15:14:33 +0530 -Subject: [PATCH] cpufreq: scpi/scmi: Fix freeing of dynamic OPPs - -Commit 1690d8bb91e370ab772062b79bd434ce815c4729 upstream - -Since the commit 2a4eb7358aba "OPP: Don't remove dynamic OPPs from -_dev_pm_opp_remove_table()", dynamically created OPP aren't -automatically removed anymore by dev_pm_opp_cpumask_remove_table(). This -affects the scpi and scmi cpufreq drivers which no longer free OPPs on -failures or on invocations of the policy->exit() callback. - -Create a generic OPP helper dev_pm_opp_remove_all_dynamic() which can be -called from these drivers instead of dev_pm_opp_cpumask_remove_table(). - -In dev_pm_opp_remove_all_dynamic(), we need to make sure that the -opp_list isn't getting accessed simultaneously from other parts of the -OPP core while the helper is freeing dynamic OPPs, i.e. we can't drop -the opp_table->lock while traversing through the OPP list. And to -accomplish that, this patch also creates _opp_kref_release_unlocked() -which can be called from this new helper with the opp_table lock already -held. - -Cc: 4.20 # v4.20 -Reported-by: Valentin Schneider -Fixes: 2a4eb7358aba "OPP: Don't remove dynamic OPPs from _dev_pm_opp_remove_table()" -Signed-off-by: Viresh Kumar -Tested-by: Valentin Schneider -Reviewed-by: Sudeep Holla -Signed-off-by: Rafael J. Wysocki ---- - drivers/cpufreq/scmi-cpufreq.c | 4 +-- - drivers/cpufreq/scpi-cpufreq.c | 4 +-- - drivers/opp/core.c | 63 +++++++++++++++++++++++++++++++--- - include/linux/pm_opp.h | 5 +++ - 4 files changed, 67 insertions(+), 9 deletions(-) - ---- a/drivers/cpufreq/scmi-cpufreq.c -+++ b/drivers/cpufreq/scmi-cpufreq.c -@@ -176,7 +176,7 @@ static int scmi_cpufreq_init(struct cpuf - out_free_priv: - kfree(priv); - out_free_opp: -- dev_pm_opp_cpumask_remove_table(policy->cpus); -+ dev_pm_opp_remove_all_dynamic(cpu_dev); - - return ret; - } -@@ -188,7 +188,7 @@ static int scmi_cpufreq_exit(struct cpuf - cpufreq_cooling_unregister(priv->cdev); - dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); - kfree(priv); -- dev_pm_opp_cpumask_remove_table(policy->related_cpus); -+ dev_pm_opp_remove_all_dynamic(priv->cpu_dev); - - return 0; - } ---- a/drivers/cpufreq/scpi-cpufreq.c -+++ b/drivers/cpufreq/scpi-cpufreq.c -@@ -177,7 +177,7 @@ out_free_cpufreq_table: - out_free_priv: - kfree(priv); - out_free_opp: -- dev_pm_opp_cpumask_remove_table(policy->cpus); -+ dev_pm_opp_remove_all_dynamic(cpu_dev); - - return ret; - } -@@ -190,7 +190,7 @@ static int scpi_cpufreq_exit(struct cpuf - clk_put(priv->clk); - dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); - kfree(priv); -- dev_pm_opp_cpumask_remove_table(policy->related_cpus); -+ dev_pm_opp_remove_all_dynamic(priv->cpu_dev); - - return 0; - } ---- a/drivers/opp/core.c -+++ b/drivers/opp/core.c -@@ -884,11 +884,9 @@ void _opp_free(struct dev_pm_opp *opp) - kfree(opp); - } - --static void _opp_kref_release(struct kref *kref) -+static void _opp_kref_release(struct dev_pm_opp *opp, -+ struct opp_table *opp_table) - { -- struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref); -- struct opp_table *opp_table = opp->opp_table; -- - /* - * Notify the changes in the availability of the operable - * frequency/voltage list. -@@ -897,7 +895,22 @@ static void _opp_kref_release(struct kre - opp_debug_remove_one(opp); - list_del(&opp->node); - kfree(opp); -+} -+ -+static void _opp_kref_release_unlocked(struct kref *kref) -+{ -+ struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref); -+ struct opp_table *opp_table = opp->opp_table; -+ -+ _opp_kref_release(opp, opp_table); -+} - -+static void _opp_kref_release_locked(struct kref *kref) -+{ -+ struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref); -+ struct opp_table *opp_table = opp->opp_table; -+ -+ _opp_kref_release(opp, opp_table); - mutex_unlock(&opp_table->lock); - dev_pm_opp_put_opp_table(opp_table); - } -@@ -909,10 +922,16 @@ void dev_pm_opp_get(struct dev_pm_opp *o - - void dev_pm_opp_put(struct dev_pm_opp *opp) - { -- kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock); -+ kref_put_mutex(&opp->kref, _opp_kref_release_locked, -+ &opp->opp_table->lock); - } - EXPORT_SYMBOL_GPL(dev_pm_opp_put); - -+static void dev_pm_opp_put_unlocked(struct dev_pm_opp *opp) -+{ -+ kref_put(&opp->kref, _opp_kref_release_unlocked); -+} -+ - /** - * dev_pm_opp_remove() - Remove an OPP from OPP table - * @dev: device for which we do this operation -@@ -952,6 +971,40 @@ void dev_pm_opp_remove(struct device *de - } - EXPORT_SYMBOL_GPL(dev_pm_opp_remove); - -+/** -+ * dev_pm_opp_remove_all_dynamic() - Remove all dynamically created OPPs -+ * @dev: device for which we do this operation -+ * -+ * This function removes all dynamically created OPPs from the opp table. -+ */ -+void dev_pm_opp_remove_all_dynamic(struct device *dev) -+{ -+ struct opp_table *opp_table; -+ struct dev_pm_opp *opp, *temp; -+ int count = 0; -+ -+ opp_table = _find_opp_table(dev); -+ if (IS_ERR(opp_table)) -+ return; -+ -+ mutex_lock(&opp_table->lock); -+ list_for_each_entry_safe(opp, temp, &opp_table->opp_list, node) { -+ if (opp->dynamic) { -+ dev_pm_opp_put_unlocked(opp); -+ count++; -+ } -+ } -+ mutex_unlock(&opp_table->lock); -+ -+ /* Drop the references taken by dev_pm_opp_add() */ -+ while (count--) -+ dev_pm_opp_put_opp_table(opp_table); -+ -+ /* Drop the reference taken by _find_opp_table() */ -+ dev_pm_opp_put_opp_table(opp_table); -+} -+EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic); -+ - struct dev_pm_opp *_opp_allocate(struct opp_table *table) - { - struct dev_pm_opp *opp; ---- a/include/linux/pm_opp.h -+++ b/include/linux/pm_opp.h -@@ -107,6 +107,7 @@ void dev_pm_opp_put(struct dev_pm_opp *o - int dev_pm_opp_add(struct device *dev, unsigned long freq, - unsigned long u_volt); - void dev_pm_opp_remove(struct device *dev, unsigned long freq); -+void dev_pm_opp_remove_all_dynamic(struct device *dev); - - int dev_pm_opp_enable(struct device *dev, unsigned long freq); - -@@ -208,6 +209,10 @@ static inline void dev_pm_opp_remove(str - { - } - -+static inline void dev_pm_opp_remove_all_dynamic(struct device *dev) -+{ -+} -+ - static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq) - { - return 0;