History

Merge branch 'opp/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm

Pull operating performance points (OPP) framework changes for v5.3 from Viresh Kumar: "This pull request contains: - OPP core changes to support a wider range of devices, like IO devices (Rajendra Nayak and Stehpen Boyd). - Fixes around genpd_virt_devs (Viresh Kumar). - Fix for platform with set_opp() callback (Dmitry Osipenko)." * 'opp/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm: opp: Don't use IS_ERR on invalid supplies opp: Make dev_pm_opp_set_rate() handle freq = 0 to drop performance votes opp: Don't overwrite rounded clk rate opp: Allocate genpd_virt_devs from dev_pm_opp_attach_genpd() opp: Attach genpds to devices from within OPP core

Rafael J. Wysocki committed 7 years ago

Commit 41de2562 parents 4b972a0 560d1bc3 files · +121 −91Browse files

Unified · Split

3 files
  1. drivers/opp/core.c +115 −59
  2. drivers/opp/of.c +2 −28
  3. include/linux/pm_opp.h +4 −4
drivers/opp/core.c+115−59
@@ -682,7 +682,7 @@ static int _set_opp_custom(const struct opp_table *opp_table, · 681 unmodified lines
682 682
683 data->old_opp.rate = old_freq;683 data->old_opp.rate = old_freq;
684 size = sizeof(*old_supply) * opp_table->regulator_count;684 size = sizeof(*old_supply) * opp_table->regulator_count;
685 if (IS_ERR(old_supply))685 if (!old_supply)
686 memset(data->old_opp.supplies, 0, size);686 memset(data->old_opp.supplies, 0, size);
687 else687 else
688 memcpy(data->old_opp.supplies, old_supply, size);688 memcpy(data->old_opp.supplies, old_supply, size);
@@ -708,7 +708,7 @@ static int _set_required_opps(struct device *dev, · 19 unmodified lines
708 708
709 /* Single genpd case */709 /* Single genpd case */
710 if (!genpd_virt_devs) {710 if (!genpd_virt_devs) {
711 pstate = opp->required_opps[0]->pstate;711 pstate = likely(opp) ? opp->required_opps[0]->pstate : 0;
712 ret = dev_pm_genpd_set_performance_state(dev, pstate);712 ret = dev_pm_genpd_set_performance_state(dev, pstate);
713 if (ret) {713 if (ret) {
714 dev_err(dev, "Failed to set performance state of %s: %d (%d)\n",714 dev_err(dev, "Failed to set performance state of %s: %d (%d)\n",
@@ -726,7 +726,7 @@ static int _set_required_opps(struct device *dev, · 11 unmodified lines
726 mutex_lock(&opp_table->genpd_virt_dev_lock);726 mutex_lock(&opp_table->genpd_virt_dev_lock);
727 727
728 for (i = 0; i < opp_table->required_opp_count; i++) {728 for (i = 0; i < opp_table->required_opp_count; i++) {
729 pstate = opp->required_opps[i]->pstate;729 pstate = likely(opp) ? opp->required_opps[i]->pstate : 0;
730 730
731 if (!genpd_virt_devs[i])731 if (!genpd_virt_devs[i])
732 continue;732 continue;
@@ -748,29 +748,37 @@ static int _set_required_opps(struct device *dev, · 15 unmodified lines
748 * @dev: device for which we do this operation748 * @dev: device for which we do this operation
749 * @target_freq: frequency to achieve749 * @target_freq: frequency to achieve
750 *750 *
751 * This configures the power-supplies and clock source to the levels specified751 * This configures the power-supplies to the levels specified by the OPP
752 * by the OPP corresponding to the target_freq.752 * corresponding to the target_freq, and programs the clock to a value <=
753 * target_freq, as rounded by clk_round_rate(). Device wanting to run at fmax
754 * provided by the opp, should have already rounded to the target OPP's
755 * frequency.
753 */756 */
754int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)757int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
755{758{
756 struct opp_table *opp_table;759 struct opp_table *opp_table;
757 unsigned long freq, old_freq;760 unsigned long freq, old_freq, temp_freq;
758 struct dev_pm_opp *old_opp, *opp;761 struct dev_pm_opp *old_opp, *opp;
759 struct clk *clk;762 struct clk *clk;
760 int ret;763 int ret;
761 764
762 if (unlikely(!target_freq)) {
763 dev_err(dev, "%s: Invalid target frequency %lu\n", __func__,
764 target_freq);
765 return -EINVAL;
766 }
767
768 opp_table = _find_opp_table(dev);765 opp_table = _find_opp_table(dev);
769 if (IS_ERR(opp_table)) {766 if (IS_ERR(opp_table)) {
770 dev_err(dev, "%s: device opp doesn't exist\n", __func__);767 dev_err(dev, "%s: device opp doesn't exist\n", __func__);
771 return PTR_ERR(opp_table);768 return PTR_ERR(opp_table);
772 }769 }
773 770
771 if (unlikely(!target_freq)) {
772 if (opp_table->required_opp_tables) {
773 ret = _set_required_opps(dev, opp_table, NULL);
774 } else {
775 dev_err(dev, "target frequency can't be 0\n");
776 ret = -EINVAL;
777 }
778
779 goto put_opp_table;
780 }
781
774 clk = opp_table->clk;782 clk = opp_table->clk;
775 if (IS_ERR(clk)) {783 if (IS_ERR(clk)) {
776 dev_err(dev, "%s: No clock available for the device\n",784 dev_err(dev, "%s: No clock available for the device\n",
@@ -793,13 +801,15 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) · 16 unmodified lines
793 goto put_opp_table;801 goto put_opp_table;
794 }802 }
795 803
796 old_opp = _find_freq_ceil(opp_table, &old_freq);804 temp_freq = old_freq;
805 old_opp = _find_freq_ceil(opp_table, &temp_freq);
797 if (IS_ERR(old_opp)) {806 if (IS_ERR(old_opp)) {
798 dev_err(dev, "%s: failed to find current OPP for freq %lu (%ld)\n",807 dev_err(dev, "%s: failed to find current OPP for freq %lu (%ld)\n",
799 __func__, old_freq, PTR_ERR(old_opp));808 __func__, old_freq, PTR_ERR(old_opp));
800 }809 }
801 810
802 opp = _find_freq_ceil(opp_table, &freq);811 temp_freq = freq;
812 opp = _find_freq_ceil(opp_table, &temp_freq);
803 if (IS_ERR(opp)) {813 if (IS_ERR(opp)) {
804 ret = PTR_ERR(opp);814 ret = PTR_ERR(opp);
805 dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n",815 dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n",
@@ -1741,91 +1751,137 @@ void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table) · 935 unmodified lines
1741}1751}
1742EXPORT_SYMBOL_GPL(dev_pm_opp_unregister_set_opp_helper);1752EXPORT_SYMBOL_GPL(dev_pm_opp_unregister_set_opp_helper);
1743 1753
1754static void _opp_detach_genpd(struct opp_table *opp_table)
1755{
1756 int index;
1757
1758 for (index = 0; index < opp_table->required_opp_count; index++) {
1759 if (!opp_table->genpd_virt_devs[index])
1760 continue;
1761
1762 dev_pm_domain_detach(opp_table->genpd_virt_devs[index], false);
1763 opp_table->genpd_virt_devs[index] = NULL;
1764 }
1765
1766 kfree(opp_table->genpd_virt_devs);
1767 opp_table->genpd_virt_devs = NULL;
1768}
1769
1744/**1770/**
1745 * dev_pm_opp_set_genpd_virt_dev - Set virtual genpd device for an index1771 * dev_pm_opp_attach_genpd - Attach genpd(s) for the device and save virtual device pointer
1746 * @dev: Consumer device for which the genpd device is getting set.1772 * @dev: Consumer device for which the genpd is getting attached.
1747 * @virt_dev: virtual genpd device.1773 * @names: Null terminated array of pointers containing names of genpd to attach.
1748 * @index: index.
1749 *1774 *
1750 * Multiple generic power domains for a device are supported with the help of1775 * Multiple generic power domains for a device are supported with the help of
1751 * virtual genpd devices, which are created for each consumer device - genpd1776 * virtual genpd devices, which are created for each consumer device - genpd
1752 * pair. These are the device structures which are attached to the power domain1777 * pair. These are the device structures which are attached to the power domain
1753 * and are required by the OPP core to set the performance state of the genpd.1778 * and are required by the OPP core to set the performance state of the genpd.
1779 * The same API also works for the case where single genpd is available and so
1780 * we don't need to support that separately.
1754 *1781 *
1755 * This helper will normally be called by the consumer driver of the device1782 * This helper will normally be called by the consumer driver of the device
1756 * "dev", as only that has details of the genpd devices.1783 * "dev", as only that has details of the genpd names.
1757 *1784 *
1758 * This helper needs to be called once for each of those virtual devices, but1785 * This helper needs to be called once with a list of all genpd to attach.
1759 * only if multiple domains are available for a device. Otherwise the original1786 * Otherwise the original device structure will be used instead by the OPP core.
1760 * device structure will be used instead by the OPP core.
1761 */1787 */
1762struct opp_table *dev_pm_opp_set_genpd_virt_dev(struct device *dev,1788struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names)
1763 struct device *virt_dev,
1764 int index)
1765{1789{
1766 struct opp_table *opp_table;1790 struct opp_table *opp_table;
1791 struct device *virt_dev;
1792 int index, ret = -EINVAL;
1793 const char **name = names;
1767 1794
1768 opp_table = dev_pm_opp_get_opp_table(dev);1795 opp_table = dev_pm_opp_get_opp_table(dev);
1769 if (!opp_table)1796 if (!opp_table)
1770 return ERR_PTR(-ENOMEM);1797 return ERR_PTR(-ENOMEM);
1771 1798
1799 /*
1800 * If the genpd's OPP table isn't already initialized, parsing of the
1801 * required-opps fail for dev. We should retry this after genpd's OPP
1802 * table is added.
1803 */
1804 if (!opp_table->required_opp_count) {
1805 ret = -EPROBE_DEFER;
1806 goto put_table;
1807 }
1808
1772 mutex_lock(&opp_table->genpd_virt_dev_lock);1809 mutex_lock(&opp_table->genpd_virt_dev_lock);
1773 1810
1774 if (unlikely(!opp_table->genpd_virt_devs ||1811 opp_table->genpd_virt_devs = kcalloc(opp_table->required_opp_count,
1775 index >= opp_table->required_opp_count ||1812 sizeof(*opp_table->genpd_virt_devs),
1776 opp_table->genpd_virt_devs[index])) {1813 GFP_KERNEL);
1814 if (!opp_table->genpd_virt_devs)
1815 goto unlock;
1777 1816
1778 dev_err(dev, "Invalid request to set required device\n");1817 while (*name) {
1779 dev_pm_opp_put_opp_table(opp_table);1818 index = of_property_match_string(dev->of_node,
1780 mutex_unlock(&opp_table->genpd_virt_dev_lock);1819 "power-domain-names", *name);
1820 if (index < 0) {
1821 dev_err(dev, "Failed to find power domain: %s (%d)\n",
1822 *name, index);
1823 goto err;
1824 }
1781 1825
1782 return ERR_PTR(-EINVAL);1826 if (index >= opp_table->required_opp_count) {
1827 dev_err(dev, "Index can't be greater than required-opp-count - 1, %s (%d : %d)\n",
1828 *name, opp_table->required_opp_count, index);
1829 goto err;
1830 }
1831
1832 if (opp_table->genpd_virt_devs[index]) {
1833 dev_err(dev, "Genpd virtual device already set %s\n",
1834 *name);
1835 goto err;
1836 }
1837
1838 virt_dev = dev_pm_domain_attach_by_name(dev, *name);
1839 if (IS_ERR(virt_dev)) {
1840 ret = PTR_ERR(virt_dev);
1841 dev_err(dev, "Couldn't attach to pm_domain: %d\n", ret);
1842 goto err;
1843 }
1844
1845 opp_table->genpd_virt_devs[index] = virt_dev;
1846 name++;
1783 }1847 }
1784 1848
1785 opp_table->genpd_virt_devs[index] = virt_dev;
1786 mutex_unlock(&opp_table->genpd_virt_dev_lock);1849 mutex_unlock(&opp_table->genpd_virt_dev_lock);
1787 1850
1788 return opp_table;1851 return opp_table;
1852
1853err:
1854 _opp_detach_genpd(opp_table);
1855unlock:
1856 mutex_unlock(&opp_table->genpd_virt_dev_lock);
1857
1858put_table:
1859 dev_pm_opp_put_opp_table(opp_table);
1860
1861 return ERR_PTR(ret);
1789}1862}
1863EXPORT_SYMBOL_GPL(dev_pm_opp_attach_genpd);
1790 1864
1791/**1865/**
1792 * dev_pm_opp_put_genpd_virt_dev() - Releases resources blocked for genpd device.1866 * dev_pm_opp_detach_genpd() - Detach genpd(s) from the device.
1793 * @opp_table: OPP table returned by dev_pm_opp_set_genpd_virt_dev().1867 * @opp_table: OPP table returned by dev_pm_opp_attach_genpd().
1794 * @virt_dev: virtual genpd device.
1795 *1868 *
1796 * This releases the resource previously acquired with a call to1869 * This detaches the genpd(s), resets the virtual device pointers, and puts the
1797 * dev_pm_opp_set_genpd_virt_dev(). The consumer driver shall call this helper1870 * OPP table.
1798 * if it doesn't want OPP core to update performance state of a power domain
1799 * anymore.
1800 */1871 */
1801void dev_pm_opp_put_genpd_virt_dev(struct opp_table *opp_table,1872void dev_pm_opp_detach_genpd(struct opp_table *opp_table)
1802 struct device *virt_dev)
1803{1873{
1804 int i;
1805
1806 /*1874 /*
1807 * Acquire genpd_virt_dev_lock to make sure virt_dev isn't getting1875 * Acquire genpd_virt_dev_lock to make sure virt_dev isn't getting
1808 * used in parallel.1876 * used in parallel.
1809 */1877 */
1810 mutex_lock(&opp_table->genpd_virt_dev_lock);1878 mutex_lock(&opp_table->genpd_virt_dev_lock);
1811 1879 _opp_detach_genpd(opp_table);
1812 for (i = 0; i < opp_table->required_opp_count; i++) {
1813 if (opp_table->genpd_virt_devs[i] != virt_dev)
1814 continue;
1815
1816 opp_table->genpd_virt_devs[i] = NULL;
1817 dev_pm_opp_put_opp_table(opp_table);
1818
1819 /* Drop the vote */
1820 dev_pm_genpd_set_performance_state(virt_dev, 0);
1821 break;
1822 }
1823
1824 mutex_unlock(&opp_table->genpd_virt_dev_lock);1880 mutex_unlock(&opp_table->genpd_virt_dev_lock);
1825 1881
1826 if (unlikely(i == opp_table->required_opp_count))1882 dev_pm_opp_put_opp_table(opp_table);
1827 dev_err(virt_dev, "Failed to find required device entry\n");
1828}1883}
1884EXPORT_SYMBOL_GPL(dev_pm_opp_detach_genpd);
1829 1885
1830/**1886/**
1831 * dev_pm_opp_xlate_performance_state() - Find required OPP's pstate for src_table.1887 * dev_pm_opp_xlate_performance_state() - Find required OPP's pstate for src_table.
drivers/opp/of.c+2−28
@@ -138,7 +138,6 @@ err: · 137 unmodified lines
138static void _opp_table_free_required_tables(struct opp_table *opp_table)138static void _opp_table_free_required_tables(struct opp_table *opp_table)
139{139{
140 struct opp_table **required_opp_tables = opp_table->required_opp_tables;140 struct opp_table **required_opp_tables = opp_table->required_opp_tables;
141 struct device **genpd_virt_devs = opp_table->genpd_virt_devs;
142 int i;141 int i;
143 142
144 if (!required_opp_tables)143 if (!required_opp_tables)
@@ -152,10 +151,8 @@ static void _opp_table_free_required_tables(struct opp_table *opp_table) · 7 unmodified lines
152 }151 }
153 152
154 kfree(required_opp_tables);153 kfree(required_opp_tables);
155 kfree(genpd_virt_devs);
156 154
157 opp_table->required_opp_count = 0;155 opp_table->required_opp_count = 0;
158 opp_table->genpd_virt_devs = NULL;
159 opp_table->required_opp_tables = NULL;156 opp_table->required_opp_tables = NULL;
160}157}
161 158
@@ -168,9 +165,8 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table, · 6 unmodified lines
168 struct device_node *opp_np)165 struct device_node *opp_np)
169{166{
170 struct opp_table **required_opp_tables;167 struct opp_table **required_opp_tables;
171 struct device **genpd_virt_devs = NULL;
172 struct device_node *required_np, *np;168 struct device_node *required_np, *np;
173 int count, count_pd, i;169 int count, i;
174 170
175 /* Traversing the first OPP node is all we need */171 /* Traversing the first OPP node is all we need */
176 np = of_get_next_available_child(opp_np, NULL);172 np = of_get_next_available_child(opp_np, NULL);
@@ -183,33 +179,11 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table, · 6 unmodified lines
183 if (!count)179 if (!count)
184 goto put_np;180 goto put_np;
185 181
186 /*
187 * Check the number of power-domains to know if we need to deal
188 * with virtual devices. In some cases we have devices with multiple
189 * power domains but with only one of them being scalable, hence
190 * 'count' could be 1, but we still have to deal with multiple genpds
191 * and virtual devices.
192 */
193 count_pd = of_count_phandle_with_args(dev->of_node, "power-domains",
194 "#power-domain-cells");
195 if (!count_pd)
196 goto put_np;
197
198 if (count_pd > 1) {
199 genpd_virt_devs = kcalloc(count, sizeof(*genpd_virt_devs),
200 GFP_KERNEL);
201 if (!genpd_virt_devs)
202 goto put_np;
203 }
204
205 required_opp_tables = kcalloc(count, sizeof(*required_opp_tables),182 required_opp_tables = kcalloc(count, sizeof(*required_opp_tables),
206 GFP_KERNEL);183 GFP_KERNEL);
207 if (!required_opp_tables) {184 if (!required_opp_tables)
208 kfree(genpd_virt_devs);
209 goto put_np;185 goto put_np;
210 }
211 186
212 opp_table->genpd_virt_devs = genpd_virt_devs;
213 opp_table->required_opp_tables = required_opp_tables;187 opp_table->required_opp_tables = required_opp_tables;
214 opp_table->required_opp_count = count;188 opp_table->required_opp_count = count;
215 189
include/linux/pm_opp.h+4−4
@@ -128,8 +128,8 @@ struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * name); · 127 unmodified lines
128void dev_pm_opp_put_clkname(struct opp_table *opp_table);128void dev_pm_opp_put_clkname(struct opp_table *opp_table);
129struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data));129struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data));
130void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table);130void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table);
131struct opp_table *dev_pm_opp_set_genpd_virt_dev(struct device *dev, struct device *virt_dev, int index);131struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names);
132void dev_pm_opp_put_genpd_virt_dev(struct opp_table *opp_table, struct device *virt_dev);132void dev_pm_opp_detach_genpd(struct opp_table *opp_table);
133int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate);133int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate);
134int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);134int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);
135int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask);135int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask);
@@ -292,12 +292,12 @@ static inline struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const · 156 unmodified lines
292 292
293static inline void dev_pm_opp_put_clkname(struct opp_table *opp_table) {}293static inline void dev_pm_opp_put_clkname(struct opp_table *opp_table) {}
294 294
295static inline struct opp_table *dev_pm_opp_set_genpd_virt_dev(struct device *dev, struct device *virt_dev, int index)295static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names)
296{296{
297 return ERR_PTR(-ENOTSUPP);297 return ERR_PTR(-ENOTSUPP);
298}298}
299 299
300static inline void dev_pm_opp_put_genpd_virt_dev(struct opp_table *opp_table, struct device *virt_dev) {}300static inline void dev_pm_opp_detach_genpd(struct opp_table *opp_table) {}
301 301
302static inline int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate)302static inline int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate)
303{303{

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t