1 /* 2 * Copyright (c) 2013 - 2017 Intel Corporation. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 #include <linux/debugfs.h> 33 #include <linux/seq_file.h> 34 #include <linux/kernel.h> 35 #include <linux/export.h> 36 37 #include "qib.h" 38 #include "qib_verbs.h" 39 #include "qib_debugfs.h" 40 41 static struct dentry *qib_dbg_root; 42 43 #define DEBUGFS_FILE(name) \ 44 static const struct seq_operations _##name##_seq_ops = { \ 45 .start = _##name##_seq_start, \ 46 .next = _##name##_seq_next, \ 47 .stop = _##name##_seq_stop, \ 48 .show = _##name##_seq_show \ 49 }; \ 50 static int _##name##_open(struct inode *inode, struct file *s) \ 51 { \ 52 struct seq_file *seq; \ 53 int ret; \ 54 ret = seq_open(s, &_##name##_seq_ops); \ 55 if (ret) \ 56 return ret; \ 57 seq = s->private_data; \ 58 seq->private = inode->i_private; \ 59 return 0; \ 60 } \ 61 static const struct file_operations _##name##_file_ops = { \ 62 .owner = THIS_MODULE, \ 63 .open = _##name##_open, \ 64 .read = seq_read, \ 65 .llseek = seq_lseek, \ 66 .release = seq_release \ 67 }; 68 69 #define DEBUGFS_FILE_CREATE(name) \ 70 do { \ 71 struct dentry *ent; \ 72 ent = debugfs_create_file(#name , 0400, ibd->qib_ibdev_dbg, \ 73 ibd, &_##name##_file_ops); \ 74 if (!ent) \ 75 pr_warn("create of " #name " failed\n"); \ 76 } while (0) 77 78 static void *_opcode_stats_seq_start(struct seq_file *s, loff_t *pos) 79 { 80 struct qib_opcode_stats_perctx *opstats; 81 82 if (*pos >= ARRAY_SIZE(opstats->stats)) 83 return NULL; 84 return pos; 85 } 86 87 static void *_opcode_stats_seq_next(struct seq_file *s, void *v, loff_t *pos) 88 { 89 struct qib_opcode_stats_perctx *opstats; 90 91 ++*pos; 92 if (*pos >= ARRAY_SIZE(opstats->stats)) 93 return NULL; 94 return pos; 95 } 96 97 98 static void _opcode_stats_seq_stop(struct seq_file *s, void *v) 99 { 100 /* nothing allocated */ 101 } 102 103 static int _opcode_stats_seq_show(struct seq_file *s, void *v) 104 { 105 loff_t *spos = v; 106 loff_t i = *spos, j; 107 u64 n_packets = 0, n_bytes = 0; 108 struct qib_ibdev *ibd = (struct qib_ibdev *)s->private; 109 struct qib_devdata *dd = dd_from_dev(ibd); 110 111 for (j = 0; j < dd->first_user_ctxt; j++) { 112 if (!dd->rcd[j]) 113 continue; 114 n_packets += dd->rcd[j]->opstats->stats[i].n_packets; 115 n_bytes += dd->rcd[j]->opstats->stats[i].n_bytes; 116 } 117 if (!n_packets && !n_bytes) 118 return SEQ_SKIP; 119 seq_printf(s, "%02llx %llu/%llu\n", i, 120 (unsigned long long) n_packets, 121 (unsigned long long) n_bytes); 122 123 return 0; 124 } 125 126 DEBUGFS_FILE(opcode_stats) 127 128 static void *_ctx_stats_seq_start(struct seq_file *s, loff_t *pos) 129 { 130 struct qib_ibdev *ibd = (struct qib_ibdev *)s->private; 131 struct qib_devdata *dd = dd_from_dev(ibd); 132 133 if (!*pos) 134 return SEQ_START_TOKEN; 135 if (*pos >= dd->first_user_ctxt) 136 return NULL; 137 return pos; 138 } 139 140 static void *_ctx_stats_seq_next(struct seq_file *s, void *v, loff_t *pos) 141 { 142 struct qib_ibdev *ibd = (struct qib_ibdev *)s->private; 143 struct qib_devdata *dd = dd_from_dev(ibd); 144 145 if (v == SEQ_START_TOKEN) 146 return pos; 147 148 ++*pos; 149 if (*pos >= dd->first_user_ctxt) 150 return NULL; 151 return pos; 152 } 153 154 static void _ctx_stats_seq_stop(struct seq_file *s, void *v) 155 { 156 /* nothing allocated */ 157 } 158 159 static int _ctx_stats_seq_show(struct seq_file *s, void *v) 160 { 161 loff_t *spos; 162 loff_t i, j; 163 u64 n_packets = 0; 164 struct qib_ibdev *ibd = (struct qib_ibdev *)s->private; 165 struct qib_devdata *dd = dd_from_dev(ibd); 166 167 if (v == SEQ_START_TOKEN) { 168 seq_puts(s, "Ctx:npkts\n"); 169 return 0; 170 } 171 172 spos = v; 173 i = *spos; 174 175 if (!dd->rcd[i]) 176 return SEQ_SKIP; 177 178 for (j = 0; j < ARRAY_SIZE(dd->rcd[i]->opstats->stats); j++) 179 n_packets += dd->rcd[i]->opstats->stats[j].n_packets; 180 181 if (!n_packets) 182 return SEQ_SKIP; 183 184 seq_printf(s, " %llu:%llu\n", i, n_packets); 185 return 0; 186 } 187 188 DEBUGFS_FILE(ctx_stats) 189 190 static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos) 191 __acquires(RCU) 192 { 193 struct rvt_qp_iter *iter; 194 loff_t n = *pos; 195 196 iter = rvt_qp_iter_init(s->private, 0, NULL); 197 198 /* stop calls rcu_read_unlock */ 199 rcu_read_lock(); 200 201 if (!iter) 202 return NULL; 203 204 do { 205 if (rvt_qp_iter_next(iter)) { 206 kfree(iter); 207 return NULL; 208 } 209 } while (n--); 210 211 return iter; 212 } 213 214 static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr, 215 loff_t *pos) 216 __must_hold(RCU) 217 { 218 struct rvt_qp_iter *iter = iter_ptr; 219 220 (*pos)++; 221 222 if (rvt_qp_iter_next(iter)) { 223 kfree(iter); 224 return NULL; 225 } 226 227 return iter; 228 } 229 230 static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr) 231 __releases(RCU) 232 { 233 rcu_read_unlock(); 234 } 235 236 static int _qp_stats_seq_show(struct seq_file *s, void *iter_ptr) 237 { 238 struct rvt_qp_iter *iter = iter_ptr; 239 240 if (!iter) 241 return 0; 242 243 qib_qp_iter_print(s, iter); 244 245 return 0; 246 } 247 248 DEBUGFS_FILE(qp_stats) 249 250 void qib_dbg_ibdev_init(struct qib_ibdev *ibd) 251 { 252 char name[10]; 253 254 snprintf(name, sizeof(name), "qib%d", dd_from_dev(ibd)->unit); 255 ibd->qib_ibdev_dbg = debugfs_create_dir(name, qib_dbg_root); 256 if (!ibd->qib_ibdev_dbg) { 257 pr_warn("create of %s failed\n", name); 258 return; 259 } 260 DEBUGFS_FILE_CREATE(opcode_stats); 261 DEBUGFS_FILE_CREATE(ctx_stats); 262 DEBUGFS_FILE_CREATE(qp_stats); 263 } 264 265 void qib_dbg_ibdev_exit(struct qib_ibdev *ibd) 266 { 267 if (!qib_dbg_root) 268 goto out; 269 debugfs_remove_recursive(ibd->qib_ibdev_dbg); 270 out: 271 ibd->qib_ibdev_dbg = NULL; 272 } 273 274 void qib_dbg_init(void) 275 { 276 qib_dbg_root = debugfs_create_dir(QIB_DRV_NAME, NULL); 277 if (!qib_dbg_root) 278 pr_warn("init of debugfs failed\n"); 279 } 280 281 void qib_dbg_exit(void) 282 { 283 debugfs_remove_recursive(qib_dbg_root); 284 qib_dbg_root = NULL; 285 } 286