diff options
Diffstat (limited to 'arch/mips/sibyte/sb1250')
| -rw-r--r-- | arch/mips/sibyte/sb1250/Makefile | 1 | ||||
| -rw-r--r-- | arch/mips/sibyte/sb1250/bus_watcher.c | 258 | ||||
| -rw-r--r-- | arch/mips/sibyte/sb1250/irq.c | 19 | ||||
| -rw-r--r-- | arch/mips/sibyte/sb1250/setup.c | 21 | ||||
| -rw-r--r-- | arch/mips/sibyte/sb1250/smp.c | 25 |
5 files changed, 32 insertions, 292 deletions
diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile index d3d969de407..cdc4c56c3e2 100644 --- a/arch/mips/sibyte/sb1250/Makefile +++ b/arch/mips/sibyte/sb1250/Makefile @@ -1,4 +1,3 @@ obj-y := setup.o irq.o time.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c deleted file mode 100644 index 45274bd3cd8..00000000000 --- a/arch/mips/sibyte/sb1250/bus_watcher.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2002,2003 Broadcom Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * The Bus Watcher monitors internal bus transactions and maintains - * counts of transactions with error status, logging details and - * causing one of several interrupts. This driver provides a handler - * for those interrupts which aggregates the counts (to avoid - * saturating the 8-bit counters) and provides a presence in - * /proc/bus_watcher if PROC_FS is on. - */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/interrupt.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> -#include <asm/system.h> -#include <asm/io.h> - -#include <asm/sibyte/sb1250.h> -#include <asm/sibyte/sb1250_regs.h> -#include <asm/sibyte/sb1250_int.h> -#include <asm/sibyte/sb1250_scd.h> - - -struct bw_stats_struct { - uint64_t status; - uint32_t l2_err; - uint32_t memio_err; - int status_printed; - unsigned long l2_cor_d; - unsigned long l2_bad_d; - unsigned long l2_cor_t; - unsigned long l2_bad_t; - unsigned long mem_cor_d; - unsigned long mem_bad_d; - unsigned long bus_error; -} bw_stats; - - -static void print_summary(uint32_t status, uint32_t l2_err, - uint32_t memio_err) -{ - printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err); - printk("\nLast recorded signature:\n"); - printk("Request %02x from %d, answered by %d with Dcode %d\n", - (unsigned int)(G_SCD_BERR_TID(status) & 0x3f), - (int)(G_SCD_BERR_TID(status) >> 6), - (int)G_SCD_BERR_RID(status), - (int)G_SCD_BERR_DCODE(status)); -} - -/* - * check_bus_watcher is exported for use in situations where we want - * to see the most recent status of the bus watcher, which might have - * already been destructively read out of the registers. - * - * notes: this is currently used by the cache error handler - * should provide locking against the interrupt handler - */ -void check_bus_watcher(void) -{ - u32 status, l2_err, memio_err; - -#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS - /* Destructive read, clears register and interrupt */ - status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS)); -#else - /* Use non-destructive register */ - status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS_DEBUG)); -#endif - if (!(status & 0x7fffffff)) { - printk("Using last values reaped by bus watcher driver\n"); - status = bw_stats.status; - l2_err = bw_stats.l2_err; - memio_err = bw_stats.memio_err; - } else { - l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS)); - memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS)); - } - if (status & ~(1UL << 31)) - print_summary(status, l2_err, memio_err); - else - printk("Bus watcher indicates no error\n"); -} - -static int bw_print_buffer(char *page, struct bw_stats_struct *stats) -{ - int len; - - len = sprintf(page, "SiByte Bus Watcher statistics\n"); - len += sprintf(page+len, "-----------------------------\n"); - len += sprintf(page+len, "L2-d-cor %8ld\nL2-d-bad %8ld\n", - stats->l2_cor_d, stats->l2_bad_d); - len += sprintf(page+len, "L2-t-cor %8ld\nL2-t-bad %8ld\n", - stats->l2_cor_t, stats->l2_bad_t); - len += sprintf(page+len, "MC-d-cor %8ld\nMC-d-bad %8ld\n", - stats->mem_cor_d, stats->mem_bad_d); - len += sprintf(page+len, "IO-err %8ld\n", stats->bus_error); - len += sprintf(page+len, "\nLast recorded signature:\n"); - len += sprintf(page+len, "Request %02x from %d, answered by %d with Dcode %d\n", - (unsigned int)(G_SCD_BERR_TID(stats->status) & 0x3f), - (int)(G_SCD_BERR_TID(stats->status) >> 6), - (int)G_SCD_BERR_RID(stats->status), - (int)G_SCD_BERR_DCODE(stats->status)); - /* XXXKW indicate multiple errors between printings, or stats - collection (or both)? */ - if (stats->status & M_SCD_BERR_MULTERRS) - len += sprintf(page+len, "Multiple errors observed since last check.\n"); - if (stats->status_printed) { - len += sprintf(page+len, "(no change since last printing)\n"); - } else { - stats->status_printed = 1; - } - - return len; -} - -#ifdef CONFIG_PROC_FS - -/* For simplicity, I want to assume a single read is required each - time */ -static int bw_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - if (off == 0) { - len = bw_print_buffer(page, data); - *start = page; - } else { - len = 0; - *eof = 1; - } - return len; -} - -static void create_proc_decoder(struct bw_stats_struct *stats) -{ - struct proc_dir_entry *ent; - - ent = create_proc_read_entry("bus_watcher", S_IWUSR | S_IRUGO, NULL, - bw_read_proc, stats); - if (!ent) { - printk(KERN_INFO "Unable to initialize bus_watcher /proc entry\n"); - return; - } -} - -#endif /* CONFIG_PROC_FS */ - -/* - * sibyte_bw_int - handle bus watcher interrupts and accumulate counts - * - * notes: possible re-entry due to multiple sources - * should check/indicate saturation - */ -static irqreturn_t sibyte_bw_int(int irq, void *data) -{ - struct bw_stats_struct *stats = data; - unsigned long cntr; -#ifdef CONFIG_SIBYTE_BW_TRACE - int i; -#endif -#ifndef CONFIG_PROC_FS - char bw_buf[1024]; -#endif - -#ifdef CONFIG_SIBYTE_BW_TRACE - csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG)); - csr_out32(M_SCD_TRACE_CFG_START_READ, IOADDR(A_SCD_TRACE_CFG)); - - for (i=0; i<256*6; i++) - printk("%016llx\n", - (long long)__raw_readq(IOADDR(A_SCD_TRACE_READ))); - - csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); - csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG)); -#endif - - /* Destructive read, clears register and interrupt */ - stats->status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS)); - stats->status_printed = 0; - - stats->l2_err = cntr = csr_in32(IOADDR(A_BUS_L2_ERRORS)); - stats->l2_cor_d += G_SCD_L2ECC_CORR_D(cntr); - stats->l2_bad_d += G_SCD_L2ECC_BAD_D(cntr); - stats->l2_cor_t += G_SCD_L2ECC_CORR_T(cntr); - stats->l2_bad_t += G_SCD_L2ECC_BAD_T(cntr); - csr_out32(0, IOADDR(A_BUS_L2_ERRORS)); - - stats->memio_err = cntr = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS)); - stats->mem_cor_d += G_SCD_MEM_ECC_CORR(cntr); - stats->mem_bad_d += G_SCD_MEM_ECC_BAD(cntr); - stats->bus_error += G_SCD_MEM_BUSERR(cntr); - csr_out32(0, IOADDR(A_BUS_MEM_IO_ERRORS)); - -#ifndef CONFIG_PROC_FS - bw_print_buffer(bw_buf, stats); - printk(bw_buf); -#endif - - return IRQ_HANDLED; -} - -int __init sibyte_bus_watcher(void) -{ - memset(&bw_stats, 0, sizeof(struct bw_stats_struct)); - bw_stats.status_printed = 1; - - if (request_irq(K_INT_BAD_ECC, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) { - printk("Failed to register bus watcher BAD_ECC irq\n"); - return -1; - } - if (request_irq(K_INT_COR_ECC, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) { - free_irq(K_INT_BAD_ECC, &bw_stats); - printk("Failed to register bus watcher COR_ECC irq\n"); - return -1; - } - if (request_irq(K_INT_IO_BUS, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) { - free_irq(K_INT_BAD_ECC, &bw_stats); - free_irq(K_INT_COR_ECC, &bw_stats); - printk("Failed to register bus watcher IO_BUS irq\n"); - return -1; - } - -#ifdef CONFIG_PROC_FS - create_proc_decoder(&bw_stats); -#endif - -#ifdef CONFIG_SIBYTE_BW_TRACE - csr_out32((M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE | - K_SCD_TRSEQ_TRIGGER_ALL), - IOADDR(A_SCD_TRACE_SEQUENCE_0)); - csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); - csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG)); -#endif - - return 0; -} - -__initcall(sibyte_bus_watcher); diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c index be4460a5f6a..6d8dba5cf34 100644 --- a/arch/mips/sibyte/sb1250/irq.c +++ b/arch/mips/sibyte/sb1250/irq.c @@ -26,7 +26,6 @@ #include <asm/errno.h> #include <asm/signal.h> -#include <asm/system.h> #include <asm/time.h> #include <asm/io.h> @@ -89,7 +88,7 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask, u64 cur_ints; unsigned long flags; - i = cpumask_first(mask); + i = cpumask_first_and(mask, cpu_online_mask); /* Convert logical CPU to physical CPU */ cpu = cpu_logical_map(i); @@ -123,6 +122,13 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask, } #endif +static void disable_sb1250_irq(struct irq_data *d) +{ + unsigned int irq = d->irq; + + sb1250_mask_irq(sb1250_irq_owner[irq], irq); +} + static void enable_sb1250_irq(struct irq_data *d) { unsigned int irq = d->irq; @@ -180,6 +186,7 @@ static struct irq_chip sb1250_irq_type = { .name = "SB1250-IMR", .irq_mask_ack = ack_sb1250_irq, .irq_unmask = enable_sb1250_irq, + .irq_mask = disable_sb1250_irq, #ifdef CONFIG_SMP .irq_set_affinity = sb1250_set_affinity #endif @@ -257,7 +264,7 @@ void __init arch_init_irq(void) IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) + (K_INT_MBOX_0 << 3))); - /* Clear the mailboxes. The firmware may leave them dirty */ + /* Clear the mailboxes. The firmware may leave them dirty */ __raw_writeq(0xffffffffffffffffULL, IOADDR(A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU))); __raw_writeq(0xffffffffffffffffULL, @@ -270,7 +277,7 @@ void __init arch_init_irq(void) /* * Note that the timer interrupts are also mapped, but this is - * done in sb1250_time_init(). Also, the profiling driver + * done in sb1250_time_init(). Also, the profiling driver * does its own management of IP7. */ @@ -287,7 +294,7 @@ static inline void dispatch_ip2(void) /* * Default...we've hit an IP[2] interrupt, which means we've got to - * check the 1250 interrupt registers to figure out what to do. Need + * check the 1250 interrupt registers to figure out what to do. Need * to detect which CPU we're on, now that smp_affinity is supported. */ mask = __raw_readq(IOADDR(A_IMR_REGISTER(cpu, @@ -316,7 +323,7 @@ asmlinkage void plat_irq_dispatch(void) if (pending & CAUSEF_IP7) /* CPU performance counter interrupt */ do_IRQ(MIPS_CPU_IRQ_BASE + 7); else if (pending & CAUSEF_IP4) - do_IRQ(K_INT_TIMER_0 + cpu); /* sb1250_timer_interrupt() */ + do_IRQ(K_INT_TIMER_0 + cpu); /* sb1250_timer_interrupt() */ #ifdef CONFIG_SMP else if (pending & CAUSEF_IP3) diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c index 92da3155ce0..3c02b2a77ae 100644 --- a/arch/mips/sibyte/sb1250/setup.c +++ b/arch/mips/sibyte/sb1250/setup.c @@ -22,6 +22,7 @@ #include <linux/string.h> #include <asm/bootinfo.h> +#include <asm/cpu.h> #include <asm/mipsregs.h> #include <asm/io.h> #include <asm/sibyte/sb1250.h> @@ -182,7 +183,7 @@ void __init sb1250_setup(void) int plldiv; int bad_config = 0; - sb1_pass = read_c0_prid() & 0xff; + sb1_pass = read_c0_prid() & PRID_REV_MASK; sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION)); soc_type = SYS_SOC_TYPE(sys_rev); soc_pass = G_SYS_REVISION(sys_rev); @@ -203,8 +204,8 @@ void __init sb1250_setup(void) case K_SYS_REVISION_BCM1250_PASS1: #ifndef CONFIG_SB1_PASS_1_WORKAROUNDS printk("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, " - "and the kernel doesn't have the proper " - "workarounds compiled in. @@@@\n"); + "and the kernel doesn't have the proper " + "workarounds compiled in. @@@@\n"); bad_config = 1; #endif break; @@ -213,28 +214,28 @@ void __init sb1250_setup(void) #if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \ !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) printk("@@@@ This is a BCM1250 A3-A10 board, and the " - "kernel doesn't have the proper workarounds " - "compiled in. @@@@\n"); + "kernel doesn't have the proper workarounds " + "compiled in. @@@@\n"); bad_config = 1; #endif #ifdef CONFIG_CPU_HAS_PREFETCH printk("@@@@ Prefetches may be enabled in this kernel, " - "but are buggy on this board. @@@@\n"); + "but are buggy on this board. @@@@\n"); bad_config = 1; #endif break; case K_SYS_REVISION_BCM1250_PASS2_2: #ifndef CONFIG_SB1_PASS_2_WORKAROUNDS printk("@@@@ This is a BCM1250 B1/B2. board, and the " - "kernel doesn't have the proper workarounds " - "compiled in. @@@@\n"); + "kernel doesn't have the proper workarounds " + "compiled in. @@@@\n"); bad_config = 1; #endif #if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \ !defined(CONFIG_CPU_HAS_PREFETCH) printk("@@@@ This is a BCM1250 B1/B2, but the kernel is " - "conservatively configured for an 'A' stepping. " - "@@@@\n"); + "conservatively configured for an 'A' stepping. " + "@@@@\n"); #endif break; default: diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index 38e7f6bd792..c0c4b3f88a0 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c @@ -48,7 +48,7 @@ static void *mailbox_regs[] = { /* * SMP init and finish on secondary CPUs */ -void __cpuinit sb1250_smp_init(void) +void sb1250_smp_init(void) { unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 | STATUSF_IP1 | STATUSF_IP0; @@ -83,7 +83,7 @@ static inline void sb1250_send_ipi_mask(const struct cpumask *mask, /* * Code to run on secondary just after probing the CPU */ -static void __cpuinit sb1250_init_secondary(void) +static void sb1250_init_secondary(void) { extern void sb1250_smp_init(void); @@ -94,7 +94,7 @@ static void __cpuinit sb1250_init_secondary(void) * Do any tidying up before marking online and running the idle * loop */ -static void __cpuinit sb1250_smp_finish(void) +static void sb1250_smp_finish(void) { extern void sb1250_clockevent_init(void); @@ -103,17 +103,10 @@ static void __cpuinit sb1250_smp_finish(void) } /* - * Final cleanup after all secondaries booted - */ -static void sb1250_cpus_done(void) -{ -} - -/* * Setup the PC, SP, and GP of a secondary processor and start it * running! */ -static void __cpuinit sb1250_boot_secondary(int cpu, struct task_struct *idle) +static void sb1250_boot_secondary(int cpu, struct task_struct *idle) { int retval; @@ -126,7 +119,7 @@ static void __cpuinit sb1250_boot_secondary(int cpu, struct task_struct *idle) /* * Use CFE to find out how many CPUs are available, setting up - * cpu_possible_map and the logical/physical mappings. + * cpu_possible_mask and the logical/physical mappings. * XXXKW will the boot CPU ever not be physical 0? * * Common setup before any secondaries are started @@ -135,14 +128,13 @@ static void __init sb1250_smp_setup(void) { int i, num; - cpus_clear(cpu_possible_map); - cpu_set(0, cpu_possible_map); + init_cpu_possible(cpumask_of(0)); __cpu_number_map[0] = 0; __cpu_logical_map[0] = 0; for (i = 1, num = 0; i < NR_CPUS; i++) { if (cfe_cpu_stop(i) == 0) { - cpu_set(i, cpu_possible_map); + set_cpu_possible(i, true); __cpu_number_map[i] = ++num; __cpu_logical_map[num] = i; } @@ -159,7 +151,6 @@ struct plat_smp_ops sb_smp_ops = { .send_ipi_mask = sb1250_send_ipi_mask, .init_secondary = sb1250_init_secondary, .smp_finish = sb1250_smp_finish, - .cpus_done = sb1250_cpus_done, .boot_secondary = sb1250_boot_secondary, .smp_setup = sb1250_smp_setup, .prepare_cpus = sb1250_prepare_cpus, @@ -171,7 +162,7 @@ void sb1250_mailbox_interrupt(void) int irq = K_INT_MBOX_0; unsigned int action; - kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); + kstat_incr_irq_this_cpu(irq); /* Load the mailbox register to figure out what we're supposed to do */ action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff; |
