xref: /openbmc/linux/drivers/infiniband/hw/qib/qib_sysfs.c (revision f931551bafe1f10ded7f5282e2aa162c267a2e5d)
1*f931551bSRalph Campbell /*
2*f931551bSRalph Campbell  * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved.
3*f931551bSRalph Campbell  * Copyright (c) 2006 PathScale, Inc. All rights reserved.
4*f931551bSRalph Campbell  *
5*f931551bSRalph Campbell  * This software is available to you under a choice of one of two
6*f931551bSRalph Campbell  * licenses.  You may choose to be licensed under the terms of the GNU
7*f931551bSRalph Campbell  * General Public License (GPL) Version 2, available from the file
8*f931551bSRalph Campbell  * COPYING in the main directory of this source tree, or the
9*f931551bSRalph Campbell  * OpenIB.org BSD license below:
10*f931551bSRalph Campbell  *
11*f931551bSRalph Campbell  *     Redistribution and use in source and binary forms, with or
12*f931551bSRalph Campbell  *     without modification, are permitted provided that the following
13*f931551bSRalph Campbell  *     conditions are met:
14*f931551bSRalph Campbell  *
15*f931551bSRalph Campbell  *      - Redistributions of source code must retain the above
16*f931551bSRalph Campbell  *        copyright notice, this list of conditions and the following
17*f931551bSRalph Campbell  *        disclaimer.
18*f931551bSRalph Campbell  *
19*f931551bSRalph Campbell  *      - Redistributions in binary form must reproduce the above
20*f931551bSRalph Campbell  *        copyright notice, this list of conditions and the following
21*f931551bSRalph Campbell  *        disclaimer in the documentation and/or other materials
22*f931551bSRalph Campbell  *        provided with the distribution.
23*f931551bSRalph Campbell  *
24*f931551bSRalph Campbell  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25*f931551bSRalph Campbell  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26*f931551bSRalph Campbell  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27*f931551bSRalph Campbell  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28*f931551bSRalph Campbell  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29*f931551bSRalph Campbell  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30*f931551bSRalph Campbell  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31*f931551bSRalph Campbell  * SOFTWARE.
32*f931551bSRalph Campbell  */
33*f931551bSRalph Campbell #include <linux/ctype.h>
34*f931551bSRalph Campbell 
35*f931551bSRalph Campbell #include "qib.h"
36*f931551bSRalph Campbell 
37*f931551bSRalph Campbell /**
38*f931551bSRalph Campbell  * qib_parse_ushort - parse an unsigned short value in an arbitrary base
39*f931551bSRalph Campbell  * @str: the string containing the number
40*f931551bSRalph Campbell  * @valp: where to put the result
41*f931551bSRalph Campbell  *
42*f931551bSRalph Campbell  * Returns the number of bytes consumed, or negative value on error.
43*f931551bSRalph Campbell  */
44*f931551bSRalph Campbell static int qib_parse_ushort(const char *str, unsigned short *valp)
45*f931551bSRalph Campbell {
46*f931551bSRalph Campbell 	unsigned long val;
47*f931551bSRalph Campbell 	char *end;
48*f931551bSRalph Campbell 	int ret;
49*f931551bSRalph Campbell 
50*f931551bSRalph Campbell 	if (!isdigit(str[0])) {
51*f931551bSRalph Campbell 		ret = -EINVAL;
52*f931551bSRalph Campbell 		goto bail;
53*f931551bSRalph Campbell 	}
54*f931551bSRalph Campbell 
55*f931551bSRalph Campbell 	val = simple_strtoul(str, &end, 0);
56*f931551bSRalph Campbell 
57*f931551bSRalph Campbell 	if (val > 0xffff) {
58*f931551bSRalph Campbell 		ret = -EINVAL;
59*f931551bSRalph Campbell 		goto bail;
60*f931551bSRalph Campbell 	}
61*f931551bSRalph Campbell 
62*f931551bSRalph Campbell 	*valp = val;
63*f931551bSRalph Campbell 
64*f931551bSRalph Campbell 	ret = end + 1 - str;
65*f931551bSRalph Campbell 	if (ret == 0)
66*f931551bSRalph Campbell 		ret = -EINVAL;
67*f931551bSRalph Campbell 
68*f931551bSRalph Campbell bail:
69*f931551bSRalph Campbell 	return ret;
70*f931551bSRalph Campbell }
71*f931551bSRalph Campbell 
72*f931551bSRalph Campbell /* start of per-port functions */
73*f931551bSRalph Campbell /*
74*f931551bSRalph Campbell  * Get/Set heartbeat enable. OR of 1=enabled, 2=auto
75*f931551bSRalph Campbell  */
76*f931551bSRalph Campbell static ssize_t show_hrtbt_enb(struct qib_pportdata *ppd, char *buf)
77*f931551bSRalph Campbell {
78*f931551bSRalph Campbell 	struct qib_devdata *dd = ppd->dd;
79*f931551bSRalph Campbell 	int ret;
80*f931551bSRalph Campbell 
81*f931551bSRalph Campbell 	ret = dd->f_get_ib_cfg(ppd, QIB_IB_CFG_HRTBT);
82*f931551bSRalph Campbell 	ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
83*f931551bSRalph Campbell 	return ret;
84*f931551bSRalph Campbell }
85*f931551bSRalph Campbell 
86*f931551bSRalph Campbell static ssize_t store_hrtbt_enb(struct qib_pportdata *ppd, const char *buf,
87*f931551bSRalph Campbell 			       size_t count)
88*f931551bSRalph Campbell {
89*f931551bSRalph Campbell 	struct qib_devdata *dd = ppd->dd;
90*f931551bSRalph Campbell 	int ret;
91*f931551bSRalph Campbell 	u16 val;
92*f931551bSRalph Campbell 
93*f931551bSRalph Campbell 	ret = qib_parse_ushort(buf, &val);
94*f931551bSRalph Campbell 
95*f931551bSRalph Campbell 	/*
96*f931551bSRalph Campbell 	 * Set the "intentional" heartbeat enable per either of
97*f931551bSRalph Campbell 	 * "Enable" and "Auto", as these are normally set together.
98*f931551bSRalph Campbell 	 * This bit is consulted when leaving loopback mode,
99*f931551bSRalph Campbell 	 * because entering loopback mode overrides it and automatically
100*f931551bSRalph Campbell 	 * disables heartbeat.
101*f931551bSRalph Campbell 	 */
102*f931551bSRalph Campbell 	if (ret >= 0)
103*f931551bSRalph Campbell 		ret = dd->f_set_ib_cfg(ppd, QIB_IB_CFG_HRTBT, val);
104*f931551bSRalph Campbell 	if (ret < 0)
105*f931551bSRalph Campbell 		qib_dev_err(dd, "attempt to set invalid Heartbeat enable\n");
106*f931551bSRalph Campbell 	return ret < 0 ? ret : count;
107*f931551bSRalph Campbell }
108*f931551bSRalph Campbell 
109*f931551bSRalph Campbell static ssize_t store_loopback(struct qib_pportdata *ppd, const char *buf,
110*f931551bSRalph Campbell 			      size_t count)
111*f931551bSRalph Campbell {
112*f931551bSRalph Campbell 	struct qib_devdata *dd = ppd->dd;
113*f931551bSRalph Campbell 	int ret = count, r;
114*f931551bSRalph Campbell 
115*f931551bSRalph Campbell 	r = dd->f_set_ib_loopback(ppd, buf);
116*f931551bSRalph Campbell 	if (r < 0)
117*f931551bSRalph Campbell 		ret = r;
118*f931551bSRalph Campbell 
119*f931551bSRalph Campbell 	return ret;
120*f931551bSRalph Campbell }
121*f931551bSRalph Campbell 
122*f931551bSRalph Campbell static ssize_t store_led_override(struct qib_pportdata *ppd, const char *buf,
123*f931551bSRalph Campbell 				  size_t count)
124*f931551bSRalph Campbell {
125*f931551bSRalph Campbell 	struct qib_devdata *dd = ppd->dd;
126*f931551bSRalph Campbell 	int ret;
127*f931551bSRalph Campbell 	u16 val;
128*f931551bSRalph Campbell 
129*f931551bSRalph Campbell 	ret = qib_parse_ushort(buf, &val);
130*f931551bSRalph Campbell 	if (ret > 0)
131*f931551bSRalph Campbell 		qib_set_led_override(ppd, val);
132*f931551bSRalph Campbell 	else
133*f931551bSRalph Campbell 		qib_dev_err(dd, "attempt to set invalid LED override\n");
134*f931551bSRalph Campbell 	return ret < 0 ? ret : count;
135*f931551bSRalph Campbell }
136*f931551bSRalph Campbell 
137*f931551bSRalph Campbell static ssize_t show_status(struct qib_pportdata *ppd, char *buf)
138*f931551bSRalph Campbell {
139*f931551bSRalph Campbell 	ssize_t ret;
140*f931551bSRalph Campbell 
141*f931551bSRalph Campbell 	if (!ppd->statusp)
142*f931551bSRalph Campbell 		ret = -EINVAL;
143*f931551bSRalph Campbell 	else
144*f931551bSRalph Campbell 		ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n",
145*f931551bSRalph Campbell 				(unsigned long long) *(ppd->statusp));
146*f931551bSRalph Campbell 	return ret;
147*f931551bSRalph Campbell }
148*f931551bSRalph Campbell 
149*f931551bSRalph Campbell /*
150*f931551bSRalph Campbell  * For userland compatibility, these offsets must remain fixed.
151*f931551bSRalph Campbell  * They are strings for QIB_STATUS_*
152*f931551bSRalph Campbell  */
153*f931551bSRalph Campbell static const char *qib_status_str[] = {
154*f931551bSRalph Campbell 	"Initted",
155*f931551bSRalph Campbell 	"",
156*f931551bSRalph Campbell 	"",
157*f931551bSRalph Campbell 	"",
158*f931551bSRalph Campbell 	"",
159*f931551bSRalph Campbell 	"Present",
160*f931551bSRalph Campbell 	"IB_link_up",
161*f931551bSRalph Campbell 	"IB_configured",
162*f931551bSRalph Campbell 	"",
163*f931551bSRalph Campbell 	"Fatal_Hardware_Error",
164*f931551bSRalph Campbell 	NULL,
165*f931551bSRalph Campbell };
166*f931551bSRalph Campbell 
167*f931551bSRalph Campbell static ssize_t show_status_str(struct qib_pportdata *ppd, char *buf)
168*f931551bSRalph Campbell {
169*f931551bSRalph Campbell 	int i, any;
170*f931551bSRalph Campbell 	u64 s;
171*f931551bSRalph Campbell 	ssize_t ret;
172*f931551bSRalph Campbell 
173*f931551bSRalph Campbell 	if (!ppd->statusp) {
174*f931551bSRalph Campbell 		ret = -EINVAL;
175*f931551bSRalph Campbell 		goto bail;
176*f931551bSRalph Campbell 	}
177*f931551bSRalph Campbell 
178*f931551bSRalph Campbell 	s = *(ppd->statusp);
179*f931551bSRalph Campbell 	*buf = '\0';
180*f931551bSRalph Campbell 	for (any = i = 0; s && qib_status_str[i]; i++) {
181*f931551bSRalph Campbell 		if (s & 1) {
182*f931551bSRalph Campbell 			/* if overflow */
183*f931551bSRalph Campbell 			if (any && strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE)
184*f931551bSRalph Campbell 				break;
185*f931551bSRalph Campbell 			if (strlcat(buf, qib_status_str[i], PAGE_SIZE) >=
186*f931551bSRalph Campbell 					PAGE_SIZE)
187*f931551bSRalph Campbell 				break;
188*f931551bSRalph Campbell 			any = 1;
189*f931551bSRalph Campbell 		}
190*f931551bSRalph Campbell 		s >>= 1;
191*f931551bSRalph Campbell 	}
192*f931551bSRalph Campbell 	if (any)
193*f931551bSRalph Campbell 		strlcat(buf, "\n", PAGE_SIZE);
194*f931551bSRalph Campbell 
195*f931551bSRalph Campbell 	ret = strlen(buf);
196*f931551bSRalph Campbell 
197*f931551bSRalph Campbell bail:
198*f931551bSRalph Campbell 	return ret;
199*f931551bSRalph Campbell }
200*f931551bSRalph Campbell 
201*f931551bSRalph Campbell /* end of per-port functions */
202*f931551bSRalph Campbell 
203*f931551bSRalph Campbell /*
204*f931551bSRalph Campbell  * Start of per-port file structures and support code
205*f931551bSRalph Campbell  * Because we are fitting into other infrastructure, we have to supply the
206*f931551bSRalph Campbell  * full set of kobject/sysfs_ops structures and routines.
207*f931551bSRalph Campbell  */
208*f931551bSRalph Campbell #define QIB_PORT_ATTR(name, mode, show, store) \
209*f931551bSRalph Campbell 	static struct qib_port_attr qib_port_attr_##name = \
210*f931551bSRalph Campbell 		__ATTR(name, mode, show, store)
211*f931551bSRalph Campbell 
212*f931551bSRalph Campbell struct qib_port_attr {
213*f931551bSRalph Campbell 	struct attribute attr;
214*f931551bSRalph Campbell 	ssize_t (*show)(struct qib_pportdata *, char *);
215*f931551bSRalph Campbell 	ssize_t (*store)(struct qib_pportdata *, const char *, size_t);
216*f931551bSRalph Campbell };
217*f931551bSRalph Campbell 
218*f931551bSRalph Campbell QIB_PORT_ATTR(loopback, S_IWUSR, NULL, store_loopback);
219*f931551bSRalph Campbell QIB_PORT_ATTR(led_override, S_IWUSR, NULL, store_led_override);
220*f931551bSRalph Campbell QIB_PORT_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb,
221*f931551bSRalph Campbell 	      store_hrtbt_enb);
222*f931551bSRalph Campbell QIB_PORT_ATTR(status, S_IRUGO, show_status, NULL);
223*f931551bSRalph Campbell QIB_PORT_ATTR(status_str, S_IRUGO, show_status_str, NULL);
224*f931551bSRalph Campbell 
225*f931551bSRalph Campbell static struct attribute *port_default_attributes[] = {
226*f931551bSRalph Campbell 	&qib_port_attr_loopback.attr,
227*f931551bSRalph Campbell 	&qib_port_attr_led_override.attr,
228*f931551bSRalph Campbell 	&qib_port_attr_hrtbt_enable.attr,
229*f931551bSRalph Campbell 	&qib_port_attr_status.attr,
230*f931551bSRalph Campbell 	&qib_port_attr_status_str.attr,
231*f931551bSRalph Campbell 	NULL
232*f931551bSRalph Campbell };
233*f931551bSRalph Campbell 
234*f931551bSRalph Campbell static ssize_t qib_portattr_show(struct kobject *kobj,
235*f931551bSRalph Campbell 	struct attribute *attr, char *buf)
236*f931551bSRalph Campbell {
237*f931551bSRalph Campbell 	struct qib_port_attr *pattr =
238*f931551bSRalph Campbell 		container_of(attr, struct qib_port_attr, attr);
239*f931551bSRalph Campbell 	struct qib_pportdata *ppd =
240*f931551bSRalph Campbell 		container_of(kobj, struct qib_pportdata, pport_kobj);
241*f931551bSRalph Campbell 
242*f931551bSRalph Campbell 	return pattr->show(ppd, buf);
243*f931551bSRalph Campbell }
244*f931551bSRalph Campbell 
245*f931551bSRalph Campbell static ssize_t qib_portattr_store(struct kobject *kobj,
246*f931551bSRalph Campbell 	struct attribute *attr, const char *buf, size_t len)
247*f931551bSRalph Campbell {
248*f931551bSRalph Campbell 	struct qib_port_attr *pattr =
249*f931551bSRalph Campbell 		container_of(attr, struct qib_port_attr, attr);
250*f931551bSRalph Campbell 	struct qib_pportdata *ppd =
251*f931551bSRalph Campbell 		container_of(kobj, struct qib_pportdata, pport_kobj);
252*f931551bSRalph Campbell 
253*f931551bSRalph Campbell 	return pattr->store(ppd, buf, len);
254*f931551bSRalph Campbell }
255*f931551bSRalph Campbell 
256*f931551bSRalph Campbell static void qib_port_release(struct kobject *kobj)
257*f931551bSRalph Campbell {
258*f931551bSRalph Campbell 	/* nothing to do since memory is freed by qib_free_devdata() */
259*f931551bSRalph Campbell }
260*f931551bSRalph Campbell 
261*f931551bSRalph Campbell static const struct sysfs_ops qib_port_ops = {
262*f931551bSRalph Campbell 	.show = qib_portattr_show,
263*f931551bSRalph Campbell 	.store = qib_portattr_store,
264*f931551bSRalph Campbell };
265*f931551bSRalph Campbell 
266*f931551bSRalph Campbell static struct kobj_type qib_port_ktype = {
267*f931551bSRalph Campbell 	.release = qib_port_release,
268*f931551bSRalph Campbell 	.sysfs_ops = &qib_port_ops,
269*f931551bSRalph Campbell 	.default_attrs = port_default_attributes
270*f931551bSRalph Campbell };
271*f931551bSRalph Campbell 
272*f931551bSRalph Campbell /* Start sl2vl */
273*f931551bSRalph Campbell 
274*f931551bSRalph Campbell #define QIB_SL2VL_ATTR(N) \
275*f931551bSRalph Campbell 	static struct qib_sl2vl_attr qib_sl2vl_attr_##N = { \
276*f931551bSRalph Campbell 		.attr = { .name = __stringify(N), .mode = 0444 }, \
277*f931551bSRalph Campbell 		.sl = N \
278*f931551bSRalph Campbell 	}
279*f931551bSRalph Campbell 
280*f931551bSRalph Campbell struct qib_sl2vl_attr {
281*f931551bSRalph Campbell 	struct attribute attr;
282*f931551bSRalph Campbell 	int sl;
283*f931551bSRalph Campbell };
284*f931551bSRalph Campbell 
285*f931551bSRalph Campbell QIB_SL2VL_ATTR(0);
286*f931551bSRalph Campbell QIB_SL2VL_ATTR(1);
287*f931551bSRalph Campbell QIB_SL2VL_ATTR(2);
288*f931551bSRalph Campbell QIB_SL2VL_ATTR(3);
289*f931551bSRalph Campbell QIB_SL2VL_ATTR(4);
290*f931551bSRalph Campbell QIB_SL2VL_ATTR(5);
291*f931551bSRalph Campbell QIB_SL2VL_ATTR(6);
292*f931551bSRalph Campbell QIB_SL2VL_ATTR(7);
293*f931551bSRalph Campbell QIB_SL2VL_ATTR(8);
294*f931551bSRalph Campbell QIB_SL2VL_ATTR(9);
295*f931551bSRalph Campbell QIB_SL2VL_ATTR(10);
296*f931551bSRalph Campbell QIB_SL2VL_ATTR(11);
297*f931551bSRalph Campbell QIB_SL2VL_ATTR(12);
298*f931551bSRalph Campbell QIB_SL2VL_ATTR(13);
299*f931551bSRalph Campbell QIB_SL2VL_ATTR(14);
300*f931551bSRalph Campbell QIB_SL2VL_ATTR(15);
301*f931551bSRalph Campbell 
302*f931551bSRalph Campbell static struct attribute *sl2vl_default_attributes[] = {
303*f931551bSRalph Campbell 	&qib_sl2vl_attr_0.attr,
304*f931551bSRalph Campbell 	&qib_sl2vl_attr_1.attr,
305*f931551bSRalph Campbell 	&qib_sl2vl_attr_2.attr,
306*f931551bSRalph Campbell 	&qib_sl2vl_attr_3.attr,
307*f931551bSRalph Campbell 	&qib_sl2vl_attr_4.attr,
308*f931551bSRalph Campbell 	&qib_sl2vl_attr_5.attr,
309*f931551bSRalph Campbell 	&qib_sl2vl_attr_6.attr,
310*f931551bSRalph Campbell 	&qib_sl2vl_attr_7.attr,
311*f931551bSRalph Campbell 	&qib_sl2vl_attr_8.attr,
312*f931551bSRalph Campbell 	&qib_sl2vl_attr_9.attr,
313*f931551bSRalph Campbell 	&qib_sl2vl_attr_10.attr,
314*f931551bSRalph Campbell 	&qib_sl2vl_attr_11.attr,
315*f931551bSRalph Campbell 	&qib_sl2vl_attr_12.attr,
316*f931551bSRalph Campbell 	&qib_sl2vl_attr_13.attr,
317*f931551bSRalph Campbell 	&qib_sl2vl_attr_14.attr,
318*f931551bSRalph Campbell 	&qib_sl2vl_attr_15.attr,
319*f931551bSRalph Campbell 	NULL
320*f931551bSRalph Campbell };
321*f931551bSRalph Campbell 
322*f931551bSRalph Campbell static ssize_t sl2vl_attr_show(struct kobject *kobj, struct attribute *attr,
323*f931551bSRalph Campbell 			       char *buf)
324*f931551bSRalph Campbell {
325*f931551bSRalph Campbell 	struct qib_sl2vl_attr *sattr =
326*f931551bSRalph Campbell 		container_of(attr, struct qib_sl2vl_attr, attr);
327*f931551bSRalph Campbell 	struct qib_pportdata *ppd =
328*f931551bSRalph Campbell 		container_of(kobj, struct qib_pportdata, sl2vl_kobj);
329*f931551bSRalph Campbell 	struct qib_ibport *qibp = &ppd->ibport_data;
330*f931551bSRalph Campbell 
331*f931551bSRalph Campbell 	return sprintf(buf, "%u\n", qibp->sl_to_vl[sattr->sl]);
332*f931551bSRalph Campbell }
333*f931551bSRalph Campbell 
334*f931551bSRalph Campbell static const struct sysfs_ops qib_sl2vl_ops = {
335*f931551bSRalph Campbell 	.show = sl2vl_attr_show,
336*f931551bSRalph Campbell };
337*f931551bSRalph Campbell 
338*f931551bSRalph Campbell static struct kobj_type qib_sl2vl_ktype = {
339*f931551bSRalph Campbell 	.release = qib_port_release,
340*f931551bSRalph Campbell 	.sysfs_ops = &qib_sl2vl_ops,
341*f931551bSRalph Campbell 	.default_attrs = sl2vl_default_attributes
342*f931551bSRalph Campbell };
343*f931551bSRalph Campbell 
344*f931551bSRalph Campbell /* End sl2vl */
345*f931551bSRalph Campbell 
346*f931551bSRalph Campbell /* Start diag_counters */
347*f931551bSRalph Campbell 
348*f931551bSRalph Campbell #define QIB_DIAGC_ATTR(N) \
349*f931551bSRalph Campbell 	static struct qib_diagc_attr qib_diagc_attr_##N = { \
350*f931551bSRalph Campbell 		.attr = { .name = __stringify(N), .mode = 0444 }, \
351*f931551bSRalph Campbell 		.counter = offsetof(struct qib_ibport, n_##N) \
352*f931551bSRalph Campbell 	}
353*f931551bSRalph Campbell 
354*f931551bSRalph Campbell struct qib_diagc_attr {
355*f931551bSRalph Campbell 	struct attribute attr;
356*f931551bSRalph Campbell 	size_t counter;
357*f931551bSRalph Campbell };
358*f931551bSRalph Campbell 
359*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_resends);
360*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_acks);
361*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_qacks);
362*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_delayed_comp);
363*f931551bSRalph Campbell QIB_DIAGC_ATTR(seq_naks);
364*f931551bSRalph Campbell QIB_DIAGC_ATTR(rdma_seq);
365*f931551bSRalph Campbell QIB_DIAGC_ATTR(rnr_naks);
366*f931551bSRalph Campbell QIB_DIAGC_ATTR(other_naks);
367*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_timeouts);
368*f931551bSRalph Campbell QIB_DIAGC_ATTR(loop_pkts);
369*f931551bSRalph Campbell QIB_DIAGC_ATTR(pkt_drops);
370*f931551bSRalph Campbell QIB_DIAGC_ATTR(dmawait);
371*f931551bSRalph Campbell QIB_DIAGC_ATTR(unaligned);
372*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_dupreq);
373*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_seqnak);
374*f931551bSRalph Campbell 
375*f931551bSRalph Campbell static struct attribute *diagc_default_attributes[] = {
376*f931551bSRalph Campbell 	&qib_diagc_attr_rc_resends.attr,
377*f931551bSRalph Campbell 	&qib_diagc_attr_rc_acks.attr,
378*f931551bSRalph Campbell 	&qib_diagc_attr_rc_qacks.attr,
379*f931551bSRalph Campbell 	&qib_diagc_attr_rc_delayed_comp.attr,
380*f931551bSRalph Campbell 	&qib_diagc_attr_seq_naks.attr,
381*f931551bSRalph Campbell 	&qib_diagc_attr_rdma_seq.attr,
382*f931551bSRalph Campbell 	&qib_diagc_attr_rnr_naks.attr,
383*f931551bSRalph Campbell 	&qib_diagc_attr_other_naks.attr,
384*f931551bSRalph Campbell 	&qib_diagc_attr_rc_timeouts.attr,
385*f931551bSRalph Campbell 	&qib_diagc_attr_loop_pkts.attr,
386*f931551bSRalph Campbell 	&qib_diagc_attr_pkt_drops.attr,
387*f931551bSRalph Campbell 	&qib_diagc_attr_dmawait.attr,
388*f931551bSRalph Campbell 	&qib_diagc_attr_unaligned.attr,
389*f931551bSRalph Campbell 	&qib_diagc_attr_rc_dupreq.attr,
390*f931551bSRalph Campbell 	&qib_diagc_attr_rc_seqnak.attr,
391*f931551bSRalph Campbell 	NULL
392*f931551bSRalph Campbell };
393*f931551bSRalph Campbell 
394*f931551bSRalph Campbell static ssize_t diagc_attr_show(struct kobject *kobj, struct attribute *attr,
395*f931551bSRalph Campbell 			       char *buf)
396*f931551bSRalph Campbell {
397*f931551bSRalph Campbell 	struct qib_diagc_attr *dattr =
398*f931551bSRalph Campbell 		container_of(attr, struct qib_diagc_attr, attr);
399*f931551bSRalph Campbell 	struct qib_pportdata *ppd =
400*f931551bSRalph Campbell 		container_of(kobj, struct qib_pportdata, diagc_kobj);
401*f931551bSRalph Campbell 	struct qib_ibport *qibp = &ppd->ibport_data;
402*f931551bSRalph Campbell 
403*f931551bSRalph Campbell 	return sprintf(buf, "%u\n", *(u32 *)((char *)qibp + dattr->counter));
404*f931551bSRalph Campbell }
405*f931551bSRalph Campbell 
406*f931551bSRalph Campbell static const struct sysfs_ops qib_diagc_ops = {
407*f931551bSRalph Campbell 	.show = diagc_attr_show,
408*f931551bSRalph Campbell };
409*f931551bSRalph Campbell 
410*f931551bSRalph Campbell static struct kobj_type qib_diagc_ktype = {
411*f931551bSRalph Campbell 	.release = qib_port_release,
412*f931551bSRalph Campbell 	.sysfs_ops = &qib_diagc_ops,
413*f931551bSRalph Campbell 	.default_attrs = diagc_default_attributes
414*f931551bSRalph Campbell };
415*f931551bSRalph Campbell 
416*f931551bSRalph Campbell /* End diag_counters */
417*f931551bSRalph Campbell 
418*f931551bSRalph Campbell /* end of per-port file structures and support code */
419*f931551bSRalph Campbell 
420*f931551bSRalph Campbell /*
421*f931551bSRalph Campbell  * Start of per-unit (or driver, in some cases, but replicated
422*f931551bSRalph Campbell  * per unit) functions (these get a device *)
423*f931551bSRalph Campbell  */
424*f931551bSRalph Campbell static ssize_t show_rev(struct device *device, struct device_attribute *attr,
425*f931551bSRalph Campbell 			char *buf)
426*f931551bSRalph Campbell {
427*f931551bSRalph Campbell 	struct qib_ibdev *dev =
428*f931551bSRalph Campbell 		container_of(device, struct qib_ibdev, ibdev.dev);
429*f931551bSRalph Campbell 
430*f931551bSRalph Campbell 	return sprintf(buf, "%x\n", dd_from_dev(dev)->minrev);
431*f931551bSRalph Campbell }
432*f931551bSRalph Campbell 
433*f931551bSRalph Campbell static ssize_t show_hca(struct device *device, struct device_attribute *attr,
434*f931551bSRalph Campbell 			char *buf)
435*f931551bSRalph Campbell {
436*f931551bSRalph Campbell 	struct qib_ibdev *dev =
437*f931551bSRalph Campbell 		container_of(device, struct qib_ibdev, ibdev.dev);
438*f931551bSRalph Campbell 	struct qib_devdata *dd = dd_from_dev(dev);
439*f931551bSRalph Campbell 	int ret;
440*f931551bSRalph Campbell 
441*f931551bSRalph Campbell 	if (!dd->boardname)
442*f931551bSRalph Campbell 		ret = -EINVAL;
443*f931551bSRalph Campbell 	else
444*f931551bSRalph Campbell 		ret = scnprintf(buf, PAGE_SIZE, "%s\n", dd->boardname);
445*f931551bSRalph Campbell 	return ret;
446*f931551bSRalph Campbell }
447*f931551bSRalph Campbell 
448*f931551bSRalph Campbell static ssize_t show_version(struct device *device,
449*f931551bSRalph Campbell 			    struct device_attribute *attr, char *buf)
450*f931551bSRalph Campbell {
451*f931551bSRalph Campbell 	/* The string printed here is already newline-terminated. */
452*f931551bSRalph Campbell 	return scnprintf(buf, PAGE_SIZE, "%s", (char *)ib_qib_version);
453*f931551bSRalph Campbell }
454*f931551bSRalph Campbell 
455*f931551bSRalph Campbell static ssize_t show_boardversion(struct device *device,
456*f931551bSRalph Campbell 				 struct device_attribute *attr, char *buf)
457*f931551bSRalph Campbell {
458*f931551bSRalph Campbell 	struct qib_ibdev *dev =
459*f931551bSRalph Campbell 		container_of(device, struct qib_ibdev, ibdev.dev);
460*f931551bSRalph Campbell 	struct qib_devdata *dd = dd_from_dev(dev);
461*f931551bSRalph Campbell 
462*f931551bSRalph Campbell 	/* The string printed here is already newline-terminated. */
463*f931551bSRalph Campbell 	return scnprintf(buf, PAGE_SIZE, "%s", dd->boardversion);
464*f931551bSRalph Campbell }
465*f931551bSRalph Campbell 
466*f931551bSRalph Campbell 
467*f931551bSRalph Campbell static ssize_t show_localbus_info(struct device *device,
468*f931551bSRalph Campbell 				  struct device_attribute *attr, char *buf)
469*f931551bSRalph Campbell {
470*f931551bSRalph Campbell 	struct qib_ibdev *dev =
471*f931551bSRalph Campbell 		container_of(device, struct qib_ibdev, ibdev.dev);
472*f931551bSRalph Campbell 	struct qib_devdata *dd = dd_from_dev(dev);
473*f931551bSRalph Campbell 
474*f931551bSRalph Campbell 	/* The string printed here is already newline-terminated. */
475*f931551bSRalph Campbell 	return scnprintf(buf, PAGE_SIZE, "%s", dd->lbus_info);
476*f931551bSRalph Campbell }
477*f931551bSRalph Campbell 
478*f931551bSRalph Campbell 
479*f931551bSRalph Campbell static ssize_t show_nctxts(struct device *device,
480*f931551bSRalph Campbell 			   struct device_attribute *attr, char *buf)
481*f931551bSRalph Campbell {
482*f931551bSRalph Campbell 	struct qib_ibdev *dev =
483*f931551bSRalph Campbell 		container_of(device, struct qib_ibdev, ibdev.dev);
484*f931551bSRalph Campbell 	struct qib_devdata *dd = dd_from_dev(dev);
485*f931551bSRalph Campbell 
486*f931551bSRalph Campbell 	/* Return the number of user ports (contexts) available. */
487*f931551bSRalph Campbell 	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->cfgctxts -
488*f931551bSRalph Campbell 		dd->first_user_ctxt);
489*f931551bSRalph Campbell }
490*f931551bSRalph Campbell 
491*f931551bSRalph Campbell static ssize_t show_serial(struct device *device,
492*f931551bSRalph Campbell 			   struct device_attribute *attr, char *buf)
493*f931551bSRalph Campbell {
494*f931551bSRalph Campbell 	struct qib_ibdev *dev =
495*f931551bSRalph Campbell 		container_of(device, struct qib_ibdev, ibdev.dev);
496*f931551bSRalph Campbell 	struct qib_devdata *dd = dd_from_dev(dev);
497*f931551bSRalph Campbell 
498*f931551bSRalph Campbell 	buf[sizeof dd->serial] = '\0';
499*f931551bSRalph Campbell 	memcpy(buf, dd->serial, sizeof dd->serial);
500*f931551bSRalph Campbell 	strcat(buf, "\n");
501*f931551bSRalph Campbell 	return strlen(buf);
502*f931551bSRalph Campbell }
503*f931551bSRalph Campbell 
504*f931551bSRalph Campbell static ssize_t store_chip_reset(struct device *device,
505*f931551bSRalph Campbell 				struct device_attribute *attr, const char *buf,
506*f931551bSRalph Campbell 				size_t count)
507*f931551bSRalph Campbell {
508*f931551bSRalph Campbell 	struct qib_ibdev *dev =
509*f931551bSRalph Campbell 		container_of(device, struct qib_ibdev, ibdev.dev);
510*f931551bSRalph Campbell 	struct qib_devdata *dd = dd_from_dev(dev);
511*f931551bSRalph Campbell 	int ret;
512*f931551bSRalph Campbell 
513*f931551bSRalph Campbell 	if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) {
514*f931551bSRalph Campbell 		ret = -EINVAL;
515*f931551bSRalph Campbell 		goto bail;
516*f931551bSRalph Campbell 	}
517*f931551bSRalph Campbell 
518*f931551bSRalph Campbell 	ret = qib_reset_device(dd->unit);
519*f931551bSRalph Campbell bail:
520*f931551bSRalph Campbell 	return ret < 0 ? ret : count;
521*f931551bSRalph Campbell }
522*f931551bSRalph Campbell 
523*f931551bSRalph Campbell static ssize_t show_logged_errs(struct device *device,
524*f931551bSRalph Campbell 				struct device_attribute *attr, char *buf)
525*f931551bSRalph Campbell {
526*f931551bSRalph Campbell 	struct qib_ibdev *dev =
527*f931551bSRalph Campbell 		container_of(device, struct qib_ibdev, ibdev.dev);
528*f931551bSRalph Campbell 	struct qib_devdata *dd = dd_from_dev(dev);
529*f931551bSRalph Campbell 	int idx, count;
530*f931551bSRalph Campbell 
531*f931551bSRalph Campbell 	/* force consistency with actual EEPROM */
532*f931551bSRalph Campbell 	if (qib_update_eeprom_log(dd) != 0)
533*f931551bSRalph Campbell 		return -ENXIO;
534*f931551bSRalph Campbell 
535*f931551bSRalph Campbell 	count = 0;
536*f931551bSRalph Campbell 	for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) {
537*f931551bSRalph Campbell 		count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c",
538*f931551bSRalph Campbell 				   dd->eep_st_errs[idx],
539*f931551bSRalph Campbell 				   idx == (QIB_EEP_LOG_CNT - 1) ? '\n' : ' ');
540*f931551bSRalph Campbell 	}
541*f931551bSRalph Campbell 
542*f931551bSRalph Campbell 	return count;
543*f931551bSRalph Campbell }
544*f931551bSRalph Campbell 
545*f931551bSRalph Campbell /*
546*f931551bSRalph Campbell  * Dump tempsense regs. in decimal, to ease shell-scripts.
547*f931551bSRalph Campbell  */
548*f931551bSRalph Campbell static ssize_t show_tempsense(struct device *device,
549*f931551bSRalph Campbell 			      struct device_attribute *attr, char *buf)
550*f931551bSRalph Campbell {
551*f931551bSRalph Campbell 	struct qib_ibdev *dev =
552*f931551bSRalph Campbell 		container_of(device, struct qib_ibdev, ibdev.dev);
553*f931551bSRalph Campbell 	struct qib_devdata *dd = dd_from_dev(dev);
554*f931551bSRalph Campbell 	int ret;
555*f931551bSRalph Campbell 	int idx;
556*f931551bSRalph Campbell 	u8 regvals[8];
557*f931551bSRalph Campbell 
558*f931551bSRalph Campbell 	ret = -ENXIO;
559*f931551bSRalph Campbell 	for (idx = 0; idx < 8; ++idx) {
560*f931551bSRalph Campbell 		if (idx == 6)
561*f931551bSRalph Campbell 			continue;
562*f931551bSRalph Campbell 		ret = dd->f_tempsense_rd(dd, idx);
563*f931551bSRalph Campbell 		if (ret < 0)
564*f931551bSRalph Campbell 			break;
565*f931551bSRalph Campbell 		regvals[idx] = ret;
566*f931551bSRalph Campbell 	}
567*f931551bSRalph Campbell 	if (idx == 8)
568*f931551bSRalph Campbell 		ret = scnprintf(buf, PAGE_SIZE, "%d %d %02X %02X %d %d\n",
569*f931551bSRalph Campbell 				*(signed char *)(regvals),
570*f931551bSRalph Campbell 				*(signed char *)(regvals + 1),
571*f931551bSRalph Campbell 				regvals[2], regvals[3],
572*f931551bSRalph Campbell 				*(signed char *)(regvals + 5),
573*f931551bSRalph Campbell 				*(signed char *)(regvals + 7));
574*f931551bSRalph Campbell 	return ret;
575*f931551bSRalph Campbell }
576*f931551bSRalph Campbell 
577*f931551bSRalph Campbell /*
578*f931551bSRalph Campbell  * end of per-unit (or driver, in some cases, but replicated
579*f931551bSRalph Campbell  * per unit) functions
580*f931551bSRalph Campbell  */
581*f931551bSRalph Campbell 
582*f931551bSRalph Campbell /* start of per-unit file structures and support code */
583*f931551bSRalph Campbell static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
584*f931551bSRalph Campbell static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
585*f931551bSRalph Campbell static DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
586*f931551bSRalph Campbell static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
587*f931551bSRalph Campbell static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL);
588*f931551bSRalph Campbell static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
589*f931551bSRalph Campbell static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
590*f931551bSRalph Campbell static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
591*f931551bSRalph Campbell static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL);
592*f931551bSRalph Campbell static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL);
593*f931551bSRalph Campbell static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset);
594*f931551bSRalph Campbell 
595*f931551bSRalph Campbell static struct device_attribute *qib_attributes[] = {
596*f931551bSRalph Campbell 	&dev_attr_hw_rev,
597*f931551bSRalph Campbell 	&dev_attr_hca_type,
598*f931551bSRalph Campbell 	&dev_attr_board_id,
599*f931551bSRalph Campbell 	&dev_attr_version,
600*f931551bSRalph Campbell 	&dev_attr_nctxts,
601*f931551bSRalph Campbell 	&dev_attr_serial,
602*f931551bSRalph Campbell 	&dev_attr_boardversion,
603*f931551bSRalph Campbell 	&dev_attr_logged_errors,
604*f931551bSRalph Campbell 	&dev_attr_tempsense,
605*f931551bSRalph Campbell 	&dev_attr_localbus_info,
606*f931551bSRalph Campbell 	&dev_attr_chip_reset,
607*f931551bSRalph Campbell };
608*f931551bSRalph Campbell 
609*f931551bSRalph Campbell int qib_create_port_files(struct ib_device *ibdev, u8 port_num,
610*f931551bSRalph Campbell 			  struct kobject *kobj)
611*f931551bSRalph Campbell {
612*f931551bSRalph Campbell 	struct qib_pportdata *ppd;
613*f931551bSRalph Campbell 	struct qib_devdata *dd = dd_from_ibdev(ibdev);
614*f931551bSRalph Campbell 	int ret;
615*f931551bSRalph Campbell 
616*f931551bSRalph Campbell 	if (!port_num || port_num > dd->num_pports) {
617*f931551bSRalph Campbell 		qib_dev_err(dd, "Skipping infiniband class with "
618*f931551bSRalph Campbell 			    "invalid port %u\n", port_num);
619*f931551bSRalph Campbell 		ret = -ENODEV;
620*f931551bSRalph Campbell 		goto bail;
621*f931551bSRalph Campbell 	}
622*f931551bSRalph Campbell 	ppd = &dd->pport[port_num - 1];
623*f931551bSRalph Campbell 
624*f931551bSRalph Campbell 	ret = kobject_init_and_add(&ppd->pport_kobj, &qib_port_ktype, kobj,
625*f931551bSRalph Campbell 				   "linkcontrol");
626*f931551bSRalph Campbell 	if (ret) {
627*f931551bSRalph Campbell 		qib_dev_err(dd, "Skipping linkcontrol sysfs info, "
628*f931551bSRalph Campbell 			    "(err %d) port %u\n", ret, port_num);
629*f931551bSRalph Campbell 		goto bail;
630*f931551bSRalph Campbell 	}
631*f931551bSRalph Campbell 	kobject_uevent(&ppd->pport_kobj, KOBJ_ADD);
632*f931551bSRalph Campbell 
633*f931551bSRalph Campbell 	ret = kobject_init_and_add(&ppd->sl2vl_kobj, &qib_sl2vl_ktype, kobj,
634*f931551bSRalph Campbell 				   "sl2vl");
635*f931551bSRalph Campbell 	if (ret) {
636*f931551bSRalph Campbell 		qib_dev_err(dd, "Skipping sl2vl sysfs info, "
637*f931551bSRalph Campbell 			    "(err %d) port %u\n", ret, port_num);
638*f931551bSRalph Campbell 		goto bail_sl;
639*f931551bSRalph Campbell 	}
640*f931551bSRalph Campbell 	kobject_uevent(&ppd->sl2vl_kobj, KOBJ_ADD);
641*f931551bSRalph Campbell 
642*f931551bSRalph Campbell 	ret = kobject_init_and_add(&ppd->diagc_kobj, &qib_diagc_ktype, kobj,
643*f931551bSRalph Campbell 				   "diag_counters");
644*f931551bSRalph Campbell 	if (ret) {
645*f931551bSRalph Campbell 		qib_dev_err(dd, "Skipping diag_counters sysfs info, "
646*f931551bSRalph Campbell 			    "(err %d) port %u\n", ret, port_num);
647*f931551bSRalph Campbell 		goto bail_diagc;
648*f931551bSRalph Campbell 	}
649*f931551bSRalph Campbell 	kobject_uevent(&ppd->diagc_kobj, KOBJ_ADD);
650*f931551bSRalph Campbell 
651*f931551bSRalph Campbell 	return 0;
652*f931551bSRalph Campbell 
653*f931551bSRalph Campbell bail_diagc:
654*f931551bSRalph Campbell 	kobject_put(&ppd->sl2vl_kobj);
655*f931551bSRalph Campbell bail_sl:
656*f931551bSRalph Campbell 	kobject_put(&ppd->pport_kobj);
657*f931551bSRalph Campbell bail:
658*f931551bSRalph Campbell 	return ret;
659*f931551bSRalph Campbell }
660*f931551bSRalph Campbell 
661*f931551bSRalph Campbell /*
662*f931551bSRalph Campbell  * Register and create our files in /sys/class/infiniband.
663*f931551bSRalph Campbell  */
664*f931551bSRalph Campbell int qib_verbs_register_sysfs(struct qib_devdata *dd)
665*f931551bSRalph Campbell {
666*f931551bSRalph Campbell 	struct ib_device *dev = &dd->verbs_dev.ibdev;
667*f931551bSRalph Campbell 	int i, ret;
668*f931551bSRalph Campbell 
669*f931551bSRalph Campbell 	for (i = 0; i < ARRAY_SIZE(qib_attributes); ++i) {
670*f931551bSRalph Campbell 		ret = device_create_file(&dev->dev, qib_attributes[i]);
671*f931551bSRalph Campbell 		if (ret)
672*f931551bSRalph Campbell 			return ret;
673*f931551bSRalph Campbell 	}
674*f931551bSRalph Campbell 
675*f931551bSRalph Campbell 	return 0;
676*f931551bSRalph Campbell }
677*f931551bSRalph Campbell 
678*f931551bSRalph Campbell /*
679*f931551bSRalph Campbell  * Unregister and remove our files in /sys/class/infiniband.
680*f931551bSRalph Campbell  */
681*f931551bSRalph Campbell void qib_verbs_unregister_sysfs(struct qib_devdata *dd)
682*f931551bSRalph Campbell {
683*f931551bSRalph Campbell 	struct qib_pportdata *ppd;
684*f931551bSRalph Campbell 	int i;
685*f931551bSRalph Campbell 
686*f931551bSRalph Campbell 	for (i = 0; i < dd->num_pports; i++) {
687*f931551bSRalph Campbell 		ppd = &dd->pport[i];
688*f931551bSRalph Campbell 		kobject_put(&ppd->pport_kobj);
689*f931551bSRalph Campbell 		kobject_put(&ppd->sl2vl_kobj);
690*f931551bSRalph Campbell 	}
691*f931551bSRalph Campbell }
692