Re: [PATCH 12/31] nds32: Device specific operations

2017-11-22 Thread Greentime Hu
2017-11-11 0:14 GMT+08:00 Arnd Bergmann :
> Could you move ioremap_nocache/ioremap_uc/ioremap_wc/ioremap_wt
> out of that #ifdef, or would that break other architectures?
>

It seems ok. I just tried arm64, x86 and nds32.

#endif /* CONFIG_MMU */
#ifndef ioremap_nocache
void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
#define ioremap_nocache ioremap_nocache
static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
{
return ioremap(offset, size);
}
#endif

#ifndef ioremap_uc
#define ioremap_uc ioremap_uc
static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
{
return ioremap_nocache(offset, size);
}
#endif

#ifndef ioremap_wc
#define ioremap_wc ioremap_wc
static inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)
{
return ioremap_nocache(offset, size);
}
#endif

#ifndef ioremap_wt
#define ioremap_wt ioremap_wt
static inline void __iomem *ioremap_wt(phys_addr_t offset, size_t size)
{
return ioremap_nocache(offset, size);
}
#endif


Re: [PATCH 12/31] nds32: Device specific operations

2017-11-22 Thread Greentime Hu
2017-11-11 0:14 GMT+08:00 Arnd Bergmann :
> Could you move ioremap_nocache/ioremap_uc/ioremap_wc/ioremap_wt
> out of that #ifdef, or would that break other architectures?
>

It seems ok. I just tried arm64, x86 and nds32.

#endif /* CONFIG_MMU */
#ifndef ioremap_nocache
void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
#define ioremap_nocache ioremap_nocache
static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
{
return ioremap(offset, size);
}
#endif

#ifndef ioremap_uc
#define ioremap_uc ioremap_uc
static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
{
return ioremap_nocache(offset, size);
}
#endif

#ifndef ioremap_wc
#define ioremap_wc ioremap_wc
static inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)
{
return ioremap_nocache(offset, size);
}
#endif

#ifndef ioremap_wt
#define ioremap_wt ioremap_wt
static inline void __iomem *ioremap_wt(phys_addr_t offset, size_t size)
{
return ioremap_nocache(offset, size);
}
#endif


Re: [PATCH 12/31] nds32: Device specific operations

2017-11-10 Thread Arnd Bergmann
On Fri, Nov 10, 2017 at 5:07 PM, Greentime Hu  wrote:
> 2017-11-09 15:04 GMT+08:00 Greentime Hu :
>> 2017-11-08 17:04 GMT+08:00 Arnd Bergmann :
>>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu  wrote:
>>>
 +
 +#define ioremap(cookie,size)   __ioremap(cookie,size,0,1)
 +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
 +#define iounmap(cookie)__iounmap(cookie)
>>>
 +#include 
>>>
>>> asm-generic/io.h now provides an ioremap_nocache() helper along with
>>> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
>>> ioremap_nocache definition here. You might also be able to remove
>>> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
>>> the identity macro 'define ioremap ioremap'
>>
>> Thanks. I will try to use generic ioremap_nocache() helper in the next
>> version patch.
>
> I think I can't remove ioremap_nocache definition because it is defined
> in asm-generic/io.h with !CONFIG_MMU.

Ah, I see.

Could you move ioremap_nocache/ioremap_uc/ioremap_wc/ioremap_wt
out of that #ifdef, or would that break other architectures?

  Arnd


Re: [PATCH 12/31] nds32: Device specific operations

2017-11-10 Thread Arnd Bergmann
On Fri, Nov 10, 2017 at 5:07 PM, Greentime Hu  wrote:
> 2017-11-09 15:04 GMT+08:00 Greentime Hu :
>> 2017-11-08 17:04 GMT+08:00 Arnd Bergmann :
>>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu  wrote:
>>>
 +
 +#define ioremap(cookie,size)   __ioremap(cookie,size,0,1)
 +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
 +#define iounmap(cookie)__iounmap(cookie)
