Merge branch 'for-linus' of git://git.kernel.dk/linux-block
[sfrench/cifs-2.6.git] / arch / powerpc / platforms / powernv / vas-debug.c
1 /*
2  * Copyright 2016-17 IBM Corp.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version
7  * 2 of the License, or (at your option) any later version.
8  */
9
10 #define pr_fmt(fmt) "vas: " fmt
11
12 #include <linux/types.h>
13 #include <linux/slab.h>
14 #include <linux/debugfs.h>
15 #include <linux/seq_file.h>
16 #include "vas.h"
17
18 static struct dentry *vas_debugfs;
19
20 static char *cop_to_str(int cop)
21 {
22         switch (cop) {
23         case VAS_COP_TYPE_FAULT:        return "Fault";
24         case VAS_COP_TYPE_842:          return "NX-842 Normal Priority";
25         case VAS_COP_TYPE_842_HIPRI:    return "NX-842 High Priority";
26         case VAS_COP_TYPE_GZIP:         return "NX-GZIP Normal Priority";
27         case VAS_COP_TYPE_GZIP_HIPRI:   return "NX-GZIP High Priority";
28         case VAS_COP_TYPE_FTW:          return "Fast Thread-wakeup";
29         default:                        return "Unknown";
30         }
31 }
32
33 static int info_dbg_show(struct seq_file *s, void *private)
34 {
35         struct vas_window *window = s->private;
36
37         mutex_lock(&vas_mutex);
38
39         /* ensure window is not unmapped */
40         if (!window->hvwc_map)
41                 goto unlock;
42
43         seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop),
44                                         window->tx_win ? "Send" : "Receive");
45         seq_printf(s, "Pid : %d\n", window->pid);
46
47 unlock:
48         mutex_unlock(&vas_mutex);
49         return 0;
50 }
51
52 static int info_dbg_open(struct inode *inode, struct file *file)
53 {
54         return single_open(file, info_dbg_show, inode->i_private);
55 }
56
57 static const struct file_operations info_fops = {
58         .open           = info_dbg_open,
59         .read           = seq_read,
60         .llseek         = seq_lseek,
61         .release        = single_release,
62 };
63
64 static inline void print_reg(struct seq_file *s, struct vas_window *win,
65                         char *name, u32 reg)
66 {
67         seq_printf(s, "0x%016llx %s\n", read_hvwc_reg(win, name, reg), name);
68 }
69
70 static int hvwc_dbg_show(struct seq_file *s, void *private)
71 {
72         struct vas_window *window = s->private;
73
74         mutex_lock(&vas_mutex);
75
76         /* ensure window is not unmapped */
77         if (!window->hvwc_map)
78                 goto unlock;
79
80         print_reg(s, window, VREG(LPID));
81         print_reg(s, window, VREG(PID));
82         print_reg(s, window, VREG(XLATE_MSR));
83         print_reg(s, window, VREG(XLATE_LPCR));
84         print_reg(s, window, VREG(XLATE_CTL));
85         print_reg(s, window, VREG(AMR));
86         print_reg(s, window, VREG(SEIDR));
87         print_reg(s, window, VREG(FAULT_TX_WIN));
88         print_reg(s, window, VREG(OSU_INTR_SRC_RA));
89         print_reg(s, window, VREG(HV_INTR_SRC_RA));
90         print_reg(s, window, VREG(PSWID));
91         print_reg(s, window, VREG(LFIFO_BAR));
92         print_reg(s, window, VREG(LDATA_STAMP_CTL));
93         print_reg(s, window, VREG(LDMA_CACHE_CTL));
94         print_reg(s, window, VREG(LRFIFO_PUSH));
95         print_reg(s, window, VREG(CURR_MSG_COUNT));
96         print_reg(s, window, VREG(LNOTIFY_AFTER_COUNT));
97         print_reg(s, window, VREG(LRX_WCRED));
98         print_reg(s, window, VREG(LRX_WCRED_ADDER));
99         print_reg(s, window, VREG(TX_WCRED));
100         print_reg(s, window, VREG(TX_WCRED_ADDER));
101         print_reg(s, window, VREG(LFIFO_SIZE));
102         print_reg(s, window, VREG(WINCTL));
103         print_reg(s, window, VREG(WIN_STATUS));
104         print_reg(s, window, VREG(WIN_CTX_CACHING_CTL));
105         print_reg(s, window, VREG(TX_RSVD_BUF_COUNT));
106         print_reg(s, window, VREG(LRFIFO_WIN_PTR));
107         print_reg(s, window, VREG(LNOTIFY_CTL));
108         print_reg(s, window, VREG(LNOTIFY_PID));
109         print_reg(s, window, VREG(LNOTIFY_LPID));
110         print_reg(s, window, VREG(LNOTIFY_TID));
111         print_reg(s, window, VREG(LNOTIFY_SCOPE));
112         print_reg(s, window, VREG(NX_UTIL_ADDER));
113 unlock:
114         mutex_unlock(&vas_mutex);
115         return 0;
116 }
117
118 static int hvwc_dbg_open(struct inode *inode, struct file *file)
119 {
120         return single_open(file, hvwc_dbg_show, inode->i_private);
121 }
122
123 static const struct file_operations hvwc_fops = {
124         .open           = hvwc_dbg_open,
125         .read           = seq_read,
126         .llseek         = seq_lseek,
127         .release        = single_release,
128 };
129
130 void vas_window_free_dbgdir(struct vas_window *window)
131 {
132         if (window->dbgdir) {
133                 debugfs_remove_recursive(window->dbgdir);
134                 kfree(window->dbgname);
135                 window->dbgdir = NULL;
136                 window->dbgname = NULL;
137         }
138 }
139
140 void vas_window_init_dbgdir(struct vas_window *window)
141 {
142         struct dentry *f, *d;
143
144         if (!window->vinst->dbgdir)
145                 return;
146
147         window->dbgname = kzalloc(16, GFP_KERNEL);
148         if (!window->dbgname)
149                 return;
150
151         snprintf(window->dbgname, 16, "w%d", window->winid);
152
153         d = debugfs_create_dir(window->dbgname, window->vinst->dbgdir);
154         if (IS_ERR(d))
155                 goto free_name;
156
157         window->dbgdir = d;
158
159         f = debugfs_create_file("info", 0444, d, window, &info_fops);
160         if (IS_ERR(f))
161                 goto remove_dir;
162
163         f = debugfs_create_file("hvwc", 0444, d, window, &hvwc_fops);
164         if (IS_ERR(f))
165                 goto remove_dir;
166
167         return;
168
169 free_name:
170         kfree(window->dbgname);
171         window->dbgname = NULL;
172
173 remove_dir:
174         debugfs_remove_recursive(window->dbgdir);
175         window->dbgdir = NULL;
176 }
177
178 void vas_instance_init_dbgdir(struct vas_instance *vinst)
179 {
180         struct dentry *d;
181
182         if (!vas_debugfs)
183                 return;
184
185         vinst->dbgname = kzalloc(16, GFP_KERNEL);
186         if (!vinst->dbgname)
187                 return;
188
189         snprintf(vinst->dbgname, 16, "v%d", vinst->vas_id);
190
191         d = debugfs_create_dir(vinst->dbgname, vas_debugfs);
192         if (IS_ERR(d))
193                 goto free_name;
194
195         vinst->dbgdir = d;
196         return;
197
198 free_name:
199         kfree(vinst->dbgname);
200         vinst->dbgname = NULL;
201         vinst->dbgdir = NULL;
202 }
203
204 void vas_init_dbgdir(void)
205 {
206         vas_debugfs = debugfs_create_dir("vas", NULL);
207         if (IS_ERR(vas_debugfs))
208                 vas_debugfs = NULL;
209 }