Skip to content

Commit eddd376

Browse files
committed
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
3 parents a5c16f2 + a500aca + 763fcb9 commit eddd376

File tree

6 files changed

+97
-33
lines changed

6 files changed

+97
-33
lines changed

drivers/devfreq/devfreq-event.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,9 @@ struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(struct device *dev,
244244
edev = NULL;
245245
out:
246246
mutex_unlock(&devfreq_event_list_lock);
247-
248-
if (!edev) {
249-
of_node_put(node);
250-
return ERR_PTR(-ENODEV);
251-
}
252-
253247
of_node_put(node);
248+
if (!edev)
249+
return ERR_PTR(-ENODEV);
254250

255251
return edev;
256252
}

drivers/devfreq/exynos-bus.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,7 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
236236
return ret;
237237
}
238238

239-
static int exynos_bus_parse_of(struct device_node *np,
240-
struct exynos_bus *bus)
239+
static int exynos_bus_parse_of(struct exynos_bus *bus)
241240
{
242241
struct device *dev = bus->dev;
243242
struct dev_pm_opp *opp;
@@ -408,7 +407,7 @@ static int exynos_bus_probe(struct platform_device *pdev)
408407
}
409408

410409
/* Parse the device-tree to get the resource information */
411-
ret = exynos_bus_parse_of(np, bus);
410+
ret = exynos_bus_parse_of(bus);
412411
if (ret < 0)
413412
goto err_reg;
414413

drivers/opp/core.c

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,55 @@ struct opp_table *_find_opp_table(struct device *dev)
101101
* representation in the OPP table and manage the clock configuration themselves
102102
* in an platform specific way.
103103
*/
104-
static bool assert_single_clk(struct opp_table *opp_table)
104+
static bool assert_single_clk(struct opp_table *opp_table,
105+
unsigned int __always_unused index)
105106
{
106107
return !WARN_ON(opp_table->clk_count > 1);
107108
}
108109

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+
109153
/**
110154
* dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp
111155
* @opp: opp for which voltage has to be returned for
@@ -499,12 +543,12 @@ static struct dev_pm_opp *_opp_table_find_key(struct opp_table *opp_table,
499543
unsigned long (*read)(struct dev_pm_opp *opp, int index),
500544
bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp,
501545
unsigned long opp_key, unsigned long key),
502-
bool (*assert)(struct opp_table *opp_table))
546+
bool (*assert)(struct opp_table *opp_table, unsigned int index))
503547
{
504548
struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
505549

506550
/* Assert that the requirement is met */
507-
if (assert && !assert(opp_table))
551+
if (assert && !assert(opp_table, index))
508552
return ERR_PTR(-EINVAL);
509553

