Message ID | 4e9acf2ec55fb26ddb290ca2d955eeea628e0a77.1510118606.git.green.hu@gmail.com |
---|---|
State | Not Applicable, archived |
Delegated to: | David Miller |
Headers | show |
Series | Andes(nds32) Linux Kernel Port | expand |
On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> 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> 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
2017-11-08 17:04 GMT+08:00 Arnd Bergmann <arnd@arndb.de>: > On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> 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> > > 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
2017-11-09 15:04 GMT+08:00 Greentime Hu <green.hu@gmail.com>: > 2017-11-08 17:04 GMT+08:00 Arnd Bergmann <arnd@arndb.de>: >> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> 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> >> >> 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.
On Fri, Nov 10, 2017 at 5:07 PM, Greentime Hu <green.hu@gmail.com> wrote: > 2017-11-09 15:04 GMT+08:00 Greentime Hu <green.hu@gmail.com>: >> 2017-11-08 17:04 GMT+08:00 Arnd Bergmann <arnd@arndb.de>: >>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> 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> >>> >>> 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
2017-11-11 0:14 GMT+08:00 Arnd Bergmann <arnd@arndb.de>: > 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
diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h new file mode 100644 index 0000000..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 <http://www.gnu.org/licenses/>. + */ + +#ifndef __ASM_NDS32_IO_H +#define __ASM_NDS32_IO_H + +#ifdef __KERNEL__ + +#include <asm-generic/iomap.h> +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 <asm-generic/io.h> + +#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 0000000..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 <http://www.gnu.org/licenses/>. + */ + +#include <linux/vmalloc.h> +#include <linux/io.h> +#include <linux/mm.h> +#include <asm/pgtable.h> + +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);