>>>
 +#include 
>>>
>>> asm-generic/io.h now provides an ioremap_nocache() helper along with
>>> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
>>> ioremap_nocache definition here. You might also be able to remove
>>> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
>>> the identity macro 'define ioremap ioremap'
>>
>> Thanks. I will try to use generic ioremap_nocache() helper in the next
>> version patch.
>
> I think I can't remove ioremap_nocache definition because it is defined
> in asm-generic/io.h with !CONFIG_MMU.

Ah, I see.

Could you move ioremap_nocache/ioremap_uc/ioremap_wc/ioremap_wt
out of that #ifdef, or would that break other architectures?

  Arnd


Re: [PATCH 12/31] nds32: Device specific operations

2017-11-10 Thread Greentime Hu
2017-11-09 15:04 GMT+08:00 Greentime Hu :
> 2017-11-08 17:04 GMT+08:00 Arnd Bergmann :
>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu  wrote:
>>
>>> +
>>> +#define ioremap(cookie,size)   __ioremap(cookie,size,0,1)
>>> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
>>> +#define iounmap(cookie)__iounmap(cookie)
>>
>>> +#include 
>>
>> asm-generic/io.h now provides an ioremap_nocache() helper along with
>> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
>> ioremap_nocache definition here. You might also be able to remove
>> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
>> the identity macro 'define ioremap ioremap'
>
> Thanks. I will try to use generic ioremap_nocache() helper in the next
> version patch.

I think I can't remove ioremap_nocache definition because it is defined
in asm-generic/io.h with !CONFIG_MMU.


Re: [PATCH 12/31] nds32: Device specific operations

2017-11-10 Thread Greentime Hu
2017-11-09 15:04 GMT+08:00 Greentime Hu :
> 2017-11-08 17:04 GMT+08:00 Arnd Bergmann :
>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu  wrote:
>>
>>> +
>>> +#define ioremap(cookie,size)   __ioremap(cookie,size,0,1)
>>> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
>>> +#define iounmap(cookie)__iounmap(cookie)
>>
>>> +#include 
>>
>> asm-generic/io.h now provides an ioremap_nocache() helper along with
>> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
>> ioremap_nocache definition here. You might also be able to remove
>> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
>> the identity macro 'define ioremap ioremap'
>
> Thanks. I will try to use generic ioremap_nocache() helper in the next
> version patch.

I think I can't remove ioremap_nocache definition because it is defined
in asm-generic/io.h with !CONFIG_MMU.


Re: [PATCH 12/31] nds32: Device specific operations

2017-11-08 Thread Greentime Hu
2017-11-08 17:04 GMT+08:00 Arnd Bergmann :
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu  wrote:
>
>> +
>> +#define ioremap(cookie,size)   __ioremap(cookie,size,0,1)
>> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
>> +#define iounmap(cookie)__iounmap(cookie)
>
>> +#include 
>
> asm-generic/io.h now provides an ioremap_nocache() helper along with
> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
> ioremap_nocache definition here. You might also be able to remove
> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
> the identity macro 'define ioremap ioremap'

Thanks. I will try to use generic ioremap_nocache() helper in the next
version patch.

>> +void __iomem *__ioremap(unsigned long phys_addr, size_t size,
>> +   unsigned long flags, unsigned long align)
>
> The 'align' argument is unused here, and not used on other architectures
> either.
>

Thanks. I will remove this argument in the next version patch.

