linux/drivers/infiniband/hw/qib/qib_fs.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2012 Intel Corporation. All rights reserved.
   3 * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved.
   4 * Copyright (c) 2006 PathScale, Inc. All rights reserved.
   5 *
   6 * This software is available to you under a choice of one of two
   7 * licenses.  You may choose to be licensed under the terms of the GNU
   8 * General Public License (GPL) Version 2, available from the file
   9 * COPYING in the main directory of this source tree, or the
  10 * OpenIB.org BSD license below:
  11 *
  12 *     Redistribution and use in source and binary forms, with or
  13 *     without modification, are permitted provided that the following
  14 *     conditions are met:
  15 *
  16 *      - Redistributions of source code must retain the above
  17 *        copyright notice, this list of conditions and the following
  18 *        disclaimer.
  19 *
  20 *      - Redistributions in binary form must reproduce the above
  21 *        copyright notice, this list of conditions and the following
  22 *        disclaimer in the documentation and/or other materials
  23 *        provided with the distribution.
  24 *
  25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  32 * SOFTWARE.
  33 */
  34
  35#include <linux/module.h>
  36#include <linux/fs.h>
  37#include <linux/fs_context.h>
  38#include <linux/mount.h>
  39#include <linux/pagemap.h>
  40#include <linux/init.h>
  41#include <linux/namei.h>
  42
  43#include "qib.h"
  44
  45#define QIBFS_MAGIC 0x726a77
  46
  47static struct super_block *qib_super;
  48
  49#define private2dd(file) (file_inode(file)->i_private)
  50
  51static int qibfs_mknod(struct inode *dir, struct dentry *dentry,
  52                       umode_t mode, const struct file_operations *fops,
  53                       void *data)
  54{
  55        int error;
  56        struct inode *inode = new_inode(dir->i_sb);
  57
  58        if (!inode) {
  59                error = -EPERM;
  60                goto bail;
  61        }
  62
  63        inode->i_ino = get_next_ino();
  64        inode->i_mode = mode;
  65        inode->i_uid = GLOBAL_ROOT_UID;
  66        inode->i_gid = GLOBAL_ROOT_GID;
  67        inode->i_blocks = 0;
  68        inode->i_atime = current_time(inode);
  69        inode->i_mtime = inode->i_atime;
  70        inode->i_ctime = inode->i_atime;
  71        inode->i_private = data;
  72        if (S_ISDIR(mode)) {
  73                inode->i_op = &simple_dir_inode_operations;
  74                inc_nlink(inode);
  75                inc_nlink(dir);
  76        }
  77
  78        inode->i_fop = fops;
  79
  80        d_instantiate(dentry, inode);
  81        error = 0;
  82
  83bail:
  84        return error;
  85}
  86
  87static int create_file(const char *name, umode_t mode,
  88                       struct dentry *parent, struct dentry **dentry,
  89                       const struct file_operations *fops, void *data)
  90{
  91        int error;
  92
  93        inode_lock(d_inode(parent));
  94        *dentry = lookup_one_len(name, parent, strlen(name));
  95        if (!IS_ERR(*dentry))
  96                error = qibfs_mknod(d_inode(parent), *dentry,
  97                                    mode, fops, data);
  98        else
  99                error = PTR_ERR(*dentry);
 100        inode_unlock(d_inode(parent));
 101
 102        return error;
 103}
 104
 105static ssize_t driver_stats_read(struct file *file, char __user *buf,
 106                                 size_t count, loff_t *ppos)
 107{
 108        qib_stats.sps_ints = qib_sps_ints();
 109        return simple_read_from_buffer(buf, count, ppos, &qib_stats,
 110                                       sizeof(qib_stats));
 111}
 112
 113/*
 114 * driver stats field names, one line per stat, single string.  Used by
 115 * programs like ipathstats to print the stats in a way which works for
 116 * different versions of drivers, without changing program source.
 117 * if qlogic_ib_stats changes, this needs to change.  Names need to be
 118 * 12 chars or less (w/o newline), for proper display by ipathstats utility.
 119 */
 120static const char qib_statnames[] =
 121        "KernIntr\n"
 122        "ErrorIntr\n"
 123        "Tx_Errs\n"
 124        "Rcv_Errs\n"
 125        "H/W_Errs\n"
 126        "NoPIOBufs\n"
 127        "CtxtsOpen\n"
 128        "RcvLen_Errs\n"
 129        "EgrBufFull\n"
 130        "EgrHdrFull\n"
 131        ;
 132
 133static ssize_t driver_names_read(struct file *file, char __user *buf,
 134                                 size_t count, loff_t *ppos)
 135{
 136        return simple_read_from_buffer(buf, count, ppos, qib_statnames,
 137                sizeof(qib_statnames) - 1); /* no null */
 138}
 139
 140static const struct file_operations driver_ops[] = {
 141        { .read = driver_stats_read, .llseek = generic_file_llseek, },
 142        { .read = driver_names_read, .llseek = generic_file_llseek, },
 143};
 144
 145/* read the per-device counters */
 146static ssize_t dev_counters_read(struct file *file, char __user *buf,
 147                                 size_t count, loff_t *ppos)
 148{
 149        u64 *counters;
 150        size_t avail;
 151        struct qib_devdata *dd = private2dd(file);
 152
 153        avail = dd->f_read_cntrs(dd, *ppos, NULL, &counters);
 154        return simple_read_from_buffer(buf, count, ppos, counters, avail);
 155}
 156
 157/* read the per-device counters */
 158static ssize_t dev_names_read(struct file *file, char __user *buf,
 159                              size_t count, loff_t *ppos)
 160{
 161        char *names;
 162        size_t avail;
 163        struct qib_devdata *dd = private2dd(file);
 164
 165        avail = dd->f_read_cntrs(dd, *ppos, &names, NULL);
 166        return simple_read_from_buffer(buf, count, ppos, names, avail);
 167}
 168
 169static const struct file_operations cntr_ops[] = {
 170        { .read = dev_counters_read, .llseek = generic_file_llseek, },
 171        { .read = dev_names_read, .llseek = generic_file_llseek, },
 172};
 173
 174/*
 175 * Could use file_inode(file)->i_ino to figure out which file,
 176 * instead of separate routine for each, but for now, this works...
 177 */
 178
 179/* read the per-port names (same for each port) */
 180static ssize_t portnames_read(struct file *file, char __user *buf,
 181                              size_t count, loff_t *ppos)
 182{
 183        char *names;
 184        size_t avail;
 185        struct qib_devdata *dd = private2dd(file);
 186
 187        avail = dd->f_read_portcntrs(dd, *ppos, 0, &names, NULL);
 188        return simple_read_from_buffer(buf, count, ppos, names, avail);
 189}
 190
 191/* read the per-port counters for port 1 (pidx 0) */
 192static ssize_t portcntrs_1_read(struct file *file, char __user *buf,
 193                                size_t count, loff_t *ppos)
 194{
 195        u64 *counters;
 196        size_t avail;
 197        struct qib_devdata *dd = private2dd(file);
 198
 199        avail = dd->f_read_portcntrs(dd, *ppos, 0, NULL, &counters);
 200        return simple_read_from_buffer(buf, count, ppos, counters, avail);
 201}
 202
 203/* read the per-port counters for port 2 (pidx 1) */
 204static ssize_t portcntrs_2_read(struct file *file, char __user *buf,
 205                                size_t count, loff_t *ppos)
 206{
 207        u64 *counters;
 208        size_t avail;
 209        struct qib_devdata *dd = private2dd(file);
 210
 211        avail = dd->f_read_portcntrs(dd, *ppos, 1, NULL, &counters);
 212        return simple_read_from_buffer(buf, count, ppos, counters, avail);
 213}
 214
 215static const struct file_operations portcntr_ops[] = {
 216        { .read = portnames_read, .llseek = generic_file_llseek, },
 217        { .read = portcntrs_1_read, .llseek = generic_file_llseek, },
 218        { .read = portcntrs_2_read, .llseek = generic_file_llseek, },
 219};
 220
 221/*
 222 * read the per-port QSFP data for port 1 (pidx 0)
 223 */
 224static ssize_t qsfp_1_read(struct file *file, char __user *buf,
 225                           size_t count, loff_t *ppos)
 226{
 227        struct qib_devdata *dd = private2dd(file);
 228        char *tmp;
 229        int ret;
 230
 231        tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
 232        if (!tmp)
 233                return -ENOMEM;
 234
 235        ret = qib_qsfp_dump(dd->pport, tmp, PAGE_SIZE);
 236        if (ret > 0)
 237                ret = simple_read_from_buffer(buf, count, ppos, tmp, ret);
 238        kfree(tmp);
 239        return ret;
 240}
 241
 242/*
 243 * read the per-port QSFP data for port 2 (pidx 1)
 244 */
 245static ssize_t qsfp_2_read(struct file *file, char __user *buf,
 246                           size_t count, loff_t *ppos)
 247{
 248        struct qib_devdata *dd = private2dd(file);
 249        char *tmp;
 250        int ret;
 251
 252        if (dd->num_pports < 2)
 253                return -ENODEV;
 254
 255        tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
 256        if (!tmp)
 257                return -ENOMEM;
 258
 259        ret = qib_qsfp_dump(dd->pport + 1, tmp, PAGE_SIZE);
 260        if (ret > 0)
 261                ret = simple_read_from_buffer(buf, count, ppos, tmp, ret);
 262        kfree(tmp);
 263        return ret;
 264}
 265
 266static const struct file_operations qsfp_ops[] = {
 267        { .read = qsfp_1_read, .llseek = generic_file_llseek, },
 268        { .read = qsfp_2_read, .llseek = generic_file_llseek, },
 269};
 270
 271static ssize_t flash_read(struct file *file, char __user *buf,
 272                          size_t count, loff_t *ppos)
 273{
 274        struct qib_devdata *dd;
 275        ssize_t ret;
 276        loff_t pos;
 277        char *tmp;
 278
 279        pos = *ppos;
 280
 281        if (pos < 0) {
 282                ret = -EINVAL;
 283                goto bail;
 284        }
 285
 286        if (pos >= sizeof(struct qib_flash)) {
 287                ret = 0;
 288                goto bail;
 289        }
 290
 291        if (count > sizeof(struct qib_flash) - pos)
 292                count = sizeof(struct qib_flash) - pos;
 293
 294        tmp = kmalloc(count, GFP_KERNEL);
 295        if (!tmp) {
 296                ret = -ENOMEM;
 297                goto bail;
 298        }
 299
 300        dd = private2dd(file);
 301        if (qib_eeprom_read(dd, pos, tmp, count)) {
 302                qib_dev_err(dd, "failed to read from flash\n");
 303                ret = -ENXIO;
 304                goto bail_tmp;
 305        }
 306
 307        if (copy_to_user(buf, tmp, count)) {
 308                ret = -EFAULT;
 309                goto bail_tmp;
 310        }
 311
 312        *ppos = pos + count;
 313        ret = count;
 314
 315bail_tmp:
 316        kfree(tmp);
 317
 318bail:
 319        return ret;
 320}
 321
 322static ssize_t flash_write(struct file *file, const char __user *buf,
 323                           size_t count, loff_t *ppos)
 324{
 325        struct qib_devdata *dd;
 326        ssize_t ret;
 327        loff_t pos;
 328        char *tmp;
 329
 330        pos = *ppos;
 331
 332        if (pos != 0 || count != sizeof(struct qib_flash))
 333                return -EINVAL;
 334
 335        tmp = memdup_user(buf, count);
 336        if (IS_ERR(tmp))
 337                return PTR_ERR(tmp);
 338
 339        dd = private2dd(file);
 340        if (qib_eeprom_write(dd, pos, tmp, count)) {
 341                ret = -ENXIO;
 342                qib_dev_err(dd, "failed to write to flash\n");
 343                goto bail_tmp;
 344        }
 345
 346        *ppos = pos + count;
 347        ret = count;
 348
 349bail_tmp:
 350        kfree(tmp);
 351        return ret;
 352}
 353
 354static const struct file_operations flash_ops = {
 355        .read = flash_read,
 356        .write = flash_write,
 357        .llseek = default_llseek,
 358};
 359
 360static int add_cntr_files(struct super_block *sb, struct qib_devdata *dd)
 361{
 362        struct dentry *dir, *tmp;
 363        char unit[10];
 364        int ret, i;
 365
 366        /* create the per-unit directory */
 367        snprintf(unit, sizeof(unit), "%u", dd->unit);
 368        ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir,
 369                          &simple_dir_operations, dd);
 370        if (ret) {
 371                pr_err("create_file(%s) failed: %d\n", unit, ret);
 372                goto bail;
 373        }
 374
 375        /* create the files in the new directory */
 376        ret = create_file("counters", S_IFREG|S_IRUGO, dir, &tmp,
 377                          &cntr_ops[0], dd);
 378        if (ret) {
 379                pr_err("create_file(%s/counters) failed: %d\n",
 380                       unit, ret);
 381                goto bail;
 382        }
 383        ret = create_file("counter_names", S_IFREG|S_IRUGO, dir, &tmp,
 384                          &cntr_ops[1], dd);
 385        if (ret) {
 386                pr_err("create_file(%s/counter_names) failed: %d\n",
 387                       unit, ret);
 388                goto bail;
 389        }
 390        ret = create_file("portcounter_names", S_IFREG|S_IRUGO, dir, &tmp,
 391                          &portcntr_ops[0], dd);
 392        if (ret) {
 393                pr_err("create_file(%s/%s) failed: %d\n",
 394                       unit, "portcounter_names", ret);
 395                goto bail;
 396        }
 397        for (i = 1; i <= dd->num_pports; i++) {
 398                char fname[24];
 399
 400                sprintf(fname, "port%dcounters", i);
 401                /* create the files in the new directory */
 402                ret = create_file(fname, S_IFREG|S_IRUGO, dir, &tmp,
 403                                  &portcntr_ops[i], dd);
 404                if (ret) {
 405                        pr_err("create_file(%s/%s) failed: %d\n",
 406                                unit, fname, ret);
 407                        goto bail;
 408                }
 409                if (!(dd->flags & QIB_HAS_QSFP))
 410                        continue;
 411                sprintf(fname, "qsfp%d", i);
 412                ret = create_file(fname, S_IFREG|S_IRUGO, dir, &tmp,
 413                                  &qsfp_ops[i - 1], dd);
 414                if (ret) {
 415                        pr_err("create_file(%s/%s) failed: %d\n",
 416                                unit, fname, ret);
 417                        goto bail;
 418                }
 419        }
 420
 421        ret = create_file("flash", S_IFREG|S_IWUSR|S_IRUGO, dir, &tmp,
 422                          &flash_ops, dd);
 423        if (ret)
 424                pr_err("create_file(%s/flash) failed: %d\n",
 425                        unit, ret);
 426bail:
 427        return ret;
 428}
 429
 430static int remove_device_files(struct super_block *sb,
 431                               struct qib_devdata *dd)
 432{
 433        struct dentry *dir;
 434        char unit[10];
 435
 436        snprintf(unit, sizeof(unit), "%u", dd->unit);
 437        dir = lookup_one_len_unlocked(unit, sb->s_root, strlen(unit));
 438
 439        if (IS_ERR(dir)) {
 440                pr_err("Lookup of %s failed\n", unit);
 441                return PTR_ERR(dir);
 442        }
 443        simple_recursive_removal(dir, NULL);
 444        return 0;
 445}
 446
 447/*
 448 * This fills everything in when the fs is mounted, to handle umount/mount
 449 * after device init.  The direct add_cntr_files() call handles adding
 450 * them from the init code, when the fs is already mounted.
 451 */
 452static int qibfs_fill_super(struct super_block *sb, struct fs_context *fc)
 453{
 454        struct qib_devdata *dd;
 455        unsigned long index;
 456        int ret;
 457
 458        static const struct tree_descr files[] = {
 459                [2] = {"driver_stats", &driver_ops[0], S_IRUGO},
 460                [3] = {"driver_stats_names", &driver_ops[1], S_IRUGO},
 461                {""},
 462        };
 463
 464        ret = simple_fill_super(sb, QIBFS_MAGIC, files);
 465        if (ret) {
 466                pr_err("simple_fill_super failed: %d\n", ret);
 467                goto bail;
 468        }
 469
 470        xa_for_each(&qib_dev_table, index, dd) {
 471                ret = add_cntr_files(sb, dd);
 472                if (ret)
 473                        goto bail;
 474        }
 475
 476bail:
 477        return ret;
 478}
 479
 480static int qibfs_get_tree(struct fs_context *fc)
 481{
 482        int ret = get_tree_single(fc, qibfs_fill_super);
 483        if (ret == 0)
 484                qib_super = fc->root->d_sb;
 485        return ret;
 486}
 487
 488static const struct fs_context_operations qibfs_context_ops = {
 489        .get_tree       = qibfs_get_tree,
 490};
 491
 492static int qibfs_init_fs_context(struct fs_context *fc)
 493{
 494        fc->ops = &qibfs_context_ops;
 495        return 0;
 496}
 497
 498static void qibfs_kill_super(struct super_block *s)
 499{
 500        kill_litter_super(s);
 501        qib_super = NULL;
 502}
 503
 504int qibfs_add(struct qib_devdata *dd)
 505{
 506        int ret;
 507
 508        /*
 509         * On first unit initialized, qib_super will not yet exist
 510         * because nobody has yet tried to mount the filesystem, so
 511         * we can't consider that to be an error; if an error occurs
 512         * during the mount, that will get a complaint, so this is OK.
 513         * add_cntr_files() for all units is done at mount from
 514         * qibfs_fill_super(), so one way or another, everything works.
 515         */
 516        if (qib_super == NULL)
 517                ret = 0;
 518        else
 519                ret = add_cntr_files(qib_super, dd);
 520        return ret;
 521}
 522
 523int qibfs_remove(struct qib_devdata *dd)
 524{
 525        int ret = 0;
 526
 527        if (qib_super)
 528                ret = remove_device_files(qib_super, dd);
 529
 530        return ret;
 531}
 532
 533static struct file_system_type qibfs_fs_type = {
 534        .owner =        THIS_MODULE,
 535        .name =         "ipathfs",
 536        .init_fs_context = qibfs_init_fs_context,
 537        .kill_sb =      qibfs_kill_super,
 538};
 539MODULE_ALIAS_FS("ipathfs");
 540
 541int __init qib_init_qibfs(void)
 542{
 543        return register_filesystem(&qibfs_fs_type);
 544}
 545
 546int __exit qib_exit_qibfs(void)
 547{
 548        return unregister_filesystem(&qibfs_fs_type);
 549}
 550