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#include <rdma/ib_sysfs.h>
  49
  50#include "hfi.h"
  51#include "mad.h"
  52#include "trace.h"
  53
  54static struct hfi1_pportdata *hfi1_get_pportdata_kobj(struct kobject *kobj)
  55{
  56        u32 port_num;
  57        struct ib_device *ibdev = ib_port_sysfs_get_ibdev_kobj(kobj, &port_num);
  58        struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
  59
  60        return &dd->pport[port_num - 1];
  61}
  62
  63/*
  64 * Start of per-port congestion control structures and support code
  65 */
  66
  67/*
  68 * Congestion control table size followed by table entries
  69 */
  70static ssize_t cc_table_bin_read(struct file *filp, struct kobject *kobj,
  71                                 struct bin_attribute *bin_attr, char *buf,
  72                                 loff_t pos, size_t count)
  73{
  74        int ret;
  75        struct hfi1_pportdata *ppd = hfi1_get_pportdata_kobj(kobj);
  76        struct cc_state *cc_state;
  77
  78        ret = ppd->total_cct_entry * sizeof(struct ib_cc_table_entry_shadow)
  79                 + sizeof(__be16);
  80
  81        if (pos > ret)
  82                return -EINVAL;
  83
  84        if (count > ret - pos)
  85                count = ret - pos;
  86
  87        if (!count)
  88                return count;
  89
  90        rcu_read_lock();
  91        cc_state = get_cc_state(ppd);
  92        if (!cc_state) {
  93                rcu_read_unlock();
  94                return -EINVAL;
  95        }
  96        memcpy(buf, (void *)&cc_state->cct + pos, count);
  97        rcu_read_unlock();
  98
  99        return count;
 100}
 101static BIN_ATTR_RO(cc_table_bin, PAGE_SIZE);
 102
 103/*
 104 * Congestion settings: port control, control map and an array of 16
 105 * entries for the congestion entries - increase, timer, event log
 106 * trigger threshold and the minimum injection rate delay.
 107 */
 108static ssize_t cc_setting_bin_read(struct file *filp, struct kobject *kobj,
 109                                   struct bin_attribute *bin_attr,
 110                                   char *buf, loff_t pos, size_t count)
 111{
 112        struct hfi1_pportdata *ppd = hfi1_get_pportdata_kobj(kobj);
 113        int ret;
 114        struct cc_state *cc_state;
 115
 116        ret = sizeof(struct opa_congestion_setting_attr_shadow);
 117
 118        if (pos > ret)
 119                return -EINVAL;
 120        if (count > ret - pos)
 121                count = ret - pos;
 122
 123        if (!count)
 124                return count;
 125
 126        rcu_read_lock();
 127        cc_state = get_cc_state(ppd);
 128        if (!cc_state) {
 129                rcu_read_unlock();
 130                return -EINVAL;
 131        }
 132        memcpy(buf, (void *)&cc_state->cong_setting + pos, count);
 133        rcu_read_unlock();
 134
 135        return count;
 136}
 137static BIN_ATTR_RO(cc_setting_bin, PAGE_SIZE);
 138
 139static struct bin_attribute *port_cc_bin_attributes[] = {
 140        &bin_attr_cc_setting_bin,
 141        &bin_attr_cc_table_bin,
 142        NULL
 143};
 144
 145static ssize_t cc_prescan_show(struct ib_device *ibdev, u32 port_num,
 146                               struct ib_port_attribute *attr, char *buf)
 147{
 148        struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
 149        struct hfi1_pportdata *ppd = &dd->pport[port_num - 1];
 150
 151        return sysfs_emit(buf, "%s\n", ppd->cc_prescan ? "on" : "off");
 152}
 153
 154static ssize_t cc_prescan_store(struct ib_device *ibdev, u32 port_num,
 155                                struct ib_port_attribute *attr, const char *buf,
 156                                size_t count)
 157{
 158        struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
 159        struct hfi1_pportdata *ppd = &dd->pport[port_num - 1];
 160
 161        if (!memcmp(buf, "on", 2))
 162                ppd->cc_prescan = true;
 163        else if (!memcmp(buf, "off", 3))
 164                ppd->cc_prescan = false;
 165
 166        return count;
 167}
 168static IB_PORT_ATTR_ADMIN_RW(cc_prescan);
 169
 170static struct attribute *port_cc_attributes[] = {
 171        &ib_port_attr_cc_prescan.attr,
 172        NULL
 173};
 174
 175static const struct attribute_group port_cc_group = {
 176        .name = "CCMgtA",
 177        .attrs = port_cc_attributes,
 178        .bin_attrs = port_cc_bin_attributes,
 179};
 180
 181/* Start sc2vl */
 182struct hfi1_sc2vl_attr {
 183        struct ib_port_attribute attr;
 184        int sc;
 185};
 186
 187static ssize_t sc2vl_attr_show(struct ib_device *ibdev, u32 port_num,
 188                               struct ib_port_attribute *attr, char *buf)
 189{
 190        struct hfi1_sc2vl_attr *sattr =
 191                container_of(attr, struct hfi1_sc2vl_attr, attr);
 192        struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
 193
 194        return sysfs_emit(buf, "%u\n", *((u8 *)dd->sc2vl + sattr->sc));
 195}
 196
 197#define HFI1_SC2VL_ATTR(N)                                                     \
 198        static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = {                  \
 199                .attr = __ATTR(N, 0444, sc2vl_attr_show, NULL),                \
 200                .sc = N,                                                       \
 201        }
 202
 203HFI1_SC2VL_ATTR(0);
 204HFI1_SC2VL_ATTR(1);
 205HFI1_SC2VL_ATTR(2);
 206HFI1_SC2VL_ATTR(3);
 207HFI1_SC2VL_ATTR(4);
 208HFI1_SC2VL_ATTR(5);
 209HFI1_SC2VL_ATTR(6);
 210HFI1_SC2VL_ATTR(7);
 211HFI1_SC2VL_ATTR(8);
 212HFI1_SC2VL_ATTR(9);
 213HFI1_SC2VL_ATTR(10);
 214HFI1_SC2VL_ATTR(11);
 215HFI1_SC2VL_ATTR(12);
 216HFI1_SC2VL_ATTR(13);
 217HFI1_SC2VL_ATTR(14);
 218HFI1_SC2VL_ATTR(15);
 219HFI1_SC2VL_ATTR(16);
 220HFI1_SC2VL_ATTR(17);
 221HFI1_SC2VL_ATTR(18);
 222HFI1_SC2VL_ATTR(19);
 223HFI1_SC2VL_ATTR(20);
 224HFI1_SC2VL_ATTR(21);
 225HFI1_SC2VL_ATTR(22);
 226HFI1_SC2VL_ATTR(23);
 227HFI1_SC2VL_ATTR(24);
 228HFI1_SC2VL_ATTR(25);
 229HFI1_SC2VL_ATTR(26);
 230HFI1_SC2VL_ATTR(27);
 231HFI1_SC2VL_ATTR(28);
 232HFI1_SC2VL_ATTR(29);
 233HFI1_SC2VL_ATTR(30);
 234HFI1_SC2VL_ATTR(31);
 235
 236static struct attribute *port_sc2vl_attributes[] = {
 237        &hfi1_sc2vl_attr_0.attr.attr,
 238        &hfi1_sc2vl_attr_1.attr.attr,
 239        &hfi1_sc2vl_attr_2.attr.attr,
 240        &hfi1_sc2vl_attr_3.attr.attr,
 241        &hfi1_sc2vl_attr_4.attr.attr,
 242        &hfi1_sc2vl_attr_5.attr.attr,
 243        &hfi1_sc2vl_attr_6.attr.attr,
 244        &hfi1_sc2vl_attr_7.attr.attr,
 245        &hfi1_sc2vl_attr_8.attr.attr,
 246        &hfi1_sc2vl_attr_9.attr.attr,
 247        &hfi1_sc2vl_attr_10.attr.attr,
 248        &hfi1_sc2vl_attr_11.attr.attr,
 249        &hfi1_sc2vl_attr_12.attr.attr,
 250        &hfi1_sc2vl_attr_13.attr.attr,
 251        &hfi1_sc2vl_attr_14.attr.attr,
 252        &hfi1_sc2vl_attr_15.attr.attr,
 253        &hfi1_sc2vl_attr_16.attr.attr,
 254        &hfi1_sc2vl_attr_17.attr.attr,
 255        &hfi1_sc2vl_attr_18.attr.attr,
 256        &hfi1_sc2vl_attr_19.attr.attr,
 257        &hfi1_sc2vl_attr_20.attr.attr,
 258        &hfi1_sc2vl_attr_21.attr.attr,
 259        &hfi1_sc2vl_attr_22.attr.attr,
 260        &hfi1_sc2vl_attr_23.attr.attr,
 261        &hfi1_sc2vl_attr_24.attr.attr,
 262        &hfi1_sc2vl_attr_25.attr.attr,
 263        &hfi1_sc2vl_attr_26.attr.attr,
 264        &hfi1_sc2vl_attr_27.attr.attr,
 265        &hfi1_sc2vl_attr_28.attr.attr,
 266        &hfi1_sc2vl_attr_29.attr.attr,
 267        &hfi1_sc2vl_attr_30.attr.attr,
 268        &hfi1_sc2vl_attr_31.attr.attr,
 269        NULL
 270};
 271
 272static const struct attribute_group port_sc2vl_group = {
 273        .name = "sc2vl",
 274        .attrs = port_sc2vl_attributes,
 275};
 276/* End sc2vl */
 277
 278/* Start sl2sc */
 279struct hfi1_sl2sc_attr {
 280        struct ib_port_attribute attr;
 281        int sl;
 282};
 283
 284static ssize_t sl2sc_attr_show(struct ib_device *ibdev, u32 port_num,
 285                               struct ib_port_attribute *attr, char *buf)
 286{
 287        struct hfi1_sl2sc_attr *sattr =
 288                container_of(attr, struct hfi1_sl2sc_attr, attr);
 289        struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
 290        struct hfi1_ibport *ibp = &dd->pport[port_num - 1].ibport_data;
 291
 292        return sysfs_emit(buf, "%u\n", ibp->sl_to_sc[sattr->sl]);
 293}
 294
 295#define HFI1_SL2SC_ATTR(N)                                                     \
 296        static struct hfi1_sl2sc_attr hfi1_sl2sc_attr_##N = {                  \
 297                .attr = __ATTR(N, 0444, sl2sc_attr_show, NULL), .sl = N        \
 298        }
 299
 300HFI1_SL2SC_ATTR(0);
 301HFI1_SL2SC_ATTR(1);
 302HFI1_SL2SC_ATTR(2);
 303HFI1_SL2SC_ATTR(3);
 304HFI1_SL2SC_ATTR(4);
 305HFI1_SL2SC_ATTR(5);
 306HFI1_SL2SC_ATTR(6);
 307HFI1_SL2SC_ATTR(7);
 308HFI1_SL2SC_ATTR(8);
 309HFI1_SL2SC_ATTR(9);
 310HFI1_SL2SC_ATTR(10);
 311HFI1_SL2SC_ATTR(11);
 312HFI1_SL2SC_ATTR(12);
 313HFI1_SL2SC_ATTR(13);
 314HFI1_SL2SC_ATTR(14);
 315HFI1_SL2SC_ATTR(15);
 316HFI1_SL2SC_ATTR(16);
 317HFI1_SL2SC_ATTR(17);
 318HFI1_SL2SC_ATTR(18);
 319HFI1_SL2SC_ATTR(19);
 320HFI1_SL2SC_ATTR(20);
 321HFI1_SL2SC_ATTR(21);
 322HFI1_SL2SC_ATTR(22);
 323HFI1_SL2SC_ATTR(23);
 324HFI1_SL2SC_ATTR(24);
 325HFI1_SL2SC_ATTR(25);
 326HFI1_SL2SC_ATTR(26);
 327HFI1_SL2SC_ATTR(27);
 328HFI1_SL2SC_ATTR(28);
 329HFI1_SL2SC_ATTR(29);
 330HFI1_SL2SC_ATTR(30);
 331HFI1_SL2SC_ATTR(31);
 332
 333static struct attribute *port_sl2sc_attributes[] = {
 334        &hfi1_sl2sc_attr_0.attr.attr,
 335        &hfi1_sl2sc_attr_1.attr.attr,
 336        &hfi1_sl2sc_attr_2.attr.attr,
 337        &hfi1_sl2sc_attr_3.attr.attr,
 338        &hfi1_sl2sc_attr_4.attr.attr,
 339        &hfi1_sl2sc_attr_5.attr.attr,
 340        &hfi1_sl2sc_attr_6.attr.attr,
 341        &hfi1_sl2sc_attr_7.attr.attr,
 342        &hfi1_sl2sc_attr_8.attr.attr,
 343        &hfi1_sl2sc_attr_9.attr.attr,
 344        &hfi1_sl2sc_attr_10.attr.attr,
 345        &hfi1_sl2sc_attr_11.attr.attr,
 346        &hfi1_sl2sc_attr_12.attr.attr,
 347        &hfi1_sl2sc_attr_13.attr.attr,
 348        &hfi1_sl2sc_attr_14.attr.attr,
 349        &hfi1_sl2sc_attr_15.attr.attr,
 350        &hfi1_sl2sc_attr_16.attr.attr,
 351        &hfi1_sl2sc_attr_17.attr.attr,
 352        &hfi1_sl2sc_attr_18.attr.attr,
 353        &hfi1_sl2sc_attr_19.attr.attr,
 354        &hfi1_sl2sc_attr_20.attr.attr,
 355        &hfi1_sl2sc_attr_21.attr.attr,
 356        &hfi1_sl2sc_attr_22.attr.attr,
 357        &hfi1_sl2sc_attr_23.attr.attr,
 358        &hfi1_sl2sc_attr_24.attr.attr,
 359        &hfi1_sl2sc_attr_25.attr.attr,
 360        &hfi1_sl2sc_attr_26.attr.attr,
 361        &hfi1_sl2sc_attr_27.attr.attr,
 362        &hfi1_sl2sc_attr_28.attr.attr,
 363        &hfi1_sl2sc_attr_29.attr.attr,
 364        &hfi1_sl2sc_attr_30.attr.attr,
 365        &hfi1_sl2sc_attr_31.attr.attr,
 366        NULL
 367};
 368
 369static const struct attribute_group port_sl2sc_group = {
 370        .name = "sl2sc",
 371        .attrs = port_sl2sc_attributes,
 372};
 373
 374/* End sl2sc */
 375
 376/* Start vl2mtu */
 377
 378struct hfi1_vl2mtu_attr {
 379        struct ib_port_attribute attr;
 380        int vl;
 381};
 382
 383static ssize_t vl2mtu_attr_show(struct ib_device *ibdev, u32 port_num,
 384                                struct ib_port_attribute *attr, char *buf)
 385{
 386        struct hfi1_vl2mtu_attr *vlattr =
 387                container_of(attr, struct hfi1_vl2mtu_attr, attr);
 388        struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
 389
 390        return sysfs_emit(buf, "%u\n", dd->vld[vlattr->vl].mtu);
 391}
 392
 393#define HFI1_VL2MTU_ATTR(N)                                                    \
 394        static struct hfi1_vl2mtu_attr hfi1_vl2mtu_attr_##N = {                \
 395                .attr = __ATTR(N, 0444, vl2mtu_attr_show, NULL),               \
 396                .vl = N,                                                       \
 397        }
 398
 399HFI1_VL2MTU_ATTR(0);
 400HFI1_VL2MTU_ATTR(1);
 401HFI1_VL2MTU_ATTR(2);
 402HFI1_VL2MTU_ATTR(3);
 403HFI1_VL2MTU_ATTR(4);
 404HFI1_VL2MTU_ATTR(5);
 405HFI1_VL2MTU_ATTR(6);
 406HFI1_VL2MTU_ATTR(7);
 407HFI1_VL2MTU_ATTR(8);
 408HFI1_VL2MTU_ATTR(9);
 409HFI1_VL2MTU_ATTR(10);
 410HFI1_VL2MTU_ATTR(11);
 411HFI1_VL2MTU_ATTR(12);
 412HFI1_VL2MTU_ATTR(13);
 413HFI1_VL2MTU_ATTR(14);
 414HFI1_VL2MTU_ATTR(15);
 415
 416static struct attribute *port_vl2mtu_attributes[] = {
 417        &hfi1_vl2mtu_attr_0.attr.attr,
 418        &hfi1_vl2mtu_attr_1.attr.attr,
 419        &hfi1_vl2mtu_attr_2.attr.attr,
 420        &hfi1_vl2mtu_attr_3.attr.attr,
 421        &hfi1_vl2mtu_attr_4.attr.attr,
 422        &hfi1_vl2mtu_attr_5.attr.attr,
 423        &hfi1_vl2mtu_attr_6.attr.attr,
 424        &hfi1_vl2mtu_attr_7.attr.attr,
 425        &hfi1_vl2mtu_attr_8.attr.attr,
 426        &hfi1_vl2mtu_attr_9.attr.attr,
 427        &hfi1_vl2mtu_attr_10.attr.attr,
 428        &hfi1_vl2mtu_attr_11.attr.attr,
 429        &hfi1_vl2mtu_attr_12.attr.attr,
 430        &hfi1_vl2mtu_attr_13.attr.attr,
 431        &hfi1_vl2mtu_attr_14.attr.attr,
 432        &hfi1_vl2mtu_attr_15.attr.attr,
 433        NULL
 434};
 435
 436static const struct attribute_group port_vl2mtu_group = {
 437        .name = "vl2mtu",
 438        .attrs = port_vl2mtu_attributes,
 439};
 440
 441/* end of per-port file structures and support code */
 442
 443/*
 444 * Start of per-unit (or driver, in some cases, but replicated
 445 * per unit) functions (these get a device *)
 446 */
 447static ssize_t hw_rev_show(struct device *device, struct device_attribute *attr,
 448                           char *buf)
 449{
 450        struct hfi1_ibdev *dev =
 451                rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
 452
 453        return sysfs_emit(buf, "%x\n", dd_from_dev(dev)->minrev);
 454}
 455static DEVICE_ATTR_RO(hw_rev);
 456
 457static ssize_t board_id_show(struct device *device,
 458                             struct device_attribute *attr, char *buf)
 459{
 460        struct hfi1_ibdev *dev =
 461                rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
 462        struct hfi1_devdata *dd = dd_from_dev(dev);
 463
 464        if (!dd->boardname)
 465                return -EINVAL;
 466
 467        return sysfs_emit(buf, "%s\n", dd->boardname);
 468}
 469static DEVICE_ATTR_RO(board_id);
 470
 471static ssize_t boardversion_show(struct device *device,
 472                                 struct device_attribute *attr, char *buf)
 473{
 474        struct hfi1_ibdev *dev =
 475                rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
 476        struct hfi1_devdata *dd = dd_from_dev(dev);
 477
 478        /* The string printed here is already newline-terminated. */
 479        return sysfs_emit(buf, "%s", dd->boardversion);
 480}
 481static DEVICE_ATTR_RO(boardversion);
 482
 483static ssize_t nctxts_show(struct device *device,
 484                           struct device_attribute *attr, char *buf)
 485{
 486        struct hfi1_ibdev *dev =
 487                rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
 488        struct hfi1_devdata *dd = dd_from_dev(dev);
 489
 490        /*
 491         * Return the smaller of send and receive contexts.
 492         * Normally, user level applications would require both a send
 493         * and a receive context, so returning the smaller of the two counts
 494         * give a more accurate picture of total contexts available.
 495         */
 496        return sysfs_emit(buf, "%u\n",
 497                          min(dd->num_user_contexts,
 498                              (u32)dd->sc_sizes[SC_USER].count));
 499}
 500static DEVICE_ATTR_RO(nctxts);
 501
 502static ssize_t nfreectxts_show(struct device *device,
 503                               struct device_attribute *attr, char *buf)
 504{
 505        struct hfi1_ibdev *dev =
 506                rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
 507        struct hfi1_devdata *dd = dd_from_dev(dev);
 508
 509        /* Return the number of free user ports (contexts) available. */
 510        return sysfs_emit(buf, "%u\n", dd->freectxts);
 511}
 512static DEVICE_ATTR_RO(nfreectxts);
 513
 514static ssize_t serial_show(struct device *device,
 515                           struct device_attribute *attr, char *buf)
 516{
 517        struct hfi1_ibdev *dev =
 518                rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
 519        struct hfi1_devdata *dd = dd_from_dev(dev);
 520
 521        /* dd->serial is already newline terminated in chip.c */
 522        return sysfs_emit(buf, "%s", dd->serial);
 523}
 524static DEVICE_ATTR_RO(serial);
 525
 526static ssize_t chip_reset_store(struct device *device,
 527                                struct device_attribute *attr, const char *buf,
 528                                size_t count)
 529{
 530        struct hfi1_ibdev *dev =
 531                rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
 532        struct hfi1_devdata *dd = dd_from_dev(dev);
 533        int ret;
 534
 535        if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) {
 536                ret = -EINVAL;
 537                goto bail;
 538        }
 539
 540        ret = hfi1_reset_device(dd->unit);
 541bail:
 542        return ret < 0 ? ret : count;
 543}
 544static DEVICE_ATTR_WO(chip_reset);
 545
 546/*
 547 * Convert the reported temperature from an integer (reported in
 548 * units of 0.25C) to a floating point number.
 549 */
 550#define temp_d(t) ((t) >> 2)
 551#define temp_f(t) (((t)&0x3) * 25u)
 552
 553/*
 554 * Dump tempsense values, in decimal, to ease shell-scripts.
 555 */
 556static ssize_t tempsense_show(struct device *device,
 557                              struct device_attribute *attr, char *buf)
 558{
 559        struct hfi1_ibdev *dev =
 560                rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
 561        struct hfi1_devdata *dd = dd_from_dev(dev);
 562        struct hfi1_temp temp;
 563        int ret;
 564
 565        ret = hfi1_tempsense_rd(dd, &temp);
 566        if (ret)
 567                return ret;
 568
 569        return sysfs_emit(buf, "%u.%02u %u.%02u %u.%02u %u.%02u %u %u %u\n",
 570                          temp_d(temp.curr), temp_f(temp.curr),
 571                          temp_d(temp.lo_lim), temp_f(temp.lo_lim),
 572                          temp_d(temp.hi_lim), temp_f(temp.hi_lim),
 573                          temp_d(temp.crit_lim), temp_f(temp.crit_lim),
 574                          temp.triggers & 0x1,
 575                          temp.triggers & 0x2,
 576                          temp.triggers & 0x4);
 577}
 578static DEVICE_ATTR_RO(tempsense);
 579
 580/*
 581 * end of per-unit (or driver, in some cases, but replicated
 582 * per unit) functions
 583 */
 584
 585/* start of per-unit file structures and support code */
 586static struct attribute *hfi1_attributes[] = {
 587        &dev_attr_hw_rev.attr,
 588        &dev_attr_board_id.attr,
 589        &dev_attr_nctxts.attr,
 590        &dev_attr_nfreectxts.attr,
 591        &dev_attr_serial.attr,
 592        &dev_attr_boardversion.attr,
 593        &dev_attr_tempsense.attr,
 594        &dev_attr_chip_reset.attr,
 595        NULL,
 596};
 597
 598const struct attribute_group ib_hfi1_attr_group = {
 599        .attrs = hfi1_attributes,
 600};
 601
 602const struct attribute_group *hfi1_attr_port_groups[] = {
 603        &port_cc_group,
 604        &port_sc2vl_group,
 605        &port_sl2sc_group,
 606        &port_vl2mtu_group,
 607        NULL,
 608};
 609
 610struct sde_attribute {
 611        struct attribute attr;
 612        ssize_t (*show)(struct sdma_engine *sde, char *buf);
 613        ssize_t (*store)(struct sdma_engine *sde, const char *buf, size_t cnt);
 614};
 615
 616static ssize_t sde_show(struct kobject *kobj, struct attribute *attr, char *buf)
 617{
 618        struct sde_attribute *sde_attr =
 619                container_of(attr, struct sde_attribute, attr);
 620        struct sdma_engine *sde =
 621                container_of(kobj, struct sdma_engine, kobj);
 622
 623        if (!sde_attr->show)
 624                return -EINVAL;
 625
 626        return sde_attr->show(sde, buf);
 627}
 628
 629static ssize_t sde_store(struct kobject *kobj, struct attribute *attr,
 630                         const char *buf, size_t count)
 631{
 632        struct sde_attribute *sde_attr =
 633                container_of(attr, struct sde_attribute, attr);
 634        struct sdma_engine *sde =
 635                container_of(kobj, struct sdma_engine, kobj);
 636
 637        if (!capable(CAP_SYS_ADMIN))
 638                return -EPERM;
 639
 640        if (!sde_attr->store)
 641                return -EINVAL;
 642
 643        return sde_attr->store(sde, buf, count);
 644}
 645
 646static const struct sysfs_ops sde_sysfs_ops = {
 647        .show = sde_show,
 648        .store = sde_store,
 649};
 650
 651static struct kobj_type sde_ktype = {
 652        .sysfs_ops = &sde_sysfs_ops,
 653};
 654
 655#define SDE_ATTR(_name, _mode, _show, _store) \
 656        struct sde_attribute sde_attr_##_name = \
 657                __ATTR(_name, _mode, _show, _store)
 658
 659static ssize_t sde_show_cpu_to_sde_map(struct sdma_engine *sde, char *buf)
 660{
 661        return sdma_get_cpu_to_sde_map(sde, buf);
 662}
 663
 664static ssize_t sde_store_cpu_to_sde_map(struct sdma_engine *sde,
 665                                        const char *buf, size_t count)
 666{
 667        return sdma_set_cpu_to_sde_map(sde, buf, count);
 668}
 669
 670static ssize_t sde_show_vl(struct sdma_engine *sde, char *buf)
 671{
 672        int vl;
 673
 674        vl = sdma_engine_get_vl(sde);
 675        if (vl < 0)
 676                return vl;
 677
 678        return sysfs_emit(buf, "%d\n", vl);
 679}
 680
 681static SDE_ATTR(cpu_list, S_IWUSR | S_IRUGO,
 682                sde_show_cpu_to_sde_map,
 683                sde_store_cpu_to_sde_map);
 684static SDE_ATTR(vl, S_IRUGO, sde_show_vl, NULL);
 685
 686static struct sde_attribute *sde_attribs[] = {
 687        &sde_attr_cpu_list,
 688        &sde_attr_vl
 689};
 690
 691/*
 692 * Register and create our files in /sys/class/infiniband.
 693 */
 694int hfi1_verbs_register_sysfs(struct hfi1_devdata *dd)
 695{
 696        struct ib_device *dev = &dd->verbs_dev.rdi.ibdev;
 697        struct device *class_dev = &dev->dev;
 698        int i, j, ret;
 699
 700        for (i = 0; i < dd->num_sdma; i++) {
 701                ret = kobject_init_and_add(&dd->per_sdma[i].kobj,
 702                                           &sde_ktype, &class_dev->kobj,
 703                                           "sdma%d", i);
 704                if (ret)
 705                        goto bail;
 706
 707                for (j = 0; j < ARRAY_SIZE(sde_attribs); j++) {
 708                        ret = sysfs_create_file(&dd->per_sdma[i].kobj,
 709                                                &sde_attribs[j]->attr);
 710                        if (ret)
 711                                goto bail;
 712                }
 713        }
 714
 715        return 0;
 716bail:
 717        /*
 718         * The function kobject_put() will call kobject_del() if the kobject
 719         * has been added successfully. The sysfs files created under the
 720         * kobject directory will also be removed during the process.
 721         */
 722        for (; i >= 0; i--)
 723                kobject_put(&dd->per_sdma[i].kobj);
 724
 725        return ret;
 726}
 727
 728/*
 729 * Unregister and remove our files in /sys/class/infiniband.
 730 */
 731void hfi1_verbs_unregister_sysfs(struct hfi1_devdata *dd)
 732{
 733        int i;
 734
 735        /* Unwind operations in hfi1_verbs_register_sysfs() */
 736        for (i = 0; i < dd->num_sdma; i++)
 737                kobject_put(&dd->per_sdma[i].kobj);
 738}
 739