From: Ralf Baechle Date: Wed, 19 Jun 2013 18:18:55 +0000 (+0200) Subject: MIPS: Sibyte: Fix bus watcher build for BCM1x55 and BCM1x80. X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=ae5b0e0973ae1326809084aa3243a97f180cc903;p=GitHub%2Fexynos8895%2Fandroid_kernel_samsung_universal8895.git MIPS: Sibyte: Fix bus watcher build for BCM1x55 and BCM1x80. CC arch/mips/sibyte/bcm1480/bus_watcher.o CHK kernel/config_data.h arch/mips/sibyte/bcm1480/bus_watcher.c: In function ‘check_bus_watcher’: arch/mips/sibyte/bcm1480/bus_watcher.c:86:82: error: ‘A_SCD_BUS_ERR_STATUS_DEBUG’ undeclared (first use in this function) arch/mips/sibyte/bcm1480/bus_watcher.c:86:82: note: each undeclared identifier is reported only once for each function it appears in make[3]: *** [arch/mips/sibyte/bcm1480/bus_watcher.o] Error 1 make[2]: *** [arch/mips/sibyte/bcm1480] Error 2 make[1]: *** [arch/mips/sibyte] Error 2 make: *** [arch/mips] Error 2 The register moved around though it's otherwise the same but because of the changed address it now also has a different name. Signed-off-by: Ralf Baechle Patchwork: https://patchwork.linux-mips.org/patch/5514/ Reported-by: Markos Chandras --- diff --git a/arch/mips/sibyte/common/Makefile b/arch/mips/sibyte/common/Makefile index 36aa700cc40c..b3d6bf23a662 100644 --- a/arch/mips/sibyte/common/Makefile +++ b/arch/mips/sibyte/common/Makefile @@ -1,3 +1,4 @@ obj-y := cfe.o +obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o obj-$(CONFIG_SIBYTE_CFE_CONSOLE) += cfe_console.o obj-$(CONFIG_SIBYTE_TBPROF) += sb_tbprof.o diff --git a/arch/mips/sibyte/common/bus_watcher.c b/arch/mips/sibyte/common/bus_watcher.c new file mode 100644 index 000000000000..5581844c9194 --- /dev/null +++ b/arch/mips/sibyte/common/bus_watcher.c @@ -0,0 +1,256 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) +#include +#endif + + +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)); +#elif defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250) + /* Use non-destructive register */ + status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS_DEBUG)); +#elif defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) + /* Use non-destructive register */ + /* Same as 1250 except BUS_ERR_STATUS_DEBUG is in a different place. */ + status = csr_in32(IOADDR(A_BCM1480_BUS_ERR_STATUS_DEBUG)); +#else +#error bus watcher being built for unknown Sibyte SOC! +#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"); +} + +#ifdef CONFIG_PROC_FS + +/* For simplicity, I want to assume a single read is required each + time */ +static int bw_proc_show(struct seq_file *m, void *v) +{ + struct bw_stats_struct *stats = m->private; + + seq_puts(m, "SiByte Bus Watcher statistics\n"); + seq_puts(m, "-----------------------------\n"); + seq_printf(m, "L2-d-cor %8ld\nL2-d-bad %8ld\n", + stats->l2_cor_d, stats->l2_bad_d); + seq_printf(m, "L2-t-cor %8ld\nL2-t-bad %8ld\n", + stats->l2_cor_t, stats->l2_bad_t); + seq_printf(m, "MC-d-cor %8ld\nMC-d-bad %8ld\n", + stats->mem_cor_d, stats->mem_bad_d); + seq_printf(m, "IO-err %8ld\n", stats->bus_error); + seq_puts(m, "\nLast recorded signature:\n"); + seq_printf(m, "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) + seq_puts(m, "Multiple errors observed since last check.\n"); + if (stats->status_printed) { + seq_puts(m, "(no change since last printing)\n"); + } else { + stats->status_printed = 1; + } + + return 0; +} + +static int bw_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, bw_proc_show, PDE_DATA(inode)); +} + +static const struct file_operations bw_proc_fops = { + .open = bw_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void create_proc_decoder(struct bw_stats_struct *stats) +{ + struct proc_dir_entry *ent; + + ent = proc_create_data("bus_watcher", S_IWUSR | S_IRUGO, NULL, + &bw_proc_fops, 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 + +#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)); + + 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/Makefile b/arch/mips/sibyte/sb1250/Makefile index d3d969de407b..cdc4c56c3e29 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 d0ca7b91c417..000000000000 --- a/arch/mips/sibyte/sb1250/bus_watcher.c +++ /dev/null @@ -1,247 +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 -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -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"); -} - -#ifdef CONFIG_PROC_FS - -/* For simplicity, I want to assume a single read is required each - time */ -static int bw_proc_show(struct seq_file *m, void *v) -{ - struct bw_stats_struct *stats = m->private; - - seq_puts(m, "SiByte Bus Watcher statistics\n"); - seq_puts(m, "-----------------------------\n"); - seq_printf(m, "L2-d-cor %8ld\nL2-d-bad %8ld\n", - stats->l2_cor_d, stats->l2_bad_d); - seq_printf(m, "L2-t-cor %8ld\nL2-t-bad %8ld\n", - stats->l2_cor_t, stats->l2_bad_t); - seq_printf(m, "MC-d-cor %8ld\nMC-d-bad %8ld\n", - stats->mem_cor_d, stats->mem_bad_d); - seq_printf(m, "IO-err %8ld\n", stats->bus_error); - seq_puts(m, "\nLast recorded signature:\n"); - seq_printf(m, "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) - seq_puts(m, "Multiple errors observed since last check.\n"); - if (stats->status_printed) { - seq_puts(m, "(no change since last printing)\n"); - } else { - stats->status_printed = 1; - } - - return 0; -} - -static int bw_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, bw_proc_show, PDE_DATA(inode)); -} - -static const struct file_operations bw_proc_fops = { - .open = bw_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static void create_proc_decoder(struct bw_stats_struct *stats) -{ - struct proc_dir_entry *ent; - - ent = proc_create_data("bus_watcher", S_IWUSR | S_IRUGO, NULL, - &bw_proc_fops, 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 - -#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)); - - 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);