aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/sgi-gru/gruhandles.c12
-rw-r--r--drivers/misc/sgi-gru/gruprocfs.c39
-rw-r--r--drivers/misc/sgi-gru/grutables.h8
3 files changed, 59 insertions, 0 deletions
diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c
index 5b82e7def16d..9dcf5d896683 100644
--- a/drivers/misc/sgi-gru/gruhandles.c
+++ b/drivers/misc/sgi-gru/gruhandles.c
@@ -35,6 +35,16 @@
35/* Extract the status field from a kernel handle */ 35/* Extract the status field from a kernel handle */
36#define GET_MSEG_HANDLE_STATUS(h) (((*(unsigned long *)(h)) >> 16) & 3) 36#define GET_MSEG_HANDLE_STATUS(h) (((*(unsigned long *)(h)) >> 16) & 3)
37 37
38struct mcs_op_statistic mcs_op_statistics[mcsop_last];
39
40static void update_mcs_stats(enum mcs_op op, unsigned long clks)
41{
42 atomic_long_inc(&mcs_op_statistics[op].count);
43 atomic_long_add(clks, &mcs_op_statistics[op].total);
44 if (mcs_op_statistics[op].max < clks)
45 mcs_op_statistics[op].max = clks;
46}
47
38static void start_instruction(void *h) 48static void start_instruction(void *h)
39{ 49{
40 unsigned long *w0 = h; 50 unsigned long *w0 = h;
@@ -57,6 +67,8 @@ static int wait_instruction_complete(void *h, enum mcs_op opc)
57 if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time)) 67 if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time))
58 panic("GRU %p is malfunctioning\n", h); 68 panic("GRU %p is malfunctioning\n", h);
59 } 69 }
70 if (gru_options & OPT_STATS)
71 update_mcs_stats(opc, get_cycles() - start_time);
60 return status; 72 return status;
61} 73}
62 74
diff --git a/drivers/misc/sgi-gru/gruprocfs.c b/drivers/misc/sgi-gru/gruprocfs.c
index 6d63a8d70f86..8724551aa55e 100644
--- a/drivers/misc/sgi-gru/gruprocfs.c
+++ b/drivers/misc/sgi-gru/gruprocfs.c
@@ -122,6 +122,30 @@ static ssize_t statistics_write(struct file *file, const char __user *userbuf,
122 return count; 122 return count;
123} 123}
124 124
125static int mcs_statistics_show(struct seq_file *s, void *p)
126{
127 int op;
128 unsigned long total, count, max;
129 static char *id[] = {"cch_allocate", "cch_start", "cch_interrupt",
130 "cch_interrupt_sync", "cch_deallocate", "tgh_invalidate"};
131
132 for (op = 0; op < mcsop_last; op++) {
133 count = atomic_long_read(&mcs_op_statistics[op].count);
134 total = atomic_long_read(&mcs_op_statistics[op].total);
135 max = mcs_op_statistics[op].max;
136 seq_printf(s, "%-20s%12ld%12ld%12ld\n", id[op], count,
137 count ? total / count : 0, max);
138 }
139 return 0;
140}
141
142static ssize_t mcs_statistics_write(struct file *file,
143 const char __user *userbuf, size_t count, loff_t *data)
144{
145 memset(mcs_op_statistics, 0, sizeof(mcs_op_statistics));
146 return count;
147}
148
125static int options_show(struct seq_file *s, void *p) 149static int options_show(struct seq_file *s, void *p)
126{ 150{
127 seq_printf(s, "0x%lx\n", gru_options); 151 seq_printf(s, "0x%lx\n", gru_options);
@@ -137,6 +161,7 @@ static ssize_t options_write(struct file *file, const char __user *userbuf,
137 if (copy_from_user 161 if (copy_from_user
138 (buf, userbuf, count < sizeof(buf) ? count : sizeof(buf))) 162 (buf, userbuf, count < sizeof(buf) ? count : sizeof(buf)))
139 return -EFAULT; 163 return -EFAULT;
164 buf[count - 1] = '\0';
140 if (!strict_strtoul(buf, 10, &val)) 165 if (!strict_strtoul(buf, 10, &val))
141 gru_options = val; 166 gru_options = val;
142 167
@@ -233,6 +258,11 @@ static int statistics_open(struct inode *inode, struct file *file)
233 return single_open(file, statistics_show, NULL); 258 return single_open(file, statistics_show, NULL);
234} 259}
235 260
261static int mcs_statistics_open(struct inode *inode, struct file *file)
262{
263 return single_open(file, mcs_statistics_show, NULL);
264}
265
236static int options_open(struct inode *inode, struct file *file) 266static int options_open(struct inode *inode, struct file *file)
237{ 267{
238 return single_open(file, options_show, NULL); 268 return single_open(file, options_show, NULL);
@@ -257,6 +287,14 @@ static const struct file_operations statistics_fops = {
257 .release = single_release, 287 .release = single_release,
258}; 288};
259 289
290static const struct file_operations mcs_statistics_fops = {
291 .open = mcs_statistics_open,
292 .read = seq_read,
293 .write = mcs_statistics_write,
294 .llseek = seq_lseek,
295 .release = single_release,
296};
297
260static const struct file_operations options_fops = { 298static const struct file_operations options_fops = {
261 .open = options_open, 299 .open = options_open,
262 .read = seq_read, 300 .read = seq_read,
@@ -285,6 +323,7 @@ static struct proc_entry {
285 struct proc_dir_entry *entry; 323 struct proc_dir_entry *entry;
286} proc_files[] = { 324} proc_files[] = {
287 {"statistics", 0644, &statistics_fops}, 325 {"statistics", 0644, &statistics_fops},
326 {"mcs_statistics", 0644, &mcs_statistics_fops},
288 {"debug_options", 0644, &options_fops}, 327 {"debug_options", 0644, &options_fops},
289 {"cch_status", 0444, &cch_fops}, 328 {"cch_status", 0444, &cch_fops},
290 {"gru_status", 0444, &gru_fops}, 329 {"gru_status", 0444, &gru_fops},
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h
index 378a0894198e..685db88cc475 100644
--- a/drivers/misc/sgi-gru/grutables.h
+++ b/drivers/misc/sgi-gru/grutables.h
@@ -242,6 +242,14 @@ struct gru_stats_s {
242enum mcs_op {cchop_allocate, cchop_start, cchop_interrupt, cchop_interrupt_sync, 242enum mcs_op {cchop_allocate, cchop_start, cchop_interrupt, cchop_interrupt_sync,
243 cchop_deallocate, tghop_invalidate, mcsop_last}; 243 cchop_deallocate, tghop_invalidate, mcsop_last};
244 244
245struct mcs_op_statistic {
246 atomic_long_t count;
247 atomic_long_t total;
248 unsigned long max;
249};
250
251extern struct mcs_op_statistic mcs_op_statistics[mcsop_last];
252
245#define OPT_DPRINT 1 253#define OPT_DPRINT 1
246#define OPT_STATS 2 254#define OPT_STATS 2
247#define GRU_QUICKLOOK 4 255#define GRU_QUICKLOOK 4