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 33337096Shselasky#include <sys/cdefs.h> 34337096Shselasky__FBSDID("$FreeBSD$"); 35337096Shselasky 36219820Sjeff#include <linux/err.h> 37219820Sjeff#include <linux/seq_file.h> 38219820Sjeff 39219820Sjeffstruct file_operations; 40219820Sjeff 41219820Sjeff#include <linux/debugfs.h> 42219820Sjeff 43219820Sjeff#include "ipoib.h" 44219820Sjeff 45219820Sjeffstatic struct dentry *ipoib_root; 46219820Sjeff 47219820Sjeffstatic void format_gid(union ib_gid *gid, char *buf) 48219820Sjeff{ 49219820Sjeff int i, n; 50219820Sjeff 51219820Sjeff for (n = 0, i = 0; i < 8; ++i) { 52219820Sjeff n += sprintf(buf + n, "%x", 53219820Sjeff be16_to_cpu(((__be16 *) gid->raw)[i])); 54219820Sjeff if (i < 7) 55219820Sjeff buf[n++] = ':'; 56219820Sjeff } 57219820Sjeff} 58219820Sjeff 59219820Sjeffstatic void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos) 60219820Sjeff{ 61219820Sjeff struct ipoib_mcast_iter *iter; 62219820Sjeff loff_t n = *pos; 63219820Sjeff 64219820Sjeff iter = ipoib_mcast_iter_init(file->private); 65219820Sjeff if (!iter) 66219820Sjeff return NULL; 67219820Sjeff 68219820Sjeff while (n--) { 69219820Sjeff if (ipoib_mcast_iter_next(iter)) { 70219820Sjeff kfree(iter); 71219820Sjeff return NULL; 72219820Sjeff } 73219820Sjeff } 74219820Sjeff 75219820Sjeff return iter; 76219820Sjeff} 77219820Sjeff 78219820Sjeffstatic void *ipoib_mcg_seq_next(struct seq_file *file, void *iter_ptr, 79219820Sjeff loff_t *pos) 80219820Sjeff{ 81219820Sjeff struct ipoib_mcast_iter *iter = iter_ptr; 82219820Sjeff 83219820Sjeff (*pos)++; 84219820Sjeff 85219820Sjeff if (ipoib_mcast_iter_next(iter)) { 86219820Sjeff kfree(iter); 87219820Sjeff return NULL; 88219820Sjeff } 89219820Sjeff 90219820Sjeff return iter; 91219820Sjeff} 92219820Sjeff 93219820Sjeffstatic void ipoib_mcg_seq_stop(struct seq_file *file, void *iter_ptr) 94219820Sjeff{ 95219820Sjeff /* nothing for now */ 96219820Sjeff} 97219820Sjeff 98219820Sjeffstatic int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr) 99219820Sjeff{ 100219820Sjeff struct ipoib_mcast_iter *iter = iter_ptr; 101219820Sjeff char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; 102219820Sjeff union ib_gid mgid; 103219820Sjeff unsigned long created; 104219820Sjeff unsigned int queuelen, complete, send_only; 105219820Sjeff 106219820Sjeff if (!iter) 107219820Sjeff return 0; 108219820Sjeff 109219820Sjeff ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen, 110219820Sjeff &complete, &send_only); 111219820Sjeff 112219820Sjeff format_gid(&mgid, gid_buf); 113219820Sjeff 114219820Sjeff seq_printf(file, 115219820Sjeff "GID: %s\n" 116219820Sjeff " created: %10ld\n" 117219820Sjeff " queuelen: %9d\n" 118219820Sjeff " complete: %9s\n" 119219820Sjeff " send_only: %8s\n" 120219820Sjeff "\n", 121219820Sjeff gid_buf, created, queuelen, 122219820Sjeff complete ? "yes" : "no", 123219820Sjeff send_only ? "yes" : "no"); 124219820Sjeff 125219820Sjeff return 0; 126219820Sjeff} 127219820Sjeff 128219820Sjeffstatic const struct seq_operations ipoib_mcg_seq_ops = { 129219820Sjeff .start = ipoib_mcg_seq_start, 130219820Sjeff .next = ipoib_mcg_seq_next, 131219820Sjeff .stop = ipoib_mcg_seq_stop, 132219820Sjeff .show = ipoib_mcg_seq_show, 133219820Sjeff}; 134219820Sjeff 135219820Sjeffstatic int ipoib_mcg_open(struct inode *inode, struct file *file) 136219820Sjeff{ 137219820Sjeff struct seq_file *seq; 138219820Sjeff int ret; 139219820Sjeff 140219820Sjeff ret = seq_open(file, &ipoib_mcg_seq_ops); 141219820Sjeff if (ret) 142219820Sjeff return ret; 143219820Sjeff 144219820Sjeff seq = file->private_data; 145219820Sjeff seq->private = inode->i_private; 146219820Sjeff 147219820Sjeff return 0; 148219820Sjeff} 149219820Sjeff 150219820Sjeffstatic const struct file_operations ipoib_mcg_fops = { 151219820Sjeff .owner = THIS_MODULE, 152219820Sjeff .open = ipoib_mcg_open, 153219820Sjeff .read = seq_read, 154219820Sjeff .llseek = seq_lseek, 155219820Sjeff .release = seq_release 156219820Sjeff}; 157219820Sjeff 158219820Sjeffstatic void *ipoib_path_seq_start(struct seq_file *file, loff_t *pos) 159219820Sjeff{ 160219820Sjeff struct ipoib_path_iter *iter; 161219820Sjeff loff_t n = *pos; 162219820Sjeff 163219820Sjeff iter = ipoib_path_iter_init(file->private); 164219820Sjeff if (!iter) 165219820Sjeff return NULL; 166219820Sjeff 167219820Sjeff while (n--) { 168219820Sjeff if (ipoib_path_iter_next(iter)) { 169219820Sjeff kfree(iter); 170219820Sjeff return NULL; 171219820Sjeff } 172219820Sjeff } 173219820Sjeff 174219820Sjeff return iter; 175219820Sjeff} 176219820Sjeff 177219820Sjeffstatic void *ipoib_path_seq_next(struct seq_file *file, void *iter_ptr, 178219820Sjeff loff_t *pos) 179219820Sjeff{ 180219820Sjeff struct ipoib_path_iter *iter = iter_ptr; 181219820Sjeff 182219820Sjeff (*pos)++; 183219820Sjeff 184219820Sjeff if (ipoib_path_iter_next(iter)) { 185219820Sjeff kfree(iter); 186219820Sjeff return NULL; 187219820Sjeff } 188219820Sjeff 189219820Sjeff return iter; 190219820Sjeff} 191219820Sjeff 192219820Sjeffstatic void ipoib_path_seq_stop(struct seq_file *file, void *iter_ptr) 193219820Sjeff{ 194219820Sjeff /* nothing for now */ 195219820Sjeff} 196219820Sjeff 197219820Sjeffstatic int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr) 198219820Sjeff{ 199219820Sjeff struct ipoib_path_iter *iter = iter_ptr; 200219820Sjeff char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; 201219820Sjeff struct ipoib_path path; 202219820Sjeff int rate; 203219820Sjeff 204219820Sjeff if (!iter) 205219820Sjeff return 0; 206219820Sjeff 207219820Sjeff ipoib_path_iter_read(iter, &path); 208219820Sjeff 209219820Sjeff format_gid(&path.pathrec.dgid, gid_buf); 210219820Sjeff 211219820Sjeff seq_printf(file, 212219820Sjeff "GID: %s\n" 213219820Sjeff " complete: %6s\n", 214219820Sjeff gid_buf, path.pathrec.dlid ? "yes" : "no"); 215219820Sjeff 216219820Sjeff if (path.pathrec.dlid) { 217219820Sjeff rate = ib_rate_to_mult(path.pathrec.rate) * 25; 218219820Sjeff 219219820Sjeff seq_printf(file, 220219820Sjeff " DLID: 0x%04x\n" 221219820Sjeff " SL: %12d\n" 222219820Sjeff " rate: %*d%s Gb/sec\n", 223219820Sjeff be16_to_cpu(path.pathrec.dlid), 224219820Sjeff path.pathrec.sl, 225219820Sjeff 10 - ((rate % 10) ? 2 : 0), 226219820Sjeff rate / 10, rate % 10 ? ".5" : ""); 227219820Sjeff } 228219820Sjeff 229219820Sjeff seq_putc(file, '\n'); 230219820Sjeff 231219820Sjeff return 0; 232219820Sjeff} 233219820Sjeff 234219820Sjeffstatic const struct seq_operations ipoib_path_seq_ops = { 235219820Sjeff .start = ipoib_path_seq_start, 236219820Sjeff .next = ipoib_path_seq_next, 237219820Sjeff .stop = ipoib_path_seq_stop, 238219820Sjeff .show = ipoib_path_seq_show, 239219820Sjeff}; 240219820Sjeff 241219820Sjeffstatic int ipoib_path_open(struct inode *inode, struct file *file) 242219820Sjeff{ 243219820Sjeff struct seq_file *seq; 244219820Sjeff int ret; 245219820Sjeff 246219820Sjeff ret = seq_open(file, &ipoib_path_seq_ops); 247219820Sjeff if (ret) 248219820Sjeff return ret; 249219820Sjeff 250219820Sjeff seq = file->private_data; 251219820Sjeff seq->private = inode->i_private; 252219820Sjeff 253219820Sjeff return 0; 254219820Sjeff} 255219820Sjeff 256219820Sjeffstatic const struct file_operations ipoib_path_fops = { 257219820Sjeff .owner = THIS_MODULE, 258219820Sjeff .open = ipoib_path_open, 259219820Sjeff .read = seq_read, 260219820Sjeff .llseek = seq_lseek, 261219820Sjeff .release = seq_release 262219820Sjeff}; 263219820Sjeff 264219820Sjeffvoid ipoib_create_debug_files(struct ifnet *dev) 265219820Sjeff{ 266219820Sjeff struct ipoib_dev_priv *priv = dev->if_softc; 267219820Sjeff char name[IFNAMSIZ + sizeof "_path"]; 268219820Sjeff 269219820Sjeff snprintf(name, sizeof name, "%s_mcg", if_name(dev)); 270219820Sjeff priv->mcg_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO, 271219820Sjeff ipoib_root, dev, &ipoib_mcg_fops); 272219820Sjeff if (!priv->mcg_dentry) 273219820Sjeff ipoib_warn(priv, "failed to create mcg debug file\n"); 274219820Sjeff 275219820Sjeff snprintf(name, sizeof name, "%s_path", if_name(dev)); 276219820Sjeff priv->path_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO, 277219820Sjeff ipoib_root, dev, &ipoib_path_fops); 278219820Sjeff if (!priv->path_dentry) 279219820Sjeff ipoib_warn(priv, "failed to create path debug file\n"); 280219820Sjeff} 281219820Sjeff 282219820Sjeffvoid ipoib_delete_debug_files(struct ifnet *dev) 283219820Sjeff{ 284219820Sjeff struct ipoib_dev_priv *priv = dev->if_softc; 285219820Sjeff 286219820Sjeff if (priv->mcg_dentry) 287219820Sjeff debugfs_remove(priv->mcg_dentry); 288219820Sjeff if (priv->path_dentry) 289219820Sjeff debugfs_remove(priv->path_dentry); 290219820Sjeff} 291219820Sjeff 292219820Sjeffint ipoib_register_debugfs(void) 293219820Sjeff{ 294219820Sjeff ipoib_root = debugfs_create_dir("ipoib", NULL); 295219820Sjeff return ipoib_root ? 0 : -ENOMEM; 296219820Sjeff} 297219820Sjeff 298219820Sjeffvoid ipoib_unregister_debugfs(void) 299219820Sjeff{ 300219820Sjeff debugfs_remove(ipoib_root); 301219820Sjeff} 302