From: Nicholas Piggin <npiggin@gmail.com> Date: 2019-06-10 03:12:37
__ioremap_at error handling is wonky, it requires caller to clean up
after it. Implement a helper that does the map and error cleanup and
remove the requirement from the caller.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
This series is a different approach to the problem, using the generic
ioremap_page_range directly which reduces added code, and moves
the radix specific code into radix files. Thanks to Christophe for
pointing out various problems with the previous patch.
arch/powerpc/mm/pgtable_64.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
@@ -108,14 +108,30 @@ unsigned long ioremap_bot;unsignedlongioremap_bot=IOREMAP_BASE;#endif+staticintioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,pgprot_tprot,intnid)+{+unsignedlongi;++for(i=0;i<size;i+=PAGE_SIZE){+interr=map_kernel_page(ea+i,pa+i,prot);+if(err){+if(slab_is_available())+unmap_kernel_range(ea,size);+else+WARN_ON_ONCE(1);/* Should clean up */+returnerr;+}+}++return0;+}+/***__ioremap_at-Lowlevelfunctiontoestablishthepagetables*foranIOmapping*/void__iomem*__ioremap_at(phys_addr_tpa,void*ea,unsignedlongsize,pgprot_tprot){-unsignedlongi;-/* We don't support the 4K PFN hack with ioremap */if(pgprot_val(prot)&H_PAGE_4K_PFN)returnNULL;
From: Nicholas Piggin <npiggin@gmail.com> Date: 2019-06-10 03:14:12
Radix can use ioremap_page_range for ioremap, after slab is available.
This makes it possible to enable huge ioremap mapping support.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/book3s/64/radix.h | 3 +++
arch/powerpc/mm/book3s64/pgtable.c | 21 +++++++++++++++++++++
arch/powerpc/mm/book3s64/radix_pgtable.c | 21 +++++++++++++++++++++
arch/powerpc/mm/pgtable_64.c | 2 +-
4 files changed, 46 insertions(+), 1 deletion(-)
@@ -450,3 +450,24 @@ int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,returntrue;}++intioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,pgprot_tprot,intnid)+{+unsignedlongi;++if(radix_enabled())+returnradix__ioremap_range(ea,pa,size,prot,nid);++for(i=0;i<size;i+=PAGE_SIZE){+interr=map_kernel_page(ea+i,pa+i,prot);+if(err){+if(slab_is_available())+unmap_kernel_range(ea,size);+else+WARN_ON_ONCE(1);/* Should clean up */+returnerr;+}+}++return0;+}
Radix can use ioremap_page_range for ioremap, after slab is available.
This makes it possible to enable huge ioremap mapping support.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/book3s/64/radix.h | 3 +++
arch/powerpc/mm/book3s64/pgtable.c | 21 +++++++++++++++++++++
arch/powerpc/mm/book3s64/radix_pgtable.c | 21 +++++++++++++++++++++
arch/powerpc/mm/pgtable_64.c | 2 +-
4 files changed, 46 insertions(+), 1 deletion(-)
@@ -450,3 +450,24 @@ int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,returntrue;}++intioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,pgprot_tprot,intnid)+{+unsignedlongi;++if(radix_enabled())+returnradix__ioremap_range(ea,pa,size,prot,nid);
This function looks pretty similar to the one in the previous patch.
Since radix_enabled() is available and return false for all other
subarches, I think the above could go in the generic ioremap_range(),
you'll only need to move the function declaration in a common file, for
instance asm/io.h
quoted hunk
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ int err = map_kernel_page(ea + i, pa + i, prot);
+ if (err) {
+ if (slab_is_available())
+ unmap_kernel_range(ea, size);
+ else
+ WARN_ON_ONCE(1); /* Should clean up */
+ return err;
+ }
+ }
+
+ return 0;
+}
@@ -1122,3 +1123,23 @@ void radix__ptep_modify_prot_commit(struct vm_area_struct *vma,set_pte_at(mm,addr,ptep,pte);}++intradix__ioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,+pgprot_tprot,intnid)+{+if(likely(slab_is_available())){+interr=ioremap_page_range(ea,ea+size,pa,prot);+if(err)+unmap_kernel_range(ea,size);+returnerr;+}else{+unsignedlongi;++for(i=0;i<size;i+=PAGE_SIZE){+interr=map_kernel_page(ea+i,pa+i,prot);+if(WARN_ON_ONCE(err))/* Should clean up */+returnerr;+}
Same loop again.
What about not doing a radix specific function and just putting
something like below in the core ioremap_range() function ?
if (likely(slab_is_available()) && radix_enabled()) {
int err = ioremap_page_range(ea, ea + size, pa, prot);
if (err)
unmap_kernel_range(ea, size);
return err;
}
Because I'm pretty sure will more and more use ioremap_page_range().
@@ -108,7 +108,7 @@ unsigned long ioremap_bot;unsignedlongioremap_bot=IOREMAP_BASE;#endif-staticintioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,pgprot_tprot,intnid)+int__weakioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,pgprot_tprot,intnid)
Hum. Weak functions remain in unused in vmlinux unless
CONFIG_LD_DEAD_CODE_DATA_ELIMINATION is selected.
Also, they are some how dangerous because people might change them
without seeing that it is overridden for some particular configuration.
Christophe
From: Nicholas Piggin <npiggin@gmail.com> Date: 2019-06-19 04:06:57
Christophe Leroy's on June 11, 2019 4:46 pm:
Le 10/06/2019 à 05:08, Nicholas Piggin a écrit :
quoted
Radix can use ioremap_page_range for ioremap, after slab is available.
This makes it possible to enable huge ioremap mapping support.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/book3s/64/radix.h | 3 +++
arch/powerpc/mm/book3s64/pgtable.c | 21 +++++++++++++++++++++
arch/powerpc/mm/book3s64/radix_pgtable.c | 21 +++++++++++++++++++++
arch/powerpc/mm/pgtable_64.c | 2 +-
4 files changed, 46 insertions(+), 1 deletion(-)
@@ -450,3 +450,24 @@ int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,returntrue;}++intioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,pgprot_tprot,intnid)+{+unsignedlongi;++if(radix_enabled())+returnradix__ioremap_range(ea,pa,size,prot,nid);
This function looks pretty similar to the one in the previous patch.
Since radix_enabled() is available and return false for all other
subarches, I think the above could go in the generic ioremap_range(),
you'll only need to move the function declaration in a common file, for
instance asm/io.h
quoted
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ int err = map_kernel_page(ea + i, pa + i, prot);
+ if (err) {
+ if (slab_is_available())
+ unmap_kernel_range(ea, size);
+ else
+ WARN_ON_ONCE(1); /* Should clean up */
+ return err;
+ }
+ }
+
+ return 0;
+}
@@ -1122,3 +1123,23 @@ void radix__ptep_modify_prot_commit(struct vm_area_struct *vma,set_pte_at(mm,addr,ptep,pte);}++intradix__ioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,+pgprot_tprot,intnid)+{+if(likely(slab_is_available())){+interr=ioremap_page_range(ea,ea+size,pa,prot);+if(err)+unmap_kernel_range(ea,size);+returnerr;+}else{+unsignedlongi;++for(i=0;i<size;i+=PAGE_SIZE){+interr=map_kernel_page(ea+i,pa+i,prot);+if(WARN_ON_ONCE(err))/* Should clean up */+returnerr;+}
Same loop again.
What about not doing a radix specific function and just putting
something like below in the core ioremap_range() function ?
if (likely(slab_is_available()) && radix_enabled()) {
int err = ioremap_page_range(ea, ea + size, pa, prot);
if (err)
unmap_kernel_range(ea, size);
return err;
}
Because I'm pretty sure will more and more use ioremap_page_range().
Well I agree the duplication is not so nice, but it's convenient
to see what is going on for each MMU type.
There is a significant amount of churn that needs to be done in
this layer so I prefer to make it a bit simpler despite duplication.
I would like to remove the early ioremap or make it into its own
function. Re-implement map_kernel_page with ioremap_page_range,
allow page tables that don't use slab to avoid the early check,
unbolt the hptes mapped in early boot, etc.
I just wanted to escape out the 64s and hash/radix implementations
completely until that settles.
quoted
-static int ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size, pgprot_t prot, int nid)
+int __weak ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size, pgprot_t prot, int nid)
Hum. Weak functions remain in unused in vmlinux unless
CONFIG_LD_DEAD_CODE_DATA_ELIMINATION is selected.
Also, they are some how dangerous because people might change them
without seeing that it is overridden for some particular configuration.
Well you shouldn't assume that when you see a weak function, but
what's the preferred alternative? A config option?
Thanks,
Nick
@@ -1122,3 +1123,23 @@ void radix__ptep_modify_prot_commit(struct vm_area_struct *vma,set_pte_at(mm,addr,ptep,pte);}++intradix__ioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,+pgprot_tprot,intnid)+{+if(likely(slab_is_available())){+interr=ioremap_page_range(ea,ea+size,pa,prot);+if(err)+unmap_kernel_range(ea,size);+returnerr;+}else{+unsignedlongi;++for(i=0;i<size;i+=PAGE_SIZE){+interr=map_kernel_page(ea+i,pa+i,prot);+if(WARN_ON_ONCE(err))/* Should clean up */+returnerr;+}
Same loop again.
What about not doing a radix specific function and just putting
something like below in the core ioremap_range() function ?
if (likely(slab_is_available()) && radix_enabled()) {
int err = ioremap_page_range(ea, ea + size, pa, prot);
if (err)
unmap_kernel_range(ea, size);
return err;
}
Because I'm pretty sure will more and more use ioremap_page_range().
Well I agree the duplication is not so nice, but it's convenient
to see what is going on for each MMU type.
There is a significant amount of churn that needs to be done in
this layer so I prefer to make it a bit simpler despite duplication.
I would like to remove the early ioremap or make it into its own
function. Re-implement map_kernel_page with ioremap_page_range,
allow page tables that don't use slab to avoid the early check,
unbolt the hptes mapped in early boot, etc.
I just wanted to escape out the 64s and hash/radix implementations
completely until that settles.
I can understand the benefit in some situations but here I just can't.
And code duplication should be avoided as much as possible as it makes
code maintenance more difficult.
Here you have:
+static int ioremap_range(unsigned long ea, phys_addr_t pa, unsigned
long size, pgprot_t prot, int nid)
+{
+ unsigned long i;
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ int err = map_kernel_page(ea + i, pa + i, prot);
+ if (err) {
+ if (slab_is_available())
+ unmap_kernel_range(ea, size);
+ else
+ WARN_ON_ONCE(1); /* Should clean up */
+ return err;
+ }
+ }
+
+ return 0;
+}
You now create a new one in another file, that is almost identical:
+int ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size,
pgprot_t prot, int nid)
+{
+ unsigned long i;
+
+ if (radix_enabled())
+ return radix__ioremap_range(ea, pa, size, prot, nid);
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ int err = map_kernel_page(ea + i, pa + i, prot);
+ if (err) {
+ if (slab_is_available())
+ unmap_kernel_range(ea, size);
+ else
+ WARN_ON_ONCE(1); /* Should clean up */
+ return err;
+ }
+ }
+
+ return 0;
+}
Then you have to make the original one __weak.
Sorry I'm still having difficulties understanding what the benefit is.
radix_enabled() is defined for every platforms so could just add the
following on top of the existing ioremap_range() and voila.
+ if (radix_enabled())
+ return radix__ioremap_range(ea, pa, size, prot, nid);
And with that you wouldn't have the __weak stuff to handle.
quoted
quoted
-static int ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size, pgprot_t prot, int nid)
+int __weak ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size, pgprot_t prot, int nid)
Hum. Weak functions remain in unused in vmlinux unless
CONFIG_LD_DEAD_CODE_DATA_ELIMINATION is selected.
Also, they are some how dangerous because people might change them
without seeing that it is overridden for some particular configuration.
Well you shouldn't assume that when you see a weak function, but
what's the preferred alternative? A config option?
Yes you are right, nobody should assume that, but ...
But I think if the fonctions were really different, the preferred
alternative would be to move the original function into a file dedicated
to nohash64.
Christophe
@@ -1122,3 +1123,23 @@ void radix__ptep_modify_prot_commit(struct vm_area_struct *vma,set_pte_at(mm,addr,ptep,pte);}++intradix__ioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,+pgprot_tprot,intnid)+{+if(likely(slab_is_available())){+interr=ioremap_page_range(ea,ea+size,pa,prot);+if(err)+unmap_kernel_range(ea,size);+returnerr;+}else{+unsignedlongi;++for(i=0;i<size;i+=PAGE_SIZE){+interr=map_kernel_page(ea+i,pa+i,prot);+if(WARN_ON_ONCE(err))/* Should clean up */+returnerr;+}
Same loop again.
What about not doing a radix specific function and just putting
something like below in the core ioremap_range() function ?
if (likely(slab_is_available()) && radix_enabled()) {
int err = ioremap_page_range(ea, ea + size, pa, prot);
if (err)
unmap_kernel_range(ea, size);
return err;
}
Because I'm pretty sure will more and more use ioremap_page_range().
Well I agree the duplication is not so nice, but it's convenient
to see what is going on for each MMU type.
There is a significant amount of churn that needs to be done in
this layer so I prefer to make it a bit simpler despite duplication.
I would like to remove the early ioremap or make it into its own
function. Re-implement map_kernel_page with ioremap_page_range,
allow page tables that don't use slab to avoid the early check,
unbolt the hptes mapped in early boot, etc.
I just wanted to escape out the 64s and hash/radix implementations
completely until that settles.
I can understand the benefit in some situations but here I just can't.
And code duplication should be avoided as much as possible as it makes
code maintenance more difficult.
Here you have:
+static int ioremap_range(unsigned long ea, phys_addr_t pa, unsigned
long size, pgprot_t prot, int nid)
+{
+ unsigned long i;
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ int err = map_kernel_page(ea + i, pa + i, prot);
+ if (err) {
+ if (slab_is_available())
+ unmap_kernel_range(ea, size);
+ else
+ WARN_ON_ONCE(1); /* Should clean up */
+ return err;
+ }
+ }
+
+ return 0;
+}
You now create a new one in another file, that is almost identical:
+int ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size,
pgprot_t prot, int nid)
+{
+ unsigned long i;
+
+ if (radix_enabled())
+ return radix__ioremap_range(ea, pa, size, prot, nid);
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ int err = map_kernel_page(ea + i, pa + i, prot);
+ if (err) {
+ if (slab_is_available())
+ unmap_kernel_range(ea, size);
+ else
+ WARN_ON_ONCE(1); /* Should clean up */
+ return err;
+ }
+ }
+
+ return 0;
+}
Then you have to make the original one __weak.
Sorry I'm still having difficulties understanding what the benefit is.
radix_enabled() is defined for every platforms so could just add the
following on top of the existing ioremap_range() and voila.
+ if (radix_enabled())
+ return radix__ioremap_range(ea, pa, size, prot, nid);
And with that you wouldn't have the __weak stuff to handle.
I guess so. I don't really like radix_enabled escaping from 64s too
much though. I'll try to improve the code in follow ups if possible.
quoted
quoted
quoted
-static int ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size, pgprot_t prot, int nid)
+int __weak ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size, pgprot_t prot, int nid)
Hum. Weak functions remain in unused in vmlinux unless
CONFIG_LD_DEAD_CODE_DATA_ELIMINATION is selected.
Also, they are some how dangerous because people might change them
without seeing that it is overridden for some particular configuration.
Well you shouldn't assume that when you see a weak function, but
what's the preferred alternative? A config option?
Yes you are right, nobody should assume that, but ...
But I think if the fonctions were really different, the preferred
alternative would be to move the original function into a file dedicated
to nohash64.
Possibly we could do that, but we might be able to just collapse these
back to using generic ioremap_page_range.
Thanks,
Nick
I would like to remove the early ioremap or make it into its own
function. Re-implement map_kernel_page with ioremap_page_range,
allow page tables that don't use slab to avoid the early check,
unbolt the hptes mapped in early boot, etc.
Getting early ioremap out of the picture is a very good idea, it will
help making things more common between all platform types. Today we face
the fact that PPC32 allocates early io from the top of memory while
PPC64 allocates it from the bottom of memory.
Any idea on how to proceed ?
Christophe
From: Nicholas Piggin <npiggin@gmail.com> Date: 2019-06-24 03:14:49
Christophe Leroy's on June 20, 2019 2:25 am:
Le 19/06/2019 à 05:59, Nicholas Piggin a écrit :
quoted
Christophe Leroy's on June 11, 2019 4:46 pm:
quoted
Le 10/06/2019 à 05:08, Nicholas Piggin a écrit :
I would like to remove the early ioremap or make it into its own
function. Re-implement map_kernel_page with ioremap_page_range,
allow page tables that don't use slab to avoid the early check,
unbolt the hptes mapped in early boot, etc.
Getting early ioremap out of the picture is a very good idea, it will
help making things more common between all platform types. Today we face
the fact that PPC32 allocates early io from the top of memory while
PPC64 allocates it from the bottom of memory.
Any idea on how to proceed ?
I have to have a bit better look at other arches and our platform
code. Without having looked closely at all the details, I would hope
we could use GENERIC_EARLY_IOREMAP without too much pain.
Thanks,
Nick
I would like to remove the early ioremap or make it into its own
function. Re-implement map_kernel_page with ioremap_page_range,
allow page tables that don't use slab to avoid the early check,
unbolt the hptes mapped in early boot, etc.
Getting early ioremap out of the picture is a very good idea, it will
help making things more common between all platform types. Today we face
the fact that PPC32 allocates early io from the top of memory while
PPC64 allocates it from the bottom of memory.
Any idea on how to proceed ?
I have to have a bit better look at other arches and our platform
code. Without having looked closely at all the details, I would hope
we could use GENERIC_EARLY_IOREMAP without too much pain.
Good idea.
I have looked at it and implemented it for PPC32. In its own it works
well, now the challenge is to move all early call sites of ioremap() to
early_ioremap().
I point however is that early_ioremap() expects all maps being released
by the time we do paging_init(), whereas several of early PPC ioremap()
users never release the mapped area. I think we have to dig into this in
more details.
Christophe
From: Nicholas Piggin <npiggin@gmail.com> Date: 2019-06-10 03:15:56
This sets the HAVE_ARCH_HUGE_VMAP option, and defines the required
page table functions.
This enables huge (2MB and 1GB) ioremap mappings. I don't have a
benchmark for this change, but huge vmap will be used by a later core
kernel change to enable huge vmalloc memory mappings. This improves
cached `git diff` performance by about 5% on a 2-node POWER9 with 32MB
size dentry cache hash.
Profiling git diff dTLB misses with a vanilla kernel:
81.75% git [kernel.vmlinux] [k] __d_lookup_rcu
7.21% git [kernel.vmlinux] [k] strncpy_from_user
1.77% git [kernel.vmlinux] [k] find_get_entry
1.59% git [kernel.vmlinux] [k] kmem_cache_free
40,168 dTLB-miss
0.100342754 seconds time elapsed
With powerpc huge vmalloc:
2,987 dTLB-miss
0.095933138 seconds time elapsed
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
.../admin-guide/kernel-parameters.txt | 2 +-
arch/powerpc/Kconfig | 1 +
arch/powerpc/include/asm/book3s/64/pgtable.h | 8 ++
arch/powerpc/mm/book3s64/radix_pgtable.c | 100 ++++++++++++++++++
4 files changed, 110 insertions(+), 1 deletion(-)
@@ -1124,6 +1124,106 @@ void radix__ptep_modify_prot_commit(struct vm_area_struct *vma,set_pte_at(mm,addr,ptep,pte);}+int__initarch_ioremap_pud_supported(void)+{+/* HPT does not cope with large pages in the vmalloc area */+returnradix_enabled();+}++int__initarch_ioremap_pmd_supported(void)+{+returnradix_enabled();+}++intp4d_free_pud_page(p4d_t*p4d,unsignedlongaddr)+{+return0;+}++intpud_set_huge(pud_t*pud,phys_addr_taddr,pgprot_tprot)+{+pte_t*ptep=(pte_t*)pud;+pte_tnew_pud=pfn_pte(__phys_to_pfn(addr),prot);++if(!radix_enabled())+return0;++set_pte_at(&init_mm,0/* radix unused */,ptep,new_pud);++return1;+}++intpud_clear_huge(pud_t*pud)+{+if(pud_huge(*pud)){+pud_clear(pud);+return1;+}++return0;+}++intpud_free_pmd_page(pud_t*pud,unsignedlongaddr)+{+pmd_t*pmd;+inti;++pmd=(pmd_t*)pud_page_vaddr(*pud);+pud_clear(pud);++flush_tlb_kernel_range(addr,addr+PUD_SIZE);++for(i=0;i<PTRS_PER_PMD;i++){+if(!pmd_none(pmd[i])){+pte_t*pte;+pte=(pte_t*)pmd_page_vaddr(pmd[i]);++pte_free_kernel(&init_mm,pte);+}+}++pmd_free(&init_mm,pmd);++return1;+}++intpmd_set_huge(pmd_t*pmd,phys_addr_taddr,pgprot_tprot)+{+pte_t*ptep=(pte_t*)pmd;+pte_tnew_pmd=pfn_pte(__phys_to_pfn(addr),prot);++if(!radix_enabled())+return0;++set_pte_at(&init_mm,0/* radix unused */,ptep,new_pmd);++return1;+}++intpmd_clear_huge(pmd_t*pmd)+{+if(pmd_huge(*pmd)){+pmd_clear(pmd);+return1;+}++return0;+}++intpmd_free_pte_page(pmd_t*pmd,unsignedlongaddr)+{+pte_t*pte;++pte=(pte_t*)pmd_page_vaddr(*pmd);+pmd_clear(pmd);++flush_tlb_kernel_range(addr,addr+PMD_SIZE);++pte_free_kernel(&init_mm,pte);++return1;+}+intradix__ioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,pgprot_tprot,intnid){
__ioremap_at error handling is wonky, it requires caller to clean up
after it. Implement a helper that does the map and error cleanup and
remove the requirement from the caller.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
This series is a different approach to the problem, using the generic
ioremap_page_range directly which reduces added code, and moves
the radix specific code into radix files. Thanks to Christophe for
pointing out various problems with the previous patch.
arch/powerpc/mm/pgtable_64.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2019-06-19 04:12:00
Christophe Leroy's on June 11, 2019 4:28 pm:
Le 10/06/2019 à 05:08, Nicholas Piggin a écrit :
quoted
__ioremap_at error handling is wonky, it requires caller to clean up
after it. Implement a helper that does the map and error cleanup and
remove the requirement from the caller.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
This series is a different approach to the problem, using the generic
ioremap_page_range directly which reduces added code, and moves
the radix specific code into radix files. Thanks to Christophe for
pointing out various problems with the previous patch.
arch/powerpc/mm/pgtable_64.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
@@ -108,14 +108,30 @@ unsigned long ioremap_bot;unsignedlongioremap_bot=IOREMAP_BASE;#endif+staticintioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,pgprot_tprot,intnid)+{+unsignedlongi;++for(i=0;i<size;i+=PAGE_SIZE){+interr=map_kernel_page(ea+i,pa+i,prot);
Missing a blank line
quoted
+ if (err) {
I'd have done the following to reduce indentation depth
if (!err)
continue
I'll consider it, line lengths were not too bad.
quoted
+ if (slab_is_available())
+ unmap_kernel_range(ea, size);
Shouldn't it be unmap_kernel_range(ea, i) ?
I guess (i - PAGE_SIZE really), although the old code effectively did
the full range. As a "clean up" it may be better to avoid subtle
change in behaviour and do that in another patch?
Thanks,
Nick
__ioremap_at error handling is wonky, it requires caller to clean up
after it. Implement a helper that does the map and error cleanup and
remove the requirement from the caller.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
This series is a different approach to the problem, using the generic
ioremap_page_range directly which reduces added code, and moves
the radix specific code into radix files. Thanks to Christophe for
pointing out various problems with the previous patch.
arch/powerpc/mm/pgtable_64.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
@@ -108,14 +108,30 @@ unsigned long ioremap_bot;unsignedlongioremap_bot=IOREMAP_BASE;#endif+staticintioremap_range(unsignedlongea,phys_addr_tpa,unsignedlongsize,pgprot_tprot,intnid)+{+unsignedlongi;++for(i=0;i<size;i+=PAGE_SIZE){+interr=map_kernel_page(ea+i,pa+i,prot);
Missing a blank line
quoted
+ if (err) {
I'd have done the following to reduce indentation depth
if (!err)
continue
I'll consider it, line lengths were not too bad.
quoted
quoted
+ if (slab_is_available())
+ unmap_kernel_range(ea, size);
Shouldn't it be unmap_kernel_range(ea, i) ?
I guess (i - PAGE_SIZE really), although the old code effectively did
the full range. As a "clean up" it may be better to avoid subtle
change in behaviour and do that in another patch?
Not sure we have to do it in another patch.
Previous code was doing full range because it was done at upper level so
it didn't know the boundaries. You are creating a nice brand new
function that have all necessary information, so why not make it right
from the start ?
Christophe
From: Michael Ellerman <hidden> Date: 2019-06-30 08:45:37
On Mon, 2019-06-10 at 03:08:16 UTC, Nicholas Piggin wrote:
__ioremap_at error handling is wonky, it requires caller to clean up
after it. Implement a helper that does the map and error cleanup and
remove the requirement from the caller.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Hi Nick,
Le 10/06/2019 à 05:08, Nicholas Piggin a écrit :
quoted hunk
__ioremap_at error handling is wonky, it requires caller to clean up
after it. Implement a helper that does the map and error cleanup and
remove the requirement from the caller.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
This series is a different approach to the problem, using the generic
ioremap_page_range directly which reduces added code, and moves
the radix specific code into radix files. Thanks to Christophe for
pointing out various problems with the previous patch.
arch/powerpc/mm/pgtable_64.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
@@ -182,8 +197,6 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, area->phys_addr = paligned; ret = __ioremap_at(paligned, area->addr, size, prot);- if (!ret)- vunmap(area->addr);
AFAICS, ioremap_range() calls unmap_kernel_range() in the error case,
but I can't see that that function does the vunmap(), does it ?. If not,
who frees the area allocated by __get_vm_area_caller() ?
Christophe
From: Nicholas Piggin <npiggin@gmail.com> Date: 2019-08-27 08:25:00
Christophe Leroy's on August 20, 2019 5:44 pm:
Hi Nick,
Le 10/06/2019 à 05:08, Nicholas Piggin a écrit :
quoted
__ioremap_at error handling is wonky, it requires caller to clean up
after it. Implement a helper that does the map and error cleanup and
remove the requirement from the caller.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
This series is a different approach to the problem, using the generic
ioremap_page_range directly which reduces added code, and moves
the radix specific code into radix files. Thanks to Christophe for
pointing out various problems with the previous patch.
arch/powerpc/mm/pgtable_64.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
@@ -182,8 +197,6 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, area->phys_addr = paligned; ret = __ioremap_at(paligned, area->addr, size, prot);- if (!ret)- vunmap(area->addr);
AFAICS, ioremap_range() calls unmap_kernel_range() in the error case,
but I can't see that that function does the vunmap(), does it ?. If not,
who frees the area allocated by __get_vm_area_caller() ?
Oh good catch, I guess we need to keep a free_vm_area here.
Thanks,
Nick