aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig4
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/entry-common.S4
-rw-r--r--arch/arm/kernel/sys_arm.c10
-rw-r--r--arch/arm/mach-pxa/time.c58
-rw-r--r--arch/arm/mach-sa1100/time.c68
-rw-r--r--arch/arm/mm/mm-armv.c26
-rw-r--r--include/asm-arm/unistd.h2
8 files changed, 143 insertions, 31 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4bf0e8737e1f..68dfdba71d74 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -365,8 +365,8 @@ config NO_IDLE_HZ
Please note that dynamic tick may affect the accuracy of
timekeeping on some platforms depending on the implementation.
- Currently at least OMAP platform is known to have accurate
- timekeeping with dynamic tick.
+ Currently at least OMAP, PXA2xx and SA11x0 platforms are known
+ to have accurate timekeeping with dynamic tick.
config ARCH_DISCONTIGMEM_ENABLE
bool
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 2b6b4c786e65..db07ce42b3b2 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -284,7 +284,7 @@ __syscall_start:
.long sys_fstatfs64
.long sys_tgkill
.long sys_utimes
-/* 270 */ .long sys_fadvise64_64
+/* 270 */ .long sys_arm_fadvise64_64_wrapper
.long sys_pciconfig_iobase
.long sys_pciconfig_read
.long sys_pciconfig_write
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 3f8d0e3aefab..6281d488ac97 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -265,6 +265,10 @@ sys_futex_wrapper:
str r5, [sp, #4] @ push sixth arg
b sys_futex
+sys_arm_fadvise64_64_wrapper:
+ str r5, [sp, #4] @ push r5 to stack
+ b sys_arm_fadvise64_64
+
/*
* Note: off_4k (r5) is always units of 4K. If we can't do the requested
* offset, we return EINVAL.
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index f897ce2ccf0d..42629ff84f5a 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -311,3 +311,13 @@ long execve(const char *filename, char **argv, char **envp)
return ret;
}
EXPORT_SYMBOL(execve);
+
+/*
+ * Since loff_t is a 64 bit type we avoid a lot of ABI hastle
+ * with a different argument ordering.
+ */
+asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
+ loff_t offset, loff_t len)
+{
+ return sys_fadvise64_64(fd, offset, len, advice);
+}
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 6e5202154f91..7dad3f1465e0 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -70,6 +70,11 @@ static unsigned long pxa_gettimeoffset (void)
return usec;
}
+#ifdef CONFIG_NO_IDLE_HZ
+static unsigned long initial_match;
+static int match_posponed;
+#endif
+
static irqreturn_t
pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -77,11 +82,19 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
write_seqlock(&xtime_lock);
+#ifdef CONFIG_NO_IDLE_HZ
+ if (match_posponed) {
+ match_posponed = 0;
+ OSMR0 = initial_match;
+ }
+#endif
+
/* Loop until we get ahead of the free running timer.
* This ensures an exact clock tick count and time accuracy.
- * IRQs are disabled inside the loop to ensure coherence between
- * lost_ticks (updated in do_timer()) and the match reg value, so we
- * can use do_gettimeofday() from interrupt handlers.
+ * Since IRQs are disabled at this point, coherence between
+ * lost_ticks(updated in do_timer()) and the match reg value is
+ * ensured, hence we can use do_gettimeofday() from interrupt
+ * handlers.
*
* HACK ALERT: it seems that the PXA timer regs aren't updated right
* away in all cases when a write occurs. We therefore compare with
@@ -126,6 +139,42 @@ static void __init pxa_timer_init(void)
OSCR = 0; /* initialize free-running timer, force first match */
}
+#ifdef CONFIG_NO_IDLE_HZ
+static int pxa_dyn_tick_enable_disable(void)
+{
+ /* nothing to do */
+ return 0;
+}
+
+static void pxa_dyn_tick_reprogram(unsigned long ticks)
+{
+ if (ticks > 1) {
+ initial_match = OSMR0;
+ OSMR0 = initial_match + ticks * LATCH;
+ match_posponed = 1;
+ }
+}
+
+static irqreturn_t
+pxa_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (match_posponed) {
+ match_posponed = 0;
+ OSMR0 = initial_match;
+ if ( (signed long)(initial_match - OSCR) <= 8 )
+ return pxa_timer_interrupt(irq, dev_id, regs);
+ }
+ return IRQ_NONE;
+}
+
+static struct dyn_tick_timer pxa_dyn_tick = {
+ .enable = pxa_dyn_tick_enable_disable,
+ .disable = pxa_dyn_tick_enable_disable,
+ .reprogram = pxa_dyn_tick_reprogram,
+ .handler = pxa_dyn_tick_handler,
+};
+#endif
+
#ifdef CONFIG_PM
static unsigned long osmr[4], oier;
@@ -161,4 +210,7 @@ struct sys_timer pxa_timer = {
.suspend = pxa_timer_suspend,
.resume = pxa_timer_resume,
.offset = pxa_gettimeoffset,
+#ifdef CONFIG_NO_IDLE_HZ
+ .dyn_tick = &pxa_dyn_tick,
+#endif
};
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 0eeb3616ffea..47e0420623fc 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -70,15 +70,11 @@ static unsigned long sa1100_gettimeoffset (void)
return usec;
}
-/*
- * We will be entered with IRQs enabled.
- *
- * Loop until we get ahead of the free running timer.
- * This ensures an exact clock tick count and time accuracy.
- * IRQs are disabled inside the loop to ensure coherence between
- * lost_ticks (updated in do_timer()) and the match reg value, so we
- * can use do_gettimeofday() from interrupt handlers.
- */
+#ifdef CONFIG_NO_IDLE_HZ
+static unsigned long initial_match;
+static int match_posponed;
+#endif
+
static irqreturn_t
sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -86,6 +82,21 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
write_seqlock(&xtime_lock);
+#ifdef CONFIG_NO_IDLE_HZ
+ if (match_posponed) {
+ match_posponed = 0;
+ OSMR0 = initial_match;
+ }
+#endif
+
+ /*
+ * Loop until we get ahead of the free running timer.
+ * This ensures an exact clock tick count and time accuracy.
+ * Since IRQs are disabled at this point, coherence between
+ * lost_ticks(updated in do_timer()) and the match reg value is
+ * ensured, hence we can use do_gettimeofday() from interrupt
+ * handlers.
+ */
do {
timer_tick(regs);
OSSR = OSSR_M0; /* Clear match on timer 0 */
@@ -120,6 +131,42 @@ static void __init sa1100_timer_init(void)
OSCR = 0; /* initialize free-running timer, force first match */
}
+#ifdef CONFIG_NO_IDLE_HZ
+static int sa1100_dyn_tick_enable_disable(void)
+{
+ /* nothing to do */
+ return 0;
+}
+
+static void sa1100_dyn_tick_reprogram(unsigned long ticks)
+{
+ if (ticks > 1) {
+ initial_match = OSMR0;
+ OSMR0 = initial_match + ticks * LATCH;
+ match_posponed = 1;
+ }
+}
+
+static irqreturn_t
+sa1100_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (match_posponed) {
+ match_posponed = 0;
+ OSMR0 = initial_match;
+ if ((signed long)(initial_match - OSCR) <= 0)
+ return sa1100_timer_interrupt(irq, dev_id, regs);
+ }
+ return IRQ_NONE;
+}
+
+static struct dyn_tick_timer sa1100_dyn_tick = {
+ .enable = sa1100_dyn_tick_enable_disable,
+ .disable = sa1100_dyn_tick_enable_disable,
+ .reprogram = sa1100_dyn_tick_reprogram,
+ .handler = sa1100_dyn_tick_handler,
+};
+#endif
+
#ifdef CONFIG_PM
unsigned long osmr[4], oier;
@@ -156,4 +203,7 @@ struct sys_timer sa1100_timer = {
.suspend = sa1100_timer_suspend,
.resume = sa1100_timer_resume,
.offset = sa1100_gettimeoffset,
+#ifdef CONFIG_NO_IDLE_HZ
+ .dyn_tick = &sa1100_dyn_tick,
+#endif
};
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 4dae00bf7a56..d125a3dc061c 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -295,14 +295,10 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
pte_t *ptep;
if (pmd_none(*pmdp)) {
- unsigned long pmdval;
ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
sizeof(pte_t));
- pmdval = __pa(ptep) | prot_l1;
- pmdp[0] = __pmd(pmdval);
- pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
- flush_pmd_entry(pmdp);
+ __pmd_populate(pmdp, __pa(ptep) | prot_l1);
}
ptep = pte_offset_kernel(pmdp, virt);
@@ -457,7 +453,7 @@ static void __init build_mem_type_table(void)
for (i = 0; i < 16; i++) {
unsigned long v = pgprot_val(protection_map[i]);
- v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
+ v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
protection_map[i] = __pgprot(v);
}
@@ -581,23 +577,23 @@ static void __init create_mapping(struct map_desc *md)
*/
void setup_mm_for_reboot(char mode)
{
- unsigned long pmdval;
+ unsigned long base_pmdval;
pgd_t *pgd;
- pmd_t *pmd;
int i;
- int cpu_arch = cpu_architecture();
if (current->mm && current->mm->pgd)
pgd = current->mm->pgd;
else
pgd = init_mm.pgd;
- for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) {
- pmdval = (i << PGDIR_SHIFT) |
- PMD_SECT_AP_WRITE | PMD_SECT_AP_READ |
- PMD_TYPE_SECT;
- if (cpu_arch <= CPU_ARCH_ARMv5TEJ)
- pmdval |= PMD_BIT4;
+ base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
+ if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ)
+ base_pmdval |= PMD_BIT4;
+
+ for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
+ unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
+ pmd_t *pmd;
+
pmd = pmd_off(pgd, i << PGDIR_SHIFT);
pmd[0] = __pmd(pmdval);
pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 94619ccee789..278de61224d1 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -295,7 +295,7 @@
#define __NR_fstatfs64 (__NR_SYSCALL_BASE+267)
#define __NR_tgkill (__NR_SYSCALL_BASE+268)
#define __NR_utimes (__NR_SYSCALL_BASE+269)
-#define __NR_fadvise64_64 (__NR_SYSCALL_BASE+270)
+#define __NR_arm_fadvise64_64 (__NR_SYSCALL_BASE+270)
#define __NR_pciconfig_iobase (__NR_SYSCALL_BASE+271)
#define __NR_pciconfig_read (__NR_SYSCALL_BASE+272)
#define __NR_pciconfig_write (__NR_SYSCALL_BASE+273)