LCOV - code coverage report
Current view: top level - lib - devres.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 24 60 40.0 %
Date: 2015-04-12 14:34:49 Functions: 3 10 30.0 %

          Line data    Source code
       1             : #include <linux/err.h>
       2             : #include <linux/pci.h>
       3             : #include <linux/io.h>
       4             : #include <linux/gfp.h>
       5             : #include <linux/export.h>
       6             : 
       7           0 : void devm_ioremap_release(struct device *dev, void *res)
       8             : {
       9           0 :         iounmap(*(void __iomem **)res);
      10           0 : }
      11             : 
      12           0 : static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
      13             : {
      14           0 :         return *(void **)res == match_data;
      15             : }
      16             : 
      17             : /**
      18             :  * devm_ioremap - Managed ioremap()
      19             :  * @dev: Generic device to remap IO address for
      20             :  * @offset: BUS offset to map
      21             :  * @size: Size of map
      22             :  *
      23             :  * Managed ioremap().  Map is automatically unmapped on driver detach.
      24             :  */
      25           1 : void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
      26             :                            resource_size_t size)
      27             : {
      28             :         void __iomem **ptr, *addr;
      29             : 
      30           1 :         ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
      31           1 :         if (!ptr)
      32             :                 return NULL;
      33             : 
      34           1 :         addr = ioremap(offset, size);
      35           1 :         if (addr) {
      36           1 :                 *ptr = addr;
      37           1 :                 devres_add(dev, ptr);
      38             :         } else
      39           0 :                 devres_free(ptr);
      40             : 
      41           1 :         return addr;
      42             : }
      43             : EXPORT_SYMBOL(devm_ioremap);
      44             : 
      45             : /**
      46             :  * devm_ioremap_nocache - Managed ioremap_nocache()
      47             :  * @dev: Generic device to remap IO address for
      48             :  * @offset: BUS offset to map
      49             :  * @size: Size of map
      50             :  *
      51             :  * Managed ioremap_nocache().  Map is automatically unmapped on driver
      52             :  * detach.
      53             :  */
      54           2 : void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
      55             :                                    resource_size_t size)
      56             : {
      57             :         void __iomem **ptr, *addr;
      58             : 
      59           2 :         ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
      60           2 :         if (!ptr)
      61             :                 return NULL;
      62             : 
      63           2 :         addr = ioremap_nocache(offset, size);
      64           2 :         if (addr) {
      65           2 :                 *ptr = addr;
      66           2 :                 devres_add(dev, ptr);
      67             :         } else
      68           0 :                 devres_free(ptr);
      69             : 
      70           2 :         return addr;
      71             : }
      72             : EXPORT_SYMBOL(devm_ioremap_nocache);
      73             : 
      74             : /**
      75             :  * devm_iounmap - Managed iounmap()
      76             :  * @dev: Generic device to unmap for
      77             :  * @addr: Address to unmap
      78             :  *
      79             :  * Managed iounmap().  @addr must have been mapped using devm_ioremap*().
      80             :  */
      81           0 : void devm_iounmap(struct device *dev, void __iomem *addr)
      82             : {
      83           0 :         WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match,
      84             :                                (__force void *)addr));
      85           0 :         iounmap(addr);
      86           0 : }
      87             : EXPORT_SYMBOL(devm_iounmap);
      88             : 
      89             : /**
      90             :  * devm_ioremap_resource() - check, request region, and ioremap resource
      91             :  * @dev: generic device to handle the resource for
      92             :  * @res: resource to be handled
      93             :  *
      94             :  * Checks that a resource is a valid memory region, requests the memory region
      95             :  * and ioremaps it either as cacheable or as non-cacheable memory depending on
      96             :  * the resource's flags. All operations are managed and will be undone on
      97             :  * driver detach.
      98             :  *
      99             :  * Returns a pointer to the remapped memory or an ERR_PTR() encoded error code
     100             :  * on failure. Usage example:
     101             :  *
     102             :  *      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
     103             :  *      base = devm_ioremap_resource(&pdev->dev, res);
     104             :  *      if (IS_ERR(base))
     105             :  *              return PTR_ERR(base);
     106             :  */
     107           6 : void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
     108             : {
     109             :         resource_size_t size;
     110             :         const char *name;
     111             :         void __iomem *dest_ptr;
     112             : 
     113             :         BUG_ON(!dev);
     114             : 
     115           4 :         if (!res || resource_type(res) != IORESOURCE_MEM) {
     116           0 :                 dev_err(dev, "invalid resource\n");
     117           0 :                 return IOMEM_ERR_PTR(-EINVAL);
     118             :         }
     119             : 
     120             :         size = resource_size(res);
     121           2 :         name = res->name ?: dev_name(dev);
     122             : 
     123           2 :         if (!devm_request_mem_region(dev, res->start, size, name)) {
     124           0 :                 dev_err(dev, "can't request region for resource %pR\n", res);
     125           0 :                 return IOMEM_ERR_PTR(-EBUSY);
     126             :         }
     127             : 
     128           2 :         if (res->flags & IORESOURCE_CACHEABLE)
     129           0 :                 dest_ptr = devm_ioremap(dev, res->start, size);
     130             :         else
     131           2 :                 dest_ptr = devm_ioremap_nocache(dev, res->start, size);
     132             : 
     133           2 :         if (!dest_ptr) {
     134           0 :                 dev_err(dev, "ioremap failed for resource %pR\n", res);
     135           0 :                 devm_release_mem_region(dev, res->start, size);
     136             :                 dest_ptr = IOMEM_ERR_PTR(-ENOMEM);
     137             :         }
     138             : 
     139           2 :         return dest_ptr;
     140             : }
     141             : EXPORT_SYMBOL(devm_ioremap_resource);
     142             : 
     143             : #ifdef CONFIG_HAS_IOPORT_MAP
     144             : /*
     145             :  * Generic iomap devres
     146             :  */
     147           0 : static void devm_ioport_map_release(struct device *dev, void *res)
     148             : {
     149           0 :         ioport_unmap(*(void __iomem **)res);
     150           0 : }
     151             : 
     152           0 : static int devm_ioport_map_match(struct device *dev, void *res,
     153             :                                  void *match_data)
     154             : {
     155           0 :         return *(void **)res == match_data;
     156             : }
     157             : 
     158             : /**
     159             :  * devm_ioport_map - Managed ioport_map()
     160             :  * @dev: Generic device to map ioport for
     161             :  * @port: Port to map
     162             :  * @nr: Number of ports to map
     163             :  *
     164             :  * Managed ioport_map().  Map is automatically unmapped on driver
     165             :  * detach.
     166             :  */
     167           0 : void __iomem *devm_ioport_map(struct device *dev, unsigned long port,
     168             :                                unsigned int nr)
     169             : {
     170             :         void __iomem **ptr, *addr;
     171             : 
     172           0 :         ptr = devres_alloc(devm_ioport_map_release, sizeof(*ptr), GFP_KERNEL);
     173           0 :         if (!ptr)
     174             :                 return NULL;
     175             : 
     176           0 :         addr = ioport_map(port, nr);
     177           0 :         if (addr) {
     178           0 :                 *ptr = addr;
     179           0 :                 devres_add(dev, ptr);
     180             :         } else
     181           0 :                 devres_free(ptr);
     182             : 
     183           0 :         return addr;
     184             : }
     185             : EXPORT_SYMBOL(devm_ioport_map);
     186             : 
     187             : /**
     188             :  * devm_ioport_unmap - Managed ioport_unmap()
     189             :  * @dev: Generic device to unmap for
     190             :  * @addr: Address to unmap
     191             :  *
     192             :  * Managed ioport_unmap().  @addr must have been mapped using
     193             :  * devm_ioport_map().
     194             :  */
     195           0 : void devm_ioport_unmap(struct device *dev, void __iomem *addr)
     196             : {
     197           0 :         ioport_unmap(addr);
     198           0 :         WARN_ON(devres_destroy(dev, devm_ioport_map_release,
     199             :                                devm_ioport_map_match, (__force void *)addr));
     200           0 : }
     201             : EXPORT_SYMBOL(devm_ioport_unmap);
     202             : #endif /* CONFIG_HAS_IOPORT_MAP */
     203             : 
     204             : #ifdef CONFIG_PCI
     205             : /*
     206             :  * PCI iomap devres
     207             :  */
     208             : #define PCIM_IOMAP_MAX  PCI_ROM_RESOURCE
     209             : 
     210             : struct pcim_iomap_devres {
     211             :         void __iomem *table[PCIM_IOMAP_MAX];
     212             : };
     213             : 
     214             : static void pcim_iomap_release(struct device *gendev, void *res)
     215             : {
     216             :         struct pci_dev *dev = container_of(gendev, struct pci_dev, dev);
     217             :         struct pcim_iomap_devres *this = res;
     218             :         int i;
     219             : 
     220             :         for (i = 0; i < PCIM_IOMAP_MAX; i++)
     221             :                 if (this->table[i])
     222             :                         pci_iounmap(dev, this->table[i]);
     223             : }
     224             : 
     225             : /**
     226             :  * pcim_iomap_table - access iomap allocation table
     227             :  * @pdev: PCI device to access iomap table for
     228             :  *
     229             :  * Access iomap allocation table for @dev.  If iomap table doesn't
     230             :  * exist and @pdev is managed, it will be allocated.  All iomaps
     231             :  * recorded in the iomap table are automatically unmapped on driver
     232             :  * detach.
     233             :  *
     234             :  * This function might sleep when the table is first allocated but can
     235             :  * be safely called without context and guaranteed to succed once
     236             :  * allocated.
     237             :  */
     238             : void __iomem * const *pcim_iomap_table(struct pci_dev *pdev)
     239             : {
     240             :         struct pcim_iomap_devres *dr, *new_dr;
     241             : 
     242             :         dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL);
     243             :         if (dr)
     244             :                 return dr->table;
     245             : 
     246             :         new_dr = devres_alloc(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL);
     247             :         if (!new_dr)
     248             :                 return NULL;
     249             :         dr = devres_get(&pdev->dev, new_dr, NULL, NULL);
     250             :         return dr->table;
     251             : }
     252             : EXPORT_SYMBOL(pcim_iomap_table);
     253             : 
     254             : /**
     255             :  * pcim_iomap - Managed pcim_iomap()
     256             :  * @pdev: PCI device to iomap for
     257             :  * @bar: BAR to iomap
     258             :  * @maxlen: Maximum length of iomap
     259             :  *
     260             :  * Managed pci_iomap().  Map is automatically unmapped on driver
     261             :  * detach.
     262             :  */
     263             : void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
     264             : {
     265             :         void __iomem **tbl;
     266             : 
     267             :         BUG_ON(bar >= PCIM_IOMAP_MAX);
     268             : 
     269             :         tbl = (void __iomem **)pcim_iomap_table(pdev);
     270             :         if (!tbl || tbl[bar])   /* duplicate mappings not allowed */
     271             :                 return NULL;
     272             : 
     273             :         tbl[bar] = pci_iomap(pdev, bar, maxlen);
     274             :         return tbl[bar];
     275             : }
     276             : EXPORT_SYMBOL(pcim_iomap);
     277             : 
     278             : /**
     279             :  * pcim_iounmap - Managed pci_iounmap()
     280             :  * @pdev: PCI device to iounmap for
     281             :  * @addr: Address to unmap
     282             :  *
     283             :  * Managed pci_iounmap().  @addr must have been mapped using pcim_iomap().
     284             :  */
     285             : void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
     286             : {
     287             :         void __iomem **tbl;
     288             :         int i;
     289             : 
     290             :         pci_iounmap(pdev, addr);
     291             : 
     292             :         tbl = (void __iomem **)pcim_iomap_table(pdev);
     293             :         BUG_ON(!tbl);
     294             : 
     295             :         for (i = 0; i < PCIM_IOMAP_MAX; i++)
     296             :                 if (tbl[i] == addr) {
     297             :                         tbl[i] = NULL;
     298             :                         return;
     299             :                 }
     300             :         WARN_ON(1);
     301             : }
     302             : EXPORT_SYMBOL(pcim_iounmap);
     303             : 
     304             : /**
     305             :  * pcim_iomap_regions - Request and iomap PCI BARs
     306             :  * @pdev: PCI device to map IO resources for
     307             :  * @mask: Mask of BARs to request and iomap
     308             :  * @name: Name used when requesting regions
     309             :  *
     310             :  * Request and iomap regions specified by @mask.
     311             :  */
     312             : int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name)
     313             : {
     314             :         void __iomem * const *iomap;
     315             :         int i, rc;
     316             : 
     317             :         iomap = pcim_iomap_table(pdev);
     318             :         if (!iomap)
     319             :                 return -ENOMEM;
     320             : 
     321             :         for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
     322             :                 unsigned long len;
     323             : 
     324             :                 if (!(mask & (1 << i)))
     325             :                         continue;
     326             : 
     327             :                 rc = -EINVAL;
     328             :                 len = pci_resource_len(pdev, i);
     329             :                 if (!len)
     330             :                         goto err_inval;
     331             : 
     332             :                 rc = pci_request_region(pdev, i, name);
     333             :                 if (rc)
     334             :                         goto err_inval;
     335             : 
     336             :                 rc = -ENOMEM;
     337             :                 if (!pcim_iomap(pdev, i, 0))
     338             :                         goto err_region;
     339             :         }
     340             : 
     341             :         return 0;
     342             : 
     343             :  err_region:
     344             :         pci_release_region(pdev, i);
     345             :  err_inval:
     346             :         while (--i >= 0) {
     347             :                 if (!(mask & (1 << i)))
     348             :                         continue;
     349             :                 pcim_iounmap(pdev, iomap[i]);
     350             :                 pci_release_region(pdev, i);
     351             :         }
     352             : 
     353             :         return rc;
     354             : }
     355             : EXPORT_SYMBOL(pcim_iomap_regions);
     356             : 
     357             : /**
     358             :  * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones
     359             :  * @pdev: PCI device to map IO resources for
     360             :  * @mask: Mask of BARs to iomap
     361             :  * @name: Name used when requesting regions
     362             :  *
     363             :  * Request all PCI BARs and iomap regions specified by @mask.
     364             :  */
     365             : int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
     366             :                                    const char *name)
     367             : {
     368             :         int request_mask = ((1 << 6) - 1) & ~mask;
     369             :         int rc;
     370             : 
     371             :         rc = pci_request_selected_regions(pdev, request_mask, name);
     372             :         if (rc)
     373             :                 return rc;
     374             : 
     375             :         rc = pcim_iomap_regions(pdev, mask, name);
     376             :         if (rc)
     377             :                 pci_release_selected_regions(pdev, request_mask);
     378             :         return rc;
     379             : }
     380             : EXPORT_SYMBOL(pcim_iomap_regions_request_all);
     381             : 
     382             : /**
     383             :  * pcim_iounmap_regions - Unmap and release PCI BARs
     384             :  * @pdev: PCI device to map IO resources for
     385             :  * @mask: Mask of BARs to unmap and release
     386             :  *
     387             :  * Unmap and release regions specified by @mask.
     388             :  */
     389             : void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
     390             : {
     391             :         void __iomem * const *iomap;
     392             :         int i;
     393             : 
     394             :         iomap = pcim_iomap_table(pdev);
     395             :         if (!iomap)
     396             :                 return;
     397             : 
     398             :         for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
     399             :                 if (!(mask & (1 << i)))
     400             :                         continue;
     401             : 
     402             :                 pcim_iounmap(pdev, iomap[i]);
     403             :                 pci_release_region(pdev, i);
     404             :         }
     405             : }
     406             : EXPORT_SYMBOL(pcim_iounmap_regions);
     407             : #endif /* CONFIG_PCI */

Generated by: LCOV version 1.11