LCOV - code coverage report
Current view: top level - drivers/base/power - opp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 163 0.0 %
Date: 2014-02-18 Functions: 0 15 0.0 %
Branches: 0 100 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Generic OPP Interface
       3                 :            :  *
       4                 :            :  * Copyright (C) 2009-2010 Texas Instruments Incorporated.
       5                 :            :  *      Nishanth Menon
       6                 :            :  *      Romit Dasgupta
       7                 :            :  *      Kevin Hilman
       8                 :            :  *
       9                 :            :  * This program is free software; you can redistribute it and/or modify
      10                 :            :  * it under the terms of the GNU General Public License version 2 as
      11                 :            :  * published by the Free Software Foundation.
      12                 :            :  */
      13                 :            : 
      14                 :            : #include <linux/kernel.h>
      15                 :            : #include <linux/errno.h>
      16                 :            : #include <linux/err.h>
      17                 :            : #include <linux/init.h>
      18                 :            : #include <linux/slab.h>
      19                 :            : #include <linux/cpufreq.h>
      20                 :            : #include <linux/device.h>
      21                 :            : #include <linux/list.h>
      22                 :            : #include <linux/rculist.h>
      23                 :            : #include <linux/rcupdate.h>
      24                 :            : #include <linux/pm_opp.h>
      25                 :            : #include <linux/of.h>
      26                 :            : #include <linux/export.h>
      27                 :            : 
      28                 :            : /*
      29                 :            :  * Internal data structure organization with the OPP layer library is as
      30                 :            :  * follows:
      31                 :            :  * dev_opp_list (root)
      32                 :            :  *      |- device 1 (represents voltage domain 1)
      33                 :            :  *      |       |- opp 1 (availability, freq, voltage)
      34                 :            :  *      |       |- opp 2 ..
      35                 :            :  *      ...     ...
      36                 :            :  *      |       `- opp n ..
      37                 :            :  *      |- device 2 (represents the next voltage domain)
      38                 :            :  *      ...
      39                 :            :  *      `- device m (represents mth voltage domain)
      40                 :            :  * device 1, 2.. are represented by dev_opp structure while each opp
      41                 :            :  * is represented by the opp structure.
      42                 :            :  */
      43                 :            : 
      44                 :            : /**
      45                 :            :  * struct dev_pm_opp - Generic OPP description structure
      46                 :            :  * @node:       opp list node. The nodes are maintained throughout the lifetime
      47                 :            :  *              of boot. It is expected only an optimal set of OPPs are
      48                 :            :  *              added to the library by the SoC framework.
      49                 :            :  *              RCU usage: opp list is traversed with RCU locks. node
      50                 :            :  *              modification is possible realtime, hence the modifications
      51                 :            :  *              are protected by the dev_opp_list_lock for integrity.
      52                 :            :  *              IMPORTANT: the opp nodes should be maintained in increasing
      53                 :            :  *              order.
      54                 :            :  * @available:  true/false - marks if this OPP as available or not
      55                 :            :  * @rate:       Frequency in hertz
      56                 :            :  * @u_volt:     Nominal voltage in microvolts corresponding to this OPP
      57                 :            :  * @dev_opp:    points back to the device_opp struct this opp belongs to
      58                 :            :  * @head:       RCU callback head used for deferred freeing
      59                 :            :  *
      60                 :            :  * This structure stores the OPP information for a given device.
      61                 :            :  */
      62                 :            : struct dev_pm_opp {
      63                 :            :         struct list_head node;
      64                 :            : 
      65                 :            :         bool available;
      66                 :            :         unsigned long rate;
      67                 :            :         unsigned long u_volt;
      68                 :            : 
      69                 :            :         struct device_opp *dev_opp;
      70                 :            :         struct rcu_head head;
      71                 :            : };
      72                 :            : 
      73                 :            : /**
      74                 :            :  * struct device_opp - Device opp structure
      75                 :            :  * @node:       list node - contains the devices with OPPs that
      76                 :            :  *              have been registered. Nodes once added are not modified in this
      77                 :            :  *              list.
      78                 :            :  *              RCU usage: nodes are not modified in the list of device_opp,
      79                 :            :  *              however addition is possible and is secured by dev_opp_list_lock
      80                 :            :  * @dev:        device pointer
      81                 :            :  * @head:       notifier head to notify the OPP availability changes.
      82                 :            :  * @opp_list:   list of opps
      83                 :            :  *
      84                 :            :  * This is an internal data structure maintaining the link to opps attached to
      85                 :            :  * a device. This structure is not meant to be shared to users as it is
      86                 :            :  * meant for book keeping and private to OPP library
      87                 :            :  */
      88                 :            : struct device_opp {
      89                 :            :         struct list_head node;
      90                 :            : 
      91                 :            :         struct device *dev;
      92                 :            :         struct srcu_notifier_head head;
      93                 :            :         struct list_head opp_list;
      94                 :            : };
      95                 :            : 
      96                 :            : /*
      97                 :            :  * The root of the list of all devices. All device_opp structures branch off
      98                 :            :  * from here, with each device_opp containing the list of opp it supports in
      99                 :            :  * various states of availability.
     100                 :            :  */
     101                 :            : static LIST_HEAD(dev_opp_list);
     102                 :            : /* Lock to allow exclusive modification to the device and opp lists */
     103                 :            : static DEFINE_MUTEX(dev_opp_list_lock);
     104                 :            : 
     105                 :            : /**
     106                 :            :  * find_device_opp() - find device_opp struct using device pointer
     107                 :            :  * @dev:        device pointer used to lookup device OPPs
     108                 :            :  *
     109                 :            :  * Search list of device OPPs for one containing matching device. Does a RCU
     110                 :            :  * reader operation to grab the pointer needed.
     111                 :            :  *
     112                 :            :  * Returns pointer to 'struct device_opp' if found, otherwise -ENODEV or
     113                 :            :  * -EINVAL based on type of error.
     114                 :            :  *
     115                 :            :  * Locking: This function must be called under rcu_read_lock(). device_opp
     116                 :            :  * is a RCU protected pointer. This means that device_opp is valid as long
     117                 :            :  * as we are under RCU lock.
     118                 :            :  */
     119                 :          0 : static struct device_opp *find_device_opp(struct device *dev)
     120                 :            : {
     121                 :            :         struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
     122                 :            : 
     123         [ #  # ]:          0 :         if (unlikely(IS_ERR_OR_NULL(dev))) {
     124                 :          0 :                 pr_err("%s: Invalid parameters\n", __func__);
     125                 :          0 :                 return ERR_PTR(-EINVAL);
     126                 :            :         }
     127                 :            : 
     128         [ #  # ]:          0 :         list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
     129         [ #  # ]:          0 :                 if (tmp_dev_opp->dev == dev) {
     130                 :            :                         dev_opp = tmp_dev_opp;
     131                 :            :                         break;
     132                 :            :                 }
     133                 :            :         }
     134                 :            : 
     135                 :          0 :         return dev_opp;
     136                 :            : }
     137                 :            : 
     138                 :            : /**
     139                 :            :  * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an available opp
     140                 :            :  * @opp:        opp for which voltage has to be returned for
     141                 :            :  *
     142                 :            :  * Return voltage in micro volt corresponding to the opp, else
     143                 :            :  * return 0
     144                 :            :  *
     145                 :            :  * Locking: This function must be called under rcu_read_lock(). opp is a rcu
     146                 :            :  * protected pointer. This means that opp which could have been fetched by
     147                 :            :  * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
     148                 :            :  * under RCU lock. The pointer returned by the opp_find_freq family must be
     149                 :            :  * used in the same section as the usage of this function with the pointer
     150                 :            :  * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
     151                 :            :  * pointer.
     152                 :            :  */
     153                 :          0 : unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
     154                 :            : {
     155                 :            :         struct dev_pm_opp *tmp_opp;
     156                 :            :         unsigned long v = 0;
     157                 :            : 
     158                 :          0 :         tmp_opp = rcu_dereference(opp);
     159 [ #  # ][ #  # ]:          0 :         if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
     160                 :          0 :                 pr_err("%s: Invalid parameters\n", __func__);
     161                 :            :         else
     162                 :          0 :                 v = tmp_opp->u_volt;
     163                 :            : 
     164                 :          0 :         return v;
     165                 :            : }
     166                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_get_voltage);
     167                 :            : 
     168                 :            : /**
     169                 :            :  * dev_pm_opp_get_freq() - Gets the frequency corresponding to an available opp
     170                 :            :  * @opp:        opp for which frequency has to be returned for
     171                 :            :  *
     172                 :            :  * Return frequency in hertz corresponding to the opp, else
     173                 :            :  * return 0
     174                 :            :  *
     175                 :            :  * Locking: This function must be called under rcu_read_lock(). opp is a rcu
     176                 :            :  * protected pointer. This means that opp which could have been fetched by
     177                 :            :  * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
     178                 :            :  * under RCU lock. The pointer returned by the opp_find_freq family must be
     179                 :            :  * used in the same section as the usage of this function with the pointer
     180                 :            :  * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
     181                 :            :  * pointer.
     182                 :            :  */
     183                 :          0 : unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
     184                 :            : {
     185                 :            :         struct dev_pm_opp *tmp_opp;
     186                 :            :         unsigned long f = 0;
     187                 :            : 
     188                 :          0 :         tmp_opp = rcu_dereference(opp);
     189 [ #  # ][ #  # ]:          0 :         if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
     190                 :          0 :                 pr_err("%s: Invalid parameters\n", __func__);
     191                 :            :         else
     192                 :          0 :                 f = tmp_opp->rate;
     193                 :            : 
     194                 :          0 :         return f;
     195                 :            : }
     196                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
     197                 :            : 
     198                 :            : /**
     199                 :            :  * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list
     200                 :            :  * @dev:        device for which we do this operation
     201                 :            :  *
     202                 :            :  * This function returns the number of available opps if there are any,
     203                 :            :  * else returns 0 if none or the corresponding error value.
     204                 :            :  *
     205                 :            :  * Locking: This function must be called under rcu_read_lock(). This function
     206                 :            :  * internally references two RCU protected structures: device_opp and opp which
     207                 :            :  * are safe as long as we are under a common RCU locked section.
     208                 :            :  */
     209                 :          0 : int dev_pm_opp_get_opp_count(struct device *dev)
     210                 :            : {
     211                 :            :         struct device_opp *dev_opp;
     212                 :            :         struct dev_pm_opp *temp_opp;
     213                 :            :         int count = 0;
     214                 :            : 
     215                 :          0 :         dev_opp = find_device_opp(dev);
     216         [ #  # ]:          0 :         if (IS_ERR(dev_opp)) {
     217                 :            :                 int r = PTR_ERR(dev_opp);
     218                 :          0 :                 dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r);
     219                 :          0 :                 return r;
     220                 :            :         }
     221                 :            : 
     222         [ #  # ]:          0 :         list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
     223         [ #  # ]:          0 :                 if (temp_opp->available)
     224                 :          0 :                         count++;
     225                 :            :         }
     226                 :            : 
     227                 :            :         return count;
     228                 :            : }
     229                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count);
     230                 :            : 
     231                 :            : /**
     232                 :            :  * dev_pm_opp_find_freq_exact() - search for an exact frequency
     233                 :            :  * @dev:                device for which we do this operation
     234                 :            :  * @freq:               frequency to search for
     235                 :            :  * @available:          true/false - match for available opp
     236                 :            :  *
     237                 :            :  * Searches for exact match in the opp list and returns pointer to the matching
     238                 :            :  * opp if found, else returns ERR_PTR in case of error and should be handled
     239                 :            :  * using IS_ERR. Error return values can be:
     240                 :            :  * EINVAL:      for bad pointer
     241                 :            :  * ERANGE:      no match found for search
     242                 :            :  * ENODEV:      if device not found in list of registered devices
     243                 :            :  *
     244                 :            :  * Note: available is a modifier for the search. if available=true, then the
     245                 :            :  * match is for exact matching frequency and is available in the stored OPP
     246                 :            :  * table. if false, the match is for exact frequency which is not available.
     247                 :            :  *
     248                 :            :  * This provides a mechanism to enable an opp which is not available currently
     249                 :            :  * or the opposite as well.
     250                 :            :  *
     251                 :            :  * Locking: This function must be called under rcu_read_lock(). opp is a rcu
     252                 :            :  * protected pointer. The reason for the same is that the opp pointer which is
     253                 :            :  * returned will remain valid for use with opp_get_{voltage, freq} only while
     254                 :            :  * under the locked area. The pointer returned must be used prior to unlocking
     255                 :            :  * with rcu_read_unlock() to maintain the integrity of the pointer.
     256                 :            :  */
     257                 :          0 : struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
     258                 :            :                                               unsigned long freq,
     259                 :            :                                               bool available)
     260                 :            : {
     261                 :            :         struct device_opp *dev_opp;
     262                 :            :         struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
     263                 :            : 
     264                 :          0 :         dev_opp = find_device_opp(dev);
     265         [ #  # ]:          0 :         if (IS_ERR(dev_opp)) {
     266                 :            :                 int r = PTR_ERR(dev_opp);
     267                 :          0 :                 dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r);
     268                 :          0 :                 return ERR_PTR(r);
     269                 :            :         }
     270                 :            : 
     271         [ #  # ]:          0 :         list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
     272 [ #  # ][ #  # ]:          0 :                 if (temp_opp->available == available &&
     273                 :          0 :                                 temp_opp->rate == freq) {
     274                 :            :                         opp = temp_opp;
     275                 :            :                         break;
     276                 :            :                 }
     277                 :            :         }
     278                 :            : 
     279                 :          0 :         return opp;
     280                 :            : }
     281                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact);
     282                 :            : 
     283                 :            : /**
     284                 :            :  * dev_pm_opp_find_freq_ceil() - Search for an rounded ceil freq
     285                 :            :  * @dev:        device for which we do this operation
     286                 :            :  * @freq:       Start frequency
     287                 :            :  *
     288                 :            :  * Search for the matching ceil *available* OPP from a starting freq
     289                 :            :  * for a device.
     290                 :            :  *
     291                 :            :  * Returns matching *opp and refreshes *freq accordingly, else returns
     292                 :            :  * ERR_PTR in case of error and should be handled using IS_ERR. Error return
     293                 :            :  * values can be:
     294                 :            :  * EINVAL:      for bad pointer
     295                 :            :  * ERANGE:      no match found for search
     296                 :            :  * ENODEV:      if device not found in list of registered devices
     297                 :            :  *
     298                 :            :  * Locking: This function must be called under rcu_read_lock(). opp is a rcu
     299                 :            :  * protected pointer. The reason for the same is that the opp pointer which is
     300                 :            :  * returned will remain valid for use with opp_get_{voltage, freq} only while
     301                 :            :  * under the locked area. The pointer returned must be used prior to unlocking
     302                 :            :  * with rcu_read_unlock() to maintain the integrity of the pointer.
     303                 :            :  */
     304                 :          0 : struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
     305                 :            :                                              unsigned long *freq)
     306                 :            : {
     307                 :            :         struct device_opp *dev_opp;
     308                 :            :         struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
     309                 :            : 
     310         [ #  # ]:          0 :         if (!dev || !freq) {
     311                 :          0 :                 dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
     312                 :          0 :                 return ERR_PTR(-EINVAL);
     313                 :            :         }
     314                 :            : 
     315                 :          0 :         dev_opp = find_device_opp(dev);
     316         [ #  # ]:          0 :         if (IS_ERR(dev_opp))
     317                 :            :                 return ERR_CAST(dev_opp);
     318                 :            : 
     319         [ #  # ]:          0 :         list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
     320 [ #  # ][ #  # ]:          0 :                 if (temp_opp->available && temp_opp->rate >= *freq) {
     321                 :            :                         opp = temp_opp;
     322                 :          0 :                         *freq = opp->rate;
     323                 :          0 :                         break;
     324                 :            :                 }
     325                 :            :         }
     326                 :            : 
     327                 :          0 :         return opp;
     328                 :            : }
     329                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil);
     330                 :            : 
     331                 :            : /**
     332                 :            :  * dev_pm_opp_find_freq_floor() - Search for a rounded floor freq
     333                 :            :  * @dev:        device for which we do this operation
     334                 :            :  * @freq:       Start frequency
     335                 :            :  *
     336                 :            :  * Search for the matching floor *available* OPP from a starting freq
     337                 :            :  * for a device.
     338                 :            :  *
     339                 :            :  * Returns matching *opp and refreshes *freq accordingly, else returns
     340                 :            :  * ERR_PTR in case of error and should be handled using IS_ERR. Error return
     341                 :            :  * values can be:
     342                 :            :  * EINVAL:      for bad pointer
     343                 :            :  * ERANGE:      no match found for search
     344                 :            :  * ENODEV:      if device not found in list of registered devices
     345                 :            :  *
     346                 :            :  * Locking: This function must be called under rcu_read_lock(). opp is a rcu
     347                 :            :  * protected pointer. The reason for the same is that the opp pointer which is
     348                 :            :  * returned will remain valid for use with opp_get_{voltage, freq} only while
     349                 :            :  * under the locked area. The pointer returned must be used prior to unlocking
     350                 :            :  * with rcu_read_unlock() to maintain the integrity of the pointer.
     351                 :            :  */
     352                 :          0 : struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
     353                 :            :                                               unsigned long *freq)
     354                 :            : {
     355                 :            :         struct device_opp *dev_opp;
     356                 :            :         struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
     357                 :            : 
     358         [ #  # ]:          0 :         if (!dev || !freq) {
     359                 :          0 :                 dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
     360                 :          0 :                 return ERR_PTR(-EINVAL);
     361                 :            :         }
     362                 :            : 
     363                 :          0 :         dev_opp = find_device_opp(dev);
     364         [ #  # ]:          0 :         if (IS_ERR(dev_opp))
     365                 :            :                 return ERR_CAST(dev_opp);
     366                 :            : 
     367         [ #  # ]:          0 :         list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
     368         [ #  # ]:          0 :                 if (temp_opp->available) {
     369                 :            :                         /* go to the next node, before choosing prev */
     370         [ #  # ]:          0 :                         if (temp_opp->rate > *freq)
     371                 :            :                                 break;
     372                 :            :                         else
     373                 :            :                                 opp = temp_opp;
     374                 :            :                 }
     375                 :            :         }
     376         [ #  # ]:          0 :         if (!IS_ERR(opp))
     377                 :          0 :                 *freq = opp->rate;
     378                 :            : 
     379                 :          0 :         return opp;
     380                 :            : }
     381                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
     382                 :            : 
     383                 :            : /**
     384                 :            :  * dev_pm_opp_add()  - Add an OPP table from a table definitions
     385                 :            :  * @dev:        device for which we do this operation
     386                 :            :  * @freq:       Frequency in Hz for this OPP
     387                 :            :  * @u_volt:     Voltage in uVolts for this OPP
     388                 :            :  *
     389                 :            :  * This function adds an opp definition to the opp list and returns status.
     390                 :            :  * The opp is made available by default and it can be controlled using
     391                 :            :  * dev_pm_opp_enable/disable functions.
     392                 :            :  *
     393                 :            :  * Locking: The internal device_opp and opp structures are RCU protected.
     394                 :            :  * Hence this function internally uses RCU updater strategy with mutex locks
     395                 :            :  * to keep the integrity of the internal data structures. Callers should ensure
     396                 :            :  * that this function is *NOT* called under RCU protection or in contexts where
     397                 :            :  * mutex cannot be locked.
     398                 :            :  */
     399                 :          0 : int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
     400                 :            : {
     401                 :            :         struct device_opp *dev_opp = NULL;
     402                 :            :         struct dev_pm_opp *opp, *new_opp;
     403                 :            :         struct list_head *head;
     404                 :            : 
     405                 :            :         /* allocate new OPP node */
     406                 :            :         new_opp = kzalloc(sizeof(*new_opp), GFP_KERNEL);
     407         [ #  # ]:          0 :         if (!new_opp) {
     408                 :          0 :                 dev_warn(dev, "%s: Unable to create new OPP node\n", __func__);
     409                 :          0 :                 return -ENOMEM;
     410                 :            :         }
     411                 :            : 
     412                 :            :         /* Hold our list modification lock here */
     413                 :          0 :         mutex_lock(&dev_opp_list_lock);
     414                 :            : 
     415                 :            :         /* Check for existing list for 'dev' */
     416                 :          0 :         dev_opp = find_device_opp(dev);
     417         [ #  # ]:          0 :         if (IS_ERR(dev_opp)) {
     418                 :            :                 /*
     419                 :            :                  * Allocate a new device OPP table. In the infrequent case
     420                 :            :                  * where a new device is needed to be added, we pay this
     421                 :            :                  * penalty.
     422                 :            :                  */
     423                 :            :                 dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
     424         [ #  # ]:          0 :                 if (!dev_opp) {
     425                 :          0 :                         mutex_unlock(&dev_opp_list_lock);
     426                 :          0 :                         kfree(new_opp);
     427                 :          0 :                         dev_warn(dev,
     428                 :            :                                 "%s: Unable to create device OPP structure\n",
     429                 :            :                                 __func__);
     430                 :          0 :                         return -ENOMEM;
     431                 :            :                 }
     432                 :            : 
     433                 :          0 :                 dev_opp->dev = dev;
     434                 :          0 :                 srcu_init_notifier_head(&dev_opp->head);
     435                 :          0 :                 INIT_LIST_HEAD(&dev_opp->opp_list);
     436                 :            : 
     437                 :            :                 /* Secure the device list modification */
     438                 :          0 :                 list_add_rcu(&dev_opp->node, &dev_opp_list);
     439                 :            :         }
     440                 :            : 
     441                 :            :         /* populate the opp table */
     442                 :          0 :         new_opp->dev_opp = dev_opp;
     443                 :          0 :         new_opp->rate = freq;
     444                 :          0 :         new_opp->u_volt = u_volt;
     445                 :          0 :         new_opp->available = true;
     446                 :            : 
     447                 :            :         /* Insert new OPP in order of increasing frequency */
     448                 :          0 :         head = &dev_opp->opp_list;
     449         [ #  # ]:          0 :         list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
     450         [ #  # ]:          0 :                 if (new_opp->rate < opp->rate)
     451                 :            :                         break;
     452                 :            :                 else
     453                 :            :                         head = &opp->node;
     454                 :            :         }
     455                 :            : 
     456                 :          0 :         list_add_rcu(&new_opp->node, head);
     457                 :          0 :         mutex_unlock(&dev_opp_list_lock);
     458                 :            : 
     459                 :            :         /*
     460                 :            :          * Notify the changes in the availability of the operable
     461                 :            :          * frequency/voltage list.
     462                 :            :          */
     463                 :          0 :         srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp);
     464                 :          0 :         return 0;
     465                 :            : }
     466                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_add);
     467                 :            : 
     468                 :            : /**
     469                 :            :  * opp_set_availability() - helper to set the availability of an opp
     470                 :            :  * @dev:                device for which we do this operation
     471                 :            :  * @freq:               OPP frequency to modify availability
     472                 :            :  * @availability_req:   availability status requested for this opp
     473                 :            :  *
     474                 :            :  * Set the availability of an OPP with an RCU operation, opp_{enable,disable}
     475                 :            :  * share a common logic which is isolated here.
     476                 :            :  *
     477                 :            :  * Returns -EINVAL for bad pointers, -ENOMEM if no memory available for the
     478                 :            :  * copy operation, returns 0 if no modifcation was done OR modification was
     479                 :            :  * successful.
     480                 :            :  *
     481                 :            :  * Locking: The internal device_opp and opp structures are RCU protected.
     482                 :            :  * Hence this function internally uses RCU updater strategy with mutex locks to
     483                 :            :  * keep the integrity of the internal data structures. Callers should ensure
     484                 :            :  * that this function is *NOT* called under RCU protection or in contexts where
     485                 :            :  * mutex locking or synchronize_rcu() blocking calls cannot be used.
     486                 :            :  */
     487                 :          0 : static int opp_set_availability(struct device *dev, unsigned long freq,
     488                 :            :                 bool availability_req)
     489                 :            : {
     490                 :            :         struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
     491                 :            :         struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
     492                 :            :         int r = 0;
     493                 :            : 
     494                 :            :         /* keep the node allocated */
     495                 :            :         new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL);
     496         [ #  # ]:          0 :         if (!new_opp) {
     497                 :          0 :                 dev_warn(dev, "%s: Unable to create OPP\n", __func__);
     498                 :          0 :                 return -ENOMEM;
     499                 :            :         }
     500                 :            : 
     501                 :          0 :         mutex_lock(&dev_opp_list_lock);
     502                 :            : 
     503                 :            :         /* Find the device_opp */
     504         [ #  # ]:          0 :         list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) {
     505         [ #  # ]:          0 :                 if (dev == tmp_dev_opp->dev) {
     506                 :            :                         dev_opp = tmp_dev_opp;
     507                 :            :                         break;
     508                 :            :                 }
     509                 :            :         }
     510         [ #  # ]:          0 :         if (IS_ERR(dev_opp)) {
     511                 :            :                 r = PTR_ERR(dev_opp);
     512                 :          0 :                 dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
     513                 :          0 :                 goto unlock;
     514                 :            :         }
     515                 :            : 
     516                 :            :         /* Do we have the frequency? */
     517         [ #  # ]:          0 :         list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) {
     518         [ #  # ]:          0 :                 if (tmp_opp->rate == freq) {
     519                 :            :                         opp = tmp_opp;
     520                 :            :                         break;
     521                 :            :                 }
     522                 :            :         }
     523         [ #  # ]:          0 :         if (IS_ERR(opp)) {
     524                 :            :                 r = PTR_ERR(opp);
     525                 :          0 :                 goto unlock;
     526                 :            :         }
     527                 :            : 
     528                 :            :         /* Is update really needed? */
     529         [ #  # ]:          0 :         if (opp->available == availability_req)
     530                 :            :                 goto unlock;
     531                 :            :         /* copy the old data over */
     532                 :          0 :         *new_opp = *opp;
     533                 :            : 
     534                 :            :         /* plug in new node */
     535                 :          0 :         new_opp->available = availability_req;
     536                 :            : 
     537                 :          0 :         list_replace_rcu(&opp->node, &new_opp->node);
     538                 :          0 :         mutex_unlock(&dev_opp_list_lock);
     539                 :          0 :         kfree_rcu(opp, head);
     540                 :            : 
     541                 :            :         /* Notify the change of the OPP availability */
     542         [ #  # ]:          0 :         if (availability_req)
     543                 :          0 :                 srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ENABLE,
     544                 :            :                                          new_opp);
     545                 :            :         else
     546                 :          0 :                 srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE,
     547                 :            :                                          new_opp);
     548                 :            : 
     549                 :            :         return 0;
     550                 :            : 
     551                 :            : unlock:
     552                 :          0 :         mutex_unlock(&dev_opp_list_lock);
     553                 :          0 :         kfree(new_opp);
     554                 :          0 :         return r;
     555                 :            : }
     556                 :            : 
     557                 :            : /**
     558                 :            :  * dev_pm_opp_enable() - Enable a specific OPP
     559                 :            :  * @dev:        device for which we do this operation
     560                 :            :  * @freq:       OPP frequency to enable
     561                 :            :  *
     562                 :            :  * Enables a provided opp. If the operation is valid, this returns 0, else the
     563                 :            :  * corresponding error value. It is meant to be used for users an OPP available
     564                 :            :  * after being temporarily made unavailable with dev_pm_opp_disable.
     565                 :            :  *
     566                 :            :  * Locking: The internal device_opp and opp structures are RCU protected.
     567                 :            :  * Hence this function indirectly uses RCU and mutex locks to keep the
     568                 :            :  * integrity of the internal data structures. Callers should ensure that
     569                 :            :  * this function is *NOT* called under RCU protection or in contexts where
     570                 :            :  * mutex locking or synchronize_rcu() blocking calls cannot be used.
     571                 :            :  */
     572                 :          0 : int dev_pm_opp_enable(struct device *dev, unsigned long freq)
     573                 :            : {
     574                 :          0 :         return opp_set_availability(dev, freq, true);
     575                 :            : }
     576                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_enable);
     577                 :            : 
     578                 :            : /**
     579                 :            :  * dev_pm_opp_disable() - Disable a specific OPP
     580                 :            :  * @dev:        device for which we do this operation
     581                 :            :  * @freq:       OPP frequency to disable
     582                 :            :  *
     583                 :            :  * Disables a provided opp. If the operation is valid, this returns
     584                 :            :  * 0, else the corresponding error value. It is meant to be a temporary
     585                 :            :  * control by users to make this OPP not available until the circumstances are
     586                 :            :  * right to make it available again (with a call to dev_pm_opp_enable).
     587                 :            :  *
     588                 :            :  * Locking: The internal device_opp and opp structures are RCU protected.
     589                 :            :  * Hence this function indirectly uses RCU and mutex locks to keep the
     590                 :            :  * integrity of the internal data structures. Callers should ensure that
     591                 :            :  * this function is *NOT* called under RCU protection or in contexts where
     592                 :            :  * mutex locking or synchronize_rcu() blocking calls cannot be used.
     593                 :            :  */
     594                 :          0 : int dev_pm_opp_disable(struct device *dev, unsigned long freq)
     595                 :            : {
     596                 :          0 :         return opp_set_availability(dev, freq, false);
     597                 :            : }
     598                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_disable);
     599                 :            : 
     600                 :            : #ifdef CONFIG_CPU_FREQ
     601                 :            : /**
     602                 :            :  * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device
     603                 :            :  * @dev:        device for which we do this operation
     604                 :            :  * @table:      Cpufreq table returned back to caller
     605                 :            :  *
     606                 :            :  * Generate a cpufreq table for a provided device- this assumes that the
     607                 :            :  * opp list is already initialized and ready for usage.
     608                 :            :  *
     609                 :            :  * This function allocates required memory for the cpufreq table. It is
     610                 :            :  * expected that the caller does the required maintenance such as freeing
     611                 :            :  * the table as required.
     612                 :            :  *
     613                 :            :  * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
     614                 :            :  * if no memory available for the operation (table is not populated), returns 0
     615                 :            :  * if successful and table is populated.
     616                 :            :  *
     617                 :            :  * WARNING: It is  important for the callers to ensure refreshing their copy of
     618                 :            :  * the table if any of the mentioned functions have been invoked in the interim.
     619                 :            :  *
     620                 :            :  * Locking: The internal device_opp and opp structures are RCU protected.
     621                 :            :  * To simplify the logic, we pretend we are updater and hold relevant mutex here
     622                 :            :  * Callers should ensure that this function is *NOT* called under RCU protection
     623                 :            :  * or in contexts where mutex locking cannot be used.
     624                 :            :  */
     625                 :          0 : int dev_pm_opp_init_cpufreq_table(struct device *dev,
     626                 :            :                             struct cpufreq_frequency_table **table)
     627                 :            : {
     628                 :            :         struct device_opp *dev_opp;
     629                 :            :         struct dev_pm_opp *opp;
     630                 :            :         struct cpufreq_frequency_table *freq_table;
     631                 :            :         int i = 0;
     632                 :            : 
     633                 :            :         /* Pretend as if I am an updater */
     634                 :          0 :         mutex_lock(&dev_opp_list_lock);
     635                 :            : 
     636                 :          0 :         dev_opp = find_device_opp(dev);
     637         [ #  # ]:          0 :         if (IS_ERR(dev_opp)) {
     638                 :            :                 int r = PTR_ERR(dev_opp);
     639                 :          0 :                 mutex_unlock(&dev_opp_list_lock);
     640                 :          0 :                 dev_err(dev, "%s: Device OPP not found (%d)\n", __func__, r);
     641                 :          0 :                 return r;
     642                 :            :         }
     643                 :            : 
     644                 :          0 :         freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
     645                 :          0 :                              (dev_pm_opp_get_opp_count(dev) + 1), GFP_KERNEL);
     646         [ #  # ]:          0 :         if (!freq_table) {
     647                 :          0 :                 mutex_unlock(&dev_opp_list_lock);
     648                 :          0 :                 dev_warn(dev, "%s: Unable to allocate frequency table\n",
     649                 :            :                         __func__);
     650                 :          0 :                 return -ENOMEM;
     651                 :            :         }
     652                 :            : 
     653         [ #  # ]:          0 :         list_for_each_entry(opp, &dev_opp->opp_list, node) {
     654         [ #  # ]:          0 :                 if (opp->available) {
     655                 :          0 :                         freq_table[i].driver_data = i;
     656                 :          0 :                         freq_table[i].frequency = opp->rate / 1000;
     657                 :          0 :                         i++;
     658                 :            :                 }
     659                 :            :         }
     660                 :          0 :         mutex_unlock(&dev_opp_list_lock);
     661                 :            : 
     662                 :          0 :         freq_table[i].driver_data = i;
     663                 :          0 :         freq_table[i].frequency = CPUFREQ_TABLE_END;
     664                 :            : 
     665                 :          0 :         *table = &freq_table[0];
     666                 :            : 
     667                 :          0 :         return 0;
     668                 :            : }
     669                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table);
     670                 :            : 
     671                 :            : /**
     672                 :            :  * dev_pm_opp_free_cpufreq_table() - free the cpufreq table
     673                 :            :  * @dev:        device for which we do this operation
     674                 :            :  * @table:      table to free
     675                 :            :  *
     676                 :            :  * Free up the table allocated by dev_pm_opp_init_cpufreq_table
     677                 :            :  */
     678                 :          0 : void dev_pm_opp_free_cpufreq_table(struct device *dev,
     679                 :            :                                 struct cpufreq_frequency_table **table)
     680                 :            : {
     681         [ #  # ]:          0 :         if (!table)
     682                 :          0 :                 return;
     683                 :            : 
     684                 :          0 :         kfree(*table);
     685                 :          0 :         *table = NULL;
     686                 :            : }
     687                 :            : EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
     688                 :            : #endif          /* CONFIG_CPU_FREQ */
     689                 :            : 
     690                 :            : /**
     691                 :            :  * dev_pm_opp_get_notifier() - find notifier_head of the device with opp
     692                 :            :  * @dev:        device pointer used to lookup device OPPs.
     693                 :            :  */
     694                 :          0 : struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev)
     695                 :            : {
     696                 :          0 :         struct device_opp *dev_opp = find_device_opp(dev);
     697                 :            : 
     698         [ #  # ]:          0 :         if (IS_ERR(dev_opp))
     699                 :            :                 return ERR_CAST(dev_opp); /* matching type */
     700                 :            : 
     701                 :          0 :         return &dev_opp->head;
     702                 :            : }
     703                 :            : 
     704                 :            : #ifdef CONFIG_OF
     705                 :            : /**
     706                 :            :  * of_init_opp_table() - Initialize opp table from device tree
     707                 :            :  * @dev:        device pointer used to lookup device OPPs.
     708                 :            :  *
     709                 :            :  * Register the initial OPP table with the OPP library for given device.
     710                 :            :  */
     711                 :          0 : int of_init_opp_table(struct device *dev)
     712                 :            : {
     713                 :            :         const struct property *prop;
     714                 :            :         const __be32 *val;
     715                 :            :         int nr;
     716                 :            : 
     717                 :          0 :         prop = of_find_property(dev->of_node, "operating-points", NULL);
     718         [ #  # ]:          0 :         if (!prop)
     719                 :            :                 return -ENODEV;
     720         [ #  # ]:          0 :         if (!prop->value)
     721                 :            :                 return -ENODATA;
     722                 :            : 
     723                 :            :         /*
     724                 :            :          * Each OPP is a set of tuples consisting of frequency and
     725                 :            :          * voltage like <freq-kHz vol-uV>.
     726                 :            :          */
     727                 :          0 :         nr = prop->length / sizeof(u32);
     728         [ #  # ]:          0 :         if (nr % 2) {
     729                 :          0 :                 dev_err(dev, "%s: Invalid OPP list\n", __func__);
     730                 :          0 :                 return -EINVAL;
     731                 :            :         }
     732                 :            : 
     733                 :            :         val = prop->value;
     734         [ #  # ]:          0 :         while (nr) {
     735                 :          0 :                 unsigned long freq = be32_to_cpup(val++) * 1000;
     736                 :          0 :                 unsigned long volt = be32_to_cpup(val++);
     737                 :            : 
     738         [ #  # ]:          0 :                 if (dev_pm_opp_add(dev, freq, volt)) {
     739                 :          0 :                         dev_warn(dev, "%s: Failed to add OPP %ld\n",
     740                 :            :                                  __func__, freq);
     741                 :          0 :                         continue;
     742                 :            :                 }
     743                 :          0 :                 nr -= 2;
     744                 :            :         }
     745                 :            : 
     746                 :            :         return 0;
     747                 :            : }
     748                 :            : EXPORT_SYMBOL_GPL(of_init_opp_table);
     749                 :            : #endif

Generated by: LCOV version 1.9