linux/drivers/infiniband/hw/hfi1/sysfs.c
<<
>>
Prefs
   1/*
   2 * Copyright(c) 2015, 2016 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 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 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};
 201
 202static struct kobj_type port_cc_ktype = {
 203        .release = port_release,
 204        .sysfs_ops = &port_cc_sysfs_ops,
 205        .default_attrs = port_cc_default_attributes
 206};
 207
 208/* Start sc2vl */
 209#define HFI1_SC2VL_ATTR(N)                                  \
 210        static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = { \
 211                .attr = { .name = __stringify(N), .mode = 0444 }, \
 212                .sc = N \
 213        }
 214
 215struct hfi1_sc2vl_attr {
 216        struct attribute attr;
 217        int sc;
 218};
 219
 220HFI1_SC2VL_ATTR(0);
 221HFI1_SC2VL_ATTR(1);
 222HFI1_SC2VL_ATTR(2);
 223HFI1_SC2VL_ATTR(3);
 224HFI1_SC2VL_ATTR(4);
 225HFI1_SC2VL_ATTR(5);
 226HFI1_SC2VL_ATTR(6);
 227HFI1_SC2VL_ATTR(7);
 228HFI1_SC2VL_ATTR(8);
 229HFI1_SC2VL_ATTR(9);
 230HFI1_SC2VL_ATTR(10);
 231HFI1_SC2VL_ATTR(11);
 232HFI1_SC2VL_ATTR(12);
 233HFI1_SC2VL_ATTR(13);
 234HFI1_SC2VL_ATTR(14);
 235HFI1_SC2VL_ATTR(15);
 236HFI1_SC2VL_ATTR(16);
 237HFI1_SC2VL_ATTR(17);
 238HFI1_SC2VL_ATTR(18);
 239HFI1_SC2VL_ATTR(19);
 240HFI1_SC2VL_ATTR(20);
 241HFI1_SC2VL_ATTR(21);
 242HFI1_SC2VL_ATTR(22);
 243HFI1_SC2VL_ATTR(23);
 244HFI1_SC2VL_ATTR(24);
 245HFI1_SC2VL_ATTR(25);
 246HFI1_SC2VL_ATTR(26);
 247HFI1_SC2VL_ATTR(27);
 248HFI1_SC2VL_ATTR(28);
 249HFI1_SC2VL_ATTR(29);
 250HFI1_SC2VL_ATTR(30);
 251HFI1_SC2VL_ATTR(31);
 252
 253static struct attribute *sc2vl_default_attributes[] = {
 254        &hfi1_sc2vl_attr_0.attr,
 255        &hfi1_sc2vl_attr_1.attr,
 256        &hfi1_sc2vl_attr_2.attr,
 257        &hfi1_sc2vl_attr_3.attr,
 258        &hfi1_sc2vl_attr_4.attr,
 259        &hfi1_sc2vl_attr_5.attr,
 260        &hfi1_sc2vl_attr_6.attr,
 261        &hfi1_sc2vl_attr_7.attr,
 262        &hfi1_sc2vl_attr_8.attr,
 263        &hfi1_sc2vl_attr_9.attr,
 264        &hfi1_sc2vl_attr_10.attr,
 265        &hfi1_sc2vl_attr_11.attr,
 266        &hfi1_sc2vl_attr_12.attr,
 267        &hfi1_sc2vl_attr_13.attr,
 268        &hfi1_sc2vl_attr_14.attr,
 269        &hfi1_sc2vl_attr_15.attr,
 270        &hfi1_sc2vl_attr_16.attr,
 271        &hfi1_sc2vl_attr_17.attr,
 272        &hfi1_sc2vl_attr_18.attr,
 273        &hfi1_sc2vl_attr_19.attr,
 274        &hfi1_sc2vl_attr_20.attr,
 275        &hfi1_sc2vl_attr_21.attr,
 276        &hfi1_sc2vl_attr_22.attr,
 277        &hfi1_sc2vl_attr_23.attr,
 278        &hfi1_sc2vl_attr_24.attr,
 279        &hfi1_sc2vl_attr_25.attr,
 280        &hfi1_sc2vl_attr_26.attr,
 281        &hfi1_sc2vl_attr_27.attr,
 282        &hfi1_sc2vl_attr_28.attr,
 283        &hfi1_sc2vl_attr_29.attr,
 284        &hfi1_sc2vl_attr_30.attr,
 285        &hfi1_sc2vl_attr_31.attr,
 286        NULL
 287};
 288
 289static ssize_t sc2vl_attr_show(struct kobject *kobj, struct attribute *attr,
 290                               char *buf)
 291{
 292        struct hfi1_sc2vl_attr *sattr =
 293                container_of(attr, struct hfi1_sc2vl_attr, attr);
 294        struct hfi1_pportdata *ppd =
 295                container_of(kobj, struct hfi1_pportdata, sc2vl_kobj);
 296        struct hfi1_devdata *dd = ppd->dd;
 297
 298        return sprintf(buf, "%u\n", *((u8 *)dd->sc2vl + sattr->sc));
 299}
 300
 301static const struct sysfs_ops hfi1_sc2vl_ops = {
 302        .show = sc2vl_attr_show,
 303};
 304
 305static struct kobj_type hfi1_sc2vl_ktype = {
 306        .release = port_release,
 307        .sysfs_ops = &hfi1_sc2vl_ops,
 308        .default_attrs = sc2vl_default_attributes
 309};
 310
 311/* End sc2vl */
 312
 313/* Start sl2sc */
 314#define HFI1_SL2SC_ATTR(N)                                  \
 315        static struct hfi1_sl2sc_attr hfi1_sl2sc_attr_##N = {     \
 316                .attr = { .name = __stringify(N), .mode = 0444 }, \
 317                .sl = N                                           \
 318        }
 319
 320struct hfi1_sl2sc_attr {
 321        struct attribute attr;
 322        int sl;
 323};
 324
 325HFI1_SL2SC_ATTR(0);
 326HFI1_SL2SC_ATTR(1);
 327HFI1_SL2SC_ATTR(2);
 328HFI1_SL2SC_ATTR(3);
 329HFI1_SL2SC_ATTR(4);
 330HFI1_SL2SC_ATTR(5);
 331HFI1_SL2SC_ATTR(6);
 332HFI1_SL2SC_ATTR(7);
 333HFI1_SL2SC_ATTR(8);
 334HFI1_SL2SC_ATTR(9);
 335HFI1_SL2SC_ATTR(10);
 336HFI1_SL2SC_ATTR(11);
 337HFI1_SL2SC_ATTR(12);
 338HFI1_SL2SC_ATTR(13);
 339HFI1_SL2SC_ATTR(14);
 340HFI1_SL2SC_ATTR(15);
 341HFI1_SL2SC_ATTR(16);
 342HFI1_SL2SC_ATTR(17);
 343HFI1_SL2SC_ATTR(18);
 344HFI1_SL2SC_ATTR(19);
 345HFI1_SL2SC_ATTR(20);
 346HFI1_SL2SC_ATTR(21);
 347HFI1_SL2SC_ATTR(22);
 348HFI1_SL2SC_ATTR(23);
 349HFI1_SL2SC_ATTR(24);
 350HFI1_SL2SC_ATTR(25);
 351HFI1_SL2SC_ATTR(26);
 352HFI1_SL2SC_ATTR(27);
 353HFI1_SL2SC_ATTR(28);
 354HFI1_SL2SC_ATTR(29);
 355HFI1_SL2SC_ATTR(30);
 356HFI1_SL2SC_ATTR(31);
 357
 358static struct attribute *sl2sc_default_attributes[] = {
 359        &hfi1_sl2sc_attr_0.attr,
 360        &hfi1_sl2sc_attr_1.attr,
 361        &hfi1_sl2sc_attr_2.attr,
 362        &hfi1_sl2sc_attr_3.attr,
 363        &hfi1_sl2sc_attr_4.attr,
 364        &hfi1_sl2sc_attr_5.attr,
 365        &hfi1_sl2sc_attr_6.attr,
 366        &hfi1_sl2sc_attr_7.attr,
 367        &hfi1_sl2sc_attr_8.attr,
 368        &hfi1_sl2sc_attr_9.attr,
 369        &hfi1_sl2sc_attr_10.attr,
 370        &hfi1_sl2sc_attr_11.attr,
 371        &hfi1_sl2sc_attr_12.attr,
 372        &hfi1_sl2sc_attr_13.attr,
 373        &hfi1_sl2sc_attr_14.attr,
 374        &hfi1_sl2sc_attr_15.attr,
 375        &hfi1_sl2sc_attr_16.attr,
 376        &hfi1_sl2sc_attr_17.attr,
 377        &hfi1_sl2sc_attr_18.attr,
 378        &hfi1_sl2sc_attr_19.attr,
 379        &hfi1_sl2sc_attr_20.attr,
 380        &hfi1_sl2sc_attr_21.attr,
 381        &hfi1_sl2sc_attr_22.attr,
 382        &hfi1_sl2sc_attr_23.attr,
 383        &hfi1_sl2sc_attr_24.attr,
 384        &hfi1_sl2sc_attr_25.attr,
 385        &hfi1_sl2sc_attr_26.attr,
 386        &hfi1_sl2sc_attr_27.attr,
 387        &hfi1_sl2sc_attr_28.attr,
 388        &hfi1_sl2sc_attr_29.attr,
 389        &hfi1_sl2sc_attr_30.attr,
 390        &hfi1_sl2sc_attr_31.attr,
 391        NULL
 392};
 393
 394static ssize_t sl2sc_attr_show(struct kobject *kobj, struct attribute *attr,
 395                               char *buf)
 396{
 397        struct hfi1_sl2sc_attr *sattr =
 398                container_of(attr, struct hfi1_sl2sc_attr, attr);
 399        struct hfi1_pportdata *ppd =
 400                container_of(kobj, struct hfi1_pportdata, sl2sc_kobj);
 401        struct hfi1_ibport *ibp = &ppd->ibport_data;
 402
 403        return sprintf(buf, "%u\n", ibp->sl_to_sc[sattr->sl]);
 404}
 405
 406static const struct sysfs_ops hfi1_sl2sc_ops = {
 407        .show = sl2sc_attr_show,
 408};
 409
 410static struct kobj_type hfi1_sl2sc_ktype = {
 411        .release = port_release,
 412        .sysfs_ops = &hfi1_sl2sc_ops,
 413        .default_attrs = sl2sc_default_attributes
 414};
 415
 416/* End sl2sc */
 417
 418/* Start vl2mtu */
 419
 420#define HFI1_VL2MTU_ATTR(N) \
 421        static struct hfi1_vl2mtu_attr hfi1_vl2mtu_attr_##N = { \
 422                .attr = { .name = __stringify(N), .mode = 0444 }, \
 423                .vl = N                                           \
 424        }
 425
 426struct hfi1_vl2mtu_attr {
 427        struct attribute attr;
 428        int vl;
 429};
 430
 431HFI1_VL2MTU_ATTR(0);
 432HFI1_VL2MTU_ATTR(1);
 433HFI1_VL2MTU_ATTR(2);
 434HFI1_VL2MTU_ATTR(3);
 435HFI1_VL2MTU_ATTR(4);
 436HFI1_VL2MTU_ATTR(5);
 437HFI1_VL2MTU_ATTR(6);
 438HFI1_VL2MTU_ATTR(7);
 439HFI1_VL2MTU_ATTR(8);
 440HFI1_VL2MTU_ATTR(9);
 441HFI1_VL2MTU_ATTR(10);
 442HFI1_VL2MTU_ATTR(11);
 443HFI1_VL2MTU_ATTR(12);
 444HFI1_VL2MTU_ATTR(13);
 445HFI1_VL2MTU_ATTR(14);
 446HFI1_VL2MTU_ATTR(15);
 447
 448static struct attribute *vl2mtu_default_attributes[] = {
 449        &hfi1_vl2mtu_attr_0.attr,
 450        &hfi1_vl2mtu_attr_1.attr,
 451        &hfi1_vl2mtu_attr_2.attr,
 452        &hfi1_vl2mtu_attr_3.attr,
 453        &hfi1_vl2mtu_attr_4.attr,
 454        &hfi1_vl2mtu_attr_5.attr,
 455        &hfi1_vl2mtu_attr_6.attr,
 456        &hfi1_vl2mtu_attr_7.attr,
 457        &hfi1_vl2mtu_attr_8.attr,
 458        &hfi1_vl2mtu_attr_9.attr,
 459        &hfi1_vl2mtu_attr_10.attr,
 460        &hfi1_vl2mtu_attr_11.attr,
 461        &hfi1_vl2mtu_attr_12.attr,
 462        &hfi1_vl2mtu_attr_13.attr,
 463        &hfi1_vl2mtu_attr_14.attr,
 464        &hfi1_vl2mtu_attr_15.attr,
 465        NULL
 466};
 467
 468static ssize_t vl2mtu_attr_show(struct kobject *kobj, struct attribute *attr,
 469                                char *buf)
 470{
 471        struct hfi1_vl2mtu_attr *vlattr =
 472                container_of(attr, struct hfi1_vl2mtu_attr, attr);
 473        struct hfi1_pportdata *ppd =
 474                container_of(kobj, struct hfi1_pportdata, vl2mtu_kobj);
 475        struct hfi1_devdata *dd = ppd->dd;
 476
 477        return sprintf(buf, "%u\n", dd->vld[vlattr->vl].mtu);
 478}
 479
 480static const struct sysfs_ops hfi1_vl2mtu_ops = {
 481        .show = vl2mtu_attr_show,
 482};
 483
 484static struct kobj_type hfi1_vl2mtu_ktype = {
 485        .release = port_release,
 486        .sysfs_ops = &hfi1_vl2mtu_ops,
 487        .default_attrs = vl2mtu_default_attributes
 488};
 489
 490/* end of per-port file structures and support code */
 491
 492/*
 493 * Start of per-unit (or driver, in some cases, but replicated
 494 * per unit) functions (these get a device *)
 495 */
 496static ssize_t show_rev(struct device *device, struct device_attribute *attr,
 497                        char *buf)
 498{
 499        struct hfi1_ibdev *dev =
 500                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 501
 502        return sprintf(buf, "%x\n", dd_from_dev(dev)->minrev);
 503}
 504
 505static ssize_t show_hfi(struct device *device, struct device_attribute *attr,
 506                        char *buf)
 507{
 508        struct hfi1_ibdev *dev =
 509                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 510        struct hfi1_devdata *dd = dd_from_dev(dev);
 511        int ret;
 512
 513        if (!dd->boardname)
 514                ret = -EINVAL;
 515        else
 516                ret = scnprintf(buf, PAGE_SIZE, "%s\n", dd->boardname);
 517        return ret;
 518}
 519
 520static ssize_t show_boardversion(struct device *device,
 521                                 struct device_attribute *attr, char *buf)
 522{
 523        struct hfi1_ibdev *dev =
 524                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 525        struct hfi1_devdata *dd = dd_from_dev(dev);
 526
 527        /* The string printed here is already newline-terminated. */
 528        return scnprintf(buf, PAGE_SIZE, "%s", dd->boardversion);
 529}
 530
 531static ssize_t show_nctxts(struct device *device,
 532                           struct device_attribute *attr, char *buf)
 533{
 534        struct hfi1_ibdev *dev =
 535                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 536        struct hfi1_devdata *dd = dd_from_dev(dev);
 537
 538        /*
 539         * Return the smaller of send and receive contexts.
 540         * Normally, user level applications would require both a send
 541         * and a receive context, so returning the smaller of the two counts
 542         * give a more accurate picture of total contexts available.
 543         */
 544        return scnprintf(buf, PAGE_SIZE, "%u\n",
 545                         min(dd->num_rcv_contexts - dd->first_user_ctxt,
 546                             (u32)dd->sc_sizes[SC_USER].count));
 547}
 548
 549static ssize_t show_nfreectxts(struct device *device,
 550                               struct device_attribute *attr, char *buf)
 551{
 552        struct hfi1_ibdev *dev =
 553                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 554        struct hfi1_devdata *dd = dd_from_dev(dev);
 555
 556        /* Return the number of free user ports (contexts) available. */
 557        return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts);
 558}
 559
 560static ssize_t show_serial(struct device *device,
 561                           struct device_attribute *attr, char *buf)
 562{
 563        struct hfi1_ibdev *dev =
 564                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 565        struct hfi1_devdata *dd = dd_from_dev(dev);
 566
 567        return scnprintf(buf, PAGE_SIZE, "%s", dd->serial);
 568}
 569
 570static ssize_t store_chip_reset(struct device *device,
 571                                struct device_attribute *attr, const char *buf,
 572                                size_t count)
 573{
 574        struct hfi1_ibdev *dev =
 575                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 576        struct hfi1_devdata *dd = dd_from_dev(dev);
 577        int ret;
 578
 579        if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) {
 580                ret = -EINVAL;
 581                goto bail;
 582        }
 583
 584        ret = hfi1_reset_device(dd->unit);
 585bail:
 586        return ret < 0 ? ret : count;
 587}
 588
 589/*
 590 * Convert the reported temperature from an integer (reported in
 591 * units of 0.25C) to a floating point number.
 592 */
 593#define temp2str(temp, buf, size, idx)                                  \
 594        scnprintf((buf) + (idx), (size) - (idx), "%u.%02u ",            \
 595                              ((temp) >> 2), ((temp) & 0x3) * 25)
 596
 597/*
 598 * Dump tempsense values, in decimal, to ease shell-scripts.
 599 */
 600static ssize_t show_tempsense(struct device *device,
 601                              struct device_attribute *attr, char *buf)
 602{
 603        struct hfi1_ibdev *dev =
 604                container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
 605        struct hfi1_devdata *dd = dd_from_dev(dev);
 606        struct hfi1_temp temp;
 607        int ret;
 608
 609        ret = hfi1_tempsense_rd(dd, &temp);
 610        if (!ret) {
 611                int idx = 0;
 612
 613                idx += temp2str(temp.curr, buf, PAGE_SIZE, idx);
 614                idx += temp2str(temp.lo_lim, buf, PAGE_SIZE, idx);
 615                idx += temp2str(temp.hi_lim, buf, PAGE_SIZE, idx);
 616                idx += temp2str(temp.crit_lim, buf, PAGE_SIZE, idx);
 617                idx += scnprintf(buf + idx, PAGE_SIZE - idx,
 618                                "%u %u %u\n", temp.triggers & 0x1,
 619                                temp.triggers & 0x2, temp.triggers & 0x4);
 620                ret = idx;
 621        }
 622        return ret;
 623}
 624
 625/*
 626 * end of per-unit (or driver, in some cases, but replicated
 627 * per unit) functions
 628 */
 629
 630/* start of per-unit file structures and support code */
 631static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
 632static DEVICE_ATTR(board_id, S_IRUGO, show_hfi, NULL);
 633static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL);
 634static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL);
 635static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
 636static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
 637static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL);
 638static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset);
 639
 640static struct device_attribute *hfi1_attributes[] = {
 641        &dev_attr_hw_rev,
 642        &dev_attr_board_id,
 643        &dev_attr_nctxts,
 644        &dev_attr_nfreectxts,
 645        &dev_attr_serial,
 646        &dev_attr_boardversion,
 647        &dev_attr_tempsense,
 648        &dev_attr_chip_reset,
 649};
 650
 651int hfi1_create_port_files(struct ib_device *ibdev, u8 port_num,
 652                           struct kobject *kobj)
 653{
 654        struct hfi1_pportdata *ppd;
 655        struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
 656        int ret;
 657
 658        if (!port_num || port_num > dd->num_pports) {
 659                dd_dev_err(dd,
 660                           "Skipping infiniband class with invalid port %u\n",
 661                           port_num);
 662                return -ENODEV;
 663        }
 664        ppd = &dd->pport[port_num - 1];
 665
 666        ret = kobject_init_and_add(&ppd->sc2vl_kobj, &hfi1_sc2vl_ktype, kobj,
 667                                   "sc2vl");
 668        if (ret) {
 669                dd_dev_err(dd,
 670                           "Skipping sc2vl sysfs info, (err %d) port %u\n",
 671                           ret, port_num);
 672                goto bail;
 673        }
 674        kobject_uevent(&ppd->sc2vl_kobj, KOBJ_ADD);
 675
 676        ret = kobject_init_and_add(&ppd->sl2sc_kobj, &hfi1_sl2sc_ktype, kobj,
 677                                   "sl2sc");
 678        if (ret) {
 679                dd_dev_err(dd,
 680                           "Skipping sl2sc sysfs info, (err %d) port %u\n",
 681                           ret, port_num);
 682                goto bail_sc2vl;
 683        }
 684        kobject_uevent(&ppd->sl2sc_kobj, KOBJ_ADD);
 685
 686        ret = kobject_init_and_add(&ppd->vl2mtu_kobj, &hfi1_vl2mtu_ktype, kobj,
 687                                   "vl2mtu");
 688        if (ret) {
 689                dd_dev_err(dd,
 690                           "Skipping vl2mtu sysfs info, (err %d) port %u\n",
 691                           ret, port_num);
 692                goto bail_sl2sc;
 693        }
 694        kobject_uevent(&ppd->vl2mtu_kobj, KOBJ_ADD);
 695
 696        ret = kobject_init_and_add(&ppd->pport_cc_kobj, &port_cc_ktype,
 697                                   kobj, "CCMgtA");
 698        if (ret) {
 699                dd_dev_err(dd,
 700                           "Skipping Congestion Control sysfs info, (err %d) port %u\n",
 701                           ret, port_num);
 702                goto bail_vl2mtu;
 703        }
 704
 705        kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD);
 706
 707        ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, &cc_setting_bin_attr);
 708        if (ret) {
 709                dd_dev_err(dd,
 710                           "Skipping Congestion Control setting sysfs info, (err %d) port %u\n",
 711                           ret, port_num);
 712                goto bail_cc;
 713        }
 714
 715        ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, &cc_table_bin_attr);
 716        if (ret) {
 717                dd_dev_err(dd,
 718                           "Skipping Congestion Control table sysfs info, (err %d) port %u\n",
 719                           ret, port_num);
 720                goto bail_cc_entry_bin;
 721        }
 722
 723        dd_dev_info(dd,
 724                    "Congestion Control Agent enabled for port %d\n",
 725                    port_num);
 726
 727        return 0;
 728
 729bail_cc_entry_bin:
 730        sysfs_remove_bin_file(&ppd->pport_cc_kobj,
 731                              &cc_setting_bin_attr);
 732bail_cc:
 733        kobject_put(&ppd->pport_cc_kobj);
 734bail_vl2mtu:
 735        kobject_put(&ppd->vl2mtu_kobj);
 736bail_sl2sc:
 737        kobject_put(&ppd->sl2sc_kobj);
 738bail_sc2vl:
 739        kobject_put(&ppd->sc2vl_kobj);
 740bail:
 741        return ret;
 742}
 743
 744struct sde_attribute {
 745        struct attribute attr;
 746        ssize_t (*show)(struct sdma_engine *sde, char *buf);
 747        ssize_t (*store)(struct sdma_engine *sde, const char *buf, size_t cnt);
 748};
 749
 750static ssize_t sde_show(struct kobject *kobj, struct attribute *attr, char *buf)
 751{
 752        struct sde_attribute *sde_attr =
 753                container_of(attr, struct sde_attribute, attr);
 754        struct sdma_engine *sde =
 755                container_of(kobj, struct sdma_engine, kobj);
 756
 757        if (!sde_attr->show)
 758                return -EINVAL;
 759
 760        return sde_attr->show(sde, buf);
 761}
 762
 763static ssize_t sde_store(struct kobject *kobj, struct attribute *attr,
 764                         const char *buf, size_t count)
 765{
 766        struct sde_attribute *sde_attr =
 767                container_of(attr, struct sde_attribute, attr);
 768        struct sdma_engine *sde =
 769                container_of(kobj, struct sdma_engine, kobj);
 770
 771        if (!capable(CAP_SYS_ADMIN))
 772                return -EPERM;
 773
 774        if (!sde_attr->store)
 775                return -EINVAL;
 776
 777        return sde_attr->store(sde, buf, count);
 778}
 779
 780static const struct sysfs_ops sde_sysfs_ops = {
 781        .show = sde_show,
 782        .store = sde_store,
 783};
 784
 785static struct kobj_type sde_ktype = {
 786        .sysfs_ops = &sde_sysfs_ops,
 787};
 788
 789#define SDE_ATTR(_name, _mode, _show, _store) \
 790        struct sde_attribute sde_attr_##_name = \
 791                __ATTR(_name, _mode, _show, _store)
 792
 793static ssize_t sde_show_cpu_to_sde_map(struct sdma_engine *sde, char *buf)
 794{
 795        return sdma_get_cpu_to_sde_map(sde, buf);
 796}
 797
 798static ssize_t sde_store_cpu_to_sde_map(struct sdma_engine *sde,
 799                                        const char *buf, size_t count)
 800{
 801        return sdma_set_cpu_to_sde_map(sde, buf, count);
 802}
 803
 804static ssize_t sde_show_vl(struct sdma_engine *sde, char *buf)
 805{
 806        int vl;
 807
 808        vl = sdma_engine_get_vl(sde);
 809        if (vl < 0)
 810                return vl;
 811
 812        return snprintf(buf, PAGE_SIZE, "%d\n", vl);
 813}
 814
 815static SDE_ATTR(cpu_list, S_IWUSR | S_IRUGO,
 816                sde_show_cpu_to_sde_map,
 817                sde_store_cpu_to_sde_map);
 818static SDE_ATTR(vl, S_IRUGO, sde_show_vl, NULL);
 819
 820static struct sde_attribute *sde_attribs[] = {
 821        &sde_attr_cpu_list,
 822        &sde_attr_vl
 823};
 824
 825/*
 826 * Register and create our files in /sys/class/infiniband.
 827 */
 828int hfi1_verbs_register_sysfs(struct hfi1_devdata *dd)
 829{
 830        struct ib_device *dev = &dd->verbs_dev.rdi.ibdev;
 831        struct device *class_dev = &dev->dev;
 832        int i, j, ret;
 833
 834        for (i = 0; i < ARRAY_SIZE(hfi1_attributes); ++i) {
 835                ret = device_create_file(&dev->dev, hfi1_attributes[i]);
 836                if (ret)
 837                        goto bail;
 838        }
 839
 840        for (i = 0; i < dd->num_sdma; i++) {
 841                ret = kobject_init_and_add(&dd->per_sdma[i].kobj,
 842                                           &sde_ktype, &class_dev->kobj,
 843                                           "sdma%d", i);
 844                if (ret)
 845                        goto bail;
 846
 847                for (j = 0; j < ARRAY_SIZE(sde_attribs); j++) {
 848                        ret = sysfs_create_file(&dd->per_sdma[i].kobj,
 849                                                &sde_attribs[j]->attr);
 850                        if (ret)
 851                                goto bail;
 852                }
 853        }
 854
 855        return 0;
 856bail:
 857        for (i = 0; i < ARRAY_SIZE(hfi1_attributes); ++i)
 858                device_remove_file(&dev->dev, hfi1_attributes[i]);
 859
 860        for (i = 0; i < dd->num_sdma; i++)
 861                kobject_del(&dd->per_sdma[i].kobj);
 862
 863        return ret;
 864}
 865
 866/*
 867 * Unregister and remove our files in /sys/class/infiniband.
 868 */
 869void hfi1_verbs_unregister_sysfs(struct hfi1_devdata *dd)
 870{
 871        struct hfi1_pportdata *ppd;
 872        int i;
 873
 874        for (i = 0; i < dd->num_pports; i++) {
 875                ppd = &dd->pport[i];
 876
 877                sysfs_remove_bin_file(&ppd->pport_cc_kobj,
 878                                      &cc_setting_bin_attr);
 879                sysfs_remove_bin_file(&ppd->pport_cc_kobj,
 880                                      &cc_table_bin_attr);
 881                kobject_put(&ppd->pport_cc_kobj);
 882                kobject_put(&ppd->vl2mtu_kobj);
 883                kobject_put(&ppd->sl2sc_kobj);
 884                kobject_put(&ppd->sc2vl_kobj);
 885        }
 886}
 887