>> +{
>> +   struct vm_struct *area;
>> +   unsigned long addr, offset, last_addr;
>> +   pgprot_t prot;
>> +
>> +   /* Don't allow wraparound or zero size */
>> +   last_addr = phys_addr + size - 1;
>> +   if (!size || last_addr < phys_addr)
>> +   return NULL;
>> +
>> +   /*
>> +* Mappings have to be page-aligned
>> +*/
>> +   offset = phys_addr & ~PAGE_MASK;
>> +   phys_addr &= PAGE_MASK;
>> +   size = PAGE_ALIGN(last_addr + 1) - phys_addr;
>> +
>> +   /*
>> +* Ok, go for it..
>> +*/
>> +   area = get_vm_area(size, VM_IOREMAP);
>
> Better use get_vm_area_caller here to have the ioremap areas show up
> in a more useful form in /proc/vmallocinfo

Thanks.
I will use get_vm_area_caller() in the next version patch.

> Please also have a look at what you can do for memremap().
>
> Since you have no cacheable version of ioremap_wb/wt, it will
> return an uncached mapping all the time, which is not ideal.

Thanks.
I will study kernel/memremap.c


Re: [PATCH 12/31] nds32: Device specific operations

2017-11-08 Thread Greentime Hu
2017-11-08 17:04 GMT+08:00 Arnd Bergmann :
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu  wrote:
>
>> +
>> +#define ioremap(cookie,size)   __ioremap(cookie,size,0,1)
>> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
>> +#define iounmap(cookie)__iounmap(cookie)
>
>> +#include 
>
> asm-generic/io.h now provides an ioremap_nocache() helper along with
> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
> ioremap_nocache definition here. You might also be able to remove
> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
> the identity macro 'define ioremap ioremap'

Thanks. I will try to use generic ioremap_nocache() helper in the next
version patch.

>> +void __iomem *__ioremap(unsigned long phys_addr, size_t size,
>> +   unsigned long flags, unsigned long align)
>
> The 'align' argument is unused here, and not used on other architectures
> either.
>

Thanks. I will remove this argument in the next version patch.

>> +{
>> +   struct vm_struct *area;
>> +   unsigned long addr, offset, last_addr;
>> +   pgprot_t prot;
>> +
>> +   /* Don't allow wraparound or zero size */
>> +   last_addr = phys_addr + size - 1;
>> +   if (!size || last_addr < phys_addr)
>> +   return NULL;
>> +
>> +   /*
>> +* Mappings have to be page-aligned
>> +*/
>> +   offset = phys_addr & ~PAGE_MASK;
>> +   phys_addr &= PAGE_MASK;
>> +   size = PAGE_ALIGN(last_addr + 1) - phys_addr;
>> +
>> +   /*
>> +* Ok, go for it..
>> +*/
>> +   area = get_vm_area(size, VM_IOREMAP);
>
> Better use get_vm_area_caller here to have the ioremap areas show up
> in a more useful form in /proc/vmallocinfo

Thanks.
I will use get_vm_area_caller() in the next version patch.

> Please also have a look at what you can do for memremap().
>
> Since you have no cacheable version of ioremap_wb/wt, it will
> return an uncached mapping all the time, which is not ideal.

Thanks.
I will study kernel/memremap.c


Re: [PATCH 12/31] nds32: Device specific operations

2017-11-08 Thread Arnd Bergmann
On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu  wrote:

> +
> +#define ioremap(cookie,size)   __ioremap(cookie,size,0,1)
> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
> +#define iounmap(cookie)__iounmap(cookie)

> +#include 

asm-generic/io.h now provides an ioremap_nocache() helper along with
ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
ioremap_nocache definition here. You might also be able to remove
__ioremap and __iounmap, and only provide ioremap/iounmap, plus
the identity macro 'define ioremap ioremap'

> +void __iomem *__ioremap(unsigned long phys_addr, size_t size,
> +   unsigned long flags, unsigned long align)

The 'align' argument is unused here, and not used on other architectures
either.

> +{
> +   struct vm_struct *area;
> +   unsigned long addr, offset, last_addr;
> +   pgprot_t prot;
> +
> +   /* Don't allow wraparound or zero size */
> +   last_addr = phys_addr + size - 1;
> +   if (!size || last_addr < phys_addr)
> +   return NULL;
> +
> +   /*
> +* Mappings have to be page-aligned
> +*/
> +   offset = phys_addr & ~PAGE_MASK;
> +   phys_addr &= PAGE_MASK;
> +   size = PAGE_ALIGN(last_addr + 1) - phys_addr;
> +
> +   /*
> +* Ok, go for it..
> +*/
> +   area = get_vm_area(size, VM_IOREMAP);

Better use get_vm_area_caller here to have the ioremap areas show up
in a more useful form in /proc/vmallocinfo

Please also have a look at what you can do for memremap().

Since you have no cacheable version of ioremap_wb/wt, it will
return an uncached mapping all the time, which is not ideal.

 Arnd


Re: [PATCH 12/31] nds32: Device specific operations

2017-11-08 Thread Arnd Bergmann
On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu  wrote:

> +
> +#define ioremap(cookie,size)   __ioremap(cookie,size,0,1)
> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
> +#define iounmap(cookie)__iounmap(cookie)

> +#include 

asm-generic/io.h now provides an ioremap_nocache() helper along with
ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
ioremap_nocache definition here. You might also be able to remove
__ioremap and __iounmap, and only provide ioremap/iounmap, plus
the identity macro 'define ioremap ioremap'

> +void __iomem *__ioremap(unsigned long phys_addr, size_t size,
> +   unsigned long flags, unsigned long align)

The 'align' argument is unused here, and not used on other architectures
either.

> +{
> +   struct vm_struct *area;
> +   unsigned long addr, offset, last_addr;
> +   pgprot_t prot;
> +
> +   /* Don't allow wraparound or zero size */
> +   last_addr = phys_addr + size - 1;
> +   if (!size || last_addr < phys_addr)
> +   return NULL;
> +
> +   /*
> +* Mappings have to be page-aligned
> +*/
> +   offset = phys_addr & ~PAGE_MASK;
> +   phys_addr &= PAGE_MASK;
> +   size = PAGE_ALIGN(last_addr + 1) - phys_addr;
> +
> +   /*
> +* Ok, go for it..
> +*/
> +   area = get_vm_area(size, VM_IOREMAP);

Better use get_vm_area_caller here to have the ioremap areas show up
in a more useful form in /proc/vmallocinfo

Please also have a look at what you can do for memremap().

Since you have no cacheable version of ioremap_wb/wt, it will
return an uncached mapping all the time, which is not ideal.

 Arnd


[PATCH 12/31] nds32: Device specific operations

2017-11-07 Thread Greentime Hu
From: Greentime Hu 

Signed-off-by: Vincent Chen 
Signed-off-by: Greentime Hu 
---
 arch/nds32/include/asm/io.h |   33 +
 arch/nds32/mm/ioremap.c |   67 +++
 2 files changed, 100 insertions(+)
 create mode 100644 arch/nds32/include/asm/io.h
 create mode 100644 arch/nds32/mm/ioremap.c

diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h
new file mode 100644
index 000..98b3ae9
--- /dev/null
+++ b/arch/nds32/include/asm/io.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#ifndef __ASM_NDS32_IO_H
+#define __ASM_NDS32_IO_H
+
+#ifdef __KERNEL__
+
+#include 
+extern void __iomem *__ioremap(unsigned long, size_t, unsigned long,
+  unsigned long);
+extern void __iounmap(void __iomem * addr);
+
+#define ioremap(cookie,size)   __ioremap(cookie,size,0,1)
+#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
+#define iounmap(cookie)__iounmap(cookie)
+#include 
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_NDS32_IO_H */
diff --git a/arch/nds32/mm/ioremap.c b/arch/nds32/mm/ioremap.c
new file mode 100644
index 000..532e6cf
--- /dev/null
+++ b/arch/nds32/mm/ioremap.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+void __iomem *__ioremap(unsigned long phys_addr, size_t size,
+   unsigned long flags, unsigned long align)
+{
+   struct vm_struct *area;
+   unsigned long addr, offset, last_addr;
+   pgprot_t prot;
+
+   /* Don't allow wraparound or zero size */
+   last_addr = phys_addr + size - 1;
+   if (!size || last_addr < phys_addr)
+   return NULL;
+
+   /*
+* Mappings have to be page-aligned
+*/
+   offset = phys_addr & ~PAGE_MASK;
+   phys_addr &= PAGE_MASK;
+   size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+   /*
+* Ok, go for it..
+*/
+   area = get_vm_area(size, VM_IOREMAP);
+   if (!area)
+   return NULL;
+
+   area->phys_addr = phys_addr;
+   addr = (unsigned long)area->addr;
+   prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D |
+   _PAGE_G | _PAGE_C_DEV);
+   if (ioremap_page_range(addr, addr + size, phys_addr, prot)) {
+   vunmap((void *)addr);
+   return NULL;
+   }
+   return (__force void __iomem *)(offset + (char *)addr);
+
+}
+
+EXPORT_SYMBOL(__ioremap);
+
+void __iounmap(void __iomem * addr)
+{
+   vunmap((void *)(PAGE_MASK & (unsigned long)addr));
+}
+
+EXPORT_SYMBOL(__iounmap);
-- 
1.7.9.5



[PATCH 12/31] nds32: Device specific operations

2017-11-07 Thread Greentime Hu
From: Greentime Hu 

Signed-off-by: Vincent Chen 
Signed-off-by: Greentime Hu 
---
 arch/nds32/include/asm/io.h |   33 +
 arch/nds32/mm/ioremap.c |   67 +++
 2 files changed, 100 insertions(+)
 create mode 100644 arch/nds32/include/asm/io.h
 create mode 100644 arch/nds32/mm/ioremap.c

diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h
new file mode 100644
index 000..98b3ae9
--- /dev/null
+++ b/arch/nds32/include/asm/io.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#ifndef __ASM_NDS32_IO_H
+#define __ASM_NDS32_IO_H
+
+#ifdef __KERNEL__
+
+#include 
+extern void __iomem *__ioremap(unsigned long, size_t, unsigned long,
+  unsigned long);
+extern void __iounmap(void __iomem * addr);
+
+#define ioremap(cookie,size)   __ioremap(cookie,size,0,1)
+#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
+#define iounmap(cookie)__iounmap(cookie)
+#include 
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_NDS32_IO_H */
diff --git a/arch/nds32/mm/ioremap.c b/arch/nds32/mm/ioremap.c
new file mode 100644
index 000..532e6cf
--- /dev/null
+++ b/arch/nds32/mm/ioremap.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+void __iomem *__ioremap(unsigned long phys_addr, size_t size,
+   unsigned long flags, unsigned long align)
+{
+   struct vm_struct *area;
+   unsigned long addr, offset, last_addr;
+   pgprot_t prot;
+
+   /* Don't allow wraparound or zero size */
+   last_addr = phys_addr + size - 1;
+   if (!size || last_addr < phys_addr)
+   return NULL;
+
+   /*
+* Mappings have to be page-aligned
+*/
+   offset = phys_addr & ~PAGE_MASK;
+   phys_addr &= PAGE_MASK;
+   size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+   /*
+* Ok, go for it..
+*/
+   area = get_vm_area(size, VM_IOREMAP);
+   if (!area)
+   return NULL;
+
+   area->phys_addr = phys_addr;
+   addr = (unsigned long)area->addr;
+   prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D |
+   _PAGE_G | _PAGE_C_DEV);
+   if (ioremap_page_range(addr, addr + size, phys_addr, prot)) {
+   vunmap((void *)addr);
+   return NULL;
+   }
+   return (__force void __iomem *)(offset + (char *)addr);
+
+}
+
+EXPORT_SYMBOL(__ioremap);
+
+void __iounmap(void __iomem * addr)
+{
+   vunmap((void *)(PAGE_MASK & (unsigned long)addr));
+}
+
+EXPORT_SYMBOL(__iounmap);
-- 
1.7.9.5