LCOV - code coverage report
Current view: top level - drivers/of - device.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_qemu_modules_combined.info Lines: 80 120 66.7 %
Date: 2020-09-30 20:25:01 Functions: 7 13 53.8 %
Branches: 55 218 25.2 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : #include <linux/string.h>
       3                 :            : #include <linux/kernel.h>
       4                 :            : #include <linux/of.h>
       5                 :            : #include <linux/of_device.h>
       6                 :            : #include <linux/of_address.h>
       7                 :            : #include <linux/of_iommu.h>
       8                 :            : #include <linux/dma-mapping.h>
       9                 :            : #include <linux/init.h>
      10                 :            : #include <linux/module.h>
      11                 :            : #include <linux/mod_devicetable.h>
      12                 :            : #include <linux/slab.h>
      13                 :            : #include <linux/platform_device.h>
      14                 :            : 
      15                 :            : #include <asm/errno.h>
      16                 :            : #include "of_private.h"
      17                 :            : 
      18                 :            : /**
      19                 :            :  * of_match_device - Tell if a struct device matches an of_device_id list
      20                 :            :  * @matches: array of of device match structures to search in
      21                 :            :  * @dev: the of device structure to match against
      22                 :            :  *
      23                 :            :  * Used by a driver to check whether an platform_device present in the
      24                 :            :  * system is in its list of supported devices.
      25                 :            :  */
      26                 :     665792 : const struct of_device_id *of_match_device(const struct of_device_id *matches,
      27                 :            :                                            const struct device *dev)
      28                 :            : {
      29   [ +  -  +  -  :     667408 :         if ((!matches) || (!dev->of_node))
             +  +  +  + ]
      30                 :            :                 return NULL;
      31                 :     405212 :         return of_match_node(matches, dev->of_node);
      32                 :            : }
      33                 :            : EXPORT_SYMBOL(of_match_device);
      34                 :            : 
      35                 :          0 : struct platform_device *of_dev_get(struct platform_device *dev)
      36                 :            : {
      37                 :            :         struct device *tmp;
      38                 :            : 
      39         [ #  # ]:          0 :         if (!dev)
      40                 :            :                 return NULL;
      41                 :          0 :         tmp = get_device(&dev->dev);
      42         [ #  # ]:          0 :         if (tmp)
      43                 :          0 :                 return to_platform_device(tmp);
      44                 :            :         else
      45                 :            :                 return NULL;
      46                 :            : }
      47                 :            : EXPORT_SYMBOL(of_dev_get);
      48                 :            : 
      49                 :          0 : void of_dev_put(struct platform_device *dev)
      50                 :            : {
      51         [ #  # ]:          0 :         if (dev)
      52                 :          0 :                 put_device(&dev->dev);
      53                 :          0 : }
      54                 :            : EXPORT_SYMBOL(of_dev_put);
      55                 :            : 
      56                 :       9696 : int of_device_add(struct platform_device *ofdev)
      57                 :            : {
      58         [ -  + ]:       9696 :         BUG_ON(ofdev->dev.of_node == NULL);
      59                 :            : 
      60                 :            :         /* name and id have to be set so that the platform bus doesn't get
      61                 :            :          * confused on matching */
      62                 :       9696 :         ofdev->name = dev_name(&ofdev->dev);
      63                 :       9696 :         ofdev->id = PLATFORM_DEVID_NONE;
      64                 :            : 
      65                 :            :         /*
      66                 :            :          * If this device has not binding numa node in devicetree, that is
      67                 :            :          * of_node_to_nid returns NUMA_NO_NODE. device_add will assume that this
      68                 :            :          * device is on the same node as the parent.
      69                 :            :          */
      70                 :            :         set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node));
      71                 :            : 
      72                 :       9696 :         return device_add(&ofdev->dev);
      73                 :            : }
      74                 :            : 
      75                 :            : /**
      76                 :            :  * of_dma_configure - Setup DMA configuration
      77                 :            :  * @dev:        Device to apply DMA configuration
      78                 :            :  * @np:         Pointer to OF node having DMA configuration
      79                 :            :  * @force_dma:  Whether device is to be set up by of_dma_configure() even if
      80                 :            :  *              DMA capability is not explicitly described by firmware.
      81                 :            :  *
      82                 :            :  * Try to get devices's DMA configuration from DT and update it
      83                 :            :  * accordingly.
      84                 :            :  *
      85                 :            :  * If platform code needs to use its own special DMA configuration, it
      86                 :            :  * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
      87                 :            :  * to fix up DMA configuration.
      88                 :            :  */
      89                 :      10908 : int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma)
      90                 :            : {
      91                 :      10908 :         u64 dma_addr, paddr, size = 0;
      92                 :            :         int ret;
      93                 :            :         bool coherent;
      94                 :            :         unsigned long offset;
      95                 :            :         const struct iommu_ops *iommu;
      96                 :            :         u64 mask, end;
      97                 :            : 
      98                 :      10908 :         ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
      99         [ +  + ]:      10908 :         if (ret < 0) {
     100                 :            :                 /*
     101                 :            :                  * For legacy reasons, we have to assume some devices need
     102                 :            :                  * DMA configuration regardless of whether "dma-ranges" is
     103                 :            :                  * correctly specified or not.
     104                 :            :                  */
     105         [ -  + ]:       1616 :                 if (!force_dma)
     106         [ #  # ]:          0 :                         return ret == -ENODEV ? 0 : ret;
     107                 :            : 
     108                 :       1616 :                 dma_addr = offset = 0;
     109                 :            :         } else {
     110                 :       9292 :                 offset = PFN_DOWN(paddr - dma_addr);
     111                 :            : 
     112                 :            :                 /*
     113                 :            :                  * Add a work around to treat the size as mask + 1 in case
     114                 :            :                  * it is defined in DT as a mask.
     115                 :            :                  */
     116         [ -  + ]:       9292 :                 if (size & 1) {
     117                 :          0 :                         dev_warn(dev, "Invalid size 0x%llx for dma-range\n",
     118                 :            :                                  size);
     119                 :          0 :                         size = size + 1;
     120                 :            :                 }
     121                 :            : 
     122         [ -  + ]:       9292 :                 if (!size) {
     123                 :          0 :                         dev_err(dev, "Adjusted size 0x%llx invalid\n", size);
     124                 :          0 :                         return -EINVAL;
     125                 :            :                 }
     126                 :            :                 dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
     127                 :            :         }
     128                 :            : 
     129                 :            :         /*
     130                 :            :          * If @dev is expected to be DMA-capable then the bus code that created
     131                 :            :          * it should have initialised its dma_mask pointer by this point. For
     132                 :            :          * now, we'll continue the legacy behaviour of coercing it to the
     133                 :            :          * coherent mask if not, but we'll no longer do so quietly.
     134                 :            :          */
     135         [ -  + ]:      10908 :         if (!dev->dma_mask) {
     136                 :          0 :                 dev_warn(dev, "DMA mask not set\n");
     137                 :          0 :                 dev->dma_mask = &dev->coherent_dma_mask;
     138                 :            :         }
     139                 :            : 
     140   [ +  +  +  - ]:      10908 :         if (!size && dev->coherent_dma_mask)
     141                 :       1616 :                 size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
     142         [ -  + ]:       9292 :         else if (!size)
     143                 :          0 :                 size = 1ULL << 32;
     144                 :            : 
     145                 :      10908 :         dev->dma_pfn_offset = offset;
     146                 :            : 
     147                 :            :         /*
     148                 :            :          * Limit coherent and dma mask based on size and default mask
     149                 :            :          * set by the driver.
     150                 :            :          */
     151                 :      10908 :         end = dma_addr + size - 1;
     152   [ -  +  #  #  :      32724 :         mask = DMA_BIT_MASK(ilog2(end) + 1);
          #  #  +  -  -  
          +  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     153                 :      10908 :         dev->coherent_dma_mask &= mask;
     154                 :      10908 :         *dev->dma_mask &= mask;
     155                 :            :         /* ...but only set bus limit if we found valid dma-ranges earlier */
     156         [ +  + ]:      10908 :         if (!ret)
     157                 :       9292 :                 dev->bus_dma_limit = end;
     158                 :            : 
     159                 :      10908 :         coherent = of_dma_is_coherent(np);
     160                 :            :         dev_dbg(dev, "device is%sdma coherent\n",
     161                 :            :                 coherent ? " " : " not ");
     162                 :            : 
     163                 :            :         iommu = of_iommu_configure(dev, np);
     164                 :            :         if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
     165                 :            :                 return -EPROBE_DEFER;
     166                 :            : 
     167                 :            :         dev_dbg(dev, "device is%sbehind an iommu\n",
     168                 :            :                 iommu ? " " : " not ");
     169                 :            : 
     170                 :      10908 :         arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
     171                 :            : 
     172                 :      10908 :         return 0;
     173                 :            : }
     174                 :            : EXPORT_SYMBOL_GPL(of_dma_configure);
     175                 :            : 
     176                 :          0 : int of_device_register(struct platform_device *pdev)
     177                 :            : {
     178                 :          0 :         device_initialize(&pdev->dev);
     179                 :          0 :         return of_device_add(pdev);
     180                 :            : }
     181                 :            : EXPORT_SYMBOL(of_device_register);
     182                 :            : 
     183                 :          0 : void of_device_unregister(struct platform_device *ofdev)
     184                 :            : {
     185                 :          0 :         device_unregister(&ofdev->dev);
     186                 :          0 : }
     187                 :            : EXPORT_SYMBOL(of_device_unregister);
     188                 :            : 
     189                 :       1616 : const void *of_device_get_match_data(const struct device *dev)
     190                 :            : {
     191                 :            :         const struct of_device_id *match;
     192                 :            : 
     193                 :       1616 :         match = of_match_device(dev->driver->of_match_table, dev);
     194         [ +  - ]:       1616 :         if (!match)
     195                 :            :                 return NULL;
     196                 :            : 
     197                 :       1616 :         return match->data;
     198                 :            : }
     199                 :            : EXPORT_SYMBOL(of_device_get_match_data);
     200                 :            : 
     201                 :      79636 : static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
     202                 :            : {
     203                 :            :         const char *compat;
     204                 :            :         char *c;
     205                 :            :         struct property *p;
     206                 :            :         ssize_t csize;
     207                 :            :         ssize_t tsize;
     208                 :            : 
     209   [ +  -  +  + ]:      79636 :         if ((!dev) || (!dev->of_node))
     210                 :            :                 return -ENODEV;
     211                 :            : 
     212                 :            :         /* Name & Type */
     213                 :            :         /* %p eats all alphanum characters, so %c must be used here */
     214                 :     159264 :         csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node, 'T',
     215                 :            :                          of_node_get_device_type(dev->of_node));
     216                 :            :         tsize = csize;
     217                 :      79636 :         len -= csize;
     218         [ +  + ]:      79636 :         if (str)
     219                 :      79634 :                 str += csize;
     220                 :            : 
     221         [ +  + ]:     168568 :         of_property_for_each_string(dev->of_node, "compatible", p, compat) {
     222                 :      88932 :                 csize = strlen(compat) + 1;
     223                 :      88932 :                 tsize += csize;
     224         [ +  + ]:      88932 :                 if (csize > len)
     225                 :          6 :                         continue;
     226                 :            : 
     227                 :      88928 :                 csize = snprintf(str, len, "C%s", compat);
     228         [ +  + ]:     266790 :                 for (c = str; c; ) {
     229                 :      88934 :                         c = strchr(c, ' ');
     230         [ +  + ]:      88934 :                         if (c)
     231                 :          4 :                                 *c++ = '_';
     232                 :            :                 }
     233                 :      88928 :                 len -= csize;
     234                 :      88928 :                 str += csize;
     235                 :            :         }
     236                 :            : 
     237                 :      79624 :         return tsize;
     238                 :            : }
     239                 :            : 
     240                 :          0 : int of_device_request_module(struct device *dev)
     241                 :            : {
     242                 :            :         char *str;
     243                 :            :         ssize_t size;
     244                 :            :         int ret;
     245                 :            : 
     246                 :          0 :         size = of_device_get_modalias(dev, NULL, 0);
     247         [ #  # ]:          0 :         if (size < 0)
     248                 :            :                 return size;
     249                 :            : 
     250                 :          0 :         str = kmalloc(size + 1, GFP_KERNEL);
     251         [ #  # ]:          0 :         if (!str)
     252                 :            :                 return -ENOMEM;
     253                 :            : 
     254                 :          0 :         of_device_get_modalias(dev, str, size);
     255                 :          0 :         str[size] = '\0';
     256                 :          0 :         ret = request_module(str);
     257                 :          0 :         kfree(str);
     258                 :            : 
     259                 :          0 :         return ret;
     260                 :            : }
     261                 :            : EXPORT_SYMBOL_GPL(of_device_request_module);
     262                 :            : 
     263                 :            : /**
     264                 :            :  * of_device_modalias - Fill buffer with newline terminated modalias string
     265                 :            :  */
     266                 :          0 : ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
     267                 :            : {
     268                 :          0 :         ssize_t sl = of_device_get_modalias(dev, str, len - 2);
     269         [ #  # ]:          0 :         if (sl < 0)
     270                 :            :                 return sl;
     271         [ #  # ]:          0 :         if (sl > len - 2)
     272                 :            :                 return -ENOMEM;
     273                 :            : 
     274                 :          0 :         str[sl++] = '\n';
     275                 :          0 :         str[sl] = 0;
     276                 :          0 :         return sl;
     277                 :            : }
     278                 :            : EXPORT_SYMBOL_GPL(of_device_modalias);
     279                 :            : 
     280                 :            : /**
     281                 :            :  * of_device_uevent - Display OF related uevent information
     282                 :            :  */
     283                 :     700130 : void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
     284                 :            : {
     285                 :            :         const char *compat, *type;
     286                 :            :         struct alias_prop *app;
     287                 :            :         struct property *p;
     288                 :            :         int seen = 0;
     289                 :            : 
     290   [ +  +  +  + ]:     700130 :         if ((!dev) || (!dev->of_node))
     291                 :     700142 :                 return;
     292                 :            : 
     293                 :     139768 :         add_uevent_var(env, "OF_NAME=%pOFn", dev->of_node);
     294                 :     139776 :         add_uevent_var(env, "OF_FULLNAME=%pOF", dev->of_node);
     295                 :     139754 :         type = of_node_get_device_type(dev->of_node);
     296         [ +  + ]:     139780 :         if (type)
     297                 :       6876 :                 add_uevent_var(env, "OF_TYPE=%s", type);
     298                 :            : 
     299                 :            :         /* Since the compatible field can contain pretty much anything
     300                 :            :          * it's not really legal to split it out with commas. We split it
     301                 :            :          * up using a number of environment variables instead. */
     302         [ +  + ]:     292892 :         of_property_for_each_string(dev->of_node, "compatible", p, compat) {
     303                 :     153116 :                 add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
     304                 :     153114 :                 seen++;
     305                 :            :         }
     306                 :     139772 :         add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
     307                 :            : 
     308                 :            :         seen = 0;
     309                 :     139774 :         mutex_lock(&of_mutex);
     310         [ +  + ]:    2096700 :         list_for_each_entry(app, &aliases_lookup, link) {
     311         [ +  + ]:    1956920 :                 if (dev->of_node == app->np) {
     312                 :      25870 :                         add_uevent_var(env, "OF_ALIAS_%d=%s", seen,
     313                 :            :                                        app->alias);
     314                 :      25870 :                         seen++;
     315                 :            :                 }
     316                 :            :         }
     317                 :     139780 :         mutex_unlock(&of_mutex);
     318                 :            : }
     319                 :            : 
     320                 :      96620 : int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
     321                 :            : {
     322                 :            :         int sl;
     323                 :            : 
     324   [ +  -  +  + ]:      96620 :         if ((!dev) || (!dev->of_node))
     325                 :            :                 return -ENODEV;
     326                 :            : 
     327                 :            :         /* Devicetree modalias is tricky, we add it in 2 steps */
     328         [ +  + ]:      79636 :         if (add_uevent_var(env, "MODALIAS="))
     329                 :            :                 return -ENOMEM;
     330                 :            : 
     331                 :     159256 :         sl = of_device_get_modalias(dev, &env->buf[env->buflen-1],
     332                 :      79628 :                                     sizeof(env->buf) - env->buflen);
     333         [ +  + ]:      79632 :         if (sl >= (sizeof(env->buf) - env->buflen))
     334                 :            :                 return -ENOMEM;
     335                 :      79618 :         env->buflen += sl;
     336                 :            : 
     337                 :      79618 :         return 0;
     338                 :            : }
     339                 :            : EXPORT_SYMBOL_GPL(of_device_uevent_modalias);

Generated by: LCOV version 1.14