[PATCH] build fix: CONFIG_MEMORY_HOTPLUG=y on i386
[linux-2.6/sactl.git] / arch / i386 / mm / ioremap.c
blob247fde76aaeddaf0c81215917a015bda7ea648ae
1 /*
2 * arch/i386/mm/ioremap.c
4 * Re-map IO memory to kernel address space so that we can access it.
5 * This is needed for high PCI addresses that aren't mapped in the
6 * 640k-1MB IO memory area on PC's
8 * (C) Copyright 1995 1996 Linus Torvalds
9 */
11 #include <linux/vmalloc.h>
12 #include <linux/init.h>
13 #include <linux/slab.h>
14 #include <linux/module.h>
15 #include <asm/io.h>
16 #include <asm/fixmap.h>
17 #include <asm/cacheflush.h>
18 #include <asm/tlbflush.h>
19 #include <asm/pgtable.h>
21 #define ISA_START_ADDRESS 0xa0000
22 #define ISA_END_ADDRESS 0x100000
24 static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
25 unsigned long end, unsigned long phys_addr, unsigned long flags)
27 pte_t *pte;
28 unsigned long pfn;
30 pfn = phys_addr >> PAGE_SHIFT;
31 pte = pte_alloc_kernel(pmd, addr);
32 if (!pte)
33 return -ENOMEM;
34 do {
35 BUG_ON(!pte_none(*pte));
36 set_pte(pte, pfn_pte(pfn, __pgprot(_PAGE_PRESENT | _PAGE_RW |
37 _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
38 pfn++;
39 } while (pte++, addr += PAGE_SIZE, addr != end);
40 return 0;
43 static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
44 unsigned long end, unsigned long phys_addr, unsigned long flags)
46 pmd_t *pmd;
47 unsigned long next;
49 phys_addr -= addr;
50 pmd = pmd_alloc(&init_mm, pud, addr);
51 if (!pmd)
52 return -ENOMEM;
53 do {
54 next = pmd_addr_end(addr, end);
55 if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, flags))
56 return -ENOMEM;
57 } while (pmd++, addr = next, addr != end);
58 return 0;
61 static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
62 unsigned long end, unsigned long phys_addr, unsigned long flags)
64 pud_t *pud;
65 unsigned long next;
67 phys_addr -= addr;
68 pud = pud_alloc(&init_mm, pgd, addr);
69 if (!pud)
70 return -ENOMEM;
71 do {
72 next = pud_addr_end(addr, end);
73 if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, flags))
74 return -ENOMEM;
75 } while (pud++, addr = next, addr != end);
76 return 0;
79 static int ioremap_page_range(unsigned long addr,
80 unsigned long end, unsigned long phys_addr, unsigned long flags)
82 pgd_t *pgd;
83 unsigned long next;
84 int err;
86 BUG_ON(addr >= end);
87 flush_cache_all();
88 phys_addr -= addr;
89 pgd = pgd_offset_k(addr);
90 do {
91 next = pgd_addr_end(addr, end);
92 err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, flags);
93 if (err)
94 break;
95 } while (pgd++, addr = next, addr != end);
96 flush_tlb_all();
97 return err;
101 * Generic mapping function (not visible outside):
105 * Remap an arbitrary physical address space into the kernel virtual
106 * address space. Needed when the kernel wants to access high addresses
107 * directly.
109 * NOTE! We need to allow non-page-aligned mappings too: we will obviously
110 * have to convert them into an offset in a page-aligned mapping, but the
111 * caller shouldn't need to know that small detail.
113 void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
115 void __iomem * addr;
116 struct vm_struct * area;
117 unsigned long offset, last_addr;
119 /* Don't allow wraparound or zero size */
120 last_addr = phys_addr + size - 1;
121 if (!size || last_addr < phys_addr)
122 return NULL;
125 * Don't remap the low PCI/ISA area, it's always mapped..
127 if (phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
128 return (void __iomem *) phys_to_virt(phys_addr);
131 * Don't allow anybody to remap normal RAM that we're using..
133 if (phys_addr <= virt_to_phys(high_memory - 1)) {
134 char *t_addr, *t_end;
135 struct page *page;
137 t_addr = __va(phys_addr);
138 t_end = t_addr + (size - 1);
140 for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
141 if(!PageReserved(page))
142 return NULL;
146 * Mappings have to be page-aligned
148 offset = phys_addr & ~PAGE_MASK;
149 phys_addr &= PAGE_MASK;
150 size = PAGE_ALIGN(last_addr+1) - phys_addr;
153 * Ok, go for it..
155 area = get_vm_area(size, VM_IOREMAP | (flags << 20));
156 if (!area)
157 return NULL;
158 area->phys_addr = phys_addr;
159 addr = (void __iomem *) area->addr;
160 if (ioremap_page_range((unsigned long) addr,
161 (unsigned long) addr + size, phys_addr, flags)) {
162 vunmap((void __force *) addr);
163 return NULL;
165 return (void __iomem *) (offset + (char __iomem *)addr);
167 EXPORT_SYMBOL(__ioremap);
170 * ioremap_nocache - map bus memory into CPU space
171 * @offset: bus address of the memory
172 * @size: size of the resource to map
174 * ioremap_nocache performs a platform specific sequence of operations to
175 * make bus memory CPU accessible via the readb/readw/readl/writeb/
176 * writew/writel functions and the other mmio helpers. The returned
177 * address is not guaranteed to be usable directly as a virtual
178 * address.
180 * This version of ioremap ensures that the memory is marked uncachable
181 * on the CPU as well as honouring existing caching rules from things like
182 * the PCI bus. Note that there are other caches and buffers on many
183 * busses. In particular driver authors should read up on PCI writes
185 * It's useful if some control registers are in such an area and
186 * write combining or read caching is not desirable:
188 * Must be freed with iounmap.
191 void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
193 unsigned long last_addr;
194 void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
195 if (!p)
196 return p;
198 /* Guaranteed to be > phys_addr, as per __ioremap() */
199 last_addr = phys_addr + size - 1;
201 if (last_addr < virt_to_phys(high_memory) - 1) {
202 struct page *ppage = virt_to_page(__va(phys_addr));
203 unsigned long npages;
205 phys_addr &= PAGE_MASK;
207 /* This might overflow and become zero.. */
208 last_addr = PAGE_ALIGN(last_addr);
210 /* .. but that's ok, because modulo-2**n arithmetic will make
211 * the page-aligned "last - first" come out right.
213 npages = (last_addr - phys_addr) >> PAGE_SHIFT;
215 if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) {
216 iounmap(p);
217 p = NULL;
219 global_flush_tlb();
222 return p;
224 EXPORT_SYMBOL(ioremap_nocache);
227 * iounmap - Free a IO remapping
228 * @addr: virtual address from ioremap_*
230 * Caller must ensure there is only one unmapping for the same pointer.
232 void iounmap(volatile void __iomem *addr)
234 struct vm_struct *p, *o;
236 if ((void __force *)addr <= high_memory)
237 return;
240 * __ioremap special-cases the PCI/ISA range by not instantiating a
241 * vm_area and by simply returning an address into the kernel mapping
242 * of ISA space. So handle that here.
244 if (addr >= phys_to_virt(ISA_START_ADDRESS) &&
245 addr < phys_to_virt(ISA_END_ADDRESS))
246 return;
248 addr = (volatile void __iomem *)(PAGE_MASK & (unsigned long __force)addr);
250 /* Use the vm area unlocked, assuming the caller
251 ensures there isn't another iounmap for the same address
252 in parallel. Reuse of the virtual address is prevented by
253 leaving it in the global lists until we're done with it.
254 cpa takes care of the direct mappings. */
255 read_lock(&vmlist_lock);
256 for (p = vmlist; p; p = p->next) {
257 if (p->addr == addr)
258 break;
260 read_unlock(&vmlist_lock);
262 if (!p) {
263 printk("iounmap: bad address %p\n", addr);
264 dump_stack();
265 return;
268 /* Reset the direct mapping. Can block */
269 if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
270 change_page_attr(virt_to_page(__va(p->phys_addr)),
271 p->size >> PAGE_SHIFT,
272 PAGE_KERNEL);
273 global_flush_tlb();
276 /* Finally remove it */
277 o = remove_vm_area((void *)addr);
278 BUG_ON(p != o || o == NULL);
279 kfree(p);
281 EXPORT_SYMBOL(iounmap);
283 void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
285 unsigned long offset, last_addr;
286 unsigned int nrpages;
287 enum fixed_addresses idx;
289 /* Don't allow wraparound or zero size */
290 last_addr = phys_addr + size - 1;
291 if (!size || last_addr < phys_addr)
292 return NULL;
295 * Don't remap the low PCI/ISA area, it's always mapped..
297 if (phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
298 return phys_to_virt(phys_addr);
301 * Mappings have to be page-aligned
303 offset = phys_addr & ~PAGE_MASK;
304 phys_addr &= PAGE_MASK;
305 size = PAGE_ALIGN(last_addr) - phys_addr;
308 * Mappings have to fit in the FIX_BTMAP area.
310 nrpages = size >> PAGE_SHIFT;
311 if (nrpages > NR_FIX_BTMAPS)
312 return NULL;
315 * Ok, go for it..
317 idx = FIX_BTMAP_BEGIN;
318 while (nrpages > 0) {
319 set_fixmap(idx, phys_addr);
320 phys_addr += PAGE_SIZE;
321 --idx;
322 --nrpages;
324 return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN));
327 void __init bt_iounmap(void *addr, unsigned long size)
329 unsigned long virt_addr;
330 unsigned long offset;
331 unsigned int nrpages;
332 enum fixed_addresses idx;
334 virt_addr = (unsigned long)addr;
335 if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))
336 return;
337 offset = virt_addr & ~PAGE_MASK;
338 nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
340 idx = FIX_BTMAP_BEGIN;
341 while (nrpages > 0) {
342 clear_fixmap(idx);
343 --idx;
344 --nrpages;