diff options
author | Graf Yang <graf.yang@analog.com> | 2008-11-18 04:48:22 -0500 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2008-11-18 04:48:22 -0500 |
commit | 8f65873e47784a390949f0d61e5692dbf2a8253e (patch) | |
tree | 4d9509bf5e52ebac190d79de04b783829d44f49e | |
parent | b8a989893cbdeb6c97a7b5af5f38fb0e480235f9 (diff) |
Blackfin arch: SMP supporting patchset: Blackfin kernel and memory management code
Blackfin dual core BF561 processor can support SMP like features.
https://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:smp-like
In this patch, we provide SMP extend to Blackfin kernel and memory management code
Singed-off-by: Graf Yang <graf.yang@analog.com>
Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
-rw-r--r-- | arch/blackfin/kernel/asm-offsets.c | 29 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_ksyms.c | 34 | ||||
-rw-r--r-- | arch/blackfin/kernel/entry.S | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/irqchip.c | 24 | ||||
-rw-r--r-- | arch/blackfin/kernel/kgdb.c | 4 | ||||
-rw-r--r-- | arch/blackfin/kernel/module.c | 13 | ||||
-rw-r--r-- | arch/blackfin/kernel/process.c | 23 | ||||
-rw-r--r-- | arch/blackfin/kernel/ptrace.c | 8 | ||||
-rw-r--r-- | arch/blackfin/kernel/reboot.c | 24 | ||||
-rw-r--r-- | arch/blackfin/kernel/setup.c | 163 | ||||
-rw-r--r-- | arch/blackfin/kernel/time.c | 114 | ||||
-rw-r--r-- | arch/blackfin/kernel/traps.c | 56 | ||||
-rw-r--r-- | arch/blackfin/mm/init.c | 60 | ||||
-rw-r--r-- | arch/blackfin/mm/sram-alloc.c | 336 |
14 files changed, 580 insertions, 309 deletions
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c index 9bb85dd5ccb3..b5df9459d6d5 100644 --- a/arch/blackfin/kernel/asm-offsets.c +++ b/arch/blackfin/kernel/asm-offsets.c | |||
@@ -56,6 +56,9 @@ int main(void) | |||
56 | /* offsets into the thread struct */ | 56 | /* offsets into the thread struct */ |
57 | DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); | 57 | DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); |
58 | DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); | 58 | DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); |
59 | DEFINE(THREAD_SR, offsetof(struct thread_struct, seqstat)); | ||
60 | DEFINE(PT_SR, offsetof(struct thread_struct, seqstat)); | ||
61 | DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); | ||
59 | DEFINE(THREAD_PC, offsetof(struct thread_struct, pc)); | 62 | DEFINE(THREAD_PC, offsetof(struct thread_struct, pc)); |
60 | DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE); | 63 | DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE); |
61 | 64 | ||
@@ -128,5 +131,31 @@ int main(void) | |||
128 | DEFINE(SIGSEGV, SIGSEGV); | 131 | DEFINE(SIGSEGV, SIGSEGV); |
129 | DEFINE(SIGTRAP, SIGTRAP); | 132 | DEFINE(SIGTRAP, SIGTRAP); |
130 | 133 | ||
134 | /* PDA management (in L1 scratchpad) */ | ||
135 | DEFINE(PDA_SYSCFG, offsetof(struct blackfin_pda, syscfg)); | ||
136 | #ifdef CONFIG_SMP | ||
137 | DEFINE(PDA_IRQFLAGS, offsetof(struct blackfin_pda, imask)); | ||
138 | #endif | ||
139 | DEFINE(PDA_IPDT, offsetof(struct blackfin_pda, ipdt)); | ||
140 | DEFINE(PDA_IPDT_SWAPCOUNT, offsetof(struct blackfin_pda, ipdt_swapcount)); | ||
141 | DEFINE(PDA_DPDT, offsetof(struct blackfin_pda, dpdt)); | ||
142 | DEFINE(PDA_DPDT_SWAPCOUNT, offsetof(struct blackfin_pda, dpdt_swapcount)); | ||
143 | DEFINE(PDA_EXIPTR, offsetof(struct blackfin_pda, ex_iptr)); | ||
144 | DEFINE(PDA_EXOPTR, offsetof(struct blackfin_pda, ex_optr)); | ||
145 | DEFINE(PDA_EXBUF, offsetof(struct blackfin_pda, ex_buf)); | ||
146 | DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask)); | ||
147 | DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack)); | ||
148 | #ifdef ANOMALY_05000261 | ||
149 | DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx)); | ||
150 | #endif | ||
151 | DEFINE(PDA_DCPLB, offsetof(struct blackfin_pda, dcplb_fault_addr)); | ||
152 | DEFINE(PDA_ICPLB, offsetof(struct blackfin_pda, icplb_fault_addr)); | ||
153 | DEFINE(PDA_RETX, offsetof(struct blackfin_pda, retx)); | ||
154 | DEFINE(PDA_SEQSTAT, offsetof(struct blackfin_pda, seqstat)); | ||
155 | #ifdef CONFIG_SMP | ||
156 | /* Inter-core lock (in L2 SRAM) */ | ||
157 | DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot)); | ||
158 | #endif | ||
159 | |||
131 | return 0; | 160 | return 0; |
132 | } | 161 | } |
diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c index b66f1d4c8344..763c31531e9e 100644 --- a/arch/blackfin/kernel/bfin_ksyms.c +++ b/arch/blackfin/kernel/bfin_ksyms.c | |||
@@ -68,3 +68,37 @@ EXPORT_SYMBOL(insw_8); | |||
68 | EXPORT_SYMBOL(outsl); | 68 | EXPORT_SYMBOL(outsl); |
69 | EXPORT_SYMBOL(insl); | 69 | EXPORT_SYMBOL(insl); |
70 | EXPORT_SYMBOL(insl_16); | 70 | EXPORT_SYMBOL(insl_16); |
71 | |||
72 | #ifdef CONFIG_SMP | ||
73 | EXPORT_SYMBOL(__raw_atomic_update_asm); | ||
74 | EXPORT_SYMBOL(__raw_atomic_clear_asm); | ||
75 | EXPORT_SYMBOL(__raw_atomic_set_asm); | ||
76 | EXPORT_SYMBOL(__raw_atomic_xor_asm); | ||
77 | EXPORT_SYMBOL(__raw_atomic_test_asm); | ||
78 | EXPORT_SYMBOL(__raw_xchg_1_asm); | ||
79 | EXPORT_SYMBOL(__raw_xchg_2_asm); | ||
80 | EXPORT_SYMBOL(__raw_xchg_4_asm); | ||
81 | EXPORT_SYMBOL(__raw_cmpxchg_1_asm); | ||
82 | EXPORT_SYMBOL(__raw_cmpxchg_2_asm); | ||
83 | EXPORT_SYMBOL(__raw_cmpxchg_4_asm); | ||
84 | EXPORT_SYMBOL(__raw_spin_is_locked_asm); | ||
85 | EXPORT_SYMBOL(__raw_spin_lock_asm); | ||
86 | EXPORT_SYMBOL(__raw_spin_trylock_asm); | ||
87 | EXPORT_SYMBOL(__raw_spin_unlock_asm); | ||
88 | EXPORT_SYMBOL(__raw_read_lock_asm); | ||
89 | EXPORT_SYMBOL(__raw_read_trylock_asm); | ||
90 | EXPORT_SYMBOL(__raw_read_unlock_asm); | ||
91 | EXPORT_SYMBOL(__raw_write_lock_asm); | ||
92 | EXPORT_SYMBOL(__raw_write_trylock_asm); | ||
93 | EXPORT_SYMBOL(__raw_write_unlock_asm); | ||
94 | EXPORT_SYMBOL(__raw_bit_set_asm); | ||
95 | EXPORT_SYMBOL(__raw_bit_clear_asm); | ||
96 | EXPORT_SYMBOL(__raw_bit_toggle_asm); | ||
97 | EXPORT_SYMBOL(__raw_bit_test_asm); | ||
98 | EXPORT_SYMBOL(__raw_bit_test_set_asm); | ||
99 | EXPORT_SYMBOL(__raw_bit_test_clear_asm); | ||
100 | EXPORT_SYMBOL(__raw_bit_test_toggle_asm); | ||
101 | EXPORT_SYMBOL(__raw_uncached_fetch_asm); | ||
102 | EXPORT_SYMBOL(__raw_smp_mark_barrier_asm); | ||
103 | EXPORT_SYMBOL(__raw_smp_check_barrier_asm); | ||
104 | #endif | ||
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S index faea88ebb2ef..c0c3fe811228 100644 --- a/arch/blackfin/kernel/entry.S +++ b/arch/blackfin/kernel/entry.S | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/linkage.h> | 30 | #include <linux/linkage.h> |
31 | #include <asm/thread_info.h> | 31 | #include <asm/thread_info.h> |
32 | #include <asm/errno.h> | 32 | #include <asm/errno.h> |
33 | #include <asm/blackfin.h> | ||
33 | #include <asm/asm-offsets.h> | 34 | #include <asm/asm-offsets.h> |
34 | 35 | ||
35 | #include <asm/context.S> | 36 | #include <asm/context.S> |
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 07402f57c9de..9eebb782fd30 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <linux/irq.h> | 36 | #include <linux/irq.h> |
37 | #include <asm/trace.h> | 37 | #include <asm/trace.h> |
38 | 38 | ||
39 | static unsigned long irq_err_count; | 39 | static atomic_t irq_err_count; |
40 | static spinlock_t irq_controller_lock; | 40 | static spinlock_t irq_controller_lock; |
41 | 41 | ||
42 | /* | 42 | /* |
@@ -48,7 +48,7 @@ void dummy_mask_unmask_irq(unsigned int irq) | |||
48 | 48 | ||
49 | void ack_bad_irq(unsigned int irq) | 49 | void ack_bad_irq(unsigned int irq) |
50 | { | 50 | { |
51 | irq_err_count += 1; | 51 | atomic_inc(&irq_err_count); |
52 | printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); | 52 | printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); |
53 | } | 53 | } |
54 | EXPORT_SYMBOL(ack_bad_irq); | 54 | EXPORT_SYMBOL(ack_bad_irq); |
@@ -72,7 +72,7 @@ static struct irq_desc bad_irq_desc = { | |||
72 | 72 | ||
73 | int show_interrupts(struct seq_file *p, void *v) | 73 | int show_interrupts(struct seq_file *p, void *v) |
74 | { | 74 | { |
75 | int i = *(loff_t *) v; | 75 | int i = *(loff_t *) v, j; |
76 | struct irqaction *action; | 76 | struct irqaction *action; |
77 | unsigned long flags; | 77 | unsigned long flags; |
78 | 78 | ||
@@ -80,19 +80,20 @@ int show_interrupts(struct seq_file *p, void *v) | |||
80 | spin_lock_irqsave(&irq_desc[i].lock, flags); | 80 | spin_lock_irqsave(&irq_desc[i].lock, flags); |
81 | action = irq_desc[i].action; | 81 | action = irq_desc[i].action; |
82 | if (!action) | 82 | if (!action) |
83 | goto unlock; | 83 | goto skip; |
84 | 84 | seq_printf(p, "%3d: ", i); | |
85 | seq_printf(p, "%3d: %10u ", i, kstat_irqs(i)); | 85 | for_each_online_cpu(j) |
86 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); | ||
87 | seq_printf(p, " %8s", irq_desc[i].chip->name); | ||
86 | seq_printf(p, " %s", action->name); | 88 | seq_printf(p, " %s", action->name); |
87 | for (action = action->next; action; action = action->next) | 89 | for (action = action->next; action; action = action->next) |
88 | seq_printf(p, ", %s", action->name); | 90 | seq_printf(p, " %s", action->name); |
89 | 91 | ||
90 | seq_putc(p, '\n'); | 92 | seq_putc(p, '\n'); |
91 | unlock: | 93 | skip: |
92 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); | 94 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); |
93 | } else if (i == NR_IRQS) { | 95 | } else if (i == NR_IRQS) |
94 | seq_printf(p, "Err: %10lu\n", irq_err_count); | 96 | seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count)); |
95 | } | ||
96 | return 0; | 97 | return 0; |
97 | } | 98 | } |
98 | 99 | ||
@@ -101,7 +102,6 @@ int show_interrupts(struct seq_file *p, void *v) | |||
101 | * come via this function. Instead, they should provide their | 102 | * come via this function. Instead, they should provide their |
102 | * own 'handler' | 103 | * own 'handler' |
103 | */ | 104 | */ |
104 | |||
105 | #ifdef CONFIG_DO_IRQ_L1 | 105 | #ifdef CONFIG_DO_IRQ_L1 |
106 | __attribute__((l1_text)) | 106 | __attribute__((l1_text)) |
107 | #endif | 107 | #endif |
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index b795a207742c..ab4022131a2a 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c | |||
@@ -363,12 +363,12 @@ void kgdb_passive_cpu_callback(void *info) | |||
363 | 363 | ||
364 | void kgdb_roundup_cpus(unsigned long flags) | 364 | void kgdb_roundup_cpus(unsigned long flags) |
365 | { | 365 | { |
366 | smp_call_function(kgdb_passive_cpu_callback, NULL, 0, 0); | 366 | smp_call_function(kgdb_passive_cpu_callback, NULL, 0); |
367 | } | 367 | } |
368 | 368 | ||
369 | void kgdb_roundup_cpu(int cpu, unsigned long flags) | 369 | void kgdb_roundup_cpu(int cpu, unsigned long flags) |
370 | { | 370 | { |
371 | smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0, 0); | 371 | smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0); |
372 | } | 372 | } |
373 | #endif | 373 | #endif |
374 | 374 | ||
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c index e1bebc80a5bf..2e14cadd4302 100644 --- a/arch/blackfin/kernel/module.c +++ b/arch/blackfin/kernel/module.c | |||
@@ -343,7 +343,13 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, | |||
343 | pr_debug("location is %x, value is %x type is %d \n", | 343 | pr_debug("location is %x, value is %x type is %d \n", |
344 | (unsigned int) location32, value, | 344 | (unsigned int) location32, value, |
345 | ELF32_R_TYPE(rel[i].r_info)); | 345 | ELF32_R_TYPE(rel[i].r_info)); |
346 | 346 | #ifdef CONFIG_SMP | |
347 | if ((unsigned long)location16 >= COREB_L1_DATA_A_START) { | ||
348 | printk(KERN_ERR "module %s: cannot relocate in L1: %u (SMP kernel)", | ||
349 | mod->name, ELF32_R_TYPE(rel[i].r_info)); | ||
350 | return -ENOEXEC; | ||
351 | } | ||
352 | #endif | ||
347 | switch (ELF32_R_TYPE(rel[i].r_info)) { | 353 | switch (ELF32_R_TYPE(rel[i].r_info)) { |
348 | 354 | ||
349 | case R_pcrel24: | 355 | case R_pcrel24: |
@@ -436,6 +442,7 @@ module_finalize(const Elf_Ehdr * hdr, | |||
436 | { | 442 | { |
437 | unsigned int i, strindex = 0, symindex = 0; | 443 | unsigned int i, strindex = 0, symindex = 0; |
438 | char *secstrings; | 444 | char *secstrings; |
445 | long err = 0; | ||
439 | 446 | ||
440 | secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | 447 | secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; |
441 | 448 | ||
@@ -460,8 +467,10 @@ module_finalize(const Elf_Ehdr * hdr, | |||
460 | (strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) || | 467 | (strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) || |
461 | ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) && | 468 | ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) && |
462 | (hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) { | 469 | (hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) { |
463 | apply_relocate_add((Elf_Shdr *) sechdrs, strtab, | 470 | err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab, |
464 | symindex, i, mod); | 471 | symindex, i, mod); |
472 | if (err < 0) | ||
473 | return -ENOEXEC; | ||
465 | } | 474 | } |
466 | } | 475 | } |
467 | return 0; | 476 | return 0; |
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 326e3019cd23..4359ea253010 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c | |||
@@ -171,6 +171,13 @@ asmlinkage int bfin_clone(struct pt_regs *regs) | |||
171 | unsigned long clone_flags; | 171 | unsigned long clone_flags; |
172 | unsigned long newsp; | 172 | unsigned long newsp; |
173 | 173 | ||
174 | #ifdef __ARCH_SYNC_CORE_DCACHE | ||
175 | if (current->rt.nr_cpus_allowed == num_possible_cpus()) { | ||
176 | current->cpus_allowed = cpumask_of_cpu(smp_processor_id()); | ||
177 | current->rt.nr_cpus_allowed = 1; | ||
178 | } | ||
179 | #endif | ||
180 | |||
174 | /* syscall2 puts clone_flags in r0 and usp in r1 */ | 181 | /* syscall2 puts clone_flags in r0 and usp in r1 */ |
175 | clone_flags = regs->r0; | 182 | clone_flags = regs->r0; |
176 | newsp = regs->r1; | 183 | newsp = regs->r1; |
@@ -338,22 +345,22 @@ int _access_ok(unsigned long addr, unsigned long size) | |||
338 | if (addr >= (unsigned long)__init_begin && | 345 | if (addr >= (unsigned long)__init_begin && |
339 | addr + size <= (unsigned long)__init_end) | 346 | addr + size <= (unsigned long)__init_end) |
340 | return 1; | 347 | return 1; |
341 | if (addr >= L1_SCRATCH_START | 348 | if (addr >= get_l1_scratch_start() |
342 | && addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH) | 349 | && addr + size <= get_l1_scratch_start() + L1_SCRATCH_LENGTH) |
343 | return 1; | 350 | return 1; |
344 | #if L1_CODE_LENGTH != 0 | 351 | #if L1_CODE_LENGTH != 0 |
345 | if (addr >= L1_CODE_START + (_etext_l1 - _stext_l1) | 352 | if (addr >= get_l1_code_start() + (_etext_l1 - _stext_l1) |
346 | && addr + size <= L1_CODE_START + L1_CODE_LENGTH) | 353 | && addr + size <= get_l1_code_start() + L1_CODE_LENGTH) |
347 | return 1; | 354 | return 1; |
348 | #endif | 355 | #endif |
349 | #if L1_DATA_A_LENGTH != 0 | 356 | #if L1_DATA_A_LENGTH != 0 |
350 | if (addr >= L1_DATA_A_START + (_ebss_l1 - _sdata_l1) | 357 | if (addr >= get_l1_data_a_start() + (_ebss_l1 - _sdata_l1) |
351 | && addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH) | 358 | && addr + size <= get_l1_data_a_start() + L1_DATA_A_LENGTH) |
352 | return 1; | 359 | return 1; |
353 | #endif | 360 | #endif |
354 | #if L1_DATA_B_LENGTH != 0 | 361 | #if L1_DATA_B_LENGTH != 0 |
355 | if (addr >= L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1) | 362 | if (addr >= get_l1_data_b_start() + (_ebss_b_l1 - _sdata_b_l1) |
356 | && addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH) | 363 | && addr + size <= get_l1_data_b_start() + L1_DATA_B_LENGTH) |
357 | return 1; | 364 | return 1; |
358 | #endif | 365 | #endif |
359 | #if L2_LENGTH != 0 | 366 | #if L2_LENGTH != 0 |
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 140bf00e9974..4de44f387dd5 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c | |||
@@ -220,8 +220,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
220 | break; | 220 | break; |
221 | pr_debug("ptrace: user address is valid\n"); | 221 | pr_debug("ptrace: user address is valid\n"); |
222 | 222 | ||
223 | if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START | 223 | if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start() |
224 | && addr + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) { | 224 | && addr + sizeof(tmp) <= get_l1_code_start() + L1_CODE_LENGTH) { |
225 | safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp)); | 225 | safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp)); |
226 | copied = sizeof(tmp); | 226 | copied = sizeof(tmp); |
227 | 227 | ||
@@ -300,8 +300,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
300 | break; | 300 | break; |
301 | pr_debug("ptrace: user address is valid\n"); | 301 | pr_debug("ptrace: user address is valid\n"); |
302 | 302 | ||
303 | if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START | 303 | if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start() |
304 | && addr + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) { | 304 | && addr + sizeof(data) <= get_l1_code_start() + L1_CODE_LENGTH) { |
305 | safe_dma_memcpy ((void *)(addr), &data, sizeof(data)); | 305 | safe_dma_memcpy ((void *)(addr), &data, sizeof(data)); |
306 | copied = sizeof(data); | 306 | copied = sizeof(data); |
307 | 307 | ||
diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index ae97ca407b0d..eeee8cb43360 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * the core reset. | 21 | * the core reset. |
22 | */ | 22 | */ |
23 | __attribute__((l1_text)) | 23 | __attribute__((l1_text)) |
24 | static void bfin_reset(void) | 24 | static void _bfin_reset(void) |
25 | { | 25 | { |
26 | /* Wait for completion of "system" events such as cache line | 26 | /* Wait for completion of "system" events such as cache line |
27 | * line fills so that we avoid infinite stalls later on as | 27 | * line fills so that we avoid infinite stalls later on as |
@@ -66,6 +66,18 @@ static void bfin_reset(void) | |||
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
69 | static void bfin_reset(void) | ||
70 | { | ||
71 | if (ANOMALY_05000353 || ANOMALY_05000386) | ||
72 | _bfin_reset(); | ||
73 | else | ||
74 | /* the bootrom checks to see how it was reset and will | ||
75 | * automatically perform a software reset for us when | ||
76 | * it starts executing boot | ||
77 | */ | ||
78 | asm("raise 1;"); | ||
79 | } | ||
80 | |||
69 | __attribute__((weak)) | 81 | __attribute__((weak)) |
70 | void native_machine_restart(char *cmd) | 82 | void native_machine_restart(char *cmd) |
71 | { | 83 | { |
@@ -75,14 +87,10 @@ void machine_restart(char *cmd) | |||
75 | { | 87 | { |
76 | native_machine_restart(cmd); | 88 | native_machine_restart(cmd); |
77 | local_irq_disable(); | 89 | local_irq_disable(); |
78 | if (ANOMALY_05000353 || ANOMALY_05000386) | 90 | if (smp_processor_id()) |
79 | bfin_reset(); | 91 | smp_call_function((void *)bfin_reset, 0, 1); |
80 | else | 92 | else |
81 | /* the bootrom checks to see how it was reset and will | 93 | bfin_reset(); |
82 | * automatically perform a software reset for us when | ||
83 | * it starts executing boot | ||
84 | */ | ||
85 | asm("raise 1;"); | ||
86 | } | 94 | } |
87 | 95 | ||
88 | __attribute__((weak)) | 96 | __attribute__((weak)) |
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 71a9a8c53cea..c644d234a02e 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c | |||
@@ -26,11 +26,10 @@ | |||
26 | #include <asm/blackfin.h> | 26 | #include <asm/blackfin.h> |
27 | #include <asm/cplbinit.h> | 27 | #include <asm/cplbinit.h> |
28 | #include <asm/div64.h> | 28 | #include <asm/div64.h> |
29 | #include <asm/cpu.h> | ||
29 | #include <asm/fixed_code.h> | 30 | #include <asm/fixed_code.h> |
30 | #include <asm/early_printk.h> | 31 | #include <asm/early_printk.h> |
31 | 32 | ||
32 | static DEFINE_PER_CPU(struct cpu, cpu_devices); | ||
33 | |||
34 | u16 _bfin_swrst; | 33 | u16 _bfin_swrst; |
35 | EXPORT_SYMBOL(_bfin_swrst); | 34 | EXPORT_SYMBOL(_bfin_swrst); |
36 | 35 | ||
@@ -79,29 +78,76 @@ static struct change_member *change_point[2*BFIN_MEMMAP_MAX] __initdata; | |||
79 | static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata; | 78 | static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata; |
80 | static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata; | 79 | static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata; |
81 | 80 | ||
82 | void __init bfin_cache_init(void) | 81 | DEFINE_PER_CPU(struct blackfin_cpudata, cpu_data); |
83 | { | 82 | |
84 | #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) | 83 | #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) |
85 | generate_cplb_tables(); | 84 | void __init generate_cplb_tables(void) |
85 | { | ||
86 | unsigned int cpu; | ||
87 | |||
88 | /* Generate per-CPU I&D CPLB tables */ | ||
89 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) | ||
90 | generate_cplb_tables_cpu(cpu); | ||
91 | } | ||
86 | #endif | 92 | #endif |
87 | 93 | ||
94 | void __cpuinit bfin_setup_caches(unsigned int cpu) | ||
95 | { | ||
88 | #ifdef CONFIG_BFIN_ICACHE | 96 | #ifdef CONFIG_BFIN_ICACHE |
89 | bfin_icache_init(); | 97 | #ifdef CONFIG_MPU |
90 | printk(KERN_INFO "Instruction Cache Enabled\n"); | 98 | bfin_icache_init(icplb_tbl[cpu]); |
99 | #else | ||
100 | bfin_icache_init(icplb_tables[cpu]); | ||
101 | #endif | ||
91 | #endif | 102 | #endif |
92 | 103 | ||
93 | #ifdef CONFIG_BFIN_DCACHE | 104 | #ifdef CONFIG_BFIN_DCACHE |
94 | bfin_dcache_init(); | 105 | #ifdef CONFIG_MPU |
95 | printk(KERN_INFO "Data Cache Enabled" | 106 | bfin_dcache_init(dcplb_tbl[cpu]); |
107 | #else | ||
108 | bfin_dcache_init(dcplb_tables[cpu]); | ||
109 | #endif | ||
110 | #endif | ||
111 | |||
112 | /* | ||
113 | * In cache coherence emulation mode, we need to have the | ||
114 | * D-cache enabled before running any atomic operation which | ||
115 | * might invove cache invalidation (i.e. spinlock, rwlock). | ||
116 | * So printk's are deferred until then. | ||
117 | */ | ||
118 | #ifdef CONFIG_BFIN_ICACHE | ||
119 | printk(KERN_INFO "Instruction Cache Enabled for CPU%u\n", cpu); | ||
120 | #endif | ||
121 | #ifdef CONFIG_BFIN_DCACHE | ||
122 | printk(KERN_INFO "Data Cache Enabled for CPU%u" | ||
96 | # if defined CONFIG_BFIN_WB | 123 | # if defined CONFIG_BFIN_WB |
97 | " (write-back)" | 124 | " (write-back)" |
98 | # elif defined CONFIG_BFIN_WT | 125 | # elif defined CONFIG_BFIN_WT |
99 | " (write-through)" | 126 | " (write-through)" |
100 | # endif | 127 | # endif |
101 | "\n"); | 128 | "\n", cpu); |
102 | #endif | 129 | #endif |
103 | } | 130 | } |
104 | 131 | ||
132 | void __cpuinit bfin_setup_cpudata(unsigned int cpu) | ||
133 | { | ||
134 | struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu); | ||
135 | |||
136 | cpudata->idle = current; | ||
137 | cpudata->loops_per_jiffy = loops_per_jiffy; | ||
138 | cpudata->cclk = get_cclk(); | ||
139 | cpudata->imemctl = bfin_read_IMEM_CONTROL(); | ||
140 | cpudata->dmemctl = bfin_read_DMEM_CONTROL(); | ||
141 | } | ||
142 | |||
143 | void __init bfin_cache_init(void) | ||
144 | { | ||
145 | #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) | ||
146 | generate_cplb_tables(); | ||
147 | #endif | ||
148 | bfin_setup_caches(0); | ||
149 | } | ||
150 | |||
105 | void __init bfin_relocate_l1_mem(void) | 151 | void __init bfin_relocate_l1_mem(void) |
106 | { | 152 | { |
107 | unsigned long l1_code_length; | 153 | unsigned long l1_code_length; |
@@ -230,7 +276,7 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map) | |||
230 | /* record all known change-points (starting and ending addresses), | 276 | /* record all known change-points (starting and ending addresses), |
231 | omitting those that are for empty memory regions */ | 277 | omitting those that are for empty memory regions */ |
232 | chgidx = 0; | 278 | chgidx = 0; |
233 | for (i = 0; i < old_nr; i++) { | 279 | for (i = 0; i < old_nr; i++) { |
234 | if (map[i].size != 0) { | 280 | if (map[i].size != 0) { |
235 | change_point[chgidx]->addr = map[i].addr; | 281 | change_point[chgidx]->addr = map[i].addr; |
236 | change_point[chgidx++]->pentry = &map[i]; | 282 | change_point[chgidx++]->pentry = &map[i]; |
@@ -238,13 +284,13 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map) | |||
238 | change_point[chgidx++]->pentry = &map[i]; | 284 | change_point[chgidx++]->pentry = &map[i]; |
239 | } | 285 | } |
240 | } | 286 | } |
241 | chg_nr = chgidx; /* true number of change-points */ | 287 | chg_nr = chgidx; /* true number of change-points */ |
242 | 288 | ||
243 | /* sort change-point list by memory addresses (low -> high) */ | 289 | /* sort change-point list by memory addresses (low -> high) */ |
244 | still_changing = 1; | 290 | still_changing = 1; |
245 | while (still_changing) { | 291 | while (still_changing) { |
246 | still_changing = 0; | 292 | still_changing = 0; |
247 | for (i = 1; i < chg_nr; i++) { | 293 | for (i = 1; i < chg_nr; i++) { |
248 | /* if <current_addr> > <last_addr>, swap */ | 294 | /* if <current_addr> > <last_addr>, swap */ |
249 | /* or, if current=<start_addr> & last=<end_addr>, swap */ | 295 | /* or, if current=<start_addr> & last=<end_addr>, swap */ |
250 | if ((change_point[i]->addr < change_point[i-1]->addr) || | 296 | if ((change_point[i]->addr < change_point[i-1]->addr) || |
@@ -261,10 +307,10 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map) | |||
261 | } | 307 | } |
262 | 308 | ||
263 | /* create a new memmap, removing overlaps */ | 309 | /* create a new memmap, removing overlaps */ |
264 | overlap_entries = 0; /* number of entries in the overlap table */ | 310 | overlap_entries = 0; /* number of entries in the overlap table */ |
265 | new_entry = 0; /* index for creating new memmap entries */ | 311 | new_entry = 0; /* index for creating new memmap entries */ |
266 | last_type = 0; /* start with undefined memory type */ | 312 | last_type = 0; /* start with undefined memory type */ |
267 | last_addr = 0; /* start with 0 as last starting address */ | 313 | last_addr = 0; /* start with 0 as last starting address */ |
268 | /* loop through change-points, determining affect on the new memmap */ | 314 | /* loop through change-points, determining affect on the new memmap */ |
269 | for (chgidx = 0; chgidx < chg_nr; chgidx++) { | 315 | for (chgidx = 0; chgidx < chg_nr; chgidx++) { |
270 | /* keep track of all overlapping memmap entries */ | 316 | /* keep track of all overlapping memmap entries */ |
@@ -286,14 +332,14 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map) | |||
286 | if (overlap_list[i]->type > current_type) | 332 | if (overlap_list[i]->type > current_type) |
287 | current_type = overlap_list[i]->type; | 333 | current_type = overlap_list[i]->type; |
288 | /* continue building up new memmap based on this information */ | 334 | /* continue building up new memmap based on this information */ |
289 | if (current_type != last_type) { | 335 | if (current_type != last_type) { |
290 | if (last_type != 0) { | 336 | if (last_type != 0) { |
291 | new_map[new_entry].size = | 337 | new_map[new_entry].size = |
292 | change_point[chgidx]->addr - last_addr; | 338 | change_point[chgidx]->addr - last_addr; |
293 | /* move forward only if the new size was non-zero */ | 339 | /* move forward only if the new size was non-zero */ |
294 | if (new_map[new_entry].size != 0) | 340 | if (new_map[new_entry].size != 0) |
295 | if (++new_entry >= BFIN_MEMMAP_MAX) | 341 | if (++new_entry >= BFIN_MEMMAP_MAX) |
296 | break; /* no more space left for new entries */ | 342 | break; /* no more space left for new entries */ |
297 | } | 343 | } |
298 | if (current_type != 0) { | 344 | if (current_type != 0) { |
299 | new_map[new_entry].addr = change_point[chgidx]->addr; | 345 | new_map[new_entry].addr = change_point[chgidx]->addr; |
@@ -303,9 +349,9 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map) | |||
303 | last_type = current_type; | 349 | last_type = current_type; |
304 | } | 350 | } |
305 | } | 351 | } |
306 | new_nr = new_entry; /* retain count for new entries */ | 352 | new_nr = new_entry; /* retain count for new entries */ |
307 | 353 | ||
308 | /* copy new mapping into original location */ | 354 | /* copy new mapping into original location */ |
309 | memcpy(map, new_map, new_nr*sizeof(struct bfin_memmap_entry)); | 355 | memcpy(map, new_map, new_nr*sizeof(struct bfin_memmap_entry)); |
310 | *pnr_map = new_nr; | 356 | *pnr_map = new_nr; |
311 | 357 | ||
@@ -361,7 +407,6 @@ static __init int parse_memmap(char *arg) | |||
361 | * - "memmap=XXX[KkmM][@][$]XXX[KkmM]" defines a memory region | 407 | * - "memmap=XXX[KkmM][@][$]XXX[KkmM]" defines a memory region |
362 | * @ from <start> to <start>+<mem>, type RAM | 408 | * @ from <start> to <start>+<mem>, type RAM |
363 | * $ from <start> to <start>+<mem>, type RESERVED | 409 | * $ from <start> to <start>+<mem>, type RESERVED |
364 | * | ||
365 | */ | 410 | */ |
366 | static __init void parse_cmdline_early(char *cmdline_p) | 411 | static __init void parse_cmdline_early(char *cmdline_p) |
367 | { | 412 | { |
@@ -383,12 +428,10 @@ static __init void parse_cmdline_early(char *cmdline_p) | |||
383 | if (*to != ' ') { | 428 | if (*to != ' ') { |
384 | if (*to == '$' | 429 | if (*to == '$' |
385 | || *(to + 1) == '$') | 430 | || *(to + 1) == '$') |
386 | reserved_mem_dcache_on = | 431 | reserved_mem_dcache_on = 1; |
387 | 1; | ||
388 | if (*to == '#' | 432 | if (*to == '#' |
389 | || *(to + 1) == '#') | 433 | || *(to + 1) == '#') |
390 | reserved_mem_icache_on = | 434 | reserved_mem_icache_on = 1; |
391 | 1; | ||
392 | } | 435 | } |
393 | } | 436 | } |
394 | } else if (!memcmp(to, "earlyprintk=", 12)) { | 437 | } else if (!memcmp(to, "earlyprintk=", 12)) { |
@@ -417,9 +460,8 @@ static __init void parse_cmdline_early(char *cmdline_p) | |||
417 | * [_ramend - DMA_UNCACHED_REGION, | 460 | * [_ramend - DMA_UNCACHED_REGION, |
418 | * _ramend]: uncached DMA region | 461 | * _ramend]: uncached DMA region |
419 | * [_ramend, physical_mem_end]: memory not managed by kernel | 462 | * [_ramend, physical_mem_end]: memory not managed by kernel |
420 | * | ||
421 | */ | 463 | */ |
422 | static __init void memory_setup(void) | 464 | static __init void memory_setup(void) |
423 | { | 465 | { |
424 | #ifdef CONFIG_MTD_UCLINUX | 466 | #ifdef CONFIG_MTD_UCLINUX |
425 | unsigned long mtd_phys = 0; | 467 | unsigned long mtd_phys = 0; |
@@ -436,7 +478,7 @@ static __init void memory_setup(void) | |||
436 | memory_end = _ramend - DMA_UNCACHED_REGION; | 478 | memory_end = _ramend - DMA_UNCACHED_REGION; |
437 | 479 | ||
438 | #ifdef CONFIG_MPU | 480 | #ifdef CONFIG_MPU |
439 | /* Round up to multiple of 4MB. */ | 481 | /* Round up to multiple of 4MB */ |
440 | memory_start = (_ramstart + 0x3fffff) & ~0x3fffff; | 482 | memory_start = (_ramstart + 0x3fffff) & ~0x3fffff; |
441 | #else | 483 | #else |
442 | memory_start = PAGE_ALIGN(_ramstart); | 484 | memory_start = PAGE_ALIGN(_ramstart); |
@@ -616,7 +658,7 @@ static __init void setup_bootmem_allocator(void) | |||
616 | end_pfn = memory_end >> PAGE_SHIFT; | 658 | end_pfn = memory_end >> PAGE_SHIFT; |
617 | 659 | ||
618 | /* | 660 | /* |
619 | * give all the memory to the bootmap allocator, tell it to put the | 661 | * give all the memory to the bootmap allocator, tell it to put the |
620 | * boot mem_map at the start of memory. | 662 | * boot mem_map at the start of memory. |
621 | */ | 663 | */ |
622 | bootmap_size = init_bootmem_node(NODE_DATA(0), | 664 | bootmap_size = init_bootmem_node(NODE_DATA(0), |
@@ -791,7 +833,11 @@ void __init setup_arch(char **cmdline_p) | |||
791 | bfin_write_SWRST(_bfin_swrst | DOUBLE_FAULT); | 833 | bfin_write_SWRST(_bfin_swrst | DOUBLE_FAULT); |
792 | #endif | 834 | #endif |
793 | 835 | ||
836 | #ifdef CONFIG_SMP | ||
837 | if (_bfin_swrst & SWRST_DBL_FAULT_A) { | ||
838 | #else | ||
794 | if (_bfin_swrst & RESET_DOUBLE) { | 839 | if (_bfin_swrst & RESET_DOUBLE) { |
840 | #endif | ||
795 | printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n"); | 841 | printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n"); |
796 | #ifdef CONFIG_DEBUG_DOUBLEFAULT | 842 | #ifdef CONFIG_DEBUG_DOUBLEFAULT |
797 | /* We assume the crashing kernel, and the current symbol table match */ | 843 | /* We assume the crashing kernel, and the current symbol table match */ |
@@ -835,7 +881,7 @@ void __init setup_arch(char **cmdline_p) | |||
835 | printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); | 881 | printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); |
836 | 882 | ||
837 | printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", | 883 | printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", |
838 | cclk / 1000000, sclk / 1000000); | 884 | cclk / 1000000, sclk / 1000000); |
839 | 885 | ||
840 | if (ANOMALY_05000273 && (cclk >> 1) <= sclk) | 886 | if (ANOMALY_05000273 && (cclk >> 1) <= sclk) |
841 | printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n"); | 887 | printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n"); |
@@ -867,18 +913,21 @@ void __init setup_arch(char **cmdline_p) | |||
867 | BUG_ON((char *)&safe_user_instruction - (char *)&fixed_code_start | 913 | BUG_ON((char *)&safe_user_instruction - (char *)&fixed_code_start |
868 | != SAFE_USER_INSTRUCTION - FIXED_CODE_START); | 914 | != SAFE_USER_INSTRUCTION - FIXED_CODE_START); |
869 | 915 | ||
916 | #ifdef CONFIG_SMP | ||
917 | platform_init_cpus(); | ||
918 | #endif | ||
870 | init_exception_vectors(); | 919 | init_exception_vectors(); |
871 | bfin_cache_init(); | 920 | bfin_cache_init(); /* Initialize caches for the boot CPU */ |
872 | } | 921 | } |
873 | 922 | ||
874 | static int __init topology_init(void) | 923 | static int __init topology_init(void) |
875 | { | 924 | { |
876 | int cpu; | 925 | unsigned int cpu; |
926 | /* Record CPU-private information for the boot processor. */ | ||
927 | bfin_setup_cpudata(0); | ||
877 | 928 | ||
878 | for_each_possible_cpu(cpu) { | 929 | for_each_possible_cpu(cpu) { |
879 | struct cpu *c = &per_cpu(cpu_devices, cpu); | 930 | register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu); |
880 | |||
881 | register_cpu(c, cpu); | ||
882 | } | 931 | } |
883 | 932 | ||
884 | return 0; | 933 | return 0; |
@@ -983,15 +1032,15 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
983 | char *cpu, *mmu, *fpu, *vendor, *cache; | 1032 | char *cpu, *mmu, *fpu, *vendor, *cache; |
984 | uint32_t revid; | 1033 | uint32_t revid; |
985 | 1034 | ||
986 | u_long cclk = 0, sclk = 0; | 1035 | u_long sclk = 0; |
987 | u_int icache_size = BFIN_ICACHESIZE / 1024, dcache_size = 0, dsup_banks = 0; | 1036 | u_int icache_size = BFIN_ICACHESIZE / 1024, dcache_size = 0, dsup_banks = 0; |
1037 | struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, *(unsigned int *)v); | ||
988 | 1038 | ||
989 | cpu = CPU; | 1039 | cpu = CPU; |
990 | mmu = "none"; | 1040 | mmu = "none"; |
991 | fpu = "none"; | 1041 | fpu = "none"; |
992 | revid = bfin_revid(); | 1042 | revid = bfin_revid(); |
993 | 1043 | ||
994 | cclk = get_cclk(); | ||
995 | sclk = get_sclk(); | 1044 | sclk = get_sclk(); |
996 | 1045 | ||
997 | switch (bfin_read_CHIPID() & CHIPID_MANUFACTURE) { | 1046 | switch (bfin_read_CHIPID() & CHIPID_MANUFACTURE) { |
@@ -1003,10 +1052,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1003 | break; | 1052 | break; |
1004 | } | 1053 | } |
1005 | 1054 | ||
1006 | seq_printf(m, "processor\t: %d\n" | 1055 | seq_printf(m, "processor\t: %d\n" "vendor_id\t: %s\n", |
1007 | "vendor_id\t: %s\n", | 1056 | *(unsigned int *)v, vendor); |
1008 | *(unsigned int *)v, | ||
1009 | vendor); | ||
1010 | 1057 | ||
1011 | if (CPUID == bfin_cpuid()) | 1058 | if (CPUID == bfin_cpuid()) |
1012 | seq_printf(m, "cpu family\t: 0x%04x\n", CPUID); | 1059 | seq_printf(m, "cpu family\t: 0x%04x\n", CPUID); |
@@ -1016,7 +1063,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1016 | 1063 | ||
1017 | seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" | 1064 | seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" |
1018 | "stepping\t: %d\n", | 1065 | "stepping\t: %d\n", |
1019 | cpu, cclk/1000000, sclk/1000000, | 1066 | cpu, cpudata->cclk/1000000, sclk/1000000, |
1020 | #ifdef CONFIG_MPU | 1067 | #ifdef CONFIG_MPU |
1021 | "mpu on", | 1068 | "mpu on", |
1022 | #else | 1069 | #else |
@@ -1025,16 +1072,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1025 | revid); | 1072 | revid); |
1026 | 1073 | ||
1027 | seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", | 1074 | seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", |
1028 | cclk/1000000, cclk%1000000, | 1075 | cpudata->cclk/1000000, cpudata->cclk%1000000, |
1029 | sclk/1000000, sclk%1000000); | 1076 | sclk/1000000, sclk%1000000); |
1030 | seq_printf(m, "bogomips\t: %lu.%02lu\n" | 1077 | seq_printf(m, "bogomips\t: %lu.%02lu\n" |
1031 | "Calibration\t: %lu loops\n", | 1078 | "Calibration\t: %lu loops\n", |
1032 | (loops_per_jiffy * HZ) / 500000, | 1079 | (cpudata->loops_per_jiffy * HZ) / 500000, |
1033 | ((loops_per_jiffy * HZ) / 5000) % 100, | 1080 | ((cpudata->loops_per_jiffy * HZ) / 5000) % 100, |
1034 | (loops_per_jiffy * HZ)); | 1081 | (cpudata->loops_per_jiffy * HZ)); |
1035 | 1082 | ||
1036 | /* Check Cache configutation */ | 1083 | /* Check Cache configutation */ |
1037 | switch (bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) { | 1084 | switch (cpudata->dmemctl & (1 << DMC0_P | 1 << DMC1_P)) { |
1038 | case ACACHE_BSRAM: | 1085 | case ACACHE_BSRAM: |
1039 | cache = "dbank-A/B\t: cache/sram"; | 1086 | cache = "dbank-A/B\t: cache/sram"; |
1040 | dcache_size = 16; | 1087 | dcache_size = 16; |
@@ -1058,10 +1105,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1058 | } | 1105 | } |
1059 | 1106 | ||
1060 | /* Is it turned on? */ | 1107 | /* Is it turned on? */ |
1061 | if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE)) | 1108 | if ((cpudata->dmemctl & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE)) |
1062 | dcache_size = 0; | 1109 | dcache_size = 0; |
1063 | 1110 | ||
1064 | if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) != (IMC | ENICPLB)) | 1111 | if ((cpudata->imemctl & (IMC | ENICPLB)) != (IMC | ENICPLB)) |
1065 | icache_size = 0; | 1112 | icache_size = 0; |
1066 | 1113 | ||
1067 | seq_printf(m, "cache size\t: %d KB(L1 icache) " | 1114 | seq_printf(m, "cache size\t: %d KB(L1 icache) " |
@@ -1086,8 +1133,13 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1086 | "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n", | 1133 | "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n", |
1087 | dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS, | 1134 | dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS, |
1088 | BFIN_DLINES); | 1135 | BFIN_DLINES); |
1136 | #ifdef __ARCH_SYNC_CORE_DCACHE | ||
1137 | seq_printf(m, | ||
1138 | "SMP Dcache Flushes\t: %lu\n\n", | ||
1139 | per_cpu(cpu_data, *(unsigned int *)v).dcache_invld_count); | ||
1140 | #endif | ||
1089 | #ifdef CONFIG_BFIN_ICACHE_LOCK | 1141 | #ifdef CONFIG_BFIN_ICACHE_LOCK |
1090 | switch ((bfin_read_IMEM_CONTROL() >> 3) & WAYALL_L) { | 1142 | switch ((cpudata->imemctl >> 3) & WAYALL_L) { |
1091 | case WAY0_L: | 1143 | case WAY0_L: |
1092 | seq_printf(m, "Way0 Locked-Down\n"); | 1144 | seq_printf(m, "Way0 Locked-Down\n"); |
1093 | break; | 1145 | break; |
@@ -1137,6 +1189,12 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1137 | seq_printf(m, "No Ways are locked\n"); | 1189 | seq_printf(m, "No Ways are locked\n"); |
1138 | } | 1190 | } |
1139 | #endif | 1191 | #endif |
1192 | if (*(unsigned int *)v != NR_CPUS-1) | ||
1193 | return 0; | ||
1194 | |||
1195 | #if L2_LENGTH | ||
1196 | seq_printf(m, "L2 SRAM\t\t: %dKB\n", L2_LENGTH/0x400); | ||
1197 | #endif | ||
1140 | seq_printf(m, "board name\t: %s\n", bfin_board_name); | 1198 | seq_printf(m, "board name\t: %s\n", bfin_board_name); |
1141 | seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n", | 1199 | seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n", |
1142 | physical_mem_end >> 10, (void *)0, (void *)physical_mem_end); | 1200 | physical_mem_end >> 10, (void *)0, (void *)physical_mem_end); |
@@ -1144,6 +1202,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1144 | ((int)memory_end - (int)_stext) >> 10, | 1202 | ((int)memory_end - (int)_stext) >> 10, |
1145 | _stext, | 1203 | _stext, |
1146 | (void *)memory_end); | 1204 | (void *)memory_end); |
1205 | seq_printf(m, "\n"); | ||
1147 | 1206 | ||
1148 | return 0; | 1207 | return 0; |
1149 | } | 1208 | } |
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index eb2352320454..06de2ce67a9e 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c | |||
@@ -34,9 +34,11 @@ | |||
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/time.h> | 35 | #include <linux/time.h> |
36 | #include <linux/irq.h> | 36 | #include <linux/irq.h> |
37 | #include <linux/delay.h> | ||
37 | 38 | ||
38 | #include <asm/blackfin.h> | 39 | #include <asm/blackfin.h> |
39 | #include <asm/time.h> | 40 | #include <asm/time.h> |
41 | #include <asm/gptimers.h> | ||
40 | 42 | ||
41 | /* This is an NTP setting */ | 43 | /* This is an NTP setting */ |
42 | #define TICK_SIZE (tick_nsec / 1000) | 44 | #define TICK_SIZE (tick_nsec / 1000) |
@@ -46,11 +48,14 @@ static unsigned long gettimeoffset(void); | |||
46 | 48 | ||
47 | static struct irqaction bfin_timer_irq = { | 49 | static struct irqaction bfin_timer_irq = { |
48 | .name = "BFIN Timer Tick", | 50 | .name = "BFIN Timer Tick", |
51 | #ifdef CONFIG_IRQ_PER_CPU | ||
52 | .flags = IRQF_DISABLED | IRQF_PERCPU, | ||
53 | #else | ||
49 | .flags = IRQF_DISABLED | 54 | .flags = IRQF_DISABLED |
55 | #endif | ||
50 | }; | 56 | }; |
51 | 57 | ||
52 | static void | 58 | void setup_core_timer(void) |
53 | time_sched_init(irq_handler_t timer_routine) | ||
54 | { | 59 | { |
55 | u32 tcount; | 60 | u32 tcount; |
56 | 61 | ||
@@ -71,12 +76,41 @@ time_sched_init(irq_handler_t timer_routine) | |||
71 | CSYNC(); | 76 | CSYNC(); |
72 | 77 | ||
73 | bfin_write_TCNTL(7); | 78 | bfin_write_TCNTL(7); |
79 | } | ||
80 | |||
81 | #ifdef CONFIG_TICK_SOURCE_SYSTMR0 | ||
82 | void setup_system_timer0(void) | ||
83 | { | ||
84 | /* Power down the core timer, just to play safe. */ | ||
85 | bfin_write_TCNTL(0); | ||
86 | |||
87 | disable_gptimers(TIMER0bit); | ||
88 | set_gptimer_status(0, TIMER_STATUS_TRUN0); | ||
89 | while (get_gptimer_status(0) & TIMER_STATUS_TRUN0) | ||
90 | udelay(10); | ||
91 | |||
92 | set_gptimer_config(0, 0x59); /* IRQ enable, periodic, PWM_OUT, SCLKed, OUT PAD disabled */ | ||
93 | set_gptimer_period(TIMER0_id, get_sclk() / HZ); | ||
94 | set_gptimer_pwidth(TIMER0_id, 1); | ||
95 | SSYNC(); | ||
96 | enable_gptimers(TIMER0bit); | ||
97 | } | ||
98 | #endif | ||
74 | 99 | ||
100 | static void | ||
101 | time_sched_init(irqreturn_t(*timer_routine) (int, void *)) | ||
102 | { | ||
103 | #ifdef CONFIG_TICK_SOURCE_SYSTMR0 | ||
104 | setup_system_timer0(); | ||
105 | #else | ||
106 | setup_core_timer(); | ||
107 | #endif | ||
75 | bfin_timer_irq.handler = (irq_handler_t)timer_routine; | 108 | bfin_timer_irq.handler = (irq_handler_t)timer_routine; |
76 | /* call setup_irq instead of request_irq because request_irq calls | 109 | #ifdef CONFIG_TICK_SOURCE_SYSTMR0 |
77 | * kmalloc which has not been initialized yet | 110 | setup_irq(IRQ_TIMER0, &bfin_timer_irq); |
78 | */ | 111 | #else |
79 | setup_irq(IRQ_CORETMR, &bfin_timer_irq); | 112 | setup_irq(IRQ_CORETMR, &bfin_timer_irq); |
113 | #endif | ||
80 | } | 114 | } |
81 | 115 | ||
82 | /* | 116 | /* |
@@ -87,17 +121,23 @@ static unsigned long gettimeoffset(void) | |||
87 | unsigned long offset; | 121 | unsigned long offset; |
88 | unsigned long clocks_per_jiffy; | 122 | unsigned long clocks_per_jiffy; |
89 | 123 | ||
124 | #ifdef CONFIG_TICK_SOURCE_SYSTMR0 | ||
125 | clocks_per_jiffy = bfin_read_TIMER0_PERIOD(); | ||
126 | offset = bfin_read_TIMER0_COUNTER() / \ | ||
127 | (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); | ||
128 | |||
129 | if ((get_gptimer_status(0) & TIMER_STATUS_TIMIL0) && offset < (100000 / HZ / 2)) | ||
130 | offset += (USEC_PER_SEC / HZ); | ||
131 | #else | ||
90 | clocks_per_jiffy = bfin_read_TPERIOD(); | 132 | clocks_per_jiffy = bfin_read_TPERIOD(); |
91 | offset = | 133 | offset = (clocks_per_jiffy - bfin_read_TCOUNT()) / \ |
92 | (clocks_per_jiffy - | 134 | (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); |
93 | bfin_read_TCOUNT()) / (((clocks_per_jiffy + 1) * HZ) / | ||
94 | USEC_PER_SEC); | ||
95 | 135 | ||
96 | /* Check if we just wrapped the counters and maybe missed a tick */ | 136 | /* Check if we just wrapped the counters and maybe missed a tick */ |
97 | if ((bfin_read_ILAT() & (1 << IRQ_CORETMR)) | 137 | if ((bfin_read_ILAT() & (1 << IRQ_CORETMR)) |
98 | && (offset < (100000 / HZ / 2))) | 138 | && (offset < (100000 / HZ / 2))) |
99 | offset += (USEC_PER_SEC / HZ); | 139 | offset += (USEC_PER_SEC / HZ); |
100 | 140 | #endif | |
101 | return offset; | 141 | return offset; |
102 | } | 142 | } |
103 | 143 | ||
@@ -120,34 +160,38 @@ irqreturn_t timer_interrupt(int irq, void *dummy) | |||
120 | static long last_rtc_update; | 160 | static long last_rtc_update; |
121 | 161 | ||
122 | write_seqlock(&xtime_lock); | 162 | write_seqlock(&xtime_lock); |
123 | 163 | #ifdef CONFIG_TICK_SOURCE_SYSTMR0 | |
124 | do_timer(1); | 164 | if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) { |
125 | 165 | #endif | |
126 | profile_tick(CPU_PROFILING); | 166 | do_timer(1); |
127 | 167 | ||
128 | /* | 168 | |
129 | * If we have an externally synchronized Linux clock, then update | 169 | /* |
130 | * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be | 170 | * If we have an externally synchronized Linux clock, then update |
131 | * called as close as possible to 500 ms before the new second starts. | 171 | * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be |
132 | */ | 172 | * called as close as possible to 500 ms before the new second starts. |
133 | 173 | */ | |
134 | if (ntp_synced() && | 174 | |
135 | xtime.tv_sec > last_rtc_update + 660 && | 175 | if (ntp_synced() && |
136 | (xtime.tv_nsec / NSEC_PER_USEC) >= | 176 | xtime.tv_sec > last_rtc_update + 660 && |
137 | 500000 - ((unsigned)TICK_SIZE) / 2 | 177 | (xtime.tv_nsec / NSEC_PER_USEC) >= |
138 | && (xtime.tv_nsec / NSEC_PER_USEC) <= | 178 | 500000 - ((unsigned)TICK_SIZE) / 2 |
139 | 500000 + ((unsigned)TICK_SIZE) / 2) { | 179 | && (xtime.tv_nsec / NSEC_PER_USEC) <= |
140 | if (set_rtc_mmss(xtime.tv_sec) == 0) | 180 | 500000 + ((unsigned)TICK_SIZE) / 2) { |
141 | last_rtc_update = xtime.tv_sec; | 181 | if (set_rtc_mmss(xtime.tv_sec) == 0) |
142 | else | 182 | last_rtc_update = xtime.tv_sec; |
143 | /* Do it again in 60s. */ | 183 | else |
144 | last_rtc_update = xtime.tv_sec - 600; | 184 | /* Do it again in 60s. */ |
185 | last_rtc_update = xtime.tv_sec - 600; | ||
186 | } | ||
187 | #ifdef CONFIG_TICK_SOURCE_SYSTMR0 | ||
188 | set_gptimer_status(0, TIMER_STATUS_TIMIL0); | ||
145 | } | 189 | } |
190 | #endif | ||
146 | write_sequnlock(&xtime_lock); | 191 | write_sequnlock(&xtime_lock); |
147 | 192 | ||
148 | #ifndef CONFIG_SMP | ||
149 | update_process_times(user_mode(get_irq_regs())); | 193 | update_process_times(user_mode(get_irq_regs())); |
150 | #endif | 194 | profile_tick(CPU_PROFILING); |
151 | 195 | ||
152 | return IRQ_HANDLED; | 196 | return IRQ_HANDLED; |
153 | } | 197 | } |
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index bef025b07443..af7cc43630de 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -75,16 +75,6 @@ void __init trap_init(void) | |||
75 | CSYNC(); | 75 | CSYNC(); |
76 | } | 76 | } |
77 | 77 | ||
78 | /* | ||
79 | * Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR | ||
80 | * values across the transition from exception to IRQ5. | ||
81 | * We put these in L1, so they are going to be in a valid | ||
82 | * location during exception context | ||
83 | */ | ||
84 | __attribute__((l1_data)) | ||
85 | unsigned long saved_retx, saved_seqstat, | ||
86 | saved_icplb_fault_addr, saved_dcplb_fault_addr; | ||
87 | |||
88 | static void decode_address(char *buf, unsigned long address) | 78 | static void decode_address(char *buf, unsigned long address) |
89 | { | 79 | { |
90 | #ifdef CONFIG_DEBUG_VERBOSE | 80 | #ifdef CONFIG_DEBUG_VERBOSE |
@@ -211,18 +201,18 @@ asmlinkage void double_fault_c(struct pt_regs *fp) | |||
211 | printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); | 201 | printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); |
212 | #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT | 202 | #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT |
213 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { | 203 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { |
204 | unsigned int cpu = smp_processor_id(); | ||
214 | char buf[150]; | 205 | char buf[150]; |
215 | decode_address(buf, saved_retx); | 206 | decode_address(buf, cpu_pda[cpu].retx); |
216 | printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", | 207 | printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", |
217 | (int)saved_seqstat & SEQSTAT_EXCAUSE, buf); | 208 | (unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf); |
218 | decode_address(buf, saved_dcplb_fault_addr); | 209 | decode_address(buf, cpu_pda[cpu].dcplb_fault_addr); |
219 | printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); | 210 | printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); |
220 | decode_address(buf, saved_icplb_fault_addr); | 211 | decode_address(buf, cpu_pda[cpu].icplb_fault_addr); |
221 | printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); | 212 | printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); |
222 | 213 | ||
223 | decode_address(buf, fp->retx); | 214 | decode_address(buf, fp->retx); |
224 | printk(KERN_NOTICE "The instruction at %s caused a double exception\n", | 215 | printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf); |
225 | buf); | ||
226 | } else | 216 | } else |
227 | #endif | 217 | #endif |
228 | { | 218 | { |
@@ -240,6 +230,9 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
240 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON | 230 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON |
241 | int j; | 231 | int j; |
242 | #endif | 232 | #endif |
233 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | ||
234 | unsigned int cpu = smp_processor_id(); | ||
235 | #endif | ||
243 | int sig = 0; | 236 | int sig = 0; |
244 | siginfo_t info; | 237 | siginfo_t info; |
245 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; | 238 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; |
@@ -417,7 +410,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
417 | info.si_code = ILL_CPLB_MULHIT; | 410 | info.si_code = ILL_CPLB_MULHIT; |
418 | sig = SIGSEGV; | 411 | sig = SIGSEGV; |
419 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | 412 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
420 | if (saved_dcplb_fault_addr < FIXED_CODE_START) | 413 | if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START) |
421 | verbose_printk(KERN_NOTICE "NULL pointer access\n"); | 414 | verbose_printk(KERN_NOTICE "NULL pointer access\n"); |
422 | else | 415 | else |
423 | #endif | 416 | #endif |
@@ -471,7 +464,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
471 | info.si_code = ILL_CPLB_MULHIT; | 464 | info.si_code = ILL_CPLB_MULHIT; |
472 | sig = SIGSEGV; | 465 | sig = SIGSEGV; |
473 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | 466 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
474 | if (saved_icplb_fault_addr < FIXED_CODE_START) | 467 | if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START) |
475 | verbose_printk(KERN_NOTICE "Jump to NULL address\n"); | 468 | verbose_printk(KERN_NOTICE "Jump to NULL address\n"); |
476 | else | 469 | else |
477 | #endif | 470 | #endif |
@@ -960,6 +953,7 @@ void dump_bfin_process(struct pt_regs *fp) | |||
960 | else | 953 | else |
961 | verbose_printk(KERN_NOTICE "COMM= invalid\n"); | 954 | verbose_printk(KERN_NOTICE "COMM= invalid\n"); |
962 | 955 | ||
956 | printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu); | ||
963 | if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) | 957 | if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) |
964 | verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" | 958 | verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" |
965 | KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" | 959 | KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" |
@@ -1053,6 +1047,7 @@ void show_regs(struct pt_regs *fp) | |||
1053 | struct irqaction *action; | 1047 | struct irqaction *action; |
1054 | unsigned int i; | 1048 | unsigned int i; |
1055 | unsigned long flags; | 1049 | unsigned long flags; |
1050 | unsigned int cpu = smp_processor_id(); | ||
1056 | 1051 | ||
1057 | verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); | 1052 | verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); |
1058 | verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", | 1053 | verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", |
@@ -1112,9 +1107,9 @@ unlock: | |||
1112 | 1107 | ||
1113 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && | 1108 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && |
1114 | (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { | 1109 | (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { |
1115 | decode_address(buf, saved_dcplb_fault_addr); | 1110 | decode_address(buf, cpu_pda[cpu].dcplb_fault_addr); |
1116 | verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); | 1111 | verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); |
1117 | decode_address(buf, saved_icplb_fault_addr); | 1112 | decode_address(buf, cpu_pda[cpu].icplb_fault_addr); |
1118 | verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); | 1113 | verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); |
1119 | } | 1114 | } |
1120 | 1115 | ||
@@ -1153,20 +1148,21 @@ unlock: | |||
1153 | asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text)); | 1148 | asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text)); |
1154 | #endif | 1149 | #endif |
1155 | 1150 | ||
1156 | asmlinkage int sys_bfin_spinlock(int *spinlock) | 1151 | static DEFINE_SPINLOCK(bfin_spinlock_lock); |
1152 | |||
1153 | asmlinkage int sys_bfin_spinlock(int *p) | ||
1157 | { | 1154 | { |
1158 | int ret = 0; | 1155 | int ret, tmp = 0; |
1159 | int tmp = 0; | ||
1160 | 1156 | ||
1161 | local_irq_disable(); | 1157 | spin_lock(&bfin_spinlock_lock); /* This would also hold kernel preemption. */ |
1162 | ret = get_user(tmp, spinlock); | 1158 | ret = get_user(tmp, p); |
1163 | if (ret == 0) { | 1159 | if (likely(ret == 0)) { |
1164 | if (tmp) | 1160 | if (unlikely(tmp)) |
1165 | ret = 1; | 1161 | ret = 1; |
1166 | tmp = 1; | 1162 | else |
1167 | put_user(tmp, spinlock); | 1163 | put_user(1, p); |
1168 | } | 1164 | } |
1169 | local_irq_enable(); | 1165 | spin_unlock(&bfin_spinlock_lock); |
1170 | return ret; | 1166 | return ret; |
1171 | } | 1167 | } |
1172 | 1168 | ||
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c index bc240abb8745..57d306b9c56d 100644 --- a/arch/blackfin/mm/init.c +++ b/arch/blackfin/mm/init.c | |||
@@ -31,7 +31,8 @@ | |||
31 | #include <linux/bootmem.h> | 31 | #include <linux/bootmem.h> |
32 | #include <linux/uaccess.h> | 32 | #include <linux/uaccess.h> |
33 | #include <asm/bfin-global.h> | 33 | #include <asm/bfin-global.h> |
34 | #include <asm/l1layout.h> | 34 | #include <asm/pda.h> |
35 | #include <asm/cplbinit.h> | ||
35 | #include "blackfin_sram.h" | 36 | #include "blackfin_sram.h" |
36 | 37 | ||
37 | /* | 38 | /* |
@@ -53,6 +54,11 @@ static unsigned long empty_bad_page; | |||
53 | 54 | ||
54 | unsigned long empty_zero_page; | 55 | unsigned long empty_zero_page; |
55 | 56 | ||
57 | extern unsigned long exception_stack[NR_CPUS][1024]; | ||
58 | |||
59 | struct blackfin_pda cpu_pda[NR_CPUS]; | ||
60 | EXPORT_SYMBOL(cpu_pda); | ||
61 | |||
56 | /* | 62 | /* |
57 | * paging_init() continues the virtual memory environment setup which | 63 | * paging_init() continues the virtual memory environment setup which |
58 | * was begun by the code in arch/head.S. | 64 | * was begun by the code in arch/head.S. |
@@ -98,6 +104,42 @@ void __init paging_init(void) | |||
98 | } | 104 | } |
99 | } | 105 | } |
100 | 106 | ||
107 | asmlinkage void init_pda(void) | ||
108 | { | ||
109 | unsigned int cpu = raw_smp_processor_id(); | ||
110 | |||
111 | /* Initialize the PDA fields holding references to other parts | ||
112 | of the memory. The content of such memory is still | ||
113 | undefined at the time of the call, we are only setting up | ||
114 | valid pointers to it. */ | ||
115 | memset(&cpu_pda[cpu], 0, sizeof(cpu_pda[cpu])); | ||
116 | |||
117 | cpu_pda[0].next = &cpu_pda[1]; | ||
118 | cpu_pda[1].next = &cpu_pda[0]; | ||
119 | |||
120 | cpu_pda[cpu].ex_stack = exception_stack[cpu + 1]; | ||
121 | |||
122 | #ifdef CONFIG_MPU | ||
123 | #else | ||
124 | cpu_pda[cpu].ipdt = ipdt_tables[cpu]; | ||
125 | cpu_pda[cpu].dpdt = dpdt_tables[cpu]; | ||
126 | #ifdef CONFIG_CPLB_INFO | ||
127 | cpu_pda[cpu].ipdt_swapcount = ipdt_swapcount_tables[cpu]; | ||
128 | cpu_pda[cpu].dpdt_swapcount = dpdt_swapcount_tables[cpu]; | ||
129 | #endif | ||
130 | #endif | ||
131 | |||
132 | #ifdef CONFIG_SMP | ||
133 | cpu_pda[cpu].imask = 0x1f; | ||
134 | #endif | ||
135 | } | ||
136 | |||
137 | void __cpuinit reserve_pda(void) | ||
138 | { | ||
139 | printk(KERN_INFO "PDA for CPU%u reserved at %p\n", smp_processor_id(), | ||
140 | &cpu_pda[smp_processor_id()]); | ||
141 | } | ||
142 | |||
101 | void __init mem_init(void) | 143 | void __init mem_init(void) |
102 | { | 144 | { |
103 | unsigned int codek = 0, datak = 0, initk = 0; | 145 | unsigned int codek = 0, datak = 0, initk = 0; |
@@ -141,21 +183,13 @@ void __init mem_init(void) | |||
141 | 183 | ||
142 | static int __init sram_init(void) | 184 | static int __init sram_init(void) |
143 | { | 185 | { |
144 | unsigned long tmp; | ||
145 | |||
146 | /* Initialize the blackfin L1 Memory. */ | 186 | /* Initialize the blackfin L1 Memory. */ |
147 | bfin_sram_init(); | 187 | bfin_sram_init(); |
148 | 188 | ||
149 | /* Allocate this once; never free it. We assume this gives us a | 189 | /* Reserve the PDA space for the boot CPU right after we |
150 | pointer to the start of L1 scratchpad memory; panic if it | 190 | * initialized the scratch memory allocator. |
151 | doesn't. */ | 191 | */ |
152 | tmp = (unsigned long)l1sram_alloc(sizeof(struct l1_scratch_task_info)); | 192 | reserve_pda(); |
153 | if (tmp != (unsigned long)L1_SCRATCH_TASK_INFO) { | ||
154 | printk(KERN_EMERG "mem_init(): Did not get the right address from l1sram_alloc: %08lx != %08lx\n", | ||
155 | tmp, (unsigned long)L1_SCRATCH_TASK_INFO); | ||
156 | panic("No L1, time to give up\n"); | ||
157 | } | ||
158 | |||
159 | return 0; | 193 | return 0; |
160 | } | 194 | } |
161 | pure_initcall(sram_init); | 195 | pure_initcall(sram_init); |
diff --git a/arch/blackfin/mm/sram-alloc.c b/arch/blackfin/mm/sram-alloc.c index cc6f336e7313..8f82b4c92d07 100644 --- a/arch/blackfin/mm/sram-alloc.c +++ b/arch/blackfin/mm/sram-alloc.c | |||
@@ -41,8 +41,10 @@ | |||
41 | #include <asm/blackfin.h> | 41 | #include <asm/blackfin.h> |
42 | #include "blackfin_sram.h" | 42 | #include "blackfin_sram.h" |
43 | 43 | ||
44 | static spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock; | 44 | static DEFINE_PER_CPU(spinlock_t, l1sram_lock) ____cacheline_aligned_in_smp; |
45 | static spinlock_t l2_sram_lock; | 45 | static DEFINE_PER_CPU(spinlock_t, l1_data_sram_lock) ____cacheline_aligned_in_smp; |
46 | static DEFINE_PER_CPU(spinlock_t, l1_inst_sram_lock) ____cacheline_aligned_in_smp; | ||
47 | static spinlock_t l2_sram_lock ____cacheline_aligned_in_smp; | ||
46 | 48 | ||
47 | /* the data structure for L1 scratchpad and DATA SRAM */ | 49 | /* the data structure for L1 scratchpad and DATA SRAM */ |
48 | struct sram_piece { | 50 | struct sram_piece { |
@@ -52,18 +54,22 @@ struct sram_piece { | |||
52 | struct sram_piece *next; | 54 | struct sram_piece *next; |
53 | }; | 55 | }; |
54 | 56 | ||
55 | static struct sram_piece free_l1_ssram_head, used_l1_ssram_head; | 57 | static DEFINE_PER_CPU(struct sram_piece, free_l1_ssram_head); |
58 | static DEFINE_PER_CPU(struct sram_piece, used_l1_ssram_head); | ||
56 | 59 | ||
57 | #if L1_DATA_A_LENGTH != 0 | 60 | #if L1_DATA_A_LENGTH != 0 |
58 | static struct sram_piece free_l1_data_A_sram_head, used_l1_data_A_sram_head; | 61 | static DEFINE_PER_CPU(struct sram_piece, free_l1_data_A_sram_head); |
62 | static DEFINE_PER_CPU(struct sram_piece, used_l1_data_A_sram_head); | ||
59 | #endif | 63 | #endif |
60 | 64 | ||
61 | #if L1_DATA_B_LENGTH != 0 | 65 | #if L1_DATA_B_LENGTH != 0 |
62 | static struct sram_piece free_l1_data_B_sram_head, used_l1_data_B_sram_head; | 66 | static DEFINE_PER_CPU(struct sram_piece, free_l1_data_B_sram_head); |
67 | static DEFINE_PER_CPU(struct sram_piece, used_l1_data_B_sram_head); | ||
63 | #endif | 68 | #endif |
64 | 69 | ||
65 | #if L1_CODE_LENGTH != 0 | 70 | #if L1_CODE_LENGTH != 0 |
66 | static struct sram_piece free_l1_inst_sram_head, used_l1_inst_sram_head; | 71 | static DEFINE_PER_CPU(struct sram_piece, free_l1_inst_sram_head); |
72 | static DEFINE_PER_CPU(struct sram_piece, used_l1_inst_sram_head); | ||
67 | #endif | 73 | #endif |
68 | 74 | ||
69 | #if L2_LENGTH != 0 | 75 | #if L2_LENGTH != 0 |
@@ -75,102 +81,115 @@ static struct kmem_cache *sram_piece_cache; | |||
75 | /* L1 Scratchpad SRAM initialization function */ | 81 | /* L1 Scratchpad SRAM initialization function */ |
76 | static void __init l1sram_init(void) | 82 | static void __init l1sram_init(void) |
77 | { | 83 | { |
78 | free_l1_ssram_head.next = | 84 | unsigned int cpu; |
79 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | 85 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { |
80 | if (!free_l1_ssram_head.next) { | 86 | per_cpu(free_l1_ssram_head, cpu).next = |
81 | printk(KERN_INFO "Failed to initialize Scratchpad data SRAM\n"); | 87 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); |
82 | return; | 88 | if (!per_cpu(free_l1_ssram_head, cpu).next) { |
89 | printk(KERN_INFO "Fail to initialize Scratchpad data SRAM.\n"); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | per_cpu(free_l1_ssram_head, cpu).next->paddr = (void *)get_l1_scratch_start_cpu(cpu); | ||
94 | per_cpu(free_l1_ssram_head, cpu).next->size = L1_SCRATCH_LENGTH; | ||
95 | per_cpu(free_l1_ssram_head, cpu).next->pid = 0; | ||
96 | per_cpu(free_l1_ssram_head, cpu).next->next = NULL; | ||
97 | |||
98 | per_cpu(used_l1_ssram_head, cpu).next = NULL; | ||
99 | |||
100 | /* mutex initialize */ | ||
101 | spin_lock_init(&per_cpu(l1sram_lock, cpu)); | ||
102 | printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n", | ||
103 | L1_SCRATCH_LENGTH >> 10); | ||
83 | } | 104 | } |
84 | |||
85 | free_l1_ssram_head.next->paddr = (void *)L1_SCRATCH_START; | ||
86 | free_l1_ssram_head.next->size = L1_SCRATCH_LENGTH; | ||
87 | free_l1_ssram_head.next->pid = 0; | ||
88 | free_l1_ssram_head.next->next = NULL; | ||
89 | |||
90 | used_l1_ssram_head.next = NULL; | ||
91 | |||
92 | /* mutex initialize */ | ||
93 | spin_lock_init(&l1sram_lock); | ||
94 | |||
95 | printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n", | ||
96 | L1_SCRATCH_LENGTH >> 10); | ||
97 | } | 105 | } |
98 | 106 | ||
99 | static void __init l1_data_sram_init(void) | 107 | static void __init l1_data_sram_init(void) |
100 | { | 108 | { |
109 | unsigned int cpu; | ||
101 | #if L1_DATA_A_LENGTH != 0 | 110 | #if L1_DATA_A_LENGTH != 0 |
102 | free_l1_data_A_sram_head.next = | 111 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { |
103 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | 112 | per_cpu(free_l1_data_A_sram_head, cpu).next = |
104 | if (!free_l1_data_A_sram_head.next) { | 113 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); |
105 | printk(KERN_INFO "Failed to initialize L1 Data A SRAM\n"); | 114 | if (!per_cpu(free_l1_data_A_sram_head, cpu).next) { |
106 | return; | 115 | printk(KERN_INFO "Fail to initialize L1 Data A SRAM.\n"); |
116 | return; | ||
117 | } | ||
118 | |||
119 | per_cpu(free_l1_data_A_sram_head, cpu).next->paddr = | ||
120 | (void *)get_l1_data_a_start_cpu(cpu) + (_ebss_l1 - _sdata_l1); | ||
121 | per_cpu(free_l1_data_A_sram_head, cpu).next->size = | ||
122 | L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1); | ||
123 | per_cpu(free_l1_data_A_sram_head, cpu).next->pid = 0; | ||
124 | per_cpu(free_l1_data_A_sram_head, cpu).next->next = NULL; | ||
125 | |||
126 | per_cpu(used_l1_data_A_sram_head, cpu).next = NULL; | ||
127 | |||
128 | printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n", | ||
129 | L1_DATA_A_LENGTH >> 10, | ||
130 | per_cpu(free_l1_data_A_sram_head, cpu).next->size >> 10); | ||
107 | } | 131 | } |
108 | |||
109 | free_l1_data_A_sram_head.next->paddr = | ||
110 | (void *)L1_DATA_A_START + (_ebss_l1 - _sdata_l1); | ||
111 | free_l1_data_A_sram_head.next->size = | ||
112 | L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1); | ||
113 | free_l1_data_A_sram_head.next->pid = 0; | ||
114 | free_l1_data_A_sram_head.next->next = NULL; | ||
115 | |||
116 | used_l1_data_A_sram_head.next = NULL; | ||
117 | |||
118 | printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n", | ||
119 | L1_DATA_A_LENGTH >> 10, | ||
120 | free_l1_data_A_sram_head.next->size >> 10); | ||
121 | #endif | 132 | #endif |
122 | #if L1_DATA_B_LENGTH != 0 | 133 | #if L1_DATA_B_LENGTH != 0 |
123 | free_l1_data_B_sram_head.next = | 134 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { |
124 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | 135 | per_cpu(free_l1_data_B_sram_head, cpu).next = |
125 | if (!free_l1_data_B_sram_head.next) { | 136 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); |
126 | printk(KERN_INFO "Failed to initialize L1 Data B SRAM\n"); | 137 | if (!per_cpu(free_l1_data_B_sram_head, cpu).next) { |
127 | return; | 138 | printk(KERN_INFO "Fail to initialize L1 Data B SRAM.\n"); |
139 | return; | ||
140 | } | ||
141 | |||
142 | per_cpu(free_l1_data_B_sram_head, cpu).next->paddr = | ||
143 | (void *)get_l1_data_b_start_cpu(cpu) + (_ebss_b_l1 - _sdata_b_l1); | ||
144 | per_cpu(free_l1_data_B_sram_head, cpu).next->size = | ||
145 | L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1); | ||
146 | per_cpu(free_l1_data_B_sram_head, cpu).next->pid = 0; | ||
147 | per_cpu(free_l1_data_B_sram_head, cpu).next->next = NULL; | ||
148 | |||
149 | per_cpu(used_l1_data_B_sram_head, cpu).next = NULL; | ||
150 | |||
151 | printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n", | ||
152 | L1_DATA_B_LENGTH >> 10, | ||
153 | per_cpu(free_l1_data_B_sram_head, cpu).next->size >> 10); | ||
154 | /* mutex initialize */ | ||
128 | } | 155 | } |
129 | |||
130 | free_l1_data_B_sram_head.next->paddr = | ||
131 | (void *)L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1); | ||
132 | free_l1_data_B_sram_head.next->size = | ||
133 | L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1); | ||
134 | free_l1_data_B_sram_head.next->pid = 0; | ||
135 | free_l1_data_B_sram_head.next->next = NULL; | ||
136 | |||
137 | used_l1_data_B_sram_head.next = NULL; | ||
138 | |||
139 | printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n", | ||
140 | L1_DATA_B_LENGTH >> 10, | ||
141 | free_l1_data_B_sram_head.next->size >> 10); | ||
142 | #endif | 156 | #endif |
143 | 157 | ||
144 | /* mutex initialize */ | 158 | #if L1_DATA_A_LENGTH != 0 || L1_DATA_B_LENGTH != 0 |
145 | spin_lock_init(&l1_data_sram_lock); | 159 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) |
160 | spin_lock_init(&per_cpu(l1_data_sram_lock, cpu)); | ||
161 | #endif | ||
146 | } | 162 | } |
147 | 163 | ||
148 | static void __init l1_inst_sram_init(void) | 164 | static void __init l1_inst_sram_init(void) |
149 | { | 165 | { |
150 | #if L1_CODE_LENGTH != 0 | 166 | #if L1_CODE_LENGTH != 0 |
151 | free_l1_inst_sram_head.next = | 167 | unsigned int cpu; |
152 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | 168 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { |
153 | if (!free_l1_inst_sram_head.next) { | 169 | per_cpu(free_l1_inst_sram_head, cpu).next = |
154 | printk(KERN_INFO "Failed to initialize L1 Instruction SRAM\n"); | 170 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); |
155 | return; | 171 | if (!per_cpu(free_l1_inst_sram_head, cpu).next) { |
172 | printk(KERN_INFO "Failed to initialize L1 Instruction SRAM\n"); | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | per_cpu(free_l1_inst_sram_head, cpu).next->paddr = | ||
177 | (void *)get_l1_code_start_cpu(cpu) + (_etext_l1 - _stext_l1); | ||
178 | per_cpu(free_l1_inst_sram_head, cpu).next->size = | ||
179 | L1_CODE_LENGTH - (_etext_l1 - _stext_l1); | ||
180 | per_cpu(free_l1_inst_sram_head, cpu).next->pid = 0; | ||
181 | per_cpu(free_l1_inst_sram_head, cpu).next->next = NULL; | ||
182 | |||
183 | per_cpu(used_l1_inst_sram_head, cpu).next = NULL; | ||
184 | |||
185 | printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n", | ||
186 | L1_CODE_LENGTH >> 10, | ||
187 | per_cpu(free_l1_inst_sram_head, cpu).next->size >> 10); | ||
188 | |||
189 | /* mutex initialize */ | ||
190 | spin_lock_init(&per_cpu(l1_inst_sram_lock, cpu)); | ||
156 | } | 191 | } |
157 | |||
158 | free_l1_inst_sram_head.next->paddr = | ||
159 | (void *)L1_CODE_START + (_etext_l1 - _stext_l1); | ||
160 | free_l1_inst_sram_head.next->size = | ||
161 | L1_CODE_LENGTH - (_etext_l1 - _stext_l1); | ||
162 | free_l1_inst_sram_head.next->pid = 0; | ||
163 | free_l1_inst_sram_head.next->next = NULL; | ||
164 | |||
165 | used_l1_inst_sram_head.next = NULL; | ||
166 | |||
167 | printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n", | ||
168 | L1_CODE_LENGTH >> 10, | ||
169 | free_l1_inst_sram_head.next->size >> 10); | ||
170 | #endif | 192 | #endif |
171 | |||
172 | /* mutex initialize */ | ||
173 | spin_lock_init(&l1_inst_sram_lock); | ||
174 | } | 193 | } |
175 | 194 | ||
176 | static void __init l2_sram_init(void) | 195 | static void __init l2_sram_init(void) |
@@ -179,7 +198,7 @@ static void __init l2_sram_init(void) | |||
179 | free_l2_sram_head.next = | 198 | free_l2_sram_head.next = |
180 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | 199 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); |
181 | if (!free_l2_sram_head.next) { | 200 | if (!free_l2_sram_head.next) { |
182 | printk(KERN_INFO "Failed to initialize L2 SRAM\n"); | 201 | printk(KERN_INFO "Fail to initialize L2 SRAM.\n"); |
183 | return; | 202 | return; |
184 | } | 203 | } |
185 | 204 | ||
@@ -200,6 +219,7 @@ static void __init l2_sram_init(void) | |||
200 | /* mutex initialize */ | 219 | /* mutex initialize */ |
201 | spin_lock_init(&l2_sram_lock); | 220 | spin_lock_init(&l2_sram_lock); |
202 | } | 221 | } |
222 | |||
203 | void __init bfin_sram_init(void) | 223 | void __init bfin_sram_init(void) |
204 | { | 224 | { |
205 | sram_piece_cache = kmem_cache_create("sram_piece_cache", | 225 | sram_piece_cache = kmem_cache_create("sram_piece_cache", |
@@ -353,20 +373,20 @@ int sram_free(const void *addr) | |||
353 | { | 373 | { |
354 | 374 | ||
355 | #if L1_CODE_LENGTH != 0 | 375 | #if L1_CODE_LENGTH != 0 |
356 | if (addr >= (void *)L1_CODE_START | 376 | if (addr >= (void *)get_l1_code_start() |
357 | && addr < (void *)(L1_CODE_START + L1_CODE_LENGTH)) | 377 | && addr < (void *)(get_l1_code_start() + L1_CODE_LENGTH)) |
358 | return l1_inst_sram_free(addr); | 378 | return l1_inst_sram_free(addr); |
359 | else | 379 | else |
360 | #endif | 380 | #endif |
361 | #if L1_DATA_A_LENGTH != 0 | 381 | #if L1_DATA_A_LENGTH != 0 |
362 | if (addr >= (void *)L1_DATA_A_START | 382 | if (addr >= (void *)get_l1_data_a_start() |
363 | && addr < (void *)(L1_DATA_A_START + L1_DATA_A_LENGTH)) | 383 | && addr < (void *)(get_l1_data_a_start() + L1_DATA_A_LENGTH)) |
364 | return l1_data_A_sram_free(addr); | 384 | return l1_data_A_sram_free(addr); |
365 | else | 385 | else |
366 | #endif | 386 | #endif |
367 | #if L1_DATA_B_LENGTH != 0 | 387 | #if L1_DATA_B_LENGTH != 0 |
368 | if (addr >= (void *)L1_DATA_B_START | 388 | if (addr >= (void *)get_l1_data_b_start() |
369 | && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH)) | 389 | && addr < (void *)(get_l1_data_b_start() + L1_DATA_B_LENGTH)) |
370 | return l1_data_B_sram_free(addr); | 390 | return l1_data_B_sram_free(addr); |
371 | else | 391 | else |
372 | #endif | 392 | #endif |
@@ -384,17 +404,20 @@ void *l1_data_A_sram_alloc(size_t size) | |||
384 | { | 404 | { |
385 | unsigned long flags; | 405 | unsigned long flags; |
386 | void *addr = NULL; | 406 | void *addr = NULL; |
407 | unsigned int cpu; | ||
387 | 408 | ||
409 | cpu = get_cpu(); | ||
388 | /* add mutex operation */ | 410 | /* add mutex operation */ |
389 | spin_lock_irqsave(&l1_data_sram_lock, flags); | 411 | spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags); |
390 | 412 | ||
391 | #if L1_DATA_A_LENGTH != 0 | 413 | #if L1_DATA_A_LENGTH != 0 |
392 | addr = _sram_alloc(size, &free_l1_data_A_sram_head, | 414 | addr = _sram_alloc(size, &per_cpu(free_l1_data_A_sram_head, cpu), |
393 | &used_l1_data_A_sram_head); | 415 | &per_cpu(used_l1_data_A_sram_head, cpu)); |
394 | #endif | 416 | #endif |
395 | 417 | ||
396 | /* add mutex operation */ | 418 | /* add mutex operation */ |
397 | spin_unlock_irqrestore(&l1_data_sram_lock, flags); | 419 | spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags); |
420 | put_cpu(); | ||
398 | 421 | ||
399 | pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n", | 422 | pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n", |
400 | (long unsigned int)addr, size); | 423 | (long unsigned int)addr, size); |
@@ -407,19 +430,22 @@ int l1_data_A_sram_free(const void *addr) | |||
407 | { | 430 | { |
408 | unsigned long flags; | 431 | unsigned long flags; |
409 | int ret; | 432 | int ret; |
433 | unsigned int cpu; | ||
410 | 434 | ||
435 | cpu = get_cpu(); | ||
411 | /* add mutex operation */ | 436 | /* add mutex operation */ |
412 | spin_lock_irqsave(&l1_data_sram_lock, flags); | 437 | spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags); |
413 | 438 | ||
414 | #if L1_DATA_A_LENGTH != 0 | 439 | #if L1_DATA_A_LENGTH != 0 |
415 | ret = _sram_free(addr, &free_l1_data_A_sram_head, | 440 | ret = _sram_free(addr, &per_cpu(free_l1_data_A_sram_head, cpu), |
416 | &used_l1_data_A_sram_head); | 441 | &per_cpu(used_l1_data_A_sram_head, cpu)); |
417 | #else | 442 | #else |
418 | ret = -1; | 443 | ret = -1; |
419 | #endif | 444 | #endif |
420 | 445 | ||
421 | /* add mutex operation */ | 446 | /* add mutex operation */ |
422 | spin_unlock_irqrestore(&l1_data_sram_lock, flags); | 447 | spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags); |
448 | put_cpu(); | ||
423 | 449 | ||
424 | return ret; | 450 | return ret; |
425 | } | 451 | } |
@@ -430,15 +456,18 @@ void *l1_data_B_sram_alloc(size_t size) | |||
430 | #if L1_DATA_B_LENGTH != 0 | 456 | #if L1_DATA_B_LENGTH != 0 |
431 | unsigned long flags; | 457 | unsigned long flags; |
432 | void *addr; | 458 | void *addr; |
459 | unsigned int cpu; | ||
433 | 460 | ||
461 | cpu = get_cpu(); | ||
434 | /* add mutex operation */ | 462 | /* add mutex operation */ |
435 | spin_lock_irqsave(&l1_data_sram_lock, flags); | 463 | spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags); |
436 | 464 | ||
437 | addr = _sram_alloc(size, &free_l1_data_B_sram_head, | 465 | addr = _sram_alloc(size, &per_cpu(free_l1_data_B_sram_head, cpu), |
438 | &used_l1_data_B_sram_head); | 466 | &per_cpu(used_l1_data_B_sram_head, cpu)); |
439 | 467 | ||
440 | /* add mutex operation */ | 468 | /* add mutex operation */ |
441 | spin_unlock_irqrestore(&l1_data_sram_lock, flags); | 469 | spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags); |
470 | put_cpu(); | ||
442 | 471 | ||
443 | pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n", | 472 | pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n", |
444 | (long unsigned int)addr, size); | 473 | (long unsigned int)addr, size); |
@@ -455,15 +484,18 @@ int l1_data_B_sram_free(const void *addr) | |||
455 | #if L1_DATA_B_LENGTH != 0 | 484 | #if L1_DATA_B_LENGTH != 0 |
456 | unsigned long flags; | 485 | unsigned long flags; |
457 | int ret; | 486 | int ret; |
487 | unsigned int cpu; | ||
458 | 488 | ||
489 | cpu = get_cpu(); | ||
459 | /* add mutex operation */ | 490 | /* add mutex operation */ |
460 | spin_lock_irqsave(&l1_data_sram_lock, flags); | 491 | spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags); |
461 | 492 | ||
462 | ret = _sram_free(addr, &free_l1_data_B_sram_head, | 493 | ret = _sram_free(addr, &per_cpu(free_l1_data_B_sram_head, cpu), |
463 | &used_l1_data_B_sram_head); | 494 | &per_cpu(used_l1_data_B_sram_head, cpu)); |
464 | 495 | ||
465 | /* add mutex operation */ | 496 | /* add mutex operation */ |
466 | spin_unlock_irqrestore(&l1_data_sram_lock, flags); | 497 | spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags); |
498 | put_cpu(); | ||
467 | 499 | ||
468 | return ret; | 500 | return ret; |
469 | #else | 501 | #else |
@@ -509,15 +541,18 @@ void *l1_inst_sram_alloc(size_t size) | |||
509 | #if L1_CODE_LENGTH != 0 | 541 | #if L1_CODE_LENGTH != 0 |
510 | unsigned long flags; | 542 | unsigned long flags; |
511 | void *addr; | 543 | void *addr; |
544 | unsigned int cpu; | ||
512 | 545 | ||
546 | cpu = get_cpu(); | ||
513 | /* add mutex operation */ | 547 | /* add mutex operation */ |
514 | spin_lock_irqsave(&l1_inst_sram_lock, flags); | 548 | spin_lock_irqsave(&per_cpu(l1_inst_sram_lock, cpu), flags); |
515 | 549 | ||
516 | addr = _sram_alloc(size, &free_l1_inst_sram_head, | 550 | addr = _sram_alloc(size, &per_cpu(free_l1_inst_sram_head, cpu), |
517 | &used_l1_inst_sram_head); | 551 | &per_cpu(used_l1_inst_sram_head, cpu)); |
518 | 552 | ||
519 | /* add mutex operation */ | 553 | /* add mutex operation */ |
520 | spin_unlock_irqrestore(&l1_inst_sram_lock, flags); | 554 | spin_unlock_irqrestore(&per_cpu(l1_inst_sram_lock, cpu), flags); |
555 | put_cpu(); | ||
521 | 556 | ||
522 | pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n", | 557 | pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n", |
523 | (long unsigned int)addr, size); | 558 | (long unsigned int)addr, size); |
@@ -534,15 +569,18 @@ int l1_inst_sram_free(const void *addr) | |||
534 | #if L1_CODE_LENGTH != 0 | 569 | #if L1_CODE_LENGTH != 0 |
535 | unsigned long flags; | 570 | unsigned long flags; |
536 | int ret; | 571 | int ret; |
572 | unsigned int cpu; | ||
537 | 573 | ||
574 | cpu = get_cpu(); | ||
538 | /* add mutex operation */ | 575 | /* add mutex operation */ |
539 | spin_lock_irqsave(&l1_inst_sram_lock, flags); | 576 | spin_lock_irqsave(&per_cpu(l1_inst_sram_lock, cpu), flags); |
540 | 577 | ||
541 | ret = _sram_free(addr, &free_l1_inst_sram_head, | 578 | ret = _sram_free(addr, &per_cpu(free_l1_inst_sram_head, cpu), |
542 | &used_l1_inst_sram_head); | 579 | &per_cpu(used_l1_inst_sram_head, cpu)); |
543 | 580 | ||
544 | /* add mutex operation */ | 581 | /* add mutex operation */ |
545 | spin_unlock_irqrestore(&l1_inst_sram_lock, flags); | 582 | spin_unlock_irqrestore(&per_cpu(l1_inst_sram_lock, cpu), flags); |
583 | put_cpu(); | ||
546 | 584 | ||
547 | return ret; | 585 | return ret; |
548 | #else | 586 | #else |
@@ -556,15 +594,18 @@ void *l1sram_alloc(size_t size) | |||
556 | { | 594 | { |
557 | unsigned long flags; | 595 | unsigned long flags; |
558 | void *addr; | 596 | void *addr; |
597 | unsigned int cpu; | ||
559 | 598 | ||
599 | cpu = get_cpu(); | ||
560 | /* add mutex operation */ | 600 | /* add mutex operation */ |
561 | spin_lock_irqsave(&l1sram_lock, flags); | 601 | spin_lock_irqsave(&per_cpu(l1sram_lock, cpu), flags); |
562 | 602 | ||
563 | addr = _sram_alloc(size, &free_l1_ssram_head, | 603 | addr = _sram_alloc(size, &per_cpu(free_l1_ssram_head, cpu), |
564 | &used_l1_ssram_head); | 604 | &per_cpu(used_l1_ssram_head, cpu)); |
565 | 605 | ||
566 | /* add mutex operation */ | 606 | /* add mutex operation */ |
567 | spin_unlock_irqrestore(&l1sram_lock, flags); | 607 | spin_unlock_irqrestore(&per_cpu(l1sram_lock, cpu), flags); |
608 | put_cpu(); | ||
568 | 609 | ||
569 | return addr; | 610 | return addr; |
570 | } | 611 | } |
@@ -574,15 +615,18 @@ void *l1sram_alloc_max(size_t *psize) | |||
574 | { | 615 | { |
575 | unsigned long flags; | 616 | unsigned long flags; |
576 | void *addr; | 617 | void *addr; |
618 | unsigned int cpu; | ||
577 | 619 | ||
620 | cpu = get_cpu(); | ||
578 | /* add mutex operation */ | 621 | /* add mutex operation */ |
579 | spin_lock_irqsave(&l1sram_lock, flags); | 622 | spin_lock_irqsave(&per_cpu(l1sram_lock, cpu), flags); |
580 | 623 | ||
581 | addr = _sram_alloc_max(&free_l1_ssram_head, | 624 | addr = _sram_alloc_max(&per_cpu(free_l1_ssram_head, cpu), |
582 | &used_l1_ssram_head, psize); | 625 | &per_cpu(used_l1_ssram_head, cpu), psize); |
583 | 626 | ||
584 | /* add mutex operation */ | 627 | /* add mutex operation */ |
585 | spin_unlock_irqrestore(&l1sram_lock, flags); | 628 | spin_unlock_irqrestore(&per_cpu(l1sram_lock, cpu), flags); |
629 | put_cpu(); | ||
586 | 630 | ||
587 | return addr; | 631 | return addr; |
588 | } | 632 | } |
@@ -592,15 +636,18 @@ int l1sram_free(const void *addr) | |||
592 | { | 636 | { |
593 | unsigned long flags; | 637 | unsigned long flags; |
594 | int ret; | 638 | int ret; |
639 | unsigned int cpu; | ||
595 | 640 | ||
641 | cpu = get_cpu(); | ||
596 | /* add mutex operation */ | 642 | /* add mutex operation */ |
597 | spin_lock_irqsave(&l1sram_lock, flags); | 643 | spin_lock_irqsave(&per_cpu(l1sram_lock, cpu), flags); |
598 | 644 | ||
599 | ret = _sram_free(addr, &free_l1_ssram_head, | 645 | ret = _sram_free(addr, &per_cpu(free_l1_ssram_head, cpu), |
600 | &used_l1_ssram_head); | 646 | &per_cpu(used_l1_ssram_head, cpu)); |
601 | 647 | ||
602 | /* add mutex operation */ | 648 | /* add mutex operation */ |
603 | spin_unlock_irqrestore(&l1sram_lock, flags); | 649 | spin_unlock_irqrestore(&per_cpu(l1sram_lock, cpu), flags); |
650 | put_cpu(); | ||
604 | 651 | ||
605 | return ret; | 652 | return ret; |
606 | } | 653 | } |
@@ -761,33 +808,36 @@ static int sram_proc_read(char *buf, char **start, off_t offset, int count, | |||
761 | int *eof, void *data) | 808 | int *eof, void *data) |
762 | { | 809 | { |
763 | int len = 0; | 810 | int len = 0; |
811 | unsigned int cpu; | ||
764 | 812 | ||
765 | if (_sram_proc_read(buf, &len, count, "Scratchpad", | 813 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { |
766 | &free_l1_ssram_head, &used_l1_ssram_head)) | 814 | if (_sram_proc_read(buf, &len, count, "Scratchpad", |
767 | goto not_done; | 815 | &per_cpu(free_l1_ssram_head, cpu), &per_cpu(used_l1_ssram_head, cpu))) |
816 | goto not_done; | ||
768 | #if L1_DATA_A_LENGTH != 0 | 817 | #if L1_DATA_A_LENGTH != 0 |
769 | if (_sram_proc_read(buf, &len, count, "L1 Data A", | 818 | if (_sram_proc_read(buf, &len, count, "L1 Data A", |
770 | &free_l1_data_A_sram_head, | 819 | &per_cpu(free_l1_data_A_sram_head, cpu), |
771 | &used_l1_data_A_sram_head)) | 820 | &per_cpu(used_l1_data_A_sram_head, cpu))) |
772 | goto not_done; | 821 | goto not_done; |
773 | #endif | 822 | #endif |
774 | #if L1_DATA_B_LENGTH != 0 | 823 | #if L1_DATA_B_LENGTH != 0 |
775 | if (_sram_proc_read(buf, &len, count, "L1 Data B", | 824 | if (_sram_proc_read(buf, &len, count, "L1 Data B", |
776 | &free_l1_data_B_sram_head, | 825 | &per_cpu(free_l1_data_B_sram_head, cpu), |
777 | &used_l1_data_B_sram_head)) | 826 | &per_cpu(used_l1_data_B_sram_head, cpu))) |
778 | goto not_done; | 827 | goto not_done; |
779 | #endif | 828 | #endif |
780 | #if L1_CODE_LENGTH != 0 | 829 | #if L1_CODE_LENGTH != 0 |
781 | if (_sram_proc_read(buf, &len, count, "L1 Instruction", | 830 | if (_sram_proc_read(buf, &len, count, "L1 Instruction", |
782 | &free_l1_inst_sram_head, &used_l1_inst_sram_head)) | 831 | &per_cpu(free_l1_inst_sram_head, cpu), |
783 | goto not_done; | 832 | &per_cpu(used_l1_inst_sram_head, cpu))) |
833 | goto not_done; | ||
784 | #endif | 834 | #endif |
835 | } | ||
785 | #if L2_LENGTH != 0 | 836 | #if L2_LENGTH != 0 |
786 | if (_sram_proc_read(buf, &len, count, "L2", | 837 | if (_sram_proc_read(buf, &len, count, "L2", &free_l2_sram_head, |
787 | &free_l2_sram_head, &used_l2_sram_head)) | 838 | &used_l2_sram_head)) |
788 | goto not_done; | 839 | goto not_done; |
789 | #endif | 840 | #endif |
790 | |||
791 | *eof = 1; | 841 | *eof = 1; |
792 | not_done: | 842 | not_done: |
793 | return len; | 843 | return len; |