diff options
Diffstat (limited to 'arch/mips/sibyte/sb1250/bus_watcher.c')
-rw-r--r-- | arch/mips/sibyte/sb1250/bus_watcher.c | 81 |
1 files changed, 37 insertions, 44 deletions
diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c index e651105b3f0b..cb1e3cb37d70 100644 --- a/arch/mips/sibyte/sb1250/bus_watcher.c +++ b/arch/mips/sibyte/sb1250/bus_watcher.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
32 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
33 | #include <linux/seq_file.h> | ||
33 | #include <asm/io.h> | 34 | #include <asm/io.h> |
34 | 35 | ||
35 | #include <asm/sibyte/sb1250.h> | 36 | #include <asm/sibyte/sb1250.h> |
@@ -99,63 +100,60 @@ void check_bus_watcher(void) | |||
99 | printk("Bus watcher indicates no error\n"); | 100 | printk("Bus watcher indicates no error\n"); |
100 | } | 101 | } |
101 | 102 | ||
102 | static int bw_print_buffer(char *page, struct bw_stats_struct *stats) | 103 | #ifdef CONFIG_PROC_FS |
104 | |||
105 | /* For simplicity, I want to assume a single read is required each | ||
106 | time */ | ||
107 | static int bw_proc_show(struct seq_file *m, void *v) | ||
103 | { | 108 | { |
104 | int len; | 109 | struct bw_stats_struct *stats = m->private; |
105 | 110 | ||
106 | len = sprintf(page, "SiByte Bus Watcher statistics\n"); | 111 | seq_puts(m, "SiByte Bus Watcher statistics\n"); |
107 | len += sprintf(page+len, "-----------------------------\n"); | 112 | seq_puts(m, "-----------------------------\n"); |
108 | len += sprintf(page+len, "L2-d-cor %8ld\nL2-d-bad %8ld\n", | 113 | seq_printf(m, "L2-d-cor %8ld\nL2-d-bad %8ld\n", |
109 | stats->l2_cor_d, stats->l2_bad_d); | 114 | stats->l2_cor_d, stats->l2_bad_d); |
110 | len += sprintf(page+len, "L2-t-cor %8ld\nL2-t-bad %8ld\n", | 115 | seq_printf(m, "L2-t-cor %8ld\nL2-t-bad %8ld\n", |
111 | stats->l2_cor_t, stats->l2_bad_t); | 116 | stats->l2_cor_t, stats->l2_bad_t); |
112 | len += sprintf(page+len, "MC-d-cor %8ld\nMC-d-bad %8ld\n", | 117 | seq_printf(m, "MC-d-cor %8ld\nMC-d-bad %8ld\n", |
113 | stats->mem_cor_d, stats->mem_bad_d); | 118 | stats->mem_cor_d, stats->mem_bad_d); |
114 | len += sprintf(page+len, "IO-err %8ld\n", stats->bus_error); | 119 | seq_printf(m, "IO-err %8ld\n", stats->bus_error); |
115 | len += sprintf(page+len, "\nLast recorded signature:\n"); | 120 | seq_puts(m, "\nLast recorded signature:\n"); |
116 | len += sprintf(page+len, "Request %02x from %d, answered by %d with Dcode %d\n", | 121 | seq_printf(m, "Request %02x from %d, answered by %d with Dcode %d\n", |
117 | (unsigned int)(G_SCD_BERR_TID(stats->status) & 0x3f), | 122 | (unsigned int)(G_SCD_BERR_TID(stats->status) & 0x3f), |
118 | (int)(G_SCD_BERR_TID(stats->status) >> 6), | 123 | (int)(G_SCD_BERR_TID(stats->status) >> 6), |
119 | (int)G_SCD_BERR_RID(stats->status), | 124 | (int)G_SCD_BERR_RID(stats->status), |
120 | (int)G_SCD_BERR_DCODE(stats->status)); | 125 | (int)G_SCD_BERR_DCODE(stats->status)); |
121 | /* XXXKW indicate multiple errors between printings, or stats | 126 | /* XXXKW indicate multiple errors between printings, or stats |
122 | collection (or both)? */ | 127 | collection (or both)? */ |
123 | if (stats->status & M_SCD_BERR_MULTERRS) | 128 | if (stats->status & M_SCD_BERR_MULTERRS) |
124 | len += sprintf(page+len, "Multiple errors observed since last check.\n"); | 129 | seq_puts(m, "Multiple errors observed since last check.\n"); |
125 | if (stats->status_printed) { | 130 | if (stats->status_printed) { |
126 | len += sprintf(page+len, "(no change since last printing)\n"); | 131 | seq_puts(m, "(no change since last printing)\n"); |
127 | } else { | 132 | } else { |
128 | stats->status_printed = 1; | 133 | stats->status_printed = 1; |
129 | } | 134 | } |
130 | 135 | ||
131 | return len; | 136 | return 0; |
132 | } | 137 | } |
133 | 138 | ||
134 | #ifdef CONFIG_PROC_FS | 139 | static int bw_proc_open(struct inode *inode, struct file *file) |
135 | |||
136 | /* For simplicity, I want to assume a single read is required each | ||
137 | time */ | ||
138 | static int bw_read_proc(char *page, char **start, off_t off, | ||
139 | int count, int *eof, void *data) | ||
140 | { | 140 | { |
141 | int len; | 141 | return single_open(file, bw_proc_show, PDE_DATA(inode)); |
142 | |||
143 | if (off == 0) { | ||
144 | len = bw_print_buffer(page, data); | ||
145 | *start = page; | ||
146 | } else { | ||
147 | len = 0; | ||
148 | *eof = 1; | ||
149 | } | ||
150 | return len; | ||
151 | } | 142 | } |
152 | 143 | ||
144 | static const struct file_operations bw_proc_fops = { | ||
145 | .open = bw_proc_open, | ||
146 | .read = seq_read, | ||
147 | .llseek = seq_lseek, | ||
148 | .release = seq_release, | ||
149 | }; | ||
150 | |||
153 | static void create_proc_decoder(struct bw_stats_struct *stats) | 151 | static void create_proc_decoder(struct bw_stats_struct *stats) |
154 | { | 152 | { |
155 | struct proc_dir_entry *ent; | 153 | struct proc_dir_entry *ent; |
156 | 154 | ||
157 | ent = create_proc_read_entry("bus_watcher", S_IWUSR | S_IRUGO, NULL, | 155 | ent = proc_create_data("bus_watcher", S_IWUSR | S_IRUGO, NULL, |
158 | bw_read_proc, stats); | 156 | &bw_proc_fops, stats); |
159 | if (!ent) { | 157 | if (!ent) { |
160 | printk(KERN_INFO "Unable to initialize bus_watcher /proc entry\n"); | 158 | printk(KERN_INFO "Unable to initialize bus_watcher /proc entry\n"); |
161 | return; | 159 | return; |
@@ -210,11 +208,6 @@ static irqreturn_t sibyte_bw_int(int irq, void *data) | |||
210 | stats->bus_error += G_SCD_MEM_BUSERR(cntr); | 208 | stats->bus_error += G_SCD_MEM_BUSERR(cntr); |
211 | csr_out32(0, IOADDR(A_BUS_MEM_IO_ERRORS)); | 209 | csr_out32(0, IOADDR(A_BUS_MEM_IO_ERRORS)); |
212 | 210 | ||
213 | #ifndef CONFIG_PROC_FS | ||
214 | bw_print_buffer(bw_buf, stats); | ||
215 | printk(bw_buf); | ||
216 | #endif | ||
217 | |||
218 | return IRQ_HANDLED; | 211 | return IRQ_HANDLED; |
219 | } | 212 | } |
220 | 213 | ||