cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sysfs.c (17932B)


      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}