@@ -1054,48 +1054,22 @@ static int _set_opp_bw(const struct opp_table *opp_table,
1054
1054
return 0 ;
1055
1055
}
1056
1056
1057
- static int _set_performance_state (struct device * dev , struct device * pd_dev ,
1058
- struct dev_pm_opp * opp , int i )
1059
- {
1060
- unsigned int pstate = 0 ;
1061
- int ret ;
1062
-
1063
- if (!pd_dev )
1064
- return 0 ;
1065
-
1066
- if (likely (opp )) {
1067
- pstate = opp -> required_opps [i ]-> level ;
1068
- if (pstate == OPP_LEVEL_UNSET )
1069
- return 0 ;
1070
- }
1071
-
1072
- ret = dev_pm_domain_set_performance_state (pd_dev , pstate );
1073
- if (ret ) {
1074
- dev_err (dev , "Failed to set performance state of %s: %d (%d)\n" ,
1075
- dev_name (pd_dev ), pstate , ret );
1076
- }
1077
-
1078
- return ret ;
1079
- }
1080
-
1081
- static int _opp_set_required_opps_generic (struct device * dev ,
1082
- struct opp_table * opp_table , struct dev_pm_opp * opp , bool scaling_down )
1083
- {
1084
- dev_err (dev , "setting required-opps isn't supported for non-genpd devices\n" );
1085
- return - ENOENT ;
1086
- }
1087
-
1088
- static int _opp_set_required_opps_genpd (struct device * dev ,
1089
- struct opp_table * opp_table , struct dev_pm_opp * opp , bool scaling_down )
1057
+ /* This is only called for PM domain for now */
1058
+ static int _set_required_opps (struct device * dev , struct opp_table * opp_table ,
1059
+ struct dev_pm_opp * opp , bool up )
1090
1060
{
1091
- struct device * * genpd_virt_devs = opp_table -> genpd_virt_devs ;
1061
+ struct device * * devs = opp_table -> required_devs ;
1092
1062
int index , target , delta , ret ;
1093
1063
1094
- if (!genpd_virt_devs )
1064
+ if (!devs )
1095
1065
return 0 ;
1096
1066
1067
+ /* required-opps not fully initialized yet */
1068
+ if (lazy_linking_pending (opp_table ))
1069
+ return - EBUSY ;
1070
+
1097
1071
/* Scaling up? Set required OPPs in normal order, else reverse */
1098
- if (! scaling_down ) {
1072
+ if (up ) {
1099
1073
index = 0 ;
1100
1074
target = opp_table -> required_opp_count ;
1101
1075
delta = 1 ;
@@ -1106,44 +1080,18 @@ static int _opp_set_required_opps_genpd(struct device *dev,
1106
1080
}
1107
1081
1108
1082
while (index != target ) {
1109
- ret = _set_performance_state (dev , genpd_virt_devs [index ], opp , index );
1110
- if (ret )
1111
- return ret ;
1083
+ if (devs [index ]) {
1084
+ ret = dev_pm_opp_set_opp (devs [index ], opp -> required_opps [index ]);
1085
+ if (ret )
1086
+ return ret ;
1087
+ }
1112
1088
1113
1089
index += delta ;
1114
1090
}
1115
1091
1116
1092
return 0 ;
1117
1093
}
1118
1094
1119
- /* This is only called for PM domain for now */
1120
- static int _set_required_opps (struct device * dev , struct opp_table * opp_table ,
1121
- struct dev_pm_opp * opp , bool up )
1122
- {
1123
- /* required-opps not fully initialized yet */
1124
- if (lazy_linking_pending (opp_table ))
1125
- return - EBUSY ;
1126
-
1127
- if (opp_table -> set_required_opps )
1128
- return opp_table -> set_required_opps (dev , opp_table , opp , up );
1129
-
1130
- return 0 ;
1131
- }
1132
-
1133
- /* Update set_required_opps handler */
1134
- void _update_set_required_opps (struct opp_table * opp_table )
1135
- {
1136
- /* Already set */
1137
- if (opp_table -> set_required_opps )
1138
- return ;
1139
-
1140
- /* All required OPPs will belong to genpd or none */
1141
- if (opp_table -> required_opp_tables [0 ]-> is_genpd )
1142
- opp_table -> set_required_opps = _opp_set_required_opps_genpd ;
1143
- else
1144
- opp_table -> set_required_opps = _opp_set_required_opps_generic ;
1145
- }
1146
-
1147
1095
static int _set_opp_level (struct device * dev , struct opp_table * opp_table ,
1148
1096
struct dev_pm_opp * opp )
1149
1097
{
@@ -2406,19 +2354,13 @@ static void _opp_detach_genpd(struct opp_table *opp_table)
2406
2354
{
2407
2355
int index ;
2408
2356
2409
- if (!opp_table -> genpd_virt_devs )
2410
- return ;
2411
-
2412
2357
for (index = 0 ; index < opp_table -> required_opp_count ; index ++ ) {
2413
- if (!opp_table -> genpd_virt_devs [index ])
2358
+ if (!opp_table -> required_devs [index ])
2414
2359
continue ;
2415
2360
2416
- dev_pm_domain_detach (opp_table -> genpd_virt_devs [index ], false);
2417
- opp_table -> genpd_virt_devs [index ] = NULL ;
2361
+ dev_pm_domain_detach (opp_table -> required_devs [index ], false);
2362
+ opp_table -> required_devs [index ] = NULL ;
2418
2363
}
2419
-
2420
- kfree (opp_table -> genpd_virt_devs );
2421
- opp_table -> genpd_virt_devs = NULL ;
2422
2364
}
2423
2365
2424
2366
/*
@@ -2445,14 +2387,14 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev,
2445
2387
int index = 0 , ret = - EINVAL ;
2446
2388
const char * const * name = names ;
2447
2389
2448
- if (opp_table -> genpd_virt_devs )
2449
- return 0 ;
2390
+ if (!opp_table -> required_devs ) {
2391
+ dev_err (dev , "Required OPPs not available, can't attach genpd\n" );
2392
+ return - EINVAL ;
2393
+ }
2450
2394
2451
- opp_table -> genpd_virt_devs = kcalloc (opp_table -> required_opp_count ,
2452
- sizeof (* opp_table -> genpd_virt_devs ),
2453
- GFP_KERNEL );
2454
- if (!opp_table -> genpd_virt_devs )
2455
- return - ENOMEM ;
2395
+ /* Checking only the first one is enough ? */
2396
+ if (opp_table -> required_devs [0 ])
2397
+ return 0 ;
2456
2398
2457
2399
while (* name ) {
2458
2400
if (index >= opp_table -> required_opp_count ) {
@@ -2468,13 +2410,25 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev,
2468
2410
goto err ;
2469
2411
}
2470
2412
2471
- opp_table -> genpd_virt_devs [index ] = virt_dev ;
2413
+ /*
2414
+ * Add the virtual genpd device as a user of the OPP table, so
2415
+ * we can call dev_pm_opp_set_opp() on it directly.
2416
+ *
2417
+ * This will be automatically removed when the OPP table is
2418
+ * removed, don't need to handle that here.
2419
+ */
2420
+ if (!_add_opp_dev (virt_dev , opp_table -> required_opp_tables [index ])) {
2421
+ ret = - ENOMEM ;
2422
+ goto err ;
2423
+ }
2424
+
2425
+ opp_table -> required_devs [index ] = virt_dev ;
2472
2426
index ++ ;
2473
2427
name ++ ;
2474
2428
}
2475
2429
2476
2430
if (virt_devs )
2477
- * virt_devs = opp_table -> genpd_virt_devs ;
2431
+ * virt_devs = opp_table -> required_devs ;
2478
2432
2479
2433
return 0 ;
2480
2434
@@ -2484,10 +2438,42 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev,
2484
2438
2485
2439
}
2486
2440
2441
+ static int _opp_set_required_devs (struct opp_table * opp_table ,
2442
+ struct device * dev ,
2443
+ struct device * * required_devs )
2444
+ {
2445
+ int i ;
2446
+
2447
+ if (!opp_table -> required_devs ) {
2448
+ dev_err (dev , "Required OPPs not available, can't set required devs\n" );
2449
+ return - EINVAL ;
2450
+ }
2451
+
2452
+ /* Another device that shares the OPP table has set the required devs ? */
2453
+ if (opp_table -> required_devs [0 ])
2454
+ return 0 ;
2455
+
2456
+ for (i = 0 ; i < opp_table -> required_opp_count ; i ++ )
2457
+ opp_table -> required_devs [i ] = required_devs [i ];
2458
+
2459
+ return 0 ;
2460
+ }
2461
+
2462
+ static void _opp_put_required_devs (struct opp_table * opp_table )
2463
+ {
2464
+ int i ;
2465
+
2466
+ for (i = 0 ; i < opp_table -> required_opp_count ; i ++ )
2467
+ opp_table -> required_devs [i ] = NULL ;
2468
+ }
2469
+
2487
2470
static void _opp_clear_config (struct opp_config_data * data )
2488
2471
{
2489
- if (data -> flags & OPP_CONFIG_GENPD )
2472
+ if (data -> flags & OPP_CONFIG_REQUIRED_DEVS )
2473
+ _opp_put_required_devs (data -> opp_table );
2474
+ else if (data -> flags & OPP_CONFIG_GENPD )
2490
2475
_opp_detach_genpd (data -> opp_table );
2476
+
2491
2477
if (data -> flags & OPP_CONFIG_REGULATOR )
2492
2478
_opp_put_regulators (data -> opp_table );
2493
2479
if (data -> flags & OPP_CONFIG_SUPPORTED_HW )
@@ -2601,12 +2587,22 @@ int dev_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config)
2601
2587
2602
2588
/* Attach genpds */
2603
2589
if (config -> genpd_names ) {
2590
+ if (config -> required_devs )
2591
+ goto err ;
2592
+
2604
2593
ret = _opp_attach_genpd (opp_table , dev , config -> genpd_names ,
2605
2594
config -> virt_devs );
2606
2595
if (ret )
2607
2596
goto err ;
2608
2597
2609
2598
data -> flags |= OPP_CONFIG_GENPD ;
2599
+ } else if (config -> required_devs ) {
2600
+ ret = _opp_set_required_devs (opp_table , dev ,
2601
+ config -> required_devs );
2602
+ if (ret )
2603
+ goto err ;
2604
+
2605
+ data -> flags |= OPP_CONFIG_REQUIRED_DEVS ;
2610
2606
}
2611
2607
2612
2608
ret = xa_alloc (& opp_configs , & id , data , XA_LIMIT (1 , INT_MAX ),
0 commit comments