510554
mutex_lock(&opp_table->lock);
@@ -532,7 +576,7 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available,
532576
unsigned long (*read)(struct dev_pm_opp *opp, int index),
533577
bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp,
534578
unsigned long opp_key, unsigned long key),
535-
bool (*assert)(struct opp_table *opp_table))
579+
bool (*assert)(struct opp_table *opp_table, unsigned int index))
536580
{
537581
struct opp_table *opp_table;
538582
struct dev_pm_opp *opp;
@@ -555,7 +599,7 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available,
555599
static struct dev_pm_opp *_find_key_exact(struct device *dev,
556600
unsigned long key, int index, bool available,
557601
unsigned long (*read)(struct dev_pm_opp *opp, int index),
558-
bool (*assert)(struct opp_table *opp_table))
602+
bool (*assert)(struct opp_table *opp_table, unsigned int index))
559603
{
560604
/*
561605
* The value of key will be updated here, but will be ignored as the
@@ -568,7 +612,7 @@ static struct dev_pm_opp *_find_key_exact(struct device *dev,
568612
static struct dev_pm_opp *_opp_table_find_key_ceil(struct opp_table *opp_table,
569613
unsigned long *key, int index, bool available,
570614
unsigned long (*read)(struct dev_pm_opp *opp, int index),
571-
bool (*assert)(struct opp_table *opp_table))
615+
bool (*assert)(struct opp_table *opp_table, unsigned int index))
572616
{
573617
return _opp_table_find_key(opp_table, key, index, available, read,
574618
_compare_ceil, assert);
@@ -577,7 +621,7 @@ static struct dev_pm_opp *_opp_table_find_key_ceil(struct opp_table *opp_table,
577621
static struct dev_pm_opp *_find_key_ceil(struct device *dev, unsigned long *key,
578622
int index, bool available,
579623
unsigned long (*read)(struct dev_pm_opp *opp, int index),
580-
bool (*assert)(struct opp_table *opp_table))
624+
bool (*assert)(struct opp_table *opp_table, unsigned int index))
581625
{
582626
return _find_key(dev, key, index, available, read, _compare_ceil,
583627
assert);
@@ -586,7 +630,7 @@ static struct dev_pm_opp *_find_key_ceil(struct device *dev, unsigned long *key,
586630
static struct dev_pm_opp *_find_key_floor(struct device *dev,
587631
unsigned long *key, int index, bool available,
588632
unsigned long (*read)(struct dev_pm_opp *opp, int index),
589-
bool (*assert)(struct opp_table *opp_table))
633+
bool (*assert)(struct opp_table *opp_table, unsigned int index))
590634
{
591635
return _find_key(dev, key, index, available, read, _compare_floor,
592636
assert);
@@ -647,7 +691,8 @@ struct dev_pm_opp *
647691
dev_pm_opp_find_freq_exact_indexed(struct device *dev, unsigned long freq,
648692
u32 index, bool available)
649693
{
650-
return _find_key_exact(dev, freq, index, available, _read_freq, NULL);
694+
return _find_key_exact(dev, freq, index, available, _read_freq,
695+
assert_clk_index);
651696
}
652697
EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact_indexed);
653698

@@ -707,7 +752,8 @@ struct dev_pm_opp *
707752
dev_pm_opp_find_freq_ceil_indexed(struct device *dev, unsigned long *freq,
708753
u32 index)
709754
{
710-
return _find_key_ceil(dev, freq, index, true, _read_freq, NULL);
755+
return _find_key_ceil(dev, freq, index, true, _read_freq,
756+
assert_clk_index);
711757
}
712758
EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil_indexed);
713759

@@ -760,7 +806,7 @@ struct dev_pm_opp *
760806
dev_pm_opp_find_freq_floor_indexed(struct device *dev, unsigned long *freq,
761807
u32 index)
762808
{
763-
return _find_key_floor(dev, freq, index, true, _read_freq, NULL);
809+
return _find_key_floor(dev, freq, index, true, _read_freq, assert_clk_index);
764810
}
765811
EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor_indexed);
766812

@@ -878,7 +924,8 @@ struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, unsigned int *bw,
878924
unsigned long temp = *bw;
879925
struct dev_pm_opp *opp;
880926

881-
opp = _find_key_ceil(dev, &temp, index, true, _read_bw, NULL);
927+
opp = _find_key_ceil(dev, &temp, index, true, _read_bw,
928+
assert_bandwidth_index);
882929
*bw = temp;
883930
return opp;
884931
}
@@ -909,7 +956,8 @@ struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
909956
unsigned long temp = *bw;
910957
struct dev_pm_opp *opp;
911958

912-
opp = _find_key_floor(dev, &temp, index, true, _read_bw, NULL);
959+
opp = _find_key_floor(dev, &temp, index, true, _read_bw,
960+
assert_bandwidth_index);
913961
*bw = temp;
914962
return opp;
915963
}
@@ -1480,11 +1528,6 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
14801528
return ERR_PTR(ret);
14811529
}
14821530

1483-
void _get_opp_table_kref(struct opp_table *opp_table)
1484-
{
1485-
kref_get(&opp_table->kref);
1486-
}
1487-
14881531
static struct opp_table *_update_opp_table_clk(struct device *dev,
14891532
struct opp_table *opp_table,
14901533
bool getclk)
@@ -1645,6 +1688,17 @@ static void _opp_table_kref_release(struct kref *kref)
16451688
kfree(opp_table);
16461689
}
16471690

1691+
void _get_opp_table_kref(struct opp_table *opp_table)
1692+
{
1693+
kref_get(&opp_table->kref);
1694+
}
1695+
1696+
void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table)
1697+
{
1698+
_get_opp_table_kref(opp_table);
1699+
}
1700+
EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table_ref);
1701+
16481702
void dev_pm_opp_put_opp_table(struct opp_table *opp_table)
16491703
{
16501704
kref_put_mutex(&opp_table->kref, _opp_table_kref_release,
@@ -1679,6 +1733,7 @@ void dev_pm_opp_get(struct dev_pm_opp *opp)
16791733
{
16801734
kref_get(&opp->kref);
16811735
}
1736+
EXPORT_SYMBOL_GPL(dev_pm_opp_get);
16821737

16831738
void dev_pm_opp_put(struct dev_pm_opp *opp)
16841739
{
@@ -1702,7 +1757,7 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
17021757
if (IS_ERR(opp_table))
17031758
return;
17041759

1705-
if (!assert_single_clk(opp_table))
1760+
if (!assert_single_clk(opp_table, 0))
17061761
goto put_table;
17071762

17081763
mutex_lock(&opp_table->lock);
@@ -2054,7 +2109,7 @@ int _opp_add_v1(struct opp_table *opp_table, struct device *dev,
20542109
unsigned long tol, u_volt = data->u_volt;
20552110
int ret;
20562111

2057-
if (!assert_single_clk(opp_table))
2112+
if (!assert_single_clk(opp_table, 0))
20582113
return -EINVAL;
20592114

20602115
new_opp = _opp_allocate(opp_table);
@@ -2810,7 +2865,7 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
28102865
return r;
28112866
}
28122867

2813-
if (!assert_single_clk(opp_table)) {
2868+
if (!assert_single_clk(opp_table, 0)) {
28142869
r = -EINVAL;
28152870
goto put_table;
28162871
}
@@ -2886,7 +2941,7 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
28862941
return r;
28872942
}
28882943

2889-
if (!assert_single_clk(opp_table)) {
2944+
if (!assert_single_clk(opp_table, 0)) {
28902945
r = -EINVAL;
28912946
goto put_table;
28922947
}

drivers/opp/of.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
926926

927927
ret = _of_opp_alloc_required_opps(opp_table, new_opp);
928928
if (ret)
929-
goto free_opp;
929+
goto put_node;
930930

931931
if (!of_property_read_u32(np, "clock-latency-ns", &val))
932932
new_opp->clock_latency_ns = val;
@@ -976,6 +976,8 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
976976

977977
free_required_opps:
978978
_of_opp_free_required_opps(opp_table, new_opp);
979+
put_node:
980+
of_node_put(np);
979981
free_opp:
980982
_opp_free(new_opp);
981983

drivers/opp/opp.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ struct opp_table {
250250
};
251251

252252
/* Routines internal to opp core */
253-
void dev_pm_opp_get(struct dev_pm_opp *opp);
254253
bool _opp_remove_all_static(struct opp_table *opp_table);
255254
void _get_opp_table_kref(struct opp_table *opp_table);
256255
int _get_opp_count(struct opp_table *opp_table);

include/linux/pm_opp.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,11 @@ struct dev_pm_opp_data {
100100
#if defined(CONFIG_PM_OPP)
101101

102102
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);
103104
void dev_pm_opp_put_opp_table(struct opp_table *opp_table);
104105

106+
unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index);
107+
105108
unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
106109

107110
int dev_pm_opp_get_supplies(struct dev_pm_opp *opp, struct dev_pm_opp_supply *supplies);
@@ -158,6 +161,7 @@ struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev,
158161
struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
159162
unsigned int *bw, int index);
160163

164+
void dev_pm_opp_get(struct dev_pm_opp *opp);
161165
void dev_pm_opp_put(struct dev_pm_opp *opp);
162166

163167
int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp);
@@ -203,8 +207,15 @@ static inline struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *
203207
return ERR_PTR(-EOPNOTSUPP);
204208
}
205209

210+
static inline void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table) {}
211+
206212
static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {}
207213

214+
static inline unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index)
215+
{
216+
return 0;
217+
}
218+
208219
static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
209220
{
210221
return 0;
@@ -334,6 +345,8 @@ static inline struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
334345
return ERR_PTR(-EOPNOTSUPP);
335346
}
336347

348+
static inline void dev_pm_opp_get(struct dev_pm_opp *opp) {}
349+
337350
static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {}
338351

339352
static inline int

0 commit comments

Comments
 (0)