linux/drivers/infiniband/hw/hfi1/sysfs.c
<<
>>
Prefs
   1/*
   2 * Copyright(c) 2015-2017 Intel Corporation.
   3 *
   4 * This file is provided under a dual BSD/GPLv2 license.  When using or
   5 * redistributing this file, you may do so under either license.
   6 *
   7 * GPL LICENSE SUMMARY
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of version 2 of the GNU General Public License as
  11 * published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it will be useful, but
  14 * WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16 * General Public License for more details.
  17 *
  18 * BSD LICENSE
  19 *
  20 * Redistribution and use in source and binary forms, with or without
  21 * modification, are permitted provided that the following conditions
  22 * are met:
  23 *
  24 *  - Redistributions of source code must retain the above copyright
  25 *    notice, this list of conditions and the following disclaimer.
  26 *  - Redistributions in binary form must reproduce the above copyright
  27 *    notice, this list of conditions and the following disclaimer in
  28 *    the documentation and/or other materials provided with the
  29 *    distribution.
  30 *  - Neither the name of Intel Corporation nor the names of its
  31 *    contributors may be used to endorse or promote products derived
  32 *    from this software without specific prior written permission.
  33 *
  34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  35 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  36 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  37 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  38 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  39 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  41 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  42 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  43 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  44 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45 *
  46 */
  47#include <linux/ctype.h>
  48
  49#include "hfi.h"
  50#include "mad.h"
  51#include "trace.h"
  52
  53/*
  54 * Start of per-port congestion control structures and support code
  55 */
  56
  57/*
  58 * Congestion control table size followed by table entries
  59 */
  60static ssize_t read_cc_table_bin(struct file *filp, struct kobject *kobj,
  61                                 struct bin_attribute *bin_attr,
  62                                 char *buf, loff_t pos, size_t count)
  63{
  64        int ret;
  65        struct hfi1_pportdata *ppd =
  66                container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
  67        struct cc_state *cc_state;
  68
  69        ret = ppd->total_cct_entry * sizeof(struct ib_cc_table_entry_shadow)
  70                 + sizeof(__be16);
  71
  72        if (pos > ret)
  73                return -EINVAL;
  74
  75        if (count > ret - pos)
  76                count = ret - pos;
  77
  78        if (!count)
  79                return count;
  80
  81        rcu_read_lock();
  82        cc_state = get_cc_state(ppd);
  83        if (!cc_state) {
  84                rcu_read_unlock();
  85                return -EINVAL;
  86        }
  87        memcpy(buf, (void *)&cc_state->cct + pos, count);
  88        rcu_read_unlock();
  89
  90        return count;
  91}
  92
  93static void port_release(struct kobject *kobj)
  94{
  95        /* nothing to do since memory is freed by hfi1_free_devdata() */
  96}
  97
  98static const struct bin_attribute cc_table_bin_attr = {
  99        .attr = {.name = "cc_table_bin", .mode = 0444},
 100        .read = read_cc_table_bin,
 101        .size = PAGE_SIZE,
 102};
 103
 104/*
 105 * Congestion settings: port control, control map and an array of 16
 106 * entries for the congestion entries - increase, timer, event log
 107 * trigger threshold and the minimum injection rate delay.
 108 */
 109static ssize_t read_cc_setting_bin(struct file *filp, struct kobject *kobj,
 110                                   struct bin_attribute *bin_attr,
 111                                   char *buf, loff_t pos, size_t count)
 112{
 113        int ret;
 114        struct hfi1_pportdata *ppd =
 115                container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
 116        struct cc_state *cc_state;
 117
 118        ret = sizeof(struct opa_congestion_setting_attr_shadow);
 119
 120        if (pos > ret)
 121                return -EINVAL;
 122        if (count > ret - pos)
 123                count = ret - pos;
 124
 125        if (!count)
 126                return count;
 127
 128        rcu_read_lock();
 129        cc_state = get_cc_state(ppd);
 130        if (!cc_state) {
 131                rcu_read_unlock();
 132                return -EINVAL;
 133        }
 134        memcpy(buf, (void *)&cc_state->cong_setting + pos, count);
 135        rcu_read_unlock();
 136
 137        return count;
 138}
 139
 140static const struct bin_attribute cc_setting_bin_attr = {
 141        .attr = {.name = "cc_settings_bin", .mode = 0444},
 142        .read = read_cc_setting_bin,
 143        .size = PAGE_SIZE,
 144};
 145
 146struct hfi1_port_attr {
 147        struct attribute attr;
 148        ssize_t (*show)(struct hfi1_pportdata *, char *);
 149        ssize_t (*store)(struct hfi1_pportdata *, const char *, size_t);
 150};
 151
 152static ssize_t cc_prescan_show(struct hfi1_pportdata *ppd, char *buf)
 153{
 154        return sprintf(buf, "%s\n", ppd->cc_prescan ? "on" : "off");
 155}
 156
 157static ssize_t cc_prescan_store(struct hfi1_pportdata *ppd, const char *buf,
 158                                size_t count)
 159{
 160        if (!memcmp(buf, "on", 2))
 161                ppd->cc_prescan = true;
 162        else if (!memcmp(buf, "off", 3))
 163                ppd->cc_prescan = false;
 164
 165        return count;
 166}
 167
 168static struct hfi1_port_attr cc_prescan_attr =
 169                __ATTR(cc_prescan, 0600, cc_prescan_show, cc_prescan_store);
 170
 171static ssize_t cc_attr_show(struct kobject *kobj, struct attribute *attr,
 172                            char *buf)
 173{
 174        struct hfi1_port_attr *port_attr =
 175                container_of(attr, struct hfi1_port_attr, attr);
 176        struct hfi1_pportdata *ppd =
 177                container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
 178
 179        return port_attr->show(ppd, buf);
 180}
 181
 182static ssize_t cc_attr_store(struct kobject *kobj, struct attribute *attr,
 183                             const char *buf, size_t count)
 184{
 185        struct hfi1_port_attr *port_attr =
 186                container_of(attr, struct hfi1_port_attr, attr);
 187        struct hfi1_pportdata *ppd =
 188                container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
 189
 190        return port_attr->store(ppd, buf, count);
 191}
 192
 193static const struct sysfs_ops port_cc_sysfs_ops = {
 194        .show = cc_attr_show,
 195        .store = cc_attr_store
 196};
 197
 198static struct attribute *port_cc_default_attributes[] = {
 199        &cc_prescan_attr.attr,
 200        NULL
 201};
 202
 203static struct kobj_type port_cc_ktype = {
 204        .release = port_release,
 205        .sysfs_ops = &port_cc_sysfs_ops,
 206        .default_attrs = port_cc_default_attributes
 207};
 208
 209/* Start sc2vl */
 210#define HFI1_SC2VL_ATTR(N)                                  \
 211        static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = { \
 212                .attr = { .name = __stringify(N), .mode = 0444 }, \
 213                .sc = N \
 214        }
 215
 216struct hfi1_sc2vl_attr {
 217        struct attribute attr;
 218        int sc;
 219};
 220
 221HFI1_SC2VL_ATTR(0);
 222HFI1_SC2VL_ATTR(1);
 223HFI1_SC2VL_ATTR(2);
 224HFI1_SC2VL_ATTR(3);
 225HFI1_SC2VL_ATTR(4);
 226HFI1_SC2VL_ATTR(5);
 227HFI1_SC2VL_ATTR(6);
 228HFI1_SC2VL_ATTR(7);
 229HFI1_SC2VL_ATTR(8);
 230HFI1_SC2VL_ATTR(9);
 231HFI1_SC2VL_ATTR(10);
 232HFI1_SC2VL_ATTR(11);
 233HFI1_SC2VL_ATTR(12);
 234HFI1_SC2VL_ATTR(13);
 235HFI1_SC2VL_ATTR(14);
 236HFI1_SC2VL_ATTR(15);
 237HFI1_SC2VL_ATTR(16);
 238HFI1_SC2VL_ATTR(17);
 239HFI1_SC2VL_ATTR(18);
 240HFI1_SC2VL_ATTR(19);
 241HFI1_SC2VL_ATTR(20);
 242HFI1_SC2VL_ATTR(21);
 243HFI1_SC2VL_ATTR(22);
 244HFI1_SC2VL_ATTR(23);
 245HFI1_SC2VL_ATTR(24);
 246HFI1_SC2VL_ATTR(25);
 247HFI1_SC2VL_ATTR(26);
 248HFI1_SC2VL_ATTR(27);
 249HFI1_SC2VL_ATTR(28);
 250HFI1_SC2VL_ATTR(29);
 251HFI1_SC2VL_ATTR(30);
 252HFI1_SC2VL_ATTR(31);
 253
 254static struct attribute *sc2vl_default_attributes[] = {
 255        &hfi1_sc2vl_attr_0.attr,
 256        &hfi1_sc2vl_attr_1.attr,
 257        &hfi1_sc2vl_attr_2.attr,
 258        &hfi1_sc2vl_attr_3.attr,
 259        &hfi1_sc2vl_attr_4.attr,
 260        &hfi1_sc2vl_attr_5.attr,
 261        &hfi1_sc2vl_attr_6.attr,
 262        &hfi1_sc2vl_attr_7.attr,
 263        &hfi1_sc2vl_attr_8.attr,
 264        &hfi1_sc2vl_attr_9.attr,
 265        &hfi1_sc2vl_attr_10.attr,
 266        &hfi1_sc2vl_attr_11.attr,
 267        &hfi1_sc2vl_attr_12.attr,
 268        &hfi1_sc2vl_attr_13.attr,
 269        &hfi1_sc2vl_attr_14.attr,
 270        &hfi1_sc2vl_attr_15.attr,
 271        &hfi1_sc2vl_attr_16.attr,
 272        &hfi1_sc2vl_attr_17.attr,
 273        &hfi1_sc2vl_attr_18.attr,
 274        &hfi1_sc2vl_attr_19.attr,
 275        &hfi1_sc2vl_attr_20.attr,
 276        &hfi1_sc2vl_attr_21.attr,
 277        &hfi1_sc2vl_attr_22.attr,
 278        &hfi1_sc2vl_attr_23.attr,
 279        &hfi1_sc2vl_attr_24.attr,
 280        &hfi1_sc2vl_attr_25.attr,
 281        &hfi1_sc2vl_attr_26.attr,
 282        &hfi1_sc2vl_attr_27.attr,
 283        &hfi1_sc2vl_attr_28.attr,
 284        &hfi1_sc2vl_attr_29.attr,
 285        &hfi1_sc2vl_attr_30.attr,
 286        &hfi1_sc2vl_attr_31.attr,
 287        NULL
 288};
 289
 290static ssize_t sc2vl_attr_show(struct kobject *kobj, struct attribute *attr,
 291                               char *buf)
 292{
 293        struct hfi1_sc2vl_attr *sattr =
 294                container_of(attr, struct hfi1_sc2vl_attr, attr);
 295        struct hfi1_pportdata *ppd =
 296                container_of(kobj, struct hfi1_pportdata, sc2vl_kobj);
 297        struct hfi1_devdata *dd = ppd->dd;
 298
 299        return sprintf(buf, "%u\n", *((u8 *)dd->sc2vl + sattr->sc));
 300}
 301
 302static const struct sysfs_ops hfi1_sc2vl_ops = {
 303        .show = sc2vl_attr_show,
 304};
 305
 306static struct kobj_type hfi1_sc2vl_ktype = {
 307        .release = port_release,
 308        .sysfs_ops = &hfi1_sc2vl_ops,
 309        .default_attrs = sc2vl_default_attributes
 310};
 311
 312/* End sc2vl */
 313
 314/* Start sl2sc */
 315#define HFI1_SL2SC_ATTR(N)                                  \
 316        static struct hfi1_sl2sc_attr hfi1_sl2sc_attr_##N = {     \
 317                .attr = { .name = __stringify(N), .mode = 0444 }, \
 318                .sl = N                                           \
 319        }
 320
 321struct hfi1_sl2sc_attr {
 322        struct attribute attr;
 323        int sl;
 324};
 325
 326HFI1_SL2SC_ATTR(0);
 327HFI1_SL2SC_ATTR(1);
 328HFI1_SL2SC_ATTR(2);
 329HFI1_SL2SC_ATTR(3);
 330HFI1_SL2SC_ATTR(4);
 331HFI1_SL2SC_ATTR(5);
 332HFI1_SL2SC_ATTR(6);
 333HFI1_SL2SC_ATTR(7);
 334HFI1_SL2SC_ATTR(8);
 335HFI1_SL2SC_ATTR(9);
 336HFI1_SL2SC_ATTR(10);
 337HFI1_SL2SC_ATTR(11);
 338HFI1_SL2SC_ATTR(12);
 339HFI1_SL2SC_ATTR(13);
 340HFI1_SL2SC_ATTR(14);
 341HFI1_SL2SC_ATTR(15);
 342HFI1_SL2SC_ATTR(16);
 343HFI1_SL2SC_ATTR(17);
 344HFI1_SL2SC_ATTR(18);
 345HFI1_SL2SC_ATTR(19);
 346HFI1_SL2SC_ATTR(20);
 347HFI1_SL2SC_ATTR(21);
 348HFI1_SL2SC_ATTR(22);
 349HFI1_SL2SC_ATTR(23);
 350HFI1_SL2SC_ATTR(24);
 351HFI1_SL2SC_ATTR(25);
 352HFI1_SL2SC_ATTR(26);
 353HFI1_SL2SC_ATTR(27);
 354HFI1_SL2SC_ATTR(28);
 355HFI1_SL2SC_ATTR(29);
 356HFI1_SL2SC_ATTR(30);
 357HFI1_SL2SC_ATTR(31);
 358
 359static struct attribute *sl2sc_default_attributes[] = {
 360        &hfi1_sl2sc_attr_0.attr,
 361        &hfi1_sl2sc_attr_1.attr,
 362        &hfi1_sl2sc_attr_2.attr,
 363        &hfi1_sl2sc_attr_3.attr,
 364        &hfi1_sl2sc_attr_4.attr,
 365        &hfi1_sl2sc_attr_5.attr,
 366        &hfi1_sl2sc_attr_6.attr,
 367        &hfi1_sl2sc_attr_7.attr,
 368        &hfi1_sl2sc_attr_8.attr,
 369        &hfi1_sl2sc_attr_9.attr,
 370        &hfi1_sl2sc_attr_10.attr,
 371        &hfi1_sl2sc_attr_11.attr,
 372        &hfi1_sl2sc_attr_12.attr,
 373        &hfi1_sl2sc_attr_13.attr,
 374        &hfi1_sl2sc_attr_14.attr,
 375        &hfi1_sl2sc_attr_15.attr,
 376        &hfi1_sl2sc_attr_16.attr,
 377        &hfi1_sl2sc_attr_17.attr,
 378        &hfi1_sl2sc_attr_18.attr,
 379        &hfi1_sl2sc_attr_19.attr,
 380        &hfi1_sl2sc_attr_20.attr,
 381        &hfi1_sl2sc_attr_21.attr,
 382        &hfi1_sl2sc_attr_22.attr,
 383        &hfi1_sl2sc_attr_23.attr,
 384        &hfi1_sl2sc_attr_24.attr,
 385        &hfi1_sl2sc_attr_25.attr,
 386        &hfi1_sl2sc_attr_26.attr,
 387        &hfi1_sl2sc_attr_27.attr,
 388        &hfi1_sl2sc_attr_28.attr,
 389        &hfi1_sl2sc_attr_29.attr,
 390        &hfi1_sl2sc_attr_30.attr,
 391        &hfi1_sl2sc_attr_31.attr,
 392        NULL
 393};
 394
 395static ssize_t sl2sc_attr_show(struct kobject *kobj, struct attribute *attr,
 396                               char *buf)
 397{
 398        struct hfi1_sl2sc_attr *sattr =
 399                container_of(attr, struct hfi1_sl2sc_attr, attr);
 400        struct hfi1_pportdata *ppd =
 401                container_of(kobj, struct hfi1_pportdata, sl2sc_kobj);
 402        struct hfi1_ibport *ibp = &ppd->ibport_data;
 403
 404        return sprintf(buf, "%u\n", ibp->sl_to_sc[sattr->sl]);
 405}
 406
 407static const struct sysfs_ops hfi1_sl2sc_ops = {
 408        .show = sl2sc_attr_show,
 409};
 410
 411static struct kobj_type hfi1_sl2sc_ktype = {
 412        .release = port_release,
 413        .sysfs_ops = &hfi1_sl2sc_ops,
 414        .default_attrs = sl2sc_default_attributes
 415};
 416
 417/* End sl2sc */
 418
 419/* Start vl2mtu */
 420
 421#define HFI1_VL2MTU_ATTR(N) \
 422        static struct hfi1_vl2mtu_attr hfi1_vl2mtu_attr_##N = { \
 423                .attr = { .name = __stringify(N), .mode = 0444 }, \
 424                .vl = N                                           \
 425        }
 426
 427struct hfi1_vl2mtu_attr {
 428        struct attribute attr;
 429        int vl;
 430};
 431
 432HFI1_VL2MTU_ATTR(0);
 433HFI1_VL2MTU_ATTR(1);
 434HFI1_VL2MTU_ATTR(2);
 435HFI1_VL2MTU_ATTR(3);
 436HFI1_VL2MTU_ATTR(4);
 437HFI1_VL2MTU_ATTR(5);
 438HFI1_VL2MTU_ATTR(6);
 439HFI1_VL2MTU_ATTR(7);
 440HFI1_VL2MTU_ATTR(8);
 441HFI1_VL2MTU_ATTR(9);
 442HFI1_VL2MTU_ATTR(10);
 443HFI1_VL2MTU_ATTR(11);
 444HFI1_VL2MTU_ATTR(12);
 445HFI1_VL2MTU_ATTR(13);
 446HFI1_VL2MTU_ATTR(14);
 447HFI1_VL2MTU_ATTR(15);
 448
 449static struct attribute *vl2mtu_default_attributes[] = {
 450        &hfi1_vl2mtu_attr_0.attr,
 451        &hfi1_vl2mtu_attr_1.attr,
 452        &hfi1_vl2mtu_attr_2.attr,
 453        &hfi1_vl2mtu_attr_3.attr,
 454        &hfi1_vl2mtu_attr_4.attr,
 455        &hfi1_vl2mtu_attr_5.attr,
 456        &hfi1_vl2mtu_attr_6.attr,
 457        &hfi1_vl2mtu_attr_7.attr,
 458        &hfi1_vl2mtu_attr_8.attr,
 459        &hfi1_vl2mtu_attr_9.attr,
 460        &hfi1_vl2mtu_attr_10.attr,
 461        &hfi1_vl2mtu_attr_11.attr,
 462        &hfi1_vl2mtu_attr_12.attr,
 463        &hfi1_vl2mtu_attr_13.attr,
 464        &hfi1_vl2mtu_attr_14.attr,
 465        &hfi1_vl2mtu_attr_15.attr,
 466        NULL
 467};
 468
 469static ssize_t vl2mtu_attr_show(struct kobject *kobj, struct attribute *attr,
 470                                char *buf)
 471{
 472        struct hfi1_vl2mtu_attr *vlattr =
 473                container_of(attr, struct hfi1_vl2mtu_attr, attr);
 474        struct hfi1_pportdata *ppd =
 475                container_of(kobj, struct hfi1_pportdata, vl2mtu_kobj);
 476        struct hfi1_devdata *dd = ppd->dd;
 477
 478        return sprintf(buf, "%u\n", dd->vld[vlattr->vl].mtu);
 479}
 480
 481static const struct sysfs_ops hfi1_vl2mtu_ops = {
 482        .show = vl2mtu_attr_show,
 483};
 484
 485static struct kobj_type hfi1_vl2mtu_ktype = {
 486        .release = port_release,
 487        .sysfs_ops = &hfi1_vl2mtu_ops,
 488        .default_attrs = vl2mtu_default_attributes
 489};
 490
 491/* end of per-port file structures and support code */
 492
 493/*
 494 * Start of per-unit (or driver, in some cases, but replicated
 495 * per unit) functions (these get a device *)
 496 */
 497static ssize_t show_rev(struct device *device, struct device_attribute *attr,
 498                        char *buf)
 499{
 500        struct hfi1_ibdev *dev =
 501                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 502
 503        return sprintf(buf, "%x\n", dd_from_dev(dev)->minrev);
 504}
 505
 506static ssize_t show_hfi(struct device *device, struct device_attribute *attr,
 507                        char *buf)
 508{
 509        struct hfi1_ibdev *dev =
 510                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 511        struct hfi1_devdata *dd = dd_from_dev(dev);
 512        int ret;
 513
 514        if (!dd->boardname)
 515                ret = -EINVAL;
 516        else
 517                ret = scnprintf(buf, PAGE_SIZE, "%s\n", dd->boardname);
 518        return ret;
 519}
 520
 521static ssize_t show_boardversion(struct device *device,
 522                                 struct device_attribute *attr, char *buf)
 523{
 524        struct hfi1_ibdev *dev =
 525                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 526        struct hfi1_devdata *dd = dd_from_dev(dev);
 527
 528        /* The string printed here is already newline-terminated. */
 529        return scnprintf(buf, PAGE_SIZE, "%s", dd->boardversion);
 530}
 531
 532static ssize_t show_nctxts(struct device *device,
 533                           struct device_attribute *attr, char *buf)
 534{
 535        struct hfi1_ibdev *dev =
 536                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 537        struct hfi1_devdata *dd = dd_from_dev(dev);
 538
 539        /*
 540         * Return the smaller of send and receive contexts.
 541         * Normally, user level applications would require both a send
 542         * and a receive context, so returning the smaller of the two counts
 543         * give a more accurate picture of total contexts available.
 544         */
 545        return scnprintf(buf, PAGE_SIZE, "%u\n",
 546                         min(dd->num_user_contexts,
 547                             (u32)dd->sc_sizes[SC_USER].count));
 548}
 549
 550static ssize_t show_nfreectxts(struct device *device,
 551                               struct device_attribute *attr, char *buf)
 552{
 553        struct hfi1_ibdev *dev =
 554                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 555        struct hfi1_devdata *dd = dd_from_dev(dev);
 556
 557        /* Return the number of free user ports (contexts) available. */
 558        return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts);
 559}
 560
 561static ssize_t show_serial(struct device *device,
 562                           struct device_attribute *attr, char *buf)
 563{
 564        struct hfi1_ibdev *dev =
 565                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 566        struct hfi1_devdata *dd = dd_from_dev(dev);
 567
 568        return scnprintf(buf, PAGE_SIZE, "%s", dd->serial);
 569}
 570
 571static ssize_t store_chip_reset(struct device *device,
 572                                struct device_attribute *attr, const char *buf,
 573                                size_t count)
 574{
 575        struct hfi1_ibdev *dev =
 576                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 577        struct hfi1_devdata *dd = dd_from_dev(dev);
 578        int ret;
 579
 580        if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) {
 581                ret = -EINVAL;
 582                goto bail;
 583        }
 584
 585        ret = hfi1_reset_device(dd->unit);
 586bail:
 587        return ret < 0 ? ret : count;
 588}
 589
 590/*
 591 * Convert the reported temperature from an integer (reported in
 592 * units of 0.25C) to a floating point number.
 593 */
 594#define temp2str(temp, buf, size, idx)                                  \
 595        scnprintf((buf) + (idx), (size) - (idx), "%u.%02u ",            \
 596                              ((temp) >> 2), ((temp) & 0x3) * 25)
 597
 598/*
 599 * Dump tempsense values, in decimal, to ease shell-scripts.
 600 */
 601static ssize_t show_tempsense(struct device *device,
 602                              struct device_attribute *attr, char *buf)
 603{
 604        struct hfi1_ibdev *dev =
 605                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 606        struct hfi1_devdata *dd = dd_from_dev(dev);
 607        struct hfi1_temp temp;
 608        int ret;
 609
 610        ret = hfi1_tempsense_rd(dd, &temp);
 611        if (!ret) {
 612                int idx = 0;
 613
 614                idx += temp2str(temp.curr, buf, PAGE_SIZE, idx);
 615                idx += temp2str(temp.lo_lim, buf, PAGE_SIZE, idx);
 616                idx += temp2str(temp.hi_lim, buf, PAGE_SIZE, idx);
 617                idx += temp2str(temp.crit_lim, buf, PAGE_SIZE, idx);
 618                idx += scnprintf(buf + idx, PAGE_SIZE - idx,
 619                                "%u %u %u\n", temp.triggers & 0x1,
 620                                temp.triggers & 0x2, temp.triggers & 0x4);
 621                ret = idx;
 622        }
 623        return ret;
 624}
 625
 626/*
 627 * end of per-unit (or driver, in some cases, but replicated
 628 * per unit) functions
 629 */
 630
 631/* start of per-unit file structures and support code */
 632static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
 633static DEVICE_ATTR(board_id, S_IRUGO, show_hfi, NULL);
 634static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL);
 635static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL);
 636static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
 637static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
 638static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL);
 639static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset);
 640
 641static struct device_attribute *hfi1_attributes[] = {
 642        &dev_attr_hw_rev,
 643        &dev_attr_board_id,
 644        &dev_attr_nctxts,
 645        &dev_attr_nfreectxts,
 646        &dev_attr_serial,
 647        &dev_attr_boardversion,
 648        &dev_attr_tempsense,
 649        &dev_attr_chip_reset,
 650};
 651
 652int hfi1_create_port_files(struct ib_device *ibdev, u8 port_num,
 653                           struct kobject *kobj)
 654{
 655        struct hfi1_pportdata *ppd;
 656        struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
 657        int ret;
 658
 659        if (!port_num || port_num > dd->num_pports) {
 660                dd_dev_err(dd,
 661                           "Skipping infiniband class with invalid port %u\n",
 662                           port_num);
 663                return -ENODEV;
 664        }
 665        ppd = &dd->pport[port_num - 1];
 666
 667        ret = kobject_init_and_add(&ppd->sc2vl_kobj, &hfi1_sc2vl_ktype, kobj,
 668                                   "sc2vl");
 669        if (ret) {
 670                dd_dev_err(dd,
 671                           "Skipping sc2vl sysfs info, (err %d) port %u\n",
 672                           ret, port_num);
 673                goto bail;
 674        }
 675        kobject_uevent(&ppd->sc2vl_kobj, KOBJ_ADD);
 676
 677        ret = kobject_init_and_add(&ppd->sl2sc_kobj, &hfi1_sl2sc_ktype, kobj,
 678                                   "sl2sc");
 679        if (ret) {
 680                dd_dev_err(dd,
 681                           "Skipping sl2sc sysfs info, (err %d) port %u\n",
 682                           ret, port_num);
 683                goto bail_sc2vl;
 684        }
 685        kobject_uevent(&ppd->sl2sc_kobj, KOBJ_ADD);
 686
 687        ret = kobject_init_and_add(&ppd->vl2mtu_kobj, &hfi1_vl2mtu_ktype, kobj,
 688                                   "vl2mtu");
 689        if (ret) {
 690                dd_dev_err(dd,
 691                           "Skipping vl2mtu sysfs info, (err %d) port %u\n",
 692                           ret, port_num);
 693                goto bail_sl2sc;
 694        }
 695        kobject_uevent(&ppd->vl2mtu_kobj, KOBJ_ADD);
 696
 697        ret = kobject_init_and_add(&ppd->pport_cc_kobj, &port_cc_ktype,
 698                                   kobj, "CCMgtA");
 699        if (ret) {
 700                dd_dev_err(dd,
 701                           "Skipping Congestion Control sysfs info, (err %d) port %u\n",
 702                           ret, port_num);
 703                goto bail_vl2mtu;
 704        }
 705
 706        kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD);
 707
 708        ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, &cc_setting_bin_attr);
 709        if (ret) {
 710                dd_dev_err(dd,
 711                           "Skipping Congestion Control setting sysfs info, (err %d) port %u\n",
 712                           ret, port_num);
 713                goto bail_cc;
 714        }
 715
 716        ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, &cc_table_bin_attr);
 717        if (ret) {
 718                dd_dev_err(dd,
 719                           "Skipping Congestion Control table sysfs info, (err %d) port %u\n",
 720                           ret, port_num);
 721                goto bail_cc_entry_bin;
 722        }
 723
 724        dd_dev_info(dd,
 725                    "Congestion Control Agent enabled for port %d\n",
 726                    port_num);
 727
 728        return 0;
 729
 730bail_cc_entry_bin:
 731        sysfs_remove_bin_file(&ppd->pport_cc_kobj,
 732                              &cc_setting_bin_attr);
 733bail_cc:
 734        kobject_put(&ppd->pport_cc_kobj);
 735bail_vl2mtu:
 736        kobject_put(&ppd->vl2mtu_kobj);
 737bail_sl2sc:
 738        kobject_put(&ppd->sl2sc_kobj);
 739bail_sc2vl:
 740        kobject_put(&ppd->sc2vl_kobj);
 741bail:
 742        return ret;
 743}
 744
 745struct sde_attribute {
 746        struct attribute attr;
 747        ssize_t (*show)(struct sdma_engine *sde, char *buf);
 748        ssize_t (*store)(struct sdma_engine *sde, const char *buf, size_t cnt);
 749};
 750
 751static ssize_t sde_show(struct kobject *kobj, struct attribute *attr, char *buf)
 752{
 753        struct sde_attribute *sde_attr =
 754                container_of(attr, struct sde_attribute, attr);
 755        struct sdma_engine *sde =
 756                container_of(kobj, struct sdma_engine, kobj);
 757
 758        if (!sde_attr->show)
 759                return -EINVAL;
 760
 761        return sde_attr->show(sde, buf);
 762}
 763
 764static ssize_t sde_store(struct kobject *kobj, struct attribute *attr,
 765                         const char *buf, size_t count)
 766{
 767        struct sde_attribute *sde_attr =
 768                container_of(attr, struct sde_attribute, attr);
 769        struct sdma_engine *sde =
 770                container_of(kobj, struct sdma_engine, kobj);
 771
 772        if (!capable(CAP_SYS_ADMIN))
 773                return -EPERM;
 774
 775        if (!sde_attr->store)
 776                return -EINVAL;
 777
 778        return sde_attr->store(sde, buf, count);
 779}
 780
 781static const struct sysfs_ops sde_sysfs_ops = {
 782        .show = sde_show,
 783        .store = sde_store,
 784};
 785
 786static struct kobj_type sde_ktype = {
 787        .sysfs_ops = &sde_sysfs_ops,
 788};
 789
 790#define SDE_ATTR(_name, _mode, _show, _store) \
 791        struct sde_attribute sde_attr_##_name = \
 792                __ATTR(_name, _mode, _show, _store)
 793
 794static ssize_t sde_show_cpu_to_sde_map(struct sdma_engine *sde, char *buf)
 795{
 796        return sdma_get_cpu_to_sde_map(sde, buf);
 797}
 798
 799static ssize_t sde_store_cpu_to_sde_map(struct sdma_engine *sde,
 800                                        const char *buf, size_t count)
 801{
 802        return sdma_set_cpu_to_sde_map(sde, buf, count);
 803}
 804
 805static ssize_t sde_show_vl(struct sdma_engine *sde, char *buf)
 806{
 807        int vl;
 808
 809        vl = sdma_engine_get_vl(sde);
 810        if (vl < 0)
 811                return vl;
 812
 813        return snprintf(buf, PAGE_SIZE, "%d\n", vl);
 814}
 815
 816static SDE_ATTR(cpu_list, S_IWUSR | S_IRUGO,
 817                sde_show_cpu_to_sde_map,
 818                sde_store_cpu_to_sde_map);
 819static SDE_ATTR(vl, S_IRUGO, sde_show_vl, NULL);
 820
 821static struct sde_attribute *sde_attribs[] = {
 822        &sde_attr_cpu_list,
 823        &sde_attr_vl
 824};
 825
 826/*
 827 * Register and create our files in /sys/class/infiniband.
 828 */
 829int hfi1_verbs_register_sysfs(struct hfi1_devdata *dd)
 830{
 831        struct ib_device *dev = &dd->verbs_dev.rdi.ibdev;
 832        struct device *class_dev = &dev->dev;
 833        int i, j, ret;
 834
 835        for (i = 0; i < ARRAY_SIZE(hfi1_attributes); ++i) {
 836                ret = device_create_file(&dev->dev, hfi1_attributes[i]);
 837                if (ret)
 838                        goto bail;
 839        }
 840
 841        for (i = 0; i < dd->num_sdma; i++) {
 842                ret = kobject_init_and_add(&dd->per_sdma[i].kobj,
 843                                           &sde_ktype, &class_dev->kobj,
 844                                           "sdma%d", i);
 845                if (ret)
 846                        goto bail;
 847
 848                for (j = 0; j < ARRAY_SIZE(sde_attribs); j++) {
 849                        ret = sysfs_create_file(&dd->per_sdma[i].kobj,
 850                                                &sde_attribs[j]->attr);
 851                        if (ret)
 852                                goto bail;
 853                }
 854        }
 855
 856        return 0;
 857bail:
 858        for (i = 0; i < ARRAY_SIZE(hfi1_attributes); ++i)
 859                device_remove_file(&dev->dev, hfi1_attributes[i]);
 860
 861        for (i = 0; i < dd->num_sdma; i++)
 862                kobject_del(&dd->per_sdma[i].kobj);
 863
 864        return ret;
 865}
 866
 867/*
 868 * Unregister and remove our files in /sys/class/infiniband.
 869 */
 870void hfi1_verbs_unregister_sysfs(struct hfi1_devdata *dd)
 871{
 872        struct hfi1_pportdata *ppd;
 873        int i;
 874
 875        for (i = 0; i < dd->num_pports; i++) {
 876                ppd = &dd->pport[i];
 877
 878                sysfs_remove_bin_file(&ppd->pport_cc_kobj,
 879                                      &cc_setting_bin_attr);
 880                sysfs_remove_bin_file(&ppd->pport_cc_kobj,
 881                                      &cc_table_bin_attr);
 882                kobject_put(&ppd->pport_cc_kobj);
 883                kobject_put(&ppd->vl2mtu_kobj);
 884                kobject_put(&ppd->sl2sc_kobj);
 885                kobject_put(&ppd->sc2vl_kobj);
 886        }
 887}
 888