diff options
Diffstat (limited to 'arch')
53 files changed, 909 insertions, 166 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f82dccad257..d4ca75b04bc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1563,7 +1563,6 @@ config HIGHMEM config HIGHPTE bool "Allocate 2nd-level pagetables from highmem" depends on HIGHMEM - depends on !OUTER_CACHE config HW_PERF_EVENTS bool "Enable hardware performance counter support for perf events" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index d51ab6c6482..4570ca76a9a 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -292,6 +292,9 @@ zinstall uinstall install: vmlinux %.dtb: $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ +dtbs: + $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ + # We use MRPROPER_FILES and CLEAN_FILES now archclean: $(Q)$(MAKE) $(clean)=$(boot) @@ -308,6 +311,7 @@ define archhelp echo ' uImage - U-Boot wrapped zImage' echo ' bootpImage - Combined zImage and initial RAM disk' echo ' (supply initrd image via make variable INITRD=<path>)' + echo ' dtbs - Build device tree blobs for enabled boards' echo ' install - Install uncompressed kernel' echo ' zinstall - Install compressed kernel' echo ' uinstall - Install U-Boot wrapped compressed kernel' diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 08fc37f1dec..a1edfd5a129 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -63,6 +63,8 @@ endif $(obj)/%.dtb: $(src)/dts/%.dts $(call cmd,dtc) +$(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y)) + quiet_cmd_uimage = UIMAGE $@ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ -C none -a $(LOADADDR) -e $(STARTADDR) \ diff --git a/arch/arm/boot/dts/isee-igep-v2.dts b/arch/arm/boot/dts/isee-igep-v2.dts new file mode 100644 index 00000000000..72caabb85b7 --- /dev/null +++ b/arch/arm/boot/dts/isee-igep-v2.dts @@ -0,0 +1,7 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "ISSE IGEPv2 Board"; + compatible = "ISEE,igep-v2"; +}; diff --git a/arch/arm/boot/dts/isee-igep-v3.dts b/arch/arm/boot/dts/isee-igep-v3.dts new file mode 100644 index 00000000000..f40886fef69 --- /dev/null +++ b/arch/arm/boot/dts/isee-igep-v3.dts @@ -0,0 +1,7 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "ISSE IGEPv3 Module"; + compatible = "ISEE,igep-v3"; +}; diff --git a/arch/arm/boot/dts/vexpress.dts b/arch/arm/boot/dts/vexpress.dts new file mode 100644 index 00000000000..5f3bc1d1f1c --- /dev/null +++ b/arch/arm/boot/dts/vexpress.dts @@ -0,0 +1,10 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "ARM Versatile Express"; + compatible = "arm,vexpress"; + memory { + reg = <0x60000000 0x40000000>; + }; +}; diff --git a/arch/arm/include/asm/cti.h b/arch/arm/include/asm/cti.h new file mode 100644 index 00000000000..26e7450beb6 --- /dev/null +++ b/arch/arm/include/asm/cti.h @@ -0,0 +1,157 @@ +#ifndef __ASMARM_CTI_H +#define __ASMARM_CTI_H + +#include <asm/io.h> + +/* The registers' definition is from section 3.2 of + * Embedded Cross Trigger Revision: r0p0 + */ +#define CTICONTROL 0x000 +#define CTISTATUS 0x004 +#define CTILOCK 0x008 +#define CTIPROTECTION 0x00C +#define CTIINTACK 0x010 +#define CTIAPPSET 0x014 +#define CTIAPPCLEAR 0x018 +#define CTIAPPPULSE 0x01c +#define CTIINEN 0x020 +#define CTIOUTEN 0x0A0 +#define CTITRIGINSTATUS 0x130 +#define CTITRIGOUTSTATUS 0x134 +#define CTICHINSTATUS 0x138 +#define CTICHOUTSTATUS 0x13c +#define CTIPERIPHID0 0xFE0 +#define CTIPERIPHID1 0xFE4 +#define CTIPERIPHID2 0xFE8 +#define CTIPERIPHID3 0xFEC +#define CTIPCELLID0 0xFF0 +#define CTIPCELLID1 0xFF4 +#define CTIPCELLID2 0xFF8 +#define CTIPCELLID3 0xFFC + +/* The below are from section 3.6.4 of + * CoreSight v1.0 Architecture Specification + */ +#define LOCKACCESS 0xFB0 +#define LOCKSTATUS 0xFB4 + +/* write this value to LOCKACCESS will unlock the module, and + * other value will lock the module + */ +#define LOCKCODE 0xC5ACCE55 + +/** + * struct cti - cross trigger interface struct + * @base: mapped virtual address for the cti base + * @irq: irq number for the cti + * @trig_out_for_irq: triger out number which will cause + * the @irq happen + * + * cti struct used to operate cti registers. + */ +struct cti { + void __iomem *base; + int irq; + int trig_out_for_irq; +}; + +/** + * cti_init - initialize the cti instance + * @cti: cti instance + * @base: mapped virtual address for the cti base + * @irq: irq number for the cti + * @trig_out: triger out number which will cause + * the @irq happen + * + * called by machine code to pass the board dependent + * @base, @irq and @trig_out to cti. + */ +static inline void cti_init(struct cti *cti, + void __iomem *base, int irq, int trig_out) +{ + cti->base = base; + cti->irq = irq; + cti->trig_out_for_irq = trig_out; +} + +/** + * cti_map_trigger - use the @chan to map @trig_in to @trig_out + * @cti: cti instance + * @trig_in: trigger in number + * @trig_out: trigger out number + * @channel: channel number + * + * This function maps one trigger in of @trig_in to one trigger + * out of @trig_out using the channel @chan. + */ +static inline void cti_map_trigger(struct cti *cti, + int trig_in, int trig_out, int chan) +{ + void __iomem *base = cti->base; + + __raw_writel(BIT(chan), base + CTIINEN + trig_in * 4); + __raw_writel(BIT(chan), base + CTIOUTEN + trig_out * 4); +} + +/** + * cti_enable - enable the cti module + * @cti: cti instance + * + * enable the cti module + */ +static inline void cti_enable(struct cti *cti) +{ + __raw_writel(0x1, cti->base + CTICONTROL); +} + +/** + * cti_disable - disable the cti module + * @cti: cti instance + * + * enable the cti module + */ +static inline void cti_disable(struct cti *cti) +{ + __raw_writel(0, cti->base + CTICONTROL); +} + +/** + * cti_irq_ack - clear the cti irq + * @cti: cti instance + * + * clear the cti irq + */ +static inline void cti_irq_ack(struct cti *cti) +{ + void __iomem *base = cti->base; + unsigned long val; + + val = __raw_readl(base + CTIINTACK); + val |= BIT(cti->trig_out_for_irq); + __raw_writel(val, base + CTIINTACK); +} + +/** + * cti_unlock - unlock cti module + * @cti: cti instance + * + * unlock the cti module, or else any writes to the cti + * module is not allowed. + */ +static inline void cti_unlock(struct cti *cti) +{ + __raw_writel(LOCKCODE, cti->base + LOCKACCESS); +} + +/** + * cti_lock - lock cti module + * @cti: cti instance + * + * lock the cti module, so any writes to the cti + * module will be not allowed. + */ +static inline void cti_lock(struct cti *cti) +{ + __raw_writel(~LOCKCODE, cti->base + LOCKACCESS); +} +#endif diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index c3cd8755e64..0e9ce8d9686 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -108,6 +108,7 @@ struct task_struct; int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); #define ELF_CORE_COPY_TASK_REGS dump_task_regs +#define CORE_DUMP_USE_REGSET #define ELF_EXEC_PAGESIZE 4096 /* This is the location that an ET_DYN program is loaded if exec'ed. Typical diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 7544ce6b481..7ca3d15046d 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -22,13 +22,22 @@ enum arm_pmu_type { /* * struct arm_pmu_platdata - ARM PMU platform data * - * @handle_irq: an optional handler which will be called from the interrupt and - * passed the address of the low level handler, and can be used to implement - * any platform specific handling before or after calling it. + * @handle_irq: an optional handler which will be called from the + * interrupt and passed the address of the low level handler, + * and can be used to implement any platform specific handling + * before or after calling it. + * @enable_irq: an optional handler which will be called after + * request_irq and be used to handle some platform specific + * irq enablement + * @disable_irq: an optional handler which will be called before + * free_irq and be used to handle some platform specific + * irq disablement */ struct arm_pmu_platdata { irqreturn_t (*handle_irq)(int irq, void *dev, irq_handler_t pmu_handler); + void (*enable_irq)(int irq); + void (*disable_irq)(int irq); }; #ifdef CONFIG_CPU_HAS_PMU diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index a8ff22b2a39..312d10877bd 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -128,6 +128,12 @@ struct pt_regs { #define ARM_r0 uregs[0] #define ARM_ORIG_r0 uregs[17] +/* + * The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS + * and core dumps. + */ +#define ARM_VFPREGS_SIZE ( 32 * 8 /*fpregs*/ + 4 /*fpscr*/ ) + #ifdef __KERNEL__ #define user_mode(regs) \ diff --git a/arch/arm/include/asm/thread_notify.h b/arch/arm/include/asm/thread_notify.h index c4391ba2035..1dc98067589 100644 --- a/arch/arm/include/asm/thread_notify.h +++ b/arch/arm/include/asm/thread_notify.h @@ -43,6 +43,7 @@ static inline void thread_notify(unsigned long rc, struct thread_info *thread) #define THREAD_NOTIFY_FLUSH 0 #define THREAD_NOTIFY_EXIT 1 #define THREAD_NOTIFY_SWITCH 2 +#define THREAD_NOTIFY_COPY 3 #endif #endif diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c index d4a0da1e48f..8524d096300 100644 --- a/arch/arm/kernel/elf.c +++ b/arch/arm/kernel/elf.c @@ -40,16 +40,23 @@ EXPORT_SYMBOL(elf_check_arch); void elf_set_personality(const struct elf32_hdr *x) { unsigned int eflags = x->e_flags; - unsigned int personality = PER_LINUX_32BIT; + unsigned int personality = current->personality; /* + * Inherit most personality flags from parent, except for those + * we're about to choose. Beware: PER_LINUX_32BIT carries flag bits + * outside of PER_MASK. + */ + personality &= ~(PER_MASK | PER_LINUX | PER_LINUX_32BIT); + + /* * APCS-26 is only valid for OABI executables */ - if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) { - if (eflags & EF_ARM_APCS_26) - personality = PER_LINUX; - } - + if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN && + (eflags & EF_ARM_APCS_26)) + personality |= PER_LINUX; + else + personality |= PER_LINUX_32BIT; set_personality(personality); /* diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 8dbc126f715..87acc25d7a3 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -868,6 +868,13 @@ static void reset_ctrl_regs(void *info) */ asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0)); isb(); + + /* + * Clear any configured vector-catch events before + * enabling monitor mode. + */ + asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0)); + isb(); } if (enable_monitor_mode()) diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 69cfee0fe00..1a0d6afbb35 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -221,7 +221,7 @@ again: prev_raw_count &= armpmu->max_period; if (overflow) - delta = armpmu->max_period - prev_raw_count + new_raw_count; + delta = armpmu->max_period - prev_raw_count + new_raw_count + 1; else delta = new_raw_count - prev_raw_count; @@ -426,14 +426,18 @@ armpmu_reserve_hardware(void) pr_warning("unable to request IRQ%d for ARM perf " "counters\n", irq); break; - } + } else if (plat->enable_irq) + plat->enable_irq(irq); } if (err) { for (i = i - 1; i >= 0; --i) { irq = platform_get_irq(pmu_device, i); - if (irq >= 0) + if (irq >= 0) { + if (plat->disable_irq) + plat->disable_irq(irq); free_irq(irq, NULL); + } } release_pmu(pmu_device); pmu_device = NULL; @@ -446,11 +450,16 @@ static void armpmu_release_hardware(void) { int i, irq; + struct arm_pmu_platdata *plat = + dev_get_platdata(&pmu_device->dev); for (i = pmu_device->num_resources - 1; i >= 0; --i) { irq = platform_get_irq(pmu_device, i); - if (irq >= 0) + if (irq >= 0) { + if (plat->disable_irq) + plat->disable_irq(irq); free_irq(irq, NULL); + } } armpmu->stop(); @@ -746,7 +755,8 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) tail = (struct frame_tail __user *)regs->ARM_fp - 1; - while (tail && !((unsigned long)tail & 0x3)) + while ((entry->nr < PERF_MAX_STACK_DEPTH) && + tail && !((unsigned long)tail & 0x3)) tail = user_backtrace(tail, entry); } diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index d8ae7018208..85e68c7ebd4 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -448,6 +448,8 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start, if (clone_flags & CLONE_SETTLS) thread->tp_value = regs->ARM_r3; + thread_notify(THREAD_NOTIFY_COPY, thread); + return 0; } diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 03438e9cc06..7c897e2c4d4 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -25,6 +25,7 @@ #include <linux/marker.h> #include <linux/kallsyms.h> #include <trace/syscall.h> +#include <linux/regset.h> #include <asm/pgtable.h> #include <asm/system.h> @@ -337,58 +338,6 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off, return put_user_reg(tsk, off >> 2, val); } -/* - * Get all user integer registers. - */ -static int ptrace_getregs(struct task_struct *tsk, void __user *uregs) -{ - struct pt_regs *regs = task_pt_regs(tsk); - - return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; -} - -/* - * Set all user integer registers. - */ -static int ptrace_setregs(struct task_struct *tsk, void __user *uregs) -{ - struct pt_regs newregs; - int ret; - - ret = -EFAULT; - if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) { - struct pt_regs *regs = task_pt_regs(tsk); - - ret = -EINVAL; - if (valid_user_regs(&newregs)) { - *regs = newregs; - ret = 0; - } - } - - return ret; -} - -/* - * Get the child FPU state. - */ -static int ptrace_getfpregs(struct task_struct *tsk, void __user *ufp) -{ - return copy_to_user(ufp, &task_thread_info(tsk)->fpstate, - sizeof(struct user_fp)) ? -EFAULT : 0; -} - -/* - * Set the child FPU state. - */ -static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp) -{ - struct thread_info *thread = task_thread_info(tsk); - thread->used_cp[1] = thread->used_cp[2] = 1; - return copy_from_user(&thread->fpstate, ufp, - sizeof(struct user_fp)) ? -EFAULT : 0; -} - #ifdef CONFIG_IWMMXT /* @@ -447,56 +396,6 @@ static int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp) } #endif -#ifdef CONFIG_VFP -/* - * Get the child VFP state. - */ -static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data) -{ - struct thread_info *thread = task_thread_info(tsk); - union vfp_state *vfp = &thread->vfpstate; - struct user_vfp __user *ufp = data; - - vfp_sync_hwstate(thread); - - /* copy the floating point registers */ - if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs, - sizeof(vfp->hard.fpregs))) - return -EFAULT; - - /* copy the status and control register */ - if (put_user(vfp->hard.fpscr, &ufp->fpscr)) - return -EFAULT; - - return 0; -} - -/* - * Set the child VFP state. - */ -static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data) -{ - struct thread_info *thread = task_thread_info(tsk); - union vfp_state *vfp = &thread->vfpstate; - struct user_vfp __user *ufp = data; - - vfp_sync_hwstate(thread); - - /* copy the floating point registers */ - if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs, - sizeof(vfp->hard.fpregs))) - return -EFAULT; - - /* copy the status and control register */ - if (get_user(vfp->hard.fpscr, &ufp->fpscr)) - return -EFAULT; - - vfp_flush_hwstate(thread); - - return 0; -} -#endif - #ifdef CONFIG_HAVE_HW_BREAKPOINT /* * Convert a virtual register number into an index for a thread_info @@ -723,6 +622,219 @@ out: } #endif +/* regset get/set implementations */ + +static int gpr_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + struct pt_regs *regs = task_pt_regs(target); + + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, + regs, + 0, sizeof(*regs)); +} + +static int gpr_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + int ret; + struct pt_regs newregs; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &newregs, + 0, sizeof(newregs)); + if (ret) + return ret; + + if (!valid_user_regs(&newregs)) + return -EINVAL; + + *task_pt_regs(target) = newregs; + return 0; +} + +static int fpa_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, + &task_thread_info(target)->fpstate, + 0, sizeof(struct user_fp)); +} + +static int fpa_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + struct thread_info *thread = task_thread_info(target); + + thread->used_cp[1] = thread->used_cp[2] = 1; + + return user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &thread->fpstate, + 0, sizeof(struct user_fp)); +} + +#ifdef CONFIG_VFP +/* + * VFP register get/set implementations. + * + * With respect to the kernel, struct user_fp is divided into three chunks: + * 16 or 32 real VFP registers (d0-d15 or d0-31) + * These are transferred to/from the real registers in the task's + * vfp_hard_struct. The number of registers depends on the kernel + * configuration. + * + * 16 or 0 fake VFP registers (d16-d31 or empty) + * i.e., the user_vfp structure has space for 32 registers even if + * the kernel doesn't have them all. + * + * vfp_get() reads this chunk as zero where applicable + * vfp_set() ignores this chunk + * + * 1 word for the FPSCR + * + * The bounds-checking logic built into user_regset_copyout and friends + * means that we can make a simple sequence of calls to map the relevant data + * to/from the specified slice of the user regset structure. + */ +static int vfp_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + int ret; + struct thread_info *thread = task_thread_info(target); + struct vfp_hard_struct const *vfp = &thread->vfpstate.hard; + const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); + const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); + + vfp_sync_hwstate(thread); + + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, + &vfp->fpregs, + user_fpregs_offset, + user_fpregs_offset + sizeof(vfp->fpregs)); + if (ret) + return ret; + + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, + user_fpregs_offset + sizeof(vfp->fpregs), + user_fpscr_offset); + if (ret) + return ret; + + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, + &vfp->fpscr, + user_fpscr_offset, + user_fpscr_offset + sizeof(vfp->fpscr)); +} + +/* + * For vfp_set() a read-modify-write is done on the VFP registers, + * in order to avoid writing back a half-modified set of registers on + * failure. + */ +static int vfp_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + int ret; + struct thread_info *thread = task_thread_info(target); + struct vfp_hard_struct new_vfp = thread->vfpstate.hard; + const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); + const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &new_vfp.fpregs, + user_fpregs_offset, + user_fpregs_offset + sizeof(new_vfp.fpregs)); + if (ret) + return ret; + + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, + user_fpregs_offset + sizeof(new_vfp.fpregs), + user_fpscr_offset); + if (ret) + return ret; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &new_vfp.fpscr, + user_fpscr_offset, + user_fpscr_offset + sizeof(new_vfp.fpscr)); + if (ret) + return ret; + + vfp_sync_hwstate(thread); + thread->vfpstate.hard = new_vfp; + vfp_flush_hwstate(thread); + + return 0; +} +#endif /* CONFIG_VFP */ + +enum arm_regset { + REGSET_GPR, + REGSET_FPR, +#ifdef CONFIG_VFP + REGSET_VFP, +#endif +}; + +static const struct user_regset arm_regsets[] = { + [REGSET_GPR] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(u32), + .align = sizeof(u32), + .get = gpr_get, + .set = gpr_set + }, + [REGSET_FPR] = { + /* + * For the FPA regs in fpstate, the real fields are a mixture + * of sizes, so pretend that the registers are word-sized: + */ + .core_note_type = NT_PRFPREG, + .n = sizeof(struct user_fp) / sizeof(u32), + .size = sizeof(u32), + .align = sizeof(u32), + .get = fpa_get, + .set = fpa_set + }, +#ifdef CONFIG_VFP + [REGSET_VFP] = { + /* + * Pretend that the VFP regs are word-sized, since the FPSCR is + * a single word dangling at the end of struct user_vfp: + */ + .core_note_type = NT_ARM_VFP, + .n = ARM_VFPREGS_SIZE / sizeof(u32), + .size = sizeof(u32), + .align = sizeof(u32), + .get = vfp_get, + .set = vfp_set + }, +#endif /* CONFIG_VFP */ +}; + +static const struct user_regset_view user_arm_view = { + .name = "arm", .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, + .regsets = arm_regsets, .n = ARRAY_SIZE(arm_regsets) +}; + +const struct user_regset_view *task_user_regset_view(struct task_struct *task) +{ + return &user_arm_view; +} + long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { @@ -739,19 +851,31 @@ long arch_ptrace(struct task_struct *child, long request, break; case PTRACE_GETREGS: - ret = ptrace_getregs(child, datap); + ret = copy_regset_to_user(child, + &user_arm_view, REGSET_GPR, + 0, sizeof(struct pt_regs), + datap); break; case PTRACE_SETREGS: - ret = ptrace_setregs(child, datap); + ret = copy_regset_from_user(child, + &user_arm_view, REGSET_GPR, + 0, sizeof(struct pt_regs), + datap); break; case PTRACE_GETFPREGS: - ret = ptrace_getfpregs(child, datap); + ret = copy_regset_to_user(child, + &user_arm_view, REGSET_FPR, + 0, sizeof(union fp_state), + datap); break; - + case PTRACE_SETFPREGS: - ret = ptrace_setfpregs(child, datap); + ret = copy_regset_from_user(child, + &user_arm_view, REGSET_FPR, + 0, sizeof(union fp_state), + datap); break; #ifdef CONFIG_IWMMXT @@ -786,11 +910,17 @@ long arch_ptrace(struct task_struct *child, long request, #ifdef CONFIG_VFP case PTRACE_GETVFPREGS: - ret = ptrace_getvfpregs(child, datap); + ret = copy_regset_to_user(child, + &user_arm_view, REGSET_VFP, + 0, ARM_VFPREGS_SIZE, + datap); break; case PTRACE_SETVFPREGS: - ret = ptrace_setvfpregs(child, datap); + ret = copy_regset_from_user(child, + &user_arm_view, REGSET_VFP, + 0, ARM_VFPREGS_SIZE, + datap); break; #endif diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile index 9be104f63c0..de197d6648a 100644 --- a/arch/arm/mach-exynos4/Makefile +++ b/arch/arm/mach-exynos4/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_CPU_EXYNOS4210) += cpu.o init.o clock.o irq-combiner.o obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o gpiolib.o irq-eint.o dma.o obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o diff --git a/arch/arm/mach-exynos4/Makefile.boot b/arch/arm/mach-exynos4/Makefile.boot index d65956ffb43..fcee6b5384a 100644 --- a/arch/arm/mach-exynos4/Makefile.boot +++ b/arch/arm/mach-exynos4/Makefile.boot @@ -1,2 +1,4 @@ zreladdr-y := 0x40008000 params_phys-y := 0x40000100 + +dtb-$(CONFIG_MACH_SMDKV310) += exynos4-smdkv310.dtb diff --git a/arch/arm/mach-exynos4/cpuidle.c b/arch/arm/mach-exynos4/cpuidle.c new file mode 100644 index 00000000000..bf7e96f2793 --- /dev/null +++ b/arch/arm/mach-exynos4/cpuidle.c @@ -0,0 +1,86 @@ +/* linux/arch/arm/mach-exynos4/cpuidle.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/cpuidle.h> +#include <linux/io.h> + +#include <asm/proc-fns.h> + +static int exynos4_enter_idle(struct cpuidle_device *dev, + struct cpuidle_state *state); + +static struct cpuidle_state exynos4_cpuidle_set[] = { + [0] = { + .enter = exynos4_enter_idle, + .exit_latency = 1, + .target_residency = 100000, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "IDLE", + .desc = "ARM clock gating(WFI)", + }, +}; + +static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device); + +static struct cpuidle_driver exynos4_idle_driver = { + .name = "exynos4_idle", + .owner = THIS_MODULE, +}; + +static int exynos4_enter_idle(struct cpuidle_device *dev, + struct cpuidle_state *state) +{ + struct timeval before, after; + int idle_time; + + local_irq_disable(); + do_gettimeofday(&before); + + cpu_do_idle(); + + do_gettimeofday(&after); + local_irq_enable(); + idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + + (after.tv_usec - before.tv_usec); + + return idle_time; +} + +static int __init exynos4_init_cpuidle(void) +{ + int i, max_cpuidle_state, cpu_id; + struct cpuidle_device *device; + + cpuidle_register_driver(&exynos4_idle_driver); + + for_each_cpu(cpu_id, cpu_online_mask) { + device = &per_cpu(exynos4_cpuidle_device, cpu_id); + device->cpu = cpu_id; + + device->state_count = (sizeof(exynos4_cpuidle_set) / + sizeof(struct cpuidle_state)); + + max_cpuidle_state = device->state_count; + + for (i = 0; i < max_cpuidle_state; i++) { + memcpy(&device->states[i], &exynos4_cpuidle_set[i], + sizeof(struct cpuidle_state)); + } + + if (cpuidle_register_device(device)) { + printk(KERN_ERR "CPUidle register device failed\n,"); + return -EIO; + } + } + return 0; +} +device_initcall(exynos4_init_cpuidle); diff --git a/arch/arm/mach-exynos4/gpiolib.c b/arch/arm/mach-exynos4/gpiolib.c index d54ca6adb66..3a47c8e84c9 100644 --- a/arch/arm/mach-exynos4/gpiolib.c +++ b/arch/arm/mach-exynos4/gpiolib.c @@ -23,14 +23,14 @@ static struct s3c_gpio_cfg gpio_cfg = { .set_config = s3c_gpio_setcfg_s3c64xx_4bit, - .set_pull = s3c_gpio_setpull_updown, - .get_pull = s3c_gpio_getpull_updown, + .set_pull = s3c_gpio_setpull_exynos4, + .get_pull = s3c_gpio_getpull_exynos4, }; static struct s3c_gpio_cfg gpio_cfg_noint = { .set_config = s3c_gpio_setcfg_s3c64xx_4bit, - .set_pull = s3c_gpio_setpull_updown, - .get_pull = s3c_gpio_getpull_updown, + .set_pull = s3c_gpio_setpull_exynos4, + .get_pull = s3c_gpio_getpull_exynos4, }; /* diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c index 08bcc557458..82e0df737c0 100644 --- a/arch/arm/mach-exynos4/mach-smdkv310.c +++ b/arch/arm/mach-exynos4/mach-smdkv310.c @@ -78,7 +78,7 @@ static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = { }; static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = { - .cd_type = S3C_SDHCI_CD_GPIO, + .cd_type = S3C_SDHCI_CD_INTERNAL, .ext_cd_gpio = EXYNOS4_GPK0(2), .ext_cd_gpio_invert = 1, .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, @@ -96,7 +96,7 @@ static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = { }; static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = { - .cd_type = S3C_SDHCI_CD_GPIO, + .cd_type = S3C_SDHCI_CD_INTERNAL, .ext_cd_gpio = EXYNOS4_GPK2(2), .ext_cd_gpio_invert = 1, .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, @@ -168,9 +168,9 @@ static struct i2c_board_info i2c_devs1[] __initdata = { }; static struct platform_device *smdkv310_devices[] __initdata = { + &s3c_device_hsmmc2, &s3c_device_hsmmc0, &s3c_device_hsmmc1, - &s3c_device_hsmmc2, &s3c_device_hsmmc3, &s3c_device_i2c1, &s3c_device_rtc, diff --git a/arch/arm/mach-mx5/Makefile.boot b/arch/arm/mach-mx5/Makefile.boot index e928be1b675..4111462e242 100644 --- a/arch/arm/mach-mx5/Makefile.boot +++ b/arch/arm/mach-mx5/Makefile.boot @@ -7,3 +7,8 @@ initrd_phys-$(CONFIG_ARCH_MX51) := 0x90800000 zreladdr-$(CONFIG_ARCH_MX53) := 0x70008000 params_phys-$(CONFIG_ARCH_MX53) := 0x70000100 initrd_phys-$(CONFIG_ARCH_MX53) := 0x70800000 + +dtb-$(CONFIG_MACH_MX51_BABBAGE) += mx51-babbage.dtb +dtb-$(CONFIG_MACH_MX51_EFIKAMX) += genesi-efikamx.dtb +dtb-$(CONFIG_MACH_MX51_EFIKASB) += genesi-efikasb.dtb +dtb-$(CONFIG_MACH_MX53_LOCO) += mx53-loco.dtb diff --git a/arch/arm/mach-omap2/Makefile.boot b/arch/arm/mach-omap2/Makefile.boot index 565aff7f37a..422c1700ccf 100644 --- a/arch/arm/mach-omap2/Makefile.boot +++ b/arch/arm/mach-omap2/Makefile.boot @@ -1,3 +1,9 @@ zreladdr-y := 0x80008000 params_phys-y := 0x80000100 initrd_phys-y := 0x80800000 + +dtb-$(CONFIG_MACH_OMAP3_BEAGLE) += omap3-beagle.dtb +dtb-$(CONFIG_MACH_OMAP4_PANDA) += omap4-panda.dtb +dtb-$(CONFIG_MACH_OVERO) += omap3-overo.dtb +dtb-$(CONFIG_MACH_IGEP0020) += isee-igep-v2.dtb +dtb-$(CONFIG_MACH_IGEP0030) += isee-igep-v3.dtb diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 9afd087cc29..e512b48c936 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -275,6 +275,7 @@ static struct panel_generic_dpi_data dvi_panel = { .name = "generic", .platform_enable = sdp3430_panel_enable_dvi, .platform_disable = sdp3430_panel_disable_dvi, + .i2c_bus_num = 3, }; static struct omap_dss_device sdp3430_dvi_device = { diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index ce7d5e6e415..ace46665d67 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -311,6 +311,7 @@ static struct panel_generic_dpi_data lcd_panel = { .name = "sharp_lq", .platform_enable = am3517_evm_panel_enable_lcd, .platform_disable = am3517_evm_panel_disable_lcd, + .i2c_bus_num = 3, }; static struct omap_dss_device am3517_evm_lcd_device = { @@ -359,6 +360,7 @@ static struct panel_generic_dpi_data dvi_panel = { .name = "generic", .platform_enable = am3517_evm_panel_enable_dvi, .platform_disable = am3517_evm_panel_disable_dvi, + .i2c_bus_num = 3, }; static struct omap_dss_device am3517_evm_dvi_device = { diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 02a12b41c0f..edd48356c30 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -356,6 +356,7 @@ static struct panel_generic_dpi_data lcd_panel = { .name = "toppoly_tdo35s", .platform_enable = cm_t35_panel_enable_lcd, .platform_disable = cm_t35_panel_disable_lcd, + .i2c_bus_num = 3, }; static struct omap_dss_device cm_t35_lcd_device = { @@ -370,6 +371,7 @@ static struct panel_generic_dpi_data dvi_panel = { .name = "generic", .platform_enable = cm_t35_panel_enable_dvi, .platform_disable = cm_t35_panel_disable_dvi, + .i2c_bus_num = 3, }; static struct omap_dss_device cm_t35_dvi_device = { diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 65f9fde2c56..0a35c3a3ed9 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -151,6 +151,7 @@ static struct panel_generic_dpi_data lcd_panel = { .name = "generic", .platform_enable = devkit8000_panel_enable_lcd, .platform_disable = devkit8000_panel_disable_lcd, + .i2c_bus_num = 3, }; static struct omap_dss_device devkit8000_lcd_device = { @@ -165,6 +166,7 @@ static struct panel_generic_dpi_data dvi_panel = { .name = "generic", .platform_enable = devkit8000_panel_enable_dvi, .platform_disable = devkit8000_panel_disable_dvi, + .i2c_bus_num = 3, }; static struct omap_dss_device devkit8000_dvi_device = { diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 5f8a2fd0633..8b24d62e8f2 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -465,6 +465,7 @@ static struct panel_generic_dpi_data dvi_panel = { .name = "generic", .platform_enable = igep2_enable_dvi, .platform_disable = igep2_disable_dvi, + .i2c_bus_num = 3, }; static struct omap_dss_device igep2_dvi_device = { @@ -703,6 +704,11 @@ static void __init igep2_init(void) } +static const char *igep2_dt_compat[] __initdata = { + "ISEE,igep-v2", + NULL +}; + MACHINE_START(IGEP0020, "IGEP v2 board") .boot_params = 0x80000100, .reserve = omap_reserve, @@ -711,4 +717,5 @@ MACHINE_START(IGEP0020, "IGEP v2 board") .init_irq = omap_init_irq, .init_machine = igep2_init, .timer = &omap_timer, + .dt_compat = &igep2_dt_compat, MACHINE_END diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c index b10db0e6ee6..01762bb6800 100644 --- a/arch/arm/mach-omap2/board-igep0030.c +++ b/arch/arm/mach-omap2/board-igep0030.c @@ -447,6 +447,11 @@ static void __init igep3_init(void) } +static const char *igep3_dt_compat[] __initdata = { + "ISEE,igep-v3", + NULL +}; + MACHINE_START(IGEP0030, "IGEP OMAP3 module") .boot_params = 0x80000100, .reserve = omap_reserve, @@ -455,4 +460,5 @@ MACHINE_START(IGEP0030, "IGEP OMAP3 module") .init_irq = omap_init_irq, .init_machine = igep3_init, .timer = &omap_timer, + .dt_compat = &igep3_dt_compat, MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 4c62a01a379..34b0cb4d189 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -202,6 +202,7 @@ static struct panel_generic_dpi_data dvi_panel = { .name = "generic", .platform_enable = beagle_enable_dvi, .platform_disable = beagle_disable_dvi, + .i2c_bus_num = 3, }; static struct omap_dss_device beagle_dvi_device = { diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 5a1a916e5cc..792ca7454b8 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -341,6 +341,7 @@ static struct panel_generic_dpi_data dvi_panel = { .name = "generic", .platform_enable = omap3_evm_enable_dvi, .platform_disable = omap3_evm_disable_dvi, + .i2c_bus_num = 3, }; static struct omap_dss_device omap3_evm_dvi_device = { diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index a6e0b9161c9..8491295d650 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -165,6 +165,7 @@ static struct panel_generic_dpi_data lcd_panel = { .name = "generic", .platform_enable = omap3_stalker_enable_lcd, .platform_disable = omap3_stalker_disable_lcd, + .i2c_bus_num = 3, }; static struct omap_dss_device omap3_stalker_lcd_device = { @@ -218,6 +219,7 @@ static struct panel_generic_dpi_data dvi_panel = { .name = "generic", .platform_enable = omap3_stalker_enable_dvi, .platform_disable = omap3_stalker_disable_dvi, + .i2c_bus_num = 3, }; static struct omap_dss_device omap3_stalker_dvi_device = { diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index da6d2f150d9..bcdffe22d19 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -296,6 +296,7 @@ static struct panel_generic_dpi_data dvi_panel = { .name = "generic", .platform_enable = overo_panel_enable_dvi, .platform_disable = overo_panel_disable_dvi, + .i2c_bus_num = 3, }; static struct omap_dss_device overo_dvi_device = { diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index d478f53f908..f30c1bdaa98 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -22,6 +22,7 @@ #include <asm/mach-types.h> #include <asm/mach/map.h> #include <asm/pmu.h> +#include <asm/cti.h> #include <plat/tc.h> #include <plat/board.h> @@ -386,20 +387,95 @@ static struct resource omap3_pmu_resource = { .flags = IORESOURCE_IRQ, }; +static struct resource omap4_pmu_resource[] = { + { + .start = OMAP44XX_IRQ_CTI0, + .end = OMAP44XX_IRQ_CTI0, + .flags = IORESOURCE_IRQ, + }, + { + .start = OMAP44XX_IRQ_CTI1, + .end = OMAP44XX_IRQ_CTI1, + .flags = IORESOURCE_IRQ, + } +}; + static struct platform_device omap_pmu_device = { .name = "arm-pmu", .id = ARM_PMU_DEVICE_CPU, .num_resources = 1, }; +static struct arm_pmu_platdata omap4_pmu_data; +static struct cti omap4_cti[2]; + +static void omap4_enable_cti(int irq) +{ + if (irq == OMAP44XX_IRQ_CTI0) + cti_enable(&omap4_cti[0]); + else if (irq == OMAP44XX_IRQ_CTI1) + cti_enable(&omap4_cti[1]); +} + +static void omap4_disable_cti(int irq) +{ + if (irq == OMAP44XX_IRQ_CTI0) + cti_disable(&omap4_cti[0]); + else if (irq == OMAP44XX_IRQ_CTI1) + cti_disable(&omap4_cti[1]); +} + +static irqreturn_t omap4_pmu_handler(int irq, void *dev, irq_handler_t handler) +{ + if (irq == OMAP44XX_IRQ_CTI0) + cti_irq_ack(&omap4_cti[0]); + else if (irq == OMAP44XX_IRQ_CTI1) + cti_irq_ack(&omap4_cti[1]); + + return handler(irq, dev); +} + +static void omap4_configure_pmu_irq(void) +{ + void __iomem *base0; + void __iomem *base1; + + base0 = ioremap(OMAP44XX_CTI0_BASE, SZ_4K); + base1 = ioremap(OMAP44XX_CTI1_BASE, SZ_4K); + if (!base0 && !base1) { + pr_err("ioremap for OMAP4 CTI failed\n"); + return; + } + + /*configure CTI0 for pmu irq routing*/ + cti_init(&omap4_cti[0], base0, OMAP44XX_IRQ_CTI0, 6); + cti_unlock(&omap4_cti[0]); + cti_map_trigger(&omap4_cti[0], 1, 6, 2); + + /*configure CTI1 for pmu irq routing*/ + cti_init(&omap4_cti[1], base1, OMAP44XX_IRQ_CTI1, 6); + cti_unlock(&omap4_cti[1]); + cti_map_trigger(&omap4_cti[1], 1, 6, 2); + + omap4_pmu_data.handle_irq = omap4_pmu_handler; + omap4_pmu_data.enable_irq = omap4_enable_cti; + omap4_pmu_data.disable_irq = omap4_disable_cti; +} + static void omap_init_pmu(void) { - if (cpu_is_omap24xx()) + if (cpu_is_omap24xx()) { omap_pmu_device.resource = &omap2_pmu_resource; - else if (cpu_is_omap34xx()) + } else if (cpu_is_omap34xx()) { omap_pmu_device.resource = &omap3_pmu_resource; - else + } else if (cpu_is_omap44xx()) { + omap_pmu_device.resource = omap4_pmu_resource; + omap_pmu_device.num_resources = 2; + omap_pmu_device.dev.platform_data = &omap4_pmu_data; + omap4_configure_pmu_irq(); + } else { return; + } platform_device_register(&omap_pmu_device); } @@ -637,13 +713,21 @@ static inline void omap_hdq_init(void) {} #if defined(CONFIG_VIDEO_OMAP2_VOUT) || \ defined(CONFIG_VIDEO_OMAP2_VOUT_MODULE) #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) -static struct resource omap_vout_resource[3 - CONFIG_FB_OMAP2_NUM_FBS] = { -}; +#define NUM_FB CONFIG_FB_OMAP2_NUM_FBS +#elif defined(CONFIG_DRM_OMAP) || defined(CONFIG_DRM_OMAP_MODULE) +#define NUM_FB CONFIG_DRM_OMAP_NUM_CRTCS #else -static struct resource omap_vout_resource[2] = { -}; +#define NUM_FB 1 /* we don't want gfx pipe */ +#endif +#ifdef CONFIG_ARCH_OMAP4 +#define NUM_PIPES 4 +#else +#define NUM_PIPES 3 #endif +static struct resource omap_vout_resource[NUM_PIPES - NUM_FB] = { +}; + static struct platform_device omap_vout_device = { .name = "omap_vout", .num_resources = ARRAY_SIZE(omap_vout_resource), @@ -659,6 +743,16 @@ static void omap_init_vout(void) static inline void omap_init_vout(void) {} #endif +static struct platform_device omap_gpu_device = { + .name = "omap_gpu", + .id = -1, +}; + +static void omap_init_gpu(void) +{ + platform_device_register(&omap_gpu_device); +} + /*-------------------------------------------------------------------------*/ static int __init omap2_init_devices(void) @@ -677,6 +771,7 @@ static int __init omap2_init_devices(void) omap_init_sham(); omap_init_aes(); omap_init_vout(); + omap_init_gpu(); return 0; } diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot index db52d61a738..c98addfc904 100644 --- a/arch/arm/mach-tegra/Makefile.boot +++ b/arch/arm/mach-tegra/Makefile.boot @@ -1,3 +1,5 @@ zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00008000 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00000100 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00800000 + +dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb diff --git a/arch/arm/mach-versatile/Makefile.boot b/arch/arm/mach-versatile/Makefile.boot index c7e75acfe6c..e2227d3c23c 100644 --- a/arch/arm/mach-versatile/Makefile.boot +++ b/arch/arm/mach-versatile/Makefile.boot @@ -2,3 +2,5 @@ params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 +dtb-$(CONFIG_ARCH_VERSATILE_PB) += versatile-pb.dtb +dtb-$(CONFIG_MACH_VERSATILE_AB) += versatile-ab.dtb diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot index 07c2d9c457e..9920a1053e2 100644 --- a/arch/arm/mach-vexpress/Makefile.boot +++ b/arch/arm/mach-vexpress/Makefile.boot @@ -1,3 +1,5 @@ zreladdr-y := 0x60008000 params_phys-y := 0x60000100 initrd_phys-y := 0x60800000 + +dtb-$(CONFIG_ARCH_VEXPRESS_CA9X4) += vexpress.dtb diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index ba46e8e0743..e318df39efd 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -437,6 +437,11 @@ static void __init v2m_init(void) ct_desc->init_tile(); } +static const char *vexpress_dt_match[] __initdata = { + "arm,vexpress", + NULL, +}; + MACHINE_START(VEXPRESS, "ARM-Versatile Express") .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .map_io = v2m_map_io, @@ -444,4 +449,5 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express") .init_irq = v2m_init_irq, .timer = &v2m_timer, .init_machine = v2m_init, + .dt_compat = vexpress_dt_match, MACHINE_END diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index afe209e1e1f..74be05f3e03 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -7,6 +7,7 @@ #include <linux/shm.h> #include <linux/sched.h> #include <linux/io.h> +#include <linux/personality.h> #include <linux/random.h> #include <asm/cputype.h> #include <asm/system.h> @@ -82,7 +83,8 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, mm->cached_hole_size = 0; } /* 8 bits of randomness in 20 address space bits */ - if (current->flags & PF_RANDOMIZE) + if ((current->flags & PF_RANDOMIZE) && + !(current->personality & ADDR_NO_RANDOMIZE)) addr += (get_random_int() % (1 << 8)) << PAGE_SHIFT; full_search: diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h index 5e04ddc18fa..9f30ab8d1e1 100644 --- a/arch/arm/plat-omap/include/plat/display.h +++ b/arch/arm/plat-omap/include/plat/display.h @@ -23,6 +23,7 @@ #include <linux/list.h> #include <linux/kobject.h> #include <linux/device.h> +#include <linux/notifier.h> #include <linux/platform_device.h> #include <asm/atomic.h> @@ -131,6 +132,10 @@ enum omap_dss_venc_type { enum omap_display_caps { OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0, OMAP_DSS_DISPLAY_CAP_TEAR_ELIM = 1 << 1, + /* set if display supports hotplug detect, and will call + * omap_dss_notify(CONNECT/DISCONNECT) at appropriate times + */ + OMAP_DSS_DISPLAY_CAP_HPD = 1 << 2, }; enum omap_dss_update_mode { @@ -459,6 +464,7 @@ struct omap_dss_device { struct omap_overlay_manager *manager; enum omap_dss_display_state state; + struct blocking_notifier_head notifier; /* platform specific */ int (*platform_enable)(struct omap_dss_device *dssdev); @@ -514,6 +520,17 @@ struct omap_dss_driver { int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); u32 (*get_wss)(struct omap_dss_device *dssdev); + + /* return raw EDID.. len indicates the max number of bytes of the + * EDID to read */ + int (*get_edid)(struct omap_dss_device *dssdev, u8 *edid, int len); + + /* is this display physically present / plugged-in? For hot-plug + * type displays (DVI, HDMI), this means is the cable plugged in. + * For displays like LCD panels, this means is the display present + * on the board. + */ + bool (*is_detected)(struct omap_dss_device *dssdev); }; int omap_dss_register_driver(struct omap_dss_driver *); @@ -532,12 +549,34 @@ struct omap_dss_device *omap_dss_find_device(void *data, int omap_dss_start_device(struct omap_dss_device *dssdev); void omap_dss_stop_device(struct omap_dss_device *dssdev); +/* the event id of the event that occurred is passed in as the second arg + * to the notifier function, and the dssdev is passed as the third. + */ +enum omap_dss_event { + OMAP_DSS_SIZE_CHANGE, + /* the CONNECT/DISCONNECT events will be sent if OMAP_DSS_DISPLAY_CAP_HPD + * flag is set in the dssdev->caps. Otherwise the user will have to poll + * for detection when a monitor is plugged/unplugged. + */ + OMAP_DSS_HOTPLUG_CONNECT, + OMAP_DSS_HOTPLUG_DISCONNECT, +}; + +void omap_dss_notify(struct omap_dss_device *dssdev, enum omap_dss_event evt); +void omap_dss_add_notify(struct omap_dss_device *dssdev, struct notifier_block *nb); +void omap_dss_remove_notify(struct omap_dss_device *dssdev, struct notifier_block *nb); + int omap_dss_get_num_overlay_managers(void); struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); int omap_dss_get_num_overlays(void); struct omap_overlay *omap_dss_get_overlay(int num); +void omapdss_default_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings); +int omapdss_default_check_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings); +bool omapdss_default_is_detected(struct omap_dss_device *dssdev); void omapdss_default_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres); int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev); diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h index ea2b8a6306e..b127a1641f4 100644 --- a/arch/arm/plat-omap/include/plat/omap44xx.h +++ b/arch/arm/plat-omap/include/plat/omap44xx.h @@ -57,5 +57,7 @@ #define OMAP44XX_HSUSB_OHCI_BASE (L4_44XX_BASE + 0x64800) #define OMAP44XX_HSUSB_EHCI_BASE (L4_44XX_BASE + 0x64C00) +#define OMAP44XX_CTI0_BASE 0x54148000 +#define OMAP44XX_CTI1_BASE 0x54149000 #endif /* __ASM_ARCH_OMAP44XX_H */ diff --git a/arch/arm/plat-omap/include/plat/panel-generic-dpi.h b/arch/arm/plat-omap/include/plat/panel-generic-dpi.h index 790619734bc..164d3b9bde5 100644 --- a/arch/arm/plat-omap/include/plat/panel-generic-dpi.h +++ b/arch/arm/plat-omap/include/plat/panel-generic-dpi.h @@ -27,11 +27,13 @@ * @name: panel name * @platform_enable: platform specific panel enable function * @platform_disable: platform specific panel disable function + * @i2c_bus_num: i2c control bus id the eeprom is attached to */ struct panel_generic_dpi_data { const char *name; int (*platform_enable)(struct omap_dss_device *dssdev); void (*platform_disable)(struct omap_dss_device *dssdev); + u16 i2c_bus_num; }; #endif /* __ARCH_ARM_PLAT_OMAP_PANEL_GENERIC_DPI_H */ diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index 1c0b0401594..2a710b0a6df 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -320,6 +320,29 @@ s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip, return pull; } #endif + +#ifdef CONFIG_CPU_EXYNOS4210 +int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull) +{ + if (pull == S3C_GPIO_PULL_UP) + pull = 3; + + return s3c_gpio_setpull_updown(chip, off, pull); +} + +s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip, + unsigned int off) +{ + s3c_gpio_pull_t pull; + + pull = s3c_gpio_getpull_updown(chip, off); + if (pull == 3) + pull = S3C_GPIO_PULL_UP; + + return pull; +} +#endif /* CONFIG_CPU_EXYNOS4210 */ #endif #if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN) diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h index 5603db0b79b..75c46b9f505 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h @@ -247,5 +247,30 @@ extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip, extern s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip, unsigned int off); +/** + * s3c_gpio_setpull_exynos4() - Pull configuration for Exynos 4210. + * @chip: The gpio chip that is being configured. + * @off: The offset for the GPIO being configured. + * @param: pull: The pull mode being requested. + * + * This is a wrapper function for s3c_gpio_setpull_updown() function. + * It provides a different mapping of S3C_GPIO_PULL_XXX to actual + * register settings. + */ +extern int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull); + +/** + * s3c_gpio_getpull_exynos4() - Get configuration for Exynos 4210 pull resistors + * @chip: The gpio chip that the GPIO pin belongs to + * @off: The offset to the pin to get the configuration of. + * + * This is a wrapper function for s3c_gpio_getpull_updown() function. + * It provides a different mapping of S3C_GPIO_PULL_XXX to actual + * register settings. +*/ +extern s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip, + unsigned int off); + #endif /* __PLAT_GPIO_CFG_HELPERS_H */ diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index bbf3da012af..f74695075e6 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -78,6 +78,14 @@ static void vfp_thread_exit(struct thread_info *thread) put_cpu(); } +static void vfp_thread_copy(struct thread_info *thread) +{ + struct thread_info *parent = current_thread_info(); + + vfp_sync_hwstate(parent); + thread->vfpstate = parent->vfpstate; +} + /* * When this function is called with the following 'cmd's, the following * is true while this function is being run: @@ -104,12 +112,17 @@ static void vfp_thread_exit(struct thread_info *thread) static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) { struct thread_info *thread = v; + u32 fpexc; +#ifdef CONFIG_SMP + unsigned int cpu; +#endif - if (likely(cmd == THREAD_NOTIFY_SWITCH)) { - u32 fpexc = fmrx(FPEXC); + switch (cmd) { + case THREAD_NOTIFY_SWITCH: + fpexc = fmrx(FPEXC); #ifdef CONFIG_SMP - unsigned int cpu = thread->cpu; + cpu = thread->cpu; /* * On SMP, if VFP is enabled, save the old state in @@ -134,13 +147,20 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) * old state. */ fmxr(FPEXC, fpexc & ~FPEXC_EN); - return NOTIFY_DONE; - } + break; - if (cmd == THREAD_NOTIFY_FLUSH) + case THREAD_NOTIFY_FLUSH: vfp_thread_flush(thread); - else + break; + + case THREAD_NOTIFY_EXIT: vfp_thread_exit(thread); + break; + + case THREAD_NOTIFY_COPY: + vfp_thread_copy(thread); + break; + } return NOTIFY_DONE; } diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index fcbe3f5c074..59abf59ef6c 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -357,7 +357,7 @@ void account_system_vtime(struct task_struct *tsk) } get_paca()->user_time_scaled += user_scaled; - if (in_irq() || idle_task(smp_processor_id()) != tsk) { + if (in_interrupt() || idle_task(smp_processor_id()) != tsk) { account_system_time(tsk, 0, delta, sys_scaled); if (stolen) account_steal_time(stolen); diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index 8fe2a4966b7..4292df78c9d 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S @@ -1612,6 +1612,7 @@ _zero_cipher_left_encrypt: movdqa SHUF_MASK(%rip), %xmm10 PSHUFB_XMM %xmm10, %xmm0 + ENCRYPT_SINGLE_BLOCK %xmm0, %xmm1 # Encrypt(K, Yn) sub $16, %r11 add %r13, %r11 @@ -1634,7 +1635,9 @@ _zero_cipher_left_encrypt: # GHASH computation for the last <16 byte block sub %r13, %r11 add $16, %r11 - PSHUFB_XMM %xmm10, %xmm1 + + movdqa SHUF_MASK(%rip), %xmm10 + PSHUFB_XMM %xmm10, %xmm0 # shuffle xmm0 back to output as ciphertext diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index e1e60c7d581..b375b2a7a14 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -828,9 +828,15 @@ static int rfc4106_init(struct crypto_tfm *tfm) struct cryptd_aead *cryptd_tfm; struct aesni_rfc4106_gcm_ctx *ctx = (struct aesni_rfc4106_gcm_ctx *) PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN); + struct crypto_aead *cryptd_child; + struct aesni_rfc4106_gcm_ctx *child_ctx; cryptd_tfm = cryptd_alloc_aead("__driver-gcm-aes-aesni", 0, 0); if (IS_ERR(cryptd_tfm)) return PTR_ERR(cryptd_tfm); + + cryptd_child = cryptd_aead_child(cryptd_tfm); + child_ctx = aesni_rfc4106_gcm_ctx_get(cryptd_child); + memcpy(child_ctx, ctx, sizeof(*ctx)); ctx->cryptd_tfm = cryptd_tfm; tfm->crt_aead.reqsize = sizeof(struct aead_request) + crypto_aead_reqsize(&cryptd_tfm->base); @@ -925,6 +931,9 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, int ret = 0; struct crypto_tfm *tfm = crypto_aead_tfm(parent); struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent); + struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); + struct aesni_rfc4106_gcm_ctx *child_ctx = + aesni_rfc4106_gcm_ctx_get(cryptd_child); u8 *new_key_mem = NULL; if (key_len < 4) { @@ -968,6 +977,7 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, goto exit; } ret = rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len); + memcpy(child_ctx, ctx, sizeof(*ctx)); exit: kfree(new_key_mem); return ret; @@ -999,7 +1009,6 @@ static int rfc4106_encrypt(struct aead_request *req) int ret; struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm); - struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); if (!irq_fpu_usable()) { struct aead_request *cryptd_req = @@ -1008,6 +1017,7 @@ static int rfc4106_encrypt(struct aead_request *req) aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); return crypto_aead_encrypt(cryptd_req); } else { + struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); kernel_fpu_begin(); ret = cryptd_child->base.crt_aead.encrypt(req); kernel_fpu_end(); @@ -1020,7 +1030,6 @@ static int rfc4106_decrypt(struct aead_request *req) int ret; struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm); - struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); if (!irq_fpu_usable()) { struct aead_request *cryptd_req = @@ -1029,6 +1038,7 @@ static int rfc4106_decrypt(struct aead_request *req) aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); return crypto_aead_decrypt(cryptd_req); } else { + struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); kernel_fpu_begin(); ret = cryptd_child->base.crt_aead.decrypt(req); kernel_fpu_end(); diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index bebabec5b44..151787e382c 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -292,14 +292,24 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ /* * HACK! - * We use this same function to initialize the mtrrs on boot. - * The state of the boot cpu's mtrrs has been saved, and we want - * to replicate across all the APs. - * If we're doing that @reg is set to something special... + * + * We use this same function to initialize the mtrrs during boot, + * resume, runtime cpu online and on an explicit request to set a + * specific MTRR. + * + * During boot or suspend, the state of the boot cpu's mtrrs has been + * saved, and we want to replicate that across all the cpus that come + * online (either at the end of boot or resume or during a runtime cpu + * online). If we're doing that, @reg is set to something special and on + * this cpu we still do mtrr_if->set_all(). During boot/resume, this + * is unnecessary if at this point we are still on the cpu that started + * the boot/resume sequence. But there is no guarantee that we are still + * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be + * sure that we are in sync with everyone else. */ if (reg != ~0U) mtrr_if->set(reg, base, size, type); - else if (!mtrr_aps_delayed_init) + else mtrr_if->set_all(); /* Wait for the others */ diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 5655c2272ad..2d2673c28af 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -77,6 +77,9 @@ void __init x86_64_start_kernel(char * real_mode_data) /* Make NULL pointers segfault */ zap_identity_mappings(); + /* Cleanup the over mapped high alias */ + cleanup_highmap(); + max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT; for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) { diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index e543fe9311e..d3cfe26c025 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -297,9 +297,6 @@ static void __init init_gbpages(void) static inline void init_gbpages(void) { } -static void __init cleanup_highmap(void) -{ -} #endif static void __init reserve_brk(void) @@ -925,8 +922,6 @@ void __init setup_arch(char **cmdline_p) */ reserve_brk(); - cleanup_highmap(); - memblock.current_limit = get_max_mapped(); memblock_x86_fill(); diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index f13ff3a2267..947f42abe82 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -279,6 +279,25 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, load_cr3(swapper_pg_dir); #endif +#ifdef CONFIG_X86_64 + if (!after_bootmem && !start) { + pud_t *pud; + pmd_t *pmd; + + mmu_cr4_features = read_cr4(); + + /* + * _brk_end cannot change anymore, but it and _end may be + * located on different 2M pages. cleanup_highmap(), however, + * can only consider _end when it runs, so destroy any + * mappings beyond _brk_end here. + */ + pud = pud_offset(pgd_offset_k(_brk_end), _brk_end); + pmd = pmd_offset(pud, _brk_end - 1); + while (++pmd <= pmd_offset(pud, (unsigned long)_end - 1)) + pmd_clear(pmd); + } +#endif __flush_tlb_all(); if (!after_bootmem && e820_table_end > e820_table_start) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 68f9921ae9c..c14a5422e15 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -51,7 +51,6 @@ #include <asm/numa.h> #include <asm/cacheflush.h> #include <asm/init.h> -#include <asm/setup.h> static int __init parse_direct_gbpages_off(char *arg) { @@ -294,18 +293,18 @@ void __init init_extra_mapping_uc(unsigned long phys, unsigned long size) * to the compile time generated pmds. This results in invalid pmds up * to the point where we hit the physaddr 0 mapping. * - * We limit the mappings to the region from _text to _brk_end. _brk_end - * is rounded up to the 2MB boundary. This catches the invalid pmds as + * We limit the mappings to the region from _text to _end. _end is + * rounded up to the 2MB boundary. This catches the invalid pmds as * well, as they are located before _text: */ void __init cleanup_highmap(void) { unsigned long vaddr = __START_KERNEL_map; - unsigned long vaddr_end = __START_KERNEL_map + (max_pfn_mapped << PAGE_SHIFT); - unsigned long end = roundup((unsigned long)_brk_end, PMD_SIZE) - 1; + unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1; pmd_t *pmd = level2_kernel_pgt; + pmd_t *last_pmd = pmd + PTRS_PER_PMD; - for (; vaddr + PMD_SIZE - 1 < vaddr_end; pmd++, vaddr += PMD_SIZE) { + for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) { if (pmd_none(*pmd)) continue; if (vaddr < (unsigned long) _text || vaddr > end) |