@@ -21,9 +21,15 @@ struct platform_profile_handler {
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 ;
25
26
};
26
27
28
+ struct aggregate_choices_data {
29
+ unsigned long aggregate [BITS_TO_LONGS (PLATFORM_PROFILE_LAST )];
30
+ int count ;
31
+ };
32
+
27
33
static const char * const profile_names [] = {
28
34
[PLATFORM_PROFILE_LOW_POWER ] = "low-power" ,
29
35
[PLATFORM_PROFILE_COOL ] = "cool" ,
@@ -73,7 +79,7 @@ static int _store_class_profile(struct device *dev, void *data)
73
79
74
80
lockdep_assert_held (& profile_lock );
75
81
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 ) )
77
83
return - EOPNOTSUPP ;
78
84
79
85
return handler -> ops -> profile_set (dev , * bit );
@@ -239,21 +245,44 @@ static const struct class platform_profile_class = {
239
245
/**
240
246
* _aggregate_choices - Aggregate the available profile choices
241
247
* @dev: The device
242
- * @data: The available profile choices
248
+ * @arg: struct aggregate_choices_data
243
249
*
244
250
* Return: 0 on success, -errno on failure
245
251
*/
246
- static int _aggregate_choices (struct device * dev , void * data )
252
+ static int _aggregate_choices (struct device * dev , void * arg )
247
253
{
254
+ unsigned long tmp [BITS_TO_LONGS (PLATFORM_PROFILE_LAST )];
255
+ struct aggregate_choices_data * data = arg ;
248
256
struct platform_profile_handler * handler ;
249
- unsigned long * aggregate = data ;
250
257
251
258
lockdep_assert_held (& profile_lock );
252
259
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 );
255
263
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 );
257
286
258
287
return 0 ;
259
288
}
@@ -270,22 +299,31 @@ static ssize_t platform_profile_choices_show(struct device *dev,
270
299
struct device_attribute * attr ,
271
300
char * buf )
272
301
{
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
+ };
274
306
int err ;
275
307
276
- set_bit (PLATFORM_PROFILE_LAST , aggregate );
308
+ set_bit (PLATFORM_PROFILE_LAST , data . aggregate );
277
309
scoped_cond_guard (mutex_intr , return - ERESTARTSYS , & profile_lock ) {
278
310
err = class_for_each_device (& platform_profile_class , NULL ,
279
- aggregate , _aggregate_choices );
311
+ & data , _aggregate_choices );
280
312
if (err )
281
313
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
+ }
282
320
}
283
321
284
322
/* no profile handler registered any more */
285
- if (bitmap_empty (aggregate , PLATFORM_PROFILE_LAST ))
323
+ if (bitmap_empty (data . aggregate , PLATFORM_PROFILE_LAST ))
286
324
return - EINVAL ;
287
325
288
- return _commmon_choices_show (aggregate , buf );
326
+ return _commmon_choices_show (data . aggregate , buf );
289
327
}
290
328
291
329
/**
@@ -373,21 +411,24 @@ static ssize_t platform_profile_store(struct device *dev,
373
411
struct device_attribute * attr ,
374
412
const char * buf , size_t count )
375
413
{
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
+ };
377
418
int ret ;
378
419
int i ;
379
420
380
421
/* Scan for a matching profile */
381
422
i = sysfs_match_string (profile_names , buf );
382
423
if (i < 0 || i == PLATFORM_PROFILE_CUSTOM )
383
424
return - EINVAL ;
384
- set_bit (PLATFORM_PROFILE_LAST , choices );
425
+ set_bit (PLATFORM_PROFILE_LAST , data . aggregate );
385
426
scoped_cond_guard (mutex_intr , return - ERESTARTSYS , & profile_lock ) {
386
427
ret = class_for_each_device (& platform_profile_class , NULL ,
387
- choices , _aggregate_choices );
428
+ & data , _aggregate_choices );
388
429
if (ret )
389
430
return ret ;
390
- if (!test_bit (i , choices ))
431
+ if (!test_bit (i , data . aggregate ))
391
432
return - EOPNOTSUPP ;
392
433
393
434
ret = class_for_each_device (& platform_profile_class , NULL , & i ,
@@ -453,12 +494,15 @@ EXPORT_SYMBOL_GPL(platform_profile_notify);
453
494
*/
454
495
int platform_profile_cycle (void )
455
496
{
497
+ struct aggregate_choices_data data = {
498
+ .aggregate = { [0 ... BITS_TO_LONGS (PLATFORM_PROFILE_LAST ) - 1 ] = ~0UL },
499
+ .count = 0 ,
500
+ };
456
501
enum platform_profile_option next = PLATFORM_PROFILE_LAST ;
457
502
enum platform_profile_option profile = PLATFORM_PROFILE_LAST ;
458
- unsigned long choices [BITS_TO_LONGS (PLATFORM_PROFILE_LAST )];
459
503
int err ;
460
504
461
- set_bit (PLATFORM_PROFILE_LAST , choices );
505
+ set_bit (PLATFORM_PROFILE_LAST , data . aggregate );
462
506
scoped_cond_guard (mutex_intr , return - ERESTARTSYS , & profile_lock ) {
463
507
err = class_for_each_device (& platform_profile_class , NULL ,
464
508
& profile , _aggregate_profiles );
@@ -470,14 +514,14 @@ int platform_profile_cycle(void)
470
514
return - EINVAL ;
471
515
472
516
err = class_for_each_device (& platform_profile_class , NULL ,
473
- choices , _aggregate_choices );
517
+ & data , _aggregate_choices );
474
518
if (err )
475
519
return err ;
476
520
477
521
/* 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 );
479
523
480
- next = find_next_bit_wrap (choices ,
524
+ next = find_next_bit_wrap (data . aggregate ,
481
525
PLATFORM_PROFILE_LAST ,
482
526
profile + 1 );
483
527
@@ -532,6 +576,14 @@ struct device *platform_profile_register(struct device *dev, const char *name,
532
576
return ERR_PTR (- EINVAL );
533
577
}
534
578
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
+
535
587
guard (mutex )(& profile_lock );
536
588
537
589
/* create class interface for individual handler */
0 commit comments