From 3ea3aa8cf67d3bbe00a19b6a4013d19efa7d0f41 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 8 Dec 2010 10:49:43 +0800 Subject: KVM: Fix OSXSAVE after migration CPUID's OSXSAVE is a mirror of CR4.OSXSAVE bit. We need to update the CPUID after migration. KVM-Stable-Tag. Signed-off-by: Sheng Yang Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index cdac9e592aa5..eb5c83479d89 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5522,6 +5522,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4; kvm_x86_ops->set_cr4(vcpu, sregs->cr4); + if (sregs->cr4 & X86_CR4_OSXSAVE) + update_cpuid(vcpu); if (!is_long_mode(vcpu) && is_pae(vcpu)) { load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3); mmu_reset_needed = 1; -- cgit v1.2.2 From 24d1b15f72abe3465e871d11cfc9dc34d1aab8b2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 7 Dec 2010 17:15:05 +0100 Subject: KVM: SVM: Do not report xsave in supported cpuid To support xsave properly for the guest the SVM module need software support for it. As long as this is not present do not report the xsave as supported feature in cpuid. As a side-effect this patch moves the bit() helper function into the x86.h file so that it can be used in svm.c too. KVM-Stable-Tag. Signed-off-by: Joerg Roedel Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 4 ++++ arch/x86/kvm/vmx.c | 5 ----- arch/x86/kvm/x86.c | 5 ----- arch/x86/kvm/x86.h | 5 +++++ 4 files changed, 9 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 1ca12298ffc7..b81a9b7c2ca4 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3494,6 +3494,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu) static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry) { switch (func) { + case 0x00000001: + /* Mask out xsave bit as long as it is not supported by SVM */ + entry->ecx &= ~(bit(X86_FEATURE_XSAVE)); + break; case 0x80000001: if (nested) entry->ecx |= (1 << 2); /* Set SVM bit */ diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ff21fdda0c53..81fcbe9515c5 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4227,11 +4227,6 @@ static int vmx_get_lpage_level(void) return PT_PDPE_LEVEL; } -static inline u32 bit(int bitno) -{ - return 1 << (bitno & 31); -} - static void vmx_cpuid_update(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index eb5c83479d89..e3abd84750c7 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -155,11 +155,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { u64 __read_mostly host_xcr0; -static inline u32 bit(int bitno) -{ - return 1 << (bitno & 31); -} - static void kvm_on_user_return(struct user_return_notifier *urn) { unsigned slot; diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 2cea414489f3..c600da830ce0 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -70,6 +70,11 @@ static inline int is_paging(struct kvm_vcpu *vcpu) return kvm_read_cr0_bits(vcpu, X86_CR0_PG); } +static inline u32 bit(int bitno) +{ + return 1 << (bitno & 31); +} + void kvm_before_handle_nmi(struct kvm_vcpu *vcpu); void kvm_after_handle_nmi(struct kvm_vcpu *vcpu); int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq); -- cgit v1.2.2 From 73c1160ce377d8fc6d84cb630ebf9658808bec49 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 1 Dec 2010 12:17:44 +0100 Subject: KVM: enlarge number of possible CPUID leaves Currently the number of CPUID leaves KVM handles is limited to 40. My desktop machine (AthlonII) already has 35 and future CPUs will expand this well beyond the limit. Extend the limit to 80 to make room for future processors. KVM-Stable-Tag. Signed-off-by: Andre Przywara Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 9e6fe391094e..f702f82aa1eb 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -79,7 +79,7 @@ #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT) #define KVM_MIN_FREE_MMU_PAGES 5 #define KVM_REFILL_PAGES 25 -#define KVM_MAX_CPUID_ENTRIES 40 +#define KVM_MAX_CPUID_ENTRIES 80 #define KVM_NR_FIXED_MTRR_REGION 88 #define KVM_NR_VAR_MTRR 8 -- cgit v1.2.2 From 4720dd1b3858f0da2593188cb1e57eb0d3bc4af2 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 9 Dec 2010 17:43:21 +0100 Subject: x86: io_apic: Avoid unused variable warning when CONFIG_GENERIC_PENDING_IRQ=n arch/x86/kernel/apic/io_apic.c: In function 'ack_apic_level': arch/x86/kernel/apic/io_apic.c:2433: warning: unused variable 'desc' Signed-off-by: Andrew Morton LKML-Reference: <201010272107.o9RL7rse018212@imap1.linux-foundation.org> Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/io_apic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 7cc0a721f628..226060eec341 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2430,13 +2430,12 @@ static void ack_apic_level(struct irq_data *data) { struct irq_cfg *cfg = data->chip_data; int i, do_unmask_irq = 0, irq = data->irq; - struct irq_desc *desc = irq_to_desc(irq); unsigned long v; irq_complete_move(cfg); #ifdef CONFIG_GENERIC_PENDING_IRQ /* If we are moving the irq we need to mask it */ - if (unlikely(desc->status & IRQ_MOVE_PENDING)) { + if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) { do_unmask_irq = 1; mask_ioapic(cfg); } -- cgit v1.2.2 From f1c18071ad70e2a78ab31fc26a18fcfa954a05c6 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 13 Dec 2010 12:43:23 +0100 Subject: x86: HPET: Chose a paranoid safe value for the ETIME check commit 995bd3bb5 (x86: Hpet: Avoid the comparator readback penalty) chose 8 HPET cycles as a safe value for the ETIME check, as we had the confirmation that the posted write to the comparator register is delayed by two HPET clock cycles on Intel chipsets which showed readback problems. After that patch hit mainline we got reports from machines with newer AMD chipsets which seem to have an even longer delay. See http://thread.gmane.org/gmane.linux.kernel/1054283 and http://thread.gmane.org/gmane.linux.kernel/1069458 for further information. Boris tried to come up with an ACPI based selection of the minimum HPET cycles, but this failed on a couple of test machines. And of course we did not get any useful information from the hardware folks. For now our only option is to chose a paranoid high and safe value for the minimum HPET cycles used by the ETIME check. Adjust the minimum ns value for the HPET clockevent accordingly. Reported-Bistected-and-Tested-by: Markus Trippelsdorf Signed-off-by: Thomas Gleixner LKML-Reference: Cc: Simon Kirby Cc: Borislav Petkov Cc: Andreas Herrmann Cc: John Stultz --- arch/x86/kernel/hpet.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ae03cab4352e..4ff5968f12d2 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -27,6 +27,9 @@ #define HPET_DEV_FSB_CAP 0x1000 #define HPET_DEV_PERI_CAP 0x2000 +#define HPET_MIN_CYCLES 128 +#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1)) + #define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt) /* @@ -299,8 +302,9 @@ static void hpet_legacy_clockevent_register(void) /* Calculate the min / max delta */ hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, &hpet_clockevent); - /* 5 usec minimum reprogramming delta. */ - hpet_clockevent.min_delta_ns = 5000; + /* Setup minimum reprogramming delta. */ + hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, + &hpet_clockevent); /* * Start hpet with the boot cpu mask and make it @@ -393,22 +397,24 @@ static int hpet_next_event(unsigned long delta, * the wraparound into account) nor a simple count down event * mode. Further the write to the comparator register is * delayed internally up to two HPET clock cycles in certain - * chipsets (ATI, ICH9,10). We worked around that by reading - * back the compare register, but that required another - * workaround for ICH9,10 chips where the first readout after - * write can return the old stale value. We already have a - * minimum delta of 5us enforced, but a NMI or SMI hitting + * chipsets (ATI, ICH9,10). Some newer AMD chipsets have even + * longer delays. We worked around that by reading back the + * compare register, but that required another workaround for + * ICH9,10 chips where the first readout after write can + * return the old stale value. We already had a minimum + * programming delta of 5us enforced, but a NMI or SMI hitting * between the counter readout and the comparator write can * move us behind that point easily. Now instead of reading * the compare register back several times, we make the ETIME * decision based on the following: Return ETIME if the - * counter value after the write is less than 8 HPET cycles + * counter value after the write is less than HPET_MIN_CYCLES * away from the event or if the counter is already ahead of - * the event. + * the event. The minimum programming delta for the generic + * clockevents code is set to 1.5 * HPET_MIN_CYCLES. */ res = (s32)(cnt - hpet_readl(HPET_COUNTER)); - return res < 8 ? -ETIME : 0; + return res < HPET_MIN_CYCLES ? -ETIME : 0; } static void hpet_legacy_set_mode(enum clock_event_mode mode, -- cgit v1.2.2 From de2a8cf98ecdde25231d6c5e7901e2cffaf32af9 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 13 Dec 2010 16:01:38 -0800 Subject: x86, gcc-4.6: Use gcc -m options when building vdso The vdso Makefile passes linker-style -m options not to the linker but to gcc. This happens to work with earlier gcc, but fails with gcc 4.6. Pass gcc-style -m options, instead. Note: all currently supported versions of gcc supports -m32, so there is no reason to conditionalize it any more. Reported-by: H. J. Lu Signed-off-by: H. Peter Anvin LKML-Reference: Cc: --- arch/x86/vdso/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile index 4a2afa1bac51..b6552b189bcd 100644 --- a/arch/x86/vdso/Makefile +++ b/arch/x86/vdso/Makefile @@ -25,7 +25,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y) export CPPFLAGS_vdso.lds += -P -C -VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \ +VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so @@ -69,7 +69,7 @@ vdso32.so-$(VDSO32-y) += sysenter vdso32-images = $(vdso32.so-y:%=vdso32-%.so) CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) -VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1 +VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1 # This makes sure the $(obj) subdirectory exists even though vdso32/ # is not a kbuild sub-make subdirectory. -- cgit v1.2.2 From 10340ae130fb70352eae1ae8a00b7906d91bf166 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 16 Nov 2010 13:23:51 -0800 Subject: x86, xsave: Use alloc_bootmem_align() instead of alloc_bootmem() Alignment of alloc_bootmem() depends on the value of L1_CACHE_SHIFT. What we need here, however, is 64 byte alignment. Use alloc_bootmem_align() and explicitly specify the alignment instead. This fixes a kernel boot crash reported by Jody when the cpu in .config is set to MPENTIUMII but the kernel is booted on a xsave-capable CPU. Reported-by: Jody Bruchon Signed-off-by: Suresh Siddha LKML-Reference: <20101116212442.059967454@sbsiddha-MOBL3.sc.intel.com> Signed-off-by: H. Peter Anvin Cc: --- arch/x86/kernel/xsave.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 9c253bd65e24..547128546cc3 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -394,7 +394,8 @@ static void __init setup_xstate_init(void) * Setup init_xstate_buf to represent the init state of * all the features managed by the xsave */ - init_xstate_buf = alloc_bootmem(xstate_size); + init_xstate_buf = alloc_bootmem_align(xstate_size, + __alignof__(struct xsave_struct)); init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; clts(); -- cgit v1.2.2 From 086e8ced65d9bcc4a8e8f1cd39b09640f2883f90 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 1 Dec 2010 09:40:32 -0800 Subject: x86, vt-d: Fix the vt-d fault handling irq migration in the x2apic mode In x2apic mode, we need to set the upper address register of the fault handling interrupt register of the vt-d hardware. Without this irq migration of the vt-d fault handling interrupt is broken. Signed-off-by: Kenji Kaneshige LKML-Reference: <1291225233.2648.39.camel@sbsiddha-MOBL3> Signed-off-by: Suresh Siddha Cc: stable@kernel.org [v2.6.32+] Acked-by: Chris Wright Tested-by: Takao Indoh Signed-off-by: H. Peter Anvin --- arch/x86/kernel/apic/io_apic.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 226060eec341..fadcd743a74f 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3412,6 +3412,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask, msg.data |= MSI_DATA_VECTOR(cfg->vector); msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; msg.address_lo |= MSI_ADDR_DEST_ID(dest); + msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest); dmar_msi_write(irq, &msg); -- cgit v1.2.2 From 7f7fbf45c6b748074546f7f16b9488ca71de99c1 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 30 Nov 2010 22:22:28 -0800 Subject: x86: Enable the intr-remap fault handling after local APIC setup Interrupt-remapping gets enabled very early in the boot, as it determines the apic mode that the processor can use. And the current code enables the vt-d fault handling before the setup_local_APIC(). And hence the APIC LDR registers and data structure in the memory may not be initialized. So the vt-d fault handling in logical xapic/x2apic modes were broken. Fix this by enabling the vt-d fault handling in the end_local_APIC_setup() A cleaner fix of enabling fault handling while enabling intr-remapping will be addressed for v2.6.38. [ Enabling intr-remapping determines the usage of x2apic mode and the apic mode determines the fault-handling configuration. ] Signed-off-by: Kenji Kaneshige LKML-Reference: <20101201062244.541996375@intel.com> Signed-off-by: Suresh Siddha Cc: stable@kernel.org [v2.6.32+] Acked-by: Chris Wright Signed-off-by: H. Peter Anvin --- arch/x86/kernel/apic/apic.c | 8 ++++++++ arch/x86/kernel/apic/probe_64.c | 7 ------- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 3f838d537392..78218135b48e 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1389,6 +1389,14 @@ void __cpuinit end_local_APIC_setup(void) setup_apic_nmi_watchdog(NULL); apic_pm_activate(); + + /* + * Now that local APIC setup is completed for BP, configure the fault + * handling for interrupt remapping. + */ + if (!smp_processor_id() && intr_remapping_enabled) + enable_drhd_fault_handling(); + } #ifdef CONFIG_X86_X2APIC diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index f9e4e6a54073..d8c4a6feb286 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c @@ -79,13 +79,6 @@ void __init default_setup_apic_routing(void) /* need to update phys_pkg_id */ apic->phys_pkg_id = apicid_phys_pkg_id; } - - /* - * Now that apic routing model is selected, configure the - * fault handling for intr remapping. - */ - if (intr_remapping_enabled) - enable_drhd_fault_handling(); } /* Same for both flat and physical. */ -- cgit v1.2.2 From a74b74a5555c741ed3df896096e33b853995631e Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 15 Dec 2010 07:20:16 +0800 Subject: ARM: pxa: PXA_ESERIES depends on FB_W100. As arch/arm/mach-pxa/eseries.c references w100fb_gpio_{read,write}() directly. Signed-off-by: Lennert Buytenhek Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index dd235ecc9d6c..c93e73d54dd1 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -540,6 +540,7 @@ config MACH_ICONTROL config ARCH_PXA_ESERIES bool "PXA based Toshiba e-series PDAs" select PXA25x + select FB_W100 config MACH_E330 bool "Toshiba e330" -- cgit v1.2.2 From 3e26f23091da06d02fa62da14c95f3688d27857c Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 16 Dec 2010 12:16:34 +0200 Subject: KVM: Fix preemption counter leak in kvm_timer_init() Based on a patch from Thomas Meyer. Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e3abd84750c7..b989e1f1e5d3 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4564,9 +4564,11 @@ static void kvm_timer_init(void) #ifdef CONFIG_CPU_FREQ struct cpufreq_policy policy; memset(&policy, 0, sizeof(policy)); - cpufreq_get_policy(&policy, get_cpu()); + cpu = get_cpu(); + cpufreq_get_policy(&policy, cpu); if (policy.cpuinfo.max_freq) max_tsc_khz = policy.cpuinfo.max_freq; + put_cpu(); #endif cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); -- cgit v1.2.2 From 2b3e50234eafc40a04f5f4a2b7bb24b506fd7e87 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 2 Nov 2010 19:38:53 +0000 Subject: MIPS: Swarm: Fix typo in symbol name: RTC_M4LT81 -> RTC_M41T81 Signed-off-by: Ralf Baechle --- arch/mips/sibyte/swarm/setup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index c308989fc464..41707a245dea 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c @@ -82,7 +82,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup) enum swarm_rtc_type { RTC_NONE, RTC_XICOR, - RTC_M4LT81 + RTC_M41T81, }; enum swarm_rtc_type swarm_rtc_type; @@ -96,7 +96,7 @@ void read_persistent_clock(struct timespec *ts) sec = xicor_get_time(); break; - case RTC_M4LT81: + case RTC_M41T81: sec = m41t81_get_time(); break; @@ -115,7 +115,7 @@ int rtc_mips_set_time(unsigned long sec) case RTC_XICOR: return xicor_set_time(sec); - case RTC_M4LT81: + case RTC_M41T81: return m41t81_set_time(sec); case RTC_NONE: @@ -141,7 +141,7 @@ void __init plat_mem_setup(void) if (xicor_probe()) swarm_rtc_type = RTC_XICOR; if (m41t81_probe()) - swarm_rtc_type = RTC_M4LT81; + swarm_rtc_type = RTC_M41T81; #ifdef CONFIG_VT screen_info = (struct screen_info) { -- cgit v1.2.2 From a989ff898f9740651d00388c33bdf4f2a7914920 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 4 Nov 2010 11:13:59 +0000 Subject: MIPS: Don't stomp on caller's ->regs[2] in copy_thread() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We never needed that (->regs[2] is overwritten on return from syscall paths with return value of syscall, so storing it there early made no sense) and with new restart logics since d27240bf7e61d2656de18e158ec910a902030847 it has become really bad - we lose the original syscall number before the place where we decide that we might need a syscall restart. Note that for child we do need the assignment to regs[2] - it won't go through the normal return from syscall path. [Ralf: Issue found and reported by Lluís; initial investigations by me; bug finally found and patch by Al; testing by me and Lluís.] Signed-off-by: Al Viro Tested-by: Lluís Batlle i Rossell Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 99960940d4a4..ae167df73ddd 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -142,7 +142,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childregs->regs[7] = 0; /* Clear error flag */ childregs->regs[2] = 0; /* Child gets zero as return value */ - regs->regs[2] = p->pid; if (childregs->cp0_status & ST0_CU0) { childregs->regs[28] = (unsigned long) ti; -- cgit v1.2.2 From fe749aab1d21cbb4d87527a7df8799583c233496 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 4 Nov 2010 23:25:56 +0100 Subject: MIPS: jz4740: qi_lb60: Fix gpio for the 6th row of the keyboard matrix This patch fixes the gpio number for the 6th row of the keyboard matrix. (And fixes a typo in my name...) Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: stable@kernel.org Signed-off-by: https://patchwork.linux-mips.org/patch/1754/ Signed-off-by: Ralf Baechle --- arch/mips/jz4740/board-qi_lb60.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 5742bb4d78f4..5c0a3575877c 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -5,7 +5,7 @@ * * Copyright (c) 2009 Qi Hardware inc., * Author: Xiangfu Liu - * Copyright 2010, Lars-Petrer Clausen + * Copyright 2010, Lars-Peter Clausen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 or later @@ -235,7 +235,7 @@ static const unsigned int qi_lb60_keypad_rows[] = { QI_LB60_GPIO_KEYIN(3), QI_LB60_GPIO_KEYIN(4), QI_LB60_GPIO_KEYIN(5), - QI_LB60_GPIO_KEYIN(7), + QI_LB60_GPIO_KEYIN(6), QI_LB60_GPIO_KEYIN8, }; -- cgit v1.2.2 From 1d210386f6ef9000b1cd723cf453c5eb0377e722 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 4 Nov 2010 23:25:57 +0100 Subject: MIPS: jz4740: Fix section mismatch in prom.c This patch fixes the following section mismatch: WARNING: arch/mips/built-in.o(.text+0xc): Section mismatch in reference from the function jz4740_init_cmdline() to the variable .init.data:arcs_cmdline While were at it, make jz4740_init_cmdline static as well. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1755/ Signed-off-by: Ralf Baechle --- arch/mips/jz4740/prom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c index cfeac15eb2e4..4a70407f55bb 100644 --- a/arch/mips/jz4740/prom.c +++ b/arch/mips/jz4740/prom.c @@ -23,7 +23,7 @@ #include #include -void jz4740_init_cmdline(int argc, char *argv[]) +static __init void jz4740_init_cmdline(int argc, char *argv[]) { unsigned int count = COMMAND_LINE_SIZE - 1; int i; -- cgit v1.2.2 From 1c0d52b9b5e6ca277c13d6fece9c34ed3159423d Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 1 Nov 2010 17:43:07 -0700 Subject: MIPS: Don't clobber personality high bits. The high bits of current->personality carry settings that we don't want to clobber on each exec. Only clobber them if the lower bits that indicate either PER_LINUX or PER_LINUX32 are invalid. The clobbering prevents us from using useful bits like ADDR_NO_RANDOMIZE. Reported-by: Camm Maguire Signed-off-by: David Daney Cc: Camm Maguire Patchwork: https://patchwork.linux-mips.org/patch/1750/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index fd1d39eb7431..455c0ac7d4ea 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -249,7 +249,8 @@ extern struct mips_abi mips_abi_n32; #define SET_PERSONALITY(ex) \ do { \ - set_personality(PER_LINUX); \ + if (personality(current->personality) != PER_LINUX) \ + set_personality(PER_LINUX); \ \ current->thread.abi = &mips_abi; \ } while (0) @@ -296,6 +297,8 @@ do { \ #define SET_PERSONALITY(ex) \ do { \ + unsigned int p; \ + \ clear_thread_flag(TIF_32BIT_REGS); \ clear_thread_flag(TIF_32BIT_ADDR); \ \ @@ -304,7 +307,8 @@ do { \ else \ current->thread.abi = &mips_abi; \ \ - if (current->personality != PER_LINUX32) \ + p = personality(current->personality); \ + if (p != PER_LINUX32 && p != PER_LINUX) \ set_personality(PER_LINUX); \ } while (0) -- cgit v1.2.2 From d62c9ced7ca783e64ff4d9d3d1340cfe2284d47b Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 1 Nov 2010 17:43:08 -0700 Subject: MIPS: compat: Don't clobber personality bits in 32-bit sys_personality(). If PER_LINUX32 has been set on a 32-bit kernel, only twiddle with the low-order personality bits, let the upper bits pass through. Signed-off-by: David Daney To: linux-mips@linux-mips.org Cc: Camm Maguire Patchwork: https://patchwork.linux-mips.org/patch/1751/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/linux32.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 6343b4a5b835..876a75cc376f 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -251,14 +251,15 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz, SYSCALL_DEFINE1(32_personality, unsigned long, personality) { + unsigned int p = personality & 0xffffffff; int ret; - personality &= 0xffffffff; + if (personality(current->personality) == PER_LINUX32 && - personality == PER_LINUX) - personality = PER_LINUX32; - ret = sys_personality(personality); - if (ret == PER_LINUX32) - ret = PER_LINUX; + personality(p) == PER_LINUX) + p = (p & ~PER_MASK) | PER_LINUX32; + ret = sys_personality(p); + if (ret != -1 && personality(ret) == PER_LINUX32) + ret = (ret & ~PER_MASK) | PER_LINUX; return ret; } -- cgit v1.2.2 From 863abad4f644b6c12bc8176206b35fa7e7cfe1a9 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 30 Oct 2010 18:37:16 +0200 Subject: MIPS: VPE loader: Check vmalloc return value in vpe_open The return value of the vmalloc() call in arch/mips/kernel/vpe.c::vpe_open() is not checked, so we potentially store a null pointer in v->pbuffer. Add a check for a null return and then return -ENOMEM in that case. [Ralf: The check added by Jesper's original patch is where it logically should be. Adding it eleminated the need for the checks in a few other places, so I removed them. There still is a zillion of other things that need to be fixed in this file / API.] Signed-off-by: Jesper Juhl Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1747/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/vpe.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 3eb3cde2f661..6a1fdfef8fde 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -1092,6 +1092,10 @@ static int vpe_open(struct inode *inode, struct file *filp) /* this of-course trashes what was there before... */ v->pbuffer = vmalloc(P_SIZE); + if (!v->pbuffer) { + pr_warning("VPE loader: unable to allocate memory\n"); + return -ENOMEM; + } v->plen = P_SIZE; v->load_addr = NULL; v->len = 0; @@ -1149,10 +1153,9 @@ static int vpe_release(struct inode *inode, struct file *filp) if (ret < 0) v->shared_ptr = NULL; - // cleanup any temp buffers - if (v->pbuffer) - vfree(v->pbuffer); + vfree(v->pbuffer); v->plen = 0; + return ret; } @@ -1169,11 +1172,6 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer, if (v == NULL) return -ENODEV; - if (v->pbuffer == NULL) { - printk(KERN_ERR "VPE loader: no buffer for program\n"); - return -ENOMEM; - } - if ((count + v->len) > v->plen) { printk(KERN_WARNING "VPE loader: elf size too big. Perhaps strip uneeded symbols\n"); -- cgit v1.2.2 From ec79812580e360081b58c3e2e8b5b69b8080b5a0 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Mon, 8 Nov 2010 21:25:24 +0800 Subject: MIPS: Loongson: Add return value check for strict_strtoul() cc1: warnings being treated as errors arch/mips/loongson/common/env.c: In function 'prom_init_env': arch/mips/loongson/common/env.c:49: error: ignoring return value of 'strict_strtol', declared with attribute warn_unused_result arch/mips/loongson/common/env.c:50: error: ignoring return value of 'strict_strtol', declared with attribute warn_unused_result arch/mips/loongson/common/env.c:51: error: ignoring return value of 'strict_strtol', declared with attribute warn_unused_result arch/mips/loongson/common/env.c:52: error: ignoring return value of 'strict_strtol', declared with attribute warn_unused_result Signed-off-by: Wu Zhangjin Cc: linux-mips Patchwork: https://patchwork.linux-mips.org/patch/1762/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/env.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c index ae4cff97a56c..11b193f848f8 100644 --- a/arch/mips/loongson/common/env.c +++ b/arch/mips/loongson/common/env.c @@ -29,9 +29,9 @@ unsigned long memsize, highmemsize; #define parse_even_earlier(res, option, p) \ do { \ + int ret; \ if (strncmp(option, (char *)p, strlen(option)) == 0) \ - strict_strtol((char *)p + strlen(option"="), \ - 10, &res); \ + ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \ } while (0) void __init prom_init_env(void) -- cgit v1.2.2 From 690ca2ce0c824e8d3da7b2e273c2c873ab96d1e6 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Mon, 8 Nov 2010 17:23:52 +0900 Subject: MIPS: Alchemy: Add return value check for strict_strtoul() arch/mips/alchemy/devboards/prom.c: In function 'prom_init': arch/mips/alchemy/devboards/prom.c:60: error: ignoring return value of 'strict_strtoul', declared with attribute warn_unused_result Signed-off-by: Yoichi Yuasa Cc: linux-mips Patchwork: https://patchwork.linux-mips.org/patch/1761/ Signed-off-by: Ralf Baechle --- arch/mips/alchemy/devboards/prom.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/alchemy/devboards/prom.c b/arch/mips/alchemy/devboards/prom.c index b30df5c97ad3..baeb21385058 100644 --- a/arch/mips/alchemy/devboards/prom.c +++ b/arch/mips/alchemy/devboards/prom.c @@ -54,10 +54,9 @@ void __init prom_init(void) prom_init_cmdline(); memsize_str = prom_getenv("memsize"); - if (!memsize_str) + if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize)) memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE; - else - strict_strtoul(memsize_str, 0, &memsize); + add_memory_region(0, memsize, BOOT_MEM_RAM); } -- cgit v1.2.2 From 3bd27e329ca80f4946efdd12bf1f5a9bf0886e76 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 5 Nov 2010 15:12:48 -0700 Subject: MIPS: Rework GENERIC_HARDIRQS Kconfig. Recent changes to CONFIG_GENERIC_HARDIRQS have caused us to start getting: warning: (SMP && SYS_SUPPORTS_SMP) selects IRQ_PER_CPU which has unmet direct dependencies (HAVE_GENERIC_HARDIRQS) Rearranging our Kconfig quiets the message. Signed-off-by: David Daney To: linux-mips@linux-mips.org Cc: Thomas Gleixner Patchwork: https://patchwork.linux-mips.org/patch/1757/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 67a2fa2caa49..7fc6bd1d3852 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -19,6 +19,8 @@ config MIPS select GENERIC_ATOMIC64 if !64BIT select HAVE_DMA_ATTRS select HAVE_DMA_API_DEBUG + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_PROBE menu "Machine selection" @@ -1921,20 +1923,6 @@ config CPU_R4000_WORKAROUNDS config CPU_R4400_WORKAROUNDS bool -# -# Use the generic interrupt handling code in kernel/irq/: -# -config GENERIC_HARDIRQS - bool - default y - -config GENERIC_IRQ_PROBE - bool - default y - -config IRQ_PER_CPU - bool - # # - Highmem only makes sense for the 32-bit kernel. # - The current highmem code will only work properly on physically indexed -- cgit v1.2.2 From ff42d62047e45075c54a5543bd4f110dfd032d11 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sun, 31 Oct 2010 23:49:57 +0100 Subject: MIPS: AR7: Fix double ar7_gpio_init declaration Signed-off-by: Florian Fainelli To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1748/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-ar7/ar7.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h index 7919d76186bf..31c7ff539830 100644 --- a/arch/mips/include/asm/mach-ar7/ar7.h +++ b/arch/mips/include/asm/mach-ar7/ar7.h @@ -202,6 +202,4 @@ static inline void ar7_device_off(u32 bit) int __init ar7_gpio_init(void); -int __init ar7_gpio_init(void); - #endif /* __AR7_H__ */ -- cgit v1.2.2 From 0bc6791707694c77b3543de39f77972a65de917a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sun, 31 Oct 2010 23:49:58 +0100 Subject: MIPS: AR7: Fix loops per jiffies on TNETD7200 devices TNETD7200 run their CPU clock faster than the default CPU clock we assume. In order to have the correct loops per jiffies settings, initialize clocks right before setting mips_hpt_frequency. As a side effect, we can no longer use msleep in clocks.c which requires other parts of the kernel to be initialized, so replace these with mdelay. Signed-off-by: Florian Fainelli To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1749/ Signed-off-by: Ralf Baechle --- arch/mips/ar7/clock.c | 9 +++------ arch/mips/ar7/time.c | 3 +++ arch/mips/include/asm/mach-ar7/ar7.h | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c index fc0e7154e8d6..2ca4ada1c291 100644 --- a/arch/mips/ar7/clock.c +++ b/arch/mips/ar7/clock.c @@ -239,12 +239,12 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock, calculate(base_clock, frequency, &prediv, &postdiv, &mul); writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl); - msleep(1); + mdelay(1); writel(4, &clock->pll); while (readl(&clock->pll) & PLL_STATUS) ; writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll); - msleep(75); + mdelay(75); } static void __init tnetd7300_init_clocks(void) @@ -456,7 +456,7 @@ void clk_put(struct clk *clk) } EXPORT_SYMBOL(clk_put); -int __init ar7_init_clocks(void) +void __init ar7_init_clocks(void) { switch (ar7_chip_id()) { case AR7_CHIP_7100: @@ -472,7 +472,4 @@ int __init ar7_init_clocks(void) } /* adjust vbus clock rate */ vbus_clk.rate = bus_clk.rate / 2; - - return 0; } -arch_initcall(ar7_init_clocks); diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c index 5fb8a0134085..22c93213b233 100644 --- a/arch/mips/ar7/time.c +++ b/arch/mips/ar7/time.c @@ -30,6 +30,9 @@ void __init plat_time_init(void) { struct clk *cpu_clk; + /* Initialize ar7 clocks so the CPU clock frequency is correct */ + ar7_init_clocks(); + cpu_clk = clk_get(NULL, "cpu"); if (IS_ERR(cpu_clk)) { printk(KERN_ERR "unable to get cpu clock\n"); diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h index 31c7ff539830..07d3fadb2443 100644 --- a/arch/mips/include/asm/mach-ar7/ar7.h +++ b/arch/mips/include/asm/mach-ar7/ar7.h @@ -201,5 +201,6 @@ static inline void ar7_device_off(u32 bit) } int __init ar7_gpio_init(void); +void __init ar7_init_clocks(void); #endif /* __AR7_H__ */ -- cgit v1.2.2 From 515b029d005b5694cf612a0a5ca6f861a7e45362 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 21 Oct 2010 16:32:26 -0700 Subject: MIPS: Send proper signal and siginfo on FP emulator faults. We were unconditionally sending SIGBUS with an empty siginfo on FP emulator faults. This differs from what happens when real floating point hardware would get a fault. For most faults we need to send SIGSEGV with the faulting address filled in in the struct siginfo. Reported-by: Camm Maguire Signed-off-by: David Daney To: linux-mips@linux-mips.org Cc: Camm Maguire Patchwork: https://patchwork.linux-mips.org/patch/1727/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 44 +++++++++++++---- arch/mips/math-emu/cp1emu.c | 116 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 130 insertions(+), 30 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 8e9fbe75894e..e97104302541 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -83,7 +83,8 @@ extern asmlinkage void handle_mcheck(void); extern asmlinkage void handle_reserved(void); extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, - struct mips_fpu_struct *ctx, int has_fpu); + struct mips_fpu_struct *ctx, int has_fpu, + void *__user *fault_addr); void (*board_be_init)(void); int (*board_be_handler)(struct pt_regs *regs, int is_fixup); @@ -661,12 +662,36 @@ asmlinkage void do_ov(struct pt_regs *regs) force_sig_info(SIGFPE, &info, current); } +static int process_fpemu_return(int sig, void __user *fault_addr) +{ + if (sig == SIGSEGV || sig == SIGBUS) { + struct siginfo si = {0}; + si.si_addr = fault_addr; + si.si_signo = sig; + if (sig == SIGSEGV) { + if (find_vma(current->mm, (unsigned long)fault_addr)) + si.si_code = SEGV_ACCERR; + else + si.si_code = SEGV_MAPERR; + } else { + si.si_code = BUS_ADRERR; + } + force_sig_info(sig, &si, current); + return 1; + } else if (sig) { + force_sig(sig, current); + return 1; + } else { + return 0; + } +} + /* * XXX Delayed fp exceptions when doing a lazy ctx switch XXX */ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) { - siginfo_t info; + siginfo_t info = {0}; if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP) @@ -675,6 +700,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) if (fcr31 & FPU_CSR_UNI_X) { int sig; + void __user *fault_addr = NULL; /* * Unimplemented operation exception. If we've got the full @@ -690,7 +716,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) lose_fpu(1); /* Run the emulator */ - sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1); + sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, + &fault_addr); /* * We can't allow the emulated instruction to leave any of @@ -702,8 +729,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) own_fpu(1); /* Using the FPU again. */ /* If something went wrong, signal */ - if (sig) - force_sig(sig, current); + process_fpemu_return(sig, fault_addr); return; } else if (fcr31 & FPU_CSR_INV_X) @@ -996,11 +1022,11 @@ asmlinkage void do_cpu(struct pt_regs *regs) if (!raw_cpu_has_fpu) { int sig; + void __user *fault_addr = NULL; sig = fpu_emulator_cop1Handler(regs, - ¤t->thread.fpu, 0); - if (sig) - force_sig(sig, current); - else + ¤t->thread.fpu, + 0, &fault_addr); + if (!process_fpemu_return(sig, fault_addr)) mt_ase_fp_affinity(); } diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index b2ad1b0910ff..d32cb0503110 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -64,7 +64,7 @@ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, #if __mips >= 4 && __mips != 32 static int fpux_emu(struct pt_regs *, - struct mips_fpu_struct *, mips_instruction); + struct mips_fpu_struct *, mips_instruction, void *__user *); #endif /* Further private data for which no space exists in mips_fpu_struct */ @@ -208,16 +208,23 @@ static inline int cop1_64bit(struct pt_regs *xcp) * Two instructions if the instruction is in a branch delay slot. */ -static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) +static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, + void *__user *fault_addr) { mips_instruction ir; unsigned long emulpc, contpc; unsigned int cond; - if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { + if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = (mips_instruction __user *)xcp->cp0_epc; return SIGBUS; } + if (__get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = (mips_instruction __user *)xcp->cp0_epc; + return SIGSEGV; + } /* XXX NEC Vr54xx bug workaround */ if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) @@ -245,10 +252,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) #endif return SIGILL; } - if (get_user(ir, (mips_instruction __user *) emulpc)) { + if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = (mips_instruction __user *)emulpc; return SIGBUS; } + if (__get_user(ir, (mips_instruction __user *) emulpc)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = (mips_instruction __user *)emulpc; + return SIGSEGV; + } /* __compute_return_epc() will have updated cp0_epc */ contpc = xcp->cp0_epc; /* In order not to confuse ptrace() et al, tweak context */ @@ -269,10 +282,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) u64 val; MIPS_FPU_EMU_INC_STATS(loads); - if (get_user(val, va)) { + + if (!access_ok(VERIFY_READ, va, sizeof(u64))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; return SIGBUS; } + if (__get_user(val, va)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; + return SIGSEGV; + } DITOREG(val, MIPSInst_RT(ir)); break; } @@ -284,10 +304,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) MIPS_FPU_EMU_INC_STATS(stores); DIFROMREG(val, MIPSInst_RT(ir)); - if (put_user(val, va)) { + if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; return SIGBUS; } + if (__put_user(val, va)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; + return SIGSEGV; + } break; } @@ -297,10 +323,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) u32 val; MIPS_FPU_EMU_INC_STATS(loads); - if (get_user(val, va)) { + if (!access_ok(VERIFY_READ, va, sizeof(u32))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; return SIGBUS; } + if (__get_user(val, va)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; + return SIGSEGV; + } SITOREG(val, MIPSInst_RT(ir)); break; } @@ -312,10 +344,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) MIPS_FPU_EMU_INC_STATS(stores); SIFROMREG(val, MIPSInst_RT(ir)); - if (put_user(val, va)) { + if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; return SIGBUS; } + if (__put_user(val, va)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; + return SIGSEGV; + } break; } @@ -440,11 +478,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) contpc = (xcp->cp0_epc + (MIPSInst_SIMM(ir) << 2)); - if (get_user(ir, - (mips_instruction __user *) xcp->cp0_epc)) { + if (!access_ok(VERIFY_READ, xcp->cp0_epc, + sizeof(mips_instruction))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = (mips_instruction __user *)xcp->cp0_epc; return SIGBUS; } + if (__get_user(ir, + (mips_instruction __user *) xcp->cp0_epc)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = (mips_instruction __user *)xcp->cp0_epc; + return SIGSEGV; + } switch (MIPSInst_OPCODE(ir)) { case lwc1_op: @@ -506,9 +551,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) #if __mips >= 4 && __mips != 32 case cop1x_op:{ - int sig; - - if ((sig = fpux_emu(xcp, ctx, ir))) + int sig = fpux_emu(xcp, ctx, ir, fault_addr); + if (sig) return sig; break; } @@ -604,7 +648,7 @@ DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, - mips_instruction ir) + mips_instruction ir, void *__user *fault_addr) { unsigned rcsr = 0; /* resulting csr */ @@ -624,10 +668,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, xcp->regs[MIPSInst_FT(ir)]); MIPS_FPU_EMU_INC_STATS(loads); - if (get_user(val, va)) { + if (!access_ok(VERIFY_READ, va, sizeof(u32))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; return SIGBUS; } + if (__get_user(val, va)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; + return SIGSEGV; + } SITOREG(val, MIPSInst_FD(ir)); break; @@ -638,10 +688,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, MIPS_FPU_EMU_INC_STATS(stores); SIFROMREG(val, MIPSInst_FS(ir)); - if (put_user(val, va)) { + if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; return SIGBUS; } + if (put_user(val, va)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; + return SIGSEGV; + } break; case madd_s_op: @@ -701,10 +757,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, xcp->regs[MIPSInst_FT(ir)]); MIPS_FPU_EMU_INC_STATS(loads); - if (get_user(val, va)) { + if (!access_ok(VERIFY_READ, va, sizeof(u64))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; return SIGBUS; } + if (__get_user(val, va)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; + return SIGSEGV; + } DITOREG(val, MIPSInst_FD(ir)); break; @@ -714,10 +776,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, MIPS_FPU_EMU_INC_STATS(stores); DIFROMREG(val, MIPSInst_FS(ir)); - if (put_user(val, va)) { + if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; return SIGBUS; } + if (__put_user(val, va)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = va; + return SIGSEGV; + } break; case madd_d_op: @@ -1242,7 +1310,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, } int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, - int has_fpu) + int has_fpu, void *__user *fault_addr) { unsigned long oldepc, prevepc; mips_instruction insn; @@ -1252,10 +1320,16 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, do { prevepc = xcp->cp0_epc; - if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { + if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) { MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = (mips_instruction __user *)xcp->cp0_epc; return SIGBUS; } + if (__get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { + MIPS_FPU_EMU_INC_STATS(errors); + *fault_addr = (mips_instruction __user *)xcp->cp0_epc; + return SIGSEGV; + } if (insn == 0) xcp->cp0_epc += 4; /* skip nops */ else { @@ -1267,7 +1341,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, */ /* convert to ieee library modes */ ieee754_csr.rm = ieee_rm[ieee754_csr.rm]; - sig = cop1Emulate(xcp, ctx); + sig = cop1Emulate(xcp, ctx, fault_addr); /* revert to mips rounding mode */ ieee754_csr.rm = mips_rm[ieee754_csr.rm]; } -- cgit v1.2.2 From e5674ad6ca9f1020c2bcc009a55becba3c30d8a3 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 10 Nov 2010 21:48:15 +0800 Subject: MIPS: Separate two consecutive loads in memset.S partial_fixup is used in noreorder block. Separating two consecutive loads can save one cycle on processors with GPR intrelock and can fix load-use on processors that need a load delay slot. Also do so for fwd_fixup. [Ralf: Only R2000/R3000 class processors are lacking the the load-user interlock and even some of those got it retrofitted. With R2000/R3000 being fairly uncommon these days the impact of this bug should be minor.] Signed-off-by: Tony Wu To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1768/ Signed-off-by: Ralf Baechle --- arch/mips/lib/memset.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 77dc3b20110a..606c8a9efe3b 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S @@ -161,16 +161,16 @@ FEXPORT(__bzero) .Lfwd_fixup: PTR_L t0, TI_TASK($28) - LONG_L t0, THREAD_BUADDR(t0) andi a2, 0x3f + LONG_L t0, THREAD_BUADDR(t0) LONG_ADDU a2, t1 jr ra LONG_SUBU a2, t0 .Lpartial_fixup: PTR_L t0, TI_TASK($28) - LONG_L t0, THREAD_BUADDR(t0) andi a2, LONGMASK + LONG_L t0, THREAD_BUADDR(t0) LONG_ADDU a2, t1 jr ra LONG_SUBU a2, t0 -- cgit v1.2.2 From 4afdea81821880d0fc35e6c7ff54eeed9ec0614d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 11 Nov 2010 19:08:52 +0100 Subject: MIPS: JZ4740: Fix pcm device name As part the ASoC multi-component patch (commit f0fba2ad) the jz4740 pcm driver was renamed to 'jz4740-pcm-audio'. Adjust the device name accordingly. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1770/ Signed-off-by: Ralf Baechle --- arch/mips/jz4740/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index 95bc2b5b14f1..1cc9e544d16b 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c @@ -208,7 +208,7 @@ struct platform_device jz4740_i2s_device = { /* PCM */ struct platform_device jz4740_pcm_device = { - .name = "jz4740-pcm", + .name = "jz4740-pcm-audio", .id = -1, }; -- cgit v1.2.2 From 190fca3e40a65303eac35ac4fbae4f1f1342431c Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Tue, 23 Nov 2010 10:26:45 -0800 Subject: MIPS: Fix regression on BCM4710 processor detection BCM4710 uses the BMIPS32 core (like BCM6345), not the MIPS 4Kc core as was previously believed. Signed-off-by: Kevin Cernekee Tested-by: Alexandros C. Couloumbis Patchwork: https://patchwork.linux-mips.org/patch/1837/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 4 ++-- arch/mips/kernel/cpu-probe.c | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 06d59dcbe243..86877539c6e8 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -111,8 +111,8 @@ * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM */ -#define PRID_IMP_BMIPS4KC 0x4000 -#define PRID_IMP_BMIPS32 0x8000 +#define PRID_IMP_BMIPS32_REV4 0x4000 +#define PRID_IMP_BMIPS32_REV8 0x8000 #define PRID_IMP_BMIPS3300 0x9000 #define PRID_IMP_BMIPS3300_ALT 0x9100 #define PRID_IMP_BMIPS3300_BUG 0x0000 diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 71620e19827a..68dae7b6b5db 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -905,7 +905,8 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) { decode_configs(c); switch (c->processor_id & 0xff00) { - case PRID_IMP_BMIPS32: + case PRID_IMP_BMIPS32_REV4: + case PRID_IMP_BMIPS32_REV8: c->cputype = CPU_BMIPS32; __cpu_name[cpu] = "Broadcom BMIPS32"; break; @@ -933,10 +934,6 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "Broadcom BMIPS5000"; c->options |= MIPS_CPU_ULRI; break; - case PRID_IMP_BMIPS4KC: - c->cputype = CPU_4KC; - __cpu_name[cpu] = "MIPS 4Kc"; - break; } } -- cgit v1.2.2 From 5878fc936aebf592cca418ca50773cd578f7daf4 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Tue, 23 Nov 2010 10:26:44 -0800 Subject: MIPS: Fix CP0 COUNTER clockevent race Consider the following test case: write_c0_compare(read_c0_count()); Even if the counter doesn't increment during execution, this might not generate an interrupt until the counter wraps around. The CPU may perform the comparison each time CP0 COUNT increments, not when CP0 COMPARE is written. If mips_next_event() is called with a very small delta, and CP0 COUNT increments during the calculation of "cnt += delta", it is possible that CP0 COMPARE will be written with the current value of CP0 COUNT. If this is detected, the function should return -ETIME, to indicate that the interrupt might not have actually gotten scheduled. Signed-off-by: Kevin Cernekee Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1836/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cevt-r4k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 2f4d7a99bcc2..98c5a9737c14 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -32,7 +32,7 @@ static int mips_next_event(unsigned long delta, cnt = read_c0_count(); cnt += delta; write_c0_compare(cnt); - res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; + res = ((int)(read_c0_count() - cnt) >= 0) ? -ETIME : 0; return res; } -- cgit v1.2.2 From e31fee7c3a197d88d1d0ced0e8600386da27fec4 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Wed, 24 Nov 2010 15:35:48 +0800 Subject: MIPS: FDT size is a be32 The totalsize field was be32. And the reserve bootmem would cause failure. Signed-off-by: Thomas Chou To: devicetree-discuss@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: grant.likely@secretlab.ca Cc: David Daney Cc: Dezhong Diao Patchwork: https://patchwork.linux-mips.org/patch/1838/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/prom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index e000b278f024..9dbe58368953 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -100,7 +100,7 @@ void __init device_tree_init(void) return; base = virt_to_phys((void *)initial_boot_params); - size = initial_boot_params->totalsize; + size = be32_to_cpu(initial_boot_params->totalsize); /* Before we do anything, lets reserve the dt blob */ reserve_mem_mach(base, size); -- cgit v1.2.2 From 825710843640dd173bc4b2ea99f1296923e4aa06 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 27 Nov 2010 17:45:58 +0100 Subject: MIPS: BCM47xx: Do not read config from CFE The config options read out here are not stored in CFE but only in NVRAM on the devices. Remove reading from CFE and only access the NVRAM. Reading out CFE does not harm but is useless here. Signed-off-by: Hauke Mehrtens To: linux-mips@linux-mips.org Cc: Hauke Mehrtens Patchwork: https://patchwork.linux-mips.org/patch/1845/ Signed-off-by: Ralf Baechle --- arch/mips/bcm47xx/setup.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index b1aee33efd11..2c6bdade3f13 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -32,7 +32,6 @@ #include #include #include -#include #include struct ssb_bus ssb_bcm47xx; @@ -82,42 +81,33 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus, /* Fill boardinfo structure */ memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); - if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 || - nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0) + if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0) iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); - if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 || - nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) + if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); - if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 || - nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) + if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); /* Fill sprom structure */ memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); iv->sprom.revision = 3; - if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 || - nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) + if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) str2eaddr(buf, iv->sprom.et0mac); - if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 || - nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) + if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) str2eaddr(buf, iv->sprom.et1mac); - if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 || - nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) + if (nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0); - if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 || - nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) + if (nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0); - if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 || - nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0) + if (nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0) iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); - if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 || - nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0) + if (nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0) iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); return 0; -- cgit v1.2.2 From 2aa088d6fd8a6c6e6020ea46b70141f0b7ccf5d2 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 27 Nov 2010 17:45:59 +0100 Subject: MIPS: BCM47xx: Fill values for b43 into SSB sprom Fill the sprom with all available values from the nvram. Most of these new values are needed for the b43 or b43legacy driver. Parts of this patch have been in OpenWRT for a long time and were written by Michael Buesch. Signed-off-by: Hauke Mehrtens To: linux-mips@linux-mips.org Cc: Hauke Mehrtens Patchwork: https://patchwork.linux-mips.org/patch/1846/ Signed-off-by: Ralf Baechle --- arch/mips/bcm47xx/setup.c | 114 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 2c6bdade3f13..1f61dfd71ac7 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -73,42 +73,112 @@ static void str2eaddr(char *str, char *dest) } } +#define READ_FROM_NVRAM(_outvar, name, buf) \ + if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\ + sprom->_outvar = simple_strtoul(buf, NULL, 0); + +static void bcm47xx_fill_sprom(struct ssb_sprom *sprom) +{ + char buf[100]; + u32 boardflags; + + memset(sprom, 0, sizeof(struct ssb_sprom)); + + sprom->revision = 1; /* Fallback: Old hardware does not define this. */ + READ_FROM_NVRAM(revision, "sromrev", buf); + if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0) + str2eaddr(buf, sprom->il0mac); + if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) + str2eaddr(buf, sprom->et0mac); + if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) + str2eaddr(buf, sprom->et1mac); + READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf); + READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf); + READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf); + READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf); + READ_FROM_NVRAM(board_rev, "boardrev", buf); + READ_FROM_NVRAM(country_code, "ccode", buf); + READ_FROM_NVRAM(ant_available_a, "aa5g", buf); + READ_FROM_NVRAM(ant_available_bg, "aa2g", buf); + READ_FROM_NVRAM(pa0b0, "pa0b0", buf); + READ_FROM_NVRAM(pa0b1, "pa0b1", buf); + READ_FROM_NVRAM(pa0b2, "pa0b2", buf); + READ_FROM_NVRAM(pa1b0, "pa1b0", buf); + READ_FROM_NVRAM(pa1b1, "pa1b1", buf); + READ_FROM_NVRAM(pa1b2, "pa1b2", buf); + READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf); + READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf); + READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf); + READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf); + READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf); + READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf); + READ_FROM_NVRAM(gpio0, "wl0gpio0", buf); + READ_FROM_NVRAM(gpio1, "wl0gpio1", buf); + READ_FROM_NVRAM(gpio2, "wl0gpio2", buf); + READ_FROM_NVRAM(gpio3, "wl0gpio3", buf); + READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf); + READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf); + READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf); + READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf); + READ_FROM_NVRAM(itssi_a, "pa1itssit", buf); + READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf); + READ_FROM_NVRAM(tri2g, "tri2g", buf); + READ_FROM_NVRAM(tri5gl, "tri5gl", buf); + READ_FROM_NVRAM(tri5g, "tri5g", buf); + READ_FROM_NVRAM(tri5gh, "tri5gh", buf); + READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf); + READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf); + READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf); + READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf); + READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf); + READ_FROM_NVRAM(bxa2g, "bxa2g", buf); + READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf); + READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf); + READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf); + READ_FROM_NVRAM(bxa5g, "bxa5g", buf); + READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf); + READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf); + READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf); + READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf); + READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf); + + if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) { + boardflags = simple_strtoul(buf, NULL, 0); + if (boardflags) { + sprom->boardflags_lo = (boardflags & 0x0000FFFFU); + sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16; + } + } + if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) { + boardflags = simple_strtoul(buf, NULL, 0); + if (boardflags) { + sprom->boardflags2_lo = (boardflags & 0x0000FFFFU); + sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16; + } + } +} + static int bcm47xx_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv) { - char buf[100]; + char buf[20]; /* Fill boardinfo structure */ memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0) - iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); + iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0); + else + iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM; if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); - /* Fill sprom structure */ - memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); - iv->sprom.revision = 3; - - if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) - str2eaddr(buf, iv->sprom.et0mac); - - if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) - str2eaddr(buf, iv->sprom.et1mac); - - if (nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) - iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0); - - if (nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) - iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0); - - if (nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0) - iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); + bcm47xx_fill_sprom(&iv->sprom); - if (nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0) - iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); + if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) + iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); return 0; } -- cgit v1.2.2 From 59833fcf48ee7b7c8a01e590aa7b7212305c3077 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 27 Nov 2010 17:46:00 +0100 Subject: MIPS: BCM47xx: Use sscanf for parsing mac address Instead of writing own function for parsing the mac address we now use sscanf. Signed-off-by: Hauke Mehrtens To: linux-mips@linux-mips.org Cc: Hauke Mehrtens Patchwork: https://patchwork.linux-mips.org/patch/1847/ Signed-off-by: Ralf Baechle --- arch/mips/bcm47xx/setup.c | 23 +++-------------------- arch/mips/include/asm/mach-bcm47xx/nvram.h | 7 +++++++ 2 files changed, 10 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 1f61dfd71ac7..87a305536604 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -56,23 +56,6 @@ static void bcm47xx_machine_halt(void) cpu_relax(); } -static void str2eaddr(char *str, char *dest) -{ - int i = 0; - - if (str == NULL) { - memset(dest, 0, 6); - return; - } - - for (;;) { - dest[i++] = (char) simple_strtoul(str, NULL, 16); - str += 2; - if (!*str++ || i == 6) - break; - } -} - #define READ_FROM_NVRAM(_outvar, name, buf) \ if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\ sprom->_outvar = simple_strtoul(buf, NULL, 0); @@ -87,11 +70,11 @@ static void bcm47xx_fill_sprom(struct ssb_sprom *sprom) sprom->revision = 1; /* Fallback: Old hardware does not define this. */ READ_FROM_NVRAM(revision, "sromrev", buf); if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0) - str2eaddr(buf, sprom->il0mac); + nvram_parse_macaddr(buf, sprom->il0mac); if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) - str2eaddr(buf, sprom->et0mac); + nvram_parse_macaddr(buf, sprom->et0mac); if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) - str2eaddr(buf, sprom->et1mac); + nvram_parse_macaddr(buf, sprom->et1mac); READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf); READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf); READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf); diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h index c58ebd8bc155..9759588ba3cf 100644 --- a/arch/mips/include/asm/mach-bcm47xx/nvram.h +++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h @@ -12,6 +12,7 @@ #define __NVRAM_H #include +#include struct nvram_header { u32 magic; @@ -36,4 +37,10 @@ struct nvram_header { extern int nvram_getenv(char *name, char *val, size_t val_len); +static inline void nvram_parse_macaddr(char *buf, u8 *macaddr) +{ + sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], &macaddr[1], + &macaddr[2], &macaddr[3], &macaddr[4], &macaddr[5]); +} + #endif -- cgit v1.2.2 From 1690a7f9ab83f5c823f3044275a4a771a059d5bb Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 27 Nov 2010 17:46:01 +0100 Subject: MIPS: BCM47xx: Swap serial console if ttyS1 was specified. Some devices like the Netgear WGT634U are using ttyS1 for default console output. We should switch to that console if it was given in the kernel_args parameters. Signed-off-by: Hauke Mehrtens To: linux-mips@linux-mips.org Cc: Hauke Mehrtens Patchwork: https://patchwork.linux-mips.org/patch/1848/ Signed-off-by: Ralf Baechle --- arch/mips/bcm47xx/setup.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch') diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 87a305536604..c95f90bf734c 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -169,12 +169,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus, void __init plat_mem_setup(void) { int err; + char buf[100]; + struct ssb_mipscore *mcore; err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, bcm47xx_get_invariants); if (err) panic("Failed to initialize SSB bus (err %d)\n", err); + mcore = &ssb_bcm47xx.mipscore; + if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { + if (strstr(buf, "console=ttyS1")) { + struct ssb_serial_port port; + + printk(KERN_DEBUG "Swapping serial ports!\n"); + /* swap serial ports */ + memcpy(&port, &mcore->serial_ports[0], sizeof(port)); + memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], + sizeof(port)); + memcpy(&mcore->serial_ports[1], &port, sizeof(port)); + } + } + _machine_restart = bcm47xx_machine_restart; _machine_halt = bcm47xx_machine_halt; pm_power_off = bcm47xx_machine_halt; -- cgit v1.2.2 From d002aaadf84c081623a0a8502c122d1492fbd47c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 1 Dec 2010 17:33:17 +0000 Subject: MIPS: MT: Fix typo in comment. Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-mt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 43e7cdc5ded2..c0e81418ba21 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -153,7 +153,7 @@ static void __cpuinit vsmp_init_secondary(void) { extern int gic_present; - /* This is Malta specific: IPI,performance and timer inetrrupts */ + /* This is Malta specific: IPI,performance and timer interrupts */ if (gic_present) change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP6 | STATUSF_IP7); -- cgit v1.2.2 From a3aad4aaf871045ab1dd9c99be6c1ace881d8eb0 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 9 Dec 2010 19:14:09 +0000 Subject: MIPS: Rename mips_dma_cache_sync back to dma_cache_sync This fixes IP22 and IP28 build errors. Signed-off-by: Ralf Baechle --- arch/mips/mm/dma-default.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 4fc1a0fbe007..21ea14efb837 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -288,7 +288,7 @@ int mips_dma_supported(struct device *dev, u64 mask) return plat_dma_supported(dev, mask); } -void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size, +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); @@ -298,6 +298,8 @@ void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size, __dma_sync((unsigned long)vaddr, size, direction); } +EXPORT_SYMBOL(dma_cache_sync); + static struct dma_map_ops mips_default_dma_map_ops = { .alloc_coherent = mips_dma_alloc_coherent, .free_coherent = mips_dma_free_coherent, -- cgit v1.2.2 From cf745a39dcb10ef80c4a2ff38448f57b69d4c4eb Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Mon, 25 Oct 2010 18:44:11 +0200 Subject: MIPS: Alchemy: fix build with SERIAL_8250=n In commit 7d172bfe ("Alchemy: Add UART PM methods") I introduced platform PM methods which call a function of the 8250 driver; this patch works around link failures when the kernel is built without 8250 support. Signed-off-by: Manuel Lauss To: Linux-MIPS Patchwork: https://patchwork.linux-mips.org/patch/1737/ Signed-off-by: Ralf Baechle --- arch/mips/alchemy/common/platform.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index 3691630931d6..9e7814db3d03 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -27,6 +27,7 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state, unsigned int old_state) { +#ifdef CONFIG_SERIAL_8250 switch (state) { case 0: if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) { @@ -49,6 +50,7 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state, serial8250_do_pm(port, state, old_state); break; } +#endif } #define PORT(_base, _irq) \ -- cgit v1.2.2 From 82b89152f00f7ad17844d5614d5011e8d7944ac9 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sun, 10 Oct 2010 10:42:12 +0100 Subject: MIPS: LD/SD o32 macro GAS fix update I am about to commit: http://sourceware.org/ml/binutils/2010-10/msg00033.html that fixes a problem with the LD/SD macro currently implemented by GAS for the o32 ABI in an inconsistent way. This is best illustrated with a simple program, which I'm copying here from the message above for easier reference: $ cat ld.s ld $5,32767($4) ld $5,32768($4) This gets assebled into the following output: $ mips-linux-as -32 -mips3 -o ld.o ld.s $ mips-linux-objdump -d ld.o ld.o: file format elf32-tradbigmips Disassembly of section .text: 00000000 <.text>: 0: dc857fff ld a1,32767(a0) 4: 3c010001 lui at,0x1 8: 00810821 addu at,a0,at c: 8c258000 lw a1,-32768(at) 10: 8c268004 lw a2,-32764(at) ... Oops! The GAS fix makes the macro behave in a consistent way and pairs of LW/SW instructions to be output as appropriate regardless of the size of the offset associated with the address used. The machine instruction is still available, but to reach it macros have to be disabled first. This has a side effect of requiring the use of a machine-addressable memory operand. As some platforms require 64-bit operations for accesses to some I/O registers LD/SD instructions are used in a couple of places in Linux regardless of the ABI selected. Here's a fix for some pieces of code affected I've been able to track down. The fix should be backwards compatible with all supported binutils releases in existence and can be used as a reference for any other places or off-tree code. The use of the "R" constraint guarantees a machine-addressable operand. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1680/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/io.h | 12 ++++++++++-- arch/mips/pmc-sierra/yosemite/py-console.c | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index c98bf514ec7d..5b017f23e243 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -329,10 +329,14 @@ static inline void pfx##write##bwlq(type val, \ "dsrl32 %L0, %L0, 0" "\n\t" \ "dsll32 %M0, %M0, 0" "\n\t" \ "or %L0, %L0, %M0" "\n\t" \ + ".set push" "\n\t" \ + ".set noreorder" "\n\t" \ + ".set nomacro" "\n\t" \ "sd %L0, %2" "\n\t" \ + ".set pop" "\n\t" \ ".set mips0" "\n" \ : "=r" (__tmp) \ - : "0" (__val), "m" (*__mem)); \ + : "0" (__val), "R" (*__mem)); \ if (irq) \ local_irq_restore(__flags); \ } else \ @@ -355,12 +359,16 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ local_irq_save(__flags); \ __asm__ __volatile__( \ ".set mips3" "\t\t# __readq" "\n\t" \ + ".set push" "\n\t" \ + ".set noreorder" "\n\t" \ + ".set nomacro" "\n\t" \ "ld %L0, %1" "\n\t" \ + ".set pop" "\n\t" \ "dsra32 %M0, %L0, 0" "\n\t" \ "sll %L0, %L0, 0" "\n\t" \ ".set mips0" "\n" \ : "=r" (__val) \ - : "m" (*__mem)); \ + : "R" (*__mem)); \ if (irq) \ local_irq_restore(__flags); \ } else { \ diff --git a/arch/mips/pmc-sierra/yosemite/py-console.c b/arch/mips/pmc-sierra/yosemite/py-console.c index b7f1d9c4a8a3..434d7b1a8c6a 100644 --- a/arch/mips/pmc-sierra/yosemite/py-console.c +++ b/arch/mips/pmc-sierra/yosemite/py-console.c @@ -65,11 +65,15 @@ static unsigned char readb_outer_space(unsigned long long phys) __asm__ __volatile__ ( " .set mips3 \n" + " .set push \n" + " .set noreorder \n" + " .set nomacro \n" " ld %0, %1 \n" + " .set pop \n" " lbu %0, (%0) \n" " .set mips0 \n" : "=r" (res) - : "m" (vaddr)); + : "R" (vaddr)); write_c0_status(sr); ssnop_4(); @@ -89,11 +93,15 @@ static void writeb_outer_space(unsigned long long phys, unsigned char c) __asm__ __volatile__ ( " .set mips3 \n" + " .set push \n" + " .set noreorder \n" + " .set nomacro \n" " ld %0, %1 \n" + " .set pop \n" " sb %2, (%0) \n" " .set mips0 \n" : "=&r" (tmp) - : "m" (vaddr), "r" (c)); + : "R" (vaddr), "r" (c)); write_c0_status(sr); ssnop_4(); -- cgit v1.2.2 From c9bace7ca1e2aeb95754ebc92c8f88a9f215691d Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 11 Oct 2010 14:52:45 -0700 Subject: MIPS: Add a CONFIG_FORCE_MAX_ZONEORDER Kconfig option. For huge page support with base page size of 16K or 32K, we have to increase the MAX_ORDER so that huge pages can be allocated. [Ralf: I don't think a user should have to configure obscure constants like this but for the time being this will have to suffice.] Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1685/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 7fc6bd1d3852..0a9b5b8b2a19 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1666,6 +1666,28 @@ config PAGE_SIZE_64KB endchoice +config FORCE_MAX_ZONEORDER + int "Maximum zone order" + range 13 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB + default "13" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB + range 12 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB + default "12" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB + range 11 64 + default "11" + help + The kernel memory allocator divides physically contiguous memory + blocks into "zones", where each zone is a power of two number of + pages. This option selects the largest power of two that the kernel + keeps in the memory allocator. If you need to allocate very large + blocks of physically contiguous memory, then you may need to + increase this value. + + This config option is actually maximum order plus one. For example, + a value of 11 means that the largest free memory block is 2^10 pages. + + The page size is not necessarily 4KB. Keep this in mind + when choosing a value for this option. + config BOARD_SCACHE bool -- cgit v1.2.2 From 147dd5610c8d1bacb88a6c1dfdaceaf257946ed0 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 16 Dec 2010 19:11:09 -0800 Subject: x86-32: Make sure we can map all of lowmem if we need to A relocatable kernel can be anywhere in lowmem -- and in the case of a kdump kernel, is likely to be fairly high. Since the early page tables map everything from address zero up we need to make sure we allocate enough brk that we can map all of lowmem if we need to. Reported-by: Stanislaw Gruszka Signed-off-by: H. Peter Anvin Tested-by: Yinghai Lu LKML-Reference: <4D0AD3ED.8070607@kernel.org> --- arch/x86/boot/compressed/misc.c | 2 +- arch/x86/kernel/head_32.S | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 23f315c9f215..325c05294fc4 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -355,7 +355,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, if (heap > 0x3fffffffffffUL) error("Destination address too large"); #else - if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff)) + if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff)) error("Destination address too large"); #endif #ifndef CONFIG_RELOCATABLE diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index bcece91dd311..d7cdf5bc1e63 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -60,16 +60,18 @@ #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) #endif +/* Number of possible pages in the lowmem region */ +LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) + /* Enough space to fit pagetables for the low memory linear map */ -MAPPING_BEYOND_END = \ - PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT +MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT /* * Worst-case size of the kernel mapping we need to make: - * the worst-case size of the kernel itself, plus the extra we need - * to map for the linear map. + * a relocatable kernel can live anywhere in lowmem, so we need to be able + * to map all of lowmem. */ -KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT +KERNEL_PAGES = LOWMEM_PAGES INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm RESERVE_BRK(pagetables, INIT_MAP_SIZE) -- cgit v1.2.2 From 258b78c364b9d3f730b5e3187fc500d472b5c237 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Fri, 3 Dec 2010 21:22:42 +0900 Subject: ARM: S3C24XX: Fix CONFIG_S3C_DEV_NAND Kconfig entry Should be CONFIG_S3C_DEV_NAND instead of CONFIG_S3C_DEVICE_NAND. Cc: Ben Dooks Signed-off-by: Kukjin Kim --- arch/arm/plat-s3c24xx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index 5a27b1b538f2..eb105e61c746 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -8,7 +8,7 @@ config PLAT_S3C24XX default y select NO_IOPORT select ARCH_REQUIRE_GPIOLIB - select S3C_DEVICE_NAND + select S3C_DEV_NAND select S3C_GPIO_CFG_S3C24XX help Base platform code for any Samsung S3C24XX device -- cgit v1.2.2 From 0f8f9c2b6c1326e99e51729a5d4aeb9c3ce164e1 Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Fri, 17 Dec 2010 14:45:01 +0900 Subject: ARM S3C24XX: Fix compilation of PM code for S3C2416 S3C2416 PM code uses low-level sleep routines from S3C2412 code, but these routines are compiled only for S3C2412 SoC. Split S3C2412_PM to two parts: S3C2412_PM, S3C2412_PM_SLEEP and select last in S3C2416's Kconfig. Signed-off-by: Yauhen Kharuzhy Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c2412/Kconfig | 7 +++++++ arch/arm/mach-s3c2412/Makefile | 3 ++- arch/arm/mach-s3c2416/Kconfig | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig index fa2e5bffbb8e..6983cb4d4cae 100644 --- a/arch/arm/mach-s3c2412/Kconfig +++ b/arch/arm/mach-s3c2412/Kconfig @@ -28,9 +28,16 @@ config S3C2412_DMA config S3C2412_PM bool + select S3C2412_PM_SLEEP help Internal config node to apply S3C2412 power management +config S3C2412_PM_SLEEP + bool + help + Internal config node to apply sleep for S3C2412 power management. + Can be selected by another SoCs with similar sleep procedure. + # Note, the S3C2412 IOtiming support is in plat-s3c24xx config S3C2412_CPUFREQ diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile index 530ec46cbaea..6c48a91ea39e 100644 --- a/arch/arm/mach-s3c2412/Makefile +++ b/arch/arm/mach-s3c2412/Makefile @@ -14,7 +14,8 @@ obj-$(CONFIG_CPU_S3C2412) += irq.o obj-$(CONFIG_CPU_S3C2412) += clock.o obj-$(CONFIG_CPU_S3C2412) += gpio.o obj-$(CONFIG_S3C2412_DMA) += dma.o -obj-$(CONFIG_S3C2412_PM) += pm.o sleep.o +obj-$(CONFIG_S3C2412_PM) += pm.o +obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep.o obj-$(CONFIG_S3C2412_CPUFREQ) += cpu-freq.o # Machine support diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index 27b3e7c9d613..df8d14974c90 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig @@ -27,6 +27,7 @@ config S3C2416_DMA config S3C2416_PM bool + select S3C2412_PM_SLEEP help Internal config node to apply S3C2416 power management -- cgit v1.2.2 From cb1868869dce7b751b670aadfc1f1360bc224b29 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 17 Dec 2010 14:47:42 +0900 Subject: ARM: S5PV210: update MAX8998 platform data to get rid of WARN() This patch adds new entries required by the new version of MAX8998 driver. Without them, the driver fails to init. See commit 50f19a4596 Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-s5pv210/mach-aquila.c | 6 ++++++ arch/arm/mach-s5pv210/mach-goni.c | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 28677caf3613..461aa035afc0 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -378,6 +378,12 @@ static struct max8998_regulator_data aquila_regulators[] = { static struct max8998_platform_data aquila_max8998_pdata = { .num_regulators = ARRAY_SIZE(aquila_regulators), .regulators = aquila_regulators, + .buck1_set1 = S5PV210_GPH0(3), + .buck1_set2 = S5PV210_GPH0(4), + .buck2_set3 = S5PV210_GPH0(5), + .buck1_max_voltage1 = 1200000, + .buck1_max_voltage2 = 1200000, + .buck2_max_voltage = 1200000, }; #endif diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index b1dcf964a768..e22d5112fd44 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -518,6 +518,12 @@ static struct max8998_regulator_data goni_regulators[] = { static struct max8998_platform_data goni_max8998_pdata = { .num_regulators = ARRAY_SIZE(goni_regulators), .regulators = goni_regulators, + .buck1_set1 = S5PV210_GPH0(3), + .buck1_set2 = S5PV210_GPH0(4), + .buck2_set3 = S5PV210_GPH0(5), + .buck1_max_voltage1 = 1200000, + .buck1_max_voltage2 = 1200000, + .buck2_max_voltage = 1200000, }; #endif -- cgit v1.2.2 From 676b14c36de5bea83f7666e5f5965188426b97a7 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 15 Dec 2010 10:59:24 +0000 Subject: ARM: mach-shmobile: fix compile warning in mm/init.c Turn down the warning noise from the compiler, basically a SH-Mobile specific version of the patch located in the RMK patch tracker: 6484/1: "fix compile warning in mm/init.c", Without this patch the following warning triggers: CC arch/arm/kernel/sys_arm.o arch/arm/mm/init.c: In function 'mem_init': arch/arm/mm/init.c:606: warning: format '%08lx' expects type 'long unsigned int', but argument 12 has type 'unsigned int' CC arch/arm/kernel/traps.o Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/include/mach/vmalloc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/include/mach/vmalloc.h b/arch/arm/mach-shmobile/include/mach/vmalloc.h index 4aecf6e3a859..2b8fd8b942fe 100644 --- a/arch/arm/mach-shmobile/include/mach/vmalloc.h +++ b/arch/arm/mach-shmobile/include/mach/vmalloc.h @@ -2,6 +2,6 @@ #define __ASM_MACH_VMALLOC_H /* Vmalloc at ... - 0xe5ffffff */ -#define VMALLOC_END 0xe6000000 +#define VMALLOC_END 0xe6000000UL #endif /* __ASM_MACH_VMALLOC_H */ -- cgit v1.2.2 From 1cf215a5b43950d1a304373037828158057ff9fc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 17 Dec 2010 15:15:48 +0900 Subject: ARM: mach-shmobile: INTC interrupt priority level demux fix Fix interrupt priority level handling on SH-Mobile ARM. SH-Mobile ARM platforms using multiple interrupt priority levels need this patch to fix a potential dead lock that may occur if multiple interrupts with different levels are pending simultaneously. The default INTC configuration is to use the same priority level for all interrupts, so this issue does not trigger by default. It is however common for board code to override the interrupt priority for certain interrupt sources depending on the application. Without this fix such boards may lock up. In detail, this patch updates the INTC code in entry-macro.S to make sure that the INTLVLA register gets set as expected. To trigger this bug modify the board specific code to adjust the interrupt priority level for the ethernet chip. After changing the priority level simply use flood ping to drown the board with interrupts. This patch applies to INTCA-based processors such as sh7372, sh7377 and sh7372. GIC-based processors are not affected. Suitable for v2.6.37-rc and stable from v2.6.34 to v2.6.36. Cc: stable@kernel.org Signed-off-by: Magnus Damm Tested-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/include/mach/entry-macro.S | 30 ++++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S index a285d13c7416..f428c4db2b60 100644 --- a/arch/arm/mach-shmobile/include/mach/entry-macro.S +++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Magnus Damm * Copyright (C) 2008 Renesas Solutions Corp. * * This program is free software; you can redistribute it and/or modify @@ -14,24 +15,45 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include +#define INTCA_BASE 0xe6980000 +#define INTFLGA_OFFS 0x00000018 /* accept pending interrupt */ +#define INTEVTA_OFFS 0x00000020 /* vector number of accepted interrupt */ +#define INTLVLA_OFFS 0x00000030 /* priority level of accepted interrupt */ +#define INTLVLB_OFFS 0x00000034 /* previous priority level */ + .macro disable_fiq .endm .macro get_irqnr_preamble, base, tmp - ldr \base, =INTFLGA + ldr \base, =INTCA_BASE .endm .macro arch_ret_to_user, tmp1, tmp2 .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \irqnr, [\base] + /* The single INTFLGA read access below results in the following: + * + * 1. INTLVLB is updated with old priority value from INTLVLA + * 2. Highest priority interrupt is accepted + * 3. INTLVLA is updated to contain priority of accepted interrupt + * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA + */ + ldr \irqnr, [\base, #INTFLGA_OFFS] + + /* Restore INTLVLA with the value saved in INTLVLB. + * This is required to support interrupt priorities properly. + */ + ldrb \tmp, [\base, #INTLVLB_OFFS] + strb \tmp, [\base, #INTLVLA_OFFS] + + /* Handle invalid vector number case */ cmp \irqnr, #0 beq 1000f - /* intevt to irq number */ + + /* Convert vector to irq number, same as the evt2irq() macro */ lsr \irqnr, \irqnr, #0x5 subs \irqnr, \irqnr, #16 -- cgit v1.2.2 From 8251544f9e28058e54c4f35b7cd13b0d191d7555 Mon Sep 17 00:00:00 2001 From: Ryan Mallon Date: Wed, 2 Jun 2010 12:55:36 +1200 Subject: at91: Fix uhpck clock rate in upll case The uhpck clock should be divided from the utmi clock, not its parent (main). This change is mostly cosmetic as the uhpck rate value is not used anywhere except for the debugfs clock output. Signed-off-by: Ryan Mallon Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 7525cee3983f..9113da6845f1 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -658,7 +658,7 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock) /* Now set uhpck values */ uhpck.parent = &utmi_clk; uhpck.pmc_mask = AT91SAM926x_PMC_UHP; - uhpck.rate_hz = utmi_clk.parent->rate_hz; + uhpck.rate_hz = utmi_clk.rate_hz; uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8); } -- cgit v1.2.2 From c20b4dd31820a551d0fb60bf27b99345905c2eb6 Mon Sep 17 00:00:00 2001 From: Christian Glindkamp Date: Thu, 9 Dec 2010 11:15:59 +0100 Subject: at91: Refactor Stamp9G20 and PControl G20 board file As PControl G20 is a carrier board for the Stamp9G20 SoM, some code can be shared. Therefore board-stamp9g20.c is refactored to allow reusing the SoM initialization and board-pcontrol-g20.c is modified to use it. Signed-off-by: Christian Glindkamp Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/Makefile | 2 +- arch/arm/mach-at91/board-pcontrol-g20.c | 98 +---------------------------- arch/arm/mach-at91/board-stamp9g20.c | 82 ++++++++++++------------ arch/arm/mach-at91/include/mach/stamp9g20.h | 7 +++ 4 files changed, 54 insertions(+), 135 deletions(-) create mode 100644 arch/arm/mach-at91/include/mach/stamp9g20.h (limited to 'arch') diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 62d686f0b426..d13add71f72a 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -65,7 +65,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o obj-$(CONFIG_MACH_CPU9G20) += board-cpu9krea.o obj-$(CONFIG_MACH_STAMP9G20) += board-stamp9g20.o obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o -obj-$(CONFIG_MACH_PCONTROL_G20) += board-pcontrol-g20.o +obj-$(CONFIG_MACH_PCONTROL_G20) += board-pcontrol-g20.o board-stamp9g20.o # AT91SAM9260/AT91SAM9G20 board-specific support obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c index bba5a560e02b..feb65787c30b 100644 --- a/arch/arm/mach-at91/board-pcontrol-g20.c +++ b/arch/arm/mach-at91/board-pcontrol-g20.c @@ -31,6 +31,7 @@ #include #include +#include #include "sam9_smc.h" #include "generic.h" @@ -38,11 +39,7 @@ static void __init pcontrol_g20_map_io(void) { - /* Initialize processor: 18.432 MHz crystal */ - at91sam9260_initialize(18432000); - - /* DGBU on ttyS0. (Rx, Tx) only TTL -> JTAG connector X7 17,19 ) */ - at91_register_uart(0, 0, 0); + stamp9g20_map_io(); /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback A2 */ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS @@ -54,9 +51,6 @@ static void __init pcontrol_g20_map_io(void) /* USART2 on ttyS3. (Rx, Tx) 9bit-Bus Multidrop-mode X4 */ at91_register_uart(AT91SAM9260_ID_US4, 3, 0); - - /* set serial console to ttyS0 (ie, DBGU) */ - at91_set_serial_console(0); } @@ -66,38 +60,6 @@ static void __init init_irq(void) } -/* - * NAND flash 512MiB 1,8V 8-bit, sector size 128 KiB - */ -static struct atmel_nand_data __initdata nand_data = { - .ale = 21, - .cle = 22, - .rdy_pin = AT91_PIN_PC13, - .enable_pin = AT91_PIN_PC14, -}; - -/* - * Bus timings; unit = 7.57ns - */ -static struct sam9_smc_config __initdata nand_smc_config = { - .ncs_read_setup = 0, - .nrd_setup = 2, - .ncs_write_setup = 0, - .nwe_setup = 2, - - .ncs_read_pulse = 4, - .nrd_pulse = 4, - .ncs_write_pulse = 4, - .nwe_pulse = 4, - - .read_cycle = 7, - .write_cycle = 7, - - .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE - | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, - .tdf_cycles = 3, -}; - static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { { .ncs_read_setup = 16, .nrd_setup = 18, @@ -138,14 +100,6 @@ static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { { .tdf_cycles = 1, } }; -static void __init add_device_nand(void) -{ - /* configure chip-select 3 (NAND) */ - sam9_smc_configure(3, &nand_smc_config); - at91_add_device_nand(&nand_data); -} - - static void __init add_device_pcontrol(void) { /* configure chip-select 4 (IO compatible to 8051 X4 ) */ @@ -155,23 +109,6 @@ static void __init add_device_pcontrol(void) } -/* - * MCI (SD/MMC) - * det_pin, wp_pin and vcc_pin are not connected - */ -#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) -static struct mci_platform_data __initdata mmc_data = { - .slot[0] = { - .bus_width = 4, - }, -}; -#else -static struct at91_mmc_data __initdata mmc_data = { - .wire4 = 1, -}; -#endif - - /* * USB Host port */ @@ -265,42 +202,13 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = { }; -/* - * Dallas 1-Wire DS2431 - */ -static struct w1_gpio_platform_data w1_gpio_pdata = { - .pin = AT91_PIN_PA29, - .is_open_drain = 1, -}; - -static struct platform_device w1_device = { - .name = "w1-gpio", - .id = -1, - .dev.platform_data = &w1_gpio_pdata, -}; - -static void add_wire1(void) -{ - at91_set_GPIO_periph(w1_gpio_pdata.pin, 1); - at91_set_multi_drive(w1_gpio_pdata.pin, 1); - platform_device_register(&w1_device); -} - - static void __init pcontrol_g20_board_init(void) { - at91_add_device_serial(); - add_device_nand(); -#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) - at91_add_device_mci(0, &mmc_data); -#else - at91_add_device_mmc(0, &mmc_data); -#endif + stamp9g20_board_init(); at91_add_device_usbh(&usbh_data); at91_add_device_eth(&macb_data); at91_add_device_i2c(pcontrol_g20_i2c_devices, ARRAY_SIZE(pcontrol_g20_i2c_devices)); - add_wire1(); add_device_pcontrol(); at91_add_device_spi(pcontrol_g20_spi_devices, ARRAY_SIZE(pcontrol_g20_spi_devices)); diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c index 5206eef4a67e..f8902b118960 100644 --- a/arch/arm/mach-at91/board-stamp9g20.c +++ b/arch/arm/mach-at91/board-stamp9g20.c @@ -32,7 +32,7 @@ #include "generic.h" -static void __init portuxg20_map_io(void) +void __init stamp9g20_map_io(void) { /* Initialize processor: 18.432 MHz crystal */ at91sam9260_initialize(18432000); @@ -40,6 +40,24 @@ static void __init portuxg20_map_io(void) /* DGBU on ttyS0. (Rx & Tx only) */ at91_register_uart(0, 0, 0); + /* set serial console to ttyS0 (ie, DBGU) */ + at91_set_serial_console(0); +} + +static void __init stamp9g20evb_map_io(void) +{ + stamp9g20_map_io(); + + /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ + at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS + | ATMEL_UART_DTR | ATMEL_UART_DSR + | ATMEL_UART_DCD | ATMEL_UART_RI); +} + +static void __init portuxg20_map_io(void) +{ + stamp9g20_map_io(); + /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR @@ -56,26 +74,6 @@ static void __init portuxg20_map_io(void) /* USART5 on ttyS6. (Rx, Tx only) */ at91_register_uart(AT91SAM9260_ID_US5, 6, 0); - - /* set serial console to ttyS0 (ie, DBGU) */ - at91_set_serial_console(0); -} - -static void __init stamp9g20_map_io(void) -{ - /* Initialize processor: 18.432 MHz crystal */ - at91sam9260_initialize(18432000); - - /* DGBU on ttyS0. (Rx & Tx only) */ - at91_register_uart(0, 0, 0); - - /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ - at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS - | ATMEL_UART_DTR | ATMEL_UART_DSR - | ATMEL_UART_DCD | ATMEL_UART_RI); - - /* set serial console to ttyS0 (ie, DBGU) */ - at91_set_serial_console(0); } static void __init init_irq(void) @@ -156,7 +154,7 @@ static struct at91_udc_data __initdata portuxg20_udc_data = { .pullup_pin = 0, /* pull-up driven by UDC */ }; -static struct at91_udc_data __initdata stamp9g20_udc_data = { +static struct at91_udc_data __initdata stamp9g20evb_udc_data = { .vbus_pin = AT91_PIN_PA22, .pullup_pin = 0, /* pull-up driven by UDC */ }; @@ -190,7 +188,7 @@ static struct gpio_led portuxg20_leds[] = { } }; -static struct gpio_led stamp9g20_leds[] = { +static struct gpio_led stamp9g20evb_leds[] = { { .name = "D8", .gpio = AT91_PIN_PB18, @@ -250,7 +248,7 @@ void add_w1(void) } -static void __init generic_board_init(void) +void __init stamp9g20_board_init(void) { /* Serial */ at91_add_device_serial(); @@ -262,34 +260,40 @@ static void __init generic_board_init(void) #else at91_add_device_mmc(0, &mmc_data); #endif - /* USB Host */ - at91_add_device_usbh(&usbh_data); - /* Ethernet */ - at91_add_device_eth(&macb_data); - /* I2C */ - at91_add_device_i2c(NULL, 0); /* W1 */ add_w1(); } static void __init portuxg20_board_init(void) { - generic_board_init(); - /* SPI */ - at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices)); + stamp9g20_board_init(); + /* USB Host */ + at91_add_device_usbh(&usbh_data); /* USB Device */ at91_add_device_udc(&portuxg20_udc_data); + /* Ethernet */ + at91_add_device_eth(&macb_data); + /* I2C */ + at91_add_device_i2c(NULL, 0); + /* SPI */ + at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices)); /* LEDs */ at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds)); } -static void __init stamp9g20_board_init(void) +static void __init stamp9g20evb_board_init(void) { - generic_board_init(); + stamp9g20_board_init(); + /* USB Host */ + at91_add_device_usbh(&usbh_data); /* USB Device */ - at91_add_device_udc(&stamp9g20_udc_data); + at91_add_device_udc(&stamp9g20evb_udc_data); + /* Ethernet */ + at91_add_device_eth(&macb_data); + /* I2C */ + at91_add_device_i2c(NULL, 0); /* LEDs */ - at91_gpio_leds(stamp9g20_leds, ARRAY_SIZE(stamp9g20_leds)); + at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds)); } MACHINE_START(PORTUXG20, "taskit PortuxG20") @@ -305,7 +309,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20") /* Maintainer: taskit GmbH */ .boot_params = AT91_SDRAM_BASE + 0x100, .timer = &at91sam926x_timer, - .map_io = stamp9g20_map_io, + .map_io = stamp9g20evb_map_io, .init_irq = init_irq, - .init_machine = stamp9g20_board_init, + .init_machine = stamp9g20evb_board_init, MACHINE_END diff --git a/arch/arm/mach-at91/include/mach/stamp9g20.h b/arch/arm/mach-at91/include/mach/stamp9g20.h new file mode 100644 index 000000000000..6120f9c46d59 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/stamp9g20.h @@ -0,0 +1,7 @@ +#ifndef __MACH_STAMP9G20_H +#define __MACH_STAMP9G20_H + +void stamp9g20_map_io(void); +void stamp9g20_board_init(void); + +#endif -- cgit v1.2.2 From 5e52f1c5e85fdc3831eeae8b546577e94a586f81 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 16 Dec 2010 10:38:25 -0700 Subject: Revert "x86: allocate space within a region top-down" This reverts commit 1af3c2e45e7a641e774bbb84fa428f2f0bf2d9c9. Acked-by: H. Peter Anvin Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- arch/x86/kernel/setup.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 21c6746338af..85268f8eadf6 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -769,7 +769,6 @@ void __init setup_arch(char **cmdline_p) x86_init.oem.arch_setup(); - resource_alloc_from_bottom = 0; iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1; setup_memory_map(); parse_setup_data(); -- cgit v1.2.2 From d14125ecfee05473de46f06d992db109308c57a3 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 16 Dec 2010 10:38:31 -0700 Subject: Revert "x86/PCI: allocate space from the end of a region, not the beginning" This reverts commit dc9887dc02e37bcf83f4e792aa14b07782ef54cf. Acked-by: H. Peter Anvin Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- arch/x86/pci/i386.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index c4bb261c106e..8379c2c3d076 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -65,21 +65,16 @@ pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { struct pci_dev *dev = data; - resource_size_t start = round_down(res->end - size + 1, align); + resource_size_t start = res->start; if (res->flags & IORESOURCE_IO) { - - /* - * If we're avoiding ISA aliases, the largest contiguous I/O - * port space is 256 bytes. Clearing bits 9 and 10 preserves - * all 256-byte and smaller alignments, so the result will - * still be correctly aligned. - */ - if (!skip_isa_ioresource_align(dev)) - start &= ~0x300; + if (skip_isa_ioresource_align(dev)) + return start; + if (start & 0x300) + start = (start + 0x3ff) & ~0x3ff; } else if (res->flags & IORESOURCE_MEM) { if (start < BIOS_END) - start = res->end; /* fail; no space */ + start = BIOS_END; } return start; } -- cgit v1.2.2 From 30919b0bf356a8ee0ef4f7d38ca8ad99b96820b2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 16 Dec 2010 10:38:51 -0700 Subject: x86: avoid low BIOS area when allocating address space This implements arch_remove_reservations() so allocate_resource() can avoid any arch-specific reserved areas. This currently just avoids the BIOS area (the first 1MB), but could be used for E820 reserved areas if that turns out to be necessary. We previously avoided this area in pcibios_align_resource(). This patch moves the test from that PCI-specific path to a generic path, so *all* resource allocations will avoid this area. Acked-by: H. Peter Anvin Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- arch/x86/kernel/Makefile | 1 + arch/x86/kernel/resource.c | 11 +++++++++++ arch/x86/pci/i386.c | 3 --- 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 arch/x86/kernel/resource.c (limited to 'arch') diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 9e13763b6092..1e994754d323 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -45,6 +45,7 @@ obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o obj-y += tsc.o io_delay.o rtc.o obj-y += pci-iommu_table.o +obj-y += resource.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-y += process.o diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c new file mode 100644 index 000000000000..407a900da9df --- /dev/null +++ b/arch/x86/kernel/resource.c @@ -0,0 +1,11 @@ +#include +#include + +void arch_remove_reservations(struct resource *avail) +{ + /* Trim out BIOS area (low 1MB) */ + if (avail->flags & IORESOURCE_MEM) { + if (avail->start < BIOS_END) + avail->start = BIOS_END; + } +} diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 8379c2c3d076..b1805b78842f 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -72,9 +72,6 @@ pcibios_align_resource(void *data, const struct resource *res, return start; if (start & 0x300) start = (start + 0x3ff) & ~0x3ff; - } else if (res->flags & IORESOURCE_MEM) { - if (start < BIOS_END) - start = BIOS_END; } return start; } -- cgit v1.2.2 From 4dc2287c1805e7fe8a7cb90bbcd44abee8cdb914 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 16 Dec 2010 10:38:56 -0700 Subject: x86: avoid E820 regions when allocating address space When we allocate address space, e.g., to assign it to a PCI device, don't allocate anything mentioned in the BIOS E820 memory map. On recent machines (2008 and newer), we assign PCI resources from the windows described by the ACPI PCI host bridge _CRS. On many Dell machines, these windows overlap some E820 reserved areas, e.g., BIOS-e820: 00000000bfe4dc00 - 00000000c0000000 (reserved) pci_root PNP0A03:00: host bridge window [mem 0xbff00000-0xdfffffff] If we put devices at 0xbff00000, they don't work, probably because that's really RAM, not I/O memory. This patch prevents that by removing the 0xbfe4dc00-0xbfffffff area from the "available" resource. I'm not very happy with this solution because Windows solves the problem differently (it seems to ignore E820 reserved areas and it allocates top-down instead of bottom-up; details at comment 45 of the bugzilla below). That means we're vulnerable to BIOS defects that Windows would not trip over. For example, if BIOS described a device in ACPI but didn't mention it in E820, Windows would work fine but Linux would fail. Reference: https://bugzilla.kernel.org/show_bug.cgi?id=16228 Acked-by: H. Peter Anvin Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- arch/x86/kernel/resource.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c index 407a900da9df..89638af2ff19 100644 --- a/arch/x86/kernel/resource.c +++ b/arch/x86/kernel/resource.c @@ -1,11 +1,47 @@ #include #include +static void resource_clip(struct resource *res, resource_size_t start, + resource_size_t end) +{ + resource_size_t low = 0, high = 0; + + if (res->end < start || res->start > end) + return; /* no conflict */ + + if (res->start < start) + low = start - res->start; + + if (res->end > end) + high = res->end - end; + + /* Keep the area above or below the conflict, whichever is larger */ + if (low > high) + res->end = start - 1; + else + res->start = end + 1; +} + +static void remove_e820_regions(struct resource *avail) +{ + int i; + struct e820entry *entry; + + for (i = 0; i < e820.nr_map; i++) { + entry = &e820.map[i]; + + resource_clip(avail, entry->addr, + entry->addr + entry->size - 1); + } +} + void arch_remove_reservations(struct resource *avail) { - /* Trim out BIOS area (low 1MB) */ + /* Trim out BIOS area (low 1MB) and E820 regions */ if (avail->flags & IORESOURCE_MEM) { if (avail->start < BIOS_END) avail->start = BIOS_END; + + remove_e820_regions(avail); } } -- cgit v1.2.2 From a2c606d53ab71dee6410f10ef0adf67321d60e06 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 16 Dec 2010 10:39:02 -0700 Subject: x86: avoid high BIOS area when allocating address space This prevents allocation of the last 2MB before 4GB. The experiment described here shows Windows 7 ignoring the last 1MB: https://bugzilla.kernel.org/show_bug.cgi?id=23542#c27 This patch ignores the top 2MB instead of just 1MB because H. Peter Anvin says "There will be ROM at the top of the 32-bit address space; it's a fact of the architecture, and on at least older systems it was common to have a shadow 1 MiB below." Acked-by: H. Peter Anvin Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- arch/x86/include/asm/e820.h | 3 +++ arch/x86/kernel/resource.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index 5be1542fbfaf..e99d55d74df5 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -72,6 +72,9 @@ struct e820map { #define BIOS_BEGIN 0x000a0000 #define BIOS_END 0x00100000 +#define BIOS_ROM_BASE 0xffe00000 +#define BIOS_ROM_END 0xffffffff + #ifdef __KERNEL__ /* see comment in arch/x86/kernel/e820.c */ extern struct e820map e820; diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c index 89638af2ff19..2a26819bb6a8 100644 --- a/arch/x86/kernel/resource.c +++ b/arch/x86/kernel/resource.c @@ -37,10 +37,11 @@ static void remove_e820_regions(struct resource *avail) void arch_remove_reservations(struct resource *avail) { - /* Trim out BIOS area (low 1MB) and E820 regions */ + /* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */ if (avail->flags & IORESOURCE_MEM) { if (avail->start < BIOS_END) avail->start = BIOS_END; + resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END); remove_e820_regions(avail); } -- cgit v1.2.2 From 081d835fa4ce70ad1e42ac76de850a49e23a1557 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Tue, 2 Nov 2010 22:28:01 -0700 Subject: MIPS: Fix build errors in sc-mips.c Seen with malta_defconfig on Linus' tree: CC arch/mips/mm/sc-mips.o arch/mips/mm/sc-mips.c: In function 'mips_sc_is_activated': arch/mips/mm/sc-mips.c:77: error: 'config2' undeclared (first use in this function) arch/mips/mm/sc-mips.c:77: error: (Each undeclared identifier is reported only once arch/mips/mm/sc-mips.c:77: error: for each function it appears in.) arch/mips/mm/sc-mips.c:81: error: 'tmp' undeclared (first use in this function) make[2]: *** [arch/mips/mm/sc-mips.o] Error 1 make[1]: *** [arch/mips/mm] Error 2 make: *** [arch/mips] Error 2 [Ralf: Cosmetic changes to minimize the number of arguments passed to mips_sc_is_activated] Signed-off-by: Kevin Cernekee Patchwork: https://patchwork.linux-mips.org/patch/1752/ Signed-off-by: Ralf Baechle --- arch/mips/mm/sc-mips.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 505fecad4684..9cca8de00545 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -68,6 +68,9 @@ static struct bcache_ops mips_sc_ops = { */ static inline int mips_sc_is_activated(struct cpuinfo_mips *c) { + unsigned int config2 = read_c0_config2(); + unsigned int tmp; + /* Check the bypass bit (L2B) */ switch (c->cputype) { case CPU_34K: @@ -83,6 +86,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c) c->scache.linesz = 2 << tmp; else return 0; + return 1; } static inline int __init mips_sc_probe(void) -- cgit v1.2.2 From bc4cf2bb271b2d557fc510426755da786fc985be Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 14 Dec 2010 15:57:49 -0500 Subject: arch/tile: handle CLONE_SETTLS in copy_thread(), not user space Previously we were just setting up the "tp" register in the new task as started by clone() in libc. However, this is not quite right, since in principle a signal might be delivered to the new task before it had its TLS set up. (Of course, this race window still exists for resetting the libc getpid() cached value in the new task, in principle. But in any case, we are now doing this exactly the way all other architectures do it.) This change is important for 2.6.37 since the tile glibc we will be submitting upstream will not set TLS in user space any more, so it will only work on a kernel that has this fix. It should also be taken for 2.6.36.x in the stable tree if possible. Signed-off-by: Chris Metcalf Cc: stable --- arch/tile/kernel/process.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 8430f45daea6..e90eb53173b0 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -211,6 +211,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, childregs->regs[0] = 0; /* return value is zero */ childregs->sp = sp; /* override with new user stack pointer */ + /* + * If CLONE_SETTLS is set, set "tp" in the new task to "r4", + * which is passed in as arg #5 to sys_clone(). + */ + if (clone_flags & CLONE_SETTLS) + childregs->tp = regs->regs[4]; + /* * Copy the callee-saved registers from the passed pt_regs struct * into the context-switch callee-saved registers area. @@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev, return __switch_to(prev, next, next_current_ksp0(next)); } +/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, void __user *, parent_tidptr, void __user *, child_tidptr, struct pt_regs *, regs) -- cgit v1.2.2 From 81711cee933599fa114abb0d258d8bbabef8adfb Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 14 Dec 2010 16:07:25 -0500 Subject: arch/tile: handle rt_sigreturn() more cleanly The current tile rt_sigreturn() syscall pattern uses the common idiom of loading up pt_regs with all the saved registers from the time of the signal, then anticipating the fact that we will clobber the ABI "return value" register (r0) as we return from the syscall by setting the rt_sigreturn return value to whatever random value was in the pt_regs for r0. However, this breaks in our 64-bit kernel when running "compat" tasks, since we always sign-extend the "return value" register to properly handle returned pointers that are in the upper 2GB of the 32-bit compat address space. Doing this to the sigreturn path then causes occasional random corruption of the 64-bit r0 register. Instead, we stop doing the crazy "load the return-value register" hack in sigreturn. We already have some sigreturn-specific assembly code that we use to pass the pt_regs pointer to C code. We extend that code to also set the link register to point to a spot a few instructions after the usual syscall return address so we don't clobber the saved r0. Now it no longer matters what the rt_sigreturn syscall returns, and the pt_regs structure can be cleanly and completely reloaded. Signed-off-by: Chris Metcalf --- arch/tile/include/asm/signal.h | 2 +- arch/tile/kernel/compat_signal.c | 6 +++--- arch/tile/kernel/intvec_32.S | 24 +++++++++++++++++++++--- arch/tile/kernel/signal.c | 10 ++++------ 4 files changed, 29 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h index c1ee1d61d44c..81d92a45cd4b 100644 --- a/arch/tile/include/asm/signal.h +++ b/arch/tile/include/asm/signal.h @@ -25,7 +25,7 @@ #if defined(__KERNEL__) && !defined(__ASSEMBLY__) struct pt_regs; -int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); +int restore_sigcontext(struct pt_regs *, struct sigcontext __user *); int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); void do_signal(struct pt_regs *regs); #endif diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 543d6a33aa26..dbb0dfc7bece 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c @@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, return ret; } +/* The assembly shim for this function arranges to ignore the return value. */ long compat_sys_rt_sigreturn(struct pt_regs *regs) { struct compat_rt_sigframe __user *frame = (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); sigset_t set; - long r0; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; @@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) goto badframe; - return r0; + return 0; badframe: force_sig(SIGSEGV, current); diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index f5821626247f..5eed4a02bf62 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S @@ -1342,8 +1342,8 @@ handle_syscall: lw r20, r20 /* Jump to syscall handler. */ - jalr r20; .Lhandle_syscall_link: - FEEDBACK_REENTER(handle_syscall) + jalr r20 +.Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */ /* * Write our r0 onto the stack so it gets restored instead @@ -1352,6 +1352,9 @@ handle_syscall: PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) sw r29, r0 +.Lsyscall_sigreturn_skip: + FEEDBACK_REENTER(handle_syscall) + /* Do syscall trace again, if requested. */ lw r30, r31 andi r30, r30, _TIF_SYSCALL_TRACE @@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr) }; \ STD_ENDPROC(_##x) +/* + * Special-case sigreturn to not write r0 to the stack on return. + * This is technically more efficient, but it also avoids difficulties + * in the 64-bit OS when handling 32-bit compat code, since we must not + * sign-extend r0 for the sigreturn return-value case. + */ +#define PTREGS_SYSCALL_SIGRETURN(x, reg) \ + STD_ENTRY(_##x); \ + addli lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \ + { \ + PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ + j x \ + }; \ + STD_ENDPROC(_##x) + PTREGS_SYSCALL(sys_execve, r3) PTREGS_SYSCALL(sys_sigaltstack, r2) -PTREGS_SYSCALL(sys_rt_sigreturn, r0) +PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 757407e36696..1260321155f1 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c @@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, */ int restore_sigcontext(struct pt_regs *regs, - struct sigcontext __user *sc, long *pr0) + struct sigcontext __user *sc) { int err = 0; int i; @@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs, regs->faultnum = INT_SWINT_1_SIGRETURN; - err |= __get_user(*pr0, &sc->gregs[0]); return err; } -/* sigreturn() returns long since it restores r0 in the interrupted code. */ +/* The assembly shim for this function arranges to ignore the return value. */ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) { struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->sp); sigset_t set; - long r0; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; @@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) goto badframe; - return r0; + return 0; badframe: force_sig(SIGSEGV, current); -- cgit v1.2.2 From 7f8595bfacef279f06c82ec98d420ef54f2537e0 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 16 Dec 2010 19:20:41 -0800 Subject: x86, kexec: Limit the crashkernel address appropriately Keep the crash kernel address below 512 MiB for 32 bits and 896 MiB for 64 bits. For 32 bits, this retains compatibility with earlier kernel releases, and makes it work even if the vmalloc= setting is adjusted. For 64 bits, we should be able to increase this substantially once a hard-coded limit in kexec-tools is fixed. Signed-off-by: H. Peter Anvin Cc: Vivek Goyal Cc: Stanislaw Gruszka Cc: Yinghai Lu LKML-Reference: <20101217195035.GE14502@redhat.com> --- arch/x86/kernel/setup.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 21c6746338af..c9089a13bad9 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -501,7 +501,18 @@ static inline unsigned long long get_total_mem(void) return total << PAGE_SHIFT; } -#define DEFAULT_BZIMAGE_ADDR_MAX 0x37FFFFFF +/* + * Keep the crash kernel below this limit. On 32 bits earlier kernels + * would limit the kernel to the low 512 MiB due to mapping restrictions. + * On 64 bits, kexec-tools currently limits us to 896 MiB; increase this + * limit once kexec-tools are fixed. + */ +#ifdef CONFIG_X86_32 +# define CRASH_KERNEL_ADDR_MAX (512 << 20) +#else +# define CRASH_KERNEL_ADDR_MAX (896 << 20) +#endif + static void __init reserve_crashkernel(void) { unsigned long long total_mem; @@ -520,10 +531,10 @@ static void __init reserve_crashkernel(void) const unsigned long long alignment = 16<<20; /* 16M */ /* - * kexec want bzImage is below DEFAULT_BZIMAGE_ADDR_MAX + * kexec want bzImage is below CRASH_KERNEL_ADDR_MAX */ crash_base = memblock_find_in_range(alignment, - DEFAULT_BZIMAGE_ADDR_MAX, crash_size, alignment); + CRASH_KERNEL_ADDR_MAX, crash_size, alignment); if (crash_base == MEMBLOCK_ERROR) { pr_info("crashkernel reservation failed - No suitable area found.\n"); -- cgit v1.2.2 From 1ae1b5f053cf36bd0f913e83f3b136fec8152d4d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 18 Dec 2010 13:57:00 +0000 Subject: ARM: smp: avoid incrementing mm_users on CPU startup We should not be incrementing mm_users when we startup a secondary CPU - doing so results in mm_users incrementing by one each time we hotplug a CPU, which will eventually wrap, and will cause problems. Other architectures such as x86 do not increment mm_users, but only mm_count, so we follow that pattern. Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8c1959590252..9066473c0ebc 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -310,7 +310,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void) * All kernel threads share the same mm context; grab a * reference and switch to it. */ - atomic_inc(&mm->mm_users); atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); -- cgit v1.2.2 From 39af22a79232373764904576f31572f1db76af10 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 15 Dec 2010 15:14:45 -0500 Subject: ARM: get rid of kmap_high_l1_vipt() Since commit 3e4d3af501 "mm: stack based kmap_atomic()", it is no longer necessary to carry an ad hoc version of kmap_atomic() added in commit 7e5a69e83b "ARM: 6007/1: fix highmem with VIPT cache and DMA" to cope with reentrancy. In fact, it is now actively wrong to rely on fixed kmap type indices (namely KM_L1_CACHE) as kmap_atomic() totally ignores them now and a concurrent instance of it may reuse any slot for any purpose. Signed-off-by: Nicolas Pitre --- arch/arm/include/asm/highmem.h | 3 -- arch/arm/mm/dma-mapping.c | 7 ++-- arch/arm/mm/flush.c | 7 ++-- arch/arm/mm/highmem.c | 87 ------------------------------------------ 4 files changed, 8 insertions(+), 96 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 1fc684e70ab6..7080e2c8fa62 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h @@ -25,9 +25,6 @@ extern void *kmap_high(struct page *page); extern void *kmap_high_get(struct page *page); extern void kunmap_high(struct page *page); -extern void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte); -extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte); - /* * The following functions are already defined by * when CONFIG_HIGHMEM is not set. diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index ac6a36142fcd..809f1bf9fa29 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -480,10 +481,10 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset, op(vaddr, len, dir); kunmap_high(page); } else if (cache_is_vipt()) { - pte_t saved_pte; - vaddr = kmap_high_l1_vipt(page, &saved_pte); + /* unmapped pages might still be cached */ + vaddr = kmap_atomic(page); op(vaddr + offset, len, dir); - kunmap_high_l1_vipt(page, saved_pte); + kunmap_atomic(vaddr); } } else { vaddr = page_address(page) + offset; diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 391ffae75098..c29f2839f1d2 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -180,10 +181,10 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page) __cpuc_flush_dcache_area(addr, PAGE_SIZE); kunmap_high(page); } else if (cache_is_vipt()) { - pte_t saved_pte; - addr = kmap_high_l1_vipt(page, &saved_pte); + /* unmapped pages might still be cached */ + addr = kmap_atomic(page); __cpuc_flush_dcache_area(addr, PAGE_SIZE); - kunmap_high_l1_vipt(page, saved_pte); + kunmap_atomic(addr); } } diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index c435fd9e1da9..807c0573abbe 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c @@ -140,90 +140,3 @@ struct page *kmap_atomic_to_page(const void *ptr) pte = TOP_PTE(vaddr); return pte_page(*pte); } - -#ifdef CONFIG_CPU_CACHE_VIPT - -#include - -/* - * The VIVT cache of a highmem page is always flushed before the page - * is unmapped. Hence unmapped highmem pages need no cache maintenance - * in that case. - * - * However unmapped pages may still be cached with a VIPT cache, and - * it is not possible to perform cache maintenance on them using physical - * addresses unfortunately. So we have no choice but to set up a temporary - * virtual mapping for that purpose. - * - * Yet this VIPT cache maintenance may be triggered from DMA support - * functions which are possibly called from interrupt context. As we don't - * want to keep interrupt disabled all the time when such maintenance is - * taking place, we therefore allow for some reentrancy by preserving and - * restoring the previous fixmap entry before the interrupted context is - * resumed. If the reentrancy depth is 0 then there is no need to restore - * the previous fixmap, and leaving the current one in place allow it to - * be reused the next time without a TLB flush (common with DMA). - */ - -static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth); - -void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte) -{ - unsigned int idx, cpu; - int *depth; - unsigned long vaddr, flags; - pte_t pte, *ptep; - - if (!in_interrupt()) - preempt_disable(); - - cpu = smp_processor_id(); - depth = &per_cpu(kmap_high_l1_vipt_depth, cpu); - - idx = KM_L1_CACHE + KM_TYPE_NR * cpu; - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); - ptep = TOP_PTE(vaddr); - pte = mk_pte(page, kmap_prot); - - raw_local_irq_save(flags); - (*depth)++; - if (pte_val(*ptep) == pte_val(pte)) { - *saved_pte = pte; - } else { - *saved_pte = *ptep; - set_pte_ext(ptep, pte, 0); - local_flush_tlb_kernel_page(vaddr); - } - raw_local_irq_restore(flags); - - return (void *)vaddr; -} - -void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte) -{ - unsigned int idx, cpu = smp_processor_id(); - int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu); - unsigned long vaddr, flags; - pte_t pte, *ptep; - - idx = KM_L1_CACHE + KM_TYPE_NR * cpu; - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); - ptep = TOP_PTE(vaddr); - pte = mk_pte(page, kmap_prot); - - BUG_ON(pte_val(*ptep) != pte_val(pte)); - BUG_ON(*depth <= 0); - - raw_local_irq_save(flags); - (*depth)--; - if (*depth != 0 && pte_val(pte) != pte_val(saved_pte)) { - set_pte_ext(ptep, saved_pte, 0); - local_flush_tlb_kernel_page(vaddr); - } - raw_local_irq_restore(flags); - - if (!in_interrupt()) - preempt_enable(); -} - -#endif /* CONFIG_CPU_CACHE_VIPT */ -- cgit v1.2.2 From 25cbe45440ea89a3b0f6f7ed326d3d476d53068b Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 15 Dec 2010 23:29:04 -0500 Subject: ARM: fix cache-xsc3l2 after stack based kmap_atomic() Since commit 3e4d3af501 "mm: stack based kmap_atomic()", it is actively wrong to rely on fixed kmap type indices (namely KM_L2_CACHE) as kmap_atomic() totally ignores them and a concurrent instance of it may happily reuse any slot for any purpose. Because kmap_atomic() is now able to deal with reentrancy, we can get rid of the ad hoc mapping here, and we even don't have to disable IRQs anymore (highmem case). While the code is made much simpler, there is a needless cache flush introduced by the usage of __kunmap_atomic(). It is not clear if the performance difference to remove that is worth the cost in code maintenance (I don't think there are that many highmem users on that platform if at all anyway). Signed-off-by: Nicolas Pitre --- arch/arm/mm/cache-xsc3l2.c | 57 +++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 36 deletions(-) (limited to 'arch') diff --git a/arch/arm/mm/cache-xsc3l2.c b/arch/arm/mm/cache-xsc3l2.c index c3154928bccd..5a32020471e3 100644 --- a/arch/arm/mm/cache-xsc3l2.c +++ b/arch/arm/mm/cache-xsc3l2.c @@ -17,14 +17,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include #include #include -#include -#include -#include -#include -#include "mm.h" #define CR_L2 (1 << 26) @@ -71,16 +67,15 @@ static inline void xsc3_l2_inv_all(void) dsb(); } +static inline void l2_unmap_va(unsigned long va) +{ #ifdef CONFIG_HIGHMEM -#define l2_map_save_flags(x) raw_local_save_flags(x) -#define l2_map_restore_flags(x) raw_local_irq_restore(x) -#else -#define l2_map_save_flags(x) ((x) = 0) -#define l2_map_restore_flags(x) ((void)(x)) + if (va != -1) + kunmap_atomic((void *)va); #endif +} -static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va, - unsigned long flags) +static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va) { #ifdef CONFIG_HIGHMEM unsigned long va = prev_va & PAGE_MASK; @@ -89,17 +84,10 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va, /* * Switching to a new page. Because cache ops are * using virtual addresses only, we must put a mapping - * in place for it. We also enable interrupts for a - * short while and disable them again to protect this - * mapping. + * in place for it. */ - unsigned long idx; - raw_local_irq_restore(flags); - idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id(); - va = __fix_to_virt(FIX_KMAP_BEGIN + idx); - raw_local_irq_restore(flags | PSR_I_BIT); - set_pte_ext(TOP_PTE(va), pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL), 0); - local_flush_tlb_kernel_page(va); + l2_unmap_va(prev_va); + va = (unsigned long)kmap_atomic_pfn(pa >> PAGE_SHIFT); } return va + (pa_offset >> (32 - PAGE_SHIFT)); #else @@ -109,7 +97,7 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va, static void xsc3_l2_inv_range(unsigned long start, unsigned long end) { - unsigned long vaddr, flags; + unsigned long vaddr; if (start == 0 && end == -1ul) { xsc3_l2_inv_all(); @@ -117,13 +105,12 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end) } vaddr = -1; /* to force the first mapping */ - l2_map_save_flags(flags); /* * Clean and invalidate partial first cache line. */ if (start & (CACHE_LINE_SIZE - 1)) { - vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr, flags); + vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr); xsc3_l2_clean_mva(vaddr); xsc3_l2_inv_mva(vaddr); start = (start | (CACHE_LINE_SIZE - 1)) + 1; @@ -133,7 +120,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end) * Invalidate all full cache lines between 'start' and 'end'. */ while (start < (end & ~(CACHE_LINE_SIZE - 1))) { - vaddr = l2_map_va(start, vaddr, flags); + vaddr = l2_map_va(start, vaddr); xsc3_l2_inv_mva(vaddr); start += CACHE_LINE_SIZE; } @@ -142,31 +129,30 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end) * Clean and invalidate partial last cache line. */ if (start < end) { - vaddr = l2_map_va(start, vaddr, flags); + vaddr = l2_map_va(start, vaddr); xsc3_l2_clean_mva(vaddr); xsc3_l2_inv_mva(vaddr); } - l2_map_restore_flags(flags); + l2_unmap_va(vaddr); dsb(); } static void xsc3_l2_clean_range(unsigned long start, unsigned long end) { - unsigned long vaddr, flags; + unsigned long vaddr; vaddr = -1; /* to force the first mapping */ - l2_map_save_flags(flags); start &= ~(CACHE_LINE_SIZE - 1); while (start < end) { - vaddr = l2_map_va(start, vaddr, flags); + vaddr = l2_map_va(start, vaddr); xsc3_l2_clean_mva(vaddr); start += CACHE_LINE_SIZE; } - l2_map_restore_flags(flags); + l2_unmap_va(vaddr); dsb(); } @@ -193,7 +179,7 @@ static inline void xsc3_l2_flush_all(void) static void xsc3_l2_flush_range(unsigned long start, unsigned long end) { - unsigned long vaddr, flags; + unsigned long vaddr; if (start == 0 && end == -1ul) { xsc3_l2_flush_all(); @@ -201,17 +187,16 @@ static void xsc3_l2_flush_range(unsigned long start, unsigned long end) } vaddr = -1; /* to force the first mapping */ - l2_map_save_flags(flags); start &= ~(CACHE_LINE_SIZE - 1); while (start < end) { - vaddr = l2_map_va(start, vaddr, flags); + vaddr = l2_map_va(start, vaddr); xsc3_l2_clean_mva(vaddr); xsc3_l2_inv_mva(vaddr); start += CACHE_LINE_SIZE; } - l2_map_restore_flags(flags); + l2_unmap_va(vaddr); dsb(); } -- cgit v1.2.2 From 6d3e6d3640052cac958d61c44597cc216f6ee09f Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 16 Dec 2010 14:56:34 -0500 Subject: ARM: fix cache-feroceon-l2 after stack based kmap_atomic() Since commit 3e4d3af501 "mm: stack based kmap_atomic()", it is actively wrong to rely on fixed kmap type indices (namely KM_L2_CACHE) as kmap_atomic() totally ignores them and a concurrent instance of it may happily reuse any slot for any purpose. Because kmap_atomic() is now able to deal with reentrancy, we can get rid of the ad hoc mapping here. While the code is made much simpler, there is a needless cache flush introduced by the usage of __kunmap_atomic(). It is not clear if the performance difference to remove that is worth the cost in code maintenance (I don't think there are that many highmem users on that platform anyway) but that should be reconsidered when/if someone cares enough to do some measurements. Signed-off-by: Nicolas Pitre --- arch/arm/mm/cache-feroceon-l2.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index 6e77c042d8e9..e0b0e7a4ec68 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c @@ -13,13 +13,9 @@ */ #include +#include #include -#include -#include -#include -#include #include -#include "mm.h" /* * Low-level cache maintenance operations. @@ -39,27 +35,30 @@ * between which we don't want to be preempted. */ -static inline unsigned long l2_start_va(unsigned long paddr) +static inline unsigned long l2_get_va(unsigned long paddr) { #ifdef CONFIG_HIGHMEM /* - * Let's do our own fixmap stuff in a minimal way here. * Because range ops can't be done on physical addresses, * we simply install a virtual mapping for it only for the * TLB lookup to occur, hence no need to flush the untouched - * memory mapping. This is protected with the disabling of - * interrupts by the caller. + * memory mapping afterwards (note: a cache flush may happen + * in some circumstances depending on the path taken in kunmap_atomic). */ - unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id(); - unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); - set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0); - local_flush_tlb_kernel_page(vaddr); - return vaddr + (paddr & ~PAGE_MASK); + void *vaddr = kmap_atomic_pfn(paddr >> PAGE_SHIFT); + return (unsigned long)vaddr + (paddr & ~PAGE_MASK); #else return __phys_to_virt(paddr); #endif } +static inline void l2_put_va(unsigned long vaddr) +{ +#ifdef CONFIG_HIGHMEM + kunmap_atomic((void *)vaddr); +#endif +} + static inline void l2_clean_pa(unsigned long addr) { __asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr)); @@ -76,13 +75,14 @@ static inline void l2_clean_pa_range(unsigned long start, unsigned long end) */ BUG_ON((start ^ end) >> PAGE_SHIFT); - raw_local_irq_save(flags); - va_start = l2_start_va(start); + va_start = l2_get_va(start); va_end = va_start + (end - start); + raw_local_irq_save(flags); __asm__("mcr p15, 1, %0, c15, c9, 4\n\t" "mcr p15, 1, %1, c15, c9, 5" : : "r" (va_start), "r" (va_end)); raw_local_irq_restore(flags); + l2_put_va(va_start); } static inline void l2_clean_inv_pa(unsigned long addr) @@ -106,13 +106,14 @@ static inline void l2_inv_pa_range(unsigned long start, unsigned long end) */ BUG_ON((start ^ end) >> PAGE_SHIFT); - raw_local_irq_save(flags); - va_start = l2_start_va(start); + va_start = l2_get_va(start); va_end = va_start + (end - start); + raw_local_irq_save(flags); __asm__("mcr p15, 1, %0, c15, c11, 4\n\t" "mcr p15, 1, %1, c15, c11, 5" : : "r" (va_start), "r" (va_end)); raw_local_irq_restore(flags); + l2_put_va(va_start); } static inline void l2_inv_all(void) -- cgit v1.2.2 From b8da46d3d55807037b58f14621a0949f18053bde Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 20 Dec 2010 00:29:32 -0500 Subject: clarify a usage constraint for cnt32_to_63() The cnt32_to_63 algorithm relies on proper counter data evaluation ordering to work properly. This was missing from the provided documentation. Let's augment the documentation with the missing usage constraint and fix the only instance that got it wrong. Signed-off-by: Nicolas Pitre Acked-by: David Howells Signed-off-by: Linus Torvalds --- arch/mn10300/kernel/time.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index f860a340acc9..75da468090b9 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c @@ -40,21 +40,17 @@ unsigned long long sched_clock(void) unsigned long long ll; unsigned l[2]; } tsc64, result; - unsigned long tsc, tmp; + unsigned long tmp; unsigned product[3]; /* 96-bit intermediate value */ /* cnt32_to_63() is not safe with preemption */ preempt_disable(); - /* read the TSC value - */ - tsc = get_cycles(); - - /* expand to 64-bits. + /* expand the tsc to 64-bits. * - sched_clock() must be called once a minute or better or the * following will go horribly wrong - see cnt32_to_63() */ - tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL; + tsc64.ll = cnt32_to_63(get_cycles()) & 0x7fffffffffffffffULL; preempt_enable(); -- cgit v1.2.2 From a2255ff45143001fecbc5e5a4b58fcb999d393ae Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Thu, 25 Nov 2010 12:11:51 +0200 Subject: mmc: at91_mci: fix multiblock SDIO transfers The AT91 MCI has special SDIO transfer types: SDIO block and SDIO byte transfers, but at91_mci driver doesn't use them and handles all SDIO transfers as ordinary MMC block transfers. This causes problems for multiple-block SDIO transfers (in particular for 256-bytes blocks). Fix this situation by checking the opcode for SDIO CMD53 and setting the transfer type in the AT91_MCI_CMDR register properly. This patch was tested with libertas SDIO driver: problem with TX timeouts on big packets was eliminated. Signed-off-by: Yauhen Kharuzhy Cc: Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Chris Ball --- arch/arm/mach-at91/include/mach/at91_mci.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-at91/include/mach/at91_mci.h b/arch/arm/mach-at91/include/mach/at91_mci.h index 57f8ee154943..27ac6f550fe3 100644 --- a/arch/arm/mach-at91/include/mach/at91_mci.h +++ b/arch/arm/mach-at91/include/mach/at91_mci.h @@ -74,6 +74,8 @@ #define AT91_MCI_TRTYP_BLOCK (0 << 19) #define AT91_MCI_TRTYP_MULTIPLE (1 << 19) #define AT91_MCI_TRTYP_STREAM (2 << 19) +#define AT91_MCI_TRTYP_SDIO_BYTE (4 << 19) +#define AT91_MCI_TRTYP_SDIO_BLOCK (5 << 19) #define AT91_MCI_BLKR 0x18 /* Block Register */ #define AT91_MCI_BLKR_BCNT(n) ((0xffff & (n)) << 0) /* Block count */ -- cgit v1.2.2 From 5e2f55c6aaf4865081c46bf53664c8b5da8dc49e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 22 Dec 2010 16:42:55 +0100 Subject: powerpc/mpc5200: include fs.h in mpc52xx_gpt.c Fix build errors like these (from a randconfig and my defconfig for a custom board): src/arch/powerpc/platforms/52xx/mpc52xx_gpt.c:549: error: dereferencing pointer to incomplete type: 1 errors in 1 logs src/arch/powerpc/platforms/52xx/mpc52xx_gpt.c:636: error: implicit declaration of function 'nonseekable_open': 1 errors in 1 logs src/arch/powerpc/platforms/52xx/mpc52xx_gpt.c:657: error: variable 'mpc52xx_wdt_fops' has initializer but incomplete type: 1 errors in 1 logs src/arch/powerpc/platforms/52xx/mpc52xx_gpt.c:658: error: excess elements in struct initializer: 1 errors in 1 logs src/arch/powerpc/platforms/52xx/mpc52xx_gpt.c:658: error: unknown field 'owner' specified in initializer: 1 errors in 1 logs ... Reported-by: Geert Uytterhoeven Signed-off-by: Wolfram Sang Cc: Grant Likely Cc: Benjamin Herrenschmidt Cc: Andrew Morton Signed-off-by: Grant Likely --- arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index fea833e18ad5..e0d703c7fdf7 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.2 From 638fa4aad5bbb75c8f0d558aa15dcb543de5fc31 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 24 Dec 2010 11:27:29 +0900 Subject: sh: Fix up SH4-202 clkfwk build. Some of the SH4-202 code was overlooked in the set_rate() API conversion, resulting in: arch/sh/kernel/cpu/sh4/clock-sh4-202.c: error: too many arguments to function 'clk->ops->set_rate' Fix it up. Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4/clock-sh4-202.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c index b601fa3978d1..6282a839e08e 100644 --- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c @@ -81,8 +81,7 @@ static void shoc_clk_init(struct clk *clk) for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) { int divisor = frqcr3_divisors[i]; - if (clk->ops->set_rate(clk, clk->parent->rate / - divisor, 0) == 0) + if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0) break; } -- cgit v1.2.2 From 27434f0af0fecba71fa58407715028d2b9550956 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 24 Dec 2010 11:30:10 +0900 Subject: sh: mach-se: Fix up SE7206 build. With some recent tidying of duplicate register definitions the se7206 IRQ code broke: arch/sh/boards/mach-se/7206/irq.c: error: 'INTC_ICR' undeclared (first use in this function) arch/sh/boards/mach-se/7206/irq.c: error: (Each undeclared identifier is reported only once arch/sh/boards/mach-se/7206/irq.c: error: for each function it appears in.) Fix it up. Signed-off-by: Paul Mundt --- arch/sh/boards/mach-se/7206/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sh/boards/mach-se/7206/irq.c b/arch/sh/boards/mach-se/7206/irq.c index d961949600fd..9070d7e60704 100644 --- a/arch/sh/boards/mach-se/7206/irq.c +++ b/arch/sh/boards/mach-se/7206/irq.c @@ -140,7 +140,7 @@ void __init init_se7206_IRQ(void) make_se7206_irq(IRQ1_IRQ); /* ATA */ make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ - __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR); /* ICR1 */ + __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */ /* FPGA System register setup*/ __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */ -- cgit v1.2.2 From 27f1acccd4d310e941d2e879445324595e2fe463 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 24 Dec 2010 12:15:57 +0900 Subject: sh: Fix up SH7201 clkfwk build. The master clock initialization for SH7201 was wholly bogus. Users of the legacy API must initialize the clock rate through the struct clk itself rather than returning the clock frequency. Given that the init function itself is void, returning the frequency isn't terribly effective. Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh2a/clock-sh7201.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c index b26264dc2aef..c509c40cba4b 100644 --- a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c @@ -34,7 +34,7 @@ static const int pfc_divisors[]={1,2,3,4,6,8,12}; static void master_clk_init(struct clk *clk) { - return 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007]; + clk->rate = 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007]; } static struct clk_ops sh7201_master_clk_ops = { -- cgit v1.2.2 From 537de3a67c0c86586eacffde40673b727242dc3a Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 22 Dec 2010 04:52:05 +0100 Subject: ARM: 6536/1: Add missing SZ_{32,64,128} ... and also remove misleading comment stating that this header is auto-generated. Signed-off-by: Stephen Warren Acked-by: Uwe Kleine-Knig Signed-off-by: Russell King --- arch/arm/include/asm/sizes.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/include/asm/sizes.h index 4fc1565e4f93..316bb2b2be3d 100644 --- a/arch/arm/include/asm/sizes.h +++ b/arch/arm/include/asm/sizes.h @@ -13,9 +13,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* DO NOT EDIT!! - this file automatically generated - * from .s file by awk -f s2h.awk - */ /* Size definitions * Copyright (C) ARM Limited 1998. All rights reserved. */ @@ -25,6 +22,9 @@ /* handy sizes */ #define SZ_16 0x00000010 +#define SZ_32 0x00000020 +#define SZ_64 0x00000040 +#define SZ_128 0x00000080 #define SZ_256 0x00000100 #define SZ_512 0x00000200 -- cgit v1.2.2 From d13e5edd7284bedcf5952e1b6490e39ad843cb91 Mon Sep 17 00:00:00 2001 From: Todd Android Poynor Date: Thu, 23 Dec 2010 01:52:44 +0100 Subject: ARM: 6540/1: Stop irqsoff trace on return to user If the irqsoff tracer is in use, stop tracing the interrupt disable interval when returning to userspace. Tracing userspace execution time as interrupts disabled time is not helpful for kernel performance analysis purposes. Only do so if the irqsoff tracer is enabled, to avoid overhead for lockdep, which doesn't care. Signed-off-by: Todd Poynor Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 8bfa98757cd2..80bf8cd88d7c 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -29,6 +29,9 @@ ret_fast_syscall: ldr r1, [tsk, #TI_FLAGS] tst r1, #_TIF_WORK_MASK bne fast_work_pending +#if defined(CONFIG_IRQSOFF_TRACER) + asm_trace_hardirqs_on +#endif /* perform architecture specific actions before user return */ arch_ret_to_user r1, lr @@ -65,6 +68,9 @@ ret_slow_syscall: tst r1, #_TIF_WORK_MASK bne work_pending no_work_pending: +#if defined(CONFIG_IRQSOFF_TRACER) + asm_trace_hardirqs_on +#endif /* perform architecture specific actions before user return */ arch_ret_to_user r1, lr -- cgit v1.2.2 From 5cdd2de0a76d0ac47f107c8a7b32d75d25768dc1 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 25 Dec 2010 19:57:41 +0100 Subject: x86/microcode: Fix double vfree() and remove redundant pointer checks before vfree() In arch/x86/kernel/microcode_intel.c::generic_load_microcode() we have this: while (leftover) { ... if (get_ucode_data(mc, ucode_ptr, mc_size) || microcode_sanity_check(mc) < 0) { vfree(mc); break; } ... } if (mc) vfree(mc); This will cause a double free of 'mc'. This patch fixes that by just removing the vfree() call in the loop since 'mc' will be freed nicely just after we break out of the loop. There's also a second change in the patch. I noticed a lot of checks for pointers being NULL before passing them to vfree(). That's completely redundant since vfree() deals gracefully with being passed a NULL pointer. Removing the redundant checks yields a nice size decrease for the object file. Size before the patch: text data bss dec hex filename 4578 240 1032 5850 16da arch/x86/kernel/microcode_intel.o Size after the patch: text data bss dec hex filename 4489 240 984 5713 1651 arch/x86/kernel/microcode_intel.o Signed-off-by: Jesper Juhl Acked-by: Tigran Aivazian Cc: Shaohua Li LKML-Reference: Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_intel.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index dcb65cc0a053..1a1b606d3e92 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -364,8 +364,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, /* For performance reasons, reuse mc area when possible */ if (!mc || mc_size > curr_mc_size) { - if (mc) - vfree(mc); + vfree(mc); mc = vmalloc(mc_size); if (!mc) break; @@ -374,13 +373,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, if (get_ucode_data(mc, ucode_ptr, mc_size) || microcode_sanity_check(mc) < 0) { - vfree(mc); break; } if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) { - if (new_mc) - vfree(new_mc); + vfree(new_mc); new_rev = mc_header.rev; new_mc = mc; mc = NULL; /* trigger new vmalloc */ @@ -390,12 +387,10 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, leftover -= mc_size; } - if (mc) - vfree(mc); + vfree(mc); if (leftover) { - if (new_mc) - vfree(new_mc); + vfree(new_mc); state = UCODE_ERROR; goto out; } @@ -405,8 +400,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, goto out; } - if (uci->mc) - vfree(uci->mc); + vfree(uci->mc); uci->mc = (struct microcode_intel *)new_mc; pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", -- cgit v1.2.2 From 88a58101608f1416f4c1ec81d88faed258a34b3d Mon Sep 17 00:00:00 2001 From: Imre Kaloz Date: Mon, 27 Dec 2010 22:59:57 +0100 Subject: ARM: fix IXP4xx build failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit arm: export dma_set_coherent_mask While a regression was fixed with commit 710224fa2750cf (arm: fix "arm: fix pci_set_consistent_dma_mask for dmabounce devices"), a new one was introduced as dma_set_coherent_mask wasn't exported for modules. This patch takes care for this issue. Signed-off-by: Imre Kaloz Signed-off-by: Krzysztof Hałasa Signed-off-by: Linus Torvalds --- arch/arm/common/it8152.c | 1 + arch/arm/mach-ixp4xx/common-pci.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c index 1bec96e85196..42ff90b46dfb 100644 --- a/arch/arm/common/it8152.c +++ b/arch/arm/common/it8152.c @@ -352,3 +352,4 @@ struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys) return pci_scan_bus(nr, &it8152_ops, sys); } +EXPORT_SYMBOL(dma_set_coherent_mask); diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 24498a932ba6..a54b3db80366 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -513,4 +513,4 @@ int dma_set_coherent_mask(struct device *dev, u64 mask) EXPORT_SYMBOL(ixp4xx_pci_read); EXPORT_SYMBOL(ixp4xx_pci_write); - +EXPORT_SYMBOL(dma_set_coherent_mask); -- cgit v1.2.2 From 649497d1a3676020802ebba04a3d9bb31253adb5 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 28 Dec 2010 12:09:07 +0200 Subject: KVM: MMU: Fix incorrect direct gfn for unpaged mode shadow We use the physical address instead of the base gfn for the four PAE page directories we use in unpaged mode. When the guest accesses an address above 1GB that is backed by a large host page, a BUG_ON() in kvm_mmu_set_gfn() triggers. Resolves: https://bugzilla.kernel.org/show_bug.cgi?id=21962 Reported-and-tested-by: Nicolas Prochazka KVM-Stable-Tag. Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index fb8b376bf28c..fbb04aee8301 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -2394,7 +2394,8 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) ASSERT(!VALID_PAGE(root)); spin_lock(&vcpu->kvm->mmu_lock); kvm_mmu_free_some_pages(vcpu); - sp = kvm_mmu_get_page(vcpu, i << 30, i << 30, + sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT), + i << 30, PT32_ROOT_LEVEL, 1, ACC_ALL, NULL); root = __pa(sp->spt); -- cgit v1.2.2 From d0dfc6b74a0c6e9ee46b62713256e2b025244d3c Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Fri, 31 Dec 2010 10:52:15 +0200 Subject: KVM: i8259: initialize isr_ack isr_ack is never initialized. So, until the first PIC reset, interrupts may fail to be injected. This can cause Windows XP to fail to boot, as reported in the fallout from the fix to https://bugzilla.kernel.org/show_bug.cgi?id=21962. Reported-and-tested-by: Nicolas Prochazka Signed-off-by: Avi Kivity --- arch/x86/kvm/i8259.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index f628234fbeca..3cece05e4ac4 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -575,6 +575,8 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm) s->pics[1].elcr_mask = 0xde; s->pics[0].pics_state = s; s->pics[1].pics_state = s; + s->pics[0].isr_ack = 0xff; + s->pics[1].isr_ack = 0xff; /* * Initialize PIO device -- cgit v1.2.2 From 7c0ab43e6ab09d72dc8dbac2521b2f819ccc4026 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 3 Jan 2011 02:26:53 +0100 Subject: ARM: 6605/1: Add missing include "asm/memory.h" This patch fixes below build error by adding the missing asm/memory.h, which is needed for arch_is_coherent(). $ make pxa3xx_defconfig; make CC init/do_mounts_rd.o In file included from include/linux/list_bl.h:5, from include/linux/rculist_bl.h:7, from include/linux/dcache.h:7, from include/linux/fs.h:381, from init/do_mounts_rd.c:3: include/linux/bit_spinlock.h: In function 'bit_spin_unlock': include/linux/bit_spinlock.h:61: error: implicit declaration of function 'arch_is_coherent' make[1]: *** [init/do_mounts_rd.o] Error 1 make: *** [init] Error 2 Signed-off-by: Axel Lin Acked-by: Peter Huewe Signed-off-by: Russell King --- arch/arm/include/asm/system.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 1120f18a6b17..80025948b8ad 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -150,6 +150,7 @@ extern unsigned int user_debug; #define rmb() dmb() #define wmb() mb() #else +#include #define mb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) #define rmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) #define wmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) -- cgit v1.2.2 From c7c25802b39c443b3745cfa973dc49a97a3491f8 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 3 Jan 2011 12:15:14 +0100 Subject: arch/x86/oprofile/op_model_amd.c: Perform initialisation on a single CPU Disable preemption in init_ibs(). The function only checks the ibs capabilities and sets up pci devices (if necessary). It runs only on one cpu but operates with the local APIC and some MSRs, thus it is better to disable preemption. [ 7.034377] BUG: using smp_processor_id() in preemptible [00000000] code: modprobe/483 [ 7.034385] caller is setup_APIC_eilvt+0x155/0x180 [ 7.034389] Pid: 483, comm: modprobe Not tainted 2.6.37-rc1-20101110+ #1 [ 7.034392] Call Trace: [ 7.034400] [] debug_smp_processor_id+0xd2/0xf0 [ 7.034404] [] setup_APIC_eilvt+0x155/0x180 [ ... ] Addresses https://bugzilla.kernel.org/show_bug.cgi?id=22812 Reported-by: Signed-off-by: Robert Richter Cc: oprofile-list@lists.sourceforge.net Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Rafael J. Wysocki Cc: Dan Carpenter Cc: Andrew Morton Cc: [2.6.37.x] LKML-Reference: <20110103111514.GM4739@erda.amd.com> [ small cleanups ] Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_amd.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index a011bcc0f943..7d90d47655ba 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -630,21 +630,29 @@ static int __init_ibs_nmi(void) return 0; } -/* initialize the APIC for the IBS interrupts if available */ +/* + * check and reserve APIC extended interrupt LVT offset for IBS if + * available + * + * init_ibs() preforms implicitly cpu-local operations, so pin this + * thread to its current CPU + */ + static void init_ibs(void) { - ibs_caps = get_ibs_caps(); + preempt_disable(); + ibs_caps = get_ibs_caps(); if (!ibs_caps) - return; + goto out; - if (__init_ibs_nmi()) { + if (__init_ibs_nmi() < 0) ibs_caps = 0; - return; - } + else + printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps); - printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", - (unsigned)ibs_caps); +out: + preempt_enable(); } static int (*create_arch_files)(struct super_block *sb, struct dentry *root); -- cgit v1.2.2 From 82427de2c7c39ee7bcaa4cb0260b4e9b9ab19eb8 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 15 Dec 2010 07:20:16 +0800 Subject: ARM: pxa: PXA_ESERIES depends on FB_W100. As arch/arm/mach-pxa/eseries.c references w100fb_gpio_{read,write}() directly. Signed-off-by: Lennert Buytenhek Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index dd235ecc9d6c..c93e73d54dd1 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -540,6 +540,7 @@ config MACH_ICONTROL config ARCH_PXA_ESERIES bool "PXA based Toshiba e-series PDAs" select PXA25x + select FB_W100 config MACH_E330 bool "Toshiba e330" -- cgit v1.2.2 From 823a2df258627b80df2e75056b850424a8eb5fed Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 29 Dec 2010 09:06:26 +0200 Subject: ARM: it8152: add IT8152_LAST_IRQ definition to fix build error The commit 6ac6b817f3f4c23c5febd960d8deb343e13af5f3 (ARM: pxa: encode IRQ number into .nr_irqs) removed definition of ITE_LAST_IRQ which caused the following build error: CC arch/arm/common/it8152.o arch/arm/common/it8152.c: In function 'it8152_init_irq': arch/arm/common/it8152.c:86: error: 'IT8152_LAST_IRQ' undeclared (first use in this function) arch/arm/common/it8152.c:86: error: (Each undeclared identifier is reported only once arch/arm/common/it8152.c:86: error: for each function it appears in.) make[2]: *** [arch/arm/common/it8152.o] Error 1 Defining the IT8152_LAST_IRQ in the arch/arm/include/hardware/it8152.c fixes the build. Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/include/asm/hardware/it8152.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/include/asm/hardware/it8152.h b/arch/arm/include/asm/hardware/it8152.h index 21fa272301f8..b2f95c72287c 100644 --- a/arch/arm/include/asm/hardware/it8152.h +++ b/arch/arm/include/asm/hardware/it8152.h @@ -76,6 +76,7 @@ extern unsigned long it8152_base_address; IT8152_PD_IRQ(0) Audio controller (ACR) */ #define IT8152_IRQ(x) (IRQ_BOARD_START + (x)) +#define IT8152_LAST_IRQ (IRQ_BOARD_START + 40) /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */ #define IT8152_LD_IRQ_COUNT 9 -- cgit v1.2.2 From 24c78557741395e038e83f25367cf2bfd7f582b8 Mon Sep 17 00:00:00 2001 From: "Aric D. Blumer" Date: Wed, 29 Dec 2010 11:18:29 -0500 Subject: ARM: pxa: fix page table corruption on resume Before this patch, the following error would sometimes occur after a resume on pxa3xx: /path/to/mm/memory.c:144: bad pmd 8040542e. The problem was that a temporary page table mapping was being improperly restored. The PXA3xx resume code creates a temporary mapping of resume_turn_on_mmu to avoid a prefetch abort. The pxa3xx_resume_after_mmu code requires that the r1 register holding the address of this mapping not be modified, however, resume_turn_on_mmu does modify it. It is mostly correct in that r1 receives the base table address, but it may also get other bits in 13:0. This results in pxa3xx_resume_after_mmu restoring the original mapping to the wrong place, corrupting memory and leaving the temporary mapping in place. Signed-off-by: Matt Reimer Signed-off-by: Eric Miao --- arch/arm/mach-pxa/sleep.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S index 52c30b01a671..ae008110db4e 100644 --- a/arch/arm/mach-pxa/sleep.S +++ b/arch/arm/mach-pxa/sleep.S @@ -353,8 +353,8 @@ resume_turn_on_mmu: @ Let us ensure we jump to resume_after_mmu only when the mcr above @ actually took effect. They call it the "cpwait" operation. - mrc p15, 0, r1, c2, c0, 0 @ queue a dependency on CP15 - sub pc, r2, r1, lsr #32 @ jump to virtual addr + mrc p15, 0, r0, c2, c0, 0 @ queue a dependency on CP15 + sub pc, r2, r0, lsr #32 @ jump to virtual addr nop nop nop -- cgit v1.2.2 From d9a1abe4844e7591cd82e167a1a09e6546f6c45e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 3 Jan 2011 14:59:11 -0800 Subject: arch/mn10300/kernel/irq.c: fix build Addresses https://bugzilla.kernel.org/show_bug.cgi?id=25702 Reported-by: Martin Ettl Cc: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/mn10300/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index c2e44597c22b..ac11754ecec5 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -459,7 +459,7 @@ void migrate_irqs(void) tmp = CROSS_GxICR(irq, new); x &= GxICR_LEVEL | GxICR_ENABLE; - if (GxICR(irq) & GxICR_REQUEST) { + if (GxICR(irq) & GxICR_REQUEST) x |= GxICR_REQUEST | GxICR_DETECT; CROSS_GxICR(irq, new) = x; tmp = CROSS_GxICR(irq, new); -- cgit v1.2.2