aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/sibyte/sb1250
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/sibyte/sb1250')
-rw-r--r--arch/mips/sibyte/sb1250/Makefile1
-rw-r--r--arch/mips/sibyte/sb1250/bus_watcher.c258
-rw-r--r--arch/mips/sibyte/sb1250/irq.c19
-rw-r--r--arch/mips/sibyte/sb1250/setup.c21
-rw-r--r--arch/mips/sibyte/sb1250/smp.c25
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;