diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-16 11:49:58 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-16 11:49:58 -0700 |
commit | 8d6cea5111f2daea8acf79d7b4b384a14175ecc1 (patch) | |
tree | ef56294da7eefbe46654b030fa8be06830a9c4f0 /arch/blackfin | |
parent | 6a454f71d795368c00d9c329b60cc4d58929e7bc (diff) | |
parent | 61cdd7a28f8b515140cb5d8aea518678f0fae024 (diff) | |
download | linux-8d6cea5111f2daea8acf79d7b4b384a14175ecc1.tar.gz linux-8d6cea5111f2daea8acf79d7b4b384a14175ecc1.tar.bz2 linux-8d6cea5111f2daea8acf79d7b4b384a14175ecc1.zip |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin: (27 commits)
Blackfin: hook up new rt_tgsigqueueinfo syscall
Blackfin: improve CLKIN_HZ config default
Blackfin: initial support for ftrace grapher
Blackfin: initial support for ftrace
Blackfin: enable support for LOCKDEP
Blackfin: add preliminary support for STACKTRACE
Blackfin: move custom sections into sections.h
Blackfin: punt unused/wrong mutex-dec.h
Blackfin: add support for irqflags
Blackfin: add support for bzip2/lzma compressed kernel images
Blackfin: convert Kconfig style to def_bool
Blackfin: bf548-ezkit: update smsc911x resources
Blackfin: update aedos-ipipe code to upstream 1.10-00
Blackfin: bf537-stamp: update ADP5520 resources
Blackfin: bf518f-ezbrd: fix SPI CS for SPI flash
Blackfin: define SPI IRQ in board resources
Blackfin: do not configure the UART early if on wrong processor
Blackfin: fix deadlock in SMP IPI handler
Blackfin: fix flag storage for irq funcs
Blackfin: push down exception oops checking
...
Diffstat (limited to 'arch/blackfin')
55 files changed, 807 insertions, 603 deletions
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index a60cfe757914..8ea0d942cdea 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -6,59 +6,65 @@ mainmenu "Blackfin Kernel Configuration" config MMU - bool - default n + def_bool n config FPU - bool - default n + def_bool n config RWSEM_GENERIC_SPINLOCK - bool - default y + def_bool y config RWSEM_XCHGADD_ALGORITHM - bool - default n + def_bool n config BLACKFIN - bool - default y + def_bool y + select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_FUNCTION_TRACER select HAVE_IDE + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_BZIP2 + select HAVE_KERNEL_LZMA select HAVE_OPROFILE select ARCH_WANT_OPTIONAL_GPIOLIB +config GENERIC_BUG + def_bool y + depends on BUG + config ZONE_DMA - bool - default y + def_bool y config GENERIC_FIND_NEXT_BIT - bool - default y + def_bool y config GENERIC_HWEIGHT - bool - default y + def_bool y config GENERIC_HARDIRQS - bool - default y + def_bool y config GENERIC_IRQ_PROBE - bool - default y + def_bool y config GENERIC_GPIO - bool - default y + def_bool y config FORCE_MAX_ZONEORDER int default "14" config GENERIC_CALIBRATE_DELAY - bool - default y + def_bool y + +config LOCKDEP_SUPPORT + def_bool y + +config STACKTRACE_SUPPORT + def_bool y + +config TRACE_IRQFLAGS_SUPPORT + def_bool y source "init/Kconfig" @@ -408,12 +414,12 @@ comment "Clock/PLL Setup" config CLKIN_HZ int "Frequency of the crystal on the board in Hz" + default "10000000" if BFIN532_IP0X default "11059200" if BFIN533_STAMP + default "24576000" if PNAV10 + default "25000000" # most people use this default "27000000" if BFIN533_EZKIT - default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN538_EZKIT || BFIN518F-EZBRD) default "30000000" if BFIN561_EZKIT - default "24576000" if PNAV10 - default "10000000" if BFIN532_IP0X help The frequency of CLKIN crystal oscillator on the board in Hz. Warning: This value should match the crystal on the board. Otherwise, diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index d54c8283825c..6f9533c3d752 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -137,7 +137,7 @@ archclean: INSTALL_PATH ?= /tftpboot boot := arch/$(ARCH)/boot -BOOT_TARGETS = vmImage +BOOT_TARGETS = vmImage vmImage.bz2 vmImage.gz vmImage.lzma PHONY += $(BOOT_TARGETS) install KBUILD_IMAGE := $(boot)/vmImage @@ -150,7 +150,10 @@ install: $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install define archhelp - echo '* vmImage - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage)' + echo '* vmImage - Alias to selected kernel format (vmImage.gz by default)' + echo ' vmImage.bz2 - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.bz2)' + echo '* vmImage.gz - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.gz)' + echo ' vmImage.lzma - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.lzma)' echo ' install - Install kernel using' echo ' (your) ~/bin/$(CROSS_COMPILE)installkernel or' echo ' (distribution) PATH: $(CROSS_COMPILE)installkernel or' diff --git a/arch/blackfin/boot/.gitignore b/arch/blackfin/boot/.gitignore index 3ae03994b88d..229e50808677 100644 --- a/arch/blackfin/boot/.gitignore +++ b/arch/blackfin/boot/.gitignore @@ -1 +1,2 @@ -+vmImage +vmImage* +vmlinux* diff --git a/arch/blackfin/boot/Makefile b/arch/blackfin/boot/Makefile index e028d13481a9..3ab6f23561dd 100644 --- a/arch/blackfin/boot/Makefile +++ b/arch/blackfin/boot/Makefile @@ -8,24 +8,41 @@ MKIMAGE := $(srctree)/scripts/mkuboot.sh -targets := vmImage -extra-y += vmlinux.bin vmlinux.gz +targets := vmImage vmImage.bz2 vmImage.gz vmImage.lzma +extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma quiet_cmd_uimage = UIMAGE $@ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(ARCH) -O linux -T kernel \ - -C gzip -n 'Linux-$(KERNELRELEASE)' -a $(CONFIG_BOOT_LOAD) \ + -C $(2) -n 'Linux-$(KERNELRELEASE)' -a $(CONFIG_BOOT_LOAD) \ -e $(shell $(NM) vmlinux | awk '$$NF == "__start" {print $$1}') \ -d $< $@ $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) -$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE +$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(call if_changed,gzip) -$(obj)/vmImage: $(obj)/vmlinux.gz - $(call if_changed,uimage) - @$(kecho) 'Kernel: $@ is ready' +$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE + $(call if_changed,bzip2) + +$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE + $(call if_changed,lzma) + +$(obj)/vmImage.bz2: $(obj)/vmlinux.bin.bz2 + $(call if_changed,uimage,bzip2) + +$(obj)/vmImage.gz: $(obj)/vmlinux.bin.gz + $(call if_changed,uimage,gzip) + +$(obj)/vmImage.lzma: $(obj)/vmlinux.bin.lzma + $(call if_changed,uimage,lzma) + +suffix-$(CONFIG_KERNEL_GZIP) := gz +suffix-$(CONFIG_KERNEL_BZIP2) := bz2 +suffix-$(CONFIG_KERNEL_LZMA) := lzma +$(obj)/vmImage: $(obj)/vmImage.$(suffix-y) + @ln -sf $(notdir $<) $@ install: sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h index 7bbf44e4ddf9..b1d92f13ef96 100644 --- a/arch/blackfin/include/asm/atomic.h +++ b/arch/blackfin/include/asm/atomic.h @@ -90,7 +90,7 @@ static inline int atomic_test_mask(int mask, atomic_t *v) static inline void atomic_add(int i, atomic_t *v) { - long flags; + unsigned long flags; local_irq_save_hw(flags); v->counter += i; @@ -99,7 +99,7 @@ static inline void atomic_add(int i, atomic_t *v) static inline void atomic_sub(int i, atomic_t *v) { - long flags; + unsigned long flags; local_irq_save_hw(flags); v->counter -= i; @@ -110,7 +110,7 @@ static inline void atomic_sub(int i, atomic_t *v) static inline int atomic_add_return(int i, atomic_t *v) { int __temp = 0; - long flags; + unsigned long flags; local_irq_save_hw(flags); v->counter += i; @@ -124,7 +124,7 @@ static inline int atomic_add_return(int i, atomic_t *v) static inline int atomic_sub_return(int i, atomic_t *v) { int __temp = 0; - long flags; + unsigned long flags; local_irq_save_hw(flags); v->counter -= i; @@ -136,7 +136,7 @@ static inline int atomic_sub_return(int i, atomic_t *v) static inline void atomic_inc(volatile atomic_t *v) { - long flags; + unsigned long flags; local_irq_save_hw(flags); v->counter++; @@ -145,7 +145,7 @@ static inline void atomic_inc(volatile atomic_t *v) static inline void atomic_dec(volatile atomic_t *v) { - long flags; + unsigned long flags; local_irq_save_hw(flags); v->counter--; @@ -154,7 +154,7 @@ static inline void atomic_dec(volatile atomic_t *v) static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) { - long flags; + unsigned long flags; local_irq_save_hw(flags); v->counter &= ~mask; @@ -163,7 +163,7 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) static inline void atomic_set_mask(unsigned int mask, atomic_t *v) { - long flags; + unsigned long flags; local_irq_save_hw(flags); v->counter |= mask; diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h index daffc0684e75..e39277ea43e8 100644 --- a/arch/blackfin/include/asm/bfin-global.h +++ b/arch/blackfin/include/asm/bfin-global.h @@ -31,7 +31,7 @@ #ifndef __ASSEMBLY__ -#include <asm-generic/sections.h> +#include <asm/sections.h> #include <asm/ptrace.h> #include <asm/user.h> #include <linux/linkage.h> @@ -99,15 +99,6 @@ extern const char bfin_board_name[]; extern unsigned long bfin_sic_iwr[]; extern unsigned vr_wakeup; extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */ -extern unsigned long _ramstart, _ramend, _rambase; -extern unsigned long memory_start, memory_end, physical_mem_end; -extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[], - _ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _sbss_b_l1[], _ebss_b_l1[], - _stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[], - _ebss_l2[], _l2_lma_start[]; - -/* only used when MTD_UCLINUX */ -extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size; #ifdef CONFIG_BFIN_ICACHE_LOCK extern void cache_grab_lock(int way); diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h index 21b036eadab1..75fee2f7d9f2 100644 --- a/arch/blackfin/include/asm/bitops.h +++ b/arch/blackfin/include/asm/bitops.h @@ -109,7 +109,8 @@ static inline void clear_bit(int nr, volatile unsigned long *addr) static inline void change_bit(int nr, volatile unsigned long *addr) { - int mask, flags; + int mask; + unsigned long flags; unsigned long *ADDR = (unsigned long *)addr; ADDR += nr >> 5; diff --git a/arch/blackfin/include/asm/bug.h b/arch/blackfin/include/asm/bug.h index 6d3e11b1fc57..655e49540e41 100644 --- a/arch/blackfin/include/asm/bug.h +++ b/arch/blackfin/include/asm/bug.h @@ -2,13 +2,58 @@ #define _BLACKFIN_BUG_H #ifdef CONFIG_BUG -#define HAVE_ARCH_BUG -#define BUG() do { \ - dump_bfin_trace_buffer(); \ - printk(KERN_EMERG "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \ - panic("BUG!"); \ -} while (0) +#define BFIN_BUG_OPCODE 0xefcd + +#ifdef CONFIG_DEBUG_BUGVERBOSE + +#define _BUG_OR_WARN(flags) \ + asm volatile( \ + "1: .hword %0\n" \ + " .section __bug_table,\"a\",@progbits\n" \ + "2: .long 1b\n" \ + " .long %1\n" \ + " .short %2\n" \ + " .short %3\n" \ + " .org 2b + %4\n" \ + " .previous" \ + : \ + : "i"(BFIN_BUG_OPCODE), "i"(__FILE__), \ + "i"(__LINE__), "i"(flags), \ + "i"(sizeof(struct bug_entry))) + +#else + +#define _BUG_OR_WARN(flags) \ + asm volatile( \ + "1: .hword %0\n" \ + " .section __bug_table,\"a\",@progbits\n" \ + "2: .long 1b\n" \ + " .short %1\n" \ + " .org 2b + %2\n" \ + " .previous" \ + : \ + : "i"(BFIN_BUG_OPCODE), "i"(flags), \ + "i"(sizeof(struct bug_entry))) + +#endif /* CONFIG_DEBUG_BUGVERBOSE */ + +#define BUG() \ + do { \ + _BUG_OR_WARN(0); \ + for (;;); \ + } while (0) + +#define WARN_ON(condition) \ + ({ \ + int __ret_warn_on = !!(condition); \ + if (unlikely(__ret_warn_on)) \ + _BUG_OR_WARN(BUGFLAG_WARNING); \ + unlikely(__ret_warn_on); \ + }) + +#define HAVE_ARCH_BUG +#define HAVE_ARCH_WARN_ON #endif diff --git a/arch/blackfin/include/asm/cache.h b/arch/blackfin/include/asm/cache.h index 86637814cf25..2ef669ed9222 100644 --- a/arch/blackfin/include/asm/cache.h +++ b/arch/blackfin/include/asm/cache.h @@ -34,9 +34,13 @@ #define L1_CACHE_SHIFT_MAX 5 #if defined(CONFIG_SMP) && \ - !defined(CONFIG_BFIN_CACHE_COHERENT) && \ - defined(CONFIG_BFIN_DCACHE) -#define __ARCH_SYNC_CORE_DCACHE + !defined(CONFIG_BFIN_CACHE_COHERENT) +# if defined(CONFIG_BFIN_ICACHE) +# define __ARCH_SYNC_CORE_ICACHE +# endif +# if defined(CONFIG_BFIN_DCACHE) +# define __ARCH_SYNC_CORE_DCACHE +# endif #ifndef __ASSEMBLY__ asmlinkage void __raw_smp_mark_barrier_asm(void); asmlinkage void __raw_smp_check_barrier_asm(void); @@ -51,6 +55,7 @@ static inline void smp_check_barrier(void) } void resync_core_dcache(void); +void resync_core_icache(void); #endif #endif diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h index 94697f0f6f40..5c17dee53b5d 100644 --- a/arch/blackfin/include/asm/cacheflush.h +++ b/arch/blackfin/include/asm/cacheflush.h @@ -37,6 +37,7 @@ extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned lo extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address); extern void blackfin_dflush_page(void *page); extern void blackfin_invalidate_entire_dcache(void); +extern void blackfin_invalidate_entire_icache(void); #define flush_dcache_mmap_lock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0) @@ -97,7 +98,7 @@ do { memcpy(dst, src, len); \ extern unsigned long reserved_mem_dcache_on; extern unsigned long reserved_mem_icache_on; -static inline int bfin_addr_dcachable(unsigned long addr) +static inline int bfin_addr_dcacheable(unsigned long addr) { #ifdef CONFIG_BFIN_DCACHE if (addr < (_ramend - DMA_UNCACHED_REGION)) diff --git a/arch/blackfin/include/asm/cpu.h b/arch/blackfin/include/asm/cpu.h index c2594ef877f6..565b8136855e 100644 --- a/arch/blackfin/include/asm/cpu.h +++ b/arch/blackfin/include/asm/cpu.h @@ -34,6 +34,7 @@ struct blackfin_cpudata { unsigned int dmemctl; unsigned long loops_per_jiffy; unsigned long dcache_invld_count; + unsigned long icache_invld_count; }; DECLARE_PER_CPU(struct blackfin_cpudata, cpu_data); diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h index 40a8c178f10d..8643680f0f78 100644 --- a/arch/blackfin/include/asm/ftrace.h +++ b/arch/blackfin/include/asm/ftrace.h @@ -1 +1,13 @@ -/* empty */ +/* + * Blackfin ftrace code + * + * Copyright 2009 Analog Devices Inc. + * Licensed under the GPL-2 or later. + */ + +#ifndef __ASM_BFIN_FTRACE_H__ +#define __ASM_BFIN_FTRACE_H__ + +#define MCOUNT_INSN_SIZE 8 /* sizeof mcount call: LINK + CALL */ + +#endif diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h index 51d0bf5e2899..bbe1c3726b69 100644 --- a/arch/blackfin/include/asm/ipipe.h +++ b/arch/blackfin/include/asm/ipipe.h @@ -35,10 +35,10 @@ #include <asm/atomic.h> #include <asm/traps.h> -#define IPIPE_ARCH_STRING "1.9-01" +#define IPIPE_ARCH_STRING "1.10-00" #define IPIPE_MAJOR_NUMBER 1 -#define IPIPE_MINOR_NUMBER 9 -#define IPIPE_PATCH_NUMBER 1 +#define IPIPE_MINOR_NUMBER 10 +#define IPIPE_PATCH_NUMBER 0 #ifdef CONFIG_SMP #error "I-pipe/blackfin: SMP not implemented" @@ -54,10 +54,11 @@ do { \ #define task_hijacked(p) \ ({ \ - int __x__ = ipipe_current_domain != ipipe_root_domain; \ - /* We would need to clear the SYNC flag for the root domain */ \ - /* over the current processor in SMP mode. */ \ - local_irq_enable_hw(); __x__; \ + int __x__ = __ipipe_root_domain_p; \ + __clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \ + if (__x__) \ + local_irq_enable_hw(); \ + !__x__; \ }) struct ipipe_domain; @@ -179,23 +180,24 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul) #define __ipipe_run_isr(ipd, irq) \ do { \ - if (ipd == ipipe_root_domain) { \ + if (!__ipipe_pipeline_head_p(ipd)) \ local_irq_enable_hw(); \ - if (ipipe_virtual_irq_p(irq)) \ + if (ipd == ipipe_root_domain) { \ + if (unlikely(ipipe_virtual_irq_p(irq))) { \ + irq_enter(); \ ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \ - else \ + irq_exit(); \ + } else \ ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \ - local_irq_disable_hw(); \ } else { \ __clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \ - local_irq_enable_nohead(ipd); \ ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \ /* Attempt to exit the outer interrupt level before \ * starting the deferred IRQ processing. */ \ - local_irq_disable_nohead(ipd); \ __ipipe_run_irqtail(); \ __set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \ } \ + local_irq_disable_hw(); \ } while (0) #define __ipipe_syscall_watched_p(p, sc) \ diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h index 7645e85a5f6f..400bdd52ce87 100644 --- a/arch/blackfin/include/asm/irq.h +++ b/arch/blackfin/include/asm/irq.h @@ -17,270 +17,17 @@ #ifndef _BFIN_IRQ_H_ #define _BFIN_IRQ_H_ -/* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h>*/ -#include <mach/irq.h> -#include <asm/pda.h> -#include <asm/processor.h> - -#ifdef CONFIG_SMP -/* Forward decl needed due to cdef inter dependencies */ -static inline uint32_t __pure bfin_dspid(void); -# define blackfin_core_id() (bfin_dspid() & 0xff) -# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask -#else -extern unsigned long bfin_irq_flags; -#endif - -#ifdef CONFIG_IPIPE - -#include <linux/ipipe_trace.h> +#include <linux/irqflags.h> -void __ipipe_unstall_root(void); - -void __ipipe_restore_root(unsigned long flags); - -#ifdef CONFIG_DEBUG_HWERR -# define __all_masked_irq_flags 0x3f -# define __save_and_cli_hw(x) \ - __asm__ __volatile__( \ - "cli %0;" \ - "sti %1;" \ - : "=&d"(x) \ - : "d" (0x3F) \ - ) -#else -# define __all_masked_irq_flags 0x1f -# define __save_and_cli_hw(x) \ - __asm__ __volatile__( \ - "cli %0;" \ - : "=&d"(x) \ - ) -#endif - -#define irqs_enabled_from_flags_hw(x) ((x) != __all_masked_irq_flags) -#define raw_irqs_disabled_flags(flags) (!irqs_enabled_from_flags_hw(flags)) -#define local_test_iflag_hw(x) irqs_enabled_from_flags_hw(x) - -#define local_save_flags(x) \ - do { \ - (x) = __ipipe_test_root() ? \ - __all_masked_irq_flags : bfin_irq_flags; \ - barrier(); \ - } while (0) - -#define local_irq_save(x) \ - do { \ - (x) = __ipipe_test_and_stall_root() ? \ - __all_masked_irq_flags : bfin_irq_flags; \ - barrier(); \ - } while (0) - -static inline void local_irq_restore(unsigned long x) -{ - barrier(); - __ipipe_restore_root(x == __all_masked_irq_flags); -} - -#define local_irq_disable() \ - do { \ - __ipipe_stall_root(); \ - barrier(); \ - } while (0) - -static inline void local_irq_enable(void) -{ - barrier(); - __ipipe_unstall_root(); -} - -#define irqs_disabled() __ipipe_test_root() - -#define local_save_flags_hw(x) \ - __asm__ __volatile__( \ - "cli %0;" \ - "sti %0;" \ - : "=d"(x) \ - ) - -#define irqs_disabled_hw() \ - ({ \ - unsigned long flags; \ - local_save_flags_hw(flags); \ - !irqs_enabled_from_flags_hw(flags); \ - }) - -static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real) -{ - /* Merge virtual and real interrupt mask bits into a single - 32bit word. */ - return (real & ~(1 << 31)) | ((virt != 0) << 31); -} - -static inline int raw_demangle_irq_bits(unsigned long *x) -{ - int virt = (*x & (1 << 31)) != 0; - *x &= ~(1L << 31); - return virt; -} - -#ifdef CONFIG_IPIPE_TRACE_IRQSOFF - -#define local_irq_disable_hw() \ - do { \ - int _tmp_dummy; \ - if (!irqs_disabled_hw()) \ - ipipe_trace_begin(0x80000000); \ - __asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : ); \ - } while (0) - -#define local_irq_enable_hw() \ - do { \ - if (irqs_disabled_hw()) \ - ipipe_trace_end(0x80000000); \ - __asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags)); \ - } while (0) - -#define local_irq_save_hw(x) \ - do { \ - __save_and_cli_hw(x); \ - if (local_test_iflag_hw(x)) \ - ipipe_trace_begin(0x80000001); \ - } while (0) - -#define local_irq_restore_hw(x) \ - do { \ - if (local_test_iflag_hw(x)) { \ - ipipe_trace_end(0x80000001); \ - local_irq_enable_hw_notrace(); \ - } \ - } while (0) - -#define local_irq_disable_hw_notrace() \ - do { \ - int _tmp_dummy; \ - __asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : ); \ - } while (0) - -#define local_irq_enable_hw_notrace() \ - __asm__ __volatile__( \ - "sti %0;" \ - : \ - : "d"(bfin_irq_flags) \ - ) - -#define local_irq_save_hw_notrace(x) __save_and_cli_hw(x) - -#define local_irq_restore_hw_notrace(x) \ - do { \ - if (local_test_iflag_hw(x)) \ - local_irq_enable_hw_notrace(); \ - } while (0) - -#else /* CONFIG_IPIPE_TRACE_IRQSOFF */ - -#define local_irq_enable_hw() \ - __asm__ __volatile__( \ - "sti %0;" \ - : \ - : "d"(bfin_irq_flags) \ - ) - -#define local_irq_disable_hw() \ - do { \ - int _tmp_dummy; \ - __asm__ __volatile__ ( \ - "cli %0;" \ - : "=d" (_tmp_dummy)); \ - } while (0) - -#define local_irq_restore_hw(x) \ - do { \ - if (irqs_enabled_from_flags_hw(x)) \ - local_irq_enable_hw(); \ - } while (0) - -#define local_irq_save_hw(x) __save_and_cli_hw(x) - -#define local_irq_disable_hw_notrace() local_irq_disable_hw() -#define local_irq_enable_hw_notrace() local_irq_enable_hw() -#define local_irq_save_hw_notrace(x) local_irq_save_hw(x) -#define local_irq_restore_hw_notrace(x) local_irq_restore_hw(x) - -#endif /* CONFIG_IPIPE_TRACE_IRQSOFF */ - -#else /* !CONFIG_IPIPE */ - -/* - * Interrupt configuring macros. - */ -#define local_irq_disable() \ - do { \ - int __tmp_dummy; \ - __asm__ __volatile__( \ - "cli %0;" \ - : "=d" (__tmp_dummy) \ - ); \ - } while (0) - -#define local_irq_enable() \ - __asm__ __volatile__( \ - "sti %0;" \ - : \ - : "d" (bfin_irq_flags) \ - ) - -#ifdef CONFIG_DEBUG_HWERR -# define __save_and_cli(x) \ - __asm__ __volatile__( \ - "cli %0;" \ - "sti %1;" \ - : "=&d" (x) \ - : "d" (0x3F) \ - ) -#else -# define __save_and_cli(x) \ - __asm__ __volatile__( \ - "cli %0;" \ - : "=&d" (x) \ - ) -#endif - -#define local_save_flags(x) \ - __asm__ __volatile__( \ - "cli %0;" \ - "sti %0;" \ - : "=d" (x) \ - ) - -#ifdef CONFIG_DEBUG_HWERR -#define irqs_enabled_from_flags(x) (((x) & ~0x3f) != 0) -#else -#define irqs_enabled_from_flags(x) ((x) != 0x1f) -#endif - -#define local_irq_restore(x) \ - do { \ - if (irqs_enabled_from_flags(x)) \ - local_irq_enable(); \ - } while (0) - -/* For spinlocks etc */ -#define local_irq_save(x) __save_and_cli(x) - -#define irqs_disabled() \ -({ \ - unsigned long flags; \ - local_save_flags(flags); \ - !irqs_enabled_from_flags(flags); \ -}) - -#define local_irq_save_hw(x) local_irq_save(x) -#define local_irq_restore_hw(x) local_irq_restore(x) -#define local_irq_enable_hw() local_irq_enable() -#define local_irq_disable_hw() local_irq_disable() -#define irqs_disabled_hw() irqs_disabled() +/* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h> */ +#include <mach/irq.h> -#endif /* !CONFIG_IPIPE */ +/* Xenomai IPIPE helpers */ +#define local_irq_restore_hw(x) local_irq_restore(x) +#define local_irq_save_hw(x) local_irq_save(x) +#define local_irq_enable_hw(x) local_irq_enable(x) +#define local_irq_disable_hw(x) local_irq_disable(x) +#define irqs_disabled_hw(x) irqs_disabled(x) #if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE) # define NOP_PAD_ANOMALY_05000244 "nop; nop;" diff --git a/arch/blackfin/include/asm/irqflags.h b/arch/blackfin/include/asm/irqflags.h new file mode 100644 index 000000000000..139cba4651b1 --- /dev/null +++ b/arch/blackfin/include/asm/irqflags.h @@ -0,0 +1,63 @@ +/* + * interface to Blackfin CEC + * + * Copyright 2009 Analog Devices Inc. + * Licensed under the GPL-2 or later. + */ + +#ifndef __ASM_BFIN_IRQFLAGS_H__ +#define __ASM_BFIN_IRQFLAGS_H__ + +#ifdef CONFIG_SMP +# include <asm/pda.h> +# include <asm/processor.h> +/* Forward decl needed due to cdef inter dependencies */ +static inline uint32_t __pure bfin_dspid(void); +# define blackfin_core_id() (bfin_dspid() & 0xff) +# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask +#else +extern unsigned long bfin_irq_flags; +#endif + +static inline void bfin_sti(unsigned long flags) +{ + asm volatile("sti %0;" : : "d" (flags)); +} + +static inline unsigned long bfin_cli(void) +{ + unsigned long flags; + asm volatile("cli %0;" : "=d" (flags)); + return flags; +} + +static inline void raw_local_irq_disable(void) +{ + bfin_cli(); +} +static inline void raw_local_irq_enable(void) +{ + bfin_sti(bfin_irq_flags); +} + +#define raw_local_save_flags(flags) do { (flags) = bfin_read_IMASK(); } while (0) + +#define raw_irqs_disabled_flags(flags) (((flags) & ~0x3f) == 0) + +static inline void raw_local_irq_restore(unsigned long flags) +{ + if (!raw_irqs_disabled_flags(flags)) + raw_local_irq_enable(); +} + +static inline unsigned long __raw_local_irq_save(void) +{ + unsigned long flags = bfin_cli(); +#ifdef CONFIG_DEBUG_HWERR + bfin_sti(0x3f); +#endif + return flags; +} +#define raw_local_irq_save(flags) do { (flags) = __raw_local_irq_save(); } while (0) + +#endif diff --git a/arch/blackfin/include/asm/mutex-dec.h b/arch/blackfin/include/asm/mutex-dec.h deleted file mode 100644 index 0134151656af..000000000000 --- a/arch/blackfin/include/asm/mutex-dec.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * include/asm-generic/mutex-dec.h - * - * Generic implementation of the mutex fastpath, based on atomic - * decrement/increment. - */ -#ifndef _ASM_GENERIC_MUTEX_DEC_H -#define _ASM_GENERIC_MUTEX_DEC_H - -/** - * __mutex_fastpath_lock - try to take the lock by moving the count - * from 1 to a 0 value - * @count: pointer of type atomic_t - * @fail_fn: function to call if the original value was not 1 - * - * Change the count from 1 to a value lower than 1, and call <fail_fn> if - * it wasn't 1 originally. This function MUST leave the value lower than - * 1 even when the "1" assertion wasn't true. - */ -static inline void -__mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *)) -{ - if (unlikely(atomic_dec_return(count) < 0)) - fail_fn(count); - else - smp_mb(); -} - -/** - * __mutex_fastpath_lock_retval - try to take the lock by moving the count - * from 1 to a 0 value - * @count: pointer of type atomic_t - * @fail_fn: function to call if the original value was not 1 - * - * Change the count from 1 to a value lower than 1, and call <fail_fn> if - * it wasn't 1 originally. This function returns 0 if the fastpath succeeds, - * or anything the slow path function returns. - */ -static inline int -__mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *)) -{ - if (unlikely(atomic_dec_return(count) < 0)) - return fail_fn(count); - else { - smp_mb(); - return 0; - } -} - -/** - * __mutex_fastpath_unlock - try to promote the count from 0 to 1 - * @count: pointer of type atomic_t - * @fail_fn: function to call if the original value was not 0 - * - * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>. - * In the failure case, this function is allowed to either set the value to - * 1, or to set it to a value lower than 1. - * - * If the implementation sets it to a value of lower than 1, then the - * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs - * to return 0 otherwise. - */ -static inline void -__mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *)) -{ - smp_mb(); - if (unlikely(atomic_inc_return(count) <= 0)) - fail_fn(count); -} - -#define __mutex_slowpath_needs_to_unlock() 1 - -/** - * __mutex_fastpath_trylock - try to acquire the mutex, without waiting - * - * @count: pointer of type atomic_t - * @fail_fn: fallback function - * - * Change the count from 1 to a value lower than 1, and return 0 (failure) - * if it wasn't 1 originally, or return 1 (success) otherwise. This function - * MUST leave the value lower than 1 even when the "1" assertion wasn't true. - * Additionally, if the value was < 0 originally, this function must not leave - * it to 0 on failure. - * - * If the architecture has no effective trylock variant, it should call the - * <fail_fn> spinlock-based trylock variant unconditionally. - */ -static inline int -__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) -{ - /* - * We have two variants here. The cmpxchg based one is the best one - * because it never induce a false contention state. It is included - * here because architectures using the inc/dec algorithms over the - * xchg ones are much more likely to support cmpxchg natively. - * - * If not we fall back to the spinlock based variant - that is - * just as efficient (and simpler) as a 'destructive' probing of - * the mutex state would be. - */ -#ifdef __HAVE_ARCH_CMPXCHG - if (likely(atomic_cmpxchg(count, 1, 0) == 1)) { - smp_mb(); - return 1; - } - return 0; -#else - return fail_fn(count); -#endif -} - -#endif diff --git a/arch/blackfin/include/asm/sections.h b/arch/blackfin/include/asm/sections.h index 1443c3353a8c..e7fd0ecd73f7 100644 --- a/arch/blackfin/include/asm/sections.h +++ b/arch/blackfin/include/asm/sections.h @@ -4,4 +4,15 @@ /* nothing to see, move along */ #include <asm-generic/sections.h> +/* only used when MTD_UCLINUX */ +extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size; + +extern unsigned long _ramstart, _ramend, _rambase; +extern unsigned long memory_start, memory_end, physical_mem_end; + +extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[], + _ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _sbss_b_l1[], _ebss_b_l1[], + _stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[], + _ebss_l2[], _l2_lma_start[]; + #endif diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h index a4c8254bec55..294dbda24164 100644 --- a/arch/blackfin/include/asm/system.h +++ b/arch/blackfin/include/asm/system.h @@ -35,10 +35,10 @@ #define _BLACKFIN_SYSTEM_H #include <linux/linkage.h> -#include <linux/compiler.h> +#include <linux/irqflags.h> #include <mach/anomaly.h> +#include <asm/cache.h> #include <asm/pda.h> -#include <asm/processor.h> #include <asm/irq.h> /* diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h index cf5066d3efd2..da35133c171d 100644 --- a/arch/blackfin/include/asm/unistd.h +++ b/arch/blackfin/include/asm/unistd.h @@ -380,8 +380,9 @@ #define __NR_inotify_init1 365 #define __NR_preadv 366 #define __NR_pwritev 367 +#define __NR_rt_tgsigqueueinfo 368 -#define __NR_syscall 368 +#define __NR_syscall 369 #define NR_syscalls __NR_syscall /* Old optional stuff no one actually uses */ diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index fd4d4328a0f2..3731088e181b 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -15,6 +15,10 @@ else obj-y += time.o endif +obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o +obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o +CFLAGS_REMOVE_ftrace.o = -pg + obj-$(CONFIG_IPIPE) += ipipe.o obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o @@ -23,6 +27,7 @@ obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o # the kgdb test puts code into L2 and without linker # relaxation, we need to force long calls to/from it diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 763ed84ba459..e0bf8cc06907 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -453,10 +453,10 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size) unsigned long src = (unsigned long)psrc; size_t bulk, rest; - if (bfin_addr_dcachable(src)) + if (bfin_addr_dcacheable(src)) blackfin_dcache_flush_range(src, src + size); - if (bfin_addr_dcachable(dst)) + if (bfin_addr_dcacheable(dst)) blackfin_dcache_invalidate_range(dst, dst + size); bulk = size & ~0xffff; diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c index 53e893ff708a..aa05e638fb7c 100644 --- a/arch/blackfin/kernel/bfin_ksyms.c +++ b/arch/blackfin/kernel/bfin_ksyms.c @@ -103,3 +103,8 @@ EXPORT_SYMBOL(__raw_smp_mark_barrier_asm); EXPORT_SYMBOL(__raw_smp_check_barrier_asm); #endif #endif + +#ifdef CONFIG_FUNCTION_TRACER +extern void _mcount(void); +EXPORT_SYMBOL(_mcount); +#endif diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c index 87463ce87f5a..784923e52a9a 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c @@ -151,7 +151,7 @@ static noinline int dcplb_miss(unsigned int cpu) d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; #ifdef CONFIG_BFIN_DCACHE - if (bfin_addr_dcachable(addr)) { + if (bfin_addr_dcacheable(addr)) { d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; #ifdef CONFIG_BFIN_WT d_data |= CPLB_L1_AOW | CPLB_WT; diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c index 8cbb47c7b663..12b030842fdb 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c @@ -28,6 +28,7 @@ #include <asm/cplbinit.h> #include <asm/cplb.h> #include <asm/mmu_context.h> +#include <asm/traps.h> /* * WARNING @@ -100,28 +101,6 @@ static inline void write_icplb_data(int cpu, int idx, unsigned long data, #endif } -/* - * Given the contents of the status register, return the index of the - * CPLB that caused the fault. - */ -static inline int faulting_cplb_index(int status) -{ - int signbits = __builtin_bfin_norm_fr1x32(status & 0xFFFF); - return 30 - signbits; -} - -/* - * Given the contents of the status register and the DCPLB_DATA contents, - * return true if a write access should be permitted. - */ -static inline int write_permitted(int status, unsigned long data) -{ - if (status & FAULT_USERSUPV) - return !!(data & CPLB_SUPV_WR); - else - return !!(data & CPLB_USER_WR); -} - /* Counters to implement round-robin replacement. */ static int icplb_rr_index[NR_CPUS] PDT_ATTR; static int dcplb_rr_index[NR_CPUS] PDT_ATTR; @@ -245,43 +224,16 @@ MGR_ATTR static int dcplb_miss(int cpu) return CPLB_RELOADED; } -MGR_ATTR static noinline int dcplb_protection_fault(int cpu) -{ - int status = bfin_read_DCPLB_STATUS(); - - nr_dcplb_prot[cpu]++; - - if (likely(status & FAULT_RW)) { - int idx = faulting_cplb_index(status); - unsigned long regaddr = DCPLB_DATA0 + idx * 4; - unsigned long data = bfin_read32(regaddr); - - /* Check if fault is to dirty a clean page */ - if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) && - write_permitted(status, data)) { - - dcplb_tbl[cpu][idx].data = data; - bfin_write32(regaddr, data); - return CPLB_RELOADED; - } - } - - return CPLB_PROT_VIOL; -} - MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs) { int cause = seqstat & 0x3f; unsigned int cpu = smp_processor_id(); switch (cause) { - case 0x2C: + case VEC_CPLB_I_M: return icplb_miss(cpu); - case 0x26: + case VEC_CPLB_M: return dcplb_miss(cpu); default: - if (unlikely(cause == 0x23)) - return dcplb_protection_fault(cpu); - return CPLB_UNKNOWN_ERR; } } diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c index 3302719173ca..2ab56811841c 100644 --- a/arch/blackfin/kernel/early_printk.c +++ b/arch/blackfin/kernel/early_printk.c @@ -202,11 +202,15 @@ asmlinkage void __init init_early_exception_vectors(void) asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) { /* This can happen before the uart is initialized, so initialize - * the UART now + * the UART now (but only if we are running on the processor we think + * we are compiled for - otherwise we write to MMRs that don't exist, + * and cause other problems. Nothing comes out the UART, but it does + * end up in the __buf_log. */ - if (likely(early_console == NULL)) + if (likely(early_console == NULL) && CPUID == bfin_cpuid()) setup_early_printk(DEFAULT_EARLY_PORT); + printk(KERN_EMERG "Early panic\n"); dump_bfin_mem(fp); show_regs(fp); dump_bfin_trace_buffer(); diff --git a/arch/blackfin/kernel/ftrace-entry.S b/arch/blackfin/kernel/ftrace-entry.S new file mode 100644 index 000000000000..6980b7a0615d --- /dev/null +++ b/arch/blackfin/kernel/ftrace-entry.S @@ -0,0 +1,140 @@ +/* + * mcount and friends -- ftrace stuff + * + * Copyright (C) 2009 Analog Devices Inc. + * Licensed under the GPL-2 or later. + */ + +#include <linux/linkage.h> +#include <asm/ftrace.h> + +.text + +/* GCC will have called us before setting up the function prologue, so we + * can clobber the normal scratch registers, but we need to make sure to + * save/restore the registers used for argument passing (R0-R2) in case + * the profiled function is using them. With data registers, R3 is the + * only one we can blow away. With pointer registers, we have P0-P2. + * + * Upon entry, the RETS will point to the top of the current profiled + * function. And since GCC setup the frame for us, the previous function + * will be waiting there. mmmm pie. + */ +ENTRY(__mcount) + /* save third function arg early so we can do testing below */ + [--sp] = r2; + + /* load the function pointer to the tracer */ + p0.l = _ftrace_trace_function; + p0.h = _ftrace_trace_function; + r3 = [p0]; + + /* optional micro optimization: don't call the stub tracer */ + r2.l = _ftrace_stub; + r2.h = _ftrace_stub; + cc = r2 == r3; + if ! cc jump .Ldo_trace; + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + /* if the ftrace_graph_return function pointer is not set to + * the ftrace_stub entry, call prepare_ftrace_return(). + */ + p0.l = _ftrace_graph_return; + p0.h = _ftrace_graph_return; + r3 = [p0]; + cc = r2 == r3; + if ! cc jump _ftrace_graph_caller; + + /* similarly, if the ftrace_graph_entry function pointer is not + * set to the ftrace_graph_entry_stub entry, ... + */ + p0.l = _ftrace_graph_entry; + p0.h = _ftrace_graph_entry; + r2.l = _ftrace_graph_entry_stub; + r2.h = _ftrace_graph_entry_stub; + r3 = [p0]; + cc = r2 == r3; + if ! cc jump _ftrace_graph_caller; +#endif + + r2 = [sp++]; + rts; + +.Ldo_trace: + + /* save first/second function arg and the return register */ + [--sp] = r0; + [--sp] = r1; + [--sp] = rets; + + /* setup the tracer function */ + p0 = r3; + + /* tracer(ulong frompc, ulong selfpc): + * frompc: the pc that did the call to ... + * selfpc: ... this location + * the selfpc itself will need adjusting for the mcount call + */ + r1 = rets; + r0 = [fp + 4]; + r1 += -MCOUNT_INSN_SIZE; + + /* call the tracer */ + call (p0); + + /* restore state and get out of dodge */ +.Lfinish_trace: + rets = [sp++]; + r1 = [sp++]; + r0 = [sp++]; + r2 = [sp++]; + +.globl _ftrace_stub +_ftrace_stub: + rts; +ENDPROC(__mcount) + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +/* The prepare_ftrace_return() function is similar to the trace function + * except it takes a pointer to the location of the frompc. This is so + * the prepare_ftrace_return() can hijack it temporarily for probing + * purposes. + */ +ENTRY(_ftrace_graph_caller) + /* save first/second function arg and the return register */ + [--sp] = r0; + [--sp] = r1; + [--sp] = rets; + + r0 = fp; + r1 = rets; + r0 += 4; + r1 += -MCOUNT_INSN_SIZE; + call _prepare_ftrace_return; + + jump .Lfinish_trace; +ENDPROC(_ftrace_graph_caller) + +/* Undo the rewrite caused by ftrace_graph_caller(). The common function + * ftrace_return_to_handler() will return the original rets so we can + * restore it and be on our way. + */ +ENTRY(_return_to_handler) + /* make sure original return values are saved */ + [--sp] = p0; + [--sp] = r0; + [--sp] = r1; + + /* get original return address */ + call _ftrace_return_to_handler; + rets = r0; + + /* anomaly 05000371 - make sure we have at least three instructions + * between rets setting and the return + */ + r1 = [sp++]; + r0 = [sp++]; + p0 = [sp++]; + rts; +ENDPROC(_return_to_handler) +#endif diff --git a/arch/blackfin/kernel/ftrace.c b/arch/blackfin/kernel/ftrace.c new file mode 100644 index 000000000000..905bfc40a00b --- /dev/null +++ b/arch/blackfin/kernel/ftrace.c @@ -0,0 +1,42 @@ +/* + * ftrace graph code + * + * Copyright (C) 2009 Analog Devices Inc. + * Licensed under the GPL-2 or later. + */ + +#include <linux/ftrace.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <asm/atomic.h> + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + +/* + * Hook the return address and push it in the stack of return addrs + * in current thread info. + */ +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) +{ + struct ftrace_graph_ent trace; + unsigned long return_hooker = (unsigned long)&return_to_handler; + + if (unlikely(atomic_read(¤t->tracing_graph_pause))) + return; + + if (ftrace_push_return_trace(*parent, self_addr, &trace.depth) == -EBUSY) + return; + + trace.func = self_addr; + + /* Only trace if the calling function expects to */ + if (!ftrace_graph_entry(&trace)) { + current->curr_ret_stack--; + return; + } + + /* all is well in the world ! hijack RETS ... */ + *parent = return_hooker; +} + +#endif diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c index 5fc424803a17..d8cde1fc5cb9 100644 --- a/arch/blackfin/kernel/ipipe.c +++ b/arch/blackfin/kernel/ipipe.c @@ -99,7 +99,7 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs) * interrupt. */ m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR); - this_domain = ipipe_current_domain; + this_domain = __ipipe_current_domain; if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control))) head = &this_domain->p_link; @@ -212,7 +212,9 @@ void __ipipe_unstall_root_raw(void) int __ipipe_syscall_root(struct pt_regs *regs) { + struct ipipe_percpu_domain_data *p; unsigned long flags; + int ret; /* * We need to run the IRQ tail hook whenever we don't @@ -231,29 +233,31 @@ int __ipipe_syscall_root(struct pt_regs *regs) /* * This routine either returns: * 0 -- if the syscall is to be passed to Linux; - * 1 -- if the syscall should not be passed to Linux, and no + * >0 -- if the syscall should not be passed to Linux, and no * tail work should be performed; - * -1 -- if the syscall should not be passed to Linux but the + * <0 -- if the syscall should not be passed to Linux but the * tail work has to be performed (for handling signals etc). */ - if (__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL) && - __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs) > 0) { - if (ipipe_root_domain_p && !in_atomic()) { - /* - * Sync pending VIRQs before _TIF_NEED_RESCHED - * is tested. - */ - local_irq_save_hw(flags); - if ((ipipe_root_cpudom_var(irqpend_himask) & IPIPE_IRQMASK_VIRT) != 0) - __ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT); - local_irq_restore_hw(flags); - return -1; - } + if (!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL)) + return 0; + + ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs); + + local_irq_save_hw(flags); + + if (!__ipipe_root_domain_p) { + local_irq_restore_hw(flags); return 1; } - return 0; + p = ipipe_root_cpudom_ptr(); + if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0) + __ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT); + + local_irq_restore_hw(flags); + + return -ret; } unsigned long ipipe_critical_enter(void (*syncfn) (void)) @@ -329,9 +333,7 @@ asmlinkage void __ipipe_sync_root(void) void ___ipipe_sync_pipeline(unsigned long syncmask) { - struct ipipe_domain *ipd = ipipe_current_domain; - - if (ipd == ipipe_root_domain) { + if (__ipipe_root_domain_p) { if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status))) return; } diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 80447f99c2b5..6454babdfaff 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -1098,7 +1098,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) CPUID, bfin_cpuid()); seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" - "stepping\t: %d\n", + "stepping\t: %d ", cpu, cclk/1000000, sclk/1000000, #ifdef CONFIG_MPU "mpu on", @@ -1107,7 +1107,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) #endif revid); - seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", + if (bfin_revid() != bfin_compiled_revid()) { + if (bfin_compiled_revid() == -1) + seq_printf(m, "(Compiled for Rev none)"); + else if (bfin_compiled_revid() == 0xffff) + seq_printf(m, "(Compiled for Rev any)"); + else + seq_printf(m, "(Compiled for Rev %d)", bfin_compiled_revid()); + } + + seq_printf(m, "\ncpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", cclk/1000000, cclk%1000000, sclk/1000000, sclk%1000000); seq_printf(m, "bogomips\t: %lu.%02lu\n" @@ -1172,6 +1181,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) #ifdef __ARCH_SYNC_CORE_DCACHE seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", cpudata->dcache_invld_count); #endif +#ifdef __ARCH_SYNC_CORE_ICACHE + seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", cpudata->icache_invld_count); +#endif #ifdef CONFIG_BFIN_ICACHE_LOCK switch ((cpudata->imemctl >> 3) & WAYALL_L) { case WAY0_L: diff --git a/arch/blackfin/kernel/stacktrace.c b/arch/blackfin/kernel/stacktrace.c new file mode 100644 index 000000000000..30301e1eace5 --- /dev/null +++ b/arch/blackfin/kernel/stacktrace.c @@ -0,0 +1,53 @@ +/* + * Blackfin stacktrace code (mostly copied from avr32) + * + * Copyright 2009 Analog Devices Inc. + * Licensed under the GPL-2 or later. + */ + +#include <linux/sched.h> +#include <linux/stacktrace.h> +#include <linux/thread_info.h> +#include <linux/module.h> + +register unsigned long current_frame_pointer asm("FP"); + +struct stackframe { + unsigned long fp; + unsigned long rets; +}; + +/* + * Save stack-backtrace addresses into a stack_trace buffer. + */ +void save_stack_trace(struct stack_trace *trace) +{ + unsigned long low, high; + unsigned long fp; + struct stackframe *frame; + int skip = trace->skip; + + low = (unsigned long)task_stack_page(current); + high = low + THREAD_SIZE; + fp = current_frame_pointer; + + while (fp >= low && fp <= (high - sizeof(*frame))) { + frame = (struct stackframe *)fp; + + if (skip) { + skip--; + } else { + trace->entries[trace->nr_entries++] = frame->rets; + if (trace->nr_entries >= trace->max_entries) + break; + } + + /* + * The next frame must be at a higher address than the + * current frame. + */ + low = fp + sizeof(*frame); + fp = frame->fp; + } +} +EXPORT_SYMBOL_GPL(save_stack_trace); diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index aa76dfb0226e..d279552fe9b0 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -27,6 +27,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <linux/bug.h> #include <linux/uaccess.h> #include <linux/interrupt.h> #include <linux/module.h> @@ -238,6 +239,11 @@ asmlinkage void double_fault_c(struct pt_regs *fp) } +static int kernel_mode_regs(struct pt_regs *regs) +{ + return regs->ipend & 0xffc0; +} + asmlinkage void trap_c(struct pt_regs *fp) { #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON @@ -246,6 +252,7 @@ asmlinkage void trap_c(struct pt_regs *fp) #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO unsigned int cpu = smp_processor_id(); #endif + const char *strerror = NULL; int sig = 0; siginfo_t info; unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; @@ -259,27 +266,10 @@ asmlinkage void trap_c(struct pt_regs *fp) * double faults if the stack has become corrupt */ - /* If the fault was caused by a kernel thread, or interrupt handler - * we will kernel panic, so the system reboots. - * If KGDB is enabled, don't set this for kernel breakpoints - */ - - /* TODO: check to see if we are in some sort of deferred HWERR - * that we should be able to recover from, not kernel panic - */ - if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP) -#ifdef CONFIG_KGDB - && (trapnr != VEC_EXCPT02) +#ifndef CONFIG_KGDB + /* IPEND is skipped if KGDB isn't enabled (see entry code) */ + fp->ipend = bfin_read_IPEND(); #endif - ){ - console_verbose(); - oops_in_progress = 1; - } else if (current) { - if (current->mm == NULL) { - console_verbose(); - oops_in_progress = 1; - } - } /* trap_c() will be called for exceptions. During exceptions * processing, the pc value should be set with retx value. @@ -307,15 +297,15 @@ asmlinkage void trap_c(struct pt_regs *fp) sig = SIGTRAP; CHK_DEBUGGER_TRAP_MAYBE(); /* Check if this is a breakpoint in kernel space */ - if (fp->ipend & 0xffc0) - return; + if (kernel_mode_regs(fp)) + goto traps_done; else break; /* 0x03 - User Defined, userspace stack overflow */ case VEC_EXCPT03: info.si_code = SEGV_STACKFLOW; sig = SIGSEGV; - verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x03(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x02 - KGDB initial connection and break signal trap */ @@ -324,7 +314,7 @@ asmlinkage void trap_c(struct pt_regs *fp) info.si_code = TRAP_ILLTRAP; sig = SIGTRAP; CHK_DEBUGGER_TRAP(); - return; + goto traps_done; #endif /* 0x04 - User Defined */ /* 0x05 - User Defined */ @@ -344,7 +334,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_EXCPT04 ... VEC_EXCPT15: info.si_code = ILL_ILLPARAOP; sig = SIGILL; - verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x04(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x10 HW Single step, handled here */ @@ -353,15 +343,15 @@ asmlinkage void trap_c(struct pt_regs *fp) sig = SIGTRAP; CHK_DEBUGGER_TRAP_MAYBE(); /* Check if this is a single step in kernel space */ - if (fp->ipend & 0xffc0) - return; + if (kernel_mode_regs(fp)) + goto traps_done; else break; /* 0x11 - Trace Buffer Full, handled here */ case VEC_OVFLOW: info.si_code = TRAP_TRACEFLOW; sig = SIGTRAP; - verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x11(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x12 - Reserved, Caught by default */ @@ -381,37 +371,54 @@ asmlinkage void trap_c(struct pt_regs *fp) /* 0x20 - Reserved, Caught by default */ /* 0x21 - Undefined Instruction, handled here */ case VEC_UNDEF_I: +#ifdef CONFIG_BUG + if (kernel_mode_regs(fp)) { + switch (report_bug(fp->pc, fp)) { + case BUG_TRAP_TYPE_NONE: + break; + case BUG_TRAP_TYPE_WARN: + dump_bfin_trace_buffer(); + fp->pc += 2; + goto traps_done; + case BUG_TRAP_TYPE_BUG: + /* call to panic() will dump trace, and it is + * off at this point, so it won't be clobbered + */ + panic("BUG()"); + } + } +#endif info.si_code = ILL_ILLOPC; sig = SIGILL; - verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x22 - Illegal Instruction Combination, handled here */ case VEC_ILGAL_I: info.si_code = ILL_ILLPARAOP; sig = SIGILL; - verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x22(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x23 - Data CPLB protection violation, handled here */ case VEC_CPLB_VL: info.si_code = ILL_CPLB_VI; sig = SIGBUS; - verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x24 - Data access misaligned, handled here */ case VEC_MISALI_D: info.si_code = BUS_ADRALN; sig = SIGBUS; - verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x24(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x25 - Unrecoverable Event, handled here */ case VEC_UNCOV: info.si_code = ILL_ILLEXCPT; sig = SIGILL; - verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x25(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, @@ -419,7 +426,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_CPLB_M: info.si_code = BUS_ADRALN; sig = SIGBUS; - verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x26(KERN_NOTICE); break; /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ case VEC_CPLB_MHIT: @@ -427,10 +434,10 @@ asmlinkage void trap_c(struct pt_regs *fp) sig = SIGSEGV; #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START) - verbose_printk(KERN_NOTICE "NULL pointer access\n"); + strerror = KERN_NOTICE "NULL pointer access\n"; else #endif - verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x27(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x28 - Emulation Watchpoint, handled here */ @@ -440,8 +447,8 @@ asmlinkage void trap_c(struct pt_regs *fp) pr_debug(EXC_0x28(KERN_DEBUG)); CHK_DEBUGGER_TRAP_MAYBE(); /* Check if this is a watchpoint in kernel space */ - if (fp->ipend & 0xffc0) - return; + if (kernel_mode_regs(fp)) + goto traps_done; else break; #ifdef CONFIG_BF535 @@ -449,7 +456,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ info.si_code = BUS_OPFETCH; sig = SIGBUS; - verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); + strerror = KERN_NOTICE "BF535: VEC_ISTRU_VL\n"; CHK_DEBUGGER_TRAP_MAYBE(); break; #else @@ -459,21 +466,21 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_MISALI_I: info.si_code = BUS_ADRALN; sig = SIGBUS; - verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x2A(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2B - Instruction CPLB protection violation, handled here */ case VEC_CPLB_I_VL: info.si_code = ILL_CPLB_VI; sig = SIGBUS; - verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x2B(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ case VEC_CPLB_I_M: info.si_code = ILL_CPLB_MISS; sig = SIGBUS; - verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x2C(KERN_NOTICE); break; /* 0x2D - Instruction CPLB Multiple Hits, handled here */ case VEC_CPLB_I_MHIT: @@ -481,17 +488,17 @@ asmlinkage void trap_c(struct pt_regs *fp) sig = SIGSEGV; #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START) - verbose_printk(KERN_NOTICE "Jump to NULL address\n"); + strerror = KERN_NOTICE "Jump to NULL address\n"; else #endif - verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x2D(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2E - Illegal use of Supervisor Resource, handled here */ case VEC_ILL_RES: info.si_code = ILL_PRVOPC; sig = SIGILL; - verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); + strerror = KERN_NOTICE EXC_0x2E(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2F - Reserved, Caught by default */ @@ -519,17 +526,17 @@ asmlinkage void trap_c(struct pt_regs *fp) case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): info.si_code = BUS_ADRALN; sig = SIGBUS; - verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE)); + strerror = KERN_NOTICE HWC_x2(KERN_NOTICE); break; /* External Memory Addressing Error */ case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): info.si_code = BUS_ADRERR; sig = SIGBUS; - verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE)); + strerror = KERN_NOTICE HWC_x3(KERN_NOTICE); break; /* Performance Monitor Overflow */ case (SEQSTAT_HWERRCAUSE_PERF_FLOW): - verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE)); + strerror = KERN_NOTICE HWC_x12(KERN_NOTICE); break; /* RAISE 5 instruction */ case (SEQSTAT_HWERRCAUSE_RAISE_5): @@ -546,7 +553,6 @@ asmlinkage void trap_c(struct pt_regs *fp) * if we get here we hit a reserved one, so panic */ default: - oops_in_progress = 1; info.si_code = ILL_ILLPARAOP; sig = SIGILL; verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", @@ -557,6 +563,16 @@ asmlinkage void trap_c(struct pt_regs *fp) BUG_ON(sig == 0); + /* If the fault was caused by a kernel thread, or interrupt handler + * we will kernel panic, so the system reboots. + */ + if (kernel_mode_regs(fp) || (current && !current->mm)) { + console_verbose(); + oops_in_progress = 1; + if (strerror) + verbose_printk(strerror); + } + if (sig != SIGTRAP) { dump_bfin_process(fp); dump_bfin_mem(fp); @@ -606,8 +622,8 @@ asmlinkage void trap_c(struct pt_regs *fp) if (ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) fp->pc = SAFE_USER_INSTRUCTION; + traps_done: trace_buffer_restore(j); - return; } /* Typical exception handling routines */ @@ -792,6 +808,18 @@ void dump_bfin_trace_buffer(void) } EXPORT_SYMBOL(dump_bfin_trace_buffer); +#ifdef CONFIG_BUG +int is_valid_bugaddr(unsigned long addr) +{ + unsigned short opcode; + + if (!get_instruction(&opcode, (unsigned short *)addr)) + return 0; + + return opcode == BFIN_BUG_OPCODE; +} +#endif + /* * Checks to see if the address pointed to is either a * 16-bit CALL instruction, or a 32-bit CALL instruction diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index 8b67167cb4f4..6ac307ca0d80 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -54,6 +54,7 @@ SECTIONS SCHED_TEXT #endif LOCK_TEXT + IRQENTRY_TEXT KPROBES_TEXT *(.text.*) *(.fixup) @@ -166,6 +167,20 @@ SECTIONS } PERCPU(4) SECURITY_INIT + + /* we have to discard exit text and such at runtime, not link time, to + * handle embedded cross-section references (alt instructions, bug + * table, eh_frame, etc...) + */ + .exit.text : + { + EXIT_TEXT + } + .exit.data : + { + EXIT_DATA + } + .init.ramfs : { . = ALIGN(4); @@ -264,8 +279,6 @@ SECTIONS /DISCARD/ : { - EXIT_TEXT - EXIT_DATA *(.exitcall.exit) } } diff --git a/arch/blackfin/lib/checksum.c b/arch/blackfin/lib/checksum.c index 762a7f02970a..cd605e7d8518 100644 --- a/arch/blackfin/lib/checksum.c +++ b/arch/blackfin/lib/checksum.c @@ -116,6 +116,7 @@ __sum16 ip_compute_csum(const void *buff, int len) { return (__force __sum16)~do_csum(buff, len); } +EXPORT_SYMBOL(ip_compute_csum); /* * copy from fs while checksumming, otherwise like csum_partial @@ -130,6 +131,7 @@ csum_partial_copy_from_user(const void __user *src, void *dst, memcpy(dst, (__force void *)src, len); return csum_partial(dst, len, sum); } +EXPORT_SYMBOL(csum_partial_copy_from_user); /* * copy from ds while checksumming, otherwise like csum_partial diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c index 62bba09bcce6..1382f0382359 100644 --- a/arch/blackfin/mach-bf518/boards/ezbrd.c +++ b/arch/blackfin/mach-bf518/boards/ezbrd.c @@ -246,7 +246,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .modalias = "m25p80", /* Name of spi_driver for this device */ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ .bus_num = 0, /* Framework bus number */ - .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/ + .chip_select = 2, /* On BF518F-EZBRD it's SPI0_SSEL2 */ .platform_data = &bfin_spi_flash_data, .controller_data = &spi_flash_chip_info, .mode = SPI_MODE_3, @@ -369,6 +369,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI0, .end = CH_SPI0, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI0, + .end = IRQ_SPI0, .flags = IORESOURCE_IRQ, }, }; @@ -399,6 +404,11 @@ static struct resource bfin_spi1_resource[] = { [1] = { .start = CH_SPI1, .end = CH_SPI1, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI1, + .end = IRQ_SPI1, .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c index 6d6f9effa0bb..1eaf27ff722e 100644 --- a/arch/blackfin/mach-bf527/boards/cm_bf527.c +++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c @@ -664,6 +664,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c index 1435c5d38cd5..9f9c0005dcf1 100644 --- a/arch/blackfin/mach-bf527/boards/ezbrd.c +++ b/arch/blackfin/mach-bf527/boards/ezbrd.c @@ -467,6 +467,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 147edd1eb1ad..3e5b7db6b065 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -723,6 +723,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c index 895f213ea454..38cf8ffd6d74 100644 --- a/arch/blackfin/mach-bf533/boards/H8606.c +++ b/arch/blackfin/mach-bf533/boards/H8606.c @@ -266,6 +266,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, } }; diff --git a/arch/blackfin/mach-bf533/boards/blackstamp.c b/arch/blackfin/mach-bf533/boards/blackstamp.c index 0765872a8ada..9ecdc361fa6d 100644 --- a/arch/blackfin/mach-bf533/boards/blackstamp.c +++ b/arch/blackfin/mach-bf533/boards/blackstamp.c @@ -162,6 +162,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, } }; diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c index a727e538fa28..1443e92d8b62 100644 --- a/arch/blackfin/mach-bf533/boards/cm_bf533.c +++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c @@ -160,6 +160,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, } }; diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c index 842f1c9c2393..89a5ec4ca048 100644 --- a/arch/blackfin/mach-bf533/boards/ezkit.c +++ b/arch/blackfin/mach-bf533/boards/ezkit.c @@ -196,6 +196,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, } }; diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index e19c565ade16..a68ade8a3ca2 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c @@ -299,6 +299,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, } }; diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c index 4fee19673127..2a87d1cfcd06 100644 --- a/arch/blackfin/mach-bf537/boards/cm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c @@ -182,8 +182,13 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, - } + }, }; /* SPI controller data */ diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c index 3c159819e555..399f81da7b93 100644 --- a/arch/blackfin/mach-bf537/boards/minotaur.c +++ b/arch/blackfin/mach-bf537/boards/minotaur.c @@ -184,6 +184,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c index 26707ce39f29..838240f151f5 100644 --- a/arch/blackfin/mach-bf537/boards/pnav10.c +++ b/arch/blackfin/mach-bf537/boards/pnav10.c @@ -398,8 +398,13 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, - } + }, }; /* SPI controller data */ diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index dfb5036f8a6b..ff7228caa7da 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -1345,7 +1345,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_PMIC_ADP5520) || defined(CONFIG_PMIC_ADP5520_MODULE) { I2C_BOARD_INFO("pmic-adp5520", 0x32), - .irq = IRQ_PF7, + .irq = IRQ_PG0, .platform_data = (void *)&adp5520_pdev_data, }, #endif diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c index 280574591201..e523e6e610d0 100644 --- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c @@ -182,6 +182,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, } }; diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c index e37cb9378884..57695b4c3c09 100644 --- a/arch/blackfin/mach-bf538/boards/ezkit.c +++ b/arch/blackfin/mach-bf538/boards/ezkit.c @@ -352,6 +352,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI0, .end = CH_SPI0, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI0, + .end = IRQ_SPI0, .flags = IORESOURCE_IRQ, } }; @@ -366,6 +371,11 @@ static struct resource bfin_spi1_resource[] = { [1] = { .start = CH_SPI1, .end = CH_SPI1, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI1, + .end = IRQ_SPI1, .flags = IORESOURCE_IRQ, } }; diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c index f53ad682530b..f5a3c30a41bd 100644 --- a/arch/blackfin/mach-bf548/boards/cm_bf548.c +++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c @@ -612,6 +612,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI0, .end = CH_SPI0, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI0, + .end = IRQ_SPI0, .flags = IORESOURCE_IRQ, } }; @@ -626,6 +631,11 @@ static struct resource bfin_spi1_resource[] = { [1] = { .start = CH_SPI1, .end = CH_SPI1, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI1, + .end = IRQ_SPI1, .flags = IORESOURCE_IRQ, } }; diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index add5a17452ce..805a57b5e650 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -396,6 +396,8 @@ static struct platform_device bfin_sir3_device = { #endif #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) +#include <linux/smsc911x.h> + static struct resource smsc911x_resources[] = { { .name = "smsc911x-memory", @@ -409,11 +411,22 @@ static struct resource smsc911x_resources[] = { .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, }, }; + +static struct smsc911x_platform_config smsc911x_config = { + .flags = SMSC911X_USE_32BIT, + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + static struct platform_device smsc911x_device = { .name = "smsc911x", .id = 0, .num_resources = ARRAY_SIZE(smsc911x_resources), .resource = smsc911x_resources, + .dev = { + .platform_data = &smsc911x_config, + }, }; #endif @@ -741,6 +754,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI0, .end = CH_SPI0, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI0, + .end = IRQ_SPI0, .flags = IORESOURCE_IRQ, } }; @@ -755,6 +773,11 @@ static struct resource bfin_spi1_resource[] = { [1] = { .start = CH_SPI1, .end = CH_SPI1, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI1, + .end = IRQ_SPI1, .flags = IORESOURCE_IRQ, } }; diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c index 0dd9685e5d53..0c9d72c5f5ba 100644 --- a/arch/blackfin/mach-bf561/boards/cm_bf561.c +++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c @@ -177,8 +177,13 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, - } + }, }; /* SPI controller data */ diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c index 0e2178a1aec5..b5ef7ff7b7bd 100644 --- a/arch/blackfin/mach-bf561/boards/ezkit.c +++ b/arch/blackfin/mach-bf561/boards/ezkit.c @@ -304,6 +304,11 @@ static struct resource bfin_spi0_resource[] = { [1] = { .start = CH_SPI, .end = CH_SPI, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = IRQ_SPI, + .end = IRQ_SPI, .flags = IORESOURCE_IRQ, } }; diff --git a/arch/blackfin/mach-common/cache-c.c b/arch/blackfin/mach-common/cache-c.c index e6ab1f815123..b59ce3cb3807 100644 --- a/arch/blackfin/mach-common/cache-c.c +++ b/arch/blackfin/mach-common/cache-c.c @@ -16,9 +16,21 @@ void blackfin_invalidate_entire_dcache(void) { u32 dmem = bfin_read_DMEM_CONTROL(); - SSYNC(); bfin_write_DMEM_CONTROL(dmem & ~0xc); SSYNC(); bfin_write_DMEM_CONTROL(dmem); SSYNC(); } + +/* Invalidate the Entire Instruction cache by + * clearing IMC bit + */ +void blackfin_invalidate_entire_icache(void) +{ + u32 imem = bfin_read_IMEM_CONTROL(); + bfin_write_IMEM_CONTROL(imem & ~0x4); + SSYNC(); + bfin_write_IMEM_CONTROL(imem); + SSYNC(); +} + diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index da0558ad1b1a..31fa313e81cf 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -42,6 +42,7 @@ #include <asm/thread_info.h> /* TIF_NEED_RESCHED */ #include <asm/asm-offsets.h> #include <asm/trace.h> +#include <asm/traps.h> #include <asm/context.S> @@ -84,13 +85,15 @@ ENTRY(_ex_workaround_261) if !cc jump _bfin_return_from_exception; /* fall through */ R7 = P4; - R6 = 0x26; /* Data CPLB Miss */ + R6 = VEC_CPLB_M; /* Data CPLB Miss */ cc = R6 == R7; if cc jump _ex_dcplb_miss (BP); - R6 = 0x23; /* Data CPLB Miss */ +#ifdef CONFIG_MPU + R6 = VEC_CPLB_VL; /* Data CPLB Violation */ cc = R6 == R7; if cc jump _ex_dcplb_viol (BP); - /* Handle 0x23 Data CPLB Protection Violation +#endif + /* Handle Data CPLB Protection Violation * and Data CPLB Multiple Hits - Linux Trap Zero */ jump _ex_trap_c; @@ -270,7 +273,7 @@ ENTRY(_bfin_return_from_exception) r6.l = lo(SEQSTAT_EXCAUSE); r6.h = hi(SEQSTAT_EXCAUSE); r7 = r7 & r6; - r6 = 0x25; + r6 = VEC_UNCOV; CC = R7 == R6; if CC JUMP _double_fault; #endif @@ -1605,6 +1608,7 @@ ENTRY(_sys_call_table) .long _sys_inotify_init1 /* 365 */ .long _sys_preadv .long _sys_pwritev + .long _sys_rt_tgsigqueueinfo .rept NR_syscalls-(.-_sys_call_table)/4 .long _sys_ni_syscall diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 3b8ebaee77f2..61840059dfac 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -144,7 +144,7 @@ static void ipi_call_function(unsigned int cpu, struct ipi_message *msg) static irqreturn_t ipi_handler(int irq, void *dev_instance) { - struct ipi_message *msg, *mg; + struct ipi_message *msg; struct ipi_message_queue *msg_queue; unsigned int cpu = smp_processor_id(); @@ -154,7 +154,8 @@ static irqreturn_t ipi_handler(int irq, void *dev_instance) msg_queue->count++; spin_lock(&msg_queue->lock); - list_for_each_entry_safe(msg, mg, &msg_queue->head, list) { + while (!list_empty(&msg_queue->head)) { + msg = list_entry(msg_queue->head.next, typeof(*msg), list); list_del(&msg->list); switch (msg->type) { case BFIN_IPI_RESCHEDULE: @@ -221,7 +222,7 @@ int smp_call_function(void (*func)(void *info), void *info, int wait) for_each_cpu_mask(cpu, callmap) { msg_queue = &per_cpu(ipi_msg_queue, cpu); spin_lock_irqsave(&msg_queue->lock, flags); - list_add(&msg->list, &msg_queue->head); + list_add_tail(&msg->list, &msg_queue->head); spin_unlock_irqrestore(&msg_queue->lock, flags); platform_send_ipi_cpu(cpu); } @@ -261,7 +262,7 @@ int smp_call_function_single(int cpuid, void (*func) (void *info), void *info, msg_queue = &per_cpu(ipi_msg_queue, cpu); spin_lock_irqsave(&msg_queue->lock, flags); - list_add(&msg->list, &msg_queue->head); + list_add_tail(&msg->list, &msg_queue->head); spin_unlock_irqrestore(&msg_queue->lock, flags); platform_send_ipi_cpu(cpu); @@ -292,7 +293,7 @@ void smp_send_reschedule(int cpu) msg_queue = &per_cpu(ipi_msg_queue, cpu); spin_lock_irqsave(&msg_queue->lock, flags); - list_add(&msg->list, &msg_queue->head); + list_add_tail(&msg->list, &msg_queue->head); spin_unlock_irqrestore(&msg_queue->lock, flags); platform_send_ipi_cpu(cpu); @@ -320,7 +321,7 @@ void smp_send_stop(void) for_each_cpu_mask(cpu, callmap) { msg_queue = &per_cpu(ipi_msg_queue, cpu); spin_lock_irqsave(&msg_queue->lock, flags); - list_add(&msg->list, &msg_queue->head); + list_add_tail(&msg->list, &msg_queue->head); spin_unlock_irqrestore(&msg_queue->lock, flags); platform_send_ipi_cpu(cpu); } @@ -468,6 +469,17 @@ void smp_icache_flush_range_others(unsigned long start, unsigned long end) } EXPORT_SYMBOL_GPL(smp_icache_flush_range_others); +#ifdef __ARCH_SYNC_CORE_ICACHE +void resync_core_icache(void) +{ + unsigned int cpu = get_cpu(); + blackfin_invalidate_entire_icache(); + ++per_cpu(cpu_data, cpu).icache_invld_count; + put_cpu(); +} +EXPORT_SYMBOL(resync_core_icache); +#endif + #ifdef __ARCH_SYNC_CORE_DCACHE unsigned long barrier_mask __attribute__ ((__section__(".l2.bss"))); |