Skip to content

Commit d4fd25b

Browse files
committed
Merge tag 'acpi-6.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI fix from Rafael Wysocki: "Restore the previous behavior of the ACPI platform_profile sysfs interface that has been changed recently in a way incompatible with the existing user space (Mario Limonciello)" * tag 'acpi-6.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: platform/x86/amd: pmf: Add balanced-performance to hidden choices platform/x86/amd: pmf: Add 'quiet' to hidden choices ACPI: platform_profile: Add support for hidden choices
2 parents dd047ef + 9a43102 commit d4fd25b

File tree

3 files changed

+87
-21
lines changed

3 files changed

+87
-21
lines changed

drivers/acpi/platform_profile.c

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,15 @@ struct platform_profile_handler {
2121
struct device dev;
2222
int minor;
2323
unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
24+
unsigned long hidden_choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
2425
const struct platform_profile_ops *ops;
2526
};
2627

28+
struct aggregate_choices_data {
29+
unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
30+
int count;
31+
};
32+
2733
static const char * const profile_names[] = {
2834
[PLATFORM_PROFILE_LOW_POWER] = "low-power",
2935
[PLATFORM_PROFILE_COOL] = "cool",
@@ -73,7 +79,7 @@ static int _store_class_profile(struct device *dev, void *data)
7379

7480
lockdep_assert_held(&profile_lock);
7581
handler = to_pprof_handler(dev);
76-
if (!test_bit(*bit, handler->choices))
82+
if (!test_bit(*bit, handler->choices) && !test_bit(*bit, handler->hidden_choices))
7783
return -EOPNOTSUPP;
7884

7985
return handler->ops->profile_set(dev, *bit);
@@ -239,21 +245,44 @@ static const struct class platform_profile_class = {
239245
/**
240246
* _aggregate_choices - Aggregate the available profile choices
241247
* @dev: The device
242-
* @data: The available profile choices
248+
* @arg: struct aggregate_choices_data
243249
*
244250
* Return: 0 on success, -errno on failure
245251
*/
246-
static int _aggregate_choices(struct device *dev, void *data)
252+
static int _aggregate_choices(struct device *dev, void *arg)
247253
{
254+
unsigned long tmp[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
255+
struct aggregate_choices_data *data = arg;
248256
struct platform_profile_handler *handler;
249-
unsigned long *aggregate = data;
250257

251258
lockdep_assert_held(&profile_lock);
252259
handler = to_pprof_handler(dev);
253-
if (test_bit(PLATFORM_PROFILE_LAST, aggregate))
254-
bitmap_copy(aggregate, handler->choices, PLATFORM_PROFILE_LAST);
260+
bitmap_or(tmp, handler->choices, handler->hidden_choices, PLATFORM_PROFILE_LAST);
261+
if (test_bit(PLATFORM_PROFILE_LAST, data->aggregate))
262+
bitmap_copy(data->aggregate, tmp, PLATFORM_PROFILE_LAST);
255263
else
256-
bitmap_and(aggregate, handler->choices, aggregate, PLATFORM_PROFILE_LAST);
264+
bitmap_and(data->aggregate, tmp, data->aggregate, PLATFORM_PROFILE_LAST);
265+
data->count++;
266+
267+
return 0;
268+
}
269+
270+
/**
271+
* _remove_hidden_choices - Remove hidden choices from aggregate data
272+
* @dev: The device
273+
* @arg: struct aggregate_choices_data
274+
*
275+
* Return: 0 on success, -errno on failure
276+
*/
277+
static int _remove_hidden_choices(struct device *dev, void *arg)
278+
{
279+
struct aggregate_choices_data *data = arg;
280+
struct platform_profile_handler *handler;
281+
282+
lockdep_assert_held(&profile_lock);
283+
handler = to_pprof_handler(dev);
284+
bitmap_andnot(data->aggregate, handler->choices,
285+
handler->hidden_choices, PLATFORM_PROFILE_LAST);
257286

258287
return 0;
259288
}
@@ -270,22 +299,31 @@ static ssize_t platform_profile_choices_show(struct device *dev,
270299
struct device_attribute *attr,
271300
char *buf)
272301
{
273-
unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
302+
struct aggregate_choices_data data = {
303+
.aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL },
304+
.count = 0,
305+
};
274306
int err;
275307

276-
set_bit(PLATFORM_PROFILE_LAST, aggregate);
308+
set_bit(PLATFORM_PROFILE_LAST, data.aggregate);
277309
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
278310
err = class_for_each_device(&platform_profile_class, NULL,
279-
aggregate, _aggregate_choices);
311+
&data, _aggregate_choices);
280312
if (err)
281313
return err;
314+
if (data.count == 1) {
315+
err = class_for_each_device(&platform_profile_class, NULL,
316+
&data, _remove_hidden_choices);
317+
if (err)
318+
return err;
319+
}
282320
}
283321

284322
/* no profile handler registered any more */
285-
if (bitmap_empty(aggregate, PLATFORM_PROFILE_LAST))
323+
if (bitmap_empty(data.aggregate, PLATFORM_PROFILE_LAST))
286324
return -EINVAL;
287325

288-
return _commmon_choices_show(aggregate, buf);
326+
return _commmon_choices_show(data.aggregate, buf);
289327
}
290328

