LCOV - code coverage report
Current view: top level - lib - ioremap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 18 18 100.0 %
Date: 2015-04-12 14:34:49 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Re-map IO memory to kernel address space so that we can access it.
       3             :  * This is needed for high PCI addresses that aren't mapped in the
       4             :  * 640k-1MB IO memory area on PC's
       5             :  *
       6             :  * (C) Copyright 1995 1996 Linus Torvalds
       7             :  */
       8             : #include <linux/vmalloc.h>
       9             : #include <linux/mm.h>
      10             : #include <linux/sched.h>
      11             : #include <linux/io.h>
      12             : #include <linux/export.h>
      13             : #include <asm/cacheflush.h>
      14             : #include <asm/pgtable.h>
      15             : 
      16          10 : static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
      17             :                 unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
      18             : {
      19             :         pte_t *pte;
      20             :         u64 pfn;
      21             : 
      22          10 :         pfn = phys_addr >> PAGE_SHIFT;
      23          20 :         pte = pte_alloc_kernel(pmd, addr);
      24          10 :         if (!pte)
      25             :                 return -ENOMEM;
      26             :         do {
      27             :                 BUG_ON(!pte_none(*pte));
      28        3538 :                 set_pte_at(&init_mm, addr, pte, pfn_pte(pfn, prot));
      29        3538 :                 pfn++;
      30        3538 :         } while (pte++, addr += PAGE_SIZE, addr != end);
      31             :         return 0;
      32             : }
      33             : 
      34             : static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
      35             :                 unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
      36             : {
      37             :         pmd_t *pmd;
      38             :         unsigned long next;
      39             : 
      40             :         phys_addr -= addr;
      41             :         pmd = pmd_alloc(&init_mm, pud, addr);
      42          10 :         if (!pmd)
      43             :                 return -ENOMEM;
      44             :         do {
      45             :                 next = pmd_addr_end(addr, end);
      46          10 :                 if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, prot))
      47             :                         return -ENOMEM;
      48             :         } while (pmd++, addr = next, addr != end);
      49             :         return 0;
      50             : }
      51             : 
      52             : static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
      53             :                 unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
      54             : {
      55             :         pud_t *pud;
      56             :         unsigned long next;
      57             : 
      58             :         phys_addr -= addr;
      59             :         pud = pud_alloc(&init_mm, pgd, addr);
      60          10 :         if (!pud)
      61             :                 return -ENOMEM;
      62             :         do {
      63             :                 next = pud_addr_end(addr, end);
      64          10 :                 if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, prot))
      65             :                         return -ENOMEM;
      66             :         } while (pud++, addr = next, addr != end);
      67             :         return 0;
      68             : }
      69             : 
      70           6 : int ioremap_page_range(unsigned long addr,
      71             :                        unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
      72             : {
      73             :         pgd_t *pgd;
      74             :         unsigned long start;
      75             :         unsigned long next;
      76             :         int err;
      77             : 
      78             :         BUG_ON(addr >= end);
      79             : 
      80             :         start = addr;
      81           6 :         phys_addr -= addr;
      82           6 :         pgd = pgd_offset_k(addr);
      83             :         do {
      84          10 :                 next = pgd_addr_end(addr, end);
      85             :                 err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, prot);
      86          10 :                 if (err)
      87             :                         break;
      88          10 :         } while (pgd++, addr = next, addr != end);
      89             : 
      90             :         flush_cache_vmap(start, end);
      91             : 
      92           6 :         return err;
      93             : }
      94             : EXPORT_SYMBOL_GPL(ioremap_page_range);

Generated by: LCOV version 1.11