Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+87 -21
+73 -21
drivers/acpi/platform_profile.c
··· 21 21 struct device dev; 22 22 int minor; 23 23 unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 24 + unsigned long hidden_choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 24 25 const struct platform_profile_ops *ops; 26 + }; 27 + 28 + struct aggregate_choices_data { 29 + unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 30 + int count; 25 31 }; 26 32 27 33 static const char * const profile_names[] = { ··· 79 73 80 74 lockdep_assert_held(&profile_lock); 81 75 handler = to_pprof_handler(dev); 82 - if (!test_bit(*bit, handler->choices)) 76 + if (!test_bit(*bit, handler->choices) && !test_bit(*bit, handler->hidden_choices)) 83 77 return -EOPNOTSUPP; 84 78 85 79 return handler->ops->profile_set(dev, *bit); ··· 245 239 /** 246 240 * _aggregate_choices - Aggregate the available profile choices 247 241 * @dev: The device 248 - * @data: The available profile choices 242 + * @arg: struct aggregate_choices_data 249 243 * 250 244 * Return: 0 on success, -errno on failure 251 245 */ 252 - static int _aggregate_choices(struct device *dev, void *data) 246 + static int _aggregate_choices(struct device *dev, void *arg) 253 247 { 248 + unsigned long tmp[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 249 + struct aggregate_choices_data *data = arg; 254 250 struct platform_profile_handler *handler; 255 - unsigned long *aggregate = data; 256 251 257 252 lockdep_assert_held(&profile_lock); 258 253 handler = to_pprof_handler(dev); 259 - if (test_bit(PLATFORM_PROFILE_LAST, aggregate)) 260 - bitmap_copy(aggregate, handler->choices, PLATFORM_PROFILE_LAST); 254 + bitmap_or(tmp, handler->choices, handler->hidden_choices, PLATFORM_PROFILE_LAST); 255 + if (test_bit(PLATFORM_PROFILE_LAST, data->aggregate)) 256 + bitmap_copy(data->aggregate, tmp, PLATFORM_PROFILE_LAST); 261 257 else 262 - bitmap_and(aggregate, handler->choices, aggregate, PLATFORM_PROFILE_LAST); 258 + bitmap_and(data->aggregate, tmp, data->aggregate, PLATFORM_PROFILE_LAST); 259 + data->count++; 260 + 261 + return 0; 262 + } 263 + 264 + /** 265 + * _remove_hidden_choices - Remove hidden choices from aggregate data 266 + * @dev: The device 267 + * @arg: struct aggregate_choices_data 268 + * 269 + * Return: 0 on success, -errno on failure 270 + */ 271 + static int _remove_hidden_choices(struct device *dev, void *arg) 272 + { 273 + struct aggregate_choices_data *data = arg; 274 + struct platform_profile_handler *handler; 275 + 276 + lockdep_assert_held(&profile_lock); 277 + handler = to_pprof_handler(dev); 278 + bitmap_andnot(data->aggregate, handler->choices, 279 + handler->hidden_choices, PLATFORM_PROFILE_LAST); 263 280 264 281 return 0; 265 282 } ··· 299 270 struct device_attribute *attr, 300 271 char *buf) 301 272 { 302 - unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 273 + struct aggregate_choices_data data = { 274 + .aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL }, 275 + .count = 0, 276 + }; 303 277 int err; 304 278 305 - set_bit(PLATFORM_PROFILE_LAST, aggregate); 279 + set_bit(PLATFORM_PROFILE_LAST, data.aggregate); 306 280 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 307 281 err = class_for_each_device(&platform_profile_class, NULL, 308 - aggregate, _aggregate_choices); 282 + &data, _aggregate_choices); 309 283 if (err) 310 284 return err; 285 + if (data.count == 1) { 286 + err = class_for_each_device(&platform_profile_class, NULL, 287 + &data, _remove_hidden_choices); 288 + if (err) 289 + return err; 290 + } 311 291 } 312 292 313 293 /* no profile handler registered any more */ 314 - if (bitmap_empty(aggregate, PLATFORM_PROFILE_LAST)) 294 + if (bitmap_empty(data.aggregate, PLATFORM_PROFILE_LAST)) 315 295 return -EINVAL; 316 296 317 - return _commmon_choices_show(aggregate, buf); 297 + return _commmon_choices_show(data.aggregate, buf); 318 298 } 319 299 320 300 /** ··· 411 373 struct device_attribute *attr, 412 374 const char *buf, size_t count) 413 375 { 414 - unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 376 + struct aggregate_choices_data data = { 377 + .aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL }, 378 + .count = 0, 379 + }; 415 380 int ret; 416 381 int i; 417 382 ··· 422 381 i = sysfs_match_string(profile_names, buf); 423 382 if (i < 0 || i == PLATFORM_PROFILE_CUSTOM) 424 383 return -EINVAL; 425 - set_bit(PLATFORM_PROFILE_LAST, choices); 384 + set_bit(PLATFORM_PROFILE_LAST, data.aggregate); 426 385 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 427 386 ret = class_for_each_device(&platform_profile_class, NULL, 428 - choices, _aggregate_choices); 387 + &data, _aggregate_choices); 429 388 if (ret) 430 389 return ret; 431 - if (!test_bit(i, choices)) 390 + if (!test_bit(i, data.aggregate)) 432 391 return -EOPNOTSUPP; 433 392 434 393 ret = class_for_each_device(&platform_profile_class, NULL, &i, ··· 494 453 */ 495 454 int platform_profile_cycle(void) 496 455 { 456 + struct aggregate_choices_data data = { 457 + .aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL }, 458 + .count = 0, 459 + }; 497 460 enum platform_profile_option next = PLATFORM_PROFILE_LAST; 498 461 enum platform_profile_option profile = PLATFORM_PROFILE_LAST; 499 - unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 500 462 int err; 501 463 502 - set_bit(PLATFORM_PROFILE_LAST, choices); 464 + set_bit(PLATFORM_PROFILE_LAST, data.aggregate); 503 465 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 504 466 err = class_for_each_device(&platform_profile_class, NULL, 505 467 &profile, _aggregate_profiles); ··· 514 470 return -EINVAL; 515 471 516 472 err = class_for_each_device(&platform_profile_class, NULL, 517 - choices, _aggregate_choices); 473 + &data, _aggregate_choices); 518 474 if (err) 519 475 return err; 520 476 521 477 /* never iterate into a custom if all drivers supported it */ 522 - clear_bit(PLATFORM_PROFILE_CUSTOM, choices); 478 + clear_bit(PLATFORM_PROFILE_CUSTOM, data.aggregate); 523 479 524 - next = find_next_bit_wrap(choices, 480 + next = find_next_bit_wrap(data.aggregate, 525 481 PLATFORM_PROFILE_LAST, 526 482 profile + 1); 527 483 ··· 574 530 if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) { 575 531 dev_err(dev, "Failed to register platform_profile class device with empty choices\n"); 576 532 return ERR_PTR(-EINVAL); 533 + } 534 + 535 + if (ops->hidden_choices) { 536 + err = ops->hidden_choices(drvdata, pprof->hidden_choices); 537 + if (err) { 538 + dev_err(dev, "platform_profile hidden_choices failed\n"); 539 + return ERR_PTR(err); 540 + } 577 541 } 578 542 579 543 guard(mutex)(&profile_lock);
+11
drivers/platform/x86/amd/pmf/sps.c
··· 297 297 298 298 switch (pmf->current_profile) { 299 299 case PLATFORM_PROFILE_PERFORMANCE: 300 + case PLATFORM_PROFILE_BALANCED_PERFORMANCE: 300 301 mode = POWER_MODE_PERFORMANCE; 301 302 break; 302 303 case PLATFORM_PROFILE_BALANCED: 303 304 mode = POWER_MODE_BALANCED_POWER; 304 305 break; 305 306 case PLATFORM_PROFILE_LOW_POWER: 307 + case PLATFORM_PROFILE_QUIET: 306 308 mode = POWER_MODE_POWER_SAVER; 307 309 break; 308 310 default: ··· 389 387 return 0; 390 388 } 391 389 390 + static int amd_pmf_hidden_choices(void *drvdata, unsigned long *choices) 391 + { 392 + set_bit(PLATFORM_PROFILE_QUIET, choices); 393 + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices); 394 + 395 + return 0; 396 + } 397 + 392 398 static int amd_pmf_profile_probe(void *drvdata, unsigned long *choices) 393 399 { 394 400 set_bit(PLATFORM_PROFILE_LOW_POWER, choices); ··· 408 398 409 399 static const struct platform_profile_ops amd_pmf_profile_ops = { 410 400 .probe = amd_pmf_profile_probe, 401 + .hidden_choices = amd_pmf_hidden_choices, 411 402 .profile_get = amd_pmf_profile_get, 412 403 .profile_set = amd_pmf_profile_set, 413 404 };
+3
include/linux/platform_profile.h
··· 33 33 * @probe: Callback to setup choices available to the new class device. These 34 34 * choices will only be enforced when setting a new profile, not when 35 35 * 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. 36 38 * @profile_get: Callback that will be called when showing the current platform 37 39 * profile in sysfs. 38 40 * @profile_set: Callback that will be called when storing a new platform ··· 42 40 */ 43 41 struct platform_profile_ops { 44 42 int (*probe)(void *drvdata, unsigned long *choices); 43 + int (*hidden_choices)(void *drvdata, unsigned long *choices); 45 44 int (*profile_get)(struct device *dev, enum platform_profile_option *profile); 46 45 int (*profile_set)(struct device *dev, enum platform_profile_option profile); 47 46 };