1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004 Topspin Communications. All rights reserved. 3219820Sjeff * 4219820Sjeff * This software is available to you under a choice of one of two 5219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 6219820Sjeff * General Public License (GPL) Version 2, available from the file 7219820Sjeff * COPYING in the main directory of this source tree, or the 8219820Sjeff * OpenIB.org BSD license below: 9219820Sjeff * 10219820Sjeff * Redistribution and use in source and binary forms, with or 11219820Sjeff * without modification, are permitted provided that the following 12219820Sjeff * conditions are met: 13219820Sjeff * 14219820Sjeff * - Redistributions of source code must retain the above 15219820Sjeff * copyright notice, this list of conditions and the following 16219820Sjeff * disclaimer. 17219820Sjeff * 18219820Sjeff * - Redistributions in binary form must reproduce the above 19219820Sjeff * copyright notice, this list of conditions and the following 20219820Sjeff * disclaimer in the documentation and/or other materials 21219820Sjeff * provided with the distribution. 22219820Sjeff * 23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30219820Sjeff * SOFTWARE. 31219820Sjeff */ 32219820Sjeff 33219820Sjeff#include <linux/err.h> 34219820Sjeff#include <linux/seq_file.h> 35219820Sjeff 36219820Sjeffstruct file_operations; 37219820Sjeff 38219820Sjeff#include <linux/debugfs.h> 39219820Sjeff 40219820Sjeff#include "ipoib.h" 41219820Sjeff 42219820Sjeffstatic struct dentry *ipoib_root; 43219820Sjeff 44219820Sjeffstatic void format_gid(union ib_gid *gid, char *buf) 45219820Sjeff{ 46219820Sjeff int i, n; 47219820Sjeff 48219820Sjeff for (n = 0, i = 0; i < 8; ++i) { 49219820Sjeff n += sprintf(buf + n, "%x", 50219820Sjeff be16_to_cpu(((__be16 *) gid->raw)[i])); 51219820Sjeff if (i < 7) 52219820Sjeff buf[n++] = ':'; 53219820Sjeff } 54219820Sjeff} 55219820Sjeff 56219820Sjeffstatic void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos) 57219820Sjeff{ 58219820Sjeff struct ipoib_mcast_iter *iter; 59219820Sjeff loff_t n = *pos; 60219820Sjeff 61219820Sjeff iter = ipoib_mcast_iter_init(file->private); 62219820Sjeff if (!iter) 63219820Sjeff return NULL; 64219820Sjeff 65219820Sjeff while (n--) { 66219820Sjeff if (ipoib_mcast_iter_next(iter)) { 67219820Sjeff kfree(iter); 68219820Sjeff return NULL; 69219820Sjeff } 70219820Sjeff } 71219820Sjeff 72219820Sjeff return iter; 73219820Sjeff} 74219820Sjeff 75219820Sjeffstatic void *ipoib_mcg_seq_next(struct seq_file *file, void *iter_ptr, 76219820Sjeff loff_t *pos) 77219820Sjeff{ 78219820Sjeff struct ipoib_mcast_iter *iter = iter_ptr; 79219820Sjeff 80219820Sjeff (*pos)++; 81219820Sjeff 82219820Sjeff if (ipoib_mcast_iter_next(iter)) { 83219820Sjeff kfree(iter); 84219820Sjeff return NULL; 85219820Sjeff } 86219820Sjeff 87219820Sjeff return iter; 88219820Sjeff} 89219820Sjeff 90219820Sjeffstatic void ipoib_mcg_seq_stop(struct seq_file *file, void *iter_ptr) 91219820Sjeff{ 92219820Sjeff /* nothing for now */ 93219820Sjeff} 94219820Sjeff 95219820Sjeffstatic int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr) 96219820Sjeff{ 97219820Sjeff struct ipoib_mcast_iter *iter = iter_ptr; 98219820Sjeff char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; 99219820Sjeff union ib_gid mgid; 100219820Sjeff unsigned long created; 101219820Sjeff unsigned int queuelen, complete, send_only; 102219820Sjeff 103219820Sjeff if (!iter) 104219820Sjeff return 0; 105219820Sjeff 106219820Sjeff ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen, 107219820Sjeff &complete, &send_only); 108219820Sjeff 109219820Sjeff format_gid(&mgid, gid_buf); 110219820Sjeff 111219820Sjeff seq_printf(file, 112219820Sjeff "GID: %s\n" 113219820Sjeff " created: %10ld\n" 114219820Sjeff " queuelen: %9d\n" 115219820Sjeff " complete: %9s\n" 116219820Sjeff " send_only: %8s\n" 117219820Sjeff "\n", 118219820Sjeff gid_buf, created, queuelen, 119219820Sjeff complete ? "yes" : "no", 120219820Sjeff send_only ? "yes" : "no"); 121219820Sjeff 122219820Sjeff return 0; 123219820Sjeff} 124219820Sjeff 125219820Sjeffstatic const struct seq_operations ipoib_mcg_seq_ops = { 126219820Sjeff .start = ipoib_mcg_seq_start, 127219820Sjeff .next = ipoib_mcg_seq_next, 128219820Sjeff .stop = ipoib_mcg_seq_stop, 129219820Sjeff .show = ipoib_mcg_seq_show, 130219820Sjeff}; 131219820Sjeff 132219820Sjeffstatic int ipoib_mcg_open(struct inode *inode, struct file *file) 133219820Sjeff{ 134219820Sjeff struct seq_file *seq; 135219820Sjeff int ret; 136219820Sjeff 137219820Sjeff ret = seq_open(file, &ipoib_mcg_seq_ops); 138219820Sjeff if (ret) 139219820Sjeff return ret; 140219820Sjeff 141219820Sjeff seq = file->private_data; 142219820Sjeff seq->private = inode->i_private; 143219820Sjeff 144219820Sjeff return 0; 145219820Sjeff} 146219820Sjeff 147219820Sjeffstatic const struct file_operations ipoib_mcg_fops = { 148219820Sjeff .owner = THIS_MODULE, 149219820Sjeff .open = ipoib_mcg_open, 150219820Sjeff .read = seq_read, 151219820Sjeff .llseek = seq_lseek, 152219820Sjeff .release = seq_release 153219820Sjeff}; 154219820Sjeff 155219820Sjeffstatic void *ipoib_path_seq_start(struct seq_file *file, loff_t *pos) 156219820Sjeff{ 157219820Sjeff struct ipoib_path_iter *iter; 158219820Sjeff loff_t n = *pos; 159219820Sjeff 160219820Sjeff iter = ipoib_path_iter_init(file->private); 161219820Sjeff if (!iter) 162219820Sjeff return NULL; 163219820Sjeff 164219820Sjeff while (n--) { 165219820Sjeff if (ipoib_path_iter_next(iter)) { 166219820Sjeff kfree(iter); 167219820Sjeff return NULL; 168219820Sjeff } 169219820Sjeff } 170219820Sjeff 171219820Sjeff return iter; 172219820Sjeff} 173219820Sjeff 174219820Sjeffstatic void *ipoib_path_seq_next(struct seq_file *file, void *iter_ptr, 175219820Sjeff loff_t *pos) 176219820Sjeff{ 177219820Sjeff struct ipoib_path_iter *iter = iter_ptr; 178219820Sjeff 179219820Sjeff (*pos)++; 180219820Sjeff 181219820Sjeff if (ipoib_path_iter_next(iter)) { 182219820Sjeff kfree(iter); 183219820Sjeff return NULL; 184219820Sjeff } 185219820Sjeff 186219820Sjeff return iter; 187219820Sjeff} 188219820Sjeff 189219820Sjeffstatic void ipoib_path_seq_stop(struct seq_file *file, void *iter_ptr) 190219820Sjeff{ 191219820Sjeff /* nothing for now */ 192219820Sjeff} 193219820Sjeff 194219820Sjeffstatic int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr) 195219820Sjeff{ 196219820Sjeff struct ipoib_path_iter *iter = iter_ptr; 197219820Sjeff char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; 198219820Sjeff struct ipoib_path path; 199219820Sjeff int rate; 200219820Sjeff 201219820Sjeff if (!iter) 202219820Sjeff return 0; 203219820Sjeff 204219820Sjeff ipoib_path_iter_read(iter, &path); 205219820Sjeff 206219820Sjeff format_gid(&path.pathrec.dgid, gid_buf); 207219820Sjeff 208219820Sjeff seq_printf(file, 209219820Sjeff "GID: %s\n" 210219820Sjeff " complete: %6s\n", 211219820Sjeff gid_buf, path.pathrec.dlid ? "yes" : "no"); 212219820Sjeff 213219820Sjeff if (path.pathrec.dlid) { 214219820Sjeff rate = ib_rate_to_mult(path.pathrec.rate) * 25; 215219820Sjeff 216219820Sjeff seq_printf(file, 217219820Sjeff " DLID: 0x%04x\n" 218219820Sjeff " SL: %12d\n" 219219820Sjeff " rate: %*d%s Gb/sec\n", 220219820Sjeff be16_to_cpu(path.pathrec.dlid), 221219820Sjeff path.pathrec.sl, 222219820Sjeff 10 - ((rate % 10) ? 2 : 0), 223219820Sjeff rate / 10, rate % 10 ? ".5" : ""); 224219820Sjeff } 225219820Sjeff 226219820Sjeff seq_putc(file, '\n'); 227219820Sjeff 228219820Sjeff return 0; 229219820Sjeff} 230219820Sjeff 231219820Sjeffstatic const struct seq_operations ipoib_path_seq_ops = { 232219820Sjeff .start = ipoib_path_seq_start, 233219820Sjeff .next = ipoib_path_seq_next, 234219820Sjeff .stop = ipoib_path_seq_stop, 235219820Sjeff .show = ipoib_path_seq_show, 236219820Sjeff}; 237219820Sjeff 238219820Sjeffstatic int ipoib_path_open(struct inode *inode, struct file *file) 239219820Sjeff{ 240219820Sjeff struct seq_file *seq; 241219820Sjeff int ret; 242219820Sjeff 243219820Sjeff ret = seq_open(file, &ipoib_path_seq_ops); 244219820Sjeff if (ret) 245219820Sjeff return ret; 246219820Sjeff 247219820Sjeff seq = file->private_data; 248219820Sjeff seq->private = inode->i_private; 249219820Sjeff 250219820Sjeff return 0; 251219820Sjeff} 252219820Sjeff 253219820Sjeffstatic const struct file_operations ipoib_path_fops = { 254219820Sjeff .owner = THIS_MODULE, 255219820Sjeff .open = ipoib_path_open, 256219820Sjeff .read = seq_read, 257219820Sjeff .llseek = seq_lseek, 258219820Sjeff .release = seq_release 259219820Sjeff}; 260219820Sjeff 261219820Sjeffvoid ipoib_create_debug_files(struct ifnet *dev) 262219820Sjeff{ 263219820Sjeff struct ipoib_dev_priv *priv = dev->if_softc; 264219820Sjeff char name[IFNAMSIZ + sizeof "_path"]; 265219820Sjeff 266219820Sjeff snprintf(name, sizeof name, "%s_mcg", if_name(dev)); 267219820Sjeff priv->mcg_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO, 268219820Sjeff ipoib_root, dev, &ipoib_mcg_fops); 269219820Sjeff if (!priv->mcg_dentry) 270219820Sjeff ipoib_warn(priv, "failed to create mcg debug file\n"); 271219820Sjeff 272219820Sjeff snprintf(name, sizeof name, "%s_path", if_name(dev)); 273219820Sjeff priv->path_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO, 274219820Sjeff ipoib_root, dev, &ipoib_path_fops); 275219820Sjeff if (!priv->path_dentry) 276219820Sjeff ipoib_warn(priv, "failed to create path debug file\n"); 277219820Sjeff} 278219820Sjeff 279219820Sjeffvoid ipoib_delete_debug_files(struct ifnet *dev) 280219820Sjeff{ 281219820Sjeff struct ipoib_dev_priv *priv = dev->if_softc; 282219820Sjeff 283219820Sjeff if (priv->mcg_dentry) 284219820Sjeff debugfs_remove(priv->mcg_dentry); 285219820Sjeff if (priv->path_dentry) 286219820Sjeff debugfs_remove(priv->path_dentry); 287219820Sjeff} 288219820Sjeff 289219820Sjeffint ipoib_register_debugfs(void) 290219820Sjeff{ 291219820Sjeff ipoib_root = debugfs_create_dir("ipoib", NULL); 292219820Sjeff return ipoib_root ? 0 : -ENOMEM; 293219820Sjeff} 294219820Sjeff 295219820Sjeffvoid ipoib_unregister_debugfs(void) 296219820Sjeff{ 297219820Sjeff debugfs_remove(ipoib_root); 298219820Sjeff} 299