From 459c1517f9873b198af7dcded8d8cc84749bbb69 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 8 Jan 2011 11:49:20 +0000 Subject: ARM: DMA: top-down allocation in DMA coherent region Achieve better usage of the DMA coherent region by doing top-down allocation rather than bottom up. If we ask for a 128kB allocation, this will be aligned to 128kB and satisfied from the very bottom address. If we then ask for a 600kB allocation, this will be aligned to 1MB, and we will have a 896kB hole. Performing top-down allocation resolves this by allocating the 128kB at the very top, and then the 600kB can come in below it without any unnecessary wastage. This problem was reported by Janusz Krzysztofik, who had 2 x 128kB + 1 x 640kB allocations which wouldn't fit into 1MB. Tested-by: Janusz Krzysztofik Signed-off-by: Russell King --- arch/arm/mm/vmregion.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/vmregion.c b/arch/arm/mm/vmregion.c index 935993e1b1ef..036fdbfdd62f 100644 --- a/arch/arm/mm/vmregion.c +++ b/arch/arm/mm/vmregion.c @@ -38,7 +38,7 @@ struct arm_vmregion * arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align, size_t size, gfp_t gfp) { - unsigned long addr = head->vm_start, end = head->vm_end - size; + unsigned long start = head->vm_start, addr = head->vm_end; unsigned long flags; struct arm_vmregion *c, *new; @@ -54,21 +54,20 @@ arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align, spin_lock_irqsave(&head->vm_lock, flags); - list_for_each_entry(c, &head->vm_list, vm_list) { - if ((addr + size) < addr) - goto nospc; - if ((addr + size) <= c->vm_start) + addr = rounddown(addr - size, align); + list_for_each_entry_reverse(c, &head->vm_list, vm_list) { + if (addr >= c->vm_end) goto found; - addr = ALIGN(c->vm_end, align); - if (addr > end) + addr = rounddown(c->vm_start - size, align); + if (addr < start) goto nospc; } found: /* - * Insert this entry _before_ the one we found. + * Insert this entry after the one we found. */ - list_add_tail(&new->vm_list, &c->vm_list); + list_add(&new->vm_list, &c->vm_list); new->vm_start = addr; new->vm_end = addr + size; new->vm_active = 1; -- cgit From aaa50048f6ce44af66ce0389d4cc6a8348333271 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 25 Jan 2011 21:35:38 +0100 Subject: ARM: 6639/1: allow highmem on SMP platforms without h/w TLB ops broadcast In commit e616c591405c168f6dc3dfd1221e105adfe49b8d, highmem support was deactivated for SMP platforms without hardware TLB ops broadcast because usage of kmap_high_get() requires that IRQs be disabled when kmap_lock is locked which is incompatible with the IPI mechanism used by the software TLB ops broadcast invoked through flush_all_zero_pkmaps(). The reason for kmap_high_get() is to ensure that the currently kmap'd page usage count does not decrease to zero while we're using its existing virtual mapping in an atomic context. With a VIVT cache this is essential to do due to cache coherency issues, but with a VIPT cache this is only an optimization so not to pay the price of establishing a second mapping if an existing one can be used. However, on VIPT platforms without hardware TLB maintenance we can give up on that optimization in order to be able to use highmem. From ARMv7 onwards the TLB ops are broadcasted in hardware, so let's disable ARCH_NEEDS_KMAP_HIGH_GET only when CONFIG_SMP and CONFIG_CPU_TLB_V6 are defined. Signed-off-by: Nicolas Pitre Tested-by: Saeed Bishara Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 3c67e92f7d59..ff7b43b5885a 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -827,16 +827,6 @@ static void __init sanity_check_meminfo(void) * rather difficult. */ reason = "with VIPT aliasing cache"; - } else if (is_smp() && tlb_ops_need_broadcast()) { - /* - * kmap_high needs to occasionally flush TLB entries, - * however, if the TLB entries need to be broadcast - * we may deadlock: - * kmap_high(irqs off)->flush_all_zero_pkmaps-> - * flush_tlb_kernel_range->smp_call_function_many - * (must not be called with irqs off) - */ - reason = "without hardware TLB ops broadcasting"; } if (reason) { printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n", -- cgit From 5637a126482026b37d426d76e1b18f748f309aaa Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 14 Feb 2011 15:55:45 +0000 Subject: ARM: move L1_CACHE_SHIFT_6 to mm/Kconfig Move L1_CACHE_SHIFT related options together, rather than spreading them across two separate Kconfig files. Signed-off-by: Russell King --- arch/arm/mm/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 9d30c6f804b9..a51661be1412 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -845,6 +845,11 @@ config CACHE_XSC3L2 help This option enables the L2 cache on XScale3. +config ARM_L1_CACHE_SHIFT_6 + bool + help + Setting ARM L1 cache line size to 64 Bytes. + config ARM_L1_CACHE_SHIFT int default 6 if ARM_L1_CACHE_SHIFT_6 -- cgit From 2839e06c95d12ada034cf9b63da60334c7c6358b Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Tue, 8 Mar 2011 06:59:54 +0100 Subject: ARM: 6795/1: l2x0: Errata fix for flush by Way operation can cause data corrupti PL310 implements the Clean & Invalidate by Way L2 cache maintenance operation (offset 0x7FC). This operation runs in background so that PL310 can handle normal accesses while it is in progress. Under very rare circumstances, due to this erratum, write data can be lost when PL310 treats a cacheable write transaction during a Clean & Invalidate by Way operation. Workaround: Disable Write-Back and Cache Linefill (Debug Control Register) Clean & Invalidate by Way (0x7FC) Re-enable Write-Back and Cache Linefill (Debug Control Register) This patch also removes any OMAP dependency on PL310 Errata's Signed-off-by: Santosh Shilimkar Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 170c9bb95866..803bce8845a7 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -67,18 +67,24 @@ static inline void l2x0_inv_line(unsigned long addr) writel_relaxed(addr, base + L2X0_INV_LINE_PA); } -#ifdef CONFIG_PL310_ERRATA_588369 -static void debug_writel(unsigned long val) -{ - extern void omap_smc1(u32 fn, u32 arg); +#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) - /* - * Texas Instrument secure monitor api to modify the - * PL310 Debug Control Register. - */ - omap_smc1(0x100, val); +#define debug_writel(val) outer_cache.set_debug(val) + +static void l2x0_set_debug(unsigned long val) +{ + writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); } +#else +/* Optimised out for non-errata case */ +static inline void debug_writel(unsigned long val) +{ +} + +#define l2x0_set_debug NULL +#endif +#ifdef CONFIG_PL310_ERRATA_588369 static inline void l2x0_flush_line(unsigned long addr) { void __iomem *base = l2x0_base; @@ -91,11 +97,6 @@ static inline void l2x0_flush_line(unsigned long addr) } #else -/* Optimised out for non-errata case */ -static inline void debug_writel(unsigned long val) -{ -} - static inline void l2x0_flush_line(unsigned long addr) { void __iomem *base = l2x0_base; @@ -119,9 +120,11 @@ static void l2x0_flush_all(void) /* clean all ways */ spin_lock_irqsave(&l2x0_lock, flags); + debug_writel(0x03); writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY); cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask); cache_sync(); + debug_writel(0x00); spin_unlock_irqrestore(&l2x0_lock, flags); } @@ -329,6 +332,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) outer_cache.flush_all = l2x0_flush_all; outer_cache.inv_all = l2x0_inv_all; outer_cache.disable = l2x0_disable; + outer_cache.set_debug = l2x0_set_debug; printk(KERN_INFO "%s cache controller enabled\n", type); printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n", -- cgit