Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

opp: Reinitialize the list_kref before adding the static OPPs again

The list_kref reaches a count of 0 when all the static OPPs are removed,
for example when dev_pm_opp_of_cpumask_remove_table() is called, though
the actual OPP table may not get freed as it may still be referenced by
other parts of the kernel, like from a call to
dev_pm_opp_set_supported_hw(). And if we call
dev_pm_opp_of_cpumask_add_table() again at this point, we must
reinitialize the list_kref otherwise the kernel will hit a WARN() in
kref infrastructure for incrementing a kref with value 0.

Fixes: 11e1a1648298 ("opp: Don't decrement uninitialized list_kref")
Reported-by: Dmitry Osipenko <digetx@gmail.com>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

+7
+7
drivers/opp/of.c
··· 663 663 return 0; 664 664 } 665 665 666 + /* 667 + * Re-initialize list_kref every time we add static OPPs to the OPP 668 + * table as the reference count may be 0 after the last tie static OPPs 669 + * were removed. 670 + */ 671 + kref_init(&opp_table->list_kref); 672 + 666 673 /* We have opp-table node now, iterate over it and add OPPs */ 667 674 for_each_available_child_of_node(opp_table->np, np) { 668 675 opp = _opp_add_static_v2(opp_table, dev, np);