diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/sgi-gru/gruhandles.c | 12 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/gruprocfs.c | 39 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grutables.h | 8 |
3 files changed, 59 insertions, 0 deletions
diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c index 5b82e7def16..9dcf5d89668 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 | ||
38 | struct mcs_op_statistic mcs_op_statistics[mcsop_last]; | ||
39 | |||
40 | static 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 | |||
38 | static void start_instruction(void *h) | 48 | static 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 6d63a8d70f8..8724551aa55 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 | ||
125 | static 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 | |||
142 | static 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 | |||
125 | static int options_show(struct seq_file *s, void *p) | 149 | static 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 | ||
261 | static int mcs_statistics_open(struct inode *inode, struct file *file) | ||
262 | { | ||
263 | return single_open(file, mcs_statistics_show, NULL); | ||
264 | } | ||
265 | |||
236 | static int options_open(struct inode *inode, struct file *file) | 266 | static 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 | ||
290 | static 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 | |||
260 | static const struct file_operations options_fops = { | 298 | static 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 378a0894198..685db88cc47 100644 --- a/drivers/misc/sgi-gru/grutables.h +++ b/drivers/misc/sgi-gru/grutables.h | |||
@@ -242,6 +242,14 @@ struct gru_stats_s { | |||
242 | enum mcs_op {cchop_allocate, cchop_start, cchop_interrupt, cchop_interrupt_sync, | 242 | enum 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 | ||
245 | struct mcs_op_statistic { | ||
246 | atomic_long_t count; | ||
247 | atomic_long_t total; | ||
248 | unsigned long max; | ||
249 | }; | ||
250 | |||
251 | extern 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 |