Commit d23b9b00cdde5c93b914a172cecd57d5625fcd04

Authored by Rafael J. Wysocki
1 parent ecf00475f2

PM / Domains: Rework system suspend callback routines (v2)

The current generic PM domains code attempts to use the generic
system suspend operations along with the domains' device stop/start
routines, which requires device drivers to assume that their
system suspend/resume (and hibernation/restore) callbacks will always
be used with generic PM domains.  However, in theory, the same
hardware may be used in devices that don't belong to any PM domain,
in which case it would be necessary to add "fake" PM domains to
satisfy the above assumption.  Also, the domain the hardware belongs
to may not be handled with the help of the generic code.

To allow device drivers that may be used along with the generic PM
domains code of more flexibility, add new device callbacks,
.suspend(), .suspend_late(), .resume_early(), .resume(), .freeze(),
.freeze_late(), .thaw_early(), and .thaw(), that can be supplied by
the drivers in addition to their "standard" system suspend and
hibernation callbacks.  These new callbacks, if defined, will be used
by the generic PM domains code for the handling of system suspend and
hibernation instead of the "standard" ones.  This will allow drivers
to be designed to work with generic PM domains as well as without
them.

For backwards compatibility, introduce default implementations of the
new callbacks for PM domains that will execute pm_generic_suspend(),
pm_generic_suspend_noirq(), pm_generic_resume_noirq(),
pm_generic_resume(), pm_generic_freeze(), pm_generic_freeze_noirq(),
pm_generic_thaw_noirq(), and pm_generic_thaw(), respectively, for the
given device if its driver doesn't define those callbacks.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>

Showing 2 changed files with 158 additions and 99 deletions Side-by-side Diff

drivers/base/power/domain.c
... ... @@ -561,6 +561,46 @@
561 561 return GENPD_DEV_CALLBACK(genpd, bool, active_wakeup, dev);
562 562 }
563 563  
  564 +static int genpd_suspend_dev(struct generic_pm_domain *genpd, struct device *dev)
  565 +{
  566 + return GENPD_DEV_CALLBACK(genpd, int, suspend, dev);
  567 +}
  568 +
  569 +static int genpd_suspend_late(struct generic_pm_domain *genpd, struct device *dev)
  570 +{
  571 + return GENPD_DEV_CALLBACK(genpd, int, suspend_late, dev);
  572 +}
  573 +
  574 +static int genpd_resume_early(struct generic_pm_domain *genpd, struct device *dev)
  575 +{
  576 + return GENPD_DEV_CALLBACK(genpd, int, resume_early, dev);
  577 +}
  578 +
  579 +static int genpd_resume_dev(struct generic_pm_domain *genpd, struct device *dev)
  580 +{
  581 + return GENPD_DEV_CALLBACK(genpd, int, resume, dev);
  582 +}
  583 +
  584 +static int genpd_freeze_dev(struct generic_pm_domain *genpd, struct device *dev)
  585 +{
  586 + return GENPD_DEV_CALLBACK(genpd, int, freeze, dev);
  587 +}
  588 +
  589 +static int genpd_freeze_late(struct generic_pm_domain *genpd, struct device *dev)
  590 +{
  591 + return GENPD_DEV_CALLBACK(genpd, int, freeze_late, dev);
  592 +}
  593 +
  594 +static int genpd_thaw_early(struct generic_pm_domain *genpd, struct device *dev)
  595 +{
  596 + return GENPD_DEV_CALLBACK(genpd, int, thaw_early, dev);
  597 +}
  598 +
  599 +static int genpd_thaw_dev(struct generic_pm_domain *genpd, struct device *dev)
  600 +{
  601 + return GENPD_DEV_CALLBACK(genpd, int, thaw, dev);
  602 +}
  603 +
