From dbfbf60f4a6b058b873b0d37e272fc3bd2f1356d Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Wed, 27 May 2015 14:15:08 +0100 Subject: MIPS: tlb-r3k: Also invalidate wired TLB entries on boot Most R3k processor implementations have their 8 first TLB entries fixed as wired, so we always skip them in TLB invalidation. That however means any leftover entries present there at boot will stay throughout the life of the kernel, unless replaced with new ones. So rename `local_flush_tlb_all' to `local_flush_tlb_from' and make it accept the TLB entry to start from. Then use 0 initially at bootstrap, and the first regular entry later on, bypassing any wired entries. Wrap the latter arrangement into a new `local_flush_tlb_all' entry point. There is no need to disable interrupts in the call made from `tlb_init' because it's made before the interrupt subsystem has been initialised; this is also true for secondary processors, should we ever support R3k SMP. So move this piece of code to new `local_flush_tlb_all'. Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/10194/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlb-r3k.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'arch/mips/mm') diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index 4094bbd42adf..b34b75d62a73 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -39,20 +39,12 @@ extern void build_tlb_refill_handler(void); int r3k_have_wired_reg; /* should be in cpu_data? */ /* TLB operations. */ -void local_flush_tlb_all(void) +static void local_flush_tlb_from(int entry) { - unsigned long flags; unsigned long old_ctx; - int entry; -#ifdef DEBUG_TLB - printk("[tlball]"); -#endif - - local_irq_save(flags); old_ctx = read_c0_entryhi() & ASID_MASK; write_c0_entrylo0(0); - entry = r3k_have_wired_reg ? read_c0_wired() : 8; for (; entry < current_cpu_data.tlbsize; entry++) { write_c0_index(entry << 8); write_c0_entryhi((entry | 0x80000) << 12); @@ -60,6 +52,17 @@ void local_flush_tlb_all(void) tlb_write_indexed(); } write_c0_entryhi(old_ctx); +} + +void local_flush_tlb_all(void) +{ + unsigned long flags; + +#ifdef DEBUG_TLB + printk("[tlball]"); +#endif + local_irq_save(flags); + local_flush_tlb_from(r3k_have_wired_reg ? read_c0_wired() : 8); local_irq_restore(flags); } @@ -277,7 +280,6 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, void tlb_init(void) { - local_flush_tlb_all(); - + local_flush_tlb_from(0); build_tlb_refill_handler(); } -- cgit v1.2.1 From 3bcb03f3a7160e411c5f335028a5c70b32f0edb7 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Wed, 27 May 2015 14:15:15 +0100 Subject: MIPS: tlb-r3k: Move CP0.Wired register initialisation to `tlb_init' Move the initialisation of the CP0.Wired register implemented by Toshiba TX3922 and TX3927 processors from `tx39_cache_init' to `tlb_init' where it belongs, correcting code structure and making sure initialisation does not rely on `tx39_cache_init' being called before `tlb_init' to work correctly. Make `r3k_have_wired_reg' static as it's no longer externally referred to; remove a stale declaration too. Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/10195/ Signed-off-by: Ralf Baechle --- arch/mips/mm/c-tx39.c | 4 ---- arch/mips/mm/tlb-r3k.c | 9 ++++++++- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'arch/mips/mm') diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index 8d909dbbf37f..596e18458e04 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -28,8 +28,6 @@ static unsigned long icache_size, dcache_size; /* Size in bytes */ #include -extern int r3k_have_wired_reg; /* in r3k-tlb.c */ - /* This sequence is required to ensure icache is disabled immediately */ #define TX39_STOP_STREAMING() \ __asm__ __volatile__( \ @@ -383,8 +381,6 @@ void tx39_cache_init(void) case CPU_TX3927: default: /* TX39/H2,H3 core (writeback 2way-set-associative cache) */ - r3k_have_wired_reg = 1; - write_c0_wired(0); /* set 8 on reset... */ /* board-dependent init code may set WBON */ __flush_cache_vmap = tx39__flush_cache_vmap; diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index b34b75d62a73..49b7132069d0 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -36,7 +36,7 @@ extern void build_tlb_refill_handler(void); "nop\n\t" \ ".set pop\n\t") -int r3k_have_wired_reg; /* should be in cpu_data? */ +static int r3k_have_wired_reg; /* Should be in cpu_data? */ /* TLB operations. */ static void local_flush_tlb_from(int entry) @@ -280,6 +280,13 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, void tlb_init(void) { + switch (current_cpu_type()) { + case CPU_TX3922: + case CPU_TX3927: + r3k_have_wired_reg = 1; + write_c0_wired(0); /* Set to 8 on reset... */ + break; + } local_flush_tlb_from(0); build_tlb_refill_handler(); } -- cgit v1.2.1 From 9a20b09285bbd75ccc2ca78233241f8e31d54a28 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Wed, 27 May 2015 14:15:20 +0100 Subject: MIPS: tlb-r3k: Optimise a TLBWI barrier in TLB invalidation Replace an explicit barrier with a useful processor instruction in TLB invalidation, following several other such cases elsewhere in `tlb-r3k.c'. Signed-off-by: Maciej W. Rozycki Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/10196/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlb-r3k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mips/mm') diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index 49b7132069d0..2b75b8f880ed 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -45,10 +45,10 @@ static void local_flush_tlb_from(int entry) old_ctx = read_c0_entryhi() & ASID_MASK; write_c0_entrylo0(0); - for (; entry < current_cpu_data.tlbsize; entry++) { + while (entry < current_cpu_data.tlbsize) { write_c0_index(entry << 8); write_c0_entryhi((entry | 0x80000) << 12); - BARRIER; + entry++; /* BARRIER */ tlb_write_indexed(); } write_c0_entryhi(old_ctx); -- cgit v1.2.1 From b1f7e1129097cdb5cf2d6ef5d365dc94d13e3c76 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 27 Apr 2015 18:47:56 -0400 Subject: MIPS: BCM77xx: Remove legacy __cpuinit{,data} sections that crept in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We removed __cpuinit support (leaving no-op stubs) quite some time ago. However a few more crept in as of commit 6ee1d93455384cef8a0426effe85da2 ("MIPS: BCM47XX: Detect more then 128 MiB of RAM (HIGHMEM)") Since we want to clobber the stubs soon, get this removed now. Signed-off-by: Paul Gortmaker Cc: Rafał Miłecki Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/9892/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlb-r4k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/mm') diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 08318ecb803a..5037d5868cef 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -423,7 +423,7 @@ int __init has_transparent_hugepage(void) * lifetime of the system */ -int temp_tlb_entry __cpuinitdata; +int temp_tlb_entry; __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) -- cgit v1.2.1 From 9a8f4ea03462f2364a1b1a82af27672f2f366eaf Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 27 Apr 2015 18:47:57 -0400 Subject: MIPS: c-r4k: Remove legacy __cpuinit section that crept in We removed __cpuinit support (leaving no-op stubs) quite some time ago. However a new instance was added in commit 4caa906ee949b7002cc1558bbe3744 ("MIPS: mm: c-r4k: Build EVA {d,i}cache flushing functions") Since we want to clobber the stubs soon, get this removed now. Signed-off-by: Paul Gortmaker Cc: Leonid Yegoshin Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/9893/ Signed-off-by: Ralf Baechle --- arch/mips/mm/c-r4k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/mm') diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 2e03ab173591..7f660dc67596 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -295,7 +295,7 @@ static void r4k_blast_icache_page_setup(void) static void (*r4k_blast_icache_user_page)(unsigned long addr); -static void __cpuinit r4k_blast_icache_user_page_setup(void) +static void r4k_blast_icache_user_page_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); -- cgit v1.2.1 From a2d25e63ee50e8a09056e206a27512e3ea85b480 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 27 Apr 2015 18:47:59 -0400 Subject: MIPS: tlbex.c: Remove new instance of __cpuinitdata that crept back in We removed __cpuinit support (leaving no-op stubs) quite some time ago. However a new instance was added in commit c5b367835cfc7a8ef53b9670a409ff ("MIPS: Add support for XPA.") Since we want to clobber the stubs soon, get this removed now. Signed-off-by: Paul Gortmaker Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/9894/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/mm') diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 97c87027c17f..d7db82c3fbce 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -35,7 +35,7 @@ #include #include -static int __cpuinitdata mips_xpa_disabled; +static int mips_xpa_disabled; static int __init xpa_disable(char *s) { -- cgit v1.2.1 From a3ae565a130a4f34f4a3f45f72c2e8fd8b402b8c Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 27 Apr 2015 15:07:17 +0100 Subject: MIPS: tlbex: Fix broken offsets on r2 without XPA Commit c5b367835cfc ("MIPS: Add support for XPA.") changed build_pte_present() and build_pte_writable() to assume a constant offset of _PAGE_READ and _PAGE_WRITE relative to _PAGE_PRESENT, however this is no longer true for some MIPS32R2 builds since commit be0c37c985ed ("MIPS: Rearrange PTE bits into fixed positions.") which moved the _PAGE_READ PTE bit away from the _PAGE_PRESENT bit, with the _PAGE_WRITE bit falling into its place. Make use of the _PAGE_READ and _PAGE_WRITE definitions to calculate the correct mask to apply instead of hard coding 3 (for _PAGE_PRESENT | _PAGE_READ) or 5 (for _PAGE_PRESENT | _PAGE_WRITE). Fixes: c5b367835cfc ("MIPS: Add support for XPA.") Signed-off-by: James Hogan Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/9888/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'arch/mips/mm') diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index d7db82c3fbce..50292878384c 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1623,8 +1623,10 @@ build_pte_present(u32 **p, struct uasm_reloc **r, } } else { uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); - uasm_i_andi(p, t, t, 3); - uasm_i_xori(p, t, t, 3); + uasm_i_andi(p, t, t, + (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); + uasm_i_xori(p, t, t, + (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); uasm_il_bnez(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ @@ -1654,8 +1656,10 @@ build_pte_writable(u32 **p, struct uasm_reloc **r, int t = scratch >= 0 ? scratch : pte; uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); - uasm_i_andi(p, t, t, 5); - uasm_i_xori(p, t, t, 5); + uasm_i_andi(p, t, t, + (_PAGE_PRESENT | _PAGE_WRITE) >> _PAGE_PRESENT_SHIFT); + uasm_i_xori(p, t, t, + (_PAGE_PRESENT | _PAGE_WRITE) >> _PAGE_PRESENT_SHIFT); uasm_il_bnez(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ -- cgit v1.2.1 From 8fe4908b837e848efd95c2a1210ec67d48fbe874 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 27 Apr 2015 15:07:18 +0100 Subject: MIPS: tlbex: Avoid unnecessary _PAGE_PRESENT shifts Commit c5b367835cfc ("MIPS: Add support for XPA.") added generation of a shift by _PAGE_PRESENT_SHIFT in build_pte_present() and build_pte_writable(), however except for the XPA case this is always zero making it unnecessary. Make the shift conditional upon _PAGE_PRESENT_SHIFT being non-zero to save an instruction in those cases. Fixes: c5b367835cfc ("MIPS: Add support for XPA.") Signed-off-by: James Hogan Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/9889/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'arch/mips/mm') diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 50292878384c..323d1d302f2b 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1608,22 +1608,29 @@ build_pte_present(u32 **p, struct uasm_reloc **r, int pte, int ptr, int scratch, enum label_id lid) { int t = scratch >= 0 ? scratch : pte; + int cur = pte; if (cpu_has_rixi) { if (use_bbit_insns()) { uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid); uasm_i_nop(p); } else { - uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); - uasm_i_andi(p, t, t, 1); + if (_PAGE_PRESENT_SHIFT) { + uasm_i_srl(p, t, cur, _PAGE_PRESENT_SHIFT); + cur = t; + } + uasm_i_andi(p, t, cur, 1); uasm_il_beqz(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ iPTE_LW(p, pte, ptr); } } else { - uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); - uasm_i_andi(p, t, t, + if (_PAGE_PRESENT_SHIFT) { + uasm_i_srl(p, t, cur, _PAGE_PRESENT_SHIFT); + cur = t; + } + uasm_i_andi(p, t, cur, (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); uasm_i_xori(p, t, t, (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); @@ -1654,9 +1661,13 @@ build_pte_writable(u32 **p, struct uasm_reloc **r, enum label_id lid) { int t = scratch >= 0 ? scratch : pte; + int cur = pte; - uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); - uasm_i_andi(p, t, t, + if (_PAGE_PRESENT_SHIFT) { + uasm_i_srl(p, t, cur, _PAGE_PRESENT_SHIFT); + cur = t; + } + uasm_i_andi(p, t, cur, (_PAGE_PRESENT | _PAGE_WRITE) >> _PAGE_PRESENT_SHIFT); uasm_i_xori(p, t, t, (_PAGE_PRESENT | _PAGE_WRITE) >> _PAGE_PRESENT_SHIFT); -- cgit v1.2.1 From 1e51714c81e11bd0ffbb2b0724a1f66ce58608a5 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 1 May 2015 22:56:38 +0900 Subject: MIPS: use for_each_sg() This replaces the plain loop over the sglist array with for_each_sg() macro which consists of sg_next() function calls. Since MIPS doesn't select ARCH_HAS_SG_CHAIN, it is not necessary to use for_each_sg() in order to loop over each sg element. But this can help find problems with drivers that do not properly initialize their sg tables when CONFIG_DEBUG_SG is enabled. Signed-off-by: Akinobu Mita Cc: akpm@linux-foundation.org Cc: linux-mips@linux-mips.org Cc: linux-arch@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/9930/ Signed-off-by: Ralf Baechle --- arch/mips/mm/dma-default.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'arch/mips/mm') diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 609d1241b0c4..eeaf0245c3b1 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -262,12 +262,13 @@ static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, plat_unmap_dma_mem(dev, dma_addr, size, direction); } -static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg, +static int mips_dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction, struct dma_attrs *attrs) { int i; + struct scatterlist *sg; - for (i = 0; i < nents; i++, sg++) { + for_each_sg(sglist, sg, nents, i) { if (!plat_device_is_coherent(dev)) __dma_sync(sg_page(sg), sg->offset, sg->length, direction); @@ -291,13 +292,14 @@ static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page, return plat_map_dma_mem_page(dev, page) + offset; } -static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg, +static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, int nhwentries, enum dma_data_direction direction, struct dma_attrs *attrs) { int i; + struct scatterlist *sg; - for (i = 0; i < nhwentries; i++, sg++) { + for_each_sg(sglist, sg, nhwentries, i) { if (!plat_device_is_coherent(dev) && direction != DMA_TO_DEVICE) __dma_sync(sg_page(sg), sg->offset, sg->length, @@ -324,26 +326,34 @@ static void mips_dma_sync_single_for_device(struct device *dev, } static void mips_dma_sync_sg_for_cpu(struct device *dev, - struct scatterlist *sg, int nelems, enum dma_data_direction direction) + struct scatterlist *sglist, int nelems, + enum dma_data_direction direction) { int i; + struct scatterlist *sg; - if (cpu_needs_post_dma_flush(dev)) - for (i = 0; i < nelems; i++, sg++) + if (cpu_needs_post_dma_flush(dev)) { + for_each_sg(sglist, sg, nelems, i) { __dma_sync(sg_page(sg), sg->offset, sg->length, direction); + } + } plat_post_dma_flush(dev); } static void mips_dma_sync_sg_for_device(struct device *dev, - struct scatterlist *sg, int nelems, enum dma_data_direction direction) + struct scatterlist *sglist, int nelems, + enum dma_data_direction direction) { int i; + struct scatterlist *sg; - if (!plat_device_is_coherent(dev)) - for (i = 0; i < nelems; i++, sg++) + if (!plat_device_is_coherent(dev)) { + for_each_sg(sglist, sg, nelems, i) { __dma_sync(sg_page(sg), sg->offset, sg->length, direction); + } + } } int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) -- cgit v1.2.1