Skip to content

Commit 9d4ae72

Browse files
Deepak SaxenaRussell King
authored andcommitted
[ARM] 3070/2: Add __ioremap_pfn() API
Patch from Deepak Saxena In working on adding 36-bit addressed supersection support to ioremap(), I came to the conclusion that it would be far simpler to do so by just splitting __ioremap() into a main external interface and adding an __ioremap_pfn() function that takes a pfn + offset into the page that __ioremap() can call. This way existing callers of __ioremap() won't have to change their code and 36-bit systems will just call __ioremap_pfn() and we will not have to deal with unsigned long long variables. Note that __ioremap_pfn() should _NOT_ be called directly by drivers but is reserved for use by arch_ioremap() implementations that map 32-bit resource regions into the real 36-bit address and then call this new function. Signed-off-by: Deepak Saxena <[email protected]> Signed-off-by: Russell King <[email protected]>
1 parent 16ed926 commit 9d4ae72

File tree

4 files changed

+41
-23
lines changed

4 files changed

+41
-23
lines changed

arch/arm/mm/ioremap.c

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,12 @@ remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
8686
}
8787

8888
static int
89-
remap_area_pages(unsigned long start, unsigned long phys_addr,
89+
remap_area_pages(unsigned long start, unsigned long pfn,
9090
unsigned long size, unsigned long flags)
9191
{
9292
unsigned long address = start;
9393
unsigned long end = start + size;
94+
unsigned long phys_addr = __pfn_to_phys(pfn);
9495
int err = 0;
9596
pgd_t * dir;
9697

@@ -129,37 +130,45 @@ remap_area_pages(unsigned long start, unsigned long phys_addr,
129130
* 'flags' are the extra L_PTE_ flags that you want to specify for this
130131
* mapping. See include/asm-arm/proc-armv/pgtable.h for more information.
131132
*/
133+
void __iomem *
134+
__ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
135+
unsigned long flags)
136+
{
137+
unsigned long addr;
138+
struct vm_struct * area;
139+
140+
area = get_vm_area(size, VM_IOREMAP);
141+
if (!area)
142+
return NULL;
143+
addr = (unsigned long)area->addr;
144+
if (remap_area_pages(addr, pfn, size, flags)) {
145+
vfree(addr);
146+
return NULL;
147+
}
148+
return (void __iomem *) (offset + (char *)addr);
149+
}
150+
EXPORT_SYMBOL(__ioremap_pfn);
151+
132152
void __iomem *
133153
__ioremap(unsigned long phys_addr, size_t size, unsigned long flags)
134154
{
135-
void * addr;
136-
struct vm_struct * area;
137-
unsigned long offset, last_addr;
155+
unsigned long last_addr;
156+
unsigned long offset = phys_addr & ~PAGE_MASK;
157+
unsigned long pfn = __phys_to_pfn(phys_addr);
138158

139-
/* Don't allow wraparound or zero size */
159+
/*
160+
* Don't allow wraparound or zero size
161+
*/
140162
last_addr = phys_addr + size - 1;
141163
if (!size || last_addr < phys_addr)
142164
return NULL;
143165

144166
/*
145-
* Mappings have to be page-aligned
167+
* Page align the mapping size
146168
*/
147-
offset = phys_addr & ~PAGE_MASK;
148-
phys_addr &= PAGE_MASK;
149169
size = PAGE_ALIGN(last_addr + 1) - phys_addr;
150170

151-
/*
152-
* Ok, go for it..
153-
*/
154-
area = get_vm_area(size, VM_IOREMAP);
155-
if (!area)
156-
return NULL;
157-
addr = area->addr;
158-
if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
159-
vfree(addr);
160-
return NULL;
161-
}
162-
return (void __iomem *) (offset + (char *)addr);
171+
return __ioremap_pfn(pfn, offset, size, flags);
163172
}
164173
EXPORT_SYMBOL(__ioremap);
165174

include/asm-arm/io.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
5656

5757
/*
5858
* Architecture ioremap implementation.
59+
*
60+
* __ioremap takes CPU physical address.
61+
*
62+
* __ioremap_pfn takes a Page Frame Number and an offset into that page
5963
*/
64+
extern void __iomem * __ioremap_pfn(unsigned long, unsigned long, size_t, unsigned long);
6065
extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
6166
extern void __iounmap(void __iomem *addr);
6267

@@ -261,6 +266,7 @@ check_signature(void __iomem *io_addr, const unsigned char *signature,
261266
*
262267
* ioremap takes a PCI memory address, as specified in
263268
* Documentation/IO-mapping.txt.
269+
*
264270
*/
265271
#ifndef __arch_ioremap
266272
#define ioremap(cookie,size) __ioremap(cookie,size,0)

include/asm-arm/mach/map.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ struct meminfo;
2727
#define MT_ROM 6
2828
#define MT_IXP2000_DEVICE 7
2929

30-
#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT)
31-
#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
32-
3330
extern void create_memmap_holes(struct meminfo *);
3431
extern void memtable_init(struct meminfo *);
3532
extern void iotable_init(struct map_desc *, int);

include/asm-arm/memory.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@
5757
#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
5858
#endif
5959

60+
/*
61+
* Convert a physical address to a Page Frame Number and back
62+
*/
63+
#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT)
64+
#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
65+
6066
/*
6167
* The module space lives between the addresses given by TASK_SIZE
6268
* and PAGE_OFFSET - it must be within 32MB of the kernel text.

0 commit comments

Comments
 (0)