root/arch/sparc/mm/generic.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. forget_pte
  2. io_remap_pte_range
  3. io_remap_pmd_range
  4. io_remap_page_range

   1 /* generic.c: Generic Sparc mm routines that are not dependent upon
   2  *            MMU type but are Sparc specific.
   3  *
   4  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
   5  */
   6 
   7 #include <linux/kernel.h>
   8 #include <linux/mm.h>
   9 #include <linux/swap.h>
  10 
  11 #include <asm/pgtable.h>
  12 #include <asm/page.h>
  13 
  14 static inline void forget_pte(pte_t page)
     /* [previous][next][first][last][top][bottom][index][help] */
  15 {
  16         if (pte_none(page))
  17                 return;
  18         if (pte_present(page)) {
  19                 unsigned long addr = pte_page(page);
  20                 if (addr >= high_memory || PageReserved(mem_map+MAP_NR(addr)))
  21                         return;
  22                 free_page(addr);
  23                 if (current->mm->rss <= 0)
  24                         return;
  25                 current->mm->rss--;
  26                 return;
  27         }
  28         swap_free(pte_val(page));
  29 }
  30 
  31 /* Remap IO memory, the same way as remap_page_range(), but use
  32  * the obio memory space.
  33  *
  34  * They use a pgprot that sets PAGE_IO and does not check the
  35  * mem_map table as this is independent of normal memory.
  36  */
  37 static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
     /* [previous][next][first][last][top][bottom][index][help] */
  38         unsigned long offset, pgprot_t prot, int space)
  39 {
  40         unsigned long end;
  41 
  42         address &= ~PMD_MASK;
  43         end = address + size;
  44         if (end > PMD_SIZE)
  45                 end = PMD_SIZE;
  46         do {
  47                 pte_t oldpage = *pte;
  48                 pte_clear(pte);
  49                 set_pte(pte, mk_pte_io(offset, prot, space));
  50                 forget_pte(oldpage);
  51                 address += PAGE_SIZE;
  52                 offset += PAGE_SIZE;
  53                 pte++;
  54         } while (address < end);
  55 }
  56 
  57 static inline int io_remap_pmd_range(pmd_t * pmd, unsigned long address, unsigned long size,
     /* [previous][next][first][last][top][bottom][index][help] */
  58         unsigned long offset, pgprot_t prot, int space)
  59 {
  60         unsigned long end;
  61 
  62         address &= ~PGDIR_MASK;
  63         end = address + size;
  64         if (end > PGDIR_SIZE)
  65                 end = PGDIR_SIZE;
  66         offset -= address;
  67         do {
  68                 pte_t * pte = pte_alloc(pmd, address);
  69                 if (!pte)
  70                         return -ENOMEM;
  71                 io_remap_pte_range(pte, address, end - address, address + offset, prot, space);
  72                 address = (address + PMD_SIZE) & PMD_MASK;
  73                 pmd++;
  74         } while (address < end);
  75         return 0;
  76 }
  77 
  78 int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space)
     /* [previous][next][first][last][top][bottom][index][help] */
  79 {
  80         int error = 0;
  81         pgd_t * dir;
  82         unsigned long beg = from;
  83         unsigned long end = from + size;
  84 
  85         pgprot_val(prot) = pg_iobits;
  86         offset -= from;
  87         dir = pgd_offset(current->mm, from);
  88         flush_cache_range(current->mm, beg, end);
  89         while (from < end) {
  90                 pmd_t *pmd = pmd_alloc(dir, from);
  91                 error = -ENOMEM;
  92                 if (!pmd)
  93                         break;
  94                 error = io_remap_pmd_range(pmd, from, end - from, offset + from, prot, space);
  95                 if (error)
  96                         break;
  97                 from = (from + PGDIR_SIZE) & PGDIR_MASK;
  98                 dir++;
  99         }
 100         flush_tlb_range(current->mm, beg, end);
 101         return error;
 102 }

/* [previous][next][first][last][top][bottom][index][help] */