summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2019-07-03 05:33:14 -0400
committerViresh Kumar <viresh.kumar@linaro.org>2019-07-26 03:55:52 -0400
commit11e1a1648298656722fe206a53e555e2e98668ae (patch)
tree09baf01360b13b1cc995c8620b0b5c51af52bc5d
parent71419d84c216cee8da3b19fb843b4242f112cde4 (diff)
opp: Don't decrement uninitialized list_kref
The list_kref was added for static OPPs and to track their users. The kref is initialized while the static OPPs are added, but removed unconditionally even if the static OPPs were never added. This causes refcount mismatch warnings currently. Fix that by always initializing the kref when the OPP table is first initialized. The refcount is later incremented only for the second user onwards. Fixes: d0e8ae6c26da ("OPP: Create separate kref for static OPPs list") Reported-by: Rajendra Nayak <rnayak@codeaurora.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--drivers/opp/core.c1
-rw-r--r--drivers/opp/of.c21
2 files changed, 5 insertions, 17 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 0ee8c0133d3e..9ff0538ee83a 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -988,6 +988,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
988 BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head); 988 BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head);
989 INIT_LIST_HEAD(&opp_table->opp_list); 989 INIT_LIST_HEAD(&opp_table->opp_list);
990 kref_init(&opp_table->kref); 990 kref_init(&opp_table->kref);
991 kref_init(&opp_table->list_kref);
991 992
992 /* Secure the device table modification */ 993 /* Secure the device table modification */
993 list_add(&opp_table->node, &opp_tables); 994 list_add(&opp_table->node, &opp_tables);
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index b313aca9894f..698a92c3c17b 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -662,8 +662,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
662 return 0; 662 return 0;
663 } 663 }
664 664
665 kref_init(&opp_table->list_kref);
666
667 /* We have opp-table node now, iterate over it and add OPPs */ 665 /* We have opp-table node now, iterate over it and add OPPs */
668 for_each_available_child_of_node(opp_table->np, np) { 666 for_each_available_child_of_node(opp_table->np, np) {
669 opp = _opp_add_static_v2(opp_table, dev, np); 667 opp = _opp_add_static_v2(opp_table, dev, np);
@@ -672,17 +670,15 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
672 dev_err(dev, "%s: Failed to add OPP, %d\n", __func__, 670 dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
673 ret); 671 ret);
674 of_node_put(np); 672 of_node_put(np);
675 goto put_list_kref; 673 return ret;
676 } else if (opp) { 674 } else if (opp) {
677 count++; 675 count++;
678 } 676 }
679 } 677 }
680 678
681 /* There should be one of more OPP defined */ 679 /* There should be one of more OPP defined */
682 if (WARN_ON(!count)) { 680 if (WARN_ON(!count))
683 ret = -ENOENT; 681 return -ENOENT;
684 goto put_list_kref;
685 }
686 682
687 list_for_each_entry(opp, &opp_table->opp_list, node) 683 list_for_each_entry(opp, &opp_table->opp_list, node)
688 pstate_count += !!opp->pstate; 684 pstate_count += !!opp->pstate;
@@ -691,8 +687,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
691 if (pstate_count && pstate_count != count) { 687 if (pstate_count && pstate_count != count) {
692 dev_err(dev, "Not all nodes have performance state set (%d: %d)\n", 688 dev_err(dev, "Not all nodes have performance state set (%d: %d)\n",
693 count, pstate_count); 689 count, pstate_count);
694 ret = -ENOENT; 690 return -ENOENT;
695 goto put_list_kref;
696 } 691 }
697 692
698 if (pstate_count) 693 if (pstate_count)
@@ -701,11 +696,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
701 opp_table->parsed_static_opps = true; 696 opp_table->parsed_static_opps = true;
702 697
703 return 0; 698 return 0;
704
705put_list_kref:
706 _put_opp_list_kref(opp_table);
707
708 return ret;
709} 699}
710 700
711/* Initializes OPP tables based on old-deprecated bindings */ 701/* Initializes OPP tables based on old-deprecated bindings */
@@ -731,8 +721,6 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
731 return -EINVAL; 721 return -EINVAL;
732 } 722 }
733 723
734 kref_init(&opp_table->list_kref);
735
736 val = prop->value; 724 val = prop->value;
737 while (nr) { 725 while (nr) {
738 unsigned long freq = be32_to_cpup(val++) * 1000; 726 unsigned long freq = be32_to_cpup(val++) * 1000;
@@ -742,7 +730,6 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
742 if (ret) { 730 if (ret) {
743 dev_err(dev, "%s: Failed to add OPP %ld (%d)\n", 731 dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
744 __func__, freq, ret); 732 __func__, freq, ret);
745 _put_opp_list_kref(opp_table);
746 return ret; 733 return ret;
747 } 734 }
748 nr -= 2; 735 nr -= 2;