564 604 /**
565 605 * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its masters.
566 606 * @genpd: PM domain to power off, if possible.
... ... @@ -712,7 +752,7 @@
712 752 if (IS_ERR(genpd))
713 753 return -EINVAL;
714 754  
715   - return genpd->suspend_power_off ? 0 : pm_generic_suspend(dev);
  755 + return genpd->suspend_power_off ? 0 : genpd_suspend_dev(genpd, dev);
716 756 }
717 757  
718 758 /**
... ... @@ -737,7 +777,7 @@
737 777 if (genpd->suspend_power_off)
738 778 return 0;
739 779  
740   - ret = pm_generic_suspend_noirq(dev);
  780 + ret = genpd_suspend_late(genpd, dev);
741 781 if (ret)
742 782 return ret;
743 783  
... ... @@ -788,7 +828,7 @@
788 828 genpd->suspended_count--;
789 829 genpd_start_dev(genpd, dev);
790 830  
791   - return pm_generic_resume_noirq(dev);
  831 + return genpd_resume_early(genpd, dev);
792 832 }
793 833  
794 834 /**
... ... @@ -809,7 +849,7 @@
809 849 if (IS_ERR(genpd))
810 850 return -EINVAL;
811 851  
812   - return genpd->suspend_power_off ? 0 : pm_generic_resume(dev);
  852 + return genpd->suspend_power_off ? 0 : genpd_resume_dev(genpd, dev);
813 853 }
814 854  
815 855 /**
... ... @@ -830,7 +870,7 @@
830 870 if (IS_ERR(genpd))
831 871 return -EINVAL;
832 872  
833   - return genpd->suspend_power_off ? 0 : pm_generic_freeze(dev);
  873 + return genpd->suspend_power_off ? 0 : genpd_freeze_dev(genpd, dev);
834 874 }
835 875  
836 876 /**
... ... @@ -856,7 +896,7 @@
856 896 if (genpd->suspend_power_off)
857 897 return 0;
858 898  
859   - ret = pm_generic_freeze_noirq(dev);
  899 + ret = genpd_freeze_late(genpd, dev);
860 900 if (ret)
861 901 return ret;
862 902  
... ... @@ -889,7 +929,7 @@
889 929  
890 930 genpd_start_dev(genpd, dev);
891 931  
892   - return pm_generic_thaw_noirq(dev);
  932 + return genpd_thaw_early(genpd, dev);
893 933 }
894 934  
895 935 /**
896 936  
... ... @@ -910,73 +950,10 @@
910 950 if (IS_ERR(genpd))
911 951 return -EINVAL;
912 952  
913   - return genpd->suspend_power_off ? 0 : pm_generic_thaw(dev);
  953 + return genpd->suspend_power_off ? 0 : genpd_thaw_dev(genpd, dev);
914 954 }
915 955  
916 956 /**
917   - * pm_genpd_dev_poweroff - Power off a device belonging to an I/O PM domain.
918   - * @dev: Device to suspend.
919   - *
920   - * Power off a device under the assumption that its pm_domain field points to
921   - * the domain member of an object of type struct generic_pm_domain representing
922   - * a PM domain consisting of I/O devices.
923   - */
924   -static int pm_genpd_dev_poweroff(struct device *dev)
925   -{
926   - struct generic_pm_domain *genpd;
927   -
928   - dev_dbg(dev, "%s()\n", __func__);
929   -
930   - genpd = dev_to_genpd(dev);
931   - if (IS_ERR(genpd))
932   - return -EINVAL;
933   -
934   - return genpd->suspend_power_off ? 0 : pm_generic_poweroff(dev);
935   -}
936   -
937   -/**
938   - * pm_genpd_dev_poweroff_noirq - Late power off of a device from a PM domain.
939   - * @dev: Device to suspend.
940   - *
941   - * Carry out a late powering off of a device under the assumption that its
942   - * pm_domain field points to the domain member of an object of type
943   - * struct generic_pm_domain representing a PM domain consisting of I/O devices.
944   - */
945   -static int pm_genpd_dev_poweroff_noirq(struct device *dev)
946   -{
947   - struct generic_pm_domain *genpd;
948   - int ret;
949   -
950   - dev_dbg(dev, "%s()\n", __func__);
951   -
952   - genpd = dev_to_genpd(dev);
953   - if (IS_ERR(genpd))
954   - return -EINVAL;
955   -
956   - if (genpd->suspend_power_off)
957   - return 0;
958   -
959   - ret = pm_generic_poweroff_noirq(dev);
960   - if (ret)
961   - return ret;
962   -
963   - if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))
964   - return 0;
965   -
966   - genpd_stop_dev(genpd, dev);
967   -
968   - /*
969   - * Since all of the "noirq" callbacks are executed sequentially, it is
970   - * guaranteed that this function will never run twice in parallel for
971   - * the same PM domain, so it is not necessary to use locking here.
972   - */
973   - genpd->suspended_count++;
974   - pm_genpd_sync_poweroff(genpd);
975   -
976   - return 0;
977   -}
978   -
979   -/**
980 957 * pm_genpd_restore_noirq - Early restore of a device from an I/O power domain.
981 958 * @dev: Device to resume.
982 959 *
983 960  
... ... @@ -1015,31 +992,10 @@
1015 992 genpd->suspended_count--;
1016 993 genpd_start_dev(genpd, dev);
1017 994  
1018   - return pm_generic_restore_noirq(dev);
  995 + return genpd_resume_early(genpd, dev);
1019 996 }
1020 997  
1021 998 /**
1022   - * pm_genpd_restore - Restore a device belonging to an I/O power domain.
1023   - * @dev: Device to resume.
1024   - *
1025   - * Restore a device under the assumption that its pm_domain field points to the
1026   - * domain member of an object of type struct generic_pm_domain representing
1027   - * a power domain consisting of I/O devices.
1028   - */
1029   -static int pm_genpd_restore(struct device *dev)
1030   -{
1031   - struct generic_pm_domain *genpd;
1032   -
1033   - dev_dbg(dev, "%s()\n", __func__);
1034   -
1035   - genpd = dev_to_genpd(dev);
1036   - if (IS_ERR(genpd))
1037   - return -EINVAL;
1038   -
1039   - return genpd->suspend_power_off ? 0 : pm_generic_restore(dev);
1040   -}
1041   -
1042   -/**
1043 999 * pm_genpd_complete - Complete power transition of a device in a power domain.
1044 1000 * @dev: Device to complete the transition of.
1045 1001 *
1046 1002  
... ... @@ -1086,10 +1042,7 @@
1086 1042 #define pm_genpd_freeze_noirq NULL
1087 1043 #define pm_genpd_thaw_noirq NULL
1088 1044 #define pm_genpd_thaw NULL
1089   -#define pm_genpd_dev_poweroff_noirq NULL
1090   -#define pm_genpd_dev_poweroff NULL
1091 1045 #define pm_genpd_restore_noirq NULL
1092   -#define pm_genpd_restore NULL
1093 1046 #define pm_genpd_complete NULL
1094 1047  
1095 1048 #endif /* CONFIG_PM_SLEEP */
... ... @@ -1361,6 +1314,8 @@
1361 1314 }
1362 1315 EXPORT_SYMBOL_GPL(pm_genpd_remove_callbacks);
1363 1316  
  1317 +/* Default device callbacks for generic PM domains. */
  1318 +
