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