@@ -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+
2733static 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 */
454495int 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 */
0 commit comments