PM / Domains: Merge measurements for PM QoS device latencies
[firefly-linux-kernel-4.4.55.git] / drivers / base / power / domain.c
index a1c3ec4cc4fb9ca8c032e1672c1a4d8bb68a1197..a7dfdf9f15bada9112d38c6c5616abbd40f3762c 100644 (file)
        __ret;                                                  \
 })
 
-#define GENPD_DEV_TIMED_CALLBACK(genpd, type, callback, dev, field, name)      \
-({                                                                             \
-       ktime_t __start = ktime_get();                                          \
-       type __retval = GENPD_DEV_CALLBACK(genpd, type, callback, dev);         \
-       s64 __elapsed = ktime_to_ns(ktime_sub(ktime_get(), __start));           \
-       struct gpd_timing_data *__td = &dev_gpd_data(dev)->td;                  \
-       if (!__retval && __elapsed > __td->field) {                             \
-               __td->field = __elapsed;                                        \
-               dev_dbg(dev, name " latency exceeded, new value %lld ns\n",     \
-                       __elapsed);                                             \
-               genpd->max_off_time_changed = true;                             \
-               __td->constraint_changed = true;                                \
-       }                                                                       \
-       __retval;                                                               \
-})
-
 static LIST_HEAD(gpd_list);
 static DEFINE_MUTEX(gpd_list_lock);
 
@@ -90,24 +74,14 @@ static struct generic_pm_domain *dev_to_genpd(struct device *dev)
        return pd_to_genpd(dev->pm_domain);
 }
 
-static int genpd_stop_dev(struct generic_pm_domain *genpd, struct device *dev,
-                       bool timed)
+static int genpd_stop_dev(struct generic_pm_domain *genpd, struct device *dev)
 {
-       if (!timed)
-               return GENPD_DEV_CALLBACK(genpd, int, stop, dev);
-
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, stop, dev,
-                                       stop_latency_ns, "stop");
+       return GENPD_DEV_CALLBACK(genpd, int, stop, dev);
 }
 
-static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev,
-                       bool timed)
+static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
 {
-       if (!timed)
-               return GENPD_DEV_CALLBACK(genpd, int, start, dev);
-
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, start, dev,
-                                       start_latency_ns, "start");
+       return GENPD_DEV_CALLBACK(genpd, int, start, dev);
 }
 
 static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
@@ -263,19 +237,13 @@ static int genpd_poweron(struct generic_pm_domain *genpd)
 
 static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
 {
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
-                                       save_state_latency_ns, "state save");
+       return GENPD_DEV_CALLBACK(genpd, int, save_state, dev);
 }
 
 static int genpd_restore_dev(struct generic_pm_domain *genpd,
-                       struct device *dev, bool timed)
+                       struct device *dev)
 {
-       if (!timed)
-               return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
-
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
-                                       restore_state_latency_ns,
-                                       "state restore");
+       return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
 }
 
 static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
@@ -422,6 +390,9 @@ static int pm_genpd_runtime_suspend(struct device *dev)
 {
        struct generic_pm_domain *genpd;
        bool (*stop_ok)(struct device *__dev);
+       struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
+       ktime_t time_start;
+       s64 elapsed_ns;
        int ret;
 
        dev_dbg(dev, "%s()\n", __func__);
@@ -434,16 +405,29 @@ static int pm_genpd_runtime_suspend(struct device *dev)
        if (stop_ok && !stop_ok(dev))
                return -EBUSY;
 
+       /* Measure suspend latency. */
+       time_start = ktime_get();
+
        ret = genpd_save_dev(genpd, dev);
        if (ret)
                return ret;
 
-       ret = genpd_stop_dev(genpd, dev, true);
+       ret = genpd_stop_dev(genpd, dev);
        if (ret) {
-               genpd_restore_dev(genpd, dev, true);
+               genpd_restore_dev(genpd, dev);
                return ret;
        }
 
+       /* Update suspend latency value if the measured time exceeds it. */
+       elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
+       if (elapsed_ns > td->suspend_latency_ns) {
+               td->suspend_latency_ns = elapsed_ns;
+               dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
+                       elapsed_ns);
+               genpd->max_off_time_changed = true;
+               td->constraint_changed = true;
+       }
+
        /*
         * If power.irq_safe is set, this routine will be run with interrupts
         * off, so it can't use mutexes.
@@ -469,6 +453,9 @@ static int pm_genpd_runtime_suspend(struct device *dev)
 static int pm_genpd_runtime_resume(struct device *dev)
 {
        struct generic_pm_domain *genpd;
+       struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
+       ktime_t time_start;
+       s64 elapsed_ns;
        int ret;
        bool timed = true;
 
@@ -492,8 +479,24 @@ static int pm_genpd_runtime_resume(struct device *dev)
                return ret;
 
  out:
-       genpd_start_dev(genpd, dev, timed);
-       genpd_restore_dev(genpd, dev, timed);
+       /* Measure resume latency. */
+       if (timed)
+               time_start = ktime_get();
+
+       genpd_start_dev(genpd, dev);
+       genpd_restore_dev(genpd, dev);
+
+       /* Update resume latency value if the measured time exceeds it. */
+       if (timed) {
+               elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
+               if (elapsed_ns > td->resume_latency_ns) {
+                       td->resume_latency_ns = elapsed_ns;
+                       dev_dbg(dev, "resume latency exceeded, %lld ns\n",
+                               elapsed_ns);
+                       genpd->max_off_time_changed = true;
+                       td->constraint_changed = true;
+               }
+       }
 
        return 0;
 }
@@ -783,7 +786,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
            || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
                return 0;
 
-       genpd_stop_dev(genpd, dev, false);
+       genpd_stop_dev(genpd, dev);
 
        /*
         * Since all of the "noirq" callbacks are executed sequentially, it is
@@ -824,7 +827,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
        pm_genpd_sync_poweron(genpd, true);
        genpd->suspended_count--;
 
-       return genpd_start_dev(genpd, dev, false);
+       return genpd_start_dev(genpd, dev);
 }
 
 /**
@@ -932,7 +935,7 @@ static int pm_genpd_freeze_noirq(struct device *dev)
        if (IS_ERR(genpd))
                return -EINVAL;
 
-       return genpd->suspend_power_off ? 0 : genpd_stop_dev(genpd, dev, false);
+       return genpd->suspend_power_off ? 0 : genpd_stop_dev(genpd, dev);
 }
 
 /**
@@ -953,7 +956,7 @@ static int pm_genpd_thaw_noirq(struct device *dev)
                return -EINVAL;
 
        return genpd->suspend_power_off ?
-               0 : genpd_start_dev(genpd, dev, false);
+               0 : genpd_start_dev(genpd, dev);
 }
 
 /**
@@ -1047,7 +1050,7 @@ static int pm_genpd_restore_noirq(struct device *dev)
 
        pm_genpd_sync_poweron(genpd, true);
 
-       return genpd_start_dev(genpd, dev, false);
+       return genpd_start_dev(genpd, dev);
 }
 
 /**