1364 1319 /**
1365 1320 * pm_genpd_default_save_state - Default "save device state" for PM domians.
1366 1321 * @dev: Device to handle.
... ... @@ -1400,6 +1355,94 @@
1400 1355 }
1401 1356  
1402 1357 /**
  1358 + * pm_genpd_default_suspend - Default "device suspend" for PM domians.
  1359 + * @dev: Device to handle.
  1360 + */
  1361 +static int pm_genpd_default_suspend(struct device *dev)
  1362 +{
  1363 + int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.freeze;
  1364 +
  1365 + return cb ? cb(dev) : pm_generic_suspend(dev);
  1366 +}
  1367 +
  1368 +/**
  1369 + * pm_genpd_default_suspend_late - Default "late device suspend" for PM domians.
  1370 + * @dev: Device to handle.
  1371 + */
  1372 +static int pm_genpd_default_suspend_late(struct device *dev)
  1373 +{
  1374 + int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.freeze_late;
  1375 +
  1376 + return cb ? cb(dev) : pm_generic_suspend_noirq(dev);
  1377 +}
  1378 +
  1379 +/**
  1380 + * pm_genpd_default_resume_early - Default "early device resume" for PM domians.
  1381 + * @dev: Device to handle.
  1382 + */
  1383 +static int pm_genpd_default_resume_early(struct device *dev)
  1384 +{
  1385 + int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.thaw_early;
  1386 +
  1387 + return cb ? cb(dev) : pm_generic_resume_noirq(dev);
  1388 +}
  1389 +
  1390 +/**
  1391 + * pm_genpd_default_resume - Default "device resume" for PM domians.
  1392 + * @dev: Device to handle.
  1393 + */
  1394 +static int pm_genpd_default_resume(struct device *dev)
  1395 +{
  1396 + int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.thaw;
  1397 +
  1398 + return cb ? cb(dev) : pm_generic_resume(dev);
  1399 +}
  1400 +
  1401 +/**
  1402 + * pm_genpd_default_freeze - Default "device freeze" for PM domians.
  1403 + * @dev: Device to handle.
  1404 + */
  1405 +static int pm_genpd_default_freeze(struct device *dev)
  1406 +{
  1407 + int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.freeze;
  1408 +
  1409 + return cb ? cb(dev) : pm_generic_freeze(dev);
  1410 +}
  1411 +
  1412 +/**
  1413 + * pm_genpd_default_freeze_late - Default "late device freeze" for PM domians.
  1414 + * @dev: Device to handle.
  1415 + */
  1416 +static int pm_genpd_default_freeze_late(struct device *dev)
  1417 +{
  1418 + int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.freeze_late;
  1419 +
  1420 + return cb ? cb(dev) : pm_generic_freeze_noirq(dev);
  1421 +}
  1422 +
  1423 +/**
  1424 + * pm_genpd_default_thaw_early - Default "early device thaw" for PM domians.
  1425 + * @dev: Device to handle.
  1426 + */
  1427 +static int pm_genpd_default_thaw_early(struct device *dev)
  1428 +{
  1429 + int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.thaw_early;
  1430 +
  1431 + return cb ? cb(dev) : pm_generic_thaw_noirq(dev);
  1432 +}
  1433 +
  1434 +/**
  1435 + * pm_genpd_default_thaw - Default "device thaw" for PM domians.
  1436 + * @dev: Device to handle.
  1437 + */
  1438 +static int pm_genpd_default_thaw(struct device *dev)
  1439 +{
  1440 + int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.thaw;
  1441 +
  1442 + return cb ? cb(dev) : pm_generic_thaw(dev);
  1443 +}
  1444 +
  1445 +/**
1403 1446 * pm_genpd_init - Initialize a generic I/O PM domain object.
1404 1447 * @genpd: PM domain object to initialize.
1405 1448 * @gov: PM domain governor to associate with the domain (may be NULL).
1406 1449  
1407 1450  
... ... @@ -1437,13 +1480,21 @@
1437 1480 genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
1438 1481 genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
1439 1482 genpd->domain.ops.thaw = pm_genpd_thaw;
1440   - genpd->domain.ops.poweroff = pm_genpd_dev_poweroff;
1441   - genpd->domain.ops.poweroff_noirq = pm_genpd_dev_poweroff_noirq;
  1483 + genpd->domain.ops.poweroff = pm_genpd_suspend;
  1484 + genpd->domain.ops.poweroff_noirq = pm_genpd_suspend_noirq;
1442 1485 genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
1443   - genpd->domain.ops.restore = pm_genpd_restore;
  1486 + genpd->domain.ops.restore = pm_genpd_resume;
1444 1487 genpd->domain.ops.complete = pm_genpd_complete;
1445 1488 genpd->dev_ops.save_state = pm_genpd_default_save_state;
1446 1489 genpd->dev_ops.restore_state = pm_genpd_default_restore_state;
  1490 + genpd->dev_ops.freeze = pm_genpd_default_suspend;
  1491 + genpd->dev_ops.freeze_late = pm_genpd_default_suspend_late;
  1492 + genpd->dev_ops.thaw_early = pm_genpd_default_resume_early;
  1493 + genpd->dev_ops.thaw = pm_genpd_default_resume;
  1494 + genpd->dev_ops.freeze = pm_genpd_default_freeze;
  1495 + genpd->dev_ops.freeze_late = pm_genpd_default_freeze_late;
  1496 + genpd->dev_ops.thaw_early = pm_genpd_default_thaw_early;
  1497 + genpd->dev_ops.thaw = pm_genpd_default_thaw;
1447 1498 mutex_lock(&gpd_list_lock);
1448 1499 list_add(&genpd->gpd_list_node, &gpd_list);
1449 1500 mutex_unlock(&gpd_list_lock);
include/linux/pm_domain.h
... ... @@ -28,6 +28,14 @@
28 28 int (*stop)(struct device *dev);
29 29 int (*save_state)(struct device *dev);
30 30 int (*restore_state)(struct device *dev);
  31 + int (*suspend)(struct device *dev);
  32 + int (*suspend_late)(struct device *dev);
  33 + int (*resume_early)(struct device *dev);
  34 + int (*resume)(struct device *dev);
  35 + int (*freeze)(struct device *dev);
  36 + int (*freeze_late)(struct device *dev);
  37 + int (*thaw_early)(struct device *dev);
  38 + int (*thaw)(struct device *dev);
31 39 bool (*active_wakeup)(struct device *dev);
32 40 };
33 41