diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-08-27 22:39:09 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-09-20 23:33:38 +0100 |
commit | de8e71ca4f2e17329f6718ae88d5c8336cb249ee (patch) | |
tree | cec0f26c5f4c9efd601edc1ac716aed168f65e1f /arch/arm/kernel | |
parent | e8ce0eb5e2254b85415e4b58e73f24a5d13846a1 (diff) | |
download | blackbird-op-linux-de8e71ca4f2e17329f6718ae88d5c8336cb249ee.tar.gz blackbird-op-linux-de8e71ca4f2e17329f6718ae88d5c8336cb249ee.zip |
ARM: pm: only use preallocated page table during resume
Only use the preallocated page table during the resume, not while
suspending. This avoids the overhead of having to switch unnecessarily
to the resume page table in the suspend path.
Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Tested-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/sleep.S | 19 | ||||
-rw-r--r-- | arch/arm/kernel/suspend.c | 17 |
2 files changed, 19 insertions, 17 deletions
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S index 8cf13de1e368..25d42dfb0a92 100644 --- a/arch/arm/kernel/sleep.S +++ b/arch/arm/kernel/sleep.S @@ -9,12 +9,14 @@ /* * Save CPU state for a suspend + * r0 = phys addr of temporary page tables * r1 = v:p offset * r2 = suspend function arg0 * r3 = suspend function */ ENTRY(__cpu_suspend) stmfd sp!, {r4 - r11, lr} + mov r4, r0 #ifdef MULTI_CPU ldr r10, =processor ldr r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state @@ -27,7 +29,7 @@ ENTRY(__cpu_suspend) sub sp, sp, r5 @ allocate CPU state on stack mov r0, sp @ save pointer to CPU save block add ip, ip, r1 @ convert resume fn to phys - stmfd sp!, {r6, ip} @ save virt SP, phys resume fn + stmfd sp!, {r4, r6, ip} @ save phys pgd, virt SP, phys resume fn ldr r5, =sleep_save_sp add r6, sp, r1 @ convert SP to phys stmfd sp!, {r2, r3} @ save suspend func arg and pointer @@ -60,7 +62,7 @@ ENDPROC(__cpu_suspend) .ltorg cpu_suspend_abort: - ldmia sp!, {r2 - r3} @ pop virt SP, phys resume fn + ldmia sp!, {r1 - r3} @ pop phys pgd, virt SP, phys resume fn teq r0, #0 moveq r0, #1 @ force non-zero value mov sp, r2 @@ -69,9 +71,6 @@ ENDPROC(cpu_suspend_abort) /* * r0 = control register value - * r1 = v:p offset (preserved by cpu_do_resume) - * r2 = phys page table base - * r3 = L1 section flags */ ENTRY(cpu_resume_mmu) ldr r3, =cpu_resume_after_mmu @@ -112,11 +111,11 @@ ENTRY(cpu_resume) ldr r0, sleep_save_sp @ stack phys addr #endif setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off - @ load stack, resume fn - ARM( ldmia r0!, {sp, pc} ) -THUMB( ldmia r0!, {r2, r3} ) -THUMB( mov sp, r2 ) -THUMB( bx r3 ) + @ load phys pgd, stack, resume fn + ARM( ldmia r0!, {r1, sp, pc} ) +THUMB( ldmia r0!, {r1, r2, r3} ) +THUMB( mov sp, r2 ) +THUMB( bx r3 ) ENDPROC(cpu_resume) sleep_save_sp: diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index 0a33f109549d..2beda56e4574 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c @@ -24,14 +24,17 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) return -EINVAL; /* - * Temporarily switch the page tables to our suspend page - * tables, which contain the temporary identity mapping - * required for resuming. + * Provide a temporary page table with an identity mapping for + * the MMU-enable code, required for resuming. On successful + * resume (indicated by a zero return code), we need to switch + * back to the correct page tables. */ - cpu_switch_mm(suspend_pgd, mm); - ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn); - cpu_switch_mm(mm->pgd, mm); - local_flush_tlb_all(); + ret = __cpu_suspend(virt_to_phys(suspend_pgd), + PHYS_OFFSET - PAGE_OFFSET, arg, fn); + if (ret == 0) { + cpu_switch_mm(mm->pgd, mm); + local_flush_tlb_all(); + } return ret; } |