@@ -427,6 +427,131 @@ int dev_pm_opp_get_opp_count(struct device *dev)
427
427
}
428
428
EXPORT_SYMBOL_GPL (dev_pm_opp_get_opp_count );
429
429
430
+ /* Helpers to read keys */
431
+ static unsigned long _read_freq (struct dev_pm_opp * opp , int index )
432
+ {
433
+ return opp -> rate ;
434
+ }
435
+
436
+ /* Generic comparison helpers */
437
+ static bool _compare_exact (struct dev_pm_opp * * opp , struct dev_pm_opp * temp_opp ,
438
+ unsigned long opp_key , unsigned long key )
439
+ {
440
+ if (opp_key == key ) {
441
+ * opp = temp_opp ;
442
+ return true;
443
+ }
444
+
445
+ return false;
446
+ }
447
+
448
+ static bool _compare_ceil (struct dev_pm_opp * * opp , struct dev_pm_opp * temp_opp ,
449
+ unsigned long opp_key , unsigned long key )
450
+ {
451
+ if (opp_key >= key ) {
452
+ * opp = temp_opp ;
453
+ return true;
454
+ }
455
+
456
+ return false;
457
+ }
458
+
459
+ static bool _compare_floor (struct dev_pm_opp * * opp , struct dev_pm_opp * temp_opp ,
460
+ unsigned long opp_key , unsigned long key )
461
+ {
462
+ if (opp_key > key )
463
+ return true;
464
+
465
+ * opp = temp_opp ;
466
+ return false;
467
+ }
468
+
469
+ /* Generic key finding helpers */
470
+ static struct dev_pm_opp * _opp_table_find_key (struct opp_table * opp_table ,
471
+ unsigned long * key , int index , bool available ,
472
+ unsigned long (* read )(struct dev_pm_opp * opp , int index ),
473
+ bool (* compare )(struct dev_pm_opp * * opp , struct dev_pm_opp * temp_opp ,
474
+ unsigned long opp_key , unsigned long key ))
475
+ {
476
+ struct dev_pm_opp * temp_opp , * opp = ERR_PTR (- ERANGE );
477
+
478
+ mutex_lock (& opp_table -> lock );
479
+
480
+ list_for_each_entry (temp_opp , & opp_table -> opp_list , node ) {
481
+ if (temp_opp -> available == available ) {
482
+ if (compare (& opp , temp_opp , read (temp_opp , index ), * key ))
483
+ break ;
484
+ }
485
+ }
486
+
487
+ /* Increment the reference count of OPP */
488
+ if (!IS_ERR (opp )) {
489
+ * key = read (opp , index );
490
+ dev_pm_opp_get (opp );
491
+ }
492
+
493
+ mutex_unlock (& opp_table -> lock );
494
+
495
+ return opp ;
496
+ }
497
+
498
+ static struct dev_pm_opp *
499
+ _find_key (struct device * dev , unsigned long * key , int index , bool available ,
500
+ unsigned long (* read )(struct dev_pm_opp * opp , int index ),
501
+ bool (* compare )(struct dev_pm_opp * * opp , struct dev_pm_opp * temp_opp ,
502
+ unsigned long opp_key , unsigned long key ))
503
+ {
504
+ struct opp_table * opp_table ;
505
+ struct dev_pm_opp * opp ;
506
+
507
+ opp_table = _find_opp_table (dev );
508
+ if (IS_ERR (opp_table )) {
509
+ dev_err (dev , "%s: OPP table not found (%ld)\n" , __func__ ,
510
+ PTR_ERR (opp_table ));
511
+ return ERR_CAST (opp_table );
512
+ }
513
+
514
+ opp = _opp_table_find_key (opp_table , key , index , available , read ,
515
+ compare );
516
+
517
+ dev_pm_opp_put_opp_table (opp_table );
518
+
519
+ return opp ;
520
+ }
521
+
522
+ static struct dev_pm_opp * _find_key_exact (struct device * dev ,
523
+ unsigned long key , int index , bool available ,
524
+ unsigned long (* read )(struct dev_pm_opp * opp , int index ))
525
+ {
526
+ /*
527
+ * The value of key will be updated here, but will be ignored as the
528
+ * caller doesn't need it.
529
+ */
530
+ return _find_key (dev , & key , index , available , read , _compare_exact );
531
+ }
532
+
533
+ static struct dev_pm_opp * _opp_table_find_key_ceil (struct opp_table * opp_table ,
534
+ unsigned long * key , int index , bool available ,
535
+ unsigned long (* read )(struct dev_pm_opp * opp , int index ))
536
+ {
537
+ return _opp_table_find_key (opp_table , key , index , available , read ,
538
+ _compare_ceil );
539
+ }
540
+
541
+ static struct dev_pm_opp * _find_key_ceil (struct device * dev , unsigned long * key ,
542
+ int index , bool available ,
543
+ unsigned long (* read )(struct dev_pm_opp * opp , int index ))
544
+ {
545
+ return _find_key (dev , key , index , available , read , _compare_ceil );
546
+ }
547
+
548
+ static struct dev_pm_opp * _find_key_floor (struct device * dev ,
549
+ unsigned long * key , int index , bool available ,
550
+ unsigned long (* read )(struct dev_pm_opp * opp , int index ))
551
+ {
552
+ return _find_key (dev , key , index , available , read , _compare_floor );
553
+ }
554
+
430
555
/**
431
556
* dev_pm_opp_find_freq_exact() - search for an exact frequency
432
557
* @dev: device for which we do this operation
@@ -451,61 +576,16 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count);
451
576
* use.
452
577
*/
453
578
struct dev_pm_opp * dev_pm_opp_find_freq_exact (struct device * dev ,
454
- unsigned long freq ,
455
- bool available )
579
+ unsigned long freq , bool available )
456
580
{
457
- struct opp_table * opp_table ;
458
- struct dev_pm_opp * temp_opp , * opp = ERR_PTR (- ERANGE );
459
-
460
- opp_table = _find_opp_table (dev );
461
- if (IS_ERR (opp_table )) {
462
- int r = PTR_ERR (opp_table );
463
-
464
- dev_err (dev , "%s: OPP table not found (%d)\n" , __func__ , r );
465
- return ERR_PTR (r );
466
- }
467
-
468
- mutex_lock (& opp_table -> lock );
469
-
470
- list_for_each_entry (temp_opp , & opp_table -> opp_list , node ) {
471
- if (temp_opp -> available == available &&
472
- temp_opp -> rate == freq ) {
473
- opp = temp_opp ;
474
-
475
- /* Increment the reference count of OPP */
476
- dev_pm_opp_get (opp );
477
- break ;
478
- }
479
- }
480
-
481
- mutex_unlock (& opp_table -> lock );
482
- dev_pm_opp_put_opp_table (opp_table );
483
-
484
- return opp ;
581
+ return _find_key_exact (dev , freq , 0 , available , _read_freq );
485
582
}
486
583
EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_exact );
487
584
488
585
static noinline struct dev_pm_opp * _find_freq_ceil (struct opp_table * opp_table ,
489
586
unsigned long * freq )
490
587
{
491
- struct dev_pm_opp * temp_opp , * opp = ERR_PTR (- ERANGE );
492
-
493
- mutex_lock (& opp_table -> lock );
494
-
495
- list_for_each_entry (temp_opp , & opp_table -> opp_list , node ) {
496
- if (temp_opp -> available && temp_opp -> rate >= * freq ) {
497
- opp = temp_opp ;
498
- * freq = opp -> rate ;
499
-
500
- /* Increment the reference count of OPP */
501
- dev_pm_opp_get (opp );
502
- break ;
503
- }
504
- }
505
-
506
- mutex_unlock (& opp_table -> lock );
507
-
508
- return opp ;
588
+ return _opp_table_find_key_ceil (opp_table , freq , 0 , true, _read_freq );
509
589
}
510
590
511
591
/**
@@ -529,23 +609,7 @@ static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table,
529
609
struct dev_pm_opp * dev_pm_opp_find_freq_ceil (struct device * dev ,
530
610
unsigned long * freq )
531
611
{
532
- struct opp_table * opp_table ;
533
- struct dev_pm_opp * opp ;
534
-
535
- if (!dev || !freq ) {
536
- dev_err (dev , "%s: Invalid argument freq=%p\n" , __func__ , freq );
537
- return ERR_PTR (- EINVAL );
538
- }
539
-
540
- opp_table = _find_opp_table (dev );
541
- if (IS_ERR (opp_table ))
542
- return ERR_CAST (opp_table );
543
-
544
- opp = _find_freq_ceil (opp_table , freq );
545
-
546
- dev_pm_opp_put_opp_table (opp_table );
547
-
548
- return opp ;
612
+ return _find_key_ceil (dev , freq , 0 , true, _read_freq );
549
613
}
550
614
EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_ceil );
551
615
@@ -570,40 +634,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil);
570
634
struct dev_pm_opp * dev_pm_opp_find_freq_floor (struct device * dev ,
571
635
unsigned long * freq )
572
636
{
573
- struct opp_table * opp_table ;
574
- struct dev_pm_opp * temp_opp , * opp = ERR_PTR (- ERANGE );
575
-
576
- if (!dev || !freq ) {
577
- dev_err (dev , "%s: Invalid argument freq=%p\n" , __func__ , freq );
578
- return ERR_PTR (- EINVAL );
579
- }
580
-
581
- opp_table = _find_opp_table (dev );
582
- if (IS_ERR (opp_table ))
583
- return ERR_CAST (opp_table );
584
-
585
- mutex_lock (& opp_table -> lock );
586
-
587
- list_for_each_entry (temp_opp , & opp_table -> opp_list , node ) {
588
- if (temp_opp -> available ) {
589
- /* go to the next node, before choosing prev */
590
- if (temp_opp -> rate > * freq )
591
- break ;
592
- else
593
- opp = temp_opp ;
594
- }
595
- }
596
-
597
- /* Increment the reference count of OPP */
598
- if (!IS_ERR (opp ))
599
- dev_pm_opp_get (opp );
600
- mutex_unlock (& opp_table -> lock );
601
- dev_pm_opp_put_opp_table (opp_table );
602
-
603
- if (!IS_ERR (opp ))
604
- * freq = opp -> rate ;
605
-
606
- return opp ;
637
+ return _find_key_floor (dev , freq , 0 , true, _read_freq );
607
638
}
608
639
EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_floor );
609
640
0 commit comments