Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
0002 /*
0003  * Copyright(c) 2015-2017 Intel Corporation.
0004  */
0005 
0006 #include <linux/ctype.h>
0007 #include <rdma/ib_sysfs.h>
0008 
0009 #include "hfi.h"
0010 #include "mad.h"
0011 #include "trace.h"
0012 
0013 static struct hfi1_pportdata *hfi1_get_pportdata_kobj(struct kobject *kobj)
0014 {
0015     u32 port_num;
0016     struct ib_device *ibdev = ib_port_sysfs_get_ibdev_kobj(kobj, &port_num);
0017     struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
0018 
0019     return &dd->pport[port_num - 1];
0020 }
0021 
0022 /*
0023  * Start of per-port congestion control structures and support code
0024  */
0025 
0026 /*
0027  * Congestion control table size followed by table entries
0028  */
0029 static ssize_t cc_table_bin_read(struct file *filp, struct kobject *kobj,
0030                  struct bin_attribute *bin_attr, char *buf,
0031                  loff_t pos, size_t count)
0032 {
0033     int ret;
0034     struct hfi1_pportdata *ppd = hfi1_get_pportdata_kobj(kobj);
0035     struct cc_state *cc_state;
0036 
0037     ret = ppd->total_cct_entry * sizeof(struct ib_cc_table_entry_shadow)
0038          + sizeof(__be16);
0039 
0040     if (pos > ret)
0041         return -EINVAL;
0042 
0043     if (count > ret - pos)
0044         count = ret - pos;
0045 
0046     if (!count)
0047         return count;
0048 
0049     rcu_read_lock();
0050     cc_state = get_cc_state(ppd);
0051     if (!cc_state) {
0052         rcu_read_unlock();
0053         return -EINVAL;
0054     }
0055     memcpy(buf, (void *)&cc_state->cct + pos, count);
0056     rcu_read_unlock();
0057 
0058     return count;
0059 }
0060 static BIN_ATTR_RO(cc_table_bin, PAGE_SIZE);
0061 
0062 /*
0063  * Congestion settings: port control, control map and an array of 16
0064  * entries for the congestion entries - increase, timer, event log
0065  * trigger threshold and the minimum injection rate delay.
0066  */
0067 static ssize_t cc_setting_bin_read(struct file *filp, struct kobject *kobj,
0068                    struct bin_attribute *bin_attr,
0069                    char *buf, loff_t pos, size_t count)
0070 {
0071     struct hfi1_pportdata *ppd = hfi1_get_pportdata_kobj(kobj);
0072     int ret;
0073     struct cc_state *cc_state;
0074 
0075     ret = sizeof(struct opa_congestion_setting_attr_shadow);
0076 
0077     if (pos > ret)
0078         return -EINVAL;
0079     if (count > ret - pos)
0080         count = ret - pos;
0081 
0082     if (!count)
0083         return count;
0084 
0085     rcu_read_lock();
0086     cc_state = get_cc_state(ppd);
0087     if (!cc_state) {
0088         rcu_read_unlock();
0089         return -EINVAL;
0090     }
0091     memcpy(buf, (void *)&cc_state->cong_setting + pos, count);
0092     rcu_read_unlock();
0093 
0094     return count;
0095 }
0096 static BIN_ATTR_RO(cc_setting_bin, PAGE_SIZE);
0097 
0098 static struct bin_attribute *port_cc_bin_attributes[] = {
0099     &bin_attr_cc_setting_bin,
0100     &bin_attr_cc_table_bin,
0101     NULL
0102 };
0103 
0104 static ssize_t cc_prescan_show(struct ib_device *ibdev, u32 port_num,
0105                    struct ib_port_attribute *attr, char *buf)
0106 {
0107     struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
0108     struct hfi1_pportdata *ppd = &dd->pport[port_num - 1];
0109 
0110     return sysfs_emit(buf, "%s\n", ppd->cc_prescan ? "on" : "off");
0111 }
0112 
0113 static ssize_t cc_prescan_store(struct ib_device *ibdev, u32 port_num,
0114                 struct ib_port_attribute *attr, const char *buf,
0115                 size_t count)
0116 {
0117     struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
0118     struct hfi1_pportdata *ppd = &dd->pport[port_num - 1];
0119 
0120     if (!memcmp(buf, "on", 2))
0121         ppd->cc_prescan = true;
0122     else if (!memcmp(buf, "off", 3))
0123         ppd->cc_prescan = false;
0124 
0125     return count;
0126 }
0127 static IB_PORT_ATTR_ADMIN_RW(cc_prescan);
0128 
0129 static struct attribute *port_cc_attributes[] = {
0130     &ib_port_attr_cc_prescan.attr,
0131     NULL
0132 };
0133 
0134 static const struct attribute_group port_cc_group = {
0135     .name = "CCMgtA",
0136     .attrs = port_cc_attributes,
0137     .bin_attrs = port_cc_bin_attributes,
0138 };
0139 
0140 /* Start sc2vl */
0141 struct hfi1_sc2vl_attr {
0142     struct ib_port_attribute attr;
0143     int sc;
0144 };
0145 
0146 static ssize_t sc2vl_attr_show(struct ib_device *ibdev, u32 port_num,
0147                    struct ib_port_attribute *attr, char *buf)
0148 {
0149     struct hfi1_sc2vl_attr *sattr =
0150         container_of(attr, struct hfi1_sc2vl_attr, attr);
0151     struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
0152 
0153     return sysfs_emit(buf, "%u\n", *((u8 *)dd->sc2vl + sattr->sc));
0154 }
0155 
0156 #define HFI1_SC2VL_ATTR(N)                                                     \
0157     static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = {                  \
0158         .attr = __ATTR(N, 0444, sc2vl_attr_show, NULL),                \
0159         .sc = N,                                                       \
0160     }
0161 
0162 HFI1_SC2VL_ATTR(0);
0163 HFI1_SC2VL_ATTR(1);
0164 HFI1_SC2VL_ATTR(2);
0165 HFI1_SC2VL_ATTR(3);
0166 HFI1_SC2VL_ATTR(4);
0167 HFI1_SC2VL_ATTR(5);
0168 HFI1_SC2VL_ATTR(6);
0169 HFI1_SC2VL_ATTR(7);
0170 HFI1_SC2VL_ATTR(8);
0171 HFI1_SC2VL_ATTR(9);
0172 HFI1_SC2VL_ATTR(10);
0173 HFI1_SC2VL_ATTR(11);
0174 HFI1_SC2VL_ATTR(12);
0175 HFI1_SC2VL_ATTR(13);
0176 HFI1_SC2VL_ATTR(14);
0177 HFI1_SC2VL_ATTR(15);
0178 HFI1_SC2VL_ATTR(16);
0179 HFI1_SC2VL_ATTR(17);
0180 HFI1_SC2VL_ATTR(18);
0181 HFI1_SC2VL_ATTR(19);
0182 HFI1_SC2VL_ATTR(20);
0183 HFI1_SC2VL_ATTR(21);
0184 HFI1_SC2VL_ATTR(22);
0185 HFI1_SC2VL_ATTR(23);
0186 HFI1_SC2VL_ATTR(24);
0187 HFI1_SC2VL_ATTR(25);
0188 HFI1_SC2VL_ATTR(26);
0189 HFI1_SC2VL_ATTR(27);
0190 HFI1_SC2VL_ATTR(28);
0191 HFI1_SC2VL_ATTR(29);
0192 HFI1_SC2VL_ATTR(30);
0193 HFI1_SC2VL_ATTR(31);
0194 
0195 static struct attribute *port_sc2vl_attributes[] = {
0196     &hfi1_sc2vl_attr_0.attr.attr,
0197     &hfi1_sc2vl_attr_1.attr.attr,
0198     &hfi1_sc2vl_attr_2.attr.attr,
0199     &hfi1_sc2vl_attr_3.attr.attr,
0200     &hfi1_sc2vl_attr_4.attr.attr,
0201     &hfi1_sc2vl_attr_5.attr.attr,
0202     &hfi1_sc2vl_attr_6.attr.attr,
0203     &hfi1_sc2vl_attr_7.attr.attr,
0204     &hfi1_sc2vl_attr_8.attr.attr,
0205     &hfi1_sc2vl_attr_9.attr.attr,
0206     &hfi1_sc2vl_attr_10.attr.attr,
0207     &hfi1_sc2vl_attr_11.attr.attr,
0208     &hfi1_sc2vl_attr_12.attr.attr,
0209     &hfi1_sc2vl_attr_13.attr.attr,
0210     &hfi1_sc2vl_attr_14.attr.attr,
0211     &hfi1_sc2vl_attr_15.attr.attr,
0212     &hfi1_sc2vl_attr_16.attr.attr,
0213     &hfi1_sc2vl_attr_17.attr.attr,
0214     &hfi1_sc2vl_attr_18.attr.attr,
0215     &hfi1_sc2vl_attr_19.attr.attr,
0216     &hfi1_sc2vl_attr_20.attr.attr,
0217     &hfi1_sc2vl_attr_21.attr.attr,
0218     &hfi1_sc2vl_attr_22.attr.attr,
0219     &hfi1_sc2vl_attr_23.attr.attr,
0220     &hfi1_sc2vl_attr_24.attr.attr,
0221     &hfi1_sc2vl_attr_25.attr.attr,
0222     &hfi1_sc2vl_attr_26.attr.attr,
0223     &hfi1_sc2vl_attr_27.attr.attr,
0224     &hfi1_sc2vl_attr_28.attr.attr,
0225     &hfi1_sc2vl_attr_29.attr.attr,
0226     &hfi1_sc2vl_attr_30.attr.attr,
0227     &hfi1_sc2vl_attr_31.attr.attr,
0228     NULL
0229 };
0230 
0231 static const struct attribute_group port_sc2vl_group = {
0232     .name = "sc2vl",
0233     .attrs = port_sc2vl_attributes,
0234 };
0235 /* End sc2vl */
0236 
0237 /* Start sl2sc */
0238 struct hfi1_sl2sc_attr {
0239     struct ib_port_attribute attr;
0240     int sl;
0241 };
0242 
0243 static ssize_t sl2sc_attr_show(struct ib_device *ibdev, u32 port_num,
0244                    struct ib_port_attribute *attr, char *buf)
0245 {
0246     struct hfi1_sl2sc_attr *sattr =
0247         container_of(attr, struct hfi1_sl2sc_attr, attr);
0248     struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
0249     struct hfi1_ibport *ibp = &dd->pport[port_num - 1].ibport_data;
0250 
0251     return sysfs_emit(buf, "%u\n", ibp->sl_to_sc[sattr->sl]);
0252 }
0253 
0254 #define HFI1_SL2SC_ATTR(N)                                                     \
0255     static struct hfi1_sl2sc_attr hfi1_sl2sc_attr_##N = {                  \
0256         .attr = __ATTR(N, 0444, sl2sc_attr_show, NULL), .sl = N        \
0257     }
0258 
0259 HFI1_SL2SC_ATTR(0);
0260 HFI1_SL2SC_ATTR(1);
0261 HFI1_SL2SC_ATTR(2);
0262 HFI1_SL2SC_ATTR(3);
0263 HFI1_SL2SC_ATTR(4);
0264 HFI1_SL2SC_ATTR(5);
0265 HFI1_SL2SC_ATTR(6);
0266 HFI1_SL2SC_ATTR(7);
0267 HFI1_SL2SC_ATTR(8);
0268 HFI1_SL2SC_ATTR(9);
0269 HFI1_SL2SC_ATTR(10);
0270 HFI1_SL2SC_ATTR(11);
0271 HFI1_SL2SC_ATTR(12);
0272 HFI1_SL2SC_ATTR(13);
0273 HFI1_SL2SC_ATTR(14);
0274 HFI1_SL2SC_ATTR(15);
0275 HFI1_SL2SC_ATTR(16);
0276 HFI1_SL2SC_ATTR(17);
0277 HFI1_SL2SC_ATTR(18);
0278 HFI1_SL2SC_ATTR(19);
0279 HFI1_SL2SC_ATTR(20);
0280 HFI1_SL2SC_ATTR(21);
0281 HFI1_SL2SC_ATTR(22);
0282 HFI1_SL2SC_ATTR(23);
0283 HFI1_SL2SC_ATTR(24);
0284 HFI1_SL2SC_ATTR(25);
0285 HFI1_SL2SC_ATTR(26);
0286 HFI1_SL2SC_ATTR(27);
0287 HFI1_SL2SC_ATTR(28);
0288 HFI1_SL2SC_ATTR(29);
0289 HFI1_SL2SC_ATTR(30);
0290 HFI1_SL2SC_ATTR(31);
0291 
0292 static struct attribute *port_sl2sc_attributes[] = {
0293     &hfi1_sl2sc_attr_0.attr.attr,
0294     &hfi1_sl2sc_attr_1.attr.attr,
0295     &hfi1_sl2sc_attr_2.attr.attr,
0296     &hfi1_sl2sc_attr_3.attr.attr,
0297     &hfi1_sl2sc_attr_4.attr.attr,
0298     &hfi1_sl2sc_attr_5.attr.attr,
0299     &hfi1_sl2sc_attr_6.attr.attr,
0300     &hfi1_sl2sc_attr_7.attr.attr,
0301     &hfi1_sl2sc_attr_8.attr.attr,
0302     &hfi1_sl2sc_attr_9.attr.attr,
0303     &hfi1_sl2sc_attr_10.attr.attr,
0304     &hfi1_sl2sc_attr_11.attr.attr,
0305     &hfi1_sl2sc_attr_12.attr.attr,
0306     &hfi1_sl2sc_attr_13.attr.attr,
0307     &hfi1_sl2sc_attr_14.attr.attr,
0308     &hfi1_sl2sc_attr_15.attr.attr,
0309     &hfi1_sl2sc_attr_16.attr.attr,
0310     &hfi1_sl2sc_attr_17.attr.attr,
0311     &hfi1_sl2sc_attr_18.attr.attr,
0312     &hfi1_sl2sc_attr_19.attr.attr,
0313     &hfi1_sl2sc_attr_20.attr.attr,
0314     &hfi1_sl2sc_attr_21.attr.attr,
0315     &hfi1_sl2sc_attr_22.attr.attr,
0316     &hfi1_sl2sc_attr_23.attr.attr,
0317     &hfi1_sl2sc_attr_24.attr.attr,
0318     &hfi1_sl2sc_attr_25.attr.attr,
0319     &hfi1_sl2sc_attr_26.attr.attr,
0320     &hfi1_sl2sc_attr_27.attr.attr,
0321     &hfi1_sl2sc_attr_28.attr.attr,
0322     &hfi1_sl2sc_attr_29.attr.attr,
0323     &hfi1_sl2sc_attr_30.attr.attr,
0324     &hfi1_sl2sc_attr_31.attr.attr,
0325     NULL
0326 };
0327 
0328 static const struct attribute_group port_sl2sc_group = {
0329     .name = "sl2sc",
0330     .attrs = port_sl2sc_attributes,
0331 };
0332 
0333 /* End sl2sc */
0334 
0335 /* Start vl2mtu */
0336 
0337 struct hfi1_vl2mtu_attr {
0338     struct ib_port_attribute attr;
0339     int vl;
0340 };
0341 
0342 static ssize_t vl2mtu_attr_show(struct ib_device *ibdev, u32 port_num,
0343                 struct ib_port_attribute *attr, char *buf)
0344 {
0345     struct hfi1_vl2mtu_attr *vlattr =
0346         container_of(attr, struct hfi1_vl2mtu_attr, attr);
0347     struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
0348 
0349     return sysfs_emit(buf, "%u\n", dd->vld[vlattr->vl].mtu);
0350 }
0351 
0352 #define HFI1_VL2MTU_ATTR(N)                                                    \
0353     static struct hfi1_vl2mtu_attr hfi1_vl2mtu_attr_##N = {                \
0354         .attr = __ATTR(N, 0444, vl2mtu_attr_show, NULL),               \
0355         .vl = N,                                                       \
0356     }
0357 
0358 HFI1_VL2MTU_ATTR(0);
0359 HFI1_VL2MTU_ATTR(1);
0360 HFI1_VL2MTU_ATTR(2);
0361 HFI1_VL2MTU_ATTR(3);
0362 HFI1_VL2MTU_ATTR(4);
0363 HFI1_VL2MTU_ATTR(5);
0364 HFI1_VL2MTU_ATTR(6);
0365 HFI1_VL2MTU_ATTR(7);
0366 HFI1_VL2MTU_ATTR(8);
0367 HFI1_VL2MTU_ATTR(9);
0368 HFI1_VL2MTU_ATTR(10);
0369 HFI1_VL2MTU_ATTR(11);
0370 HFI1_VL2MTU_ATTR(12);
0371 HFI1_VL2MTU_ATTR(13);
0372 HFI1_VL2MTU_ATTR(14);
0373 HFI1_VL2MTU_ATTR(15);
0374 
0375 static struct attribute *port_vl2mtu_attributes[] = {
0376     &hfi1_vl2mtu_attr_0.attr.attr,
0377     &hfi1_vl2mtu_attr_1.attr.attr,
0378     &hfi1_vl2mtu_attr_2.attr.attr,
0379     &hfi1_vl2mtu_attr_3.attr.attr,
0380     &hfi1_vl2mtu_attr_4.attr.attr,
0381     &hfi1_vl2mtu_attr_5.attr.attr,
0382     &hfi1_vl2mtu_attr_6.attr.attr,
0383     &hfi1_vl2mtu_attr_7.attr.attr,
0384     &hfi1_vl2mtu_attr_8.attr.attr,
0385     &hfi1_vl2mtu_attr_9.attr.attr,
0386     &hfi1_vl2mtu_attr_10.attr.attr,
0387     &hfi1_vl2mtu_attr_11.attr.attr,
0388     &hfi1_vl2mtu_attr_12.attr.attr,
0389     &hfi1_vl2mtu_attr_13.attr.attr,
0390     &hfi1_vl2mtu_attr_14.attr.attr,
0391     &hfi1_vl2mtu_attr_15.attr.attr,
0392     NULL
0393 };
0394 
0395 static const struct attribute_group port_vl2mtu_group = {
0396     .name = "vl2mtu",
0397     .attrs = port_vl2mtu_attributes,
0398 };
0399 
0400 /* end of per-port file structures and support code */
0401 
0402 /*
0403  * Start of per-unit (or driver, in some cases, but replicated
0404  * per unit) functions (these get a device *)
0405  */
0406 static ssize_t hw_rev_show(struct device *device, struct device_attribute *attr,
0407                char *buf)
0408 {
0409     struct hfi1_ibdev *dev =
0410         rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
0411 
0412     return sysfs_emit(buf, "%x\n", dd_from_dev(dev)->minrev);
0413 }
0414 static DEVICE_ATTR_RO(hw_rev);
0415 
0416 static ssize_t board_id_show(struct device *device,
0417                  struct device_attribute *attr, char *buf)
0418 {
0419     struct hfi1_ibdev *dev =
0420         rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
0421     struct hfi1_devdata *dd = dd_from_dev(dev);
0422 
0423     if (!dd->boardname)
0424         return -EINVAL;
0425 
0426     return sysfs_emit(buf, "%s\n", dd->boardname);
0427 }
0428 static DEVICE_ATTR_RO(board_id);
0429 
0430 static ssize_t boardversion_show(struct device *device,
0431                  struct device_attribute *attr, char *buf)
0432 {
0433     struct hfi1_ibdev *dev =
0434         rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
0435     struct hfi1_devdata *dd = dd_from_dev(dev);
0436 
0437     /* The string printed here is already newline-terminated. */
0438     return sysfs_emit(buf, "%s", dd->boardversion);
0439 }
0440 static DEVICE_ATTR_RO(boardversion);
0441 
0442 static ssize_t nctxts_show(struct device *device,
0443                struct device_attribute *attr, char *buf)
0444 {
0445     struct hfi1_ibdev *dev =
0446         rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
0447     struct hfi1_devdata *dd = dd_from_dev(dev);
0448 
0449     /*
0450      * Return the smaller of send and receive contexts.
0451      * Normally, user level applications would require both a send
0452      * and a receive context, so returning the smaller of the two counts
0453      * give a more accurate picture of total contexts available.
0454      */
0455     return sysfs_emit(buf, "%u\n",
0456               min(dd->num_user_contexts,
0457                   (u32)dd->sc_sizes[SC_USER].count));
0458 }
0459 static DEVICE_ATTR_RO(nctxts);
0460 
0461 static ssize_t nfreectxts_show(struct device *device,
0462                    struct device_attribute *attr, char *buf)
0463 {
0464     struct hfi1_ibdev *dev =
0465         rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
0466     struct hfi1_devdata *dd = dd_from_dev(dev);
0467 
0468     /* Return the number of free user ports (contexts) available. */
0469     return sysfs_emit(buf, "%u\n", dd->freectxts);
0470 }
0471 static DEVICE_ATTR_RO(nfreectxts);
0472 
0473 static ssize_t serial_show(struct device *device,
0474                struct device_attribute *attr, char *buf)
0475 {
0476     struct hfi1_ibdev *dev =
0477         rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
0478     struct hfi1_devdata *dd = dd_from_dev(dev);
0479 
0480     /* dd->serial is already newline terminated in chip.c */
0481     return sysfs_emit(buf, "%s", dd->serial);
0482 }
0483 static DEVICE_ATTR_RO(serial);
0484 
0485 static ssize_t chip_reset_store(struct device *device,
0486                 struct device_attribute *attr, const char *buf,
0487                 size_t count)
0488 {
0489     struct hfi1_ibdev *dev =
0490         rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
0491     struct hfi1_devdata *dd = dd_from_dev(dev);
0492     int ret;
0493 
0494     if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) {
0495         ret = -EINVAL;
0496         goto bail;
0497     }
0498 
0499     ret = hfi1_reset_device(dd->unit);
0500 bail:
0501     return ret < 0 ? ret : count;
0502 }
0503 static DEVICE_ATTR_WO(chip_reset);
0504 
0505 /*
0506  * Convert the reported temperature from an integer (reported in
0507  * units of 0.25C) to a floating point number.
0508  */
0509 #define temp_d(t) ((t) >> 2)
0510 #define temp_f(t) (((t)&0x3) * 25u)
0511 
0512 /*
0513  * Dump tempsense values, in decimal, to ease shell-scripts.
0514  */
0515 static ssize_t tempsense_show(struct device *device,
0516                   struct device_attribute *attr, char *buf)
0517 {
0518     struct hfi1_ibdev *dev =
0519         rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
0520     struct hfi1_devdata *dd = dd_from_dev(dev);
0521     struct hfi1_temp temp;
0522     int ret;
0523 
0524     ret = hfi1_tempsense_rd(dd, &temp);
0525     if (ret)
0526         return ret;
0527 
0528     return sysfs_emit(buf, "%u.%02u %u.%02u %u.%02u %u.%02u %u %u %u\n",
0529               temp_d(temp.curr), temp_f(temp.curr),
0530               temp_d(temp.lo_lim), temp_f(temp.lo_lim),
0531               temp_d(temp.hi_lim), temp_f(temp.hi_lim),
0532               temp_d(temp.crit_lim), temp_f(temp.crit_lim),
0533               temp.triggers & 0x1,
0534               temp.triggers & 0x2,
0535               temp.triggers & 0x4);
0536 }
0537 static DEVICE_ATTR_RO(tempsense);
0538 
0539 /*
0540  * end of per-unit (or driver, in some cases, but replicated
0541  * per unit) functions
0542  */
0543 
0544 /* start of per-unit file structures and support code */
0545 static struct attribute *hfi1_attributes[] = {
0546     &dev_attr_hw_rev.attr,
0547     &dev_attr_board_id.attr,
0548     &dev_attr_nctxts.attr,
0549     &dev_attr_nfreectxts.attr,
0550     &dev_attr_serial.attr,
0551     &dev_attr_boardversion.attr,
0552     &dev_attr_tempsense.attr,
0553     &dev_attr_chip_reset.attr,
0554     NULL,
0555 };
0556 
0557 const struct attribute_group ib_hfi1_attr_group = {
0558     .attrs = hfi1_attributes,
0559 };
0560 
0561 const struct attribute_group *hfi1_attr_port_groups[] = {
0562     &port_cc_group,
0563     &port_sc2vl_group,
0564     &port_sl2sc_group,
0565     &port_vl2mtu_group,
0566     NULL,
0567 };
0568 
0569 struct sde_attribute {
0570     struct attribute attr;
0571     ssize_t (*show)(struct sdma_engine *sde, char *buf);
0572     ssize_t (*store)(struct sdma_engine *sde, const char *buf, size_t cnt);
0573 };
0574 
0575 static ssize_t sde_show(struct kobject *kobj, struct attribute *attr, char *buf)
0576 {
0577     struct sde_attribute *sde_attr =
0578         container_of(attr, struct sde_attribute, attr);
0579     struct sdma_engine *sde =
0580         container_of(kobj, struct sdma_engine, kobj);
0581 
0582     if (!sde_attr->show)
0583         return -EINVAL;
0584 
0585     return sde_attr->show(sde, buf);
0586 }
0587 
0588 static ssize_t sde_store(struct kobject *kobj, struct attribute *attr,
0589              const char *buf, size_t count)
0590 {
0591     struct sde_attribute *sde_attr =
0592         container_of(attr, struct sde_attribute, attr);
0593     struct sdma_engine *sde =
0594         container_of(kobj, struct sdma_engine, kobj);
0595 
0596     if (!capable(CAP_SYS_ADMIN))
0597         return -EPERM;
0598 
0599     if (!sde_attr->store)
0600         return -EINVAL;
0601 
0602     return sde_attr->store(sde, buf, count);
0603 }
0604 
0605 static const struct sysfs_ops sde_sysfs_ops = {
0606     .show = sde_show,
0607     .store = sde_store,
0608 };
0609 
0610 static struct kobj_type sde_ktype = {
0611     .sysfs_ops = &sde_sysfs_ops,
0612 };
0613 
0614 #define SDE_ATTR(_name, _mode, _show, _store) \
0615     struct sde_attribute sde_attr_##_name = \
0616         __ATTR(_name, _mode, _show, _store)
0617 
0618 static ssize_t sde_show_cpu_to_sde_map(struct sdma_engine *sde, char *buf)
0619 {
0620     return sdma_get_cpu_to_sde_map(sde, buf);
0621 }
0622 
0623 static ssize_t sde_store_cpu_to_sde_map(struct sdma_engine *sde,
0624                     const char *buf, size_t count)
0625 {
0626     return sdma_set_cpu_to_sde_map(sde, buf, count);
0627 }
0628 
0629 static ssize_t sde_show_vl(struct sdma_engine *sde, char *buf)
0630 {
0631     int vl;
0632 
0633     vl = sdma_engine_get_vl(sde);
0634     if (vl < 0)
0635         return vl;
0636 
0637     return sysfs_emit(buf, "%d\n", vl);
0638 }
0639 
0640 static SDE_ATTR(cpu_list, S_IWUSR | S_IRUGO,
0641         sde_show_cpu_to_sde_map,
0642         sde_store_cpu_to_sde_map);
0643 static SDE_ATTR(vl, S_IRUGO, sde_show_vl, NULL);
0644 
0645 static struct sde_attribute *sde_attribs[] = {
0646     &sde_attr_cpu_list,
0647     &sde_attr_vl
0648 };
0649 
0650 /*
0651  * Register and create our files in /sys/class/infiniband.
0652  */
0653 int hfi1_verbs_register_sysfs(struct hfi1_devdata *dd)
0654 {
0655     struct ib_device *dev = &dd->verbs_dev.rdi.ibdev;
0656     struct device *class_dev = &dev->dev;
0657     int i, j, ret;
0658 
0659     for (i = 0; i < dd->num_sdma; i++) {
0660         ret = kobject_init_and_add(&dd->per_sdma[i].kobj,
0661                        &sde_ktype, &class_dev->kobj,
0662                        "sdma%d", i);
0663         if (ret)
0664             goto bail;
0665 
0666         for (j = 0; j < ARRAY_SIZE(sde_attribs); j++) {
0667             ret = sysfs_create_file(&dd->per_sdma[i].kobj,
0668                         &sde_attribs[j]->attr);
0669             if (ret)
0670                 goto bail;
0671         }
0672     }
0673 
0674     return 0;
0675 bail:
0676     /*
0677      * The function kobject_put() will call kobject_del() if the kobject
0678      * has been added successfully. The sysfs files created under the
0679      * kobject directory will also be removed during the process.
0680      */
0681     for (; i >= 0; i--)
0682         kobject_put(&dd->per_sdma[i].kobj);
0683 
0684     return ret;
0685 }
0686 
0687 /*
0688  * Unregister and remove our files in /sys/class/infiniband.
0689  */
0690 void hfi1_verbs_unregister_sysfs(struct hfi1_devdata *dd)
0691 {
0692     int i;
0693 
0694     /* Unwind operations in hfi1_verbs_register_sysfs() */
0695     for (i = 0; i < dd->num_sdma; i++)
0696         kobject_put(&dd->per_sdma[i].kobj);
0697 }