xref: /OK3568_Linux_fs/kernel/drivers/infiniband/hw/hfi1/sysfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright(c) 2015-2017 Intel Corporation.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * This file is provided under a dual BSD/GPLv2 license.  When using or
5*4882a593Smuzhiyun  * redistributing this file, you may do so under either license.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * GPL LICENSE SUMMARY
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or modify
10*4882a593Smuzhiyun  * it under the terms of version 2 of the GNU General Public License as
11*4882a593Smuzhiyun  * published by the Free Software Foundation.
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * This program is distributed in the hope that it will be useful, but
14*4882a593Smuzhiyun  * WITHOUT ANY WARRANTY; without even the implied warranty of
15*4882a593Smuzhiyun  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*4882a593Smuzhiyun  * General Public License for more details.
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * BSD LICENSE
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  * Redistribution and use in source and binary forms, with or without
21*4882a593Smuzhiyun  * modification, are permitted provided that the following conditions
22*4882a593Smuzhiyun  * are met:
23*4882a593Smuzhiyun  *
24*4882a593Smuzhiyun  *  - Redistributions of source code must retain the above copyright
25*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer.
26*4882a593Smuzhiyun  *  - Redistributions in binary form must reproduce the above copyright
27*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer in
28*4882a593Smuzhiyun  *    the documentation and/or other materials provided with the
29*4882a593Smuzhiyun  *    distribution.
30*4882a593Smuzhiyun  *  - Neither the name of Intel Corporation nor the names of its
31*4882a593Smuzhiyun  *    contributors may be used to endorse or promote products derived
32*4882a593Smuzhiyun  *    from this software without specific prior written permission.
33*4882a593Smuzhiyun  *
34*4882a593Smuzhiyun  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35*4882a593Smuzhiyun  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36*4882a593Smuzhiyun  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37*4882a593Smuzhiyun  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38*4882a593Smuzhiyun  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39*4882a593Smuzhiyun  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40*4882a593Smuzhiyun  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41*4882a593Smuzhiyun  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42*4882a593Smuzhiyun  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43*4882a593Smuzhiyun  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44*4882a593Smuzhiyun  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45*4882a593Smuzhiyun  *
46*4882a593Smuzhiyun  */
47*4882a593Smuzhiyun #include <linux/ctype.h>
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #include "hfi.h"
50*4882a593Smuzhiyun #include "mad.h"
51*4882a593Smuzhiyun #include "trace.h"
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun /*
54*4882a593Smuzhiyun  * Start of per-port congestion control structures and support code
55*4882a593Smuzhiyun  */
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /*
58*4882a593Smuzhiyun  * Congestion control table size followed by table entries
59*4882a593Smuzhiyun  */
read_cc_table_bin(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t pos,size_t count)60*4882a593Smuzhiyun static ssize_t read_cc_table_bin(struct file *filp, struct kobject *kobj,
61*4882a593Smuzhiyun 				 struct bin_attribute *bin_attr,
62*4882a593Smuzhiyun 				 char *buf, loff_t pos, size_t count)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun 	int ret;
65*4882a593Smuzhiyun 	struct hfi1_pportdata *ppd =
66*4882a593Smuzhiyun 		container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
67*4882a593Smuzhiyun 	struct cc_state *cc_state;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	ret = ppd->total_cct_entry * sizeof(struct ib_cc_table_entry_shadow)
70*4882a593Smuzhiyun 		 + sizeof(__be16);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	if (pos > ret)
73*4882a593Smuzhiyun 		return -EINVAL;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	if (count > ret - pos)
76*4882a593Smuzhiyun 		count = ret - pos;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	if (!count)
79*4882a593Smuzhiyun 		return count;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	rcu_read_lock();
82*4882a593Smuzhiyun 	cc_state = get_cc_state(ppd);
83*4882a593Smuzhiyun 	if (!cc_state) {
84*4882a593Smuzhiyun 		rcu_read_unlock();
85*4882a593Smuzhiyun 		return -EINVAL;
86*4882a593Smuzhiyun 	}
87*4882a593Smuzhiyun 	memcpy(buf, (void *)&cc_state->cct + pos, count);
88*4882a593Smuzhiyun 	rcu_read_unlock();
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	return count;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
port_release(struct kobject * kobj)93*4882a593Smuzhiyun static void port_release(struct kobject *kobj)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	/* nothing to do since memory is freed by hfi1_free_devdata() */
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun static const struct bin_attribute cc_table_bin_attr = {
99*4882a593Smuzhiyun 	.attr = {.name = "cc_table_bin", .mode = 0444},
100*4882a593Smuzhiyun 	.read = read_cc_table_bin,
101*4882a593Smuzhiyun 	.size = PAGE_SIZE,
102*4882a593Smuzhiyun };
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun /*
105*4882a593Smuzhiyun  * Congestion settings: port control, control map and an array of 16
106*4882a593Smuzhiyun  * entries for the congestion entries - increase, timer, event log
107*4882a593Smuzhiyun  * trigger threshold and the minimum injection rate delay.
108*4882a593Smuzhiyun  */
read_cc_setting_bin(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t pos,size_t count)109*4882a593Smuzhiyun static ssize_t read_cc_setting_bin(struct file *filp, struct kobject *kobj,
110*4882a593Smuzhiyun 				   struct bin_attribute *bin_attr,
111*4882a593Smuzhiyun 				   char *buf, loff_t pos, size_t count)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun 	int ret;
114*4882a593Smuzhiyun 	struct hfi1_pportdata *ppd =
115*4882a593Smuzhiyun 		container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
116*4882a593Smuzhiyun 	struct cc_state *cc_state;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	ret = sizeof(struct opa_congestion_setting_attr_shadow);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	if (pos > ret)
121*4882a593Smuzhiyun 		return -EINVAL;
122*4882a593Smuzhiyun 	if (count > ret - pos)
123*4882a593Smuzhiyun 		count = ret - pos;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	if (!count)
126*4882a593Smuzhiyun 		return count;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	rcu_read_lock();
129*4882a593Smuzhiyun 	cc_state = get_cc_state(ppd);
130*4882a593Smuzhiyun 	if (!cc_state) {
131*4882a593Smuzhiyun 		rcu_read_unlock();
132*4882a593Smuzhiyun 		return -EINVAL;
133*4882a593Smuzhiyun 	}
134*4882a593Smuzhiyun 	memcpy(buf, (void *)&cc_state->cong_setting + pos, count);
135*4882a593Smuzhiyun 	rcu_read_unlock();
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	return count;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun static const struct bin_attribute cc_setting_bin_attr = {
141*4882a593Smuzhiyun 	.attr = {.name = "cc_settings_bin", .mode = 0444},
142*4882a593Smuzhiyun 	.read = read_cc_setting_bin,
143*4882a593Smuzhiyun 	.size = PAGE_SIZE,
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun struct hfi1_port_attr {
147*4882a593Smuzhiyun 	struct attribute attr;
148*4882a593Smuzhiyun 	ssize_t	(*show)(struct hfi1_pportdata *, char *);
149*4882a593Smuzhiyun 	ssize_t	(*store)(struct hfi1_pportdata *, const char *, size_t);
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun 
cc_prescan_show(struct hfi1_pportdata * ppd,char * buf)152*4882a593Smuzhiyun static ssize_t cc_prescan_show(struct hfi1_pportdata *ppd, char *buf)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun 	return sprintf(buf, "%s\n", ppd->cc_prescan ? "on" : "off");
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
cc_prescan_store(struct hfi1_pportdata * ppd,const char * buf,size_t count)157*4882a593Smuzhiyun static ssize_t cc_prescan_store(struct hfi1_pportdata *ppd, const char *buf,
158*4882a593Smuzhiyun 				size_t count)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	if (!memcmp(buf, "on", 2))
161*4882a593Smuzhiyun 		ppd->cc_prescan = true;
162*4882a593Smuzhiyun 	else if (!memcmp(buf, "off", 3))
163*4882a593Smuzhiyun 		ppd->cc_prescan = false;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	return count;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun static struct hfi1_port_attr cc_prescan_attr =
169*4882a593Smuzhiyun 		__ATTR(cc_prescan, 0600, cc_prescan_show, cc_prescan_store);
170*4882a593Smuzhiyun 
cc_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)171*4882a593Smuzhiyun static ssize_t cc_attr_show(struct kobject *kobj, struct attribute *attr,
172*4882a593Smuzhiyun 			    char *buf)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	struct hfi1_port_attr *port_attr =
175*4882a593Smuzhiyun 		container_of(attr, struct hfi1_port_attr, attr);
176*4882a593Smuzhiyun 	struct hfi1_pportdata *ppd =
177*4882a593Smuzhiyun 		container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	return port_attr->show(ppd, buf);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
cc_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t count)182*4882a593Smuzhiyun static ssize_t cc_attr_store(struct kobject *kobj, struct attribute *attr,
183*4882a593Smuzhiyun 			     const char *buf, size_t count)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun 	struct hfi1_port_attr *port_attr =
186*4882a593Smuzhiyun 		container_of(attr, struct hfi1_port_attr, attr);
187*4882a593Smuzhiyun 	struct hfi1_pportdata *ppd =
188*4882a593Smuzhiyun 		container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	return port_attr->store(ppd, buf, count);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun static const struct sysfs_ops port_cc_sysfs_ops = {
194*4882a593Smuzhiyun 	.show = cc_attr_show,
195*4882a593Smuzhiyun 	.store = cc_attr_store
196*4882a593Smuzhiyun };
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun static struct attribute *port_cc_default_attributes[] = {
199*4882a593Smuzhiyun 	&cc_prescan_attr.attr,
200*4882a593Smuzhiyun 	NULL
201*4882a593Smuzhiyun };
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun static struct kobj_type port_cc_ktype = {
204*4882a593Smuzhiyun 	.release = port_release,
205*4882a593Smuzhiyun 	.sysfs_ops = &port_cc_sysfs_ops,
206*4882a593Smuzhiyun 	.default_attrs = port_cc_default_attributes
207*4882a593Smuzhiyun };
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun /* Start sc2vl */
210*4882a593Smuzhiyun #define HFI1_SC2VL_ATTR(N)				    \
211*4882a593Smuzhiyun 	static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = { \
212*4882a593Smuzhiyun 		.attr = { .name = __stringify(N), .mode = 0444 }, \
213*4882a593Smuzhiyun 		.sc = N \
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun struct hfi1_sc2vl_attr {
217*4882a593Smuzhiyun 	struct attribute attr;
218*4882a593Smuzhiyun 	int sc;
219*4882a593Smuzhiyun };
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun HFI1_SC2VL_ATTR(0);
222*4882a593Smuzhiyun HFI1_SC2VL_ATTR(1);
223*4882a593Smuzhiyun HFI1_SC2VL_ATTR(2);
224*4882a593Smuzhiyun HFI1_SC2VL_ATTR(3);
225*4882a593Smuzhiyun HFI1_SC2VL_ATTR(4);
226*4882a593Smuzhiyun HFI1_SC2VL_ATTR(5);
227*4882a593Smuzhiyun HFI1_SC2VL_ATTR(6);
228*4882a593Smuzhiyun HFI1_SC2VL_ATTR(7);
229*4882a593Smuzhiyun HFI1_SC2VL_ATTR(8);
230*4882a593Smuzhiyun HFI1_SC2VL_ATTR(9);
231*4882a593Smuzhiyun HFI1_SC2VL_ATTR(10);
232*4882a593Smuzhiyun HFI1_SC2VL_ATTR(11);
233*4882a593Smuzhiyun HFI1_SC2VL_ATTR(12);
234*4882a593Smuzhiyun HFI1_SC2VL_ATTR(13);
235*4882a593Smuzhiyun HFI1_SC2VL_ATTR(14);
236*4882a593Smuzhiyun HFI1_SC2VL_ATTR(15);
237*4882a593Smuzhiyun HFI1_SC2VL_ATTR(16);
238*4882a593Smuzhiyun HFI1_SC2VL_ATTR(17);
239*4882a593Smuzhiyun HFI1_SC2VL_ATTR(18);
240*4882a593Smuzhiyun HFI1_SC2VL_ATTR(19);
241*4882a593Smuzhiyun HFI1_SC2VL_ATTR(20);
242*4882a593Smuzhiyun HFI1_SC2VL_ATTR(21);
243*4882a593Smuzhiyun HFI1_SC2VL_ATTR(22);
244*4882a593Smuzhiyun HFI1_SC2VL_ATTR(23);
245*4882a593Smuzhiyun HFI1_SC2VL_ATTR(24);
246*4882a593Smuzhiyun HFI1_SC2VL_ATTR(25);
247*4882a593Smuzhiyun HFI1_SC2VL_ATTR(26);
248*4882a593Smuzhiyun HFI1_SC2VL_ATTR(27);
249*4882a593Smuzhiyun HFI1_SC2VL_ATTR(28);
250*4882a593Smuzhiyun HFI1_SC2VL_ATTR(29);
251*4882a593Smuzhiyun HFI1_SC2VL_ATTR(30);
252*4882a593Smuzhiyun HFI1_SC2VL_ATTR(31);
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun static struct attribute *sc2vl_default_attributes[] = {
255*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_0.attr,
256*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_1.attr,
257*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_2.attr,
258*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_3.attr,
259*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_4.attr,
260*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_5.attr,
261*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_6.attr,
262*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_7.attr,
263*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_8.attr,
264*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_9.attr,
265*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_10.attr,
266*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_11.attr,
267*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_12.attr,
268*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_13.attr,
269*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_14.attr,
270*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_15.attr,
271*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_16.attr,
272*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_17.attr,
273*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_18.attr,
274*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_19.attr,
275*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_20.attr,
276*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_21.attr,
277*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_22.attr,
278*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_23.attr,
279*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_24.attr,
280*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_25.attr,
281*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_26.attr,
282*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_27.attr,
283*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_28.attr,
284*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_29.attr,
285*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_30.attr,
286*4882a593Smuzhiyun 	&hfi1_sc2vl_attr_31.attr,
287*4882a593Smuzhiyun 	NULL
288*4882a593Smuzhiyun };
289*4882a593Smuzhiyun 
sc2vl_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)290*4882a593Smuzhiyun static ssize_t sc2vl_attr_show(struct kobject *kobj, struct attribute *attr,
291*4882a593Smuzhiyun 			       char *buf)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun 	struct hfi1_sc2vl_attr *sattr =
294*4882a593Smuzhiyun 		container_of(attr, struct hfi1_sc2vl_attr, attr);
295*4882a593Smuzhiyun 	struct hfi1_pportdata *ppd =
296*4882a593Smuzhiyun 		container_of(kobj, struct hfi1_pportdata, sc2vl_kobj);
297*4882a593Smuzhiyun 	struct hfi1_devdata *dd = ppd->dd;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	return sprintf(buf, "%u\n", *((u8 *)dd->sc2vl + sattr->sc));
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun static const struct sysfs_ops hfi1_sc2vl_ops = {
303*4882a593Smuzhiyun 	.show = sc2vl_attr_show,
304*4882a593Smuzhiyun };
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun static struct kobj_type hfi1_sc2vl_ktype = {
307*4882a593Smuzhiyun 	.release = port_release,
308*4882a593Smuzhiyun 	.sysfs_ops = &hfi1_sc2vl_ops,
309*4882a593Smuzhiyun 	.default_attrs = sc2vl_default_attributes
310*4882a593Smuzhiyun };
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun /* End sc2vl */
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun /* Start sl2sc */
315*4882a593Smuzhiyun #define HFI1_SL2SC_ATTR(N)				    \
316*4882a593Smuzhiyun 	static struct hfi1_sl2sc_attr hfi1_sl2sc_attr_##N = {	  \
317*4882a593Smuzhiyun 		.attr = { .name = __stringify(N), .mode = 0444 }, \
318*4882a593Smuzhiyun 		.sl = N						  \
319*4882a593Smuzhiyun 	}
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun struct hfi1_sl2sc_attr {
322*4882a593Smuzhiyun 	struct attribute attr;
323*4882a593Smuzhiyun 	int sl;
324*4882a593Smuzhiyun };
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun HFI1_SL2SC_ATTR(0);
327*4882a593Smuzhiyun HFI1_SL2SC_ATTR(1);
328*4882a593Smuzhiyun HFI1_SL2SC_ATTR(2);
329*4882a593Smuzhiyun HFI1_SL2SC_ATTR(3);
330*4882a593Smuzhiyun HFI1_SL2SC_ATTR(4);
331*4882a593Smuzhiyun HFI1_SL2SC_ATTR(5);
332*4882a593Smuzhiyun HFI1_SL2SC_ATTR(6);
333*4882a593Smuzhiyun HFI1_SL2SC_ATTR(7);
334*4882a593Smuzhiyun HFI1_SL2SC_ATTR(8);
335*4882a593Smuzhiyun HFI1_SL2SC_ATTR(9);
336*4882a593Smuzhiyun HFI1_SL2SC_ATTR(10);
337*4882a593Smuzhiyun HFI1_SL2SC_ATTR(11);
338*4882a593Smuzhiyun HFI1_SL2SC_ATTR(12);
339*4882a593Smuzhiyun HFI1_SL2SC_ATTR(13);
340*4882a593Smuzhiyun HFI1_SL2SC_ATTR(14);
341*4882a593Smuzhiyun HFI1_SL2SC_ATTR(15);
342*4882a593Smuzhiyun HFI1_SL2SC_ATTR(16);
343*4882a593Smuzhiyun HFI1_SL2SC_ATTR(17);
344*4882a593Smuzhiyun HFI1_SL2SC_ATTR(18);
345*4882a593Smuzhiyun HFI1_SL2SC_ATTR(19);
346*4882a593Smuzhiyun HFI1_SL2SC_ATTR(20);
347*4882a593Smuzhiyun HFI1_SL2SC_ATTR(21);
348*4882a593Smuzhiyun HFI1_SL2SC_ATTR(22);
349*4882a593Smuzhiyun HFI1_SL2SC_ATTR(23);
350*4882a593Smuzhiyun HFI1_SL2SC_ATTR(24);
351*4882a593Smuzhiyun HFI1_SL2SC_ATTR(25);
352*4882a593Smuzhiyun HFI1_SL2SC_ATTR(26);
353*4882a593Smuzhiyun HFI1_SL2SC_ATTR(27);
354*4882a593Smuzhiyun HFI1_SL2SC_ATTR(28);
355*4882a593Smuzhiyun HFI1_SL2SC_ATTR(29);
356*4882a593Smuzhiyun HFI1_SL2SC_ATTR(30);
357*4882a593Smuzhiyun HFI1_SL2SC_ATTR(31);
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun static struct attribute *sl2sc_default_attributes[] = {
360*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_0.attr,
361*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_1.attr,
362*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_2.attr,
363*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_3.attr,
364*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_4.attr,
365*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_5.attr,
366*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_6.attr,
367*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_7.attr,
368*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_8.attr,
369*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_9.attr,
370*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_10.attr,
371*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_11.attr,
372*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_12.attr,
373*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_13.attr,
374*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_14.attr,
375*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_15.attr,
376*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_16.attr,
377*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_17.attr,
378*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_18.attr,
379*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_19.attr,
380*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_20.attr,
381*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_21.attr,
382*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_22.attr,
383*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_23.attr,
384*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_24.attr,
385*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_25.attr,
386*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_26.attr,
387*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_27.attr,
388*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_28.attr,
389*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_29.attr,
390*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_30.attr,
391*4882a593Smuzhiyun 	&hfi1_sl2sc_attr_31.attr,
392*4882a593Smuzhiyun 	NULL
393*4882a593Smuzhiyun };
394*4882a593Smuzhiyun 
sl2sc_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)395*4882a593Smuzhiyun static ssize_t sl2sc_attr_show(struct kobject *kobj, struct attribute *attr,
396*4882a593Smuzhiyun 			       char *buf)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun 	struct hfi1_sl2sc_attr *sattr =
399*4882a593Smuzhiyun 		container_of(attr, struct hfi1_sl2sc_attr, attr);
400*4882a593Smuzhiyun 	struct hfi1_pportdata *ppd =
401*4882a593Smuzhiyun 		container_of(kobj, struct hfi1_pportdata, sl2sc_kobj);
402*4882a593Smuzhiyun 	struct hfi1_ibport *ibp = &ppd->ibport_data;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	return sprintf(buf, "%u\n", ibp->sl_to_sc[sattr->sl]);
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun static const struct sysfs_ops hfi1_sl2sc_ops = {
408*4882a593Smuzhiyun 	.show = sl2sc_attr_show,
409*4882a593Smuzhiyun };
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun static struct kobj_type hfi1_sl2sc_ktype = {
412*4882a593Smuzhiyun 	.release = port_release,
413*4882a593Smuzhiyun 	.sysfs_ops = &hfi1_sl2sc_ops,
414*4882a593Smuzhiyun 	.default_attrs = sl2sc_default_attributes
415*4882a593Smuzhiyun };
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun /* End sl2sc */
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun /* Start vl2mtu */
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun #define HFI1_VL2MTU_ATTR(N) \
422*4882a593Smuzhiyun 	static struct hfi1_vl2mtu_attr hfi1_vl2mtu_attr_##N = { \
423*4882a593Smuzhiyun 		.attr = { .name = __stringify(N), .mode = 0444 }, \
424*4882a593Smuzhiyun 		.vl = N						  \
425*4882a593Smuzhiyun 	}
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun struct hfi1_vl2mtu_attr {
428*4882a593Smuzhiyun 	struct attribute attr;
429*4882a593Smuzhiyun 	int vl;
430*4882a593Smuzhiyun };
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(0);
433*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(1);
434*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(2);
435*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(3);
436*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(4);
437*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(5);
438*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(6);
439*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(7);
440*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(8);
441*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(9);
442*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(10);
443*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(11);
444*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(12);
445*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(13);
446*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(14);
447*4882a593Smuzhiyun HFI1_VL2MTU_ATTR(15);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun static struct attribute *vl2mtu_default_attributes[] = {
450*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_0.attr,
451*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_1.attr,
452*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_2.attr,
453*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_3.attr,
454*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_4.attr,
455*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_5.attr,
456*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_6.attr,
457*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_7.attr,
458*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_8.attr,
459*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_9.attr,
460*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_10.attr,
461*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_11.attr,
462*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_12.attr,
463*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_13.attr,
464*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_14.attr,
465*4882a593Smuzhiyun 	&hfi1_vl2mtu_attr_15.attr,
466*4882a593Smuzhiyun 	NULL
467*4882a593Smuzhiyun };
468*4882a593Smuzhiyun 
vl2mtu_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)469*4882a593Smuzhiyun static ssize_t vl2mtu_attr_show(struct kobject *kobj, struct attribute *attr,
470*4882a593Smuzhiyun 				char *buf)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun 	struct hfi1_vl2mtu_attr *vlattr =
473*4882a593Smuzhiyun 		container_of(attr, struct hfi1_vl2mtu_attr, attr);
474*4882a593Smuzhiyun 	struct hfi1_pportdata *ppd =
475*4882a593Smuzhiyun 		container_of(kobj, struct hfi1_pportdata, vl2mtu_kobj);
476*4882a593Smuzhiyun 	struct hfi1_devdata *dd = ppd->dd;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	return sprintf(buf, "%u\n", dd->vld[vlattr->vl].mtu);
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun static const struct sysfs_ops hfi1_vl2mtu_ops = {
482*4882a593Smuzhiyun 	.show = vl2mtu_attr_show,
483*4882a593Smuzhiyun };
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun static struct kobj_type hfi1_vl2mtu_ktype = {
486*4882a593Smuzhiyun 	.release = port_release,
487*4882a593Smuzhiyun 	.sysfs_ops = &hfi1_vl2mtu_ops,
488*4882a593Smuzhiyun 	.default_attrs = vl2mtu_default_attributes
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun /* end of per-port file structures and support code */
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun /*
494*4882a593Smuzhiyun  * Start of per-unit (or driver, in some cases, but replicated
495*4882a593Smuzhiyun  * per unit) functions (these get a device *)
496*4882a593Smuzhiyun  */
hw_rev_show(struct device * device,struct device_attribute * attr,char * buf)497*4882a593Smuzhiyun static ssize_t hw_rev_show(struct device *device, struct device_attribute *attr,
498*4882a593Smuzhiyun 			   char *buf)
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun 	struct hfi1_ibdev *dev =
501*4882a593Smuzhiyun 		rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	return sprintf(buf, "%x\n", dd_from_dev(dev)->minrev);
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun static DEVICE_ATTR_RO(hw_rev);
506*4882a593Smuzhiyun 
board_id_show(struct device * device,struct device_attribute * attr,char * buf)507*4882a593Smuzhiyun static ssize_t board_id_show(struct device *device,
508*4882a593Smuzhiyun 			     struct device_attribute *attr, char *buf)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun 	struct hfi1_ibdev *dev =
511*4882a593Smuzhiyun 		rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
512*4882a593Smuzhiyun 	struct hfi1_devdata *dd = dd_from_dev(dev);
513*4882a593Smuzhiyun 	int ret;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	if (!dd->boardname)
516*4882a593Smuzhiyun 		ret = -EINVAL;
517*4882a593Smuzhiyun 	else
518*4882a593Smuzhiyun 		ret = scnprintf(buf, PAGE_SIZE, "%s\n", dd->boardname);
519*4882a593Smuzhiyun 	return ret;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun static DEVICE_ATTR_RO(board_id);
522*4882a593Smuzhiyun 
boardversion_show(struct device * device,struct device_attribute * attr,char * buf)523*4882a593Smuzhiyun static ssize_t boardversion_show(struct device *device,
524*4882a593Smuzhiyun 				 struct device_attribute *attr, char *buf)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun 	struct hfi1_ibdev *dev =
527*4882a593Smuzhiyun 		rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
528*4882a593Smuzhiyun 	struct hfi1_devdata *dd = dd_from_dev(dev);
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	/* The string printed here is already newline-terminated. */
531*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s", dd->boardversion);
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun static DEVICE_ATTR_RO(boardversion);
534*4882a593Smuzhiyun 
nctxts_show(struct device * device,struct device_attribute * attr,char * buf)535*4882a593Smuzhiyun static ssize_t nctxts_show(struct device *device,
536*4882a593Smuzhiyun 			   struct device_attribute *attr, char *buf)
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun 	struct hfi1_ibdev *dev =
539*4882a593Smuzhiyun 		rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
540*4882a593Smuzhiyun 	struct hfi1_devdata *dd = dd_from_dev(dev);
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	/*
543*4882a593Smuzhiyun 	 * Return the smaller of send and receive contexts.
544*4882a593Smuzhiyun 	 * Normally, user level applications would require both a send
545*4882a593Smuzhiyun 	 * and a receive context, so returning the smaller of the two counts
546*4882a593Smuzhiyun 	 * give a more accurate picture of total contexts available.
547*4882a593Smuzhiyun 	 */
548*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%u\n",
549*4882a593Smuzhiyun 			 min(dd->num_user_contexts,
550*4882a593Smuzhiyun 			     (u32)dd->sc_sizes[SC_USER].count));
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun static DEVICE_ATTR_RO(nctxts);
553*4882a593Smuzhiyun 
nfreectxts_show(struct device * device,struct device_attribute * attr,char * buf)554*4882a593Smuzhiyun static ssize_t nfreectxts_show(struct device *device,
555*4882a593Smuzhiyun 			       struct device_attribute *attr, char *buf)
556*4882a593Smuzhiyun {
557*4882a593Smuzhiyun 	struct hfi1_ibdev *dev =
558*4882a593Smuzhiyun 		rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
559*4882a593Smuzhiyun 	struct hfi1_devdata *dd = dd_from_dev(dev);
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	/* Return the number of free user ports (contexts) available. */
562*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts);
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun static DEVICE_ATTR_RO(nfreectxts);
565*4882a593Smuzhiyun 
serial_show(struct device * device,struct device_attribute * attr,char * buf)566*4882a593Smuzhiyun static ssize_t serial_show(struct device *device,
567*4882a593Smuzhiyun 			   struct device_attribute *attr, char *buf)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun 	struct hfi1_ibdev *dev =
570*4882a593Smuzhiyun 		rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
571*4882a593Smuzhiyun 	struct hfi1_devdata *dd = dd_from_dev(dev);
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s", dd->serial);
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun static DEVICE_ATTR_RO(serial);
576*4882a593Smuzhiyun 
chip_reset_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)577*4882a593Smuzhiyun static ssize_t chip_reset_store(struct device *device,
578*4882a593Smuzhiyun 				struct device_attribute *attr, const char *buf,
579*4882a593Smuzhiyun 				size_t count)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun 	struct hfi1_ibdev *dev =
582*4882a593Smuzhiyun 		rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
583*4882a593Smuzhiyun 	struct hfi1_devdata *dd = dd_from_dev(dev);
584*4882a593Smuzhiyun 	int ret;
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun 	if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) {
587*4882a593Smuzhiyun 		ret = -EINVAL;
588*4882a593Smuzhiyun 		goto bail;
589*4882a593Smuzhiyun 	}
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	ret = hfi1_reset_device(dd->unit);
592*4882a593Smuzhiyun bail:
593*4882a593Smuzhiyun 	return ret < 0 ? ret : count;
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun static DEVICE_ATTR_WO(chip_reset);
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun /*
598*4882a593Smuzhiyun  * Convert the reported temperature from an integer (reported in
599*4882a593Smuzhiyun  * units of 0.25C) to a floating point number.
600*4882a593Smuzhiyun  */
601*4882a593Smuzhiyun #define temp2str(temp, buf, size, idx)					\
602*4882a593Smuzhiyun 	scnprintf((buf) + (idx), (size) - (idx), "%u.%02u ",		\
603*4882a593Smuzhiyun 			      ((temp) >> 2), ((temp) & 0x3) * 25)
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun /*
606*4882a593Smuzhiyun  * Dump tempsense values, in decimal, to ease shell-scripts.
607*4882a593Smuzhiyun  */
tempsense_show(struct device * device,struct device_attribute * attr,char * buf)608*4882a593Smuzhiyun static ssize_t tempsense_show(struct device *device,
609*4882a593Smuzhiyun 			      struct device_attribute *attr, char *buf)
610*4882a593Smuzhiyun {
611*4882a593Smuzhiyun 	struct hfi1_ibdev *dev =
612*4882a593Smuzhiyun 		rdma_device_to_drv_device(device, struct hfi1_ibdev, rdi.ibdev);
613*4882a593Smuzhiyun 	struct hfi1_devdata *dd = dd_from_dev(dev);
614*4882a593Smuzhiyun 	struct hfi1_temp temp;
615*4882a593Smuzhiyun 	int ret;
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	ret = hfi1_tempsense_rd(dd, &temp);
618*4882a593Smuzhiyun 	if (!ret) {
619*4882a593Smuzhiyun 		int idx = 0;
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 		idx += temp2str(temp.curr, buf, PAGE_SIZE, idx);
622*4882a593Smuzhiyun 		idx += temp2str(temp.lo_lim, buf, PAGE_SIZE, idx);
623*4882a593Smuzhiyun 		idx += temp2str(temp.hi_lim, buf, PAGE_SIZE, idx);
624*4882a593Smuzhiyun 		idx += temp2str(temp.crit_lim, buf, PAGE_SIZE, idx);
625*4882a593Smuzhiyun 		idx += scnprintf(buf + idx, PAGE_SIZE - idx,
626*4882a593Smuzhiyun 				"%u %u %u\n", temp.triggers & 0x1,
627*4882a593Smuzhiyun 				temp.triggers & 0x2, temp.triggers & 0x4);
628*4882a593Smuzhiyun 		ret = idx;
629*4882a593Smuzhiyun 	}
630*4882a593Smuzhiyun 	return ret;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun static DEVICE_ATTR_RO(tempsense);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun /*
635*4882a593Smuzhiyun  * end of per-unit (or driver, in some cases, but replicated
636*4882a593Smuzhiyun  * per unit) functions
637*4882a593Smuzhiyun  */
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun /* start of per-unit file structures and support code */
640*4882a593Smuzhiyun static struct attribute *hfi1_attributes[] = {
641*4882a593Smuzhiyun 	&dev_attr_hw_rev.attr,
642*4882a593Smuzhiyun 	&dev_attr_board_id.attr,
643*4882a593Smuzhiyun 	&dev_attr_nctxts.attr,
644*4882a593Smuzhiyun 	&dev_attr_nfreectxts.attr,
645*4882a593Smuzhiyun 	&dev_attr_serial.attr,
646*4882a593Smuzhiyun 	&dev_attr_boardversion.attr,
647*4882a593Smuzhiyun 	&dev_attr_tempsense.attr,
648*4882a593Smuzhiyun 	&dev_attr_chip_reset.attr,
649*4882a593Smuzhiyun 	NULL,
650*4882a593Smuzhiyun };
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun const struct attribute_group ib_hfi1_attr_group = {
653*4882a593Smuzhiyun 	.attrs = hfi1_attributes,
654*4882a593Smuzhiyun };
655*4882a593Smuzhiyun 
hfi1_create_port_files(struct ib_device * ibdev,u8 port_num,struct kobject * kobj)656*4882a593Smuzhiyun int hfi1_create_port_files(struct ib_device *ibdev, u8 port_num,
657*4882a593Smuzhiyun 			   struct kobject *kobj)
658*4882a593Smuzhiyun {
659*4882a593Smuzhiyun 	struct hfi1_pportdata *ppd;
660*4882a593Smuzhiyun 	struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
661*4882a593Smuzhiyun 	int ret;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 	if (!port_num || port_num > dd->num_pports) {
664*4882a593Smuzhiyun 		dd_dev_err(dd,
665*4882a593Smuzhiyun 			   "Skipping infiniband class with invalid port %u\n",
666*4882a593Smuzhiyun 			   port_num);
667*4882a593Smuzhiyun 		return -ENODEV;
668*4882a593Smuzhiyun 	}
669*4882a593Smuzhiyun 	ppd = &dd->pport[port_num - 1];
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 	ret = kobject_init_and_add(&ppd->sc2vl_kobj, &hfi1_sc2vl_ktype, kobj,
672*4882a593Smuzhiyun 				   "sc2vl");
673*4882a593Smuzhiyun 	if (ret) {
674*4882a593Smuzhiyun 		dd_dev_err(dd,
675*4882a593Smuzhiyun 			   "Skipping sc2vl sysfs info, (err %d) port %u\n",
676*4882a593Smuzhiyun 			   ret, port_num);
677*4882a593Smuzhiyun 		/*
678*4882a593Smuzhiyun 		 * Based on the documentation for kobject_init_and_add(), the
679*4882a593Smuzhiyun 		 * caller should call kobject_put even if this call fails.
680*4882a593Smuzhiyun 		 */
681*4882a593Smuzhiyun 		goto bail_sc2vl;
682*4882a593Smuzhiyun 	}
683*4882a593Smuzhiyun 	kobject_uevent(&ppd->sc2vl_kobj, KOBJ_ADD);
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	ret = kobject_init_and_add(&ppd->sl2sc_kobj, &hfi1_sl2sc_ktype, kobj,
686*4882a593Smuzhiyun 				   "sl2sc");
687*4882a593Smuzhiyun 	if (ret) {
688*4882a593Smuzhiyun 		dd_dev_err(dd,
689*4882a593Smuzhiyun 			   "Skipping sl2sc sysfs info, (err %d) port %u\n",
690*4882a593Smuzhiyun 			   ret, port_num);
691*4882a593Smuzhiyun 		goto bail_sl2sc;
692*4882a593Smuzhiyun 	}
693*4882a593Smuzhiyun 	kobject_uevent(&ppd->sl2sc_kobj, KOBJ_ADD);
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	ret = kobject_init_and_add(&ppd->vl2mtu_kobj, &hfi1_vl2mtu_ktype, kobj,
696*4882a593Smuzhiyun 				   "vl2mtu");
697*4882a593Smuzhiyun 	if (ret) {
698*4882a593Smuzhiyun 		dd_dev_err(dd,
699*4882a593Smuzhiyun 			   "Skipping vl2mtu sysfs info, (err %d) port %u\n",
700*4882a593Smuzhiyun 			   ret, port_num);
701*4882a593Smuzhiyun 		goto bail_vl2mtu;
702*4882a593Smuzhiyun 	}
703*4882a593Smuzhiyun 	kobject_uevent(&ppd->vl2mtu_kobj, KOBJ_ADD);
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 	ret = kobject_init_and_add(&ppd->pport_cc_kobj, &port_cc_ktype,
706*4882a593Smuzhiyun 				   kobj, "CCMgtA");
707*4882a593Smuzhiyun 	if (ret) {
708*4882a593Smuzhiyun 		dd_dev_err(dd,
709*4882a593Smuzhiyun 			   "Skipping Congestion Control sysfs info, (err %d) port %u\n",
710*4882a593Smuzhiyun 			   ret, port_num);
711*4882a593Smuzhiyun 		goto bail_cc;
712*4882a593Smuzhiyun 	}
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD);
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, &cc_setting_bin_attr);
717*4882a593Smuzhiyun 	if (ret) {
718*4882a593Smuzhiyun 		dd_dev_err(dd,
719*4882a593Smuzhiyun 			   "Skipping Congestion Control setting sysfs info, (err %d) port %u\n",
720*4882a593Smuzhiyun 			   ret, port_num);
721*4882a593Smuzhiyun 		goto bail_cc;
722*4882a593Smuzhiyun 	}
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, &cc_table_bin_attr);
725*4882a593Smuzhiyun 	if (ret) {
726*4882a593Smuzhiyun 		dd_dev_err(dd,
727*4882a593Smuzhiyun 			   "Skipping Congestion Control table sysfs info, (err %d) port %u\n",
728*4882a593Smuzhiyun 			   ret, port_num);
729*4882a593Smuzhiyun 		goto bail_cc_entry_bin;
730*4882a593Smuzhiyun 	}
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 	dd_dev_info(dd,
733*4882a593Smuzhiyun 		    "Congestion Control Agent enabled for port %d\n",
734*4882a593Smuzhiyun 		    port_num);
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	return 0;
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun bail_cc_entry_bin:
739*4882a593Smuzhiyun 	sysfs_remove_bin_file(&ppd->pport_cc_kobj,
740*4882a593Smuzhiyun 			      &cc_setting_bin_attr);
741*4882a593Smuzhiyun bail_cc:
742*4882a593Smuzhiyun 	kobject_put(&ppd->pport_cc_kobj);
743*4882a593Smuzhiyun bail_vl2mtu:
744*4882a593Smuzhiyun 	kobject_put(&ppd->vl2mtu_kobj);
745*4882a593Smuzhiyun bail_sl2sc:
746*4882a593Smuzhiyun 	kobject_put(&ppd->sl2sc_kobj);
747*4882a593Smuzhiyun bail_sc2vl:
748*4882a593Smuzhiyun 	kobject_put(&ppd->sc2vl_kobj);
749*4882a593Smuzhiyun 	return ret;
750*4882a593Smuzhiyun }
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun struct sde_attribute {
753*4882a593Smuzhiyun 	struct attribute attr;
754*4882a593Smuzhiyun 	ssize_t (*show)(struct sdma_engine *sde, char *buf);
755*4882a593Smuzhiyun 	ssize_t (*store)(struct sdma_engine *sde, const char *buf, size_t cnt);
756*4882a593Smuzhiyun };
757*4882a593Smuzhiyun 
sde_show(struct kobject * kobj,struct attribute * attr,char * buf)758*4882a593Smuzhiyun static ssize_t sde_show(struct kobject *kobj, struct attribute *attr, char *buf)
759*4882a593Smuzhiyun {
760*4882a593Smuzhiyun 	struct sde_attribute *sde_attr =
761*4882a593Smuzhiyun 		container_of(attr, struct sde_attribute, attr);
762*4882a593Smuzhiyun 	struct sdma_engine *sde =
763*4882a593Smuzhiyun 		container_of(kobj, struct sdma_engine, kobj);
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	if (!sde_attr->show)
766*4882a593Smuzhiyun 		return -EINVAL;
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	return sde_attr->show(sde, buf);
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun 
sde_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t count)771*4882a593Smuzhiyun static ssize_t sde_store(struct kobject *kobj, struct attribute *attr,
772*4882a593Smuzhiyun 			 const char *buf, size_t count)
773*4882a593Smuzhiyun {
774*4882a593Smuzhiyun 	struct sde_attribute *sde_attr =
775*4882a593Smuzhiyun 		container_of(attr, struct sde_attribute, attr);
776*4882a593Smuzhiyun 	struct sdma_engine *sde =
777*4882a593Smuzhiyun 		container_of(kobj, struct sdma_engine, kobj);
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	if (!capable(CAP_SYS_ADMIN))
780*4882a593Smuzhiyun 		return -EPERM;
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun 	if (!sde_attr->store)
783*4882a593Smuzhiyun 		return -EINVAL;
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 	return sde_attr->store(sde, buf, count);
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun static const struct sysfs_ops sde_sysfs_ops = {
789*4882a593Smuzhiyun 	.show = sde_show,
790*4882a593Smuzhiyun 	.store = sde_store,
791*4882a593Smuzhiyun };
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun static struct kobj_type sde_ktype = {
794*4882a593Smuzhiyun 	.sysfs_ops = &sde_sysfs_ops,
795*4882a593Smuzhiyun };
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun #define SDE_ATTR(_name, _mode, _show, _store) \
798*4882a593Smuzhiyun 	struct sde_attribute sde_attr_##_name = \
799*4882a593Smuzhiyun 		__ATTR(_name, _mode, _show, _store)
800*4882a593Smuzhiyun 
sde_show_cpu_to_sde_map(struct sdma_engine * sde,char * buf)801*4882a593Smuzhiyun static ssize_t sde_show_cpu_to_sde_map(struct sdma_engine *sde, char *buf)
802*4882a593Smuzhiyun {
803*4882a593Smuzhiyun 	return sdma_get_cpu_to_sde_map(sde, buf);
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun 
sde_store_cpu_to_sde_map(struct sdma_engine * sde,const char * buf,size_t count)806*4882a593Smuzhiyun static ssize_t sde_store_cpu_to_sde_map(struct sdma_engine *sde,
807*4882a593Smuzhiyun 					const char *buf, size_t count)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun 	return sdma_set_cpu_to_sde_map(sde, buf, count);
810*4882a593Smuzhiyun }
811*4882a593Smuzhiyun 
sde_show_vl(struct sdma_engine * sde,char * buf)812*4882a593Smuzhiyun static ssize_t sde_show_vl(struct sdma_engine *sde, char *buf)
813*4882a593Smuzhiyun {
814*4882a593Smuzhiyun 	int vl;
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun 	vl = sdma_engine_get_vl(sde);
817*4882a593Smuzhiyun 	if (vl < 0)
818*4882a593Smuzhiyun 		return vl;
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%d\n", vl);
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun static SDE_ATTR(cpu_list, S_IWUSR | S_IRUGO,
824*4882a593Smuzhiyun 		sde_show_cpu_to_sde_map,
825*4882a593Smuzhiyun 		sde_store_cpu_to_sde_map);
826*4882a593Smuzhiyun static SDE_ATTR(vl, S_IRUGO, sde_show_vl, NULL);
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun static struct sde_attribute *sde_attribs[] = {
829*4882a593Smuzhiyun 	&sde_attr_cpu_list,
830*4882a593Smuzhiyun 	&sde_attr_vl
831*4882a593Smuzhiyun };
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun /*
834*4882a593Smuzhiyun  * Register and create our files in /sys/class/infiniband.
835*4882a593Smuzhiyun  */
hfi1_verbs_register_sysfs(struct hfi1_devdata * dd)836*4882a593Smuzhiyun int hfi1_verbs_register_sysfs(struct hfi1_devdata *dd)
837*4882a593Smuzhiyun {
838*4882a593Smuzhiyun 	struct ib_device *dev = &dd->verbs_dev.rdi.ibdev;
839*4882a593Smuzhiyun 	struct device *class_dev = &dev->dev;
840*4882a593Smuzhiyun 	int i, j, ret;
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	for (i = 0; i < dd->num_sdma; i++) {
843*4882a593Smuzhiyun 		ret = kobject_init_and_add(&dd->per_sdma[i].kobj,
844*4882a593Smuzhiyun 					   &sde_ktype, &class_dev->kobj,
845*4882a593Smuzhiyun 					   "sdma%d", i);
846*4882a593Smuzhiyun 		if (ret)
847*4882a593Smuzhiyun 			goto bail;
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun 		for (j = 0; j < ARRAY_SIZE(sde_attribs); j++) {
850*4882a593Smuzhiyun 			ret = sysfs_create_file(&dd->per_sdma[i].kobj,
851*4882a593Smuzhiyun 						&sde_attribs[j]->attr);
852*4882a593Smuzhiyun 			if (ret)
853*4882a593Smuzhiyun 				goto bail;
854*4882a593Smuzhiyun 		}
855*4882a593Smuzhiyun 	}
856*4882a593Smuzhiyun 
857*4882a593Smuzhiyun 	return 0;
858*4882a593Smuzhiyun bail:
859*4882a593Smuzhiyun 	/*
860*4882a593Smuzhiyun 	 * The function kobject_put() will call kobject_del() if the kobject
861*4882a593Smuzhiyun 	 * has been added successfully. The sysfs files created under the
862*4882a593Smuzhiyun 	 * kobject directory will also be removed during the process.
863*4882a593Smuzhiyun 	 */
864*4882a593Smuzhiyun 	for (; i >= 0; i--)
865*4882a593Smuzhiyun 		kobject_put(&dd->per_sdma[i].kobj);
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun 	return ret;
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun /*
871*4882a593Smuzhiyun  * Unregister and remove our files in /sys/class/infiniband.
872*4882a593Smuzhiyun  */
hfi1_verbs_unregister_sysfs(struct hfi1_devdata * dd)873*4882a593Smuzhiyun void hfi1_verbs_unregister_sysfs(struct hfi1_devdata *dd)
874*4882a593Smuzhiyun {
875*4882a593Smuzhiyun 	struct hfi1_pportdata *ppd;
876*4882a593Smuzhiyun 	int i;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	/* Unwind operations in hfi1_verbs_register_sysfs() */
879*4882a593Smuzhiyun 	for (i = 0; i < dd->num_sdma; i++)
880*4882a593Smuzhiyun 		kobject_put(&dd->per_sdma[i].kobj);
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun 	for (i = 0; i < dd->num_pports; i++) {
883*4882a593Smuzhiyun 		ppd = &dd->pport[i];
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun 		sysfs_remove_bin_file(&ppd->pport_cc_kobj,
886*4882a593Smuzhiyun 				      &cc_setting_bin_attr);
887*4882a593Smuzhiyun 		sysfs_remove_bin_file(&ppd->pport_cc_kobj,
888*4882a593Smuzhiyun 				      &cc_table_bin_attr);
889*4882a593Smuzhiyun 		kobject_put(&ppd->pport_cc_kobj);
890*4882a593Smuzhiyun 		kobject_put(&ppd->vl2mtu_kobj);
891*4882a593Smuzhiyun 		kobject_put(&ppd->sl2sc_kobj);
892*4882a593Smuzhiyun 		kobject_put(&ppd->sc2vl_kobj);
893*4882a593Smuzhiyun 	}
894*4882a593Smuzhiyun }
895