aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-11-17 21:17:59 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2012-01-06 17:14:03 -0500
commit2d2eb1d284257cbb7ebb29bd75a3cbbc9275e4f7 (patch)
tree98fba028d8615e534b2f5a81b219e25fc992aa89
parentcff6d2096e9a57c2497dd5ee4aed3c97149bfc9e (diff)
sparc: Kill custom io_remap_pfn_range().
[ Upstream commit 3e37fd3153ac95088a74f5e7c569f7567e9f993a ] To handle the large physical addresses, just make a simple wrapper around remap_pfn_range() like MIPS does. Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--arch/sparc/include/asm/pgtable_32.h20
-rw-r--r--arch/sparc/include/asm/pgtable_64.h20
-rw-r--r--arch/sparc/mm/Makefile1
-rw-r--r--arch/sparc/mm/generic_32.c98
-rw-r--r--arch/sparc/mm/generic_64.c164
5 files changed, 32 insertions, 271 deletions
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
index 5b31a8e8982..a790cc65747 100644
--- a/arch/sparc/include/asm/pgtable_32.h
+++ b/arch/sparc/include/asm/pgtable_32.h
@@ -431,10 +431,6 @@ extern unsigned long *sparc_valid_addr_bitmap;
431#define kern_addr_valid(addr) \ 431#define kern_addr_valid(addr) \
432 (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap)) 432 (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
433 433
434extern int io_remap_pfn_range(struct vm_area_struct *vma,
435 unsigned long from, unsigned long pfn,
436 unsigned long size, pgprot_t prot);
437
438/* 434/*
439 * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in 435 * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
440 * its high 4 bits. These macros/functions put it there or get it from there. 436 * its high 4 bits. These macros/functions put it there or get it from there.
@@ -443,6 +439,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma,
443#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4)) 439#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
444#define GET_PFN(pfn) (pfn & 0x0fffffffUL) 440#define GET_PFN(pfn) (pfn & 0x0fffffffUL)
445 441
442extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
443 unsigned long, pgprot_t);
444
445static inline int io_remap_pfn_range(struct vm_area_struct *vma,
446 unsigned long from, unsigned long pfn,
447 unsigned long size, pgprot_t prot)
448{
449 unsigned long long offset, space, phys_base;
450
451 offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
452 space = GET_IOSPACE(pfn);
453 phys_base = offset | (space << 32ULL);
454
455 return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
456}
457
446#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS 458#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
447#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ 459#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
448({ \ 460({ \
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 1e03c5a6b4f..98226280423 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -750,10 +750,6 @@ static inline bool kern_addr_valid(unsigned long addr)
750 750
751extern int page_in_phys_avail(unsigned long paddr); 751extern int page_in_phys_avail(unsigned long paddr);
752 752
753extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
754 unsigned long pfn,
755 unsigned long size, pgprot_t prot);
756
757/* 753/*
758 * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in 754 * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
759 * its high 4 bits. These macros/functions put it there or get it from there. 755 * its high 4 bits. These macros/functions put it there or get it from there.
@@ -762,6 +758,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
762#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4)) 758#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
763#define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL) 759#define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL)
764 760
761extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
762 unsigned long, pgprot_t);
763
764static inline int io_remap_pfn_range(struct vm_area_struct *vma,
765 unsigned long from, unsigned long pfn,
766 unsigned long size, pgprot_t prot)
767{
768 unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
769 int space = GET_IOSPACE(pfn);
770 unsigned long phys_base;
771
772 phys_base = offset | (((unsigned long) space) << 32UL);
773
774 return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
775}
776
765#include <asm-generic/pgtable.h> 777#include <asm-generic/pgtable.h>
766 778
767/* We provide our own get_unmapped_area to cope with VA holes and 779/* We provide our own get_unmapped_area to cope with VA holes and
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile
index 79836a7dd00..3b6e248650d 100644
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o
8obj-y += fault_$(BITS).o 8obj-y += fault_$(BITS).o
9obj-y += init_$(BITS).o 9obj-y += init_$(BITS).o
10obj-$(CONFIG_SPARC32) += loadmmu.o 10obj-$(CONFIG_SPARC32) += loadmmu.o
11obj-y += generic_$(BITS).o
12obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o 11obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o
13obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o 12obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o
14obj-$(CONFIG_SPARC_LEON)+= leon_mm.o 13obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
diff --git a/arch/sparc/mm/generic_32.c b/arch/sparc/mm/generic_32.c
deleted file mode 100644
index e6067b75f11..00000000000
--- a/arch/sparc/mm/generic_32.c
+++ /dev/null
@@ -1,98 +0,0 @@
1/*
2 * generic.c: Generic Sparc mm routines that are not dependent upon
3 * MMU type but are Sparc specific.
4 *
5 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
6 */
7
8#include <linux/kernel.h>
9#include <linux/mm.h>
10#include <linux/swap.h>
11#include <linux/pagemap.h>
12
13#include <asm/pgalloc.h>
14#include <asm/pgtable.h>
15#include <asm/page.h>
16#include <asm/cacheflush.h>
17#include <asm/tlbflush.h>
18
19/* Remap IO memory, the same way as remap_pfn_range(), but use
20 * the obio memory space.
21 *
22 * They use a pgprot that sets PAGE_IO and does not check the
23 * mem_map table as this is independent of normal memory.
24 */
25static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
26 unsigned long offset, pgprot_t prot, int space)
27{
28 unsigned long end;
29
30 address &= ~PMD_MASK;
31 end = address + size;
32 if (end > PMD_SIZE)
33 end = PMD_SIZE;
34 do {
35 set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space));
36 address += PAGE_SIZE;
37 offset += PAGE_SIZE;
38 pte++;
39 } while (address < end);
40}
41
42static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
43 unsigned long offset, pgprot_t prot, int space)
44{
45 unsigned long end;
46
47 address &= ~PGDIR_MASK;
48 end = address + size;
49 if (end > PGDIR_SIZE)
50 end = PGDIR_SIZE;
51 offset -= address;
52 do {
53 pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
54 if (!pte)
55 return -ENOMEM;
56 io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
57 address = (address + PMD_SIZE) & PMD_MASK;
58 pmd++;
59 } while (address < end);
60 return 0;
61}
62
63int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
64 unsigned long pfn, unsigned long size, pgprot_t prot)
65{
66 int error = 0;
67 pgd_t * dir;
68 unsigned long beg = from;
69 unsigned long end = from + size;
70 struct mm_struct *mm = vma->vm_mm;
71 int space = GET_IOSPACE(pfn);
72 unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
73
74 /* See comment in mm/memory.c remap_pfn_range */
75 vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
76 vma->vm_pgoff = (offset >> PAGE_SHIFT) |
77 ((unsigned long)space << 28UL);
78
79 offset -= from;
80 dir = pgd_offset(mm, from);
81 flush_cache_range(vma, beg, end);
82
83 while (from < end) {
84 pmd_t *pmd = pmd_alloc(mm, dir, from);
85 error = -ENOMEM;
86 if (!pmd)
87 break;
88 error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
89 if (error)
90 break;
91 from = (from + PGDIR_SIZE) & PGDIR_MASK;
92 dir++;
93 }
94
95 flush_tlb_range(vma, beg, end);
96 return error;
97}
98EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/arch/sparc/mm/generic_64.c b/arch/sparc/mm/generic_64.c
deleted file mode 100644
index 3cb00dfd4bd..00000000000
--- a/arch/sparc/mm/generic_64.c
+++ /dev/null
@@ -1,164 +0,0 @@
1/*
2 * generic.c: Generic Sparc mm routines that are not dependent upon
3 * MMU type but are Sparc specific.
4 *
5 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
6 */
7
8#include <linux/kernel.h>
9#include <linux/mm.h>
10#include <linux/swap.h>
11#include <linux/pagemap.h>
12
13#include <asm/pgalloc.h>
14#include <asm/pgtable.h>
15#include <asm/page.h>
16#include <asm/tlbflush.h>
17
18/* Remap IO memory, the same way as remap_pfn_range(), but use
19 * the obio memory space.
20 *
21 * They use a pgprot that sets PAGE_IO and does not check the
22 * mem_map table as this is independent of normal memory.
23 */
24static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
25 unsigned long address,
26 unsigned long size,
27 unsigned long offset, pgprot_t prot,
28 int space)
29{
30 unsigned long end;
31
32 /* clear hack bit that was used as a write_combine side-effect flag */
33 offset &= ~0x1UL;
34 address &= ~PMD_MASK;
35 end = address + size;
36 if (end > PMD_SIZE)
37 end = PMD_SIZE;
38 do {
39 pte_t entry;
40 unsigned long curend = address + PAGE_SIZE;
41
42 entry = mk_pte_io(offset, prot, space, PAGE_SIZE);
43 if (!(address & 0xffff)) {
44 if (PAGE_SIZE < (4 * 1024 * 1024) &&
45 !(address & 0x3fffff) &&
46 !(offset & 0x3ffffe) &&
47 end >= address + 0x400000) {
48 entry = mk_pte_io(offset, prot, space,
49 4 * 1024 * 1024);
50 curend = address + 0x400000;
51 offset += 0x400000;
52 } else if (PAGE_SIZE < (512 * 1024) &&
53 !(address & 0x7ffff) &&
54 !(offset & 0x7fffe) &&
55 end >= address + 0x80000) {
56 entry = mk_pte_io(offset, prot, space,
57 512 * 1024 * 1024);
58 curend = address + 0x80000;
59 offset += 0x80000;
60 } else if (PAGE_SIZE < (64 * 1024) &&
61 !(offset & 0xfffe) &&
62 end >= address + 0x10000) {
63 entry = mk_pte_io(offset, prot, space,
64 64 * 1024);
65 curend = address + 0x10000;
66 offset += 0x10000;
67 } else
68 offset += PAGE_SIZE;
69 } else
70 offset += PAGE_SIZE;
71
72 if (pte_write(entry))
73 entry = pte_mkdirty(entry);
74 do {
75 BUG_ON(!pte_none(*pte));
76 set_pte_at(mm, address, pte, entry);
77 address += PAGE_SIZE;
78 pte_val(entry) += PAGE_SIZE;
79 pte++;
80 } while (address < curend);
81 } while (address < end);
82}
83
84static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
85 unsigned long offset, pgprot_t prot, int space)
86{
87 unsigned long end;
88
89 address &= ~PGDIR_MASK;
90 end = address + size;
91 if (end > PGDIR_SIZE)
92 end = PGDIR_SIZE;
93 offset -= address;
94 do {
95 pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
96 if (!pte)
97 return -ENOMEM;
98 io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
99 pte_unmap(pte);
100 address = (address + PMD_SIZE) & PMD_MASK;
101 pmd++;
102 } while (address < end);
103 return 0;
104}
105
106static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
107 unsigned long offset, pgprot_t prot, int space)
108{
109 unsigned long end;
110
111 address &= ~PUD_MASK;
112 end = address + size;
113 if (end > PUD_SIZE)
114 end = PUD_SIZE;
115 offset -= address;
116 do {
117 pmd_t *pmd = pmd_alloc(mm, pud, address);
118 if (!pud)
119 return -ENOMEM;
120 io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
121 address = (address + PUD_SIZE) & PUD_MASK;
122 pud++;
123 } while (address < end);
124 return 0;
125}
126
127int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
128 unsigned long pfn, unsigned long size, pgprot_t prot)
129{
130 int error = 0;
131 pgd_t * dir;
132 unsigned long beg = from;
133 unsigned long end = from + size;
134 struct mm_struct *mm = vma->vm_mm;
135 int space = GET_IOSPACE(pfn);
136 unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
137 unsigned long phys_base;
138
139 phys_base = offset | (((unsigned long) space) << 32UL);
140
141 /* See comment in mm/memory.c remap_pfn_range */
142 vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
143 vma->vm_pgoff = phys_base >> PAGE_SHIFT;
144
145 offset -= from;
146 dir = pgd_offset(mm, from);
147 flush_cache_range(vma, beg, end);
148
149 while (from < end) {
150 pud_t *pud = pud_alloc(mm, dir, from);
151 error = -ENOMEM;
152 if (!pud)
153 break;
154 error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
155 if (error)
156 break;
157 from = (from + PGDIR_SIZE) & PGDIR_MASK;
158 dir++;
159 }
160
161 flush_tlb_range(vma, beg, end);
162 return error;
163}
164EXPORT_SYMBOL(io_remap_pfn_range);