@@ -189,6 +189,29 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
189
189
return ERR_PTR (- ENODEV );
190
190
}
191
191
192
+ static int devfreq_notify_transition (struct devfreq * devfreq ,
193
+ struct devfreq_freqs * freqs , unsigned int state )
194
+ {
195
+ if (!devfreq )
196
+ return - EINVAL ;
197
+
198
+ switch (state ) {
199
+ case DEVFREQ_PRECHANGE :
200
+ srcu_notifier_call_chain (& devfreq -> transition_notifier_list ,
201
+ DEVFREQ_PRECHANGE , freqs );
202
+ break ;
203
+
204
+ case DEVFREQ_POSTCHANGE :
205
+ srcu_notifier_call_chain (& devfreq -> transition_notifier_list ,
206
+ DEVFREQ_POSTCHANGE , freqs );
207
+ break ;
208
+ default :
209
+ return - EINVAL ;
210
+ }
211
+
212
+ return 0 ;
213
+ }
214
+
192
215
/* Load monitoring helper functions for governors use */
193
216
194
217
/**
@@ -200,7 +223,8 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
200
223
*/
201
224
int update_devfreq (struct devfreq * devfreq )
202
225
{
203
- unsigned long freq ;
226
+ struct devfreq_freqs freqs ;
227
+ unsigned long freq , cur_freq ;
204
228
int err = 0 ;
205
229
u32 flags = 0 ;
206
230
@@ -234,10 +258,22 @@ int update_devfreq(struct devfreq *devfreq)
234
258
flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND ; /* Use LUB */
235
259
}
236
260
261
+ if (devfreq -> profile -> get_cur_freq )
262
+ devfreq -> profile -> get_cur_freq (devfreq -> dev .parent , & cur_freq );
263
+ else
264
+ cur_freq = devfreq -> previous_freq ;
265
+
266
+ freqs .old = cur_freq ;
267
+ freqs .new = freq ;
268
+ devfreq_notify_transition (devfreq , & freqs , DEVFREQ_PRECHANGE );
269
+
237
270
err = devfreq -> profile -> target (devfreq -> dev .parent , & freq , flags );
238
271
if (err )
239
272
return err ;
240
273
274
+ freqs .new = freq ;
275
+ devfreq_notify_transition (devfreq , & freqs , DEVFREQ_POSTCHANGE );
276
+
241
277
if (devfreq -> profile -> freq_table )
242
278
if (devfreq_update_status (devfreq , freq ))
243
279
dev_err (& devfreq -> dev ,
@@ -542,6 +578,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
542
578
goto err_out ;
543
579
}
544
580
581
+ srcu_init_notifier_head (& devfreq -> transition_notifier_list );
582
+
545
583
mutex_unlock (& devfreq -> lock );
546
584
547
585
mutex_lock (& devfreq_list_lock );
@@ -1310,6 +1348,129 @@ void devm_devfreq_unregister_opp_notifier(struct device *dev,
1310
1348
}
1311
1349
EXPORT_SYMBOL (devm_devfreq_unregister_opp_notifier );
1312
1350
1351
+ /**
1352
+ * devfreq_register_notifier() - Register a driver with devfreq
1353
+ * @devfreq: The devfreq object.
1354
+ * @nb: The notifier block to register.
1355
+ * @list: DEVFREQ_TRANSITION_NOTIFIER.
1356
+ */
1357
+ int devfreq_register_notifier (struct devfreq * devfreq ,
1358
+ struct notifier_block * nb ,
1359
+ unsigned int list )
1360
+ {
1361
+ int ret = 0 ;
1362
+
1363
+ if (!devfreq )
1364
+ return - EINVAL ;
1365
+
1366
+ switch (list ) {
1367
+ case DEVFREQ_TRANSITION_NOTIFIER :
1368
+ ret = srcu_notifier_chain_register (
1369
+ & devfreq -> transition_notifier_list , nb );
1370
+ break ;
1371
+ default :
1372
+ ret = - EINVAL ;
1373
+ }
1374
+
1375
+ return ret ;
1376
+ }
1377
+ EXPORT_SYMBOL (devfreq_register_notifier );
1378
+
1379
+ /*
1380
+ * devfreq_unregister_notifier() - Unregister a driver with devfreq
1381
+ * @devfreq: The devfreq object.
1382
+ * @nb: The notifier block to be unregistered.
1383
+ * @list: DEVFREQ_TRANSITION_NOTIFIER.
1384
+ */
1385
+ int devfreq_unregister_notifier (struct devfreq * devfreq ,
1386
+ struct notifier_block * nb ,
1387
+ unsigned int list )
1388
+ {
1389
+ int ret = 0 ;
1390
+
1391
+ if (!devfreq )
1392
+ return - EINVAL ;
1393
+
1394
+ switch (list ) {
1395
+ case DEVFREQ_TRANSITION_NOTIFIER :
1396
+ ret = srcu_notifier_chain_unregister (
1397
+ & devfreq -> transition_notifier_list , nb );
1398
+ break ;
1399
+ default :
1400
+ ret = - EINVAL ;
1401
+ }
1402
+
1403
+ return ret ;
1404
+ }
1405
+ EXPORT_SYMBOL (devfreq_unregister_notifier );
1406
+
1407
+ struct devfreq_notifier_devres {
1408
+ struct devfreq * devfreq ;
1409
+ struct notifier_block * nb ;
1410
+ unsigned int list ;
1411
+ };
1412
+
1413
+ static void devm_devfreq_notifier_release (struct device * dev , void * res )
1414
+ {
1415
+ struct devfreq_notifier_devres * this = res ;
1416
+
1417
+ devfreq_unregister_notifier (this -> devfreq , this -> nb , this -> list );
1418
+ }
1419
+
1420
+ /**
1421
+ * devm_devfreq_register_notifier()
1422
+ - Resource-managed devfreq_register_notifier()
1423
+ * @dev: The devfreq user device. (parent of devfreq)
1424
+ * @devfreq: The devfreq object.
1425
+ * @nb: The notifier block to be unregistered.
1426
+ * @list: DEVFREQ_TRANSITION_NOTIFIER.
1427
+ */
1428
+ int devm_devfreq_register_notifier (struct device * dev ,
1429
+ struct devfreq * devfreq ,
1430
+ struct notifier_block * nb ,
1431
+ unsigned int list )
1432
+ {
1433
+ struct devfreq_notifier_devres * ptr ;
1434
+ int ret ;
1435
+
1436
+ ptr = devres_alloc (devm_devfreq_notifier_release , sizeof (* ptr ),
1437
+ GFP_KERNEL );
1438
+ if (!ptr )
1439
+ return - ENOMEM ;
1440
+
1441
+ ret = devfreq_register_notifier (devfreq , nb , list );
1442
+ if (ret ) {
1443
+ devres_free (ptr );
1444
+ return ret ;
1445
+ }
1446
+
1447
+ ptr -> devfreq = devfreq ;
1448
+ ptr -> nb = nb ;
1449
+ ptr -> list = list ;
1450
+ devres_add (dev , ptr );
1451
+
1452
+ return 0 ;
1453
+ }
1454
+ EXPORT_SYMBOL (devm_devfreq_register_notifier );
1455
+
1456
+ /**
1457
+ * devm_devfreq_unregister_notifier()
1458
+ - Resource-managed devfreq_unregister_notifier()
1459
+ * @dev: The devfreq user device. (parent of devfreq)
1460
+ * @devfreq: The devfreq object.
1461
+ * @nb: The notifier block to be unregistered.
1462
+ * @list: DEVFREQ_TRANSITION_NOTIFIER.
1463
+ */
1464
+ void devm_devfreq_unregister_notifier (struct device * dev ,
1465
+ struct devfreq * devfreq ,
1466
+ struct notifier_block * nb ,
1467
+ unsigned int list )
1468
+ {
1469
+ WARN_ON (devres_release (dev , devm_devfreq_notifier_release ,
1470
+ devm_devfreq_dev_match , devfreq ));
1471
+ }
1472
+ EXPORT_SYMBOL (devm_devfreq_unregister_notifier );
1473
+
1313
1474
MODULE_AUTHOR ("MyungJoo Ham <myungjoo.ham@samsung.com>" );
1314
1475
MODULE_DESCRIPTION ("devfreq class support" );
1315
1476
MODULE_LICENSE ("GPL" );
0 commit comments