linux/drivers/infiniband/ulp/ipoib/ipoib_fs.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2004 Topspin Communications.  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
  33#include <linux/err.h>
  34#include <linux/seq_file.h>
  35
  36struct file_operations;
  37
  38#include <linux/debugfs.h>
  39
  40#include "ipoib.h"
  41
  42static struct dentry *ipoib_root;
  43
  44static void format_gid(union ib_gid *gid, char *buf)
  45{
  46        int i, n;
  47
  48        for (n = 0, i = 0; i < 8; ++i) {
  49                n += sprintf(buf + n, "%x",
  50                             be16_to_cpu(((__be16 *) gid->raw)[i]));
  51                if (i < 7)
  52                        buf[n++] = ':';
  53        }
  54}
  55
  56static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos)
  57{
  58        struct ipoib_mcast_iter *iter;
  59        loff_t n = *pos;
  60
  61        iter = ipoib_mcast_iter_init(file->private);
  62        if (!iter)
  63                return NULL;
  64
  65        while (n--) {
  66                if (ipoib_mcast_iter_next(iter)) {
  67                        kfree(iter);
  68                        return NULL;
  69                }
  70        }
  71
  72        return iter;
  73}
  74
  75static void *ipoib_mcg_seq_next(struct seq_file *file, void *iter_ptr,
  76                                   loff_t *pos)
  77{
  78        struct ipoib_mcast_iter *iter = iter_ptr;
  79
  80        (*pos)++;
  81
  82        if (ipoib_mcast_iter_next(iter)) {
  83                kfree(iter);
  84                return NULL;
  85        }
  86
  87        return iter;
  88}
  89
  90static void ipoib_mcg_seq_stop(struct seq_file *file, void *iter_ptr)
  91{
  92        /* nothing for now */
  93}
  94
  95static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr)
  96{
  97        struct ipoib_mcast_iter *iter = iter_ptr;
  98        char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
  99        union ib_gid mgid;
 100        unsigned long created;
 101        unsigned int queuelen, complete, send_only;
 102
 103        if (!iter)
 104                return 0;
 105
 106        ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen,
 107                              &complete, &send_only);
 108
 109        format_gid(&mgid, gid_buf);
 110
 111        seq_printf(file,
 112                   "GID: %s\n"
 113                   "  created: %10ld\n"
 114                   "  queuelen: %9d\n"
 115                   "  complete: %9s\n"
 116                   "  send_only: %8s\n"
 117                   "\n",
 118                   gid_buf, created, queuelen,
 119                   complete ? "yes" : "no",
 120                   send_only ? "yes" : "no");
 121
 122        return 0;
 123}
 124
 125static const struct seq_operations ipoib_mcg_seq_ops = {
 126        .start = ipoib_mcg_seq_start,
 127        .next  = ipoib_mcg_seq_next,
 128        .stop  = ipoib_mcg_seq_stop,
 129        .show  = ipoib_mcg_seq_show,
 130};
 131
 132static int ipoib_mcg_open(struct inode *inode, struct file *file)
 133{
 134        struct seq_file *seq;
 135        int ret;
 136
 137        ret = seq_open(file, &ipoib_mcg_seq_ops);
 138        if (ret)
 139                return ret;
 140
 141        seq = file->private_data;
 142        seq->private = inode->i_private;
 143
 144        return 0;
 145}
 146
 147static const struct file_operations ipoib_mcg_fops = {
 148        .owner   = THIS_MODULE,
 149        .open    = ipoib_mcg_open,
 150        .read    = seq_read,
 151        .llseek  = seq_lseek,
 152        .release = seq_release
 153};
 154
 155static void *ipoib_path_seq_start(struct seq_file *file, loff_t *pos)
 156{
 157        struct ipoib_path_iter *iter;
 158        loff_t n = *pos;
 159
 160        iter = ipoib_path_iter_init(file->private);
 161        if (!iter)
 162                return NULL;
 163
 164        while (n--) {
 165                if (ipoib_path_iter_next(iter)) {
 166                        kfree(iter);
 167                        return NULL;
 168                }
 169        }
 170
 171        return iter;
 172}
 173
 174static void *ipoib_path_seq_next(struct seq_file *file, void *iter_ptr,
 175                                   loff_t *pos)
 176{
 177        struct ipoib_path_iter *iter = iter_ptr;
 178
 179        (*pos)++;
 180
 181        if (ipoib_path_iter_next(iter)) {
 182                kfree(iter);
 183                return NULL;
 184        }
 185
 186        return iter;
 187}
 188
 189static void ipoib_path_seq_stop(struct seq_file *file, void *iter_ptr)
 190{
 191        /* nothing for now */
 192}
 193
 194static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
 195{
 196        struct ipoib_path_iter *iter = iter_ptr;
 197        char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
 198        struct ipoib_path path;
 199        int rate;
 200
 201        if (!iter)
 202                return 0;
 203
 204        ipoib_path_iter_read(iter, &path);
 205
 206        format_gid(&path.pathrec.dgid, gid_buf);
 207
 208        seq_printf(file,
 209                   "GID: %s\n"
 210                   "  complete: %6s\n",
 211                   gid_buf, path.pathrec.dlid ? "yes" : "no");
 212
 213        if (path.pathrec.dlid) {
 214                rate = ib_rate_to_mult(path.pathrec.rate) * 25;
 215
 216                seq_printf(file,
 217                           "  DLID:     0x%04x\n"
 218                           "  SL: %12d\n"
 219                           "  rate: %*d%s Gb/sec\n",
 220                           be16_to_cpu(path.pathrec.dlid),
 221                           path.pathrec.sl,
 222                           10 - ((rate % 10) ? 2 : 0),
 223                           rate / 10, rate % 10 ? ".5" : "");
 224        }
 225
 226        seq_putc(file, '\n');
 227
 228        return 0;
 229}
 230
 231static const struct seq_operations ipoib_path_seq_ops = {
 232        .start = ipoib_path_seq_start,
 233        .next  = ipoib_path_seq_next,
 234        .stop  = ipoib_path_seq_stop,
 235        .show  = ipoib_path_seq_show,
 236};
 237
 238static int ipoib_path_open(struct inode *inode, struct file *file)
 239{
 240        struct seq_file *seq;
 241        int ret;
 242
 243        ret = seq_open(file, &ipoib_path_seq_ops);
 244        if (ret)
 245                return ret;
 246
 247        seq = file->private_data;
 248        seq->private = inode->i_private;
 249
 250        return 0;
 251}
 252
 253static const struct file_operations ipoib_path_fops = {
 254        .owner   = THIS_MODULE,
 255        .open    = ipoib_path_open,
 256        .read    = seq_read,
 257        .llseek  = seq_lseek,
 258        .release = seq_release
 259};
 260
 261void ipoib_create_debug_files(struct net_device *dev)
 262{
 263        struct ipoib_dev_priv *priv = netdev_priv(dev);
 264        char name[IFNAMSIZ + sizeof "_path"];
 265
 266        snprintf(name, sizeof name, "%s_mcg", dev->name);
 267        priv->mcg_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
 268                                               ipoib_root, dev, &ipoib_mcg_fops);
 269        if (!priv->mcg_dentry)
 270                ipoib_warn(priv, "failed to create mcg debug file\n");
 271
 272        snprintf(name, sizeof name, "%s_path", dev->name);
 273        priv->path_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
 274                                                ipoib_root, dev, &ipoib_path_fops);
 275        if (!priv->path_dentry)
 276                ipoib_warn(priv, "failed to create path debug file\n");
 277}
 278
 279void ipoib_delete_debug_files(struct net_device *dev)
 280{
 281        struct ipoib_dev_priv *priv = netdev_priv(dev);
 282
 283        if (priv->mcg_dentry)
 284                debugfs_remove(priv->mcg_dentry);
 285        if (priv->path_dentry)
 286                debugfs_remove(priv->path_dentry);
 287}
 288
 289int ipoib_register_debugfs(void)
 290{
 291        ipoib_root = debugfs_create_dir("ipoib", NULL);
 292        return ipoib_root ? 0 : -ENOMEM;
 293}
 294
 295void ipoib_unregister_debugfs(void)
 296{
 297        debugfs_remove(ipoib_root);
 298}
 299