Merge branches 'pm-devfreq' and 'pm-opp'

Merge devfreq and OPP (Operating Performance Points) updates for 6.14:

- Clean up the Exynos devfreq driver and devfreq core (Markus Elfring,
Jeongjun Park).

- Minor cleanups and fixes for OPP (Dan Carpenter, Neil Armstrong, Joe
Hattori).

- Implement dev_pm_opp_get_bw() (Neil Armstrong).

- Expose OPP reference counting helpers for Rust (Viresh Kumar).

* pm-devfreq:
PM / devfreq: exynos: remove unused function parameter
PM / devfreq: event: Call of_node_put() only once in devfreq_event_get_edev_by_phandle()

* pm-opp:
PM / OPP: Add reference counting helpers for Rust implementation
OPP: OF: Fix an OF node leak in _opp_add_static_v2()
OPP: fix dev_pm_opp_find_bw_*() when bandwidth table not initialized
OPP: add index check to assert to avoid buffer overflow in _read_freq()
opp: core: Fix off by one in dev_pm_opp_get_bw()
opp: core: implement dev_pm_opp_get_bw

+97 -33
+2 -6
drivers/devfreq/devfreq-event.c
··· 244 edev = NULL; 245 out: 246 mutex_unlock(&devfreq_event_list_lock); 247 - 248 - if (!edev) { 249 - of_node_put(node); 250 - return ERR_PTR(-ENODEV); 251 - } 252 - 253 of_node_put(node); 254 255 return edev; 256 }
··· 244 edev = NULL; 245 out: 246 mutex_unlock(&devfreq_event_list_lock); 247 of_node_put(node); 248 + if (!edev) 249 + return ERR_PTR(-ENODEV); 250 251 return edev; 252 }
+2 -3
drivers/devfreq/exynos-bus.c
··· 236 return ret; 237 } 238 239 - static int exynos_bus_parse_of(struct device_node *np, 240 - struct exynos_bus *bus) 241 { 242 struct device *dev = bus->dev; 243 struct dev_pm_opp *opp; ··· 407 } 408 409 /* Parse the device-tree to get the resource information */ 410 - ret = exynos_bus_parse_of(np, bus); 411 if (ret < 0) 412 goto err_reg; 413
··· 236 return ret; 237 } 238 239 + static int exynos_bus_parse_of(struct exynos_bus *bus) 240 { 241 struct device *dev = bus->dev; 242 struct dev_pm_opp *opp; ··· 408 } 409 410 /* Parse the device-tree to get the resource information */ 411 + ret = exynos_bus_parse_of(bus); 412 if (ret < 0) 413 goto err_reg; 414
+77 -22
drivers/opp/core.c
··· 101 * representation in the OPP table and manage the clock configuration themselves 102 * in an platform specific way. 103 */ 104 - static bool assert_single_clk(struct opp_table *opp_table) 105 { 106 return !WARN_ON(opp_table->clk_count > 1); 107 } 108 109 /** 110 * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp ··· 543 unsigned long (*read)(struct dev_pm_opp *opp, int index), 544 bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp, 545 unsigned long opp_key, unsigned long key), 546 - bool (*assert)(struct opp_table *opp_table)) 547 { 548 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); 549 550 /* Assert that the requirement is met */ 551 - if (assert && !assert(opp_table)) 552 return ERR_PTR(-EINVAL); 553 554 mutex_lock(&opp_table->lock); ··· 576 unsigned long (*read)(struct dev_pm_opp *opp, int index), 577 bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp, 578 unsigned long opp_key, unsigned long key), 579 - bool (*assert)(struct opp_table *opp_table)) 580 { 581 struct opp_table *opp_table; 582 struct dev_pm_opp *opp; ··· 599 static struct dev_pm_opp *_find_key_exact(struct device *dev, 600 unsigned long key, int index, bool available, 601 unsigned long (*read)(struct dev_pm_opp *opp, int index), 602 - bool (*assert)(struct opp_table *opp_table)) 603 { 604 /* 605 * The value of key will be updated here, but will be ignored as the ··· 612 static struct dev_pm_opp *_opp_table_find_key_ceil(struct opp_table *opp_table, 613 unsigned long *key, int index, bool available, 614 unsigned long (*read)(struct dev_pm_opp *opp, int index), 615 - bool (*assert)(struct opp_table *opp_table)) 616 { 617 return _opp_table_find_key(opp_table, key, index, available, read, 618 _compare_ceil, assert); ··· 621 static struct dev_pm_opp *_find_key_ceil(struct device *dev, unsigned long *key, 622 int index, bool available, 623 unsigned long (*read)(struct dev_pm_opp *opp, int index), 624 - bool (*assert)(struct opp_table *opp_table)) 625 { 626 return _find_key(dev, key, index, available, read, _compare_ceil, 627 assert); ··· 630 static struct dev_pm_opp *_find_key_floor(struct device *dev, 631 unsigned long *key, int index, bool available, 632 unsigned long (*read)(struct dev_pm_opp *opp, int index), 633 - bool (*assert)(struct opp_table *opp_table)) 634 { 635 return _find_key(dev, key, index, available, read, _compare_floor, 636 assert); ··· 691 dev_pm_opp_find_freq_exact_indexed(struct device *dev, unsigned long freq, 692 u32 index, bool available) 693 { 694 - return _find_key_exact(dev, freq, index, available, _read_freq, NULL); 695 } 696 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact_indexed); 697 ··· 752 dev_pm_opp_find_freq_ceil_indexed(struct device *dev, unsigned long *freq, 753 u32 index) 754 { 755 - return _find_key_ceil(dev, freq, index, true, _read_freq, NULL); 756 } 757 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil_indexed); 758 ··· 806 dev_pm_opp_find_freq_floor_indexed(struct device *dev, unsigned long *freq, 807 u32 index) 808 { 809 - return _find_key_floor(dev, freq, index, true, _read_freq, NULL); 810 } 811 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor_indexed); 812 ··· 924 unsigned long temp = *bw; 925 struct dev_pm_opp *opp; 926 927 - opp = _find_key_ceil(dev, &temp, index, true, _read_bw, NULL); 928 *bw = temp; 929 return opp; 930 } ··· 956 unsigned long temp = *bw; 957 struct dev_pm_opp *opp; 958 959 - opp = _find_key_floor(dev, &temp, index, true, _read_bw, NULL); 960 *bw = temp; 961 return opp; 962 } ··· 1528 return ERR_PTR(ret); 1529 } 1530 1531 - void _get_opp_table_kref(struct opp_table *opp_table) 1532 - { 1533 - kref_get(&opp_table->kref); 1534 - } 1535 - 1536 static struct opp_table *_update_opp_table_clk(struct device *dev, 1537 struct opp_table *opp_table, 1538 bool getclk) ··· 1688 kfree(opp_table); 1689 } 1690 1691 void dev_pm_opp_put_opp_table(struct opp_table *opp_table) 1692 { 1693 kref_put_mutex(&opp_table->kref, _opp_table_kref_release, ··· 1733 { 1734 kref_get(&opp->kref); 1735 } 1736 1737 void dev_pm_opp_put(struct dev_pm_opp *opp) 1738 { ··· 1757 if (IS_ERR(opp_table)) 1758 return; 1759 1760 - if (!assert_single_clk(opp_table)) 1761 goto put_table; 1762 1763 mutex_lock(&opp_table->lock); ··· 2109 unsigned long tol, u_volt = data->u_volt; 2110 int ret; 2111 2112 - if (!assert_single_clk(opp_table)) 2113 return -EINVAL; 2114 2115 new_opp = _opp_allocate(opp_table); ··· 2865 return r; 2866 } 2867 2868 - if (!assert_single_clk(opp_table)) { 2869 r = -EINVAL; 2870 goto put_table; 2871 } ··· 2941 return r; 2942 } 2943 2944 - if (!assert_single_clk(opp_table)) { 2945 r = -EINVAL; 2946 goto put_table; 2947 }
··· 101 * representation in the OPP table and manage the clock configuration themselves 102 * in an platform specific way. 103 */ 104 + static bool assert_single_clk(struct opp_table *opp_table, 105 + unsigned int __always_unused index) 106 { 107 return !WARN_ON(opp_table->clk_count > 1); 108 } 109 + 110 + /* 111 + * Returns true if clock table is large enough to contain the clock index. 112 + */ 113 + static bool assert_clk_index(struct opp_table *opp_table, 114 + unsigned int index) 115 + { 116 + return opp_table->clk_count > index; 117 + } 118 + 119 + /* 120 + * Returns true if bandwidth table is large enough to contain the bandwidth index. 121 + */ 122 + static bool assert_bandwidth_index(struct opp_table *opp_table, 123 + unsigned int index) 124 + { 125 + return opp_table->path_count > index; 126 + } 127 + 128 + /** 129 + * dev_pm_opp_get_bw() - Gets the bandwidth corresponding to an opp 130 + * @opp: opp for which bandwidth has to be returned for 131 + * @peak: select peak or average bandwidth 132 + * @index: bandwidth index 133 + * 134 + * Return: bandwidth in kBps, else return 0 135 + */ 136 + unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index) 137 + { 138 + if (IS_ERR_OR_NULL(opp)) { 139 + pr_err("%s: Invalid parameters\n", __func__); 140 + return 0; 141 + } 142 + 143 + if (index >= opp->opp_table->path_count) 144 + return 0; 145 + 146 + if (!opp->bandwidth) 147 + return 0; 148 + 149 + return peak ? opp->bandwidth[index].peak : opp->bandwidth[index].avg; 150 + } 151 + EXPORT_SYMBOL_GPL(dev_pm_opp_get_bw); 152 153 /** 154 * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp ··· 499 unsigned long (*read)(struct dev_pm_opp *opp, int index), 500 bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp, 501 unsigned long opp_key, unsigned long key), 502 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 503 { 504 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); 505 506 /* Assert that the requirement is met */ 507 + if (assert && !assert(opp_table, index)) 508 return ERR_PTR(-EINVAL); 509 510 mutex_lock(&opp_table->lock); ··· 532 unsigned long (*read)(struct dev_pm_opp *opp, int index), 533 bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp, 534 unsigned long opp_key, unsigned long key), 535 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 536 { 537 struct opp_table *opp_table; 538 struct dev_pm_opp *opp; ··· 555 static struct dev_pm_opp *_find_key_exact(struct device *dev, 556 unsigned long key, int index, bool available, 557 unsigned long (*read)(struct dev_pm_opp *opp, int index), 558 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 559 { 560 /* 561 * The value of key will be updated here, but will be ignored as the ··· 568 static struct dev_pm_opp *_opp_table_find_key_ceil(struct opp_table *opp_table, 569 unsigned long *key, int index, bool available, 570 unsigned long (*read)(struct dev_pm_opp *opp, int index), 571 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 572 { 573 return _opp_table_find_key(opp_table, key, index, available, read, 574 _compare_ceil, assert); ··· 577 static struct dev_pm_opp *_find_key_ceil(struct device *dev, unsigned long *key, 578 int index, bool available, 579 unsigned long (*read)(struct dev_pm_opp *opp, int index), 580 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 581 { 582 return _find_key(dev, key, index, available, read, _compare_ceil, 583 assert); ··· 586 static struct dev_pm_opp *_find_key_floor(struct device *dev, 587 unsigned long *key, int index, bool available, 588 unsigned long (*read)(struct dev_pm_opp *opp, int index), 589 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 590 { 591 return _find_key(dev, key, index, available, read, _compare_floor, 592 assert); ··· 647 dev_pm_opp_find_freq_exact_indexed(struct device *dev, unsigned long freq, 648 u32 index, bool available) 649 { 650 + return _find_key_exact(dev, freq, index, available, _read_freq, 651 + assert_clk_index); 652 } 653 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact_indexed); 654 ··· 707 dev_pm_opp_find_freq_ceil_indexed(struct device *dev, unsigned long *freq, 708 u32 index) 709 { 710 + return _find_key_ceil(dev, freq, index, true, _read_freq, 711 + assert_clk_index); 712 } 713 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil_indexed); 714 ··· 760 dev_pm_opp_find_freq_floor_indexed(struct device *dev, unsigned long *freq, 761 u32 index) 762 { 763 + return _find_key_floor(dev, freq, index, true, _read_freq, assert_clk_index); 764 } 765 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor_indexed); 766 ··· 878 unsigned long temp = *bw; 879 struct dev_pm_opp *opp; 880 881 + opp = _find_key_ceil(dev, &temp, index, true, _read_bw, 882 + assert_bandwidth_index); 883 *bw = temp; 884 return opp; 885 } ··· 909 unsigned long temp = *bw; 910 struct dev_pm_opp *opp; 911 912 + opp = _find_key_floor(dev, &temp, index, true, _read_bw, 913 + assert_bandwidth_index); 914 *bw = temp; 915 return opp; 916 } ··· 1480 return ERR_PTR(ret); 1481 } 1482 1483 static struct opp_table *_update_opp_table_clk(struct device *dev, 1484 struct opp_table *opp_table, 1485 bool getclk) ··· 1645 kfree(opp_table); 1646 } 1647 1648 + void _get_opp_table_kref(struct opp_table *opp_table) 1649 + { 1650 + kref_get(&opp_table->kref); 1651 + } 1652 + 1653 + void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table) 1654 + { 1655 + _get_opp_table_kref(opp_table); 1656 + } 1657 + EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table_ref); 1658 + 1659 void dev_pm_opp_put_opp_table(struct opp_table *opp_table) 1660 { 1661 kref_put_mutex(&opp_table->kref, _opp_table_kref_release, ··· 1679 { 1680 kref_get(&opp->kref); 1681 } 1682 + EXPORT_SYMBOL_GPL(dev_pm_opp_get); 1683 1684 void dev_pm_opp_put(struct dev_pm_opp *opp) 1685 { ··· 1702 if (IS_ERR(opp_table)) 1703 return; 1704 1705 + if (!assert_single_clk(opp_table, 0)) 1706 goto put_table; 1707 1708 mutex_lock(&opp_table->lock); ··· 2054 unsigned long tol, u_volt = data->u_volt; 2055 int ret; 2056 2057 + if (!assert_single_clk(opp_table, 0)) 2058 return -EINVAL; 2059 2060 new_opp = _opp_allocate(opp_table); ··· 2810 return r; 2811 } 2812 2813 + if (!assert_single_clk(opp_table, 0)) { 2814 r = -EINVAL; 2815 goto put_table; 2816 } ··· 2886 return r; 2887 } 2888 2889 + if (!assert_single_clk(opp_table, 0)) { 2890 r = -EINVAL; 2891 goto put_table; 2892 }
+3 -1
drivers/opp/of.c
··· 926 927 ret = _of_opp_alloc_required_opps(opp_table, new_opp); 928 if (ret) 929 - goto free_opp; 930 931 if (!of_property_read_u32(np, "clock-latency-ns", &val)) 932 new_opp->clock_latency_ns = val; ··· 976 977 free_required_opps: 978 _of_opp_free_required_opps(opp_table, new_opp); 979 free_opp: 980 _opp_free(new_opp); 981
··· 926 927 ret = _of_opp_alloc_required_opps(opp_table, new_opp); 928 if (ret) 929 + goto put_node; 930 931 if (!of_property_read_u32(np, "clock-latency-ns", &val)) 932 new_opp->clock_latency_ns = val; ··· 976 977 free_required_opps: 978 _of_opp_free_required_opps(opp_table, new_opp); 979 + put_node: 980 + of_node_put(np); 981 free_opp: 982 _opp_free(new_opp); 983
-1
drivers/opp/opp.h
··· 250 }; 251 252 /* Routines internal to opp core */ 253 - void dev_pm_opp_get(struct dev_pm_opp *opp); 254 bool _opp_remove_all_static(struct opp_table *opp_table); 255 void _get_opp_table_kref(struct opp_table *opp_table); 256 int _get_opp_count(struct opp_table *opp_table);
··· 250 }; 251 252 /* Routines internal to opp core */ 253 bool _opp_remove_all_static(struct opp_table *opp_table); 254 void _get_opp_table_kref(struct opp_table *opp_table); 255 int _get_opp_count(struct opp_table *opp_table);
+13
include/linux/pm_opp.h
··· 100 #if defined(CONFIG_PM_OPP) 101 102 struct opp_table *dev_pm_opp_get_opp_table(struct device *dev); 103 void dev_pm_opp_put_opp_table(struct opp_table *opp_table); 104 105 unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp); 106 ··· 161 struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev, 162 unsigned int *bw, int index); 163 164 void dev_pm_opp_put(struct dev_pm_opp *opp); 165 166 int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp); ··· 207 return ERR_PTR(-EOPNOTSUPP); 208 } 209 210 static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {} 211 212 static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) 213 { ··· 344 { 345 return ERR_PTR(-EOPNOTSUPP); 346 } 347 348 static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {} 349
··· 100 #if defined(CONFIG_PM_OPP) 101 102 struct opp_table *dev_pm_opp_get_opp_table(struct device *dev); 103 + void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table); 104 void dev_pm_opp_put_opp_table(struct opp_table *opp_table); 105 + 106 + unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index); 107 108 unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp); 109 ··· 158 struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev, 159 unsigned int *bw, int index); 160 161 + void dev_pm_opp_get(struct dev_pm_opp *opp); 162 void dev_pm_opp_put(struct dev_pm_opp *opp); 163 164 int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp); ··· 203 return ERR_PTR(-EOPNOTSUPP); 204 } 205 206 + static inline void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table) {} 207 + 208 static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {} 209 + 210 + static inline unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index) 211 + { 212 + return 0; 213 + } 214 215 static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) 216 { ··· 333 { 334 return ERR_PTR(-EOPNOTSUPP); 335 } 336 + 337 + static inline void dev_pm_opp_get(struct dev_pm_opp *opp) {} 338 339 static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {} 340