291329
/**
@@ -373,21 +411,24 @@ static ssize_t platform_profile_store(struct device *dev,
373411
struct device_attribute *attr,
374412
const char *buf, size_t count)
375413
{
376-
unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
414+
struct aggregate_choices_data data = {
415+
.aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL },
416+
.count = 0,
417+
};
377418
int ret;
378419
int i;
379420

380421
/* Scan for a matching profile */
381422
i = sysfs_match_string(profile_names, buf);
382423
if (i < 0 || i == PLATFORM_PROFILE_CUSTOM)
383424
return -EINVAL;
384-
set_bit(PLATFORM_PROFILE_LAST, choices);
425+
set_bit(PLATFORM_PROFILE_LAST, data.aggregate);
385426
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
386427
ret = class_for_each_device(&platform_profile_class, NULL,
387-
choices, _aggregate_choices);
428+
&data, _aggregate_choices);
388429
if (ret)
389430
return ret;
390-
if (!test_bit(i, choices))
431+
if (!test_bit(i, data.aggregate))
391432
return -EOPNOTSUPP;
392433

393434
ret = class_for_each_device(&platform_profile_class, NULL, &i,
@@ -453,12 +494,15 @@ EXPORT_SYMBOL_GPL(platform_profile_notify);
453494
*/
454495
int platform_profile_cycle(void)
455496
{
497+
struct aggregate_choices_data data = {
498+
.aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL },
499+
.count = 0,
500+
};
456501
enum platform_profile_option next = PLATFORM_PROFILE_LAST;
457502
enum platform_profile_option profile = PLATFORM_PROFILE_LAST;
458-
unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
459503
int err;
460504

461-
set_bit(PLATFORM_PROFILE_LAST, choices);
505+
set_bit(PLATFORM_PROFILE_LAST, data.aggregate);
462506
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
463507
err = class_for_each_device(&platform_profile_class, NULL,
464508
&profile, _aggregate_profiles);
@@ -470,14 +514,14 @@ int platform_profile_cycle(void)
470514
return -EINVAL;
471515

472516
err = class_for_each_device(&platform_profile_class, NULL,
473-
choices, _aggregate_choices);
517+
&data, _aggregate_choices);
474518
if (err)
475519
return err;
476520

477521
/* never iterate into a custom if all drivers supported it */
478-
clear_bit(PLATFORM_PROFILE_CUSTOM, choices);
522+
clear_bit(PLATFORM_PROFILE_CUSTOM, data.aggregate);
479523

480-
next = find_next_bit_wrap(choices,
524+
next = find_next_bit_wrap(data.aggregate,
481525
PLATFORM_PROFILE_LAST,
482526
profile + 1);
483527

@@ -532,6 +576,14 @@ struct device *platform_profile_register(struct device *dev, const char *name,
532576
return ERR_PTR(-EINVAL);
533577
}
534578

579+
if (ops->hidden_choices) {
580+
err = ops->hidden_choices(drvdata, pprof->hidden_choices);
581+
if (err) {
582+
dev_err(dev, "platform_profile hidden_choices failed\n");
583+
return ERR_PTR(err);
584+
}
585+
}
586+
535587
guard(mutex)(&profile_lock);
536588

537589
/* create class interface for individual handler */

drivers/platform/x86/amd/pmf/sps.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,12 +297,14 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
297297

298298
switch (pmf->current_profile) {
299299
case PLATFORM_PROFILE_PERFORMANCE:
300+
case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
300301
mode = POWER_MODE_PERFORMANCE;
301302
break;
302303
case PLATFORM_PROFILE_BALANCED:
303304
mode = POWER_MODE_BALANCED_POWER;
304305
break;
305306
case PLATFORM_PROFILE_LOW_POWER:
307+
case PLATFORM_PROFILE_QUIET:
306308
mode = POWER_MODE_POWER_SAVER;
307309
break;
308310
default:
@@ -387,6 +389,14 @@ static int amd_pmf_profile_set(struct device *dev,
387389
return 0;
388390
}
389391

392+
static int amd_pmf_hidden_choices(void *drvdata, unsigned long *choices)
393+
{
394+
set_bit(PLATFORM_PROFILE_QUIET, choices);
395+
set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
396+
397+
return 0;
398+
}
399+
390400
static int amd_pmf_profile_probe(void *drvdata, unsigned long *choices)
391401
{
392402
set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
@@ -398,6 +408,7 @@ static int amd_pmf_profile_probe(void *drvdata, unsigned long *choices)
398408

399409
static const struct platform_profile_ops amd_pmf_profile_ops = {
400410
.probe = amd_pmf_profile_probe,
411+
.hidden_choices = amd_pmf_hidden_choices,
401412
.profile_get = amd_pmf_profile_get,
402413
.profile_set = amd_pmf_profile_set,
403414
};

include/linux/platform_profile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@ enum platform_profile_option {
3333
* @probe: Callback to setup choices available to the new class device. These
3434
* choices will only be enforced when setting a new profile, not when
3535
* getting the current one.
36+
* @hidden_choices: Callback to setup choices that are not visible to the user
37+
* but can be set by the driver.
3638
* @profile_get: Callback that will be called when showing the current platform
3739
* profile in sysfs.
3840
* @profile_set: Callback that will be called when storing a new platform
3941
* profile in sysfs.
4042
*/
4143
struct platform_profile_ops {
4244
int (*probe)(void *drvdata, unsigned long *choices);
45+
int (*hidden_choices)(void *drvdata, unsigned long *choices);
4346
int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
4447
int (*profile_set)(struct device *dev, enum platform_profile_option profile);
4548
};

0 commit comments

Comments
 (0)