From b8d0c778e652d23750cb1af9848408d620cbc425 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Tue, 31 Mar 2009 13:40:52 +0000 Subject: Blackfin: allow scheduler functions to be placed into L1 Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/vmlinux.lds.S | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index 27952ae047d8..8b67167cb4f4 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -50,7 +50,9 @@ SECTIONS _text = .; __stext = .; TEXT_TEXT +#ifndef CONFIG_SCHEDULE_L1 SCHED_TEXT +#endif LOCK_TEXT KPROBES_TEXT *(.text.*) @@ -180,6 +182,9 @@ SECTIONS . = ALIGN(4); __stext_l1 = .; *(.l1.text) +#ifdef CONFIG_SCHEDULE_L1 + SCHED_TEXT +#endif . = ALIGN(4); __etext_l1 = .; } -- cgit v1.2.3 From 5d89137a17ca804ee60077f5d4ad8d7ca60f0614 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Apr 2009 20:52:08 +0000 Subject: Blackfin: fix data cache flushing when doing icache flushing Make sure we flush all data caches and their write buffers before flushing icache, otherwise random edge cases could crop up where stale data is read into icache from external memory. As fallout, punt the combined icache + dcache flush function since we cannot safely do them back to back -- the SSYNC is needed between the dcache flush and the icache flush. Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/cacheflush.h | 35 ++++++++++++++++------------------ arch/blackfin/kernel/bfin_ksyms.c | 1 - arch/blackfin/mach-common/cache.S | 16 ---------------- 3 files changed, 16 insertions(+), 36 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h index 1b040f5b4feb..d7726ab486ff 100644 --- a/arch/blackfin/include/asm/cacheflush.h +++ b/arch/blackfin/include/asm/cacheflush.h @@ -30,7 +30,8 @@ #ifndef _BLACKFIN_CACHEFLUSH_H #define _BLACKFIN_CACHEFLUSH_H -extern void blackfin_icache_dcache_flush_range(unsigned long start_address, unsigned long end_address); +#include /* for SSYNC() */ + extern void blackfin_icache_flush_range(unsigned long start_address, unsigned long end_address); extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address); extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address); @@ -54,32 +55,28 @@ extern void blackfin_invalidate_entire_dcache(void); static inline void flush_icache_range(unsigned start, unsigned end) { -#if defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_ICACHE) - -# if defined(CONFIG_BFIN_WT) - blackfin_icache_flush_range((start), (end)); - flush_icache_range_others(start, end); -# else - blackfin_icache_dcache_flush_range((start), (end)); -# endif - -#else +#if defined(CONFIG_BFIN_WB) + blackfin_dcache_flush_range(start, end); +#endif -# if defined(CONFIG_BFIN_ICACHE) - blackfin_icache_flush_range((start), (end)); + /* Make sure all write buffers in the data side of the core + * are flushed before trying to invalidate the icache. This + * needs to be after the data flush and before the icache + * flush so that the SSYNC does the right thing in preventing + * the instruction prefetcher from hitting things in cached + * memory at the wrong time -- it runs much further ahead than + * the pipeline. + */ + SSYNC(); +#if defined(CONFIG_BFIN_ICACHE) + blackfin_icache_flush_range(start, end); flush_icache_range_others(start, end); -# endif -# if defined(CONFIG_BFIN_DCACHE) - blackfin_dcache_flush_range((start), (end)); -# endif - #endif } #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ do { memcpy(dst, src, len); \ flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ - flush_icache_range_others((unsigned long) (dst), (unsigned long) (dst) + (len));\ } while (0) #define copy_from_user_page(vma, page, vaddr, dst, src, len) memcpy(dst, src, len) diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c index 01f917d58b59..53e893ff708a 100644 --- a/arch/blackfin/kernel/bfin_ksyms.c +++ b/arch/blackfin/kernel/bfin_ksyms.c @@ -16,7 +16,6 @@ EXPORT_SYMBOL(bfin_return_from_exception); /* All the Blackfin cache functions: mach-common/cache.S */ EXPORT_SYMBOL(blackfin_dcache_invalidate_range); -EXPORT_SYMBOL(blackfin_icache_dcache_flush_range); EXPORT_SYMBOL(blackfin_icache_flush_range); EXPORT_SYMBOL(blackfin_dcache_flush_range); EXPORT_SYMBOL(blackfin_dflush_page); diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S index aa0648c6a9fe..c295e8f837c0 100644 --- a/arch/blackfin/mach-common/cache.S +++ b/arch/blackfin/mach-common/cache.S @@ -80,22 +80,6 @@ ENTRY(_blackfin_icache_flush_range) do_flush IFLUSH, , nop ENDPROC(_blackfin_icache_flush_range) -/* Flush all cache lines assocoiated with this area of memory. */ -ENTRY(_blackfin_icache_dcache_flush_range) -/* - * Walkaround to avoid loading wrong instruction after invalidating icache - * and following sequence is met. - * - * 1) One instruction address is cached in the instruction cache. - * 2) This instruction in SDRAM is changed. - * 3) IFLASH[P0] is executed only once in blackfin_icache_flush_range(). - * 4) This instruction is executed again, but the old one is loaded. - */ - P0 = R0; - IFLUSH[P0]; - do_flush FLUSH, IFLUSH -ENDPROC(_blackfin_icache_dcache_flush_range) - /* Throw away all D-cached data in specified region without any obligation to * write them back. Since the Blackfin ISA does not have an "invalidate" * instruction, we use flush/invalidate. Perhaps as a speed optimization we -- cgit v1.2.3 From 51387009bd4d9fdbc9d4a91e45bd96cc8e3065de Mon Sep 17 00:00:00 2001 From: Philippe Gerum Date: Wed, 8 Apr 2009 07:41:55 +0000 Subject: Blackfin: merge Philippe's recent ipipe patch ipipe-2.6.28.9-blackfin-git95aafe6.patch Singed-off-by: Philippe Gerum Signed-off-by: Yi Li Signed-off-by: Bryan Wu Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/ipipe.h | 4 ++-- arch/blackfin/kernel/ipipe.c | 9 ++++++--- arch/blackfin/mach-common/ints-priority.c | 7 ------- 3 files changed, 8 insertions(+), 12 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h index 343b56361ec9..51d0bf5e2899 100644 --- a/arch/blackfin/include/asm/ipipe.h +++ b/arch/blackfin/include/asm/ipipe.h @@ -35,10 +35,10 @@ #include #include -#define IPIPE_ARCH_STRING "1.9-00" +#define IPIPE_ARCH_STRING "1.9-01" #define IPIPE_MAJOR_NUMBER 1 #define IPIPE_MINOR_NUMBER 9 -#define IPIPE_PATCH_NUMBER 0 +#define IPIPE_PATCH_NUMBER 1 #ifdef CONFIG_SMP #error "I-pipe/blackfin: SMP not implemented" diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c index a5de8d45424c..5fc424803a17 100644 --- a/arch/blackfin/kernel/ipipe.c +++ b/arch/blackfin/kernel/ipipe.c @@ -167,7 +167,7 @@ int __ipipe_check_root(void) void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq) { struct irq_desc *desc = irq_to_desc(irq); - int prio = desc->ic_prio; + int prio = __ipipe_get_irq_priority(irq); desc->depth = 0; if (ipd != &ipipe_root && @@ -178,8 +178,7 @@ EXPORT_SYMBOL(__ipipe_enable_irqdesc); void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq) { - struct irq_desc *desc = irq_to_desc(irq); - int prio = desc->ic_prio; + int prio = __ipipe_get_irq_priority(irq); if (ipd != &ipipe_root && atomic_dec_and_test(&__ipipe_irq_lvdepth[prio])) @@ -310,12 +309,16 @@ int ipipe_trigger_irq(unsigned irq) asmlinkage void __ipipe_sync_root(void) { + void (*irq_tail_hook)(void) = (void (*)(void))__ipipe_irq_tail_hook; unsigned long flags; BUG_ON(irqs_disabled()); local_irq_save_hw(flags); + if (irq_tail_hook) + irq_tail_hook(); + clear_thread_flag(TIF_IRQ_SYNC); if (ipipe_root_cpudom_var(irqpend_himask) != 0) diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 3498a90979e5..389c5e8aa456 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -1139,13 +1139,6 @@ int __init init_arch_irq(void) bfin_write_SIC_IWR(IWR_DISABLE_ALL); #endif -#ifdef CONFIG_IPIPE - for (irq = 0; irq < NR_IRQS; irq++) { - struct irq_desc *desc = irq_to_desc(irq); - desc->ic_prio = __ipipe_get_irq_priority(irq); - } -#endif /* CONFIG_IPIPE */ - return 0; } -- cgit v1.2.3 From d4b890b0cd9e0ac75cbdf7011ef38ebc662930e6 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 16 Apr 2009 12:38:34 +0000 Subject: Blackfin: do not error if GPIO IRQ is requested already as GPIO Some drivers expect to be able to request both as GPIO and GPIO IRQ, so allow that use case. Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/bfin_gpio.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index a0678da40532..32289b302e79 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -1021,15 +1021,6 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label) local_irq_save_hw(flags); - if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - if (system_state == SYSTEM_BOOTING) - dump_stack(); - printk(KERN_ERR - "bfin-gpio: GPIO %d is already reserved as gpio-irq !\n", - gpio); - local_irq_restore_hw(flags); - return -EBUSY; - } if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { if (system_state == SYSTEM_BOOTING) dump_stack(); -- cgit v1.2.3 From fecbd7366bf5a39eaae2c03541f0b412f319534f Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Thu, 23 Apr 2009 20:49:43 +0000 Subject: Blackfin: fix early L1 relocation crash Our early L1 relocate code may implicitly call code which lives in L1 memory. This is due to the dma_memcpy() rewrite that made the DMA code lockless and safe to be used by multiple processes. If we start the early DMA memcpy to relocate things into L1 instruction but then our DMA memcpy code calls a function that lives in L1, things fall apart. As such, create a small dedicated DMA memcpy routine that we can assume sanity at boot time. Reported-by: Filip Van Rillaer Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/dma.h | 2 + arch/blackfin/kernel/bfin_dma_5xx.c | 81 +++++++++++++++++++++++++++++++++++++ arch/blackfin/kernel/setup.c | 51 ++++++++++++----------- 3 files changed, 111 insertions(+), 23 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h index e4f7b8043f02..46c56185417a 100644 --- a/arch/blackfin/include/asm/dma.h +++ b/arch/blackfin/include/asm/dma.h @@ -253,5 +253,7 @@ static inline void clear_dma_irqstat(unsigned int channel) void *dma_memcpy(void *dest, const void *src, size_t count); void *safe_dma_memcpy(void *dest, const void *src, size_t count); void blackfin_dma_early_init(void); +void early_dma_memcpy(void *dest, const void *src, size_t count); +void early_dma_memcpy_done(void); #endif diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 8531693fb48d..704419e4da20 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -232,6 +232,87 @@ void blackfin_dma_resume(void) void __init blackfin_dma_early_init(void) { bfin_write_MDMA_S0_CONFIG(0); + bfin_write_MDMA_S1_CONFIG(0); +} + +void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size) +{ + unsigned long dst = (unsigned long)pdst; + unsigned long src = (unsigned long)psrc; + struct dma_register *dst_ch, *src_ch; + + /* We assume that everything is 4 byte aligned, so include + * a basic sanity check + */ + BUG_ON(dst % 4); + BUG_ON(src % 4); + BUG_ON(size % 4); + + /* Force a sync in case a previous config reset on this channel + * occurred. This is needed so subsequent writes to DMA registers + * are not spuriously lost/corrupted. + */ + __builtin_bfin_ssync(); + + src_ch = 0; + /* Find an avalible memDMA channel */ + while (1) { + if (!src_ch || src_ch == (struct dma_register *)MDMA_S1_NEXT_DESC_PTR) { + dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR; + src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR; + } else { + dst_ch = (struct dma_register *)MDMA_D1_NEXT_DESC_PTR; + src_ch = (struct dma_register *)MDMA_S1_NEXT_DESC_PTR; + } + + if (!bfin_read16(&src_ch->cfg)) { + break; + } else { + if (bfin_read16(&src_ch->irq_status) & DMA_DONE) + bfin_write16(&src_ch->cfg, 0); + } + + } + + /* Destination */ + bfin_write32(&dst_ch->start_addr, dst); + bfin_write16(&dst_ch->x_count, size >> 2); + bfin_write16(&dst_ch->x_modify, 1 << 2); + bfin_write16(&dst_ch->irq_status, DMA_DONE | DMA_ERR); + + /* Source */ + bfin_write32(&src_ch->start_addr, src); + bfin_write16(&src_ch->x_count, size >> 2); + bfin_write16(&src_ch->x_modify, 1 << 2); + bfin_write16(&src_ch->irq_status, DMA_DONE | DMA_ERR); + + /* Enable */ + bfin_write16(&src_ch->cfg, DMAEN | WDSIZE_32); + bfin_write16(&dst_ch->cfg, WNR | DI_EN | DMAEN | WDSIZE_32); + + /* Since we are atomic now, don't use the workaround ssync */ + __builtin_bfin_ssync(); +} + +void __init early_dma_memcpy_done(void) +{ + while ((bfin_read_MDMA_S0_CONFIG() && !(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) || + (bfin_read_MDMA_S1_CONFIG() && !(bfin_read_MDMA_D1_IRQ_STATUS() & DMA_DONE))) + continue; + + bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); + bfin_write_MDMA_D1_IRQ_STATUS(DMA_DONE | DMA_ERR); + /* + * Now that DMA is done, we would normally flush cache, but + * i/d cache isn't running this early, so we don't bother, + * and just clear out the DMA channel for next time + */ + bfin_write_MDMA_S0_CONFIG(0); + bfin_write_MDMA_S1_CONFIG(0); + bfin_write_MDMA_D0_CONFIG(0); + bfin_write_MDMA_D1_CONFIG(0); + + __builtin_bfin_ssync(); } /** diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index a58687bdee6a..0838eafed172 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -150,40 +150,45 @@ void __init bfin_relocate_l1_mem(void) unsigned long l1_data_b_length; unsigned long l2_length; + /* + * due to the ALIGN(4) in the arch/blackfin/kernel/vmlinux.lds.S + * we know that everything about l1 text/data is nice and aligned, + * so copy by 4 byte chunks, and don't worry about overlapping + * src/dest. + * + * We can't use the dma_memcpy functions, since they can call + * scheduler functions which might be in L1 :( and core writes + * into L1 instruction cause bad access errors, so we are stuck, + * we are required to use DMA, but can't use the common dma + * functions. We can't use memcpy either - since that might be + * going to be in the relocated L1 + */ + blackfin_dma_early_init(); + /* if necessary, copy _stext_l1 to _etext_l1 to L1 instruction SRAM */ l1_code_length = _etext_l1 - _stext_l1; - if (l1_code_length > L1_CODE_LENGTH) - panic("L1 Instruction SRAM Overflow\n"); - /* cannot complain as printk is not available as yet. - * But we can continue booting and complain later! - */ - - /* Copy _stext_l1 to _etext_l1 to L1 instruction SRAM */ - dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length); + if (l1_code_length) + early_dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length); + /* if necessary, copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */ l1_data_a_length = _sbss_l1 - _sdata_l1; - if (l1_data_a_length > L1_DATA_A_LENGTH) - panic("L1 Data SRAM Bank A Overflow\n"); - - /* Copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */ - dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length); + if (l1_data_a_length) + early_dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length); + /* if necessary, copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */ l1_data_b_length = _sbss_b_l1 - _sdata_b_l1; - if (l1_data_b_length > L1_DATA_B_LENGTH) - panic("L1 Data SRAM Bank B Overflow\n"); - - /* Copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */ - dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length + + if (l1_data_b_length) + early_dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length + l1_data_a_length, l1_data_b_length); + early_dma_memcpy_done(); + + /* if necessary, copy _stext_l2 to _edata_l2 to L2 SRAM */ if (L2_LENGTH != 0) { l2_length = _sbss_l2 - _stext_l2; - if (l2_length > L2_LENGTH) - panic("L2 SRAM Overflow\n"); - - /* Copy _stext_l2 to _edata_l2 to L2 SRAM */ - dma_memcpy(_stext_l2, _l2_lma_start, l2_length); + if (l2_length) + memcpy(_stext_l2, _l2_lma_start, l2_length); } } -- cgit v1.2.3 From 76068c3c5dee4332f532573b6423d75c3e14f660 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Thu, 23 Apr 2009 20:56:42 +0000 Subject: Blackfin: annotate anomaly 05000119 in core DMA code Add a reminder note to avoid the DMA_DONE bit in our DMA core code. Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/bfin_dma_5xx.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 704419e4da20..763ed84ba459 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -20,6 +20,11 @@ #include #include +/* + * To make sure we work around 05000119 - we always check DMA_DONE bit, + * never the DMA_RUN bit + */ + struct dma_channel dma_ch[MAX_DMA_CHANNELS]; EXPORT_SYMBOL(dma_ch); -- cgit v1.2.3 From a9a59e3096443ea4d6f50db978d7d3bbb47708b4 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 24 Apr 2009 01:42:54 +0000 Subject: Blackfin: punt useless GPIO init call This init code existed only to dump a printk(), and not even a useful one. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/bfin_gpio.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 32289b302e79..beffa00a93c3 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -313,15 +313,6 @@ inline void portmux_setup(unsigned short per) # define portmux_setup(...) do { } while (0) #endif -static int __init bfin_gpio_init(void) -{ - printk(KERN_INFO "Blackfin GPIO Controller\n"); - - return 0; -} -arch_initcall(bfin_gpio_init); - - #ifndef CONFIG_BF54x /*********************************************************** * -- cgit v1.2.3 From e522c8466d6f8437cf02a34287c8707ef53081ed Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Fri, 8 May 2009 07:42:12 +0000 Subject: Blackfin: work around anomaly 05000287 Make sure we work around anomaly 05000287 by configuring different port preferences for the data cache. Signed-off-by: Graf Yang Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/cplb-mpu/cacheinit.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/cplb-mpu/cacheinit.c b/arch/blackfin/kernel/cplb-mpu/cacheinit.c index c6ff947f9d37..d5a86c3017f7 100644 --- a/arch/blackfin/kernel/cplb-mpu/cacheinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cacheinit.c @@ -55,7 +55,14 @@ void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl) } ctrl = bfin_read_DMEM_CONTROL(); - ctrl |= DMEM_CNTR; + + /* + * Anomaly notes: + * 05000287 - We implement workaround #2 - Change the DMEM_CONTROL + * register, so that the port preferences for DAG0 and DAG1 are set + * to port B + */ + ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0); bfin_write_DMEM_CONTROL(ctrl); SSYNC(); } -- cgit v1.2.3 From a9031028ef70f658daa2151e361aee7b082965ee Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 23 Apr 2009 17:04:10 +0000 Subject: Blackfin: delete unused sys_getpagesize() function Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/sys_bfin.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c index fce49d7cf001..a8f1329c15a4 100644 --- a/arch/blackfin/kernel/sys_bfin.c +++ b/arch/blackfin/kernel/sys_bfin.c @@ -78,11 +78,6 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, return do_mmap2(addr, len, prot, flags, fd, pgoff); } -asmlinkage int sys_getpagesize(void) -{ - return PAGE_SIZE; -} - asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags) { return sram_alloc_with_lsl(size, flags); -- cgit v1.2.3 From d8804adf52f5991388fa9af77428e4cc7768059d Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 29 Apr 2009 06:26:46 +0000 Subject: Blackfin: do not append newlines to panic() messages The panic() function already handles newlines for us. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/setup.c | 8 ++++---- arch/blackfin/kernel/traps.c | 4 ++-- arch/blackfin/mach-bf561/smp.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 0838eafed172..5a4a03670085 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -477,7 +477,7 @@ static __init void memory_setup(void) if (DMA_UNCACHED_REGION > (_ramend - _ramstart)) { console_init(); - panic("DMA region exceeds memory limit: %lu.\n", + panic("DMA region exceeds memory limit: %lu.", _ramend - _ramstart); } memory_end = _ramend - DMA_UNCACHED_REGION; @@ -531,7 +531,7 @@ static __init void memory_setup(void) if (mtd_size == 0) { console_init(); - panic("Don't boot kernel without rootfs attached.\n"); + panic("Don't boot kernel without rootfs attached."); } /* Relocate MTD image to the top of memory after the uncached memory area */ @@ -886,7 +886,7 @@ void __init setup_arch(char **cmdline_p) printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", bfin_compiled_revid(), bfin_revid()); if (bfin_compiled_revid() > bfin_revid()) - panic("Error: you are missing anomaly workarounds for this rev\n"); + panic("Error: you are missing anomaly workarounds for this rev"); } } if (bfin_revid() < CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX) @@ -896,7 +896,7 @@ void __init setup_arch(char **cmdline_p) /* We can't run on BF548-0.1 due to ANOMALY 05000448 */ if (bfin_cpuid() == 0x27de && bfin_revid() == 1) - panic("You can't run on this processor due to 05000448\n"); + panic("You can't run on this processor due to 05000448"); printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index ffe7fb53eccb..fb5774275889 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -222,7 +222,7 @@ asmlinkage void double_fault_c(struct pt_regs *fp) show_regs(fp); } #endif - panic("Double Fault - unrecoverable event\n"); + panic("Double Fault - unrecoverable event"); } @@ -1246,5 +1246,5 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp) dump_bfin_mem(fp); show_regs(fp); dump_stack(); - panic("Unrecoverable event\n"); + panic("Unrecoverable event"); } diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c index 9b27e698c0b2..4ea13d2eb872 100644 --- a/arch/blackfin/mach-bf561/smp.c +++ b/arch/blackfin/mach-bf561/smp.c @@ -135,7 +135,7 @@ void __init platform_request_ipi(irq_handler_t handler) ret = request_irq(IRQ_SUPPLE_0, handler, IRQF_DISABLED, "SMP interrupt", handler); if (ret) - panic("Cannot request supplemental interrupt 0 for IPI service\n"); + panic("Cannot request supplemental interrupt 0 for IPI service"); } void platform_send_ipi(cpumask_t callmap) -- cgit v1.2.3 From 7f3aee3c187641ec7c7e260d9cabb71ac4ac9f7c Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 7 May 2009 10:04:19 +0000 Subject: Blackfin: detect anomaly 05000274 Detect and reject operating conditions for anomaly 05000274 since the problem cannot be worked around in software. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/setup.c | 9 ++------- arch/blackfin/mach-common/cpufreq.c | 3 ++- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 5a4a03670085..dc30e0aa54cd 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -801,10 +801,8 @@ void __init setup_arch(char **cmdline_p) cclk = get_cclk(); sclk = get_sclk(); -#if !defined(CONFIG_BFIN_KERNEL_CLOCK) - if (ANOMALY_05000273 && cclk == sclk) - panic("ANOMALY 05000273, SCLK can not be same as CCLK"); -#endif + if ((ANOMALY_05000273 || ANOMALY_05000274) && (cclk >> 1) < sclk) + panic("ANOMALY 05000273 or 05000274: CCLK must be >= 2*SCLK"); #ifdef BF561_FAMILY if (ANOMALY_05000266) { @@ -903,9 +901,6 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", cclk / 1000000, sclk / 1000000); - if (ANOMALY_05000273 && (cclk >> 1) <= sclk) - printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n"); - setup_bootmem_allocator(); paging_init(); diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c index 72e16605ca09..70e3411f558c 100644 --- a/arch/blackfin/mach-common/cpufreq.c +++ b/arch/blackfin/mach-common/cpufreq.c @@ -140,7 +140,8 @@ static int __init __bfin_cpu_init(struct cpufreq_policy *policy) cclk = get_cclk() / 1000; sclk = get_sclk() / 1000; -#if ANOMALY_05000273 || (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_DCACHE)) +#if ANOMALY_05000273 || ANOMALY_05000274 || \ + (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_DCACHE)) min_cclk = sclk * 2; #else min_cclk = sclk; -- cgit v1.2.3 From 1fa9be72b558c39459f98835eb86dbb4ef4da30b Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Fri, 15 May 2009 11:01:59 +0000 Subject: Blackfin: add support for gptimer0 as a tick source For systems where the core cycles are not a usable tick source (like SMP or cycles gets updated), enable gptimer0 as an alternative. Signed-off-by: Graf Yang Signed-off-by: Mike Frysinger --- arch/blackfin/Kconfig | 32 +++-- arch/blackfin/include/asm/time.h | 1 + arch/blackfin/kernel/time-ts.c | 222 ++++++++++++++++++++++++------ arch/blackfin/kernel/time.c | 10 +- arch/blackfin/mach-bf518/Kconfig | 1 + arch/blackfin/mach-bf527/Kconfig | 1 + arch/blackfin/mach-bf533/Kconfig | 1 + arch/blackfin/mach-bf537/Kconfig | 1 + arch/blackfin/mach-bf538/Kconfig | 1 + arch/blackfin/mach-bf548/Kconfig | 1 + arch/blackfin/mach-bf561/Kconfig | 1 + arch/blackfin/mach-bf561/smp.c | 2 +- arch/blackfin/mach-common/ints-priority.c | 23 +--- arch/blackfin/mach-common/smp.c | 5 +- 14 files changed, 228 insertions(+), 74 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index cea2bfd64a56..c04e7a4836f2 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -241,12 +241,6 @@ config IRQ_PER_CPU depends on SMP default y -config TICK_SOURCE_SYSTMR0 - bool - select BFIN_GPTIMERS - depends on SMP - default y - config BF_REV_MIN int default 0 if (BF51x || BF52x || (BF54x && !BF54xM)) @@ -607,7 +601,6 @@ source kernel/Kconfig.hz config GENERIC_TIME bool "Generic time" - depends on !SMP default y config GENERIC_CLOCKEVENTS @@ -615,12 +608,26 @@ config GENERIC_CLOCKEVENTS depends on GENERIC_TIME default y +choice + prompt "Kernel Tick Source" + depends on GENERIC_CLOCKEVENTS + default TICKSOURCE_CORETMR + +config TICKSOURCE_GPTMR0 + bool "Gptimer0 (SCLK domain)" + select BFIN_GPTIMERS + depends on !IPIPE + +config TICKSOURCE_CORETMR + bool "Core timer (CCLK domain)" + +endchoice + config CYCLES_CLOCKSOURCE - bool "Use 'CYCLES' as a clocksource (EXPERIMENTAL)" - depends on EXPERIMENTAL + bool "Use 'CYCLES' as a clocksource" depends on GENERIC_CLOCKEVENTS depends on !BFIN_SCRATCH_REG_CYCLES - default n + depends on !SMP help If you say Y here, you will enable support for using the 'cycles' registers as a clock source. Doing so means you will be unable to @@ -628,6 +635,11 @@ config CYCLES_CLOCKSOURCE still be able to read it (such as for performance monitoring), but writing the registers will most likely crash the kernel. +config GPTMR0_CLOCKSOURCE + bool "Use GPTimer0 as a clocksource (higher rating)" + depends on GENERIC_CLOCKEVENTS + depends on !TICKSOURCE_GPTMR0 + source kernel/time/Kconfig comment "Misc" diff --git a/arch/blackfin/include/asm/time.h b/arch/blackfin/include/asm/time.h index ddc43ce38533..589e937ed1eb 100644 --- a/arch/blackfin/include/asm/time.h +++ b/arch/blackfin/include/asm/time.h @@ -37,4 +37,5 @@ extern unsigned long long __bfin_cycles_off; extern unsigned int __bfin_cycles_mod; #endif +extern void __init setup_core_timer(void); #endif diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c index 27646121280a..0791eba40d9f 100644 --- a/arch/blackfin/kernel/time-ts.c +++ b/arch/blackfin/kernel/time-ts.c @@ -20,8 +20,9 @@ #include #include +#include -#ifdef CONFIG_CYCLES_CLOCKSOURCE +#if defined(CONFIG_CYCLES_CLOCKSOURCE) /* Accelerators for sched_clock() * convert from cycles(64bits) => nanoseconds (64bits) @@ -58,15 +59,15 @@ static inline unsigned long long cycles_2_ns(cycle_t cyc) return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; } -static cycle_t read_cycles(struct clocksource *cs) +static cycle_t bfin_read_cycles(struct clocksource *cs) { return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod); } -static struct clocksource clocksource_bfin = { - .name = "bfin_cycles", +static struct clocksource bfin_cs_cycles = { + .name = "bfin_cs_cycles", .rating = 350, - .read = read_cycles, + .read = bfin_read_cycles, .mask = CLOCKSOURCE_MASK(64), .shift = 22, .flags = CLOCK_SOURCE_IS_CONTINUOUS, @@ -74,53 +75,198 @@ static struct clocksource clocksource_bfin = { unsigned long long sched_clock(void) { - return cycles_2_ns(read_cycles(&clocksource_bfin)); + return cycles_2_ns(bfin_read_cycles(&bfin_cs_cycles)); } -static int __init bfin_clocksource_init(void) +static int __init bfin_cs_cycles_init(void) { set_cyc2ns_scale(get_cclk() / 1000); - clocksource_bfin.mult = clocksource_hz2mult(get_cclk(), clocksource_bfin.shift); + bfin_cs_cycles.mult = \ + clocksource_hz2mult(get_cclk(), bfin_cs_cycles.shift); - if (clocksource_register(&clocksource_bfin)) + if (clocksource_register(&bfin_cs_cycles)) panic("failed to register clocksource"); return 0; } +#else +# define bfin_cs_cycles_init() +#endif + +#ifdef CONFIG_GPTMR0_CLOCKSOURCE + +void __init setup_gptimer0(void) +{ + disable_gptimers(TIMER0bit); + + set_gptimer_config(TIMER0_id, \ + TIMER_OUT_DIS | TIMER_PERIOD_CNT | TIMER_MODE_PWM); + set_gptimer_period(TIMER0_id, -1); + set_gptimer_pwidth(TIMER0_id, -2); + SSYNC(); + enable_gptimers(TIMER0bit); +} + +static cycle_t bfin_read_gptimer0(void) +{ + return bfin_read_TIMER0_COUNTER(); +} + +static struct clocksource bfin_cs_gptimer0 = { + .name = "bfin_cs_gptimer0", + .rating = 400, + .read = bfin_read_gptimer0, + .mask = CLOCKSOURCE_MASK(32), + .shift = 22, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int __init bfin_cs_gptimer0_init(void) +{ + setup_gptimer0(); + bfin_cs_gptimer0.mult = \ + clocksource_hz2mult(get_sclk(), bfin_cs_gptimer0.shift); + + if (clocksource_register(&bfin_cs_gptimer0)) + panic("failed to register clocksource"); + + return 0; +} #else -# define bfin_clocksource_init() +# define bfin_cs_gptimer0_init() #endif +#ifdef CONFIG_CORE_TIMER_IRQ_L1 +__attribute__((l1_text)) +#endif +irqreturn_t timer_interrupt(int irq, void *dev_id); + +static int bfin_timer_set_next_event(unsigned long, \ + struct clock_event_device *); + +static void bfin_timer_set_mode(enum clock_event_mode, \ + struct clock_event_device *); + +static struct clock_event_device clockevent_bfin = { +#if defined(CONFIG_TICKSOURCE_GPTMR0) + .name = "bfin_gptimer0", + .rating = 300, + .irq = IRQ_TIMER0, +#else + .name = "bfin_core_timer", + .rating = 350, + .irq = IRQ_CORETMR, +#endif + .shift = 32, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = bfin_timer_set_next_event, + .set_mode = bfin_timer_set_mode, +}; + +static struct irqaction bfin_timer_irq = { +#if defined(CONFIG_TICKSOURCE_GPTMR0) + .name = "Blackfin GPTimer0", +#else + .name = "Blackfin CoreTimer", +#endif + .flags = IRQF_DISABLED | IRQF_TIMER | \ + IRQF_IRQPOLL | IRQF_PERCPU, + .handler = timer_interrupt, + .dev_id = &clockevent_bfin, +}; + +#if defined(CONFIG_TICKSOURCE_GPTMR0) static int bfin_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { + disable_gptimers(TIMER0bit); + + /* it starts counting three SCLK cycles after the TIMENx bit is set */ + set_gptimer_pwidth(TIMER0_id, cycles - 3); + enable_gptimers(TIMER0bit); + return 0; +} + +static void bfin_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: { + set_gptimer_config(TIMER0_id, \ + TIMER_OUT_DIS | TIMER_IRQ_ENA | \ + TIMER_PERIOD_CNT | TIMER_MODE_PWM); + set_gptimer_period(TIMER0_id, get_sclk() / HZ); + set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1); + enable_gptimers(TIMER0bit); + break; + } + case CLOCK_EVT_MODE_ONESHOT: + disable_gptimers(TIMER0bit); + set_gptimer_config(TIMER0_id, \ + TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM); + set_gptimer_period(TIMER0_id, 0); + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + disable_gptimers(TIMER0bit); + break; + case CLOCK_EVT_MODE_RESUME: + break; + } +} + +static void bfin_timer_ack(void) +{ + set_gptimer_status(TIMER_GROUP1, TIMER_STATUS_TIMIL0); +} + +static void __init bfin_timer_init(void) +{ + disable_gptimers(TIMER0bit); +} + +static unsigned long __init bfin_clockevent_check(void) +{ + setup_irq(IRQ_TIMER0, &bfin_timer_irq); + return get_sclk(); +} + +#else /* CONFIG_TICKSOURCE_CORETMR */ + +static int bfin_timer_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + bfin_write_TCNTL(TMPWR); + CSYNC(); bfin_write_TCOUNT(cycles); CSYNC(); + bfin_write_TCNTL(TMPWR | TMREN); return 0; } static void bfin_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) + struct clock_event_device *evt) { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: { unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); bfin_write_TCNTL(TMPWR); - bfin_write_TSCALE(TIME_SCALE - 1); CSYNC(); + bfin_write_TSCALE(TIME_SCALE - 1); bfin_write_TPERIOD(tcount); bfin_write_TCOUNT(tcount); - bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD); CSYNC(); + bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD); break; } case CLOCK_EVT_MODE_ONESHOT: + bfin_write_TCNTL(TMPWR); + CSYNC(); bfin_write_TSCALE(TIME_SCALE - 1); + bfin_write_TPERIOD(0); bfin_write_TCOUNT(0); - bfin_write_TCNTL(TMPWR | TMREN); - CSYNC(); break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: @@ -132,6 +278,10 @@ static void bfin_timer_set_mode(enum clock_event_mode mode, } } +static void bfin_timer_ack(void) +{ +} + static void __init bfin_timer_init(void) { /* power up the timer, but don't enable it just yet */ @@ -145,38 +295,32 @@ static void __init bfin_timer_init(void) bfin_write_TPERIOD(0); bfin_write_TCOUNT(0); - /* now enable the timer */ CSYNC(); } +static unsigned long __init bfin_clockevent_check(void) +{ + setup_irq(IRQ_CORETMR, &bfin_timer_irq); + return get_cclk() / TIME_SCALE; +} + +void __init setup_core_timer(void) +{ + bfin_timer_init(); + bfin_timer_set_mode(CLOCK_EVT_MODE_PERIODIC, NULL); +} +#endif /* CONFIG_TICKSOURCE_GPTMR0 */ + /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -#ifdef CONFIG_CORE_TIMER_IRQ_L1 -__attribute__((l1_text)) -#endif -irqreturn_t timer_interrupt(int irq, void *dev_id); - -static struct clock_event_device clockevent_bfin = { - .name = "bfin_core_timer", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, - .set_next_event = bfin_timer_set_next_event, - .set_mode = bfin_timer_set_mode, -}; - -static struct irqaction bfin_timer_irq = { - .name = "Blackfin Core Timer", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = timer_interrupt, - .dev_id = &clockevent_bfin, -}; - irqreturn_t timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; + smp_mb(); evt->event_handler(evt); + bfin_timer_ack(); return IRQ_HANDLED; } @@ -184,9 +328,8 @@ static int __init bfin_clockevent_init(void) { unsigned long timer_clk; - timer_clk = get_cclk() / TIME_SCALE; + timer_clk = bfin_clockevent_check(); - setup_irq(IRQ_CORETMR, &bfin_timer_irq); bfin_timer_init(); clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift); @@ -218,6 +361,7 @@ void __init time_init(void) xtime.tv_nsec = 0; set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - bfin_clocksource_init(); + bfin_cs_cycles_init(); + bfin_cs_gptimer0_init(); bfin_clockevent_init(); } diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index 1bbacfbd4c5d..daa02d45f03d 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c @@ -31,7 +31,7 @@ static struct irqaction bfin_timer_irq = { #endif }; -#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) +#if defined(CONFIG_TICKSOURCE_GPTMR0) || defined(CONFIG_IPIPE) void __init setup_system_timer0(void) { /* Power down the core timer, just to play safe. */ @@ -74,7 +74,7 @@ void __init setup_core_timer(void) static void __init time_sched_init(irqreturn_t(*timer_routine) (int, void *)) { -#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) +#if defined(CONFIG_TICKSOURCE_GPTMR0) || defined(CONFIG_IPIPE) setup_system_timer0(); bfin_timer_irq.handler = timer_routine; setup_irq(IRQ_TIMER0, &bfin_timer_irq); @@ -94,7 +94,7 @@ static unsigned long gettimeoffset(void) unsigned long offset; unsigned long clocks_per_jiffy; -#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) +#if defined(CONFIG_TICKSOURCE_GPTMR0) || defined(CONFIG_IPIPE) clocks_per_jiffy = bfin_read_TIMER0_PERIOD(); offset = bfin_read_TIMER0_COUNTER() / \ (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); @@ -133,7 +133,7 @@ irqreturn_t timer_interrupt(int irq, void *dummy) static long last_rtc_update; write_seqlock(&xtime_lock); -#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE) +#if defined(CONFIG_TICKSOURCE_GPTMR0) && !defined(CONFIG_IPIPE) /* * TIMIL0 is latched in __ipipe_grab_irq() when the I-Pipe is * enabled. @@ -159,7 +159,7 @@ irqreturn_t timer_interrupt(int irq, void *dummy) /* Do it again in 60s. */ last_rtc_update = xtime.tv_sec - 600; } -#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE) +#if defined(CONFIG_TICKSOURCE_GPTMR0) && !defined(CONFIG_IPIPE) set_gptimer_status(0, TIMER_STATUS_TIMIL0); } #endif diff --git a/arch/blackfin/mach-bf518/Kconfig b/arch/blackfin/mach-bf518/Kconfig index f397ede006bf..4c76fefb7a3b 100644 --- a/arch/blackfin/mach-bf518/Kconfig +++ b/arch/blackfin/mach-bf518/Kconfig @@ -156,6 +156,7 @@ config IRQ_PORTH_INTB default 11 config IRQ_TIMER0 int "IRQ_TIMER0" + default 7 if TICKSOURCE_GPTMR0 default 8 config IRQ_TIMER1 int "IRQ_TIMER1" diff --git a/arch/blackfin/mach-bf527/Kconfig b/arch/blackfin/mach-bf527/Kconfig index 8438ec6d6679..848ac6f86823 100644 --- a/arch/blackfin/mach-bf527/Kconfig +++ b/arch/blackfin/mach-bf527/Kconfig @@ -170,6 +170,7 @@ config IRQ_PORTH_INTB default 11 config IRQ_TIMER0 int "IRQ_TIMER0" + default 7 if TICKSOURCE_GPTMR0 default 8 config IRQ_TIMER1 int "IRQ_TIMER1" diff --git a/arch/blackfin/mach-bf533/Kconfig b/arch/blackfin/mach-bf533/Kconfig index 14427de7d77f..4c572443147e 100644 --- a/arch/blackfin/mach-bf533/Kconfig +++ b/arch/blackfin/mach-bf533/Kconfig @@ -59,6 +59,7 @@ config DMA7_UARTTX default 10 config TIMER0 int "TIMER0" + default 7 if TICKSOURCE_GPTMR0 default 8 config TIMER1 int "TIMER1" diff --git a/arch/blackfin/mach-bf537/Kconfig b/arch/blackfin/mach-bf537/Kconfig index bbc08fd4f122..d81224f9d723 100644 --- a/arch/blackfin/mach-bf537/Kconfig +++ b/arch/blackfin/mach-bf537/Kconfig @@ -66,6 +66,7 @@ config IRQ_MAC_TX default 11 config IRQ_TIMER0 int "IRQ_TIMER0" + default 7 if TICKSOURCE_GPTMR0 default 8 config IRQ_TIMER1 int "IRQ_TIMER1" diff --git a/arch/blackfin/mach-bf538/Kconfig b/arch/blackfin/mach-bf538/Kconfig index f068c3523cdc..2d280f504ab0 100644 --- a/arch/blackfin/mach-bf538/Kconfig +++ b/arch/blackfin/mach-bf538/Kconfig @@ -57,6 +57,7 @@ config IRQ_UART0_TX default 10 config IRQ_TIMER0 int "IRQ_TIMER0" + default 7 if TICKSOURCE_GPTMR0 default 8 config IRQ_TIMER1 int "IRQ_TIMER1" diff --git a/arch/blackfin/mach-bf548/Kconfig b/arch/blackfin/mach-bf548/Kconfig index 8d24eaabe589..a09623dfd550 100644 --- a/arch/blackfin/mach-bf548/Kconfig +++ b/arch/blackfin/mach-bf548/Kconfig @@ -257,6 +257,7 @@ config IRQ_OTPSEC default 11 config IRQ_TIMER0 int "IRQ_TIMER0" + default 7 if TICKSOURCE_GPTMR0 default 8 config IRQ_TIMER1 int "IRQ_TIMER1" diff --git a/arch/blackfin/mach-bf561/Kconfig b/arch/blackfin/mach-bf561/Kconfig index 6965dd59af4c..cb9743641511 100644 --- a/arch/blackfin/mach-bf561/Kconfig +++ b/arch/blackfin/mach-bf561/Kconfig @@ -125,6 +125,7 @@ config IRQ_DMA2_11 default 9 config IRQ_TIMER0 int "TIMER 0 Interrupt" + default 7 if TICKSOURCE_GPTMR0 default 8 config IRQ_TIMER1 int "TIMER 1 Interrupt" diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c index 4ea13d2eb872..8c10701c251f 100644 --- a/arch/blackfin/mach-bf561/smp.c +++ b/arch/blackfin/mach-bf561/smp.c @@ -133,7 +133,7 @@ void __init platform_request_ipi(irq_handler_t handler) int ret; ret = request_irq(IRQ_SUPPLE_0, handler, IRQF_DISABLED, - "SMP interrupt", handler); + "Supplemental Interrupt0", handler); if (ret) panic("Cannot request supplemental interrupt 0 for IPI service"); } diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 389c5e8aa456..6e808612d170 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -1052,7 +1052,7 @@ int __init init_arch_irq(void) set_irq_chained_handler(irq, bfin_demux_error_irq); break; #endif -#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) +#if defined(CONFIG_TICKSOURCE_GPTMR0) case IRQ_TIMER0: set_irq_handler(irq, handle_percpu_irq); break; @@ -1232,13 +1232,9 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) if (likely(vec == EVT_IVTMR_P)) { irq = IRQ_CORETMR; - goto core_tick; - } - - SSYNC(); + } else { #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) - { unsigned long sic_status[3]; sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); @@ -1254,9 +1250,7 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag) break; } - } #else - { unsigned long sic_status; sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR(); @@ -1268,15 +1262,13 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) } else if (sic_status & ivg->isrflag) break; } - } #endif - irq = ivg->irqno; + irq = ivg->irqno; + } if (irq == IRQ_SYSTMR) { -#ifdef CONFIG_GENERIC_CLOCKEVENTS -core_tick: -#else +#ifndef CONFIG_GENERIC_CLOCKEVENTS bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */ #endif /* This is basically what we need from the register frame. */ @@ -1288,9 +1280,6 @@ core_tick: __raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10; } -#ifndef CONFIG_GENERIC_CLOCKEVENTS -core_tick: -#endif if (this_domain == ipipe_root_domain) { s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status); barrier(); @@ -1308,7 +1297,7 @@ core_tick: } } - return 0; + return 0; } #endif /* CONFIG_IPIPE */ diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 187c79e585a1..b6695957b065 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -43,6 +43,7 @@ #include #include #include +#include #include /* @@ -356,7 +357,7 @@ int __cpuinit __cpu_up(unsigned int cpu) static void __cpuinit setup_secondary(unsigned int cpu) { -#if !(defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)) +#if !defined(CONFIG_TICKSOURCE_GPTMR0) struct irq_desc *timer_desc; #endif unsigned long ilat; @@ -377,7 +378,7 @@ static void __cpuinit setup_secondary(unsigned int cpu) IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; -#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) +#if defined(CONFIG_TICKSOURCE_GPTMR0) /* Power down the core timer, just to play safe. */ bfin_write_TCNTL(0); -- cgit v1.2.3 From 8af7ffa0d5460586e0f06b2f045a6a2631224b61 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Fri, 8 May 2009 07:42:12 +0000 Subject: Blackfin: add workaround for anomaly 05000287 Signed-off-by: Graf Yang Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/cplb-nompu/cacheinit.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/cplb-nompu/cacheinit.c b/arch/blackfin/kernel/cplb-nompu/cacheinit.c index c6ff947f9d37..d5a86c3017f7 100644 --- a/arch/blackfin/kernel/cplb-nompu/cacheinit.c +++ b/arch/blackfin/kernel/cplb-nompu/cacheinit.c @@ -55,7 +55,14 @@ void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl) } ctrl = bfin_read_DMEM_CONTROL(); - ctrl |= DMEM_CNTR; + + /* + * Anomaly notes: + * 05000287 - We implement workaround #2 - Change the DMEM_CONTROL + * register, so that the port preferences for DAG0 and DAG1 are set + * to port B + */ + ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0); bfin_write_DMEM_CONTROL(ctrl); SSYNC(); } -- cgit v1.2.3 From a17c7f6f5b3b3f91ff7121c33bea8748c415ab15 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Tue, 5 May 2009 17:14:39 +0000 Subject: Blackfin: make sure MPU CPLB for first 1k is marked as valid This way we properly catch and kill applications that jump to a NULL ptr. Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/cplb-mpu/cplbinit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c index 3e329a6ce041..c006a44527bf 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c @@ -64,7 +64,7 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB; icplb_tbl[cpu][i_i].addr = 0; - icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_1KB; + icplb_tbl[cpu][i_i++].data = CPLB_VALID | i_cache | CPLB_USER_RD | PAGE_SIZE_1KB; /* Cover kernel memory with 4M pages. */ addr = 0; -- cgit v1.2.3 From a0cab65642813b7990e1b4b2ab6ad92e171571f4 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Mon, 11 May 2009 18:34:41 +0000 Subject: Blackfin: make sure stack is accessible before dumping it When displaying a crash dump, make sure accessing the stack is safe so we don't crash at the same time. Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/traps.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index fb5774275889..0d04a4732b1f 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -196,6 +196,11 @@ done: asmlinkage void double_fault_c(struct pt_regs *fp) { +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON + int j; + trace_buffer_save(j); +#endif + console_verbose(); oops_in_progress = 1; #ifdef CONFIG_DEBUG_VERBOSE @@ -220,6 +225,7 @@ asmlinkage void double_fault_c(struct pt_regs *fp) dump_bfin_process(fp); dump_bfin_mem(fp); show_regs(fp); + dump_bfin_trace_buffer(); } #endif panic("Double Fault - unrecoverable event"); @@ -832,6 +838,11 @@ void show_stack(struct task_struct *task, unsigned long *stack) decode_address(buf, (unsigned int)stack); printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); + if (!access_ok(VERIFY_READ, stack, (unsigned int)endstack - (unsigned int)stack)) { + printk(KERN_NOTICE "Invalid stack pointer\n"); + return; + } + /* First thing is to look for a frame pointer */ for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) { if (*addr & 0x1) -- cgit v1.2.3 From 0acad8dfee6bde7e246a95a52f864a8eee777ed8 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Mon, 11 May 2009 18:55:16 +0000 Subject: Blackfin: add workaround for anomaly 05000461 Returning too fast with a bad RETI can trigger false errors. Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/traps.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 0d04a4732b1f..778a75655a0c 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -594,6 +594,9 @@ asmlinkage void trap_c(struct pt_regs *fp) force_sig_info(sig, &info, current); } + if (ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) + fp->pc = SAFE_USER_INSTRUCTION; + trace_buffer_restore(j); return; } -- cgit v1.2.3 From 9ba3c24f10c948dadac2ca91ed714dfbcedd61ca Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 20 May 2009 21:19:21 +0000 Subject: Blackfin: include system/processor info in dump messages People often copy & paste crash messages without surrounding context, so include common useful information like system/processor stats in the crash summary. This should smooth over the report/test cycle a bit more. Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/traps.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 778a75655a0c..35f675f5ca16 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -1080,6 +1080,29 @@ void show_regs(struct pt_regs *fp) unsigned int cpu = smp_processor_id(); unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic(); + verbose_printk(KERN_NOTICE "\n"); + if (CPUID != bfin_cpuid()) + verbose_printk(KERN_NOTICE "Compiled for cpu family 0x%04x (Rev %d), " + "but running on:0x%04x (Rev %d)\n", + CPUID, bfin_compiled_revid(), bfin_cpuid(), bfin_revid()); + + verbose_printk(KERN_NOTICE "ADSP-%s-0.%d", + CPU, bfin_compiled_revid()); + + if (bfin_compiled_revid() != bfin_revid()) + verbose_printk("(Detected 0.%d)", bfin_revid()); + + verbose_printk(" %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n", + get_cclk()/1000000, get_sclk()/1000000, +#ifdef CONFIG_MPU + "mpu on" +#else + "mpu off" +#endif + ); + + verbose_printk(KERN_NOTICE "%s", linux_banner); + verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", (long)fp->seqstat, fp->ipend, fp->syscfg); -- cgit v1.2.3 From c8d5ea8ccb1ce586131c6c549899cb5073222da0 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 4 May 2009 09:11:37 +0000 Subject: Blackfin: update gptimers API First we fix the prototypes for functions that return boolean values by using "int" rather than "uint16_t". Then we introduce a get_gptimer_run() function for checking the current run status of a timer, and then we add a disable_gptimers_sync() function which parallels disable_gptimers() with corresponding normal "_sync" behavior. Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/gptimers.h | 43 ++++++++++++++++++++---------------- arch/blackfin/kernel/gptimers.c | 30 ++++++++++++++++++++----- 2 files changed, 49 insertions(+), 24 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/include/asm/gptimers.h b/arch/blackfin/include/asm/gptimers.h index b0f847ae4bf4..89f08decb8e0 100644 --- a/arch/blackfin/include/asm/gptimers.h +++ b/arch/blackfin/include/asm/gptimers.h @@ -30,6 +30,7 @@ # else # define MAX_BLACKFIN_GPTIMERS 11 # define TIMER8_GROUP_REG TIMER_ENABLE1 +# define TIMER_GROUP2 1 # endif # define TIMER0_GROUP_REG TIMER_ENABLE0 #endif @@ -40,10 +41,12 @@ # define MAX_BLACKFIN_GPTIMERS 12 # define TIMER0_GROUP_REG TMRS8_ENABLE # define TIMER8_GROUP_REG TMRS4_ENABLE +# define TIMER_GROUP2 1 #endif /* * All others: 3 timers: */ +#define TIMER_GROUP1 0 #if !defined(MAX_BLACKFIN_GPTIMERS) # define MAX_BLACKFIN_GPTIMERS 3 # define TIMER0_GROUP_REG TIMER_ENABLE @@ -109,8 +112,8 @@ #define TIMER_ERR_PROG_PER 0x8000 #define TIMER_ERR_PROG_PW 0xC000 #define TIMER_EMU_RUN 0x0200 -#define TIMER_TOGGLE_HI 0x0100 -#define TIMER_CLK_SEL 0x0080 +#define TIMER_TOGGLE_HI 0x0100 +#define TIMER_CLK_SEL 0x0080 #define TIMER_OUT_DIS 0x0040 #define TIMER_TIN_SEL 0x0020 #define TIMER_IRQ_ENA 0x0010 @@ -169,23 +172,25 @@ /* The actual gptimer API */ -void set_gptimer_pwidth (int timer_id, uint32_t width); -uint32_t get_gptimer_pwidth (int timer_id); -void set_gptimer_period (int timer_id, uint32_t period); -uint32_t get_gptimer_period (int timer_id); -uint32_t get_gptimer_count (int timer_id); -uint16_t get_gptimer_intr (int timer_id); -void clear_gptimer_intr (int timer_id); -uint16_t get_gptimer_over (int timer_id); -void clear_gptimer_over (int timer_id); -void set_gptimer_config (int timer_id, uint16_t config); -uint16_t get_gptimer_config (int timer_id); -void set_gptimer_pulse_hi (int timer_id); +void set_gptimer_pwidth(int timer_id, uint32_t width); +uint32_t get_gptimer_pwidth(int timer_id); +void set_gptimer_period(int timer_id, uint32_t period); +uint32_t get_gptimer_period(int timer_id); +uint32_t get_gptimer_count(int timer_id); +int get_gptimer_intr(int timer_id); +void clear_gptimer_intr(int timer_id); +int get_gptimer_over(int timer_id); +void clear_gptimer_over(int timer_id); +void set_gptimer_config(int timer_id, uint16_t config); +uint16_t get_gptimer_config(int timer_id); +int get_gptimer_run(int timer_id); +void set_gptimer_pulse_hi(int timer_id); void clear_gptimer_pulse_hi(int timer_id); -void enable_gptimers (uint16_t mask); -void disable_gptimers (uint16_t mask); -uint16_t get_enabled_gptimers (void); -uint32_t get_gptimer_status (int group); -void set_gptimer_status (int group, uint32_t value); +void enable_gptimers(uint16_t mask); +void disable_gptimers(uint16_t mask); +void disable_gptimers_sync(uint16_t mask); +uint16_t get_enabled_gptimers(void); +uint32_t get_gptimer_status(int group); +void set_gptimer_status(int group, uint32_t value); #endif diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c index 3a3e9615b002..7281a91d26b5 100644 --- a/arch/blackfin/kernel/gptimers.c +++ b/arch/blackfin/kernel/gptimers.c @@ -189,10 +189,10 @@ void set_gptimer_status(int group, uint32_t value) } EXPORT_SYMBOL(set_gptimer_status); -uint16_t get_gptimer_intr(int timer_id) +int get_gptimer_intr(int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]) ? 1 : 0; + return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]); } EXPORT_SYMBOL(get_gptimer_intr); @@ -203,10 +203,10 @@ void clear_gptimer_intr(int timer_id) } EXPORT_SYMBOL(clear_gptimer_intr); -uint16_t get_gptimer_over(int timer_id) +int get_gptimer_over(int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); - return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]) ? 1 : 0; + return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]); } EXPORT_SYMBOL(get_gptimer_over); @@ -217,6 +217,13 @@ void clear_gptimer_over(int timer_id) } EXPORT_SYMBOL(clear_gptimer_over); +int get_gptimer_run(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & trun_mask[timer_id]); +} +EXPORT_SYMBOL(get_gptimer_run); + void set_gptimer_config(int timer_id, uint16_t config) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); @@ -244,7 +251,7 @@ void enable_gptimers(uint16_t mask) } EXPORT_SYMBOL(enable_gptimers); -void disable_gptimers(uint16_t mask) +static void _disable_gptimers(uint16_t mask) { int i; uint16_t m = mask; @@ -253,6 +260,12 @@ void disable_gptimers(uint16_t mask) group_regs[i]->disable = m & 0xFF; m >>= 8; } +} + +void disable_gptimers(uint16_t mask) +{ + int i; + _disable_gptimers(mask); for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i) if (mask & (1 << i)) group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i]; @@ -260,6 +273,13 @@ void disable_gptimers(uint16_t mask) } EXPORT_SYMBOL(disable_gptimers); +void disable_gptimers_sync(uint16_t mask) +{ + _disable_gptimers(mask); + SSYNC(); +} +EXPORT_SYMBOL(disable_gptimers_sync); + void set_gptimer_pulse_hi(int timer_id) { tassert(timer_id < MAX_BLACKFIN_GPTIMERS); -- cgit v1.2.3 From 79df1b69471b5ea4be8285c9dc6ab05cdf5a85d7 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 26 May 2009 23:34:51 +0000 Subject: Blackfin: override default uClinux MTD addr/size Due to a processor anomaly (05000263 to be exact), most Blackfin parts cannot keep the embedded filesystem image directly after the kernel in RAM. Instead, the filesystem needs to be relocated to the end of memory. As such, we need to tweak the map addr/size during boot for Blackfin systems. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/setup.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index dc30e0aa54cd..80447f99c2b5 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -18,9 +18,12 @@ #include #include +#ifdef CONFIG_MTD_UCLINUX +#include #include #include #include +#endif #include #include @@ -45,6 +48,7 @@ EXPORT_SYMBOL(_ramend); EXPORT_SYMBOL(reserved_mem_dcache_on); #ifdef CONFIG_MTD_UCLINUX +extern struct map_info uclinux_ram_map; unsigned long memory_mtd_end, memory_mtd_start, mtd_size; unsigned long _ebss; EXPORT_SYMBOL(memory_mtd_end); @@ -535,10 +539,9 @@ static __init void memory_setup(void) } /* Relocate MTD image to the top of memory after the uncached memory area */ - dma_memcpy((char *)memory_end, _end, mtd_size); - - memory_mtd_start = memory_end; - _ebss = memory_mtd_start; /* define _ebss for compatible */ + uclinux_ram_map.phys = memory_mtd_start = memory_end; + uclinux_ram_map.size = mtd_size; + dma_memcpy((void *)uclinux_ram_map.phys, _end, uclinux_ram_map.size); #endif /* CONFIG_MTD_UCLINUX */ #if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263) -- cgit v1.2.3 From 9b9bfded623cffb4259b95e5419404015dba361f Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 27 May 2009 09:58:35 +0000 Subject: Blackfin: convert SMP to only use generic time framework Signed-off-by: Graf Yang Signed-off-by: Mike Frysinger --- arch/blackfin/Kconfig | 1 + arch/blackfin/kernel/time.c | 53 ++++++++++++++++----------------------------- 2 files changed, 20 insertions(+), 34 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index f1a7969b46ca..c56fd3eb7c10 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -223,6 +223,7 @@ endchoice config SMP depends on BF561 + select GENERIC_TIME bool "Symmetric multi-processing support" ---help--- This enables support for systems with more than one CPU, diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index daa02d45f03d..adb54aa7d7c8 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c @@ -24,14 +24,10 @@ static struct irqaction bfin_timer_irq = { .name = "Blackfin Timer Tick", -#ifdef CONFIG_IRQ_PER_CPU - .flags = IRQF_DISABLED | IRQF_PERCPU, -#else .flags = IRQF_DISABLED -#endif }; -#if defined(CONFIG_TICKSOURCE_GPTMR0) || defined(CONFIG_IPIPE) +#if defined(CONFIG_IPIPE) void __init setup_system_timer0(void) { /* Power down the core timer, just to play safe. */ @@ -74,7 +70,7 @@ void __init setup_core_timer(void) static void __init time_sched_init(irqreturn_t(*timer_routine) (int, void *)) { -#if defined(CONFIG_TICKSOURCE_GPTMR0) || defined(CONFIG_IPIPE) +#if defined(CONFIG_IPIPE) setup_system_timer0(); bfin_timer_irq.handler = timer_routine; setup_irq(IRQ_TIMER0, &bfin_timer_irq); @@ -94,7 +90,7 @@ static unsigned long gettimeoffset(void) unsigned long offset; unsigned long clocks_per_jiffy; -#if defined(CONFIG_TICKSOURCE_GPTMR0) || defined(CONFIG_IPIPE) +#if defined(CONFIG_IPIPE) clocks_per_jiffy = bfin_read_TIMER0_PERIOD(); offset = bfin_read_TIMER0_COUNTER() / \ (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); @@ -133,36 +129,25 @@ irqreturn_t timer_interrupt(int irq, void *dummy) static long last_rtc_update; write_seqlock(&xtime_lock); -#if defined(CONFIG_TICKSOURCE_GPTMR0) && !defined(CONFIG_IPIPE) + do_timer(1); + /* - * TIMIL0 is latched in __ipipe_grab_irq() when the I-Pipe is - * enabled. + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. */ - if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) { -#endif - do_timer(1); - - /* - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - if (ntp_synced() && - xtime.tv_sec > last_rtc_update + 660 && - (xtime.tv_nsec / NSEC_PER_USEC) >= - 500000 - ((unsigned)TICK_SIZE) / 2 - && (xtime.tv_nsec / NSEC_PER_USEC) <= - 500000 + ((unsigned)TICK_SIZE) / 2) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - /* Do it again in 60s. */ - last_rtc_update = xtime.tv_sec - 600; - } -#if defined(CONFIG_TICKSOURCE_GPTMR0) && !defined(CONFIG_IPIPE) - set_gptimer_status(0, TIMER_STATUS_TIMIL0); + if (ntp_synced() && + xtime.tv_sec > last_rtc_update + 660 && + (xtime.tv_nsec / NSEC_PER_USEC) >= + 500000 - ((unsigned)TICK_SIZE) / 2 + && (xtime.tv_nsec / NSEC_PER_USEC) <= + 500000 + ((unsigned)TICK_SIZE) / 2) { + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + /* Do it again in 60s. */ + last_rtc_update = xtime.tv_sec - 600; } -#endif write_sequnlock(&xtime_lock); #ifdef CONFIG_IPIPE -- cgit v1.2.3 From 595d681f2c0610223bbe79189b0896f1b8c24f8a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 2 Jun 2009 00:35:33 +0000 Subject: Blackfin: rename Blackfin relocs according to the toolchain The latest Blackfin toolchain has fixed its relocation scheme to match other ports: always use R_BFIN_ prefix and capitalize everything. This brings the kernel in line with those fixes. Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/elf.h | 84 ++++++++++++++++++++--------------------- arch/blackfin/kernel/module.c | 22 +++++------ 2 files changed, 53 insertions(+), 53 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/include/asm/elf.h b/arch/blackfin/include/asm/elf.h index cdbfcfc30f6a..230e1605d3fb 100644 --- a/arch/blackfin/include/asm/elf.h +++ b/arch/blackfin/include/asm/elf.h @@ -55,50 +55,50 @@ do { \ #define ELF_FDPIC_CORE_EFLAGS EF_BFIN_FDPIC #define ELF_EXEC_PAGESIZE 4096 -#define R_unused0 0 /* relocation type 0 is not defined */ -#define R_pcrel5m2 1 /*LSETUP part a */ -#define R_unused1 2 /* relocation type 2 is not defined */ -#define R_pcrel10 3 /* type 3, if cc jump */ -#define R_pcrel12_jump 4 /* type 4, jump */ -#define R_rimm16 5 /* type 0x5, rN = */ -#define R_luimm16 6 /* # 0x6, preg.l= Load imm 16 to lower half */ -#define R_huimm16 7 /* # 0x7, preg.h= Load imm 16 to upper half */ -#define R_pcrel12_jump_s 8 /* # 0x8 jump.s */ -#define R_pcrel24_jump_x 9 /* # 0x9 jump.x */ -#define R_pcrel24 10 /* # 0xa call , not expandable */ -#define R_unusedb 11 /* # 0xb not generated */ -#define R_unusedc 12 /* # 0xc not used */ -#define R_pcrel24_jump_l 13 /*0xd jump.l */ -#define R_pcrel24_call_x 14 /* 0xE, call.x if is above 24 bit limit call through P1 */ -#define R_var_eq_symb 15 /* 0xf, linker should treat it same as 0x12 */ -#define R_byte_data 16 /* 0x10, .byte var = symbol */ -#define R_byte2_data 17 /* 0x11, .byte2 var = symbol */ -#define R_byte4_data 18 /* 0x12, .byte4 var = symbol and .var var=symbol */ -#define R_pcrel11 19 /* 0x13, lsetup part b */ -#define R_unused14 20 /* 0x14, undefined */ -#define R_unused15 21 /* not generated by VDSP 3.5 */ +#define R_BFIN_UNUSED0 0 /* relocation type 0 is not defined */ +#define R_BFIN_PCREL5M2 1 /* LSETUP part a */ +#define R_BFIN_UNUSED1 2 /* relocation type 2 is not defined */ +#define R_BFIN_PCREL10 3 /* type 3, if cc jump */ +#define R_BFIN_PCREL12_JUMP 4 /* type 4, jump */ +#define R_BFIN_RIMM16 5 /* type 0x5, rN = */ +#define R_BFIN_LUIMM16 6 /* # 0x6, preg.l= Load imm 16 to lower half */ +#define R_BFIN_HUIMM16 7 /* # 0x7, preg.h= Load imm 16 to upper half */ +#define R_BFIN_PCREL12_JUMP_S 8 /* # 0x8 jump.s */ +#define R_BFIN_PCREL24_JUMP_X 9 /* # 0x9 jump.x */ +#define R_BFIN_PCREL24 10 /* # 0xa call , not expandable */ +#define R_BFIN_UNUSEDB 11 /* # 0xb not generated */ +#define R_BFIN_UNUSEDC 12 /* # 0xc not used */ +#define R_BFIN_PCREL24_JUMP_L 13 /* 0xd jump.l */ +#define R_BFIN_PCREL24_CALL_X 14 /* 0xE, call.x if is above 24 bit limit call through P1 */ +#define R_BFIN_VAR_EQ_SYMB 15 /* 0xf, linker should treat it same as 0x12 */ +#define R_BFIN_BYTE_DATA 16 /* 0x10, .byte var = symbol */ +#define R_BFIN_BYTE2_DATA 17 /* 0x11, .byte2 var = symbol */ +#define R_BFIN_BYTE4_DATA 18 /* 0x12, .byte4 var = symbol and .var var=symbol */ +#define R_BFIN_PCREL11 19 /* 0x13, lsetup part b */ +#define R_BFIN_UNUSED14 20 /* 0x14, undefined */ +#define R_BFIN_UNUSED15 21 /* not generated by VDSP 3.5 */ /* arithmetic relocations */ -#define R_push 0xE0 -#define R_const 0xE1 -#define R_add 0xE2 -#define R_sub 0xE3 -#define R_mult 0xE4 -#define R_div 0xE5 -#define R_mod 0xE6 -#define R_lshift 0xE7 -#define R_rshift 0xE8 -#define R_and 0xE9 -#define R_or 0xEA -#define R_xor 0xEB -#define R_land 0xEC -#define R_lor 0xED -#define R_len 0xEE -#define R_neg 0xEF -#define R_comp 0xF0 -#define R_page 0xF1 -#define R_hwpage 0xF2 -#define R_addr 0xF3 +#define R_BFIN_PUSH 0xE0 +#define R_BFIN_CONST 0xE1 +#define R_BFIN_ADD 0xE2 +#define R_BFIN_SUB 0xE3 +#define R_BFIN_MULT 0xE4 +#define R_BFIN_DIV 0xE5 +#define R_BFIN_MOD 0xE6 +#define R_BFIN_LSHIFT 0xE7 +#define R_BFIN_RSHIFT 0xE8 +#define R_BFIN_AND 0xE9 +#define R_BFIN_OR 0xEA +#define R_BFIN_XOR 0xEB +#define R_BFIN_LAND 0xEC +#define R_BFIN_LOR 0xED +#define R_BFIN_LEN 0xEE +#define R_BFIN_NEG 0xEF +#define R_BFIN_COMP 0xF0 +#define R_BFIN_PAGE 0xF1 +#define R_BFIN_HWPAGE 0xF2 +#define R_BFIN_ADDR 0xF3 /* This is the location that an ET_DYN program is loaded if exec'ed. Typical use of this is to invoke "./ld.so someprog" to test out a new version of diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c index 1bd7f2d018a8..d5aee3626688 100644 --- a/arch/blackfin/kernel/module.c +++ b/arch/blackfin/kernel/module.c @@ -201,8 +201,8 @@ apply_relocate(Elf_Shdr * sechdrs, const char *strtab, /* Arithmetic relocations are handled. */ /* We do not expect LSETUP to be split and hence is not */ /* handled. */ -/* R_byte and R_byte2 are also not handled as the gas */ -/* does not generate it. */ +/* R_BFIN_BYTE and R_BFIN_BYTE2 are also not handled as the */ +/* gas does not generate it. */ /*************************************************************************/ int apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, @@ -243,8 +243,8 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, #endif switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_pcrel24: - case R_pcrel24_jump_l: + case R_BFIN_PCREL24: + case R_BFIN_PCREL24_JUMP_L: /* Add the value, subtract its postition */ location16 = (uint16_t *) (sechdrs[sechdrs[relsec].sh_info]. @@ -266,18 +266,18 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, (*location16 & 0xff00) | (value >> 16 & 0x00ff); *(location16 + 1) = value & 0xffff; break; - case R_pcrel12_jump: - case R_pcrel12_jump_s: + case R_BFIN_PCREL12_JUMP: + case R_BFIN_PCREL12_JUMP_S: value -= (uint32_t) location32; value >>= 1; *location16 = (value & 0xfff); break; - case R_pcrel10: + case R_BFIN_PCREL10: value -= (uint32_t) location32; value >>= 1; *location16 = (value & 0x3ff); break; - case R_luimm16: + case R_BFIN_LUIMM16: pr_debug("before %x after %x\n", *location16, (value & 0xffff)); tmp = (value & 0xffff); @@ -286,7 +286,7 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, } else *location16 = tmp; break; - case R_huimm16: + case R_BFIN_HUIMM16: pr_debug("before %x after %x\n", *location16, ((value >> 16) & 0xffff)); tmp = ((value >> 16) & 0xffff); @@ -295,10 +295,10 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, } else *location16 = tmp; break; - case R_rimm16: + case R_BFIN_RIMM16: *location16 = (value & 0xffff); break; - case R_byte4_data: + case R_BFIN_BYTE4_DATA: pr_debug("before %x after %x\n", *location32, value); *location32 = value; break; -- cgit v1.2.3 From 685a694f0653b7db49f663b2cd6953695214fb30 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 3 Jun 2009 00:33:31 +0000 Subject: Blackfin: convert early_printk EVT init to a loop The EVT registers are all contiguous in the memory map, so using a loop to initialize them all rather than hardcoding the list results in much better generated code (a hardware loop rather than a whole bunch of individual loads). Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/early_printk.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c index c8ad051742e2..3302719173ca 100644 --- a/arch/blackfin/kernel/early_printk.c +++ b/arch/blackfin/kernel/early_printk.c @@ -178,25 +178,15 @@ int __init setup_early_printk(char *buf) asmlinkage void __init init_early_exception_vectors(void) { + u32 evt; SSYNC(); /* cannot program in software: * evt0 - emulation (jtag) * evt1 - reset */ - bfin_write_EVT2(early_trap); - bfin_write_EVT3(early_trap); - bfin_write_EVT5(early_trap); - bfin_write_EVT6(early_trap); - bfin_write_EVT7(early_trap); - bfin_write_EVT8(early_trap); - bfin_write_EVT9(early_trap); - bfin_write_EVT10(early_trap); - bfin_write_EVT11(early_trap); - bfin_write_EVT12(early_trap); - bfin_write_EVT13(early_trap); - bfin_write_EVT14(early_trap); - bfin_write_EVT15(early_trap); + for (evt = EVT2; evt <= EVT15; evt += 4) + bfin_write32(evt, early_trap); CSYNC(); /* Set all the return from interrupt, exception, NMI to a known place -- cgit v1.2.3 From a43b739f257fd2569e11c6c93fbb86df382848e9 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 4 Jun 2009 19:24:31 +0000 Subject: Blackfin: push access_ok() L1 attribute down There is no need for the L1 attribute to be on the prototype of the access_ok() function as all consumers of the function do not care where it lives -- they'll always use pcrel calls to get to it. This prevents pointless recompiles of most of the system when this config option changes. Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/uaccess.h | 4 ---- arch/blackfin/kernel/process.c | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h index 01f42b02e26c..8894e9ffbb57 100644 --- a/arch/blackfin/include/asm/uaccess.h +++ b/arch/blackfin/include/asm/uaccess.h @@ -59,12 +59,8 @@ static inline int is_in_rom(unsigned long addr) #ifndef CONFIG_ACCESS_CHECK static inline int _access_ok(unsigned long addr, unsigned long size) { return 1; } #else -#ifdef CONFIG_ACCESS_OK_L1 -extern int _access_ok(unsigned long addr, unsigned long size)__attribute__((l1_text)); -#else extern int _access_ok(unsigned long addr, unsigned long size); #endif -#endif /* * The exception table consists of pairs of addresses: the first is the diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index e040e03335ea..30d0843ed701 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -322,6 +322,9 @@ void finish_atomic_sections (struct pt_regs *regs) } #if defined(CONFIG_ACCESS_CHECK) +#ifdef CONFIG_ACCESS_OK_L1 +__attribute__((l1_text)) +#endif /* Return 1 if access to memory range is OK, 0 otherwise */ int _access_ok(unsigned long addr, unsigned long size) { -- cgit v1.2.3 From 11aca0e7352b6a28193221cd2dd85f758fb71b23 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 4 Jun 2009 17:28:16 +0000 Subject: Blackfin: kgdb: fix up error return values The Blackfin kgdb code was all passing back positive errno values when it really should have been using negative errno values. Reported-by: Roel Kluin Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/kgdb.c | 55 ++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index b163f6d3330d..c5362b2b9ed1 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c @@ -466,7 +466,7 @@ static int validate_memory_access_address(unsigned long addr, int size) int cpu = raw_smp_processor_id(); if (size < 0) - return EFAULT; + return -EFAULT; if (addr >= 0x1000 && (addr + size) <= physical_mem_end) return 0; if (addr >= SYSMMR_BASE) @@ -498,7 +498,7 @@ static int validate_memory_access_address(unsigned long addr, int size) if (IN_MEM(addr, size, L2_START, L2_LENGTH)) return 0; - return EFAULT; + return -EFAULT; } /* @@ -508,14 +508,15 @@ static int validate_memory_access_address(unsigned long addr, int size) int kgdb_mem2hex(char *mem, char *buf, int count) { char *tmp; - int err = 0; + int err; unsigned char *pch; unsigned short mmr16; unsigned long mmr32; int cpu = raw_smp_processor_id(); - if (validate_memory_access_address((unsigned long)mem, count)) - return EFAULT; + err = validate_memory_access_address((unsigned long)mem, count); + if (err) + return err; /* * We use the upper half of buf as an intermediate buffer for the @@ -533,7 +534,7 @@ int kgdb_mem2hex(char *mem, char *buf, int count) *tmp++ = *pch++; tmp -= 2; } else - err = EFAULT; + err = -EFAULT; break; case 4: if ((unsigned int)mem % 4 == 0) { @@ -545,10 +546,10 @@ int kgdb_mem2hex(char *mem, char *buf, int count) *tmp++ = *pch++; tmp -= 4; } else - err = EFAULT; + err = -EFAULT; break; default: - err = EFAULT; + err = -EFAULT; } } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) #ifdef CONFIG_SMP @@ -557,7 +558,7 @@ int kgdb_mem2hex(char *mem, char *buf, int count) ) { /* access L1 instruction SRAM*/ if (dma_memcpy(tmp, mem, count) == NULL) - err = EFAULT; + err = -EFAULT; } else err = probe_kernel_read(tmp, mem, count); @@ -585,7 +586,7 @@ int kgdb_ebin2mem(char *buf, char *mem, int count) char *tmp_new; unsigned short *mmr16; unsigned long *mmr32; - int err = 0; + int err; int size = 0; int cpu = raw_smp_processor_id(); @@ -601,8 +602,9 @@ int kgdb_ebin2mem(char *buf, char *mem, int count) size++; } - if (validate_memory_access_address((unsigned long)mem, size)) - return EFAULT; + err = validate_memory_access_address((unsigned long)mem, size); + if (err) + return err; if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ switch (size) { @@ -611,17 +613,17 @@ int kgdb_ebin2mem(char *buf, char *mem, int count) mmr16 = (unsigned short *)buf; *(unsigned short *)mem = *mmr16; } else - return EFAULT; + err = -EFAULT; break; case 4: if ((unsigned int)mem % 4 == 0) { mmr32 = (unsigned long *)buf; *(unsigned long *)mem = *mmr32; } else - return EFAULT; + err = -EFAULT; break; default: - return EFAULT; + err = -EFAULT; } } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) #ifdef CONFIG_SMP @@ -630,7 +632,7 @@ int kgdb_ebin2mem(char *buf, char *mem, int count) ) { /* access L1 instruction SRAM */ if (dma_memcpy(mem, buf, size) == NULL) - err = EFAULT; + err = -EFAULT; } else err = probe_kernel_write(mem, buf, size); @@ -648,10 +650,12 @@ int kgdb_hex2mem(char *buf, char *mem, int count) char *tmp_hex; unsigned short *mmr16; unsigned long *mmr32; + int err; int cpu = raw_smp_processor_id(); - if (validate_memory_access_address((unsigned long)mem, count)) - return EFAULT; + err = validate_memory_access_address((unsigned long)mem, count); + if (err) + return err; /* * We use the upper half of buf as an intermediate buffer for the @@ -673,17 +677,17 @@ int kgdb_hex2mem(char *buf, char *mem, int count) mmr16 = (unsigned short *)tmp_raw; *(unsigned short *)mem = *mmr16; } else - return EFAULT; + err = -EFAULT; break; case 4: if ((unsigned int)mem % 4 == 0) { mmr32 = (unsigned long *)tmp_raw; *(unsigned long *)mem = *mmr32; } else - return EFAULT; + err = -EFAULT; break; default: - return EFAULT; + err = -EFAULT; } } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) #ifdef CONFIG_SMP @@ -692,10 +696,11 @@ int kgdb_hex2mem(char *buf, char *mem, int count) ) { /* access L1 instruction SRAM */ if (dma_memcpy(mem, tmp_raw, count) == NULL) - return EFAULT; + err = -EFAULT; } else - return probe_kernel_write(mem, tmp_raw, count); - return 0; + err = probe_kernel_write(mem, tmp_raw, count); + + return err; } int kgdb_validate_break_address(unsigned long addr) @@ -715,7 +720,7 @@ int kgdb_validate_break_address(unsigned long addr) if (IN_MEM(addr, BREAK_INSTR_SIZE, L2_START, L2_LENGTH)) return 0; - return EFAULT; + return -EFAULT; } int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) -- cgit v1.2.3 From 0a990614264f04879d9608da1cfcf9a6596efe08 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Thu, 4 Jun 2009 19:57:24 -0400 Subject: Blackfin: fix length checking in kgdb_ebin2mem The kgdb_ebin2mem() was decrementing the count variable to do parsing, but then later still tries to use it based on its original meaning. So leave it untouched and use a different variable to walk the memory. Signed-off-by: Roel Kluin Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/kgdb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index c5362b2b9ed1..da28f796ad78 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c @@ -587,19 +587,18 @@ int kgdb_ebin2mem(char *buf, char *mem, int count) unsigned short *mmr16; unsigned long *mmr32; int err; - int size = 0; + int size; int cpu = raw_smp_processor_id(); tmp_old = tmp_new = buf; - while (count-- > 0) { + for (size = 0; size < count; ++size) { if (*tmp_old == 0x7d) *tmp_new = *(++tmp_old) ^ 0x20; else *tmp_new = *tmp_old; tmp_new++; tmp_old++; - size++; } err = validate_memory_access_address((unsigned long)mem, size); -- cgit v1.2.3 From 81f7f45606812f1d15d618c2646d0f33ca111f87 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 3 Jun 2009 18:58:26 +0000 Subject: Blackfin: export the last exception cause via debugfs We have some test code that runs in userspace that exercises the exception handling of the Blackfin pretty thoroughly. Part of the validation process is checking the exact exception triggered, so export the last one seen to userspace via debugfs when debugging is enabled for the test code to check. Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/traps.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 35f675f5ca16..63ccb283acdc 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -68,6 +68,13 @@ ({ if (0) printk(fmt, ##arg); 0; }) #endif +#if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE) +u32 last_seqstat; +#ifdef CONFIG_DEBUG_MMRS_MODULE +EXPORT_SYMBOL(last_seqstat); +#endif +#endif + /* Initiate the event table handler */ void __init trap_init(void) { @@ -245,6 +252,9 @@ asmlinkage void trap_c(struct pt_regs *fp) unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; trace_buffer_save(j); +#if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE) + last_seqstat = (u32)fp->seqstat; +#endif /* Important - be very careful dereferncing pointers - will lead to * double faults if the stack has become corrupt -- cgit v1.2.3 From ce0bf52dd3f9d980889190bc6097f1756b71eb8c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 4 Jun 2009 23:51:27 -0400 Subject: Blackfin: fix unused warnings after nommu update The massive nommu update (8feae131) left the local variable "vml" unused, so punt it. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/traps.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 63ccb283acdc..aa76dfb0226e 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -86,7 +86,6 @@ void __init trap_init(void) static void decode_address(char *buf, unsigned long address) { #ifdef CONFIG_DEBUG_VERBOSE - struct vm_list_struct *vml; struct task_struct *p; struct mm_struct *mm; unsigned long flags, offset; -- cgit v1.2.3 From bf664c0a3a42683b78d74aca2d7cfb6ccc2aa2c3 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 5 Jun 2009 03:13:11 -0400 Subject: Blackfin: fix sparseirq/kstat_irqs fallout The sparseirq changes (d7e51e66) played poorly with the Blackfin irqchip implementation as we're still using the old hardirq method. Our bad irq structure had a NULL kstat_irqs field so when all the common code tries to increment this field, everything goes big bada boom. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/irqchip.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 401bd32aa499..6e31e935bb31 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -59,12 +59,14 @@ static struct irq_chip bad_chip = { .unmask = dummy_mask_unmask_irq, }; +static int bad_stats; static struct irq_desc bad_irq_desc = { .status = IRQ_DISABLED, .chip = &bad_chip, .handle_irq = handle_bad_irq, .depth = 1, .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), + .kstat_irqs = &bad_stats, #ifdef CONFIG_SMP .affinity = CPU_MASK_ALL #endif -- cgit v1.2.3 From 16aadcb680e188bd0a6d7b0ecd5d0ceabd4fba4d Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Tue, 9 Jun 2009 01:18:41 +0000 Subject: Blackfin: only handle CPLB protection violations when MPU is enabled We don't need to handle CPLB protection violations unless we are running with the MPU on. Fix the entry code to call common trap_c, and remove the code which is never run. This allows the traps test suite to run on older boards with the MPU disabled. URL: http://blackfin.uclinux.org/gf/tracker/5129 Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/cplb-nompu/cplbmgr.c | 54 ++----------------------------- arch/blackfin/mach-common/entry.S | 11 ++++--- 2 files changed, 10 insertions(+), 55 deletions(-) (limited to 'arch/blackfin/kernel') 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 #include #include +#include /* * 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/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index da0558ad1b1a..25c6aa42d45e 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -42,6 +42,7 @@ #include /* TIF_NEED_RESCHED */ #include #include +#include #include @@ -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 -- cgit v1.2.3 From 67834fa93d7a4fac9069a07e739110d3916d8cd4 Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Wed, 10 Jun 2009 06:26:26 +0000 Subject: Blackfin: rename bfin_addr_dcachable to bfin_addr_dcacheable The latter naming convention is much more common. Signed-off-by: Jie Zhang Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/cacheflush.h | 2 +- arch/blackfin/kernel/bfin_dma_5xx.c | 4 ++-- arch/blackfin/kernel/cplb-mpu/cplbmgr.c | 2 +- drivers/spi/spi_bfin5xx.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h index 94697f0f6f40..18bc4f71fe2c 100644 --- a/arch/blackfin/include/asm/cacheflush.h +++ b/arch/blackfin/include/asm/cacheflush.h @@ -97,7 +97,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/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/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/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index f014cc21e813..011c5bddba6a 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c @@ -803,7 +803,7 @@ static void bfin_spi_pump_transfers(unsigned long data) drv_data->rx, drv_data->len_in_bytes); /* invalidate caches, if needed */ - if (bfin_addr_dcachable((unsigned long) drv_data->rx)) + if (bfin_addr_dcacheable((unsigned long) drv_data->rx)) invalidate_dcache_range((unsigned long) drv_data->rx, (unsigned long) (drv_data->rx + drv_data->len_in_bytes)); @@ -816,7 +816,7 @@ static void bfin_spi_pump_transfers(unsigned long data) dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n"); /* flush caches, if needed */ - if (bfin_addr_dcachable((unsigned long) drv_data->tx)) + if (bfin_addr_dcacheable((unsigned long) drv_data->tx)) flush_dcache_range((unsigned long) drv_data->tx, (unsigned long) (drv_data->tx + drv_data->len_in_bytes)); -- cgit v1.2.3 From 70f12567ac9aca9c2f242ae060d7de245904889e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 7 Jun 2009 17:18:25 -0400 Subject: Blackfin: add support for GENERIC_BUG Signed-off-by: Mike Frysinger --- arch/blackfin/Kconfig | 4 +++ arch/blackfin/include/asm/bug.h | 57 ++++++++++++++++++++++++++++++++++---- arch/blackfin/kernel/traps.c | 30 ++++++++++++++++++++ arch/blackfin/kernel/vmlinux.lds.S | 16 +++++++++-- 4 files changed, 99 insertions(+), 8 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index c56fd3eb7c10..74cdcf39b41c 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -28,6 +28,10 @@ config BLACKFIN select HAVE_OPROFILE select ARCH_WANT_OPTIONAL_GPIOLIB +config GENERIC_BUG + def_bool y + depends on BUG + config ZONE_DMA bool default y 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/kernel/traps.c b/arch/blackfin/kernel/traps.c index aa76dfb0226e..2405f193224e 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 #include #include #include @@ -381,6 +382,23 @@ 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)); @@ -792,6 +810,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..119fbdb46475 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -166,6 +166,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 +278,6 @@ SECTIONS /DISCARD/ : { - EXIT_TEXT - EXIT_DATA *(.exitcall.exit) } } -- cgit v1.2.3 From 2466ac65560ee8b7506eea3987aba9519355fd02 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Mon, 8 Jun 2009 17:52:27 +0000 Subject: Blackfin: include the cpu compiled version in /proc/cpuinfo Since the compiled-for cpu revision can be significant, include it in the cpuinfo output along side the cpu revision we're currently running on. Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/setup.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 80447f99c2b5..f5f516e817f4 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" -- cgit v1.2.3 From 47e9dedb720364e0adff0e99960fa294c6161f71 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Wed, 10 Jun 2009 08:57:08 +0000 Subject: Blackfin: add blackfin_invalidate_entire_icache for SMP systems The KGDB code uses this when switching processors to make sure the icache is in a valid state. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/cache.h | 11 ++++++++--- arch/blackfin/include/asm/cacheflush.h | 1 + arch/blackfin/include/asm/cpu.h | 1 + arch/blackfin/kernel/setup.c | 3 +++ arch/blackfin/mach-common/cache-c.c | 14 +++++++++++++- arch/blackfin/mach-common/smp.c | 11 +++++++++++ 6 files changed, 37 insertions(+), 4 deletions(-) (limited to 'arch/blackfin/kernel') 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 18bc4f71fe2c..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) 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/kernel/setup.c b/arch/blackfin/kernel/setup.c index f5f516e817f4..6454babdfaff 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -1181,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/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/smp.c b/arch/blackfin/mach-common/smp.c index 3b8ebaee77f2..c187da2448bf 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -468,6 +468,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"))); -- cgit v1.2.3 From 6510a20e1b1a3a5703429a09d03adf44882ae373 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 7 Jun 2009 15:07:25 -0400 Subject: Blackfin: fix trap_c() exit paths The trap_c() code pushes the hardware trace status onto the stack, but doesn't always restore it when returning from some trap code paths. So unify the exit code paths to all head to the end of the function. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/traps.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 2405f193224e..ed7127b1b9f9 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -309,7 +309,7 @@ asmlinkage void trap_c(struct pt_regs *fp) CHK_DEBUGGER_TRAP_MAYBE(); /* Check if this is a breakpoint in kernel space */ if (fp->ipend & 0xffc0) - return; + goto traps_done; else break; /* 0x03 - User Defined, userspace stack overflow */ @@ -325,7 +325,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 */ @@ -355,7 +355,7 @@ asmlinkage void trap_c(struct pt_regs *fp) CHK_DEBUGGER_TRAP_MAYBE(); /* Check if this is a single step in kernel space */ if (fp->ipend & 0xffc0) - return; + goto traps_done; else break; /* 0x11 - Trace Buffer Full, handled here */ @@ -459,7 +459,7 @@ asmlinkage void trap_c(struct pt_regs *fp) CHK_DEBUGGER_TRAP_MAYBE(); /* Check if this is a watchpoint in kernel space */ if (fp->ipend & 0xffc0) - return; + goto traps_done; else break; #ifdef CONFIG_BF535 @@ -624,8 +624,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 */ -- cgit v1.2.3 From 82bd1d7d45a69c54fb6beedb78ccb1c7d308dd93 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 7 Jun 2009 17:08:28 -0400 Subject: Blackfin: push down exception oops checking Rather than maintain a duplicate list of valid exceptions we can take in the kernel both in the first if() check and the switch() check, delay the oops check to after the switch(). All valid exceptions will have returned by this point leaving only the invalid ones. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/traps.c | 88 ++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 45 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index ed7127b1b9f9..d279552fe9b0 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -239,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 @@ -247,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; @@ -260,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. @@ -308,7 +297,7 @@ 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) + if (kernel_mode_regs(fp)) goto traps_done; else break; @@ -316,7 +305,7 @@ asmlinkage void trap_c(struct pt_regs *fp) 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 */ @@ -345,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 */ @@ -354,7 +343,7 @@ 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) + if (kernel_mode_regs(fp)) goto traps_done; else break; @@ -362,7 +351,7 @@ asmlinkage void trap_c(struct pt_regs *fp) 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 */ @@ -401,35 +390,35 @@ asmlinkage void trap_c(struct pt_regs *fp) #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, @@ -437,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: @@ -445,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 */ @@ -458,7 +447,7 @@ 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) + if (kernel_mode_regs(fp)) goto traps_done; else break; @@ -467,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 @@ -477,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: @@ -499,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 */ @@ -537,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): @@ -564,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", @@ -575,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); -- cgit v1.2.3 From 54ebae7166275a618f0228138e67ff7d10a3b9d0 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 10 Jun 2009 06:11:21 +0000 Subject: Blackfin: do not configure the UART early if on wrong processor Before we configure the early UART, check to make sure we are running on the expected processor - otherwise, we cause problems by configuring pins that don't exist (and causing an infinite loop of faults). Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/early_printk.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'arch/blackfin/kernel') 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(); -- cgit v1.2.3 From 6640cfa82b77fa63f6d3fc284dbd3ab957842936 Mon Sep 17 00:00:00 2001 From: Yi Li Date: Thu, 11 Jun 2009 01:51:57 -0400 Subject: Blackfin: update aedos-ipipe code to upstream 1.10-00 Signed-off-by: Yi Li Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/ipipe.h | 28 ++++++++++++++------------ arch/blackfin/kernel/ipipe.c | 42 ++++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 33 deletions(-) (limited to 'arch/blackfin/kernel') 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 #include -#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/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; } -- cgit v1.2.3 From c7b412f41d9c95d084e049fe83248ebb41a2d8f5 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 8 Jun 2009 18:44:45 -0400 Subject: Blackfin: add preliminary support for STACKTRACE Signed-off-by: Mike Frysinger --- arch/blackfin/Kconfig | 3 +++ arch/blackfin/kernel/Makefile | 1 + arch/blackfin/kernel/stacktrace.c | 53 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 arch/blackfin/kernel/stacktrace.c (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index d68cb0dc583a..77ec14fcc610 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -55,6 +55,9 @@ config FORCE_MAX_ZONEORDER config GENERIC_CALIBRATE_DELAY def_bool y +config STACKTRACE_SUPPORT + def_bool y + config TRACE_IRQFLAGS_SUPPORT def_bool y diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index fd4d4328a0f2..a66dda4f4b1f 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -23,6 +23,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/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 +#include +#include +#include + +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); -- cgit v1.2.3 From 1c873be744410e26fb91ee9228c90adff6eabe15 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 9 Jun 2009 07:25:09 -0400 Subject: Blackfin: initial support for ftrace Just the basic ftrace support here -- mcount and the ftrace stub. Signed-off-by: Mike Frysinger --- arch/blackfin/Kconfig | 1 + arch/blackfin/include/asm/ftrace.h | 14 +++++++- arch/blackfin/kernel/Makefile | 1 + arch/blackfin/kernel/bfin_ksyms.c | 5 +++ arch/blackfin/kernel/ftrace-entry.S | 72 +++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 arch/blackfin/kernel/ftrace-entry.S (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index d03fd638e9aa..ea8d92c1d447 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -19,6 +19,7 @@ config RWSEM_XCHGADD_ALGORITHM config BLACKFIN def_bool y + select HAVE_FUNCTION_TRACER select HAVE_IDE select HAVE_KERNEL_GZIP select HAVE_KERNEL_BZIP2 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/kernel/Makefile b/arch/blackfin/kernel/Makefile index a66dda4f4b1f..d2ae285e5b6e 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -15,6 +15,7 @@ else obj-y += time.o endif +obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o obj-$(CONFIG_IPIPE) += ipipe.o obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o 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/ftrace-entry.S b/arch/blackfin/kernel/ftrace-entry.S new file mode 100644 index 000000000000..ce71487b515f --- /dev/null +++ b/arch/blackfin/kernel/ftrace-entry.S @@ -0,0 +1,72 @@ +/* + * mcount and friends -- ftrace stuff + * + * Copyright (C) 2009 Analog Devices Inc. + * Licensed under the GPL-2 or later. + */ + +#include +#include + +.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; + + 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 */ + rets = [sp++]; + r1 = [sp++]; + r0 = [sp++]; + r2 = [sp++]; + +.globl _ftrace_stub +_ftrace_stub: + rts; +ENDPROC(__mcount) -- cgit v1.2.3 From 1ee76d7e169ff2b0ff1df4b40b9d5276eec9ffb4 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 10 Jun 2009 04:45:29 -0400 Subject: Blackfin: initial support for ftrace grapher Signed-off-by: Mike Frysinger --- arch/blackfin/Kconfig | 1 + arch/blackfin/kernel/Makefile | 3 ++ arch/blackfin/kernel/ftrace-entry.S | 68 +++++++++++++++++++++++++++++++++++++ arch/blackfin/kernel/ftrace.c | 42 +++++++++++++++++++++++ arch/blackfin/kernel/vmlinux.lds.S | 1 + 5 files changed, 115 insertions(+) create mode 100644 arch/blackfin/kernel/ftrace.c (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index ea8d92c1d447..5bc1360de2ee 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -19,6 +19,7 @@ config RWSEM_XCHGADD_ALGORITHM config BLACKFIN def_bool y + select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER select HAVE_IDE select HAVE_KERNEL_GZIP diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index d2ae285e5b6e..3731088e181b 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -16,6 +16,9 @@ else 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 diff --git a/arch/blackfin/kernel/ftrace-entry.S b/arch/blackfin/kernel/ftrace-entry.S index ce71487b515f..6980b7a0615d 100644 --- a/arch/blackfin/kernel/ftrace-entry.S +++ b/arch/blackfin/kernel/ftrace-entry.S @@ -35,6 +35,28 @@ ENTRY(__mcount) 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; @@ -61,6 +83,7 @@ ENTRY(__mcount) call (p0); /* restore state and get out of dodge */ +.Lfinish_trace: rets = [sp++]; r1 = [sp++]; r0 = [sp++]; @@ -70,3 +93,48 @@ ENTRY(__mcount) _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 +#include +#include +#include + +#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/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index 119fbdb46475..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) -- cgit v1.2.3 From bb1f17b0372de93758653ca3454bc0df18dc2e5c Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 16 Jun 2009 15:31:18 -0700 Subject: mm: consolidate init_mm definition * create mm/init-mm.c, move init_mm there * remove INIT_MM, initialize init_mm with C99 initializer * unexport init_mm on all arches: init_mm is already unexported on x86. One strange place is some OMAP driver (drivers/video/omap/) which won't build modular, but it's already wants get_vm_area() export. Somebody should look there. [akpm@linux-foundation.org: add missing #includes] Signed-off-by: Alexey Dobriyan Cc: Mike Frysinger Cc: Americo Wang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/init_task.c | 3 --- arch/arm/kernel/init_task.c | 4 ---- arch/avr32/kernel/init_task.c | 4 ---- arch/blackfin/kernel/init_task.c | 4 ---- arch/cris/kernel/process.c | 4 ---- arch/frv/kernel/init_task.c | 4 ---- arch/h8300/kernel/init_task.c | 4 ---- arch/ia64/kernel/init_task.c | 4 ---- arch/m32r/kernel/init_task.c | 4 ---- arch/m68k/kernel/process.c | 4 ---- arch/m68knommu/kernel/init_task.c | 4 ---- arch/mips/kernel/init_task.c | 4 ---- arch/mn10300/kernel/init_task.c | 3 --- arch/parisc/kernel/init_task.c | 4 ---- arch/powerpc/kernel/init_task.c | 4 ---- arch/s390/kernel/init_task.c | 4 ---- arch/sh/kernel/init_task.c | 3 --- arch/sparc/kernel/init_task.c | 3 --- arch/um/kernel/init_task.c | 3 --- arch/x86/kernel/init_task.c | 1 - arch/xtensa/kernel/init_task.c | 4 ---- include/linux/init_task.h | 12 ------------ mm/Makefile | 1 + mm/init-mm.c | 20 ++++++++++++++++++++ 24 files changed, 21 insertions(+), 88 deletions(-) create mode 100644 mm/init-mm.c (limited to 'arch/blackfin/kernel') diff --git a/arch/alpha/kernel/init_task.c b/arch/alpha/kernel/init_task.c index c2938e574a40..19b86328ffd7 100644 --- a/arch/alpha/kernel/init_task.c +++ b/arch/alpha/kernel/init_task.c @@ -10,10 +10,7 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); struct task_struct init_task = INIT_TASK(init_task); - -EXPORT_SYMBOL(init_mm); EXPORT_SYMBOL(init_task); union thread_union init_thread_union diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c index e859af349467..3f470866bb89 100644 --- a/arch/arm/kernel/init_task.c +++ b/arch/arm/kernel/init_task.c @@ -14,10 +14,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial thread structure. * diff --git a/arch/avr32/kernel/init_task.c b/arch/avr32/kernel/init_task.c index 993d56ee3cf3..57ec9f2dcd95 100644 --- a/arch/avr32/kernel/init_task.c +++ b/arch/avr32/kernel/init_task.c @@ -15,10 +15,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial thread structure. Must be aligned on an 8192-byte boundary. */ diff --git a/arch/blackfin/kernel/init_task.c b/arch/blackfin/kernel/init_task.c index 2c228c020978..c26c34de9f3c 100644 --- a/arch/blackfin/kernel/init_task.c +++ b/arch/blackfin/kernel/init_task.c @@ -35,10 +35,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); - -struct mm_struct init_mm = INIT_MM(init_mm); -EXPORT_SYMBOL(init_mm); - /* * Initial task structure. * diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 4df0b320d524..51dcd04d2777 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c @@ -38,10 +38,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial thread structure. * diff --git a/arch/frv/kernel/init_task.c b/arch/frv/kernel/init_task.c index 29429a8b7f6a..1d3df1d9495c 100644 --- a/arch/frv/kernel/init_task.c +++ b/arch/frv/kernel/init_task.c @@ -12,10 +12,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial thread structure. * diff --git a/arch/h8300/kernel/init_task.c b/arch/h8300/kernel/init_task.c index cb5dc552da97..089c65ed6eb3 100644 --- a/arch/h8300/kernel/init_task.c +++ b/arch/h8300/kernel/init_task.c @@ -14,10 +14,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial task structure. * diff --git a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c index 5b0e830c6f33..c475fc281be7 100644 --- a/arch/ia64/kernel/init_task.c +++ b/arch/ia64/kernel/init_task.c @@ -19,10 +19,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial task structure. * diff --git a/arch/m32r/kernel/init_task.c b/arch/m32r/kernel/init_task.c index 016885c6f260..fce57e5d3f91 100644 --- a/arch/m32r/kernel/init_task.c +++ b/arch/m32r/kernel/init_task.c @@ -13,10 +13,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial thread structure. * diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index ec37fb56c127..72bad65dba3a 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -42,10 +42,6 @@ */ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - union thread_union init_thread_union __attribute__((section(".data.init_task"), aligned(THREAD_SIZE))) = { INIT_THREAD_INFO(init_task) }; diff --git a/arch/m68knommu/kernel/init_task.c b/arch/m68knommu/kernel/init_task.c index fe282de1d596..45e97a207fed 100644 --- a/arch/m68knommu/kernel/init_task.c +++ b/arch/m68knommu/kernel/init_task.c @@ -14,10 +14,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial task structure. * diff --git a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c index 149cd914526e..5b457a40c784 100644 --- a/arch/mips/kernel/init_task.c +++ b/arch/mips/kernel/init_task.c @@ -11,10 +11,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial thread structure. * diff --git a/arch/mn10300/kernel/init_task.c b/arch/mn10300/kernel/init_task.c index 5ac3566f8c98..80d423b80af3 100644 --- a/arch/mn10300/kernel/init_task.c +++ b/arch/mn10300/kernel/init_task.c @@ -20,9 +20,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); -EXPORT_SYMBOL(init_mm); - /* * Initial thread structure. * diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c index 1e25a45d64c1..82974b20fc10 100644 --- a/arch/parisc/kernel/init_task.c +++ b/arch/parisc/kernel/init_task.c @@ -36,10 +36,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial task structure. * diff --git a/arch/powerpc/kernel/init_task.c b/arch/powerpc/kernel/init_task.c index 688b329800bd..ffc4253fef55 100644 --- a/arch/powerpc/kernel/init_task.c +++ b/arch/powerpc/kernel/init_task.c @@ -9,10 +9,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial thread structure. * diff --git a/arch/s390/kernel/init_task.c b/arch/s390/kernel/init_task.c index 7db95c0b8693..fe787f9e5f3f 100644 --- a/arch/s390/kernel/init_task.c +++ b/arch/s390/kernel/init_task.c @@ -18,10 +18,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - /* * Initial thread structure. * diff --git a/arch/sh/kernel/init_task.c b/arch/sh/kernel/init_task.c index 80c35ff71d56..1719957c0a69 100644 --- a/arch/sh/kernel/init_task.c +++ b/arch/sh/kernel/init_task.c @@ -10,9 +10,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct pt_regs fake_swapper_regs; -struct mm_struct init_mm = INIT_MM(init_mm); -EXPORT_SYMBOL(init_mm); - /* * Initial thread structure. * diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c index f28cb8278e98..28125c5b3d3c 100644 --- a/arch/sparc/kernel/init_task.c +++ b/arch/sparc/kernel/init_task.c @@ -10,10 +10,7 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); struct task_struct init_task = INIT_TASK(init_task); - -EXPORT_SYMBOL(init_mm); EXPORT_SYMBOL(init_task); /* .text section in head.S is aligned at 8k boundary and this gets linked diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index 806d381947bf..b25121b537d8 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c @@ -10,11 +10,8 @@ #include "linux/mqueue.h" #include "asm/uaccess.h" -struct mm_struct init_mm = INIT_MM(init_mm); static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -EXPORT_SYMBOL(init_mm); - /* * Initial task structure. * diff --git a/arch/x86/kernel/init_task.c b/arch/x86/kernel/init_task.c index df3bf269beab..270ff83efc11 100644 --- a/arch/x86/kernel/init_task.c +++ b/arch/x86/kernel/init_task.c @@ -12,7 +12,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); /* * Initial thread structure. diff --git a/arch/xtensa/kernel/init_task.c b/arch/xtensa/kernel/init_task.c index e07f5c9fcd35..c4302f0e4ba0 100644 --- a/arch/xtensa/kernel/init_task.c +++ b/arch/xtensa/kernel/init_task.c @@ -23,10 +23,6 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - union thread_union init_thread_union __attribute__((__section__(".data.init_task"))) = { INIT_THREAD_INFO(init_task) }; diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 28b1f30601b5..5368fbdc7801 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -15,18 +15,6 @@ extern struct files_struct init_files; extern struct fs_struct init_fs; -#define INIT_MM(name) \ -{ \ - .mm_rb = RB_ROOT, \ - .pgd = swapper_pg_dir, \ - .mm_users = ATOMIC_INIT(2), \ - .mm_count = ATOMIC_INIT(1), \ - .mmap_sem = __RWSEM_INITIALIZER(name.mmap_sem), \ - .page_table_lock = __SPIN_LOCK_UNLOCKED(name.page_table_lock), \ - .mmlist = LIST_HEAD_INIT(name.mmlist), \ - .cpu_vm_mask = CPU_MASK_ALL, \ -} - #define INIT_SIGNALS(sig) { \ .count = ATOMIC_INIT(1), \ .wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\ diff --git a/mm/Makefile b/mm/Makefile index e89acb090b4d..cf76be785add 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -12,6 +12,7 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ readahead.o swap.o truncate.o vmscan.o shmem.o \ prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ page_isolation.o mm_init.o $(mmu-y) +obj-y += init-mm.o obj-$(CONFIG_PROC_PAGE_MONITOR) += pagewalk.o obj-$(CONFIG_BOUNCE) += bounce.o diff --git a/mm/init-mm.c b/mm/init-mm.c new file mode 100644 index 000000000000..57aba0da9668 --- /dev/null +++ b/mm/init-mm.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +struct mm_struct init_mm = { + .mm_rb = RB_ROOT, + .pgd = swapper_pg_dir, + .mm_users = ATOMIC_INIT(2), + .mm_count = ATOMIC_INIT(1), + .mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem), + .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock), + .mmlist = LIST_HEAD_INIT(init_mm.mmlist), + .cpu_vm_mask = CPU_MASK_ALL, +}; -- cgit v1.2.3 From abea0bc3d990e5d80f6112985cecee68922a08a3 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 13 Jun 2009 10:35:10 -0400 Subject: Blackfin: pull in asm/io.h in ksyms for prototypes Make sure we pull in asm/io.h when exporting symbols for the I/O functions so we don't end up with a build failure due to missing prototypes. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/bfin_ksyms.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c index aa05e638fb7c..ed8392c117ea 100644 --- a/arch/blackfin/kernel/bfin_ksyms.c +++ b/arch/blackfin/kernel/bfin_ksyms.c @@ -10,6 +10,7 @@ #include #include +#include /* Allow people to have their own Blackfin exception handler in a module */ EXPORT_SYMBOL(bfin_return_from_exception); -- cgit v1.2.3 From d5ce528c8e46fa5afb9ff021514a6658d1758b4e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 13 Jun 2009 11:32:34 -0400 Subject: Blackfin: convert irq/process to asm-generic Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/hardirq.h | 42 +++-------------------------------- arch/blackfin/include/asm/irq.h | 5 +---- arch/blackfin/include/asm/processor.h | 35 +++-------------------------- arch/blackfin/kernel/process.c | 23 +++++++++++++++++++ 4 files changed, 30 insertions(+), 75 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/include/asm/hardirq.h b/arch/blackfin/include/asm/hardirq.h index 717181a1749b..cbd52f86bb9f 100644 --- a/arch/blackfin/include/asm/hardirq.h +++ b/arch/blackfin/include/asm/hardirq.h @@ -1,47 +1,11 @@ #ifndef __BFIN_HARDIRQ_H #define __BFIN_HARDIRQ_H -#include -#include -#include - -typedef struct { - unsigned int __softirq_pending; - unsigned int __syscall_count; - struct task_struct *__ksoftirqd_task; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -/* - * We put the hardirq and softirq counter into the preemption - * counter. The bitmask has the following meaning: - * - * - bits 0-7 are the preemption count (max preemption depth: 256) - * - bits 8-15 are the softirq count (max # of softirqs: 256) - * - bits 16-23 are the hardirq count (max # of hardirqs: 256) - * - * - ( bit 26 is the PREEMPT_ACTIVE flag. ) - * - * PREEMPT_MASK: 0x000000ff - * HARDIRQ_MASK: 0x0000ff00 - * SOFTIRQ_MASK: 0x00ff0000 - */ - -#if NR_IRQS > 256 -#define HARDIRQ_BITS 9 -#else -#define HARDIRQ_BITS 8 -#endif - -#ifdef NR_IRQS -# if (1 << HARDIRQ_BITS) < NR_IRQS -# error HARDIRQ_BITS is too low! -# endif -#endif - #define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 extern void ack_bad_irq(unsigned int irq); +#define ack_bad_irq ack_bad_irq + +#include #endif diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h index 400bdd52ce87..9a7f63a83c47 100644 --- a/arch/blackfin/include/asm/irq.h +++ b/arch/blackfin/include/asm/irq.h @@ -45,9 +45,6 @@ : "d" (bfin_irq_flags) \ ) -static inline int irq_canonicalize(int irq) -{ - return irq; -} +#include #endif /* _BFIN_IRQ_H_ */ diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h index 3040415523b2..d0be99be8308 100644 --- a/arch/blackfin/include/asm/processor.h +++ b/arch/blackfin/include/asm/processor.h @@ -7,9 +7,8 @@ */ #define current_text_addr() ({ __label__ _l; _l: &&_l;}) +#include #include -#include -#include static inline unsigned long rdusp(void) { @@ -59,36 +58,8 @@ struct thread_struct { PS_S, 0, 0 \ } -/* - * Do necessary setup to start up a newly executed thread. - * - * pass the data segment into user programs if it exists, - * it can't hurt anything as far as I can tell - */ -#ifndef CONFIG_SMP -#define start_thread(_regs, _pc, _usp) \ -do { \ - set_fs(USER_DS); \ - (_regs)->pc = (_pc); \ - if (current->mm) \ - (_regs)->p5 = current->mm->start_data; \ - task_thread_info(current)->l1_task_info.stack_start \ - = (void *)current->mm->context.stack_start; \ - task_thread_info(current)->l1_task_info.lowest_sp = (void *)(_usp); \ - memcpy(L1_SCRATCH_TASK_INFO, &task_thread_info(current)->l1_task_info, \ - sizeof(*L1_SCRATCH_TASK_INFO)); \ - wrusp(_usp); \ -} while(0) -#else -#define start_thread(_regs, _pc, _usp) \ -do { \ - set_fs(USER_DS); \ - (_regs)->pc = (_pc); \ - if (current->mm) \ - (_regs)->p5 = current->mm->start_data; \ - wrusp(_usp); \ -} while (0) -#endif +extern void start_thread(struct pt_regs *regs, unsigned long new_ip, + unsigned long new_sp); /* Forward declaration, a strange C thing */ struct task_struct; diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 30d0843ed701..3e1d86e456f6 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -160,6 +160,29 @@ pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) } EXPORT_SYMBOL(kernel_thread); +/* + * Do necessary setup to start up a newly executed thread. + * + * pass the data segment into user programs if it exists, + * it can't hurt anything as far as I can tell + */ +void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) +{ + set_fs(USER_DS); + regs->pc = new_ip; + if (current->mm) + regs->p5 = current->mm->start_data; +#ifdef CONFIG_SMP + task_thread_info(current)->l1_task_info.stack_start = + (void *)current->mm->context.stack_start; + task_thread_info(current)->l1_task_info.lowest_sp = (void *)new_sp; + memcpy(L1_SCRATCH_TASK_INFO, &task_thread_info(current)->l1_task_info, + sizeof(*L1_SCRATCH_TASK_INFO)); +#endif + wrusp(new_sp); +} +EXPORT_SYMBOL_GPL(start_thread); + void flush_thread(void) { } -- cgit v1.2.3 From e56e03b0cfeb997a4be9ad874c193824364942e0 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 7 Jun 2009 16:31:52 -0400 Subject: Blackfin: unify memory region checks between kgdb and traps The kgdb (in multiple places) and traps code developed pretty much identical checks for how to access different regions of the Blackfin memory map, but each wasn't 100%, so unify them to avoid duplication, bitrot, and bugs with edge cases. Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/uaccess.h | 22 +++ arch/blackfin/kernel/kgdb.c | 297 ++++++++++++------------------------ arch/blackfin/kernel/process.c | 151 ++++++++++++++---- arch/blackfin/kernel/traps.c | 60 +++----- 4 files changed, 256 insertions(+), 274 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h index 8894e9ffbb57..2f469a1f80fb 100644 --- a/arch/blackfin/include/asm/uaccess.h +++ b/arch/blackfin/include/asm/uaccess.h @@ -265,4 +265,26 @@ __clear_user(void *to, unsigned long n) #define clear_user(to, n) __clear_user(to, n) +/* How to interpret these return values: + * CORE: can be accessed by core load or dma memcpy + * CORE_ONLY: can only be accessed by core load + * DMA: can only be accessed by dma memcpy + * IDMA: can only be accessed by interprocessor dma memcpy (BF561) + * ITEST: can be accessed by isram memcpy or dma memcpy + */ +enum { + BFIN_MEM_ACCESS_CORE = 0, + BFIN_MEM_ACCESS_CORE_ONLY, + BFIN_MEM_ACCESS_DMA, + BFIN_MEM_ACCESS_IDMA, + BFIN_MEM_ACCESS_ITEST, +}; +/** + * bfin_mem_access_type() - what kind of memory access is required + * @addr: the address to check + * @size: number of bytes needed + * @return: <0 is error, >=0 is BFIN_MEM_ACCESS_xxx enum (see above) + */ +int bfin_mem_access_type(unsigned long addr, unsigned long size); + #endif /* _BLACKFIN_UACCESS_H */ diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index da28f796ad78..cce79d05b90b 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c @@ -34,15 +34,6 @@ int gdb_bfin_vector = -1; #error change the definition of slavecpulocks #endif -#define IN_MEM(addr, size, l1_addr, l1_size) \ -({ \ - unsigned long __addr = (unsigned long)(addr); \ - (l1_size && __addr >= l1_addr && __addr + (size) <= l1_addr + l1_size); \ -}) -#define ASYNC_BANK_SIZE \ - (ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \ - ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) - void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) { gdb_regs[BFIN_R0] = regs->r0; @@ -463,41 +454,88 @@ static int hex(char ch) static int validate_memory_access_address(unsigned long addr, int size) { - int cpu = raw_smp_processor_id(); - - if (size < 0) + if (size < 0 || addr == 0) return -EFAULT; - if (addr >= 0x1000 && (addr + size) <= physical_mem_end) - return 0; - if (addr >= SYSMMR_BASE) - return 0; - if (IN_MEM(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK_SIZE)) - return 0; - if (cpu == 0) { - if (IN_MEM(addr, size, L1_SCRATCH_START, L1_SCRATCH_LENGTH)) - return 0; - if (IN_MEM(addr, size, L1_CODE_START, L1_CODE_LENGTH)) - return 0; - if (IN_MEM(addr, size, L1_DATA_A_START, L1_DATA_A_LENGTH)) - return 0; - if (IN_MEM(addr, size, L1_DATA_B_START, L1_DATA_B_LENGTH)) - return 0; -#ifdef CONFIG_SMP - } else if (cpu == 1) { - if (IN_MEM(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH)) + return bfin_mem_access_type(addr, size); +} + +static int bfin_probe_kernel_read(char *dst, char *src, int size) +{ + unsigned long lsrc = (unsigned long)src; + int mem_type; + + mem_type = validate_memory_access_address(lsrc, size); + if (mem_type < 0) + return mem_type; + + if (lsrc >= SYSMMR_BASE) { + if (size == 2 && lsrc % 2 == 0) { + u16 mmr = bfin_read16(src); + memcpy(dst, &mmr, sizeof(mmr)); return 0; - if (IN_MEM(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH)) + } else if (size == 4 && lsrc % 4 == 0) { + u32 mmr = bfin_read32(src); + memcpy(dst, &mmr, sizeof(mmr)); return 0; - if (IN_MEM(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH)) + } + } else { + switch (mem_type) { + case BFIN_MEM_ACCESS_CORE: + case BFIN_MEM_ACCESS_CORE_ONLY: + return probe_kernel_read(dst, src, size); + /* XXX: should support IDMA here with SMP */ + case BFIN_MEM_ACCESS_DMA: + if (dma_memcpy(dst, src, size)) + return 0; + break; + case BFIN_MEM_ACCESS_ITEST: + if (isram_memcpy(dst, src, size)) + return 0; + break; + } + } + + return -EFAULT; +} + +static int bfin_probe_kernel_write(char *dst, char *src, int size) +{ + unsigned long ldst = (unsigned long)dst; + int mem_type; + + mem_type = validate_memory_access_address(ldst, size); + if (mem_type < 0) + return mem_type; + + if (ldst >= SYSMMR_BASE) { + if (size == 2 && ldst % 2 == 0) { + u16 mmr; + memcpy(&mmr, src, sizeof(mmr)); + bfin_write16(dst, mmr); return 0; - if (IN_MEM(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH)) + } else if (size == 4 && ldst % 4 == 0) { + u32 mmr; + memcpy(&mmr, src, sizeof(mmr)); + bfin_write32(dst, mmr); return 0; -#endif + } + } else { + switch (mem_type) { + case BFIN_MEM_ACCESS_CORE: + case BFIN_MEM_ACCESS_CORE_ONLY: + return probe_kernel_write(dst, src, size); + /* XXX: should support IDMA here with SMP */ + case BFIN_MEM_ACCESS_DMA: + if (dma_memcpy(dst, src, size)) + return 0; + break; + case BFIN_MEM_ACCESS_ITEST: + if (isram_memcpy(dst, src, size)) + return 0; + break; + } } - if (IN_MEM(addr, size, L2_START, L2_LENGTH)) - return 0; - return -EFAULT; } @@ -509,14 +547,6 @@ int kgdb_mem2hex(char *mem, char *buf, int count) { char *tmp; int err; - unsigned char *pch; - unsigned short mmr16; - unsigned long mmr32; - int cpu = raw_smp_processor_id(); - - err = validate_memory_access_address((unsigned long)mem, count); - if (err) - return err; /* * We use the upper half of buf as an intermediate buffer for the @@ -524,44 +554,7 @@ int kgdb_mem2hex(char *mem, char *buf, int count) */ tmp = buf + count; - if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ - switch (count) { - case 2: - if ((unsigned int)mem % 2 == 0) { - mmr16 = *(unsigned short *)mem; - pch = (unsigned char *)&mmr16; - *tmp++ = *pch++; - *tmp++ = *pch++; - tmp -= 2; - } else - err = -EFAULT; - break; - case 4: - if ((unsigned int)mem % 4 == 0) { - mmr32 = *(unsigned long *)mem; - pch = (unsigned char *)&mmr32; - *tmp++ = *pch++; - *tmp++ = *pch++; - *tmp++ = *pch++; - *tmp++ = *pch++; - tmp -= 4; - } else - err = -EFAULT; - break; - default: - err = -EFAULT; - } - } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) -#ifdef CONFIG_SMP - || (cpu == 1 && IN_MEM(mem, count, COREB_L1_CODE_START, L1_CODE_LENGTH)) -#endif - ) { - /* access L1 instruction SRAM*/ - if (dma_memcpy(tmp, mem, count) == NULL) - err = -EFAULT; - } else - err = probe_kernel_read(tmp, mem, count); - + err = bfin_probe_kernel_read(tmp, mem, count); if (!err) { while (count > 0) { buf = pack_hex_byte(buf, *tmp); @@ -582,13 +575,8 @@ int kgdb_mem2hex(char *mem, char *buf, int count) */ int kgdb_ebin2mem(char *buf, char *mem, int count) { - char *tmp_old; - char *tmp_new; - unsigned short *mmr16; - unsigned long *mmr32; - int err; + char *tmp_old, *tmp_new; int size; - int cpu = raw_smp_processor_id(); tmp_old = tmp_new = buf; @@ -601,41 +589,7 @@ int kgdb_ebin2mem(char *buf, char *mem, int count) tmp_old++; } - err = validate_memory_access_address((unsigned long)mem, size); - if (err) - return err; - - if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ - switch (size) { - case 2: - if ((unsigned int)mem % 2 == 0) { - mmr16 = (unsigned short *)buf; - *(unsigned short *)mem = *mmr16; - } else - err = -EFAULT; - break; - case 4: - if ((unsigned int)mem % 4 == 0) { - mmr32 = (unsigned long *)buf; - *(unsigned long *)mem = *mmr32; - } else - err = -EFAULT; - break; - default: - err = -EFAULT; - } - } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) -#ifdef CONFIG_SMP - || (cpu == 1 && IN_MEM(mem, count, COREB_L1_CODE_START, L1_CODE_LENGTH)) -#endif - ) { - /* access L1 instruction SRAM */ - if (dma_memcpy(mem, buf, size) == NULL) - err = -EFAULT; - } else - err = probe_kernel_write(mem, buf, size); - - return err; + return bfin_probe_kernel_write(mem, buf, count); } /* @@ -645,16 +599,7 @@ int kgdb_ebin2mem(char *buf, char *mem, int count) */ int kgdb_hex2mem(char *buf, char *mem, int count) { - char *tmp_raw; - char *tmp_hex; - unsigned short *mmr16; - unsigned long *mmr32; - int err; - int cpu = raw_smp_processor_id(); - - err = validate_memory_access_address((unsigned long)mem, count); - if (err) - return err; + char *tmp_raw, *tmp_hex; /* * We use the upper half of buf as an intermediate buffer for the @@ -669,39 +614,18 @@ int kgdb_hex2mem(char *buf, char *mem, int count) *tmp_raw |= hex(*tmp_hex--) << 4; } - if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ - switch (count) { - case 2: - if ((unsigned int)mem % 2 == 0) { - mmr16 = (unsigned short *)tmp_raw; - *(unsigned short *)mem = *mmr16; - } else - err = -EFAULT; - break; - case 4: - if ((unsigned int)mem % 4 == 0) { - mmr32 = (unsigned long *)tmp_raw; - *(unsigned long *)mem = *mmr32; - } else - err = -EFAULT; - break; - default: - err = -EFAULT; - } - } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) -#ifdef CONFIG_SMP - || (cpu == 1 && IN_MEM(mem, count, COREB_L1_CODE_START, L1_CODE_LENGTH)) -#endif - ) { - /* access L1 instruction SRAM */ - if (dma_memcpy(mem, tmp_raw, count) == NULL) - err = -EFAULT; - } else - err = probe_kernel_write(mem, tmp_raw, count); - - return err; + return bfin_probe_kernel_write(mem, tmp_raw, count); } +#define IN_MEM(addr, size, l1_addr, l1_size) \ +({ \ + unsigned long __addr = (unsigned long)(addr); \ + (l1_size && __addr >= l1_addr && __addr + (size) <= l1_addr + l1_size); \ +}) +#define ASYNC_BANK_SIZE \ + (ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \ + ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) + int kgdb_validate_break_address(unsigned long addr) { int cpu = raw_smp_processor_id(); @@ -724,46 +648,17 @@ int kgdb_validate_break_address(unsigned long addr) int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) { - int err; - int cpu = raw_smp_processor_id(); - - if ((cpu == 0 && IN_MEM(addr, BREAK_INSTR_SIZE, L1_CODE_START, L1_CODE_LENGTH)) -#ifdef CONFIG_SMP - || (cpu == 1 && IN_MEM(addr, BREAK_INSTR_SIZE, COREB_L1_CODE_START, L1_CODE_LENGTH)) -#endif - ) { - /* access L1 instruction SRAM */ - if (dma_memcpy(saved_instr, (void *)addr, BREAK_INSTR_SIZE) - == NULL) - return -EFAULT; - - if (dma_memcpy((void *)addr, arch_kgdb_ops.gdb_bpt_instr, - BREAK_INSTR_SIZE) == NULL) - return -EFAULT; - - return 0; - } else { - err = probe_kernel_read(saved_instr, (char *)addr, - BREAK_INSTR_SIZE); - if (err) - return err; - - return probe_kernel_write((char *)addr, - arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); - } + int err = bfin_probe_kernel_read(saved_instr, (char *)addr, + BREAK_INSTR_SIZE); + if (err) + return err; + return bfin_probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr, + BREAK_INSTR_SIZE); } int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) { - if (IN_MEM(addr, BREAK_INSTR_SIZE, L1_CODE_START, L1_CODE_LENGTH)) { - /* access L1 instruction SRAM */ - if (dma_memcpy((void *)addr, bundle, BREAK_INSTR_SIZE) == NULL) - return -EFAULT; - - return 0; - } else - return probe_kernel_write((char *)addr, - (char *)bundle, BREAK_INSTR_SIZE); + return bfin_probe_kernel_write((char *)addr, bundle, BREAK_INSTR_SIZE); } int kgdb_arch_init(void) diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 3e1d86e456f6..79cad0ac5892 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -344,6 +344,87 @@ void finish_atomic_sections (struct pt_regs *regs) } } +static inline +int in_mem(unsigned long addr, unsigned long size, + unsigned long start, unsigned long end) +{ + return addr >= start && addr + size <= end; +} +static inline +int in_mem_const_off(unsigned long addr, unsigned long size, unsigned long off, + unsigned long const_addr, unsigned long const_size) +{ + return const_size && + in_mem(addr, size, const_addr + off, const_addr + const_size); +} +static inline +int in_mem_const(unsigned long addr, unsigned long size, + unsigned long const_addr, unsigned long const_size) +{ + return in_mem_const_off(addr, 0, size, const_addr, const_size); +} +#define IN_ASYNC(bnum, bctlnum) \ +({ \ + (bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? -EFAULT : \ + bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? -EFAULT : \ + BFIN_MEM_ACCESS_CORE; \ +}) + +int bfin_mem_access_type(unsigned long addr, unsigned long size) +{ + int cpu = raw_smp_processor_id(); + + /* Check that things do not wrap around */ + if (addr > ULONG_MAX - size) + return -EFAULT; + + if (in_mem(addr, size, FIXED_CODE_START, physical_mem_end)) + return BFIN_MEM_ACCESS_CORE; + + if (in_mem_const(addr, size, L1_CODE_START, L1_CODE_LENGTH)) + return cpu == 0 ? BFIN_MEM_ACCESS_ITEST : BFIN_MEM_ACCESS_IDMA; + if (in_mem_const(addr, size, L1_SCRATCH_START, L1_SCRATCH_LENGTH)) + return cpu == 0 ? BFIN_MEM_ACCESS_CORE_ONLY : -EFAULT; + if (in_mem_const(addr, size, L1_DATA_A_START, L1_DATA_A_LENGTH)) + return cpu == 0 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA; + if (in_mem_const(addr, size, L1_DATA_B_START, L1_DATA_B_LENGTH)) + return cpu == 0 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA; +#ifdef COREB_L1_CODE_START + if (in_mem_const(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH)) + return cpu == 1 ? BFIN_MEM_ACCESS_ITEST : BFIN_MEM_ACCESS_IDMA; + if (in_mem_const(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH)) + return cpu == 1 ? BFIN_MEM_ACCESS_CORE_ONLY : -EFAULT; + if (in_mem_const(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH)) + return cpu == 1 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA; + if (in_mem_const(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH)) + return cpu == 1 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA; +#endif + if (in_mem_const(addr, size, L2_START, L2_LENGTH)) + return BFIN_MEM_ACCESS_CORE; + + if (addr >= SYSMMR_BASE) + return BFIN_MEM_ACCESS_CORE_ONLY; + + /* We can't read EBIU banks that aren't enabled or we end up hanging + * on the access to the async space. + */ + if (in_mem_const(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK0_SIZE)) + return IN_ASYNC(0, 0); + if (in_mem_const(addr, size, ASYNC_BANK1_BASE, ASYNC_BANK1_SIZE)) + return IN_ASYNC(1, 0); + if (in_mem_const(addr, size, ASYNC_BANK2_BASE, ASYNC_BANK2_SIZE)) + return IN_ASYNC(2, 1); + if (in_mem_const(addr, size, ASYNC_BANK3_BASE, ASYNC_BANK3_SIZE)) + return IN_ASYNC(3, 1); + + if (in_mem_const(addr, size, BOOT_ROM_START, BOOT_ROM_LENGTH)) + return BFIN_MEM_ACCESS_CORE; + if (in_mem_const(addr, size, L1_ROM_START, L1_ROM_LENGTH)) + return BFIN_MEM_ACCESS_DMA; + + return -EFAULT; +} + #if defined(CONFIG_ACCESS_CHECK) #ifdef CONFIG_ACCESS_OK_L1 __attribute__((l1_text)) @@ -353,51 +434,61 @@ int _access_ok(unsigned long addr, unsigned long size) { if (size == 0) return 1; - if (addr > (addr + size)) + /* Check that things do not wrap around */ + if (addr > ULONG_MAX - size) return 0; if (segment_eq(get_fs(), KERNEL_DS)) return 1; #ifdef CONFIG_MTD_UCLINUX - if (addr >= memory_start && (addr + size) <= memory_end) - return 1; - if (addr >= memory_mtd_end && (addr + size) <= physical_mem_end) + if (1) +#else + if (0) +#endif + { + if (in_mem(addr, size, memory_start, memory_end)) + return 1; + if (in_mem(addr, size, memory_mtd_end, physical_mem_end)) + return 1; +# ifndef CONFIG_ROMFS_ON_MTD + if (0) +# endif + /* For XIP, allow user space to use pointers within the ROMFS. */ + if (in_mem(addr, size, memory_mtd_start, memory_mtd_end)) + return 1; + } else { + if (in_mem(addr, size, memory_start, physical_mem_end)) + return 1; + } + + if (in_mem(addr, size, (unsigned long)__init_begin, (unsigned long)__init_end)) return 1; -#ifdef CONFIG_ROMFS_ON_MTD - /* For XIP, allow user space to use pointers within the ROMFS. */ - if (addr >= memory_mtd_start && (addr + size) <= memory_mtd_end) + if (in_mem_const(addr, size, L1_CODE_START, L1_CODE_LENGTH)) return 1; -#endif -#else - if (addr >= memory_start && (addr + size) <= physical_mem_end) + if (in_mem_const_off(addr, size, _etext_l1 - _stext_l1, L1_CODE_START, L1_CODE_LENGTH)) return 1; -#endif - if (addr >= (unsigned long)__init_begin && - addr + size <= (unsigned long)__init_end) + if (in_mem_const_off(addr, size, _ebss_l1 - _sdata_l1, L1_DATA_A_START, L1_DATA_A_LENGTH)) return 1; - if (addr >= get_l1_scratch_start() - && addr + size <= get_l1_scratch_start() + L1_SCRATCH_LENGTH) + if (in_mem_const_off(addr, size, _ebss_b_l1 - _sdata_b_l1, L1_DATA_B_START, L1_DATA_B_LENGTH)) return 1; -#if L1_CODE_LENGTH != 0 - if (addr >= get_l1_code_start() + (_etext_l1 - _stext_l1) - && addr + size <= get_l1_code_start() + L1_CODE_LENGTH) +#ifdef COREB_L1_CODE_START + if (in_mem_const(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH)) return 1; -#endif -#if L1_DATA_A_LENGTH != 0 - if (addr >= get_l1_data_a_start() + (_ebss_l1 - _sdata_l1) - && addr + size <= get_l1_data_a_start() + L1_DATA_A_LENGTH) + if (in_mem_const(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH)) return 1; -#endif -#if L1_DATA_B_LENGTH != 0 - if (addr >= get_l1_data_b_start() + (_ebss_b_l1 - _sdata_b_l1) - && addr + size <= get_l1_data_b_start() + L1_DATA_B_LENGTH) + if (in_mem_const(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH)) return 1; -#endif -#if L2_LENGTH != 0 - if (addr >= L2_START + (_ebss_l2 - _stext_l2) - && addr + size <= L2_START + L2_LENGTH) + if (in_mem_const(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH)) return 1; #endif + if (in_mem_const_off(addr, size, _ebss_l2 - _stext_l2, L2_START, L2_LENGTH)) + return 1; + + if (in_mem_const(addr, size, BOOT_ROM_START, BOOT_ROM_LENGTH)) + return 1; + if (in_mem_const(addr, size, L1_ROM_START, L1_ROM_LENGTH)) + return 1; + return 0; } EXPORT_SYMBOL(_access_ok); diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index d279552fe9b0..8eeb457ce5d5 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -636,57 +637,30 @@ asmlinkage void trap_c(struct pt_regs *fp) */ static bool get_instruction(unsigned short *val, unsigned short *address) { - - unsigned long addr; - - addr = (unsigned long)address; + unsigned long addr = (unsigned long)address; /* Check for odd addresses */ if (addr & 0x1) return false; - /* Check that things do not wrap around */ - if (addr > (addr + 2)) + /* MMR region will never have instructions */ + if (addr >= SYSMMR_BASE) return false; - /* - * Since we are in exception context, we need to do a little address checking - * We need to make sure we are only accessing valid memory, and - * we don't read something in the async space that can hang forever - */ - if ((addr >= FIXED_CODE_START && (addr + 2) <= physical_mem_end) || -#if L2_LENGTH != 0 - (addr >= L2_START && (addr + 2) <= (L2_START + L2_LENGTH)) || -#endif - (addr >= BOOT_ROM_START && (addr + 2) <= (BOOT_ROM_START + BOOT_ROM_LENGTH)) || -#if L1_DATA_A_LENGTH != 0 - (addr >= L1_DATA_A_START && (addr + 2) <= (L1_DATA_A_START + L1_DATA_A_LENGTH)) || -#endif -#if L1_DATA_B_LENGTH != 0 - (addr >= L1_DATA_B_START && (addr + 2) <= (L1_DATA_B_START + L1_DATA_B_LENGTH)) || -#endif - (addr >= L1_SCRATCH_START && (addr + 2) <= (L1_SCRATCH_START + L1_SCRATCH_LENGTH)) || - (!(bfin_read_EBIU_AMBCTL0() & B0RDYEN) && - addr >= ASYNC_BANK0_BASE && (addr + 2) <= (ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)) || - (!(bfin_read_EBIU_AMBCTL0() & B1RDYEN) && - addr >= ASYNC_BANK1_BASE && (addr + 2) <= (ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)) || - (!(bfin_read_EBIU_AMBCTL1() & B2RDYEN) && - addr >= ASYNC_BANK2_BASE && (addr + 2) <= (ASYNC_BANK2_BASE + ASYNC_BANK1_SIZE)) || - (!(bfin_read_EBIU_AMBCTL1() & B3RDYEN) && - addr >= ASYNC_BANK3_BASE && (addr + 2) <= (ASYNC_BANK3_BASE + ASYNC_BANK1_SIZE))) { - *val = *address; - return true; + switch (bfin_mem_access_type(addr, 2)) { + case BFIN_MEM_ACCESS_CORE: + case BFIN_MEM_ACCESS_CORE_ONLY: + *val = *address; + return true; + case BFIN_MEM_ACCESS_DMA: + dma_memcpy(val, address, 2); + return true; + case BFIN_MEM_ACCESS_ITEST: + isram_memcpy(val, address, 2); + return true; + default: /* invalid access */ + return false; } - -#if L1_CODE_LENGTH != 0 - if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) { - isram_memcpy(val, address, 2); - return true; - } -#endif - - - return false; } /* -- cgit v1.2.3 From 26579216f3cdf1ae05f0af8412b444870a167510 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 15 Jun 2009 06:10:03 -0400 Subject: Blackfin: redo handling of bad irqs With the common IRQ code initializing much more of the irq_desc state, we can't blindly initialize it ourselves to the local bad_irq state. If we do, we end up wrongly clobbering many fields. So punt most of the bad irq code as the common layers will handle the default state, and simply call handle_bad_irq() directly when the IRQ we are processing is invalid. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/irqchip.c | 53 +++++++++--------------------------------- 1 file changed, 11 insertions(+), 42 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 6e31e935bb31..36bba3027735 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -38,38 +38,15 @@ #include static atomic_t irq_err_count; -static spinlock_t irq_controller_lock; - -/* - * Dummy mask/unmask handler - */ -void dummy_mask_unmask_irq(unsigned int irq) -{ -} - void ack_bad_irq(unsigned int irq) { atomic_inc(&irq_err_count); printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); } -static struct irq_chip bad_chip = { - .ack = dummy_mask_unmask_irq, - .mask = dummy_mask_unmask_irq, - .unmask = dummy_mask_unmask_irq, -}; - -static int bad_stats; static struct irq_desc bad_irq_desc = { - .status = IRQ_DISABLED, - .chip = &bad_chip, .handle_irq = handle_bad_irq, - .depth = 1, .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), - .kstat_irqs = &bad_stats, -#ifdef CONFIG_SMP - .affinity = CPU_MASK_ALL -#endif }; #ifdef CONFIG_CPUMASK_OFFSTACK @@ -119,21 +96,13 @@ __attribute__((l1_text)) #endif asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { - struct pt_regs *old_regs; - struct irq_desc *desc = irq_desc + irq; #ifndef CONFIG_IPIPE unsigned short pending, other_ints; #endif - old_regs = set_irq_regs(regs); - - /* - * Some hardware gives randomly wrong interrupts. Rather - * than crashing, do something sensible. - */ - if (irq >= NR_IRQS) - desc = &bad_irq_desc; + struct pt_regs *old_regs = set_irq_regs(regs); irq_enter(); + #ifdef CONFIG_DEBUG_STACKOVERFLOW /* Debugging check for stack overflow: is there less than STACK_WARN free? */ { @@ -149,7 +118,15 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) } } #endif - generic_handle_irq(irq); + + /* + * Some hardware gives randomly wrong interrupts. Rather + * than crashing, do something sensible. + */ + if (irq >= NR_IRQS) + handle_bad_irq(irq, &bad_irq_desc); + else + generic_handle_irq(irq); #ifndef CONFIG_IPIPE /* @@ -173,14 +150,6 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) void __init init_IRQ(void) { - struct irq_desc *desc; - int irq; - - spin_lock_init(&irq_controller_lock); - for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) { - *desc = bad_irq_desc; - } - init_arch_irq(); #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND -- cgit v1.2.3 From 46f288a0f983401ebadb918751d342cbf819cde5 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 15 Jun 2009 06:13:58 -0400 Subject: Blackfin: only build show_interrupts() when procfs is enabled Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/irqchip.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 36bba3027735..8abb642283b4 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -54,6 +54,7 @@ static struct irq_desc bad_irq_desc = { #error "Blackfin architecture does not support CONFIG_CPUMASK_OFFSTACK." #endif +#ifdef CONFIG_PROC_FS int show_interrupts(struct seq_file *p, void *v) { int i = *(loff_t *) v, j; @@ -85,6 +86,7 @@ int show_interrupts(struct seq_file *p, void *v) } return 0; } +#endif /* * do_IRQ handles all hardware IRQs. Decoded IRQs should not -- cgit v1.2.3 From 6f10fdabdce356aac3c948e659f39b6f1e2f7382 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 15 Jun 2009 06:18:38 -0400 Subject: Blackfin: simplify irq stack overflow checking Take a page from x86 and abstract the stack checking out of the asm_do_IRQ() function so that the result is easier to digest. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/irqchip.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 8abb642283b4..7378440792a4 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -88,6 +88,22 @@ int show_interrupts(struct seq_file *p, void *v) } #endif +#ifdef CONFIG_DEBUG_STACKOVERFLOW +static void check_stack_overflow(int irq) +{ + /* Debugging check for stack overflow: is there less than STACK_WARN free? */ + long sp = __get_SP() & (THREAD_SIZE - 1); + + if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { + dump_stack(); + pr_emerg("irq%i: possible stack overflow only %ld bytes free\n", + irq, sp - sizeof(struct thread_info)); + } +} +#else +static inline void check_stack_overflow(int irq) { } +#endif + /* * do_IRQ handles all hardware IRQs. Decoded IRQs should not * come via this function. Instead, they should provide their @@ -105,21 +121,7 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) irq_enter(); -#ifdef CONFIG_DEBUG_STACKOVERFLOW - /* Debugging check for stack overflow: is there less than STACK_WARN free? */ - { - long sp; - - sp = __get_SP() & (THREAD_SIZE-1); - - if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { - dump_stack(); - printk(KERN_EMERG "%s: possible stack overflow while handling irq %i " - " only %ld bytes free\n", - __func__, irq, sp - sizeof(struct thread_info)); - } - } -#endif + check_stack_overflow(irq); /* * Some hardware gives randomly wrong interrupts. Rather -- cgit v1.2.3 From 81b79c213d0200fdd16951a9fb18748fd511d810 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 15 Jun 2009 06:22:08 -0400 Subject: Blackfin: abstract irq14 lowering in do_irq Split out the optional IRQ14 lowering code to further simplify the asm_do_IRQ() function and keep the ifdef nest under control. Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/irqchip.c | 43 ++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 7378440792a4..4b5fd36187d9 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -104,6 +104,29 @@ static void check_stack_overflow(int irq) static inline void check_stack_overflow(int irq) { } #endif +#ifndef CONFIG_IPIPE +static void maybe_lower_to_irq14(void) +{ + unsigned short pending, other_ints; + + /* + * If we're the only interrupt running (ignoring IRQ15 which + * is for syscalls), lower our priority to IRQ14 so that + * softirqs run at that level. If there's another, + * lower-level interrupt, irq_exit will defer softirqs to + * that. If the interrupt pipeline is enabled, we are already + * running at IRQ14 priority, so we don't need this code. + */ + CSYNC(); + pending = bfin_read_IPEND() & ~0x8000; + other_ints = pending & (pending - 1); + if (other_ints == 0) + lower_to_irq14(); +} +#else +static inline void maybe_lower_to_irq14(void) { } +#endif + /* * do_IRQ handles all hardware IRQs. Decoded IRQs should not * come via this function. Instead, they should provide their @@ -114,9 +137,6 @@ __attribute__((l1_text)) #endif asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { -#ifndef CONFIG_IPIPE - unsigned short pending, other_ints; -#endif struct pt_regs *old_regs = set_irq_regs(regs); irq_enter(); @@ -132,21 +152,8 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) else generic_handle_irq(irq); -#ifndef CONFIG_IPIPE - /* - * If we're the only interrupt running (ignoring IRQ15 which - * is for syscalls), lower our priority to IRQ14 so that - * softirqs run at that level. If there's another, - * lower-level interrupt, irq_exit will defer softirqs to - * that. If the interrupt pipeline is enabled, we are already - * running at IRQ14 priority, so we don't need this code. - */ - CSYNC(); - pending = bfin_read_IPEND() & ~0x8000; - other_ints = pending & (pending - 1); - if (other_ints == 0) - lower_to_irq14(); -#endif /* !CONFIG_IPIPE */ + maybe_lower_to_irq14(); + irq_exit(); set_irq_regs(old_regs); -- cgit v1.2.3 From 0de4adfb8c9674fa1572b0ff1371acc94b0be901 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 15 Jun 2009 07:39:19 +0000 Subject: Blackfin: fix accidental reset in some boot modes We read the SWRST (Software Reset) register to get at the last reset state, and then we may configure the DOUBLE_FAULT bit to control behavior when a double fault occurs. But if the lower bits of the register is already set (like UART boot mode on a BF54x), we inadvertently make the system reset by writing to the SYSTEM_RESET field at the same time. So make sure the lower 4 bits are always cleared. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/setup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 6454babdfaff..b2782eae31e1 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -837,7 +837,8 @@ void __init setup_arch(char **cmdline_p) defined(CONFIG_BF538) || defined(CONFIG_BF539) _bfin_swrst = bfin_read_SWRST(); #else - _bfin_swrst = bfin_read_SYSCR(); + /* Clear boot mode field */ + _bfin_swrst = bfin_read_SYSCR() & ~0xf; #endif #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT -- cgit v1.2.3 From 06ecc190f3928850cb77c498f745fc8e9a7e2fd7 Mon Sep 17 00:00:00 2001 From: Philippe Gerum Date: Tue, 16 Jun 2009 05:25:37 +0200 Subject: Blackfin: convert interrupt pipeline to irqflags Signed-off-by: Philippe Gerum Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/ipipe_base.h | 30 +++--- arch/blackfin/include/asm/irq.h | 7 -- arch/blackfin/include/asm/irqflags.h | 164 +++++++++++++++++++++++++++++++-- arch/blackfin/include/asm/system.h | 4 +- arch/blackfin/kernel/ipipe.c | 2 +- 5 files changed, 177 insertions(+), 30 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/include/asm/ipipe_base.h b/arch/blackfin/include/asm/ipipe_base.h index 3e8acbd1a3be..490098f532a7 100644 --- a/arch/blackfin/include/asm/ipipe_base.h +++ b/arch/blackfin/include/asm/ipipe_base.h @@ -51,23 +51,23 @@ extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */ -static inline void __ipipe_stall_root(void) -{ - volatile unsigned long *p = &__ipipe_root_status; - set_bit(0, p); -} +#define __ipipe_stall_root() \ + do { \ + volatile unsigned long *p = &__ipipe_root_status; \ + set_bit(0, p); \ + } while (0) -static inline unsigned long __ipipe_test_and_stall_root(void) -{ - volatile unsigned long *p = &__ipipe_root_status; - return test_and_set_bit(0, p); -} +#define __ipipe_test_and_stall_root() \ + ({ \ + volatile unsigned long *p = &__ipipe_root_status; \ + test_and_set_bit(0, p); \ + }) -static inline unsigned long __ipipe_test_root(void) -{ - const unsigned long *p = &__ipipe_root_status; - return test_bit(0, p); -} +#define __ipipe_test_root() \ + ({ \ + const unsigned long *p = &__ipipe_root_status; \ + test_bit(0, p); \ + }) #endif /* !__ASSEMBLY__ */ diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h index 9a7f63a83c47..42a15f5ce0d0 100644 --- a/arch/blackfin/include/asm/irq.h +++ b/arch/blackfin/include/asm/irq.h @@ -22,13 +22,6 @@ /* SYS_IRQS and NR_IRQS are defined in */ #include -/* 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;" #else diff --git a/arch/blackfin/include/asm/irqflags.h b/arch/blackfin/include/asm/irqflags.h index 139cba4651b1..9b19a19d9ae9 100644 --- a/arch/blackfin/include/asm/irqflags.h +++ b/arch/blackfin/include/asm/irqflags.h @@ -31,6 +31,150 @@ static inline unsigned long bfin_cli(void) return flags; } +#ifdef CONFIG_IPIPE + +#include +#include + +#ifdef CONFIG_DEBUG_HWERR +# define bfin_no_irqs 0x3f +#else +# define bfin_no_irqs 0x1f +#endif + +#define raw_local_irq_disable() \ + do { \ + ipipe_check_context(ipipe_root_domain); \ + __ipipe_stall_root(); \ + barrier(); \ + } while (0) + +static inline void raw_local_irq_enable(void) +{ + barrier(); + ipipe_check_context(ipipe_root_domain); + __ipipe_unstall_root(); +} + +#define raw_local_save_flags_ptr(x) \ + do { \ + *(x) = __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags; \ + } while (0) + +#define raw_local_save_flags(x) raw_local_save_flags_ptr(&(x)) + +#define raw_irqs_disabled_flags(x) ((x) == bfin_no_irqs) + +#define raw_local_irq_save_ptr(x) \ + do { \ + *(x) = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags; \ + barrier(); \ + } while (0) + +#define raw_local_irq_save(x) \ + do { \ + ipipe_check_context(ipipe_root_domain); \ + raw_local_irq_save_ptr(&(x)); \ + } while (0) + +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; +} + +static inline void local_irq_disable_hw_notrace(void) +{ + bfin_cli(); +} + +static inline void local_irq_enable_hw_notrace(void) +{ + bfin_sti(bfin_irq_flags); +} + +#define local_save_flags_hw(flags) \ + do { \ + (flags) = bfin_read_IMASK(); \ + } while (0) + +#define irqs_disabled_flags_hw(flags) (((flags) & ~0x3f) == 0) + +#define irqs_disabled_hw() \ + ({ \ + unsigned long flags; \ + local_save_flags_hw(flags); \ + irqs_disabled_flags_hw(flags); \ + }) + +static inline void local_irq_save_ptr_hw(unsigned long *flags) +{ + *flags = bfin_cli(); +#ifdef CONFIG_DEBUG_HWERR + bfin_sti(0x3f); +#endif +} + +#define local_irq_save_hw_notrace(flags) \ + do { \ + local_irq_save_ptr_hw(&(flags)); \ + } while (0) + +static inline void local_irq_restore_hw_notrace(unsigned long flags) +{ + if (!irqs_disabled_flags_hw(flags)) + local_irq_enable_hw_notrace(); +} + +#ifdef CONFIG_IPIPE_TRACE_IRQSOFF +# define local_irq_disable_hw() \ + do { \ + if (!irqs_disabled_hw()) { \ + local_irq_disable_hw_notrace(); \ + ipipe_trace_begin(0x80000000); \ + } \ + } while (0) +# define local_irq_enable_hw() \ + do { \ + if (irqs_disabled_hw()) { \ + ipipe_trace_end(0x80000000); \ + local_irq_enable_hw_notrace(); \ + } \ + } while (0) +# define local_irq_save_hw(flags) \ + do { \ + local_save_flags_hw(flags); \ + if (!irqs_disabled_flags_hw(flags)) { \ + local_irq_disable_hw_notrace(); \ + ipipe_trace_begin(0x80000001); \ + } \ + } while (0) +# define local_irq_restore_hw(flags) \ + do { \ + if (!irqs_disabled_flags_hw(flags)) { \ + ipipe_trace_end(0x80000001); \ + local_irq_enable_hw_notrace(); \ + } \ + } while (0) +#else /* !CONFIG_IPIPE_TRACE_IRQSOFF */ +# define local_irq_disable_hw() local_irq_disable_hw_notrace() +# define local_irq_enable_hw() local_irq_enable_hw_notrace() +# define local_irq_save_hw(flags) local_irq_save_hw_notrace(flags) +# define local_irq_restore_hw(flags) local_irq_restore_hw_notrace(flags) +#endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */ + +#else /* CONFIG_IPIPE */ + static inline void raw_local_irq_disable(void) { bfin_cli(); @@ -44,12 +188,6 @@ static inline void raw_local_irq_enable(void) #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(); @@ -60,4 +198,18 @@ static inline unsigned long __raw_local_irq_save(void) } #define raw_local_irq_save(flags) do { (flags) = __raw_local_irq_save(); } while (0) +#define local_irq_save_hw(flags) raw_local_irq_save(flags) +#define local_irq_restore_hw(flags) raw_local_irq_restore(flags) +#define local_irq_enable_hw() raw_local_irq_enable() +#define local_irq_disable_hw() raw_local_irq_disable() +#define irqs_disabled_hw() irqs_disabled() + +#endif /* !CONFIG_IPIPE */ + +static inline void raw_local_irq_restore(unsigned long flags) +{ + if (!raw_irqs_disabled_flags(flags)) + raw_local_irq_enable(); +} + #endif diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h index 294dbda24164..85e8f16cf8c2 100644 --- a/arch/blackfin/include/asm/system.h +++ b/arch/blackfin/include/asm/system.h @@ -135,11 +135,13 @@ struct __xchg_dummy { }; #define __xg(x) ((volatile struct __xchg_dummy *)(x)) +#include + static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) { unsigned long tmp = 0; - unsigned long flags = 0; + unsigned long flags; local_irq_save_hw(flags); diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c index d8cde1fc5cb9..2b979edee140 100644 --- a/arch/blackfin/kernel/ipipe.c +++ b/arch/blackfin/kernel/ipipe.c @@ -52,7 +52,7 @@ EXPORT_SYMBOL(__ipipe_freq_scale); atomic_t __ipipe_irq_lvdepth[IVG15 + 1]; -unsigned long __ipipe_irq_lvmask = __all_masked_irq_flags; +unsigned long __ipipe_irq_lvmask = bfin_no_irqs; EXPORT_SYMBOL(__ipipe_irq_lvmask); static void __ipipe_ack_irq(unsigned irq, struct irq_desc *desc) -- cgit v1.2.3 From 5ba3b249c9e08100b0822f17276348b3447d6ee3 Mon Sep 17 00:00:00 2001 From: Philippe Gerum Date: Tue, 16 Jun 2009 05:25:50 +0200 Subject: Blackfin: remove obsolete mcount support from I-pipe code Signed-off-by: Philippe Gerum Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/Makefile | 1 - arch/blackfin/kernel/ipipe.c | 5 ---- arch/blackfin/kernel/mcount.S | 70 ------------------------------------------- 3 files changed, 76 deletions(-) delete mode 100644 arch/blackfin/kernel/mcount.S (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index 3731088e181b..141d9281e4b0 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -20,7 +20,6 @@ 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 obj-$(CONFIG_CPLB_INFO) += cplbinfo.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c index 2b979edee140..b8d22034b9a6 100644 --- a/arch/blackfin/kernel/ipipe.c +++ b/arch/blackfin/kernel/ipipe.c @@ -342,8 +342,3 @@ void ___ipipe_sync_pipeline(unsigned long syncmask) } EXPORT_SYMBOL(show_stack); - -#ifdef CONFIG_IPIPE_TRACE_MCOUNT -void notrace _mcount(void); -EXPORT_SYMBOL(_mcount); -#endif /* CONFIG_IPIPE_TRACE_MCOUNT */ diff --git a/arch/blackfin/kernel/mcount.S b/arch/blackfin/kernel/mcount.S deleted file mode 100644 index edcfb3865f46..000000000000 --- a/arch/blackfin/kernel/mcount.S +++ /dev/null @@ -1,70 +0,0 @@ -/* - * linux/arch/blackfin/mcount.S - * - * Copyright (C) 2006 Analog Devices Inc. - * - * 2007/04/12 Save index, length, modify and base registers. --rpm - */ - -#include -#include - -.text - -.align 4 /* just in case */ - -ENTRY(__mcount) - [--sp] = i0; - [--sp] = i1; - [--sp] = i2; - [--sp] = i3; - [--sp] = l0; - [--sp] = l1; - [--sp] = l2; - [--sp] = l3; - [--sp] = m0; - [--sp] = m1; - [--sp] = m2; - [--sp] = m3; - [--sp] = b0; - [--sp] = b1; - [--sp] = b2; - [--sp] = b3; - [--sp] = ( r7:0, p5:0 ); - [--sp] = ASTAT; - - p1.L = _ipipe_trace_enable; - p1.H = _ipipe_trace_enable; - r7 = [p1]; - CC = r7 == 0; - if CC jump out; - link 0x10; - r0 = 0x0; - [sp + 0xc] = r0; /* v */ - r0 = 0x0; /* type: IPIPE_TRACE_FN */ - r1 = rets; - p0 = [fp]; /* p0: Prior FP */ - r2 = [p0 + 4]; /* r2: Prior RETS */ - call ___ipipe_trace; - unlink; -out: - ASTAT = [sp++]; - ( r7:0, p5:0 ) = [sp++]; - b3 = [sp++]; - b2 = [sp++]; - b1 = [sp++]; - b0 = [sp++]; - m3 = [sp++]; - m2 = [sp++]; - m1 = [sp++]; - m0 = [sp++]; - l3 = [sp++]; - l2 = [sp++]; - l1 = [sp++]; - l0 = [sp++]; - i3 = [sp++]; - i2 = [sp++]; - i1 = [sp++]; - i0 = [sp++]; - rts; -ENDPROC(__mcount) -- cgit v1.2.3 From 41ba653f24a39a0e6a4afe9b2763a95a57e042c2 Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Tue, 16 Jun 2009 09:48:33 +0000 Subject: Blackfin: decouple unrelated cache settings to get exact behavior The current cache options don't really represent the hardware features. They end up setting different aspects of the hardware so that the end result is to turn on/off the cache. Unfortunately, when we hit cache problems with the hardware, it's difficult to test different settings to root cause the problem. The current settings also don't cleanly allow for different caching behaviors with different regions of memory. So split the configure options such that they properly reflect the settings that are applied to the hardware. Signed-off-by: Jie Zhang Signed-off-by: Mike Frysinger --- arch/blackfin/Kconfig | 57 +++++++++++++------ arch/blackfin/include/asm/cache.h | 4 +- arch/blackfin/include/asm/cacheflush.h | 10 ++-- arch/blackfin/include/asm/cplb.h | 32 ++++++----- arch/blackfin/kernel/cplb-mpu/cplbinit.c | 10 ++-- arch/blackfin/kernel/cplb-mpu/cplbmgr.c | 36 ++++++++---- arch/blackfin/kernel/setup.c | 96 ++++++++++++++++++++++++++------ arch/blackfin/mach-common/arch_checks.c | 4 +- arch/blackfin/mach-common/cpufreq.c | 2 +- arch/blackfin/mach-common/pm.c | 4 +- arch/blackfin/mm/init.c | 2 +- 11 files changed, 176 insertions(+), 81 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 8140a2fc8bbd..220635a1ebdd 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -907,23 +907,41 @@ endchoice comment "Cache Support" + config BFIN_ICACHE bool "Enable ICACHE" + default y +config BFIN_ICACHE_LOCK + bool "Enable Instruction Cache Locking" + depends on BFIN_ICACHE + default n +config BFIN_EXTMEM_ICACHEABLE + bool "Enable ICACHE for external memory" + depends on BFIN_ICACHE + default y +config BFIN_L2_ICACHEABLE + bool "Enable ICACHE for L2 SRAM" + depends on BFIN_ICACHE + depends on BF54x || BF561 + default n + config BFIN_DCACHE bool "Enable DCACHE" + default y config BFIN_DCACHE_BANKA bool "Enable only 16k BankA DCACHE - BankB is SRAM" depends on BFIN_DCACHE && !BF531 default n -config BFIN_ICACHE_LOCK - bool "Enable Instruction Cache Locking" - -choice - prompt "External memory cache policy" +config BFIN_EXTMEM_DCACHEABLE + bool "Enable DCACHE for external memory" depends on BFIN_DCACHE - default BFIN_WB if !SMP - default BFIN_WT if SMP -config BFIN_WB + default y +choice + prompt "External memory DCACHE policy" + depends on BFIN_EXTMEM_DCACHEABLE + default BFIN_EXTMEM_WRITEBACK if !SMP + default BFIN_EXTMEM_WRITETHROUGH if SMP +config BFIN_EXTMEM_WRITEBACK bool "Write back" depends on !SMP help @@ -941,7 +959,7 @@ config BFIN_WB If you are unsure of the options and you want to be safe, then go with Write Through. -config BFIN_WT +config BFIN_EXTMEM_WRITETHROUGH bool "Write through" help Write Back Policy: @@ -960,23 +978,26 @@ config BFIN_WT endchoice +config BFIN_L2_DCACHEABLE + bool "Enable DCACHE for L2 SRAM" + depends on BFIN_DCACHE + depends on BF54x || BF561 + default n choice - prompt "L2 SRAM cache policy" - depends on (BF54x || BF561) - default BFIN_L2_WT -config BFIN_L2_WB + prompt "L2 SRAM DCACHE policy" + depends on BFIN_L2_DCACHEABLE + default BFIN_L2_WRITEBACK +config BFIN_L2_WRITEBACK bool "Write back" depends on !SMP -config BFIN_L2_WT +config BFIN_L2_WRITETHROUGH bool "Write through" depends on !SMP - -config BFIN_L2_NOT_CACHED - bool "Not cached" - endchoice + +comment "Memory Protection Unit" config MPU bool "Enable the memory protection unit (EXPERIMENTAL)" default n diff --git a/arch/blackfin/include/asm/cache.h b/arch/blackfin/include/asm/cache.h index 2ef669ed9222..477050ad5c53 100644 --- a/arch/blackfin/include/asm/cache.h +++ b/arch/blackfin/include/asm/cache.h @@ -35,10 +35,10 @@ #if defined(CONFIG_SMP) && \ !defined(CONFIG_BFIN_CACHE_COHERENT) -# if defined(CONFIG_BFIN_ICACHE) +# if defined(CONFIG_BFIN_ICACHEABLE) || defined(CONFIG_BFIN_L2_ICACHEABLE) # define __ARCH_SYNC_CORE_ICACHE # endif -# if defined(CONFIG_BFIN_DCACHE) +# if defined(CONFIG_BFIN_DCACHEABLE) || defined(CONFIG_BFIN_L2_DCACHEABLE) # define __ARCH_SYNC_CORE_DCACHE # endif #ifndef __ASSEMBLY__ diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h index 5c17dee53b5d..7e55549e180f 100644 --- a/arch/blackfin/include/asm/cacheflush.h +++ b/arch/blackfin/include/asm/cacheflush.h @@ -56,7 +56,7 @@ extern void blackfin_invalidate_entire_icache(void); static inline void flush_icache_range(unsigned start, unsigned end) { -#if defined(CONFIG_BFIN_WB) +#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK) blackfin_dcache_flush_range(start, end); #endif @@ -87,9 +87,9 @@ do { memcpy(dst, src, len); \ #else # define invalidate_dcache_range(start,end) do { } while (0) #endif -#if defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_WB) +#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK) # define flush_dcache_range(start,end) blackfin_dcache_flush_range((start), (end)) -# define flush_dcache_page(page) blackfin_dflush_page(page_address(page)) +# define flush_dcache_page(page) blackfin_dflush_page(page_address(page)) #else # define flush_dcache_range(start,end) do { } while (0) # define flush_dcache_page(page) do { } while (0) @@ -100,7 +100,7 @@ extern unsigned long reserved_mem_icache_on; static inline int bfin_addr_dcacheable(unsigned long addr) { -#ifdef CONFIG_BFIN_DCACHE +#ifdef CONFIG_BFIN_EXTMEM_DCACHEABLE if (addr < (_ramend - DMA_UNCACHED_REGION)) return 1; #endif @@ -109,7 +109,7 @@ static inline int bfin_addr_dcacheable(unsigned long addr) addr >= _ramend && addr < physical_mem_end) return 1; -#ifndef CONFIG_BFIN_L2_NOT_CACHED +#ifdef CONFIG_BFIN_L2_DCACHEABLE if (addr >= L2_START && addr < L2_START + L2_LENGTH) return 1; #endif diff --git a/arch/blackfin/include/asm/cplb.h b/arch/blackfin/include/asm/cplb.h index a75a6a9f0949..c5dacf8f8cf9 100644 --- a/arch/blackfin/include/asm/cplb.h +++ b/arch/blackfin/include/asm/cplb.h @@ -37,8 +37,6 @@ #define L1_IMEMORY ( CPLB_USER_RD | CPLB_VALID | CPLB_LOCK) #define SDRAM_INON_CHBL ( CPLB_USER_RD | CPLB_VALID) -/*Use the menuconfig cache policy here - CONFIG_BFIN_WT/CONFIG_BFIN_WB*/ - #if ANOMALY_05000158 #define ANOMALY_05000158_WORKAROUND 0x200 #else @@ -47,10 +45,12 @@ #define CPLB_COMMON (CPLB_DIRTY | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND) -#ifdef CONFIG_BFIN_WB /*Write Back Policy */ +#ifdef CONFIG_BFIN_EXTMEM_WRITEBACK #define SDRAM_DGENERIC (CPLB_L1_CHBL | CPLB_COMMON) -#else /*Write Through */ +#elif defined(CONFIG_BFIN_EXTMEM_WRITETHROUGH) #define SDRAM_DGENERIC (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_COMMON) +#else +#define SDRAM_DGENERIC (CPLB_COMMON) #endif #define SDRAM_DNON_CHBL (CPLB_COMMON) @@ -61,21 +61,23 @@ #ifdef CONFIG_SMP #define L2_ATTR (INITIAL_T | I_CPLB | D_CPLB) -#define L2_IMEMORY (CPLB_COMMON) -#define L2_DMEMORY (CPLB_LOCK | CPLB_COMMON) +#define L2_IMEMORY (CPLB_COMMON | PAGE_SIZE_1MB) +#define L2_DMEMORY (CPLB_LOCK | CPLB_COMMON | PAGE_SIZE_1MB) #else #define L2_ATTR (INITIAL_T | SWITCH_T | I_CPLB | D_CPLB) -#define L2_IMEMORY (SDRAM_IGENERIC) - -# if defined(CONFIG_BFIN_L2_WB) -# define L2_DMEMORY (CPLB_L1_CHBL | CPLB_COMMON) -# elif defined(CONFIG_BFIN_L2_WT) -# define L2_DMEMORY (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_COMMON) -# elif defined(CONFIG_BFIN_L2_NOT_CACHED) -# define L2_DMEMORY (CPLB_COMMON) +# if defined(CONFIG_BFIN_L2_ICACHEABLE) +# define L2_IMEMORY (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | PAGE_SIZE_1MB) +# else +# define L2_IMEMORY ( CPLB_USER_RD | CPLB_VALID | PAGE_SIZE_1MB) +# endif + +# if defined(CONFIG_BFIN_L2_WRITEBACK) +# define L2_DMEMORY (CPLB_L1_CHBL | CPLB_COMMON | PAGE_SIZE_1MB) +# elif defined(CONFIG_BFIN_L2_WRITETHROUGH) +# define L2_DMEMORY (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_COMMON | PAGE_SIZE_1MB) # else -# define L2_DMEMORY (0) +# define L2_DMEMORY (CPLB_COMMON | PAGE_SIZE_1MB) # endif #endif /* CONFIG_SMP */ diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c index c006a44527bf..36193eed9a1f 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c @@ -46,13 +46,13 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) printk(KERN_INFO "MPU: setting up cplb tables with memory protection\n"); -#ifdef CONFIG_BFIN_ICACHE +#ifdef CONFIG_BFIN_EXTMEM_ICACHEABLE i_cache = CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; #endif -#ifdef CONFIG_BFIN_DCACHE +#ifdef CONFIG_BFIN_EXTMEM_DCACHEABLE d_cache = CPLB_L1_CHBL; -#ifdef CONFIG_BFIN_WT +#ifdef CONFIG_BFIN_EXTMEM_WRITETROUGH d_cache |= CPLB_L1_AOW | CPLB_WT; #endif #endif @@ -91,9 +91,9 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) /* Cover L2 memory */ #if L2_LENGTH > 0 dcplb_tbl[cpu][i_d].addr = L2_START; - dcplb_tbl[cpu][i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB; + dcplb_tbl[cpu][i_d++].data = L2_DMEMORY; icplb_tbl[cpu][i_i].addr = L2_START; - icplb_tbl[cpu][i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB; + icplb_tbl[cpu][i_i++].data = L2_IMEMORY; #endif first_mask_dcplb = i_d; diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c index 784923e52a9a..bcdfe9b0b71f 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c @@ -150,15 +150,19 @@ static noinline int dcplb_miss(unsigned int cpu) nr_dcplb_miss[cpu]++; d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; -#ifdef CONFIG_BFIN_DCACHE +#ifdef CONFIG_BFIN_EXTMEM_DCACHEABLE if (bfin_addr_dcacheable(addr)) { d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; -#ifdef CONFIG_BFIN_WT +# ifdef CONFIG_BFIN_EXTMEM_WRITETHROUGH d_data |= CPLB_L1_AOW | CPLB_WT; -#endif +# endif } #endif - if (addr >= physical_mem_end) { + + if (L2_LENGTH && addr >= L2_START && addr < L2_START + L2_LENGTH) { + addr = L2_START; + d_data = L2_DMEMORY; + } else if (addr >= physical_mem_end) { if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE && (status & FAULT_USERSUPV)) { addr &= ~0x3fffff; @@ -235,7 +239,7 @@ static noinline int icplb_miss(unsigned int cpu) i_data = CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4KB; -#ifdef CONFIG_BFIN_ICACHE +#ifdef CONFIG_BFIN_EXTMEM_ICACHEABLE /* * Normal RAM, and possibly the reserved memory area, are * cacheable. @@ -245,7 +249,10 @@ static noinline int icplb_miss(unsigned int cpu) i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; #endif - if (addr >= physical_mem_end) { + if (L2_LENGTH && addr >= L2_START && addr < L2_START + L2_LENGTH) { + addr = L2_START; + i_data = L2_IMEMORY; + } else if (addr >= physical_mem_end) { if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH && (status & FAULT_USERSUPV)) { addr &= ~(1 * 1024 * 1024 - 1); @@ -365,13 +372,18 @@ void set_mask_dcplbs(unsigned long *masks, unsigned int cpu) local_irq_save_hw(flags); current_rwx_mask[cpu] = masks; - d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; -#ifdef CONFIG_BFIN_DCACHE - d_data |= CPLB_L1_CHBL; -#ifdef CONFIG_BFIN_WT - d_data |= CPLB_L1_AOW | CPLB_WT; -#endif + if (L2_LENGTH && addr >= L2_START && addr < L2_START + L2_LENGTH) { + addr = L2_START; + d_data = L2_DMEMORY; + } else { + d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; +#ifdef CONFIG_BFIN_EXTMEM_DCACHEABLE + d_data |= CPLB_L1_CHBL; +# ifdef CONFIG_BFIN_EXTMEM_WRITETHROUGH + d_data |= CPLB_L1_AOW | CPLB_WT; +# endif #endif + } disable_dcplb(); for (i = first_mask_dcplb; i < first_switched_dcplb; i++) { diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index b2782eae31e1..8d7892820130 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -117,15 +117,49 @@ void __cpuinit bfin_setup_caches(unsigned int cpu) */ #ifdef CONFIG_BFIN_ICACHE printk(KERN_INFO "Instruction Cache Enabled for CPU%u\n", cpu); + printk(KERN_INFO " External memory:" +# ifdef CONFIG_BFIN_EXTMEM_ICACHEABLE + " cacheable" +# else + " uncacheable" +# endif + " in instruction cache\n"); + if (L2_LENGTH) + printk(KERN_INFO " L2 SRAM :" +# ifdef CONFIG_BFIN_L2_ICACHEABLE + " cacheable" +# else + " uncacheable" +# endif + " in instruction cache\n"); + +#else + printk(KERN_INFO "Instruction Cache Disabled for CPU%u\n", cpu); #endif + #ifdef CONFIG_BFIN_DCACHE - printk(KERN_INFO "Data Cache Enabled for CPU%u" -# if defined CONFIG_BFIN_WB - " (write-back)" -# elif defined CONFIG_BFIN_WT - " (write-through)" + printk(KERN_INFO "Data Cache Enabled for CPU%u\n", cpu); + printk(KERN_INFO " External memory:" +# if defined CONFIG_BFIN_EXTMEM_WRITEBACK + " cacheable (write-back)" +# elif defined CONFIG_BFIN_EXTMEM_WRITETHROUGH + " cacheable (write-through)" +# else + " uncacheable" +# endif + " in data cache\n"); + if (L2_LENGTH) + printk(KERN_INFO " L2 SRAM :" +# if defined CONFIG_BFIN_L2_WRITEBACK + " cacheable (write-back)" +# elif defined CONFIG_BFIN_L2_WRITETHROUGH + " cacheable (write-through)" +# else + " uncacheable" # endif - "\n", cpu); + " in data cache\n"); +#else + printk(KERN_INFO "Data Cache Disabled for CPU%u\n", cpu); #endif } @@ -516,7 +550,7 @@ static __init void memory_setup(void) && ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1) mtd_size = PAGE_ALIGN(be32_to_cpu(((unsigned long *)mtd_phys)[2])); -# if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263) +# if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263) /* Due to a Hardware Anomaly we need to limit the size of usable * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on * 05000263 - Hardware loop corrupted when taking an ICPLB exception @@ -544,7 +578,7 @@ static __init void memory_setup(void) dma_memcpy((void *)uclinux_ram_map.phys, _end, uclinux_ram_map.size); #endif /* CONFIG_MTD_UCLINUX */ -#if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263) +#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263) /* Due to a Hardware Anomaly we need to limit the size of usable * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on * 05000263 - Hardware loop corrupted when taking an ICPLB exception @@ -1158,16 +1192,25 @@ static int show_cpuinfo(struct seq_file *m, void *v) icache_size = 0; seq_printf(m, "cache size\t: %d KB(L1 icache) " - "%d KB(L1 dcache%s) %d KB(L2 cache)\n", - icache_size, dcache_size, -#if defined CONFIG_BFIN_WB - "-wb" -#elif defined CONFIG_BFIN_WT - "-wt" -#endif - "", 0); - + "%d KB(L1 dcache) %d KB(L2 cache)\n", + icache_size, dcache_size, 0); seq_printf(m, "%s\n", cache); + seq_printf(m, "external memory\t: " +#if defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) + "cacheable" +#else + "uncacheable" +#endif + " in instruction cache\n"); + seq_printf(m, "external memory\t: " +#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) + "cacheable (write-back)" +#elif defined(CONFIG_BFIN_EXTMEM_WRITETHROUGH) + "cacheable (write-through)" +#else + "uncacheable" +#endif + " in data cache\n"); if (icache_size) seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n", @@ -1240,8 +1283,25 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (cpu_num != num_possible_cpus() - 1) return 0; - if (L2_LENGTH) + if (L2_LENGTH) { seq_printf(m, "L2 SRAM\t\t: %dKB\n", L2_LENGTH/0x400); + seq_printf(m, "L2 SRAM\t\t: " +#if defined(CONFIG_BFIN_L2_ICACHEABLE) + "cacheable" +#else + "uncacheable" +#endif + " in instruction cache\n"); + seq_printf(m, "L2 SRAM\t\t: " +#if defined(CONFIG_BFIN_L2_WRITEBACK) + "cacheable (write-back)" +#elif defined(CONFIG_BFIN_L2_WRITETHROUGH) + "cacheable (write-through)" +#else + "uncacheable" +#endif + " in data cache\n"); + } seq_printf(m, "board name\t: %s\n", bfin_board_name); seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n", physical_mem_end >> 10, (void *)0, (void *)physical_mem_end); diff --git a/arch/blackfin/mach-common/arch_checks.c b/arch/blackfin/mach-common/arch_checks.c index da93d9207165..5998d8632a73 100644 --- a/arch/blackfin/mach-common/arch_checks.c +++ b/arch/blackfin/mach-common/arch_checks.c @@ -74,7 +74,7 @@ /* if 220 exists, can not set External Memory WB and L2 not_cached, either External Memory not_cached and L2 WB */ #if ANOMALY_05000220 && \ - ((defined(CONFIG_BFIN_WB) && defined(CONFIG_BFIN_L2_NOT_CACHED)) || \ - (!defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_L2_WB))) + ((defined(CONFIG_BFIN_EXTMEM_WRITEBACK) && !defined(CONFIG_BFIN_L2_DCACHEABLE)) || \ + (!defined(CONFIG_BFIN_EXTMEM_DCACHEABLE) && defined(CONFIG_BFIN_L2_WRITEBACK))) # error You are exposing Anomaly 220 in this config, either config L2 as Write Through, or make External Memory WB. #endif diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c index 70e3411f558c..85c658083279 100644 --- a/arch/blackfin/mach-common/cpufreq.c +++ b/arch/blackfin/mach-common/cpufreq.c @@ -141,7 +141,7 @@ static int __init __bfin_cpu_init(struct cpufreq_policy *policy) sclk = get_sclk() / 1000; #if ANOMALY_05000273 || ANOMALY_05000274 || \ - (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_DCACHE)) + (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE)) min_cclk = sclk * 2; #else min_cclk = sclk; diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index bce5a84be49f..9e7e27b7fc8d 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -132,7 +132,7 @@ int bf53x_resume_l1_mem(unsigned char *memptr) return 0; } -#ifdef CONFIG_BFIN_WB +#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK) static void flushinv_all_dcache(void) { u32 way, bank, subbank, set; @@ -175,7 +175,7 @@ static inline void dcache_disable(void) #ifdef CONFIG_BFIN_DCACHE unsigned long ctrl; -#ifdef CONFIG_BFIN_WB +#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK) flushinv_all_dcache(); #endif SSYNC(); diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c index 014a55abd09a..68bd0bd680cd 100644 --- a/arch/blackfin/mm/init.c +++ b/arch/blackfin/mm/init.c @@ -160,7 +160,7 @@ void __init mem_init(void) /* do not count in kernel image between _rambase and _ramstart */ reservedpages -= (_ramstart - _rambase) >> PAGE_SHIFT; -#if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263) +#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263) reservedpages += (_ramend - memory_end - DMA_UNCACHED_REGION) >> PAGE_SHIFT; #endif -- cgit v1.2.3 From bd854c077e660b5f44b5049219645042bcba61ac Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Thu, 18 Jun 2009 22:53:43 +0000 Subject: Blackfin: fix early crash when booting on wrong cpu Make sure we process the kernel command line before poking the hardware, so that we can process early printk. This helps ensure that if you boot a kernel configured for a different processor, something will be left in the log buffer. Signed-off-by: Robin Getz Signed-off-by: Mike Frysinger --- arch/blackfin/kernel/setup.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'arch/blackfin/kernel') diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 8d7892820130..298f023bcc09 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -477,9 +477,11 @@ static __init void parse_cmdline_early(char *cmdline_p) } else if (!memcmp(to, "clkin_hz=", 9)) { to += 9; early_init_clkin_hz(to); +#ifdef CONFIG_EARLY_PRINTK } else if (!memcmp(to, "earlyprintk=", 12)) { to += 12; setup_early_printk(to); +#endif } else if (!memcmp(to, "memmap=", 7)) { to += 7; parse_memmap(to); @@ -798,6 +800,11 @@ void __init setup_arch(char **cmdline_p) { unsigned long sclk, cclk; + /* Check to make sure we are running on the right processor */ + if (unlikely(CPUID != bfin_cpuid())) + printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n", + CPU, bfin_cpuid(), bfin_revid()); + #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif @@ -812,14 +819,17 @@ void __init setup_arch(char **cmdline_p) memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); boot_command_line[COMMAND_LINE_SIZE - 1] = '\0'; - /* setup memory defaults from the user config */ - physical_mem_end = 0; - _ramend = get_mem_size() * 1024 * 1024; - memset(&bfin_memmap, 0, sizeof(bfin_memmap)); + /* If the user does not specify things on the command line, use + * what the bootloader set things up as + */ + physical_mem_end = 0; parse_cmdline_early(&command_line[0]); + if (_ramend == 0) + _ramend = get_mem_size() * 1024 * 1024; + if (physical_mem_end == 0) physical_mem_end = _ramend; @@ -910,10 +920,7 @@ void __init setup_arch(char **cmdline_p) else printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid()); - if (unlikely(CPUID != bfin_cpuid())) - printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n", - CPU, bfin_cpuid(), bfin_revid()); - else { + if (likely(CPUID == bfin_cpuid())) { if (bfin_revid() != bfin_compiled_revid()) { if (bfin_compiled_revid() == -1) printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n", -- cgit v1.2.3