LCOV - code coverage report
Current view: top level - lib - devres.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 145 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 23 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : #include <linux/err.h>
       3             : #include <linux/pci.h>
       4             : #include <linux/io.h>
       5             : #include <linux/gfp.h>
       6             : #include <linux/export.h>
       7             : #include <linux/of_address.h>
       8             : 
       9             : enum devm_ioremap_type {
      10             :         DEVM_IOREMAP = 0,
      11             :         DEVM_IOREMAP_UC,
      12             :         DEVM_IOREMAP_WC,
      13             :         DEVM_IOREMAP_NP,
      14             : };
      15             : 
      16           0 : void devm_ioremap_release(struct device *dev, void *res)
      17             : {
      18           0 :         iounmap(*(void __iomem **)res);
      19           0 : }
      20             : 
      21           0 : static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
      22             : {
      23           0 :         return *(void **)res == match_data;
      24             : }
      25             : 
      26           0 : static void __iomem *__devm_ioremap(struct device *dev, resource_size_t offset,
      27             :                                     resource_size_t size,
      28             :                                     enum devm_ioremap_type type)
      29             : {
      30           0 :         void __iomem **ptr, *addr = NULL;
      31             : 
      32           0 :         ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
      33           0 :         if (!ptr)
      34             :                 return NULL;
      35             : 
      36           0 :         switch (type) {
      37             :         case DEVM_IOREMAP:
      38           0 :                 addr = ioremap(offset, size);
      39           0 :                 break;
      40             :         case DEVM_IOREMAP_UC:
      41             :                 addr = ioremap_uc(offset, size);
      42             :                 break;
      43             :         case DEVM_IOREMAP_WC:
      44           0 :                 addr = ioremap_wc(offset, size);
      45           0 :                 break;
      46             :         case DEVM_IOREMAP_NP:
      47             :                 addr = ioremap_np(offset, size);
      48             :                 break;
      49             :         }
      50             : 
      51           0 :         if (addr) {
      52           0 :                 *ptr = addr;
      53           0 :                 devres_add(dev, ptr);
      54             :         } else
      55           0 :                 devres_free(ptr);
      56             : 
      57             :         return addr;
      58             : }
      59             : 
      60             : /**
      61             :  * devm_ioremap - Managed ioremap()
      62             :  * @dev: Generic device to remap IO address for
      63             :  * @offset: Resource address to map
      64             :  * @size: Size of map
      65             :  *
      66             :  * Managed ioremap().  Map is automatically unmapped on driver detach.
      67             :  */
      68           0 : void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
      69             :                            resource_size_t size)
      70             : {
      71           0 :         return __devm_ioremap(dev, offset, size, DEVM_IOREMAP);
      72             : }
      73             : EXPORT_SYMBOL(devm_ioremap);
      74             : 
      75             : /**
      76             :  * devm_ioremap_uc - Managed ioremap_uc()
      77             :  * @dev: Generic device to remap IO address for
      78             :  * @offset: Resource address to map
      79             :  * @size: Size of map
      80             :  *
      81             :  * Managed ioremap_uc().  Map is automatically unmapped on driver detach.
      82             :  */
      83           0 : void __iomem *devm_ioremap_uc(struct device *dev, resource_size_t offset,
      84             :                               resource_size_t size)
      85             : {
      86           0 :         return __devm_ioremap(dev, offset, size, DEVM_IOREMAP_UC);
      87             : }
      88             : EXPORT_SYMBOL_GPL(devm_ioremap_uc);
      89             : 
      90             : /**
      91             :  * devm_ioremap_wc - Managed ioremap_wc()
      92             :  * @dev: Generic device to remap IO address for
      93             :  * @offset: Resource address to map
      94             :  * @size: Size of map
      95             :  *
      96             :  * Managed ioremap_wc().  Map is automatically unmapped on driver detach.
      97             :  */
      98           0 : void __iomem *devm_ioremap_wc(struct device *dev, resource_size_t offset,
      99             :                               resource_size_t size)
     100             : {
     101           0 :         return __devm_ioremap(dev, offset, size, DEVM_IOREMAP_WC);
     102             : }
     103             : EXPORT_SYMBOL(devm_ioremap_wc);
     104             : 
     105             : /**
     106             :  * devm_ioremap_np - Managed ioremap_np()
     107             :  * @dev: Generic device to remap IO address for
     108             :  * @offset: Resource address to map
     109             :  * @size: Size of map
     110             :  *
     111             :  * Managed ioremap_np().  Map is automatically unmapped on driver detach.
     112             :  */
     113           0 : void __iomem *devm_ioremap_np(struct device *dev, resource_size_t offset,
     114             :                               resource_size_t size)
     115             : {
     116           0 :         return __devm_ioremap(dev, offset, size, DEVM_IOREMAP_NP);
     117             : }
     118             : EXPORT_SYMBOL(devm_ioremap_np);
     119             : 
     120             : /**
     121             :  * devm_iounmap - Managed iounmap()
     122             :  * @dev: Generic device to unmap for
     123             :  * @addr: Address to unmap
     124             :  *
     125             :  * Managed iounmap().  @addr must have been mapped using devm_ioremap*().
     126             :  */
     127           0 : void devm_iounmap(struct device *dev, void __iomem *addr)
     128             : {
     129           0 :         WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match,
     130             :                                (__force void *)addr));
     131           0 :         iounmap(addr);
     132           0 : }
     133             : EXPORT_SYMBOL(devm_iounmap);
     134             : 
     135             : static void __iomem *
     136           0 : __devm_ioremap_resource(struct device *dev, const struct resource *res,
     137             :                         enum devm_ioremap_type type)
     138             : {
     139             :         resource_size_t size;
     140             :         void __iomem *dest_ptr;
     141             :         char *pretty_name;
     142             : 
     143           0 :         BUG_ON(!dev);
     144             : 
     145           0 :         if (!res || resource_type(res) != IORESOURCE_MEM) {
     146           0 :                 dev_err(dev, "invalid resource\n");
     147           0 :                 return IOMEM_ERR_PTR(-EINVAL);
     148             :         }
     149             : 
     150           0 :         if (type == DEVM_IOREMAP && res->flags & IORESOURCE_MEM_NONPOSTED)
     151           0 :                 type = DEVM_IOREMAP_NP;
     152             : 
     153           0 :         size = resource_size(res);
     154             : 
     155           0 :         if (res->name)
     156           0 :                 pretty_name = devm_kasprintf(dev, GFP_KERNEL, "%s %s",
     157             :                                              dev_name(dev), res->name);
     158             :         else
     159           0 :                 pretty_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
     160           0 :         if (!pretty_name) {
     161           0 :                 dev_err(dev, "can't generate pretty name for resource %pR\n", res);
     162           0 :                 return IOMEM_ERR_PTR(-ENOMEM);
     163             :         }
     164             : 
     165           0 :         if (!devm_request_mem_region(dev, res->start, size, pretty_name)) {
     166           0 :                 dev_err(dev, "can't request region for resource %pR\n", res);
     167           0 :                 return IOMEM_ERR_PTR(-EBUSY);
     168             :         }
     169             : 
     170           0 :         dest_ptr = __devm_ioremap(dev, res->start, size, type);
     171           0 :         if (!dest_ptr) {
     172           0 :                 dev_err(dev, "ioremap failed for resource %pR\n", res);
     173           0 :                 devm_release_mem_region(dev, res->start, size);
     174           0 :                 dest_ptr = IOMEM_ERR_PTR(-ENOMEM);
     175             :         }
     176             : 
     177             :         return dest_ptr;
     178             : }
     179             : 
     180             : /**
     181             :  * devm_ioremap_resource() - check, request region, and ioremap resource
     182             :  * @dev: generic device to handle the resource for
     183             :  * @res: resource to be handled
     184             :  *
     185             :  * Checks that a resource is a valid memory region, requests the memory
     186             :  * region and ioremaps it. All operations are managed and will be undone
     187             :  * on driver detach.
     188             :  *
     189             :  * Usage example:
     190             :  *
     191             :  *      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
     192             :  *      base = devm_ioremap_resource(&pdev->dev, res);
     193             :  *      if (IS_ERR(base))
     194             :  *              return PTR_ERR(base);
     195             :  *
     196             :  * Return: a pointer to the remapped memory or an ERR_PTR() encoded error code
     197             :  * on failure.
     198             :  */
     199           0 : void __iomem *devm_ioremap_resource(struct device *dev,
     200             :                                     const struct resource *res)
     201             : {
     202           0 :         return __devm_ioremap_resource(dev, res, DEVM_IOREMAP);
     203             : }
     204             : EXPORT_SYMBOL(devm_ioremap_resource);
     205             : 
     206             : /**
     207             :  * devm_ioremap_resource_wc() - write-combined variant of
     208             :  *                              devm_ioremap_resource()
     209             :  * @dev: generic device to handle the resource for
     210             :  * @res: resource to be handled
     211             :  *
     212             :  * Return: a pointer to the remapped memory or an ERR_PTR() encoded error code
     213             :  * on failure.
     214             :  */
     215           0 : void __iomem *devm_ioremap_resource_wc(struct device *dev,
     216             :                                        const struct resource *res)
     217             : {
     218           0 :         return __devm_ioremap_resource(dev, res, DEVM_IOREMAP_WC);
     219             : }
     220             : 
     221             : /*
     222             :  * devm_of_iomap - Requests a resource and maps the memory mapped IO
     223             :  *                 for a given device_node managed by a given device
     224             :  *
     225             :  * Checks that a resource is a valid memory region, requests the memory
     226             :  * region and ioremaps it. All operations are managed and will be undone
     227             :  * on driver detach of the device.
     228             :  *
     229             :  * This is to be used when a device requests/maps resources described
     230             :  * by other device tree nodes (children or otherwise).
     231             :  *
     232             :  * @dev:        The device "managing" the resource
     233             :  * @node:       The device-tree node where the resource resides
     234             :  * @index:      index of the MMIO range in the "reg" property
     235             :  * @size:       Returns the size of the resource (pass NULL if not needed)
     236             :  *
     237             :  * Usage example:
     238             :  *
     239             :  *      base = devm_of_iomap(&pdev->dev, node, 0, NULL);
     240             :  *      if (IS_ERR(base))
     241             :  *              return PTR_ERR(base);
     242             :  *
     243             :  * Please Note: This is not a one-to-one replacement for of_iomap() because the
     244             :  * of_iomap() function does not track whether the region is already mapped.  If
     245             :  * two drivers try to map the same memory, the of_iomap() function will succeed
     246             :  * but the devm_of_iomap() function will return -EBUSY.
     247             :  *
     248             :  * Return: a pointer to the requested and mapped memory or an ERR_PTR() encoded
     249             :  * error code on failure.
     250             :  */
     251           0 : void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index,
     252             :                             resource_size_t *size)
     253             : {
     254             :         struct resource res;
     255             : 
     256           0 :         if (of_address_to_resource(node, index, &res))
     257           0 :                 return IOMEM_ERR_PTR(-EINVAL);
     258             :         if (size)
     259             :                 *size = resource_size(&res);
     260             :         return devm_ioremap_resource(dev, &res);
     261             : }
     262             : EXPORT_SYMBOL(devm_of_iomap);
     263             : 
     264             : #ifdef CONFIG_HAS_IOPORT_MAP
     265             : /*
     266             :  * Generic iomap devres
     267             :  */
     268             : static void devm_ioport_map_release(struct device *dev, void *res)
     269             : {
     270             :         ioport_unmap(*(void __iomem **)res);
     271             : }
     272             : 
     273             : static int devm_ioport_map_match(struct device *dev, void *res,
     274             :                                  void *match_data)
     275             : {
     276             :         return *(void **)res == match_data;
     277             : }
     278             : 
     279             : /**
     280             :  * devm_ioport_map - Managed ioport_map()
     281             :  * @dev: Generic device to map ioport for
     282             :  * @port: Port to map
     283             :  * @nr: Number of ports to map
     284             :  *
     285             :  * Managed ioport_map().  Map is automatically unmapped on driver
     286             :  * detach.
     287             :  *
     288             :  * Return: a pointer to the remapped memory or NULL on failure.
     289             :  */
     290             : void __iomem *devm_ioport_map(struct device *dev, unsigned long port,
     291             :                                unsigned int nr)
     292             : {
     293             :         void __iomem **ptr, *addr;
     294             : 
     295             :         ptr = devres_alloc(devm_ioport_map_release, sizeof(*ptr), GFP_KERNEL);
     296             :         if (!ptr)
     297             :                 return NULL;
     298             : 
     299             :         addr = ioport_map(port, nr);
     300             :         if (addr) {
     301             :                 *ptr = addr;
     302             :                 devres_add(dev, ptr);
     303             :         } else
     304             :                 devres_free(ptr);
     305             : 
     306             :         return addr;
     307             : }
     308             : EXPORT_SYMBOL(devm_ioport_map);
     309             : 
     310             : /**
     311             :  * devm_ioport_unmap - Managed ioport_unmap()
     312             :  * @dev: Generic device to unmap for
     313             :  * @addr: Address to unmap
     314             :  *
     315             :  * Managed ioport_unmap().  @addr must have been mapped using
     316             :  * devm_ioport_map().
     317             :  */
     318             : void devm_ioport_unmap(struct device *dev, void __iomem *addr)
     319             : {
     320             :         ioport_unmap(addr);
     321             :         WARN_ON(devres_destroy(dev, devm_ioport_map_release,
     322             :                                devm_ioport_map_match, (__force void *)addr));
     323             : }
     324             : EXPORT_SYMBOL(devm_ioport_unmap);
     325             : #endif /* CONFIG_HAS_IOPORT_MAP */
     326             : 
     327             : #ifdef CONFIG_PCI
     328             : /*
     329             :  * PCI iomap devres
     330             :  */
     331             : #define PCIM_IOMAP_MAX  PCI_STD_NUM_BARS
     332             : 
     333             : struct pcim_iomap_devres {
     334             :         void __iomem *table[PCIM_IOMAP_MAX];
     335             : };
     336             : 
     337           0 : static void pcim_iomap_release(struct device *gendev, void *res)
     338             : {
     339           0 :         struct pci_dev *dev = to_pci_dev(gendev);
     340           0 :         struct pcim_iomap_devres *this = res;
     341             :         int i;
     342             : 
     343           0 :         for (i = 0; i < PCIM_IOMAP_MAX; i++)
     344           0 :                 if (this->table[i])
     345           0 :                         pci_iounmap(dev, this->table[i]);
     346           0 : }
     347             : 
     348             : /**
     349             :  * pcim_iomap_table - access iomap allocation table
     350             :  * @pdev: PCI device to access iomap table for
     351             :  *
     352             :  * Access iomap allocation table for @dev.  If iomap table doesn't
     353             :  * exist and @pdev is managed, it will be allocated.  All iomaps
     354             :  * recorded in the iomap table are automatically unmapped on driver
     355             :  * detach.
     356             :  *
     357             :  * This function might sleep when the table is first allocated but can
     358             :  * be safely called without context and guaranteed to succeed once
     359             :  * allocated.
     360             :  */
     361           0 : void __iomem * const *pcim_iomap_table(struct pci_dev *pdev)
     362             : {
     363             :         struct pcim_iomap_devres *dr, *new_dr;
     364             : 
     365           0 :         dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL);
     366           0 :         if (dr)
     367           0 :                 return dr->table;
     368             : 
     369           0 :         new_dr = devres_alloc(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL);
     370           0 :         if (!new_dr)
     371             :                 return NULL;
     372           0 :         dr = devres_get(&pdev->dev, new_dr, NULL, NULL);
     373           0 :         return dr->table;
     374             : }
     375             : EXPORT_SYMBOL(pcim_iomap_table);
     376             : 
     377             : /**
     378             :  * pcim_iomap - Managed pcim_iomap()
     379             :  * @pdev: PCI device to iomap for
     380             :  * @bar: BAR to iomap
     381             :  * @maxlen: Maximum length of iomap
     382             :  *
     383             :  * Managed pci_iomap().  Map is automatically unmapped on driver
     384             :  * detach.
     385             :  */
     386           0 : void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
     387             : {
     388             :         void __iomem **tbl;
     389             : 
     390           0 :         BUG_ON(bar >= PCIM_IOMAP_MAX);
     391             : 
     392           0 :         tbl = (void __iomem **)pcim_iomap_table(pdev);
     393           0 :         if (!tbl || tbl[bar])   /* duplicate mappings not allowed */
     394             :                 return NULL;
     395             : 
     396           0 :         tbl[bar] = pci_iomap(pdev, bar, maxlen);
     397           0 :         return tbl[bar];
     398             : }
     399             : EXPORT_SYMBOL(pcim_iomap);
     400             : 
     401             : /**
     402             :  * pcim_iounmap - Managed pci_iounmap()
     403             :  * @pdev: PCI device to iounmap for
     404             :  * @addr: Address to unmap
     405             :  *
     406             :  * Managed pci_iounmap().  @addr must have been mapped using pcim_iomap().
     407             :  */
     408           0 : void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
     409             : {
     410             :         void __iomem **tbl;
     411             :         int i;
     412             : 
     413           0 :         pci_iounmap(pdev, addr);
     414             : 
     415           0 :         tbl = (void __iomem **)pcim_iomap_table(pdev);
     416           0 :         BUG_ON(!tbl);
     417             : 
     418           0 :         for (i = 0; i < PCIM_IOMAP_MAX; i++)
     419           0 :                 if (tbl[i] == addr) {
     420           0 :                         tbl[i] = NULL;
     421           0 :                         return;
     422             :                 }
     423           0 :         WARN_ON(1);
     424             : }
     425             : EXPORT_SYMBOL(pcim_iounmap);
     426             : 
     427             : /**
     428             :  * pcim_iomap_regions - Request and iomap PCI BARs
     429             :  * @pdev: PCI device to map IO resources for
     430             :  * @mask: Mask of BARs to request and iomap
     431             :  * @name: Name used when requesting regions
     432             :  *
     433             :  * Request and iomap regions specified by @mask.
     434             :  */
     435           0 : int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name)
     436             : {
     437             :         void __iomem * const *iomap;
     438             :         int i, rc;
     439             : 
     440           0 :         iomap = pcim_iomap_table(pdev);
     441           0 :         if (!iomap)
     442             :                 return -ENOMEM;
     443             : 
     444           0 :         for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
     445             :                 unsigned long len;
     446             : 
     447           0 :                 if (!(mask & (1 << i)))
     448           0 :                         continue;
     449             : 
     450           0 :                 rc = -EINVAL;
     451           0 :                 len = pci_resource_len(pdev, i);
     452           0 :                 if (!len)
     453             :                         goto err_inval;
     454             : 
     455           0 :                 rc = pci_request_region(pdev, i, name);
     456           0 :                 if (rc)
     457             :                         goto err_inval;
     458             : 
     459           0 :                 rc = -ENOMEM;
     460           0 :                 if (!pcim_iomap(pdev, i, 0))
     461             :                         goto err_region;
     462             :         }
     463             : 
     464             :         return 0;
     465             : 
     466             :  err_region:
     467           0 :         pci_release_region(pdev, i);
     468             :  err_inval:
     469           0 :         while (--i >= 0) {
     470           0 :                 if (!(mask & (1 << i)))
     471           0 :                         continue;
     472           0 :                 pcim_iounmap(pdev, iomap[i]);
     473           0 :                 pci_release_region(pdev, i);
     474             :         }
     475             : 
     476             :         return rc;
     477             : }
     478             : EXPORT_SYMBOL(pcim_iomap_regions);
     479             : 
     480             : /**
     481             :  * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones
     482             :  * @pdev: PCI device to map IO resources for
     483             :  * @mask: Mask of BARs to iomap
     484             :  * @name: Name used when requesting regions
     485             :  *
     486             :  * Request all PCI BARs and iomap regions specified by @mask.
     487             :  */
     488           0 : int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
     489             :                                    const char *name)
     490             : {
     491           0 :         int request_mask = ((1 << 6) - 1) & ~mask;
     492             :         int rc;
     493             : 
     494           0 :         rc = pci_request_selected_regions(pdev, request_mask, name);
     495           0 :         if (rc)
     496             :                 return rc;
     497             : 
     498           0 :         rc = pcim_iomap_regions(pdev, mask, name);
     499           0 :         if (rc)
     500           0 :                 pci_release_selected_regions(pdev, request_mask);
     501             :         return rc;
     502             : }
     503             : EXPORT_SYMBOL(pcim_iomap_regions_request_all);
     504             : 
     505             : /**
     506             :  * pcim_iounmap_regions - Unmap and release PCI BARs
     507             :  * @pdev: PCI device to map IO resources for
     508             :  * @mask: Mask of BARs to unmap and release
     509             :  *
     510             :  * Unmap and release regions specified by @mask.
     511             :  */
     512           0 : void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
     513             : {
     514             :         void __iomem * const *iomap;
     515             :         int i;
     516             : 
     517           0 :         iomap = pcim_iomap_table(pdev);
     518           0 :         if (!iomap)
     519             :                 return;
     520             : 
     521           0 :         for (i = 0; i < PCIM_IOMAP_MAX; i++) {
     522           0 :                 if (!(mask & (1 << i)))
     523           0 :                         continue;
     524             : 
     525           0 :                 pcim_iounmap(pdev, iomap[i]);
     526           0 :                 pci_release_region(pdev, i);
     527             :         }
     528             : }
     529             : EXPORT_SYMBOL(pcim_iounmap_regions);
     530             : #endif /* CONFIG_PCI */
     531             : 
     532           0 : static void devm_arch_phys_ac_add_release(struct device *dev, void *res)
     533             : {
     534           0 :         arch_phys_wc_del(*((int *)res));
     535           0 : }
     536             : 
     537             : /**
     538             :  * devm_arch_phys_wc_add - Managed arch_phys_wc_add()
     539             :  * @dev: Managed device
     540             :  * @base: Memory base address
     541             :  * @size: Size of memory range
     542             :  *
     543             :  * Adds a WC MTRR using arch_phys_wc_add() and sets up a release callback.
     544             :  * See arch_phys_wc_add() for more information.
     545             :  */
     546           0 : int devm_arch_phys_wc_add(struct device *dev, unsigned long base, unsigned long size)
     547             : {
     548             :         int *mtrr;
     549             :         int ret;
     550             : 
     551           0 :         mtrr = devres_alloc(devm_arch_phys_ac_add_release, sizeof(*mtrr), GFP_KERNEL);
     552           0 :         if (!mtrr)
     553             :                 return -ENOMEM;
     554             : 
     555           0 :         ret = arch_phys_wc_add(base, size);
     556             :         if (ret < 0) {
     557             :                 devres_free(mtrr);
     558             :                 return ret;
     559             :         }
     560             : 
     561           0 :         *mtrr = ret;
     562           0 :         devres_add(dev, mtrr);
     563             : 
     564           0 :         return ret;
     565             : }
     566             : EXPORT_SYMBOL(devm_arch_phys_wc_add);
     567             : 
     568             : struct arch_io_reserve_memtype_wc_devres {
     569             :         resource_size_t start;
     570             :         resource_size_t size;
     571             : };
     572             : 
     573           0 : static void devm_arch_io_free_memtype_wc_release(struct device *dev, void *res)
     574             : {
     575           0 :         const struct arch_io_reserve_memtype_wc_devres *this = res;
     576             : 
     577           0 :         arch_io_free_memtype_wc(this->start, this->size);
     578           0 : }
     579             : 
     580             : /**
     581             :  * devm_arch_io_reserve_memtype_wc - Managed arch_io_reserve_memtype_wc()
     582             :  * @dev: Managed device
     583             :  * @start: Memory base address
     584             :  * @size: Size of memory range
     585             :  *
     586             :  * Reserves a memory range with WC caching using arch_io_reserve_memtype_wc()
     587             :  * and sets up a release callback See arch_io_reserve_memtype_wc() for more
     588             :  * information.
     589             :  */
     590           0 : int devm_arch_io_reserve_memtype_wc(struct device *dev, resource_size_t start,
     591             :                                     resource_size_t size)
     592             : {
     593             :         struct arch_io_reserve_memtype_wc_devres *dr;
     594             :         int ret;
     595             : 
     596           0 :         dr = devres_alloc(devm_arch_io_free_memtype_wc_release, sizeof(*dr), GFP_KERNEL);
     597           0 :         if (!dr)
     598             :                 return -ENOMEM;
     599             : 
     600           0 :         ret = arch_io_reserve_memtype_wc(start, size);
     601             :         if (ret < 0) {
     602             :                 devres_free(dr);
     603             :                 return ret;
     604             :         }
     605             : 
     606           0 :         dr->start = start;
     607           0 :         dr->size = size;
     608           0 :         devres_add(dev, dr);
     609             : 
     610           0 :         return ret;
     611             : }
     612             : EXPORT_SYMBOL(devm_arch_io_reserve_memtype_wc);

Generated by: LCOV version 1.14