@@ -297,7 +297,7 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
297297
298298 pdd = dev -> power .subsys_data ?
299299 dev -> power .subsys_data -> domain_data : NULL ;
300- if (pdd ) {
300+ if (pdd && pdd -> dev ) {
301301 to_gpd_data (pdd )-> td .constraint_changed = true;
302302 genpd = dev_to_genpd (dev );
303303 } else {
@@ -1266,6 +1266,27 @@ static void pm_genpd_complete(struct device *dev)
12661266
12671267#endif /* CONFIG_PM_SLEEP */
12681268
1269+ static struct generic_pm_domain_data * __pm_genpd_alloc_dev_data (struct device * dev )
1270+ {
1271+ struct generic_pm_domain_data * gpd_data ;
1272+
1273+ gpd_data = kzalloc (sizeof (* gpd_data ), GFP_KERNEL );
1274+ if (!gpd_data )
1275+ return NULL ;
1276+
1277+ mutex_init (& gpd_data -> lock );
1278+ gpd_data -> nb .notifier_call = genpd_dev_pm_qos_notifier ;
1279+ dev_pm_qos_add_notifier (dev , & gpd_data -> nb );
1280+ return gpd_data ;
1281+ }
1282+
1283+ static void __pm_genpd_free_dev_data (struct device * dev ,
1284+ struct generic_pm_domain_data * gpd_data )
1285+ {
1286+ dev_pm_qos_remove_notifier (dev , & gpd_data -> nb );
1287+ kfree (gpd_data );
1288+ }
1289+
12691290/**
12701291 * __pm_genpd_add_device - Add a device to an I/O PM domain.
12711292 * @genpd: PM domain to add the device to.
@@ -1275,7 +1296,7 @@ static void pm_genpd_complete(struct device *dev)
12751296int __pm_genpd_add_device (struct generic_pm_domain * genpd , struct device * dev ,
12761297 struct gpd_timing_data * td )
12771298{
1278- struct generic_pm_domain_data * gpd_data ;
1299+ struct generic_pm_domain_data * gpd_data_new , * gpd_data = NULL ;
12791300 struct pm_domain_data * pdd ;
12801301 int ret = 0 ;
12811302
@@ -1284,14 +1305,10 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
12841305 if (IS_ERR_OR_NULL (genpd ) || IS_ERR_OR_NULL (dev ))
12851306 return - EINVAL ;
12861307
1287- gpd_data = kzalloc ( sizeof ( * gpd_data ), GFP_KERNEL );
1288- if (!gpd_data )
1308+ gpd_data_new = __pm_genpd_alloc_dev_data ( dev );
1309+ if (!gpd_data_new )
12891310 return - ENOMEM ;
12901311
1291- mutex_init (& gpd_data -> lock );
1292- gpd_data -> nb .notifier_call = genpd_dev_pm_qos_notifier ;
1293- dev_pm_qos_add_notifier (dev , & gpd_data -> nb );
1294-
12951312 genpd_acquire_lock (genpd );
12961313
12971314 if (genpd -> prepared_count > 0 ) {
@@ -1305,35 +1322,42 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
13051322 goto out ;
13061323 }
13071324
1325+ ret = dev_pm_get_subsys_data (dev );
1326+ if (ret )
1327+ goto out ;
1328+
13081329 genpd -> device_count ++ ;
13091330 genpd -> max_off_time_changed = true;
13101331
1311- dev_pm_get_subsys_data (dev );
1312-
1313- mutex_lock (& gpd_data -> lock );
13141332 spin_lock_irq (& dev -> power .lock );
1333+
13151334 dev -> pm_domain = & genpd -> domain ;
1316- dev -> power .subsys_data -> domain_data = & gpd_data -> base ;
1317- gpd_data -> base .dev = dev ;
1318- list_add_tail (& gpd_data -> base .list_node , & genpd -> dev_list );
1319- gpd_data -> need_restore = genpd -> status == GPD_STATE_POWER_OFF ;
1335+ if (dev -> power .subsys_data -> domain_data ) {
1336+ gpd_data = to_gpd_data (dev -> power .subsys_data -> domain_data );
1337+ } else {
1338+ gpd_data = gpd_data_new ;
1339+ dev -> power .subsys_data -> domain_data = & gpd_data -> base ;
1340+ }
1341+ gpd_data -> refcount ++ ;
13201342 if (td )
13211343 gpd_data -> td = * td ;
13221344
1345+ spin_unlock_irq (& dev -> power .lock );
1346+
1347+ mutex_lock (& gpd_data -> lock );
1348+ gpd_data -> base .dev = dev ;
1349+ list_add_tail (& gpd_data -> base .list_node , & genpd -> dev_list );
1350+ gpd_data -> need_restore = genpd -> status == GPD_STATE_POWER_OFF ;
13231351 gpd_data -> td .constraint_changed = true;
13241352 gpd_data -> td .effective_constraint_ns = -1 ;
1325- spin_unlock_irq (& dev -> power .lock );
13261353 mutex_unlock (& gpd_data -> lock );
13271354
1328- genpd_release_lock (genpd );
1329-
1330- return 0 ;
1331-
13321355 out :
13331356 genpd_release_lock (genpd );
13341357
1335- dev_pm_qos_remove_notifier (dev , & gpd_data -> nb );
1336- kfree (gpd_data );
1358+ if (gpd_data != gpd_data_new )
1359+ __pm_genpd_free_dev_data (dev , gpd_data_new );
1360+
13371361 return ret ;
13381362}
13391363
@@ -1379,6 +1403,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
13791403{
13801404 struct generic_pm_domain_data * gpd_data ;
13811405 struct pm_domain_data * pdd ;
1406+ bool remove = false;
13821407 int ret = 0 ;
13831408
13841409 dev_dbg (dev , "%s()\n" , __func__ );
@@ -1399,22 +1424,28 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
13991424 genpd -> max_off_time_changed = true;
14001425
14011426 spin_lock_irq (& dev -> power .lock );
1427+
14021428 dev -> pm_domain = NULL ;
14031429 pdd = dev -> power .subsys_data -> domain_data ;
14041430 list_del_init (& pdd -> list_node );
1405- dev -> power .subsys_data -> domain_data = NULL ;
1431+ gpd_data = to_gpd_data (pdd );
1432+ if (-- gpd_data -> refcount == 0 ) {
1433+ dev -> power .subsys_data -> domain_data = NULL ;
1434+ remove = true;
1435+ }
1436+
14061437 spin_unlock_irq (& dev -> power .lock );
14071438
1408- gpd_data = to_gpd_data (pdd );
14091439 mutex_lock (& gpd_data -> lock );
14101440 pdd -> dev = NULL ;
14111441 mutex_unlock (& gpd_data -> lock );
14121442
14131443 genpd_release_lock (genpd );
14141444
1415- dev_pm_qos_remove_notifier (dev , & gpd_data -> nb );
1416- kfree (gpd_data );
14171445 dev_pm_put_subsys_data (dev );
1446+ if (remove )
1447+ __pm_genpd_free_dev_data (dev , gpd_data );
1448+
14181449 return 0 ;
14191450
14201451 out :
0 commit comments