LCOV - code coverage report
Current view: top level - drivers/base/power - domain_governor.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 0 69 0.0 %
Date: 2020-09-30 20:25:40 Functions: 0 5 0.0 %
Branches: 0 44 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * drivers/base/power/domain_governor.c - Governors for device PM domains.
       4                 :            :  *
       5                 :            :  * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
       6                 :            :  */
       7                 :            : #include <linux/kernel.h>
       8                 :            : #include <linux/pm_domain.h>
       9                 :            : #include <linux/pm_qos.h>
      10                 :            : #include <linux/hrtimer.h>
      11                 :            : #include <linux/cpuidle.h>
      12                 :            : #include <linux/cpumask.h>
      13                 :            : #include <linux/ktime.h>
      14                 :            : 
      15                 :          0 : static int dev_update_qos_constraint(struct device *dev, void *data)
      16                 :            : {
      17                 :            :         s64 *constraint_ns_p = data;
      18                 :            :         s64 constraint_ns;
      19                 :            : 
      20   [ #  #  #  # ]:          0 :         if (dev->power.subsys_data && dev->power.subsys_data->domain_data) {
      21                 :            :                 /*
      22                 :            :                  * Only take suspend-time QoS constraints of devices into
      23                 :            :                  * account, because constraints updated after the device has
      24                 :            :                  * been suspended are not guaranteed to be taken into account
      25                 :            :                  * anyway.  In order for them to take effect, the device has to
      26                 :            :                  * be resumed and suspended again.
      27                 :            :                  */
      28                 :          0 :                 constraint_ns = dev_gpd_data(dev)->td.effective_constraint_ns;
      29                 :            :         } else {
      30                 :            :                 /*
      31                 :            :                  * The child is not in a domain and there's no info on its
      32                 :            :                  * suspend/resume latencies, so assume them to be negligible and
      33                 :            :                  * take its current PM QoS constraint (that's the only thing
      34                 :            :                  * known at this point anyway).
      35                 :            :                  */
      36                 :          0 :                 constraint_ns = dev_pm_qos_read_value(dev, DEV_PM_QOS_RESUME_LATENCY);
      37                 :          0 :                 constraint_ns *= NSEC_PER_USEC;
      38                 :            :         }
      39                 :            : 
      40         [ #  # ]:          0 :         if (constraint_ns < *constraint_ns_p)
      41                 :          0 :                 *constraint_ns_p = constraint_ns;
      42                 :            : 
      43                 :          0 :         return 0;
      44                 :            : }
      45                 :            : 
      46                 :            : /**
      47                 :            :  * default_suspend_ok - Default PM domain governor routine to suspend devices.
      48                 :            :  * @dev: Device to check.
      49                 :            :  */
      50                 :          0 : static bool default_suspend_ok(struct device *dev)
      51                 :            : {
      52                 :            :         struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
      53                 :            :         unsigned long flags;
      54                 :            :         s64 constraint_ns;
      55                 :            : 
      56                 :            :         dev_dbg(dev, "%s()\n", __func__);
      57                 :            : 
      58                 :          0 :         spin_lock_irqsave(&dev->power.lock, flags);
      59                 :            : 
      60         [ #  # ]:          0 :         if (!td->constraint_changed) {
      61                 :          0 :                 bool ret = td->cached_suspend_ok;
      62                 :            : 
      63                 :            :                 spin_unlock_irqrestore(&dev->power.lock, flags);
      64                 :          0 :                 return ret;
      65                 :            :         }
      66                 :          0 :         td->constraint_changed = false;
      67                 :          0 :         td->cached_suspend_ok = false;
      68                 :          0 :         td->effective_constraint_ns = 0;
      69                 :          0 :         constraint_ns = __dev_pm_qos_resume_latency(dev);
      70                 :            : 
      71                 :            :         spin_unlock_irqrestore(&dev->power.lock, flags);
      72                 :            : 
      73         [ #  # ]:          0 :         if (constraint_ns == 0)
      74                 :            :                 return false;
      75                 :            : 
      76                 :          0 :         constraint_ns *= NSEC_PER_USEC;
      77                 :            :         /*
      78                 :            :          * We can walk the children without any additional locking, because
      79                 :            :          * they all have been suspended at this point and their
      80                 :            :          * effective_constraint_ns fields won't be modified in parallel with us.
      81                 :            :          */
      82         [ #  # ]:          0 :         if (!dev->power.ignore_children)
      83                 :          0 :                 device_for_each_child(dev, &constraint_ns,
      84                 :            :                                       dev_update_qos_constraint);
      85                 :            : 
      86         [ #  # ]:          0 :         if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS) {
      87                 :            :                 /* "No restriction", so the device is allowed to suspend. */
      88                 :          0 :                 td->effective_constraint_ns = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS;
      89                 :          0 :                 td->cached_suspend_ok = true;
      90         [ #  # ]:          0 :         } else if (constraint_ns == 0) {
      91                 :            :                 /*
      92                 :            :                  * This triggers if one of the children that don't belong to a
      93                 :            :                  * domain has a zero PM QoS constraint and it's better not to
      94                 :            :                  * suspend then.  effective_constraint_ns is zero already and
      95                 :            :                  * cached_suspend_ok is false, so bail out.
      96                 :            :                  */
      97                 :            :                 return false;
      98                 :            :         } else {
      99                 :          0 :                 constraint_ns -= td->suspend_latency_ns +
     100                 :          0 :                                 td->resume_latency_ns;
     101                 :            :                 /*
     102                 :            :                  * effective_constraint_ns is zero already and cached_suspend_ok
     103                 :            :                  * is false, so if the computed value is not positive, return
     104                 :            :                  * right away.
     105                 :            :                  */
     106         [ #  # ]:          0 :                 if (constraint_ns <= 0)
     107                 :            :                         return false;
     108                 :            : 
     109                 :          0 :                 td->effective_constraint_ns = constraint_ns;
     110                 :          0 :                 td->cached_suspend_ok = true;
     111                 :            :         }
     112                 :            : 
     113                 :            :         /*
     114                 :            :          * The children have been suspended already, so we don't need to take
     115                 :            :          * their suspend latencies into account here.
     116                 :            :          */
     117                 :          0 :         return td->cached_suspend_ok;
     118                 :            : }
     119                 :            : 
     120                 :          0 : static bool __default_power_down_ok(struct dev_pm_domain *pd,
     121                 :            :                                      unsigned int state)
     122                 :            : {
     123                 :            :         struct generic_pm_domain *genpd = pd_to_genpd(pd);
     124                 :            :         struct gpd_link *link;
     125                 :            :         struct pm_domain_data *pdd;
     126                 :            :         s64 min_off_time_ns;
     127                 :            :         s64 off_on_time_ns;
     128                 :            : 
     129                 :          0 :         off_on_time_ns = genpd->states[state].power_off_latency_ns +
     130                 :          0 :                 genpd->states[state].power_on_latency_ns;
     131                 :            : 
     132                 :            :         min_off_time_ns = -1;
     133                 :            :         /*
     134                 :            :          * Check if subdomains can be off for enough time.
     135                 :            :          *
     136                 :            :          * All subdomains have been powered off already at this point.
     137                 :            :          */
     138         [ #  # ]:          0 :         list_for_each_entry(link, &genpd->master_links, master_node) {
     139                 :          0 :                 struct generic_pm_domain *sd = link->slave;
     140                 :          0 :                 s64 sd_max_off_ns = sd->max_off_time_ns;
     141                 :            : 
     142         [ #  # ]:          0 :                 if (sd_max_off_ns < 0)
     143                 :          0 :                         continue;
     144                 :            : 
     145                 :            :                 /*
     146                 :            :                  * Check if the subdomain is allowed to be off long enough for
     147                 :            :                  * the current domain to turn off and on (that's how much time
     148                 :            :                  * it will have to wait worst case).
     149                 :            :                  */
     150         [ #  # ]:          0 :                 if (sd_max_off_ns <= off_on_time_ns)
     151                 :            :                         return false;
     152                 :            : 
     153         [ #  # ]:          0 :                 if (min_off_time_ns > sd_max_off_ns || min_off_time_ns < 0)
     154                 :            :                         min_off_time_ns = sd_max_off_ns;
     155                 :            :         }
     156                 :            : 
     157                 :            :         /*
     158                 :            :          * Check if the devices in the domain can be off enough time.
     159                 :            :          */
     160         [ #  # ]:          0 :         list_for_each_entry(pdd, &genpd->dev_list, list_node) {
     161                 :            :                 struct gpd_timing_data *td;
     162                 :            :                 s64 constraint_ns;
     163                 :            : 
     164                 :            :                 /*
     165                 :            :                  * Check if the device is allowed to be off long enough for the
     166                 :            :                  * domain to turn off and on (that's how much time it will
     167                 :            :                  * have to wait worst case).
     168                 :            :                  */
     169                 :            :                 td = &to_gpd_data(pdd)->td;
     170                 :          0 :                 constraint_ns = td->effective_constraint_ns;
     171                 :            :                 /*
     172                 :            :                  * Zero means "no suspend at all" and this runs only when all
     173                 :            :                  * devices in the domain are suspended, so it must be positive.
     174                 :            :                  */
     175         [ #  # ]:          0 :                 if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS)
     176                 :          0 :                         continue;
     177                 :            : 
     178         [ #  # ]:          0 :                 if (constraint_ns <= off_on_time_ns)
     179                 :            :                         return false;
     180                 :            : 
     181         [ #  # ]:          0 :                 if (min_off_time_ns > constraint_ns || min_off_time_ns < 0)
     182                 :            :                         min_off_time_ns = constraint_ns;
     183                 :            :         }
     184                 :            : 
     185                 :            :         /*
     186                 :            :          * If the computed minimum device off time is negative, there are no
     187                 :            :          * latency constraints, so the domain can spend arbitrary time in the
     188                 :            :          * "off" state.
     189                 :            :          */
     190         [ #  # ]:          0 :         if (min_off_time_ns < 0)
     191                 :            :                 return true;
     192                 :            : 
     193                 :            :         /*
     194                 :            :          * The difference between the computed minimum subdomain or device off
     195                 :            :          * time and the time needed to turn the domain on is the maximum
     196                 :            :          * theoretical time this domain can spend in the "off" state.
     197                 :            :          */
     198                 :          0 :         genpd->max_off_time_ns = min_off_time_ns -
     199                 :            :                 genpd->states[state].power_on_latency_ns;
     200                 :          0 :         return true;
     201                 :            : }
     202                 :            : 
     203                 :            : /**
     204                 :            :  * default_power_down_ok - Default generic PM domain power off governor routine.
     205                 :            :  * @pd: PM domain to check.
     206                 :            :  *
     207                 :            :  * This routine must be executed under the PM domain's lock.
     208                 :            :  */
     209                 :          0 : static bool default_power_down_ok(struct dev_pm_domain *pd)
     210                 :            : {
     211                 :            :         struct generic_pm_domain *genpd = pd_to_genpd(pd);
     212                 :            :         struct gpd_link *link;
     213                 :            : 
     214         [ #  # ]:          0 :         if (!genpd->max_off_time_changed) {
     215                 :          0 :                 genpd->state_idx = genpd->cached_power_down_state_idx;
     216                 :          0 :                 return genpd->cached_power_down_ok;
     217                 :            :         }
     218                 :            : 
     219                 :            :         /*
     220                 :            :          * We have to invalidate the cached results for the masters, so
     221                 :            :          * use the observation that default_power_down_ok() is not
     222                 :            :          * going to be called for any master until this instance
     223                 :            :          * returns.
     224                 :            :          */
     225         [ #  # ]:          0 :         list_for_each_entry(link, &genpd->slave_links, slave_node)
     226                 :          0 :                 link->master->max_off_time_changed = true;
     227                 :            : 
     228                 :          0 :         genpd->max_off_time_ns = -1;
     229                 :          0 :         genpd->max_off_time_changed = false;
     230                 :          0 :         genpd->cached_power_down_ok = true;
     231                 :          0 :         genpd->state_idx = genpd->state_count - 1;
     232                 :            : 
     233                 :            :         /* Find a state to power down to, starting from the deepest. */
     234         [ #  # ]:          0 :         while (!__default_power_down_ok(pd, genpd->state_idx)) {
     235         [ #  # ]:          0 :                 if (genpd->state_idx == 0) {
     236                 :          0 :                         genpd->cached_power_down_ok = false;
     237                 :          0 :                         break;
     238                 :            :                 }
     239                 :          0 :                 genpd->state_idx--;
     240                 :            :         }
     241                 :            : 
     242                 :          0 :         genpd->cached_power_down_state_idx = genpd->state_idx;
     243                 :          0 :         return genpd->cached_power_down_ok;
     244                 :            : }
     245                 :            : 
     246                 :          0 : static bool always_on_power_down_ok(struct dev_pm_domain *domain)
     247                 :            : {
     248                 :          0 :         return false;
     249                 :            : }
     250                 :            : 
     251                 :            : #ifdef CONFIG_CPU_IDLE
     252                 :            : static bool cpu_power_down_ok(struct dev_pm_domain *pd)
     253                 :            : {
     254                 :            :         struct generic_pm_domain *genpd = pd_to_genpd(pd);
     255                 :            :         struct cpuidle_device *dev;
     256                 :            :         ktime_t domain_wakeup, next_hrtimer;
     257                 :            :         s64 idle_duration_ns;
     258                 :            :         int cpu, i;
     259                 :            : 
     260                 :            :         /* Validate dev PM QoS constraints. */
     261                 :            :         if (!default_power_down_ok(pd))
     262                 :            :                 return false;
     263                 :            : 
     264                 :            :         if (!(genpd->flags & GENPD_FLAG_CPU_DOMAIN))
     265                 :            :                 return true;
     266                 :            : 
     267                 :            :         /*
     268                 :            :          * Find the next wakeup for any of the online CPUs within the PM domain
     269                 :            :          * and its subdomains. Note, we only need the genpd->cpus, as it already
     270                 :            :          * contains a mask of all CPUs from subdomains.
     271                 :            :          */
     272                 :            :         domain_wakeup = ktime_set(KTIME_SEC_MAX, 0);
     273                 :            :         for_each_cpu_and(cpu, genpd->cpus, cpu_online_mask) {
     274                 :            :                 dev = per_cpu(cpuidle_devices, cpu);
     275                 :            :                 if (dev) {
     276                 :            :                         next_hrtimer = READ_ONCE(dev->next_hrtimer);
     277                 :            :                         if (ktime_before(next_hrtimer, domain_wakeup))
     278                 :            :                                 domain_wakeup = next_hrtimer;
     279                 :            :                 }
     280                 :            :         }
     281                 :            : 
     282                 :            :         /* The minimum idle duration is from now - until the next wakeup. */
     283                 :            :         idle_duration_ns = ktime_to_ns(ktime_sub(domain_wakeup, ktime_get()));
     284                 :            :         if (idle_duration_ns <= 0)
     285                 :            :                 return false;
     286                 :            : 
     287                 :            :         /*
     288                 :            :          * Find the deepest idle state that has its residency value satisfied
     289                 :            :          * and by also taking into account the power off latency for the state.
     290                 :            :          * Start at the state picked by the dev PM QoS constraint validation.
     291                 :            :          */
     292                 :            :         i = genpd->state_idx;
     293                 :            :         do {
     294                 :            :                 if (idle_duration_ns >= (genpd->states[i].residency_ns +
     295                 :            :                     genpd->states[i].power_off_latency_ns)) {
     296                 :            :                         genpd->state_idx = i;
     297                 :            :                         return true;
     298                 :            :                 }
     299                 :            :         } while (--i >= 0);
     300                 :            : 
     301                 :            :         return false;
     302                 :            : }
     303                 :            : 
     304                 :            : struct dev_power_governor pm_domain_cpu_gov = {
     305                 :            :         .suspend_ok = default_suspend_ok,
     306                 :            :         .power_down_ok = cpu_power_down_ok,
     307                 :            : };
     308                 :            : #endif
     309                 :            : 
     310                 :            : struct dev_power_governor simple_qos_governor = {
     311                 :            :         .suspend_ok = default_suspend_ok,
     312                 :            :         .power_down_ok = default_power_down_ok,
     313                 :            : };
     314                 :            : 
     315                 :            : /**
     316                 :            :  * pm_genpd_gov_always_on - A governor implementing an always-on policy
     317                 :            :  */
     318                 :            : struct dev_power_governor pm_domain_always_on_gov = {
     319                 :            :         .power_down_ok = always_on_power_down_ok,
     320                 :            :         .suspend_ok = default_suspend_ok,
     321                 :            : };

Generated by: LCOV version 1.14