sysfs.c revision 271127
1/*
2 * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
3 * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved.
4 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses.  You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 *     Redistribution and use in source and binary forms, with or
13 *     without modification, are permitted provided that the following
14 *     conditions are met:
15 *
16 *      - Redistributions of source code must retain the above
17 *        copyright notice, this list of conditions and the following
18 *        disclaimer.
19 *
20 *      - Redistributions in binary form must reproduce the above
21 *        copyright notice, this list of conditions and the following
22 *        disclaimer in the documentation and/or other materials
23 *        provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 */
34
35#include "core_priv.h"
36
37#include <linux/slab.h>
38#include <linux/string.h>
39#include <linux/fs.h>
40
41#include <rdma/ib_mad.h>
42#include <rdma/ib_pma.h>
43
44struct ib_port {
45	struct kobject         kobj;
46	struct ib_device      *ibdev;
47	struct attribute_group gid_group;
48	struct attribute_group pkey_group;
49	u8                     port_num;
50};
51
52struct port_attribute {
53	struct attribute attr;
54	ssize_t (*show)(struct ib_port *, struct port_attribute *, char *buf);
55	ssize_t (*store)(struct ib_port *, struct port_attribute *,
56			 const char *buf, size_t count);
57};
58
59#define PORT_ATTR(_name, _mode, _show, _store) \
60struct port_attribute port_attr_##_name = __ATTR(_name, _mode, _show, _store)
61
62#define PORT_ATTR_RO(_name) \
63struct port_attribute port_attr_##_name = __ATTR_RO(_name)
64
65struct port_table_attribute {
66	struct port_attribute	attr;
67	char			name[8];
68	int			index;
69};
70
71static ssize_t port_attr_show(struct kobject *kobj,
72			      struct attribute *attr, char *buf)
73{
74	struct port_attribute *port_attr =
75		container_of(attr, struct port_attribute, attr);
76	struct ib_port *p = container_of(kobj, struct ib_port, kobj);
77
78	if (!port_attr->show)
79		return -EIO;
80
81	return port_attr->show(p, port_attr, buf);
82}
83
84static const struct sysfs_ops port_sysfs_ops = {
85	.show = port_attr_show
86};
87
88static ssize_t state_show(struct ib_port *p, struct port_attribute *unused,
89			  char *buf)
90{
91	struct ib_port_attr attr;
92	ssize_t ret;
93
94	static const char *state_name[] = {
95		[IB_PORT_NOP]		= "NOP",
96		[IB_PORT_DOWN]		= "DOWN",
97		[IB_PORT_INIT]		= "INIT",
98		[IB_PORT_ARMED]		= "ARMED",
99		[IB_PORT_ACTIVE]	= "ACTIVE",
100		[IB_PORT_ACTIVE_DEFER]	= "ACTIVE_DEFER"
101	};
102
103	ret = ib_query_port(p->ibdev, p->port_num, &attr);
104	if (ret)
105		return ret;
106
107	return sprintf(buf, "%d: %s\n", attr.state,
108		       attr.state < ARRAY_SIZE(state_name) ?
109		       state_name[attr.state] : "UNKNOWN");
110}
111
112static ssize_t lid_show(struct ib_port *p, struct port_attribute *unused,
113			char *buf)
114{
115	struct ib_port_attr attr;
116	ssize_t ret;
117
118	ret = ib_query_port(p->ibdev, p->port_num, &attr);
119	if (ret)
120		return ret;
121
122	return sprintf(buf, "0x%x\n", attr.lid);
123}
124
125static ssize_t lid_mask_count_show(struct ib_port *p,
126				   struct port_attribute *unused,
127				   char *buf)
128{
129	struct ib_port_attr attr;
130	ssize_t ret;
131
132	ret = ib_query_port(p->ibdev, p->port_num, &attr);
133	if (ret)
134		return ret;
135
136	return sprintf(buf, "%d\n", attr.lmc);
137}
138
139static ssize_t sm_lid_show(struct ib_port *p, struct port_attribute *unused,
140			   char *buf)
141{
142	struct ib_port_attr attr;
143	ssize_t ret;
144
145	ret = ib_query_port(p->ibdev, p->port_num, &attr);
146	if (ret)
147		return ret;
148
149	return sprintf(buf, "0x%x\n", attr.sm_lid);
150}
151
152static ssize_t sm_sl_show(struct ib_port *p, struct port_attribute *unused,
153			  char *buf)
154{
155	struct ib_port_attr attr;
156	ssize_t ret;
157
158	ret = ib_query_port(p->ibdev, p->port_num, &attr);
159	if (ret)
160		return ret;
161
162	return sprintf(buf, "%d\n", attr.sm_sl);
163}
164
165static ssize_t cap_mask_show(struct ib_port *p, struct port_attribute *unused,
166			     char *buf)
167{
168	struct ib_port_attr attr;
169	ssize_t ret;
170
171	ret = ib_query_port(p->ibdev, p->port_num, &attr);
172	if (ret)
173		return ret;
174
175	return sprintf(buf, "0x%08x\n", attr.port_cap_flags);
176}
177
178static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,
179			 char *buf)
180{
181	struct ib_port_attr attr;
182	char *speed = "";
183	int rate;
184	ssize_t ret;
185
186	ret = ib_query_port(p->ibdev, p->port_num, &attr);
187	if (ret)
188		return ret;
189
190	switch (attr.active_speed) {
191	case 2: speed = " DDR"; break;
192	case 4: speed = " QDR"; break;
193	}
194
195	rate = 25 * ib_width_enum_to_int(attr.active_width) * attr.active_speed;
196	if (rate < 0)
197		return -EINVAL;
198
199	return sprintf(buf, "%d%s Gb/sec (%dX%s)\n",
200		       rate / 10, rate % 10 ? ".5" : "",
201		       ib_width_enum_to_int(attr.active_width), speed);
202}
203
204static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused,
205			       char *buf)
206{
207	struct ib_port_attr attr;
208
209	ssize_t ret;
210
211	ret = ib_query_port(p->ibdev, p->port_num, &attr);
212	if (ret)
213		return ret;
214
215	switch (attr.phys_state) {
216	case 1:  return sprintf(buf, "1: Sleep\n");
217	case 2:  return sprintf(buf, "2: Polling\n");
218	case 3:  return sprintf(buf, "3: Disabled\n");
219	case 4:  return sprintf(buf, "4: PortConfigurationTraining\n");
220	case 5:  return sprintf(buf, "5: LinkUp\n");
221	case 6:  return sprintf(buf, "6: LinkErrorRecovery\n");
222	case 7:  return sprintf(buf, "7: Phy Test\n");
223	default: return sprintf(buf, "%d: <unknown>\n", attr.phys_state);
224	}
225}
226
227static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused,
228			       char *buf)
229{
230	switch (rdma_port_get_link_layer(p->ibdev, p->port_num)) {
231	case IB_LINK_LAYER_INFINIBAND:
232		return sprintf(buf, "%s\n", "IB");
233	case IB_LINK_LAYER_ETHERNET:
234		return sprintf(buf, "%s\n", "Ethernet");
235	default:
236		return sprintf(buf, "%s\n", "Unknown");
237	}
238}
239
240static PORT_ATTR_RO(state);
241static PORT_ATTR_RO(lid);
242static PORT_ATTR_RO(lid_mask_count);
243static PORT_ATTR_RO(sm_lid);
244static PORT_ATTR_RO(sm_sl);
245static PORT_ATTR_RO(cap_mask);
246static PORT_ATTR_RO(rate);
247static PORT_ATTR_RO(phys_state);
248static PORT_ATTR_RO(link_layer);
249
250static struct attribute *port_default_attrs[] = {
251	&port_attr_state.attr,
252	&port_attr_lid.attr,
253	&port_attr_lid_mask_count.attr,
254	&port_attr_sm_lid.attr,
255	&port_attr_sm_sl.attr,
256	&port_attr_cap_mask.attr,
257	&port_attr_rate.attr,
258	&port_attr_phys_state.attr,
259	&port_attr_link_layer.attr,
260	NULL
261};
262
263static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
264			     char *buf)
265{
266	struct port_table_attribute *tab_attr =
267		container_of(attr, struct port_table_attribute, attr);
268	union ib_gid gid;
269	ssize_t ret;
270	u16 *raw;
271
272	ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid);
273	if (ret)
274		return ret;
275
276	raw = (u16 *)gid.raw;
277	return sprintf(buf, "%.4x:%.4x:%.4x:%.4x:%.4x:%.4x:%.4x:%.4x\n",
278	    htons(raw[0]), htons(raw[1]), htons(raw[2]), htons(raw[3]),
279	    htons(raw[4]), htons(raw[5]), htons(raw[6]), htons(raw[7]));
280}
281
282static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr,
283			      char *buf)
284{
285	struct port_table_attribute *tab_attr =
286		container_of(attr, struct port_table_attribute, attr);
287	u16 pkey;
288	ssize_t ret;
289
290	ret = ib_query_pkey(p->ibdev, p->port_num, tab_attr->index, &pkey);
291	if (ret)
292		return ret;
293
294	return sprintf(buf, "0x%04x\n", pkey);
295}
296
297static ssize_t get_pma_counters(struct ib_port *p, struct port_attribute *attr,
298                                char *buf, int c_ext)
299{
300        struct port_table_attribute *tab_attr =
301                container_of(attr, struct port_table_attribute, attr);
302        int offset = tab_attr->index & 0xffff;
303        int width  = (tab_attr->index >> 16) & 0xff;
304        struct ib_mad *in_mad  = NULL;
305        struct ib_mad *out_mad = NULL;
306        ssize_t ret;
307
308        if (!p->ibdev->process_mad)
309                return -ENXIO;
310
311        in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
312        out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
313        if (!in_mad || !out_mad) {
314                ret = -ENOMEM;
315                goto out;
316        }
317
318        in_mad->mad_hdr.base_version  = 1;
319        in_mad->mad_hdr.mgmt_class    = IB_MGMT_CLASS_PERF_MGMT;
320        in_mad->mad_hdr.class_version = 1;
321        in_mad->mad_hdr.method        = IB_MGMT_METHOD_GET;
322        if (c_ext)
323                in_mad->mad_hdr.attr_id = IB_PMA_PORT_COUNTERS_EXT;
324        else
325                in_mad->mad_hdr.attr_id = IB_PMA_PORT_COUNTERS;
326
327        in_mad->data[41] = p->port_num; /* PortSelect field */
328
329        if ((p->ibdev->process_mad(p->ibdev, IB_MAD_IGNORE_MKEY,
330                 p->port_num, NULL, NULL, in_mad, out_mad) &
331             (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) !=
332            (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) {
333                ret = -EINVAL;
334                goto out;
335        }
336
337        switch (width) {
338        case 4:
339                ret = sprintf(buf, "%u\n", (out_mad->data[40 + offset / 8] >>
340                                            (4 - (offset % 8))) & 0xf);
341                break;
342        case 8:
343                ret = sprintf(buf, "%u\n", out_mad->data[40 + offset / 8]);
344                break;
345        case 16:
346                ret = sprintf(buf, "%u\n",
347                              be16_to_cpup((__be16 *)(out_mad->data + 40 + offset / 8)));
348                break;
349        case 32:
350                ret = sprintf(buf, "%u\n",
351                              be32_to_cpup((__be32 *)(out_mad->data + 40 + offset / 8)));
352                break;
353        case 64:
354                ret = sprintf(buf, "%llu\n", (unsigned long long)
355                              be64_to_cpup((__be64 *)(out_mad->data + 40 + offset / 8)));
356                break;
357        default:
358                ret = 0;
359        }
360
361out:
362        kfree(in_mad);
363        kfree(out_mad);
364
365        return ret;
366}
367
368#define PORT_PMA_ATTR(_name, _counter, _width, _offset)                 \
369struct port_table_attribute port_pma_attr_##_name = {                   \
370        .attr  = __ATTR(_name, S_IRUGO, show_pma_counter, NULL),        \
371        .index = (_offset) | ((_width) << 16) | ((_counter) << 24)      \
372}
373
374static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
375                                char *buf)
376{
377        return get_pma_counters(p, attr, buf, 0);
378}
379
380static PORT_PMA_ATTR(symbol_error                   ,  0, 16,  32);
381static PORT_PMA_ATTR(link_error_recovery            ,  1,  8,  48);
382static PORT_PMA_ATTR(link_downed                    ,  2,  8,  56);
383static PORT_PMA_ATTR(port_rcv_errors                ,  3, 16,  64);
384static PORT_PMA_ATTR(port_rcv_remote_physical_errors,  4, 16,  80);
385static PORT_PMA_ATTR(port_rcv_switch_relay_errors   ,  5, 16,  96);
386static PORT_PMA_ATTR(port_xmit_discards             ,  6, 16, 112);
387static PORT_PMA_ATTR(port_xmit_constraint_errors    ,  7,  8, 128);
388static PORT_PMA_ATTR(port_rcv_constraint_errors     ,  8,  8, 136);
389static PORT_PMA_ATTR(local_link_integrity_errors    ,  9,  4, 152);
390static PORT_PMA_ATTR(excessive_buffer_overrun_errors, 10,  4, 156);
391static PORT_PMA_ATTR(VL15_dropped                   , 11, 16, 176);
392static PORT_PMA_ATTR(port_xmit_data                 , 12, 32, 192);
393static PORT_PMA_ATTR(port_rcv_data                  , 13, 32, 224);
394static PORT_PMA_ATTR(port_xmit_packets              , 14, 32, 256);
395static PORT_PMA_ATTR(port_rcv_packets               , 15, 32, 288);
396
397static struct attribute *pma_attrs[] = {
398        &port_pma_attr_symbol_error.attr.attr,
399        &port_pma_attr_link_error_recovery.attr.attr,
400        &port_pma_attr_link_downed.attr.attr,
401        &port_pma_attr_port_rcv_errors.attr.attr,
402        &port_pma_attr_port_rcv_remote_physical_errors.attr.attr,
403        &port_pma_attr_port_rcv_switch_relay_errors.attr.attr,
404        &port_pma_attr_port_xmit_discards.attr.attr,
405        &port_pma_attr_port_xmit_constraint_errors.attr.attr,
406        &port_pma_attr_port_rcv_constraint_errors.attr.attr,
407        &port_pma_attr_local_link_integrity_errors.attr.attr,
408        &port_pma_attr_excessive_buffer_overrun_errors.attr.attr,
409        &port_pma_attr_VL15_dropped.attr.attr,
410        &port_pma_attr_port_xmit_data.attr.attr,
411        &port_pma_attr_port_rcv_data.attr.attr,
412        &port_pma_attr_port_xmit_packets.attr.attr,
413        &port_pma_attr_port_rcv_packets.attr.attr,
414        NULL
415};
416
417static struct attribute_group pma_group = {
418	.name  = "counters",
419	.attrs  = pma_attrs
420};
421
422#define PORT_PMA_ATTR_EXT(_name, _counter, _width, _offset)             \
423struct port_table_attribute port_pma_attr_ext_##_name = {               \
424        .attr  = __ATTR(_name, S_IRUGO, show_pma_counter_ext, NULL),    \
425        .index = (_offset) | ((_width) << 16) | ((_counter) << 24)      \
426}
427
428static ssize_t show_pma_counter_ext(struct ib_port *p,
429                                    struct port_attribute *attr, char *buf)
430{
431        return get_pma_counters(p, attr, buf, 1);
432}
433
434static PORT_PMA_ATTR_EXT(port_xmit_data_64           ,  0, 64,  64);
435static PORT_PMA_ATTR_EXT(port_rcv_data_64            ,  0, 64,  128);
436static PORT_PMA_ATTR_EXT(port_xmit_packets_64        ,  0, 64,  192);
437static PORT_PMA_ATTR_EXT(port_rcv_packets_64         ,  0, 64,  256);
438static PORT_PMA_ATTR_EXT(port_unicast_xmit_packets   ,  0, 64,  320);
439static PORT_PMA_ATTR_EXT(port_unicast_rcv_packets    ,  0, 64,  384);
440static PORT_PMA_ATTR_EXT(port_multicast_xmit_packets ,  0, 64,  448);
441static PORT_PMA_ATTR_EXT(port_multicast_rcv_packets  ,  0, 64,  512);
442
443static struct attribute *pma_attrs_ext[] = {
444        &port_pma_attr_ext_port_xmit_data_64.attr.attr,
445        &port_pma_attr_ext_port_rcv_data_64.attr.attr,
446        &port_pma_attr_ext_port_xmit_packets_64.attr.attr,
447        &port_pma_attr_ext_port_rcv_packets_64.attr.attr,
448        &port_pma_attr_ext_port_unicast_xmit_packets.attr.attr,
449        &port_pma_attr_ext_port_unicast_rcv_packets.attr.attr,
450        &port_pma_attr_ext_port_multicast_xmit_packets.attr.attr,
451        &port_pma_attr_ext_port_multicast_rcv_packets.attr.attr,
452        NULL
453};
454
455static struct attribute_group pma_ext_group = {
456        .name  = "counters_ext",
457        .attrs  = pma_attrs_ext
458};
459
460static void ib_port_release(struct kobject *kobj)
461{
462	struct ib_port *p = container_of(kobj, struct ib_port, kobj);
463	struct attribute *a;
464	int i;
465
466	for (i = 0; (a = p->gid_group.attrs[i]); ++i)
467		kfree(a);
468
469	kfree(p->gid_group.attrs);
470
471	for (i = 0; (a = p->pkey_group.attrs[i]); ++i)
472		kfree(a);
473
474	kfree(p->pkey_group.attrs);
475
476	kfree(p);
477}
478
479static struct kobj_type port_type = {
480	.release       = ib_port_release,
481	.sysfs_ops     = &port_sysfs_ops,
482	.default_attrs = port_default_attrs
483};
484
485static void ib_device_release(struct device *device)
486{
487	struct ib_device *dev = container_of(device, struct ib_device, dev);
488
489	kfree(dev);
490}
491
492#ifdef __linux__
493/* BSD supports this through devfs(5) and devd(8). */
494static int ib_device_uevent(struct device *device,
495			    struct kobj_uevent_env *env)
496{
497	struct ib_device *dev = container_of(device, struct ib_device, dev);
498
499	if (add_uevent_var(env, "NAME=%s", dev->name))
500		return -ENOMEM;
501
502	/*
503	 * It would be nice to pass the node GUID with the event...
504	 */
505
506	return 0;
507}
508#endif
509
510static struct attribute **
511alloc_group_attrs(ssize_t (*show)(struct ib_port *,
512				  struct port_attribute *, char *buf),
513		  int len)
514{
515	struct attribute **tab_attr;
516	struct port_table_attribute *element;
517	int i;
518
519	tab_attr = kcalloc(1 + len, sizeof(struct attribute *), GFP_KERNEL);
520	if (!tab_attr)
521		return NULL;
522
523	for (i = 0; i < len; i++) {
524		element = kzalloc(sizeof(struct port_table_attribute),
525				  GFP_KERNEL);
526		if (!element)
527			goto err;
528
529		if (snprintf(element->name, sizeof(element->name),
530			     "%d", i) >= sizeof(element->name)) {
531			kfree(element);
532			goto err;
533		}
534
535		element->attr.attr.name  = element->name;
536		element->attr.attr.mode  = S_IRUGO;
537		element->attr.show       = show;
538		element->index		 = i;
539
540		tab_attr[i] = &element->attr.attr;
541	}
542
543	return tab_attr;
544
545err:
546	while (--i >= 0)
547		kfree(tab_attr[i]);
548	kfree(tab_attr);
549	return NULL;
550}
551
552static int add_port(struct ib_device *device, int port_num,
553                    int (*port_callback)(struct ib_device *,
554                                         u8, struct kobject *))
555{
556	struct ib_port *p;
557	struct ib_port_attr attr;
558	int i;
559	int ret;
560
561	ret = ib_query_port(device, port_num, &attr);
562	if (ret)
563		return ret;
564
565	p = kzalloc(sizeof *p, GFP_KERNEL);
566	if (!p)
567		return -ENOMEM;
568
569	p->ibdev      = device;
570	p->port_num   = port_num;
571
572	ret = kobject_init_and_add(&p->kobj, &port_type,
573				   kobject_get(device->ports_parent),
574				   "%d", port_num);
575	if (ret)
576		goto err_put;
577
578	ret = sysfs_create_group(&p->kobj, &pma_group);
579	if (ret)
580		goto err_put;
581
582        ret = sysfs_create_group(&p->kobj, &pma_ext_group);
583        if (ret)
584                goto err_remove_pma;
585
586	p->gid_group.name  = "gids";
587	p->gid_group.attrs = alloc_group_attrs(show_port_gid, attr.gid_tbl_len);
588	if (!p->gid_group.attrs)
589		goto err_remove_pma_ext;
590
591	ret = sysfs_create_group(&p->kobj, &p->gid_group);
592	if (ret)
593		goto err_free_gid;
594
595	p->pkey_group.name  = "pkeys";
596	p->pkey_group.attrs = alloc_group_attrs(show_port_pkey,
597						attr.pkey_tbl_len);
598	if (!p->pkey_group.attrs)
599		goto err_remove_gid;
600
601	ret = sysfs_create_group(&p->kobj, &p->pkey_group);
602	if (ret)
603		goto err_free_pkey;
604
605        if (port_callback) {
606                ret = port_callback(device, port_num, &p->kobj);
607                if (ret)
608                        goto err_remove_pkey;
609        }
610
611	list_add_tail(&p->kobj.entry, &device->port_list);
612
613#ifdef __linux__
614	kobject_uevent(&p->kobj, KOBJ_ADD);
615#endif
616	return 0;
617
618err_remove_pkey:
619        sysfs_remove_group(&p->kobj, &p->pkey_group);
620
621err_free_pkey:
622	for (i = 0; i < attr.pkey_tbl_len; ++i)
623		kfree(p->pkey_group.attrs[i]);
624
625	kfree(p->pkey_group.attrs);
626
627err_remove_gid:
628	sysfs_remove_group(&p->kobj, &p->gid_group);
629
630err_free_gid:
631	for (i = 0; i < attr.gid_tbl_len; ++i)
632		kfree(p->gid_group.attrs[i]);
633
634	kfree(p->gid_group.attrs);
635
636err_remove_pma_ext:
637        sysfs_remove_group(&p->kobj, &pma_ext_group);
638
639err_remove_pma:
640	sysfs_remove_group(&p->kobj, &pma_group);
641
642err_put:
643	kobject_put(device->ports_parent);
644	kfree(p);
645	return ret;
646}
647
648static ssize_t show_node_type(struct device *device,
649			      struct device_attribute *attr, char *buf)
650{
651	struct ib_device *dev = container_of(device, struct ib_device, dev);
652
653	switch (dev->node_type) {
654	case RDMA_NODE_IB_CA:	  return sprintf(buf, "%d: CA\n", dev->node_type);
655	case RDMA_NODE_RNIC:	  return sprintf(buf, "%d: RNIC\n", dev->node_type);
656	case RDMA_NODE_IB_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type);
657	case RDMA_NODE_IB_ROUTER: return sprintf(buf, "%d: router\n", dev->node_type);
658	default:		  return sprintf(buf, "%d: <unknown>\n", dev->node_type);
659	}
660}
661
662static ssize_t show_sys_image_guid(struct device *device,
663				   struct device_attribute *dev_attr, char *buf)
664{
665	struct ib_device *dev = container_of(device, struct ib_device, dev);
666	struct ib_device_attr attr;
667	ssize_t ret;
668
669	ret = ib_query_device(dev, &attr);
670	if (ret)
671		return ret;
672
673	return sprintf(buf, "%04x:%04x:%04x:%04x\n",
674		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[0]),
675		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[1]),
676		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[2]),
677		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[3]));
678}
679
680static ssize_t show_node_guid(struct device *device,
681			      struct device_attribute *attr, char *buf)
682{
683	struct ib_device *dev = container_of(device, struct ib_device, dev);
684
685	return sprintf(buf, "%04x:%04x:%04x:%04x\n",
686		       be16_to_cpu(((__be16 *) &dev->node_guid)[0]),
687		       be16_to_cpu(((__be16 *) &dev->node_guid)[1]),
688		       be16_to_cpu(((__be16 *) &dev->node_guid)[2]),
689		       be16_to_cpu(((__be16 *) &dev->node_guid)[3]));
690}
691
692static ssize_t show_node_desc(struct device *device,
693			      struct device_attribute *attr, char *buf)
694{
695	struct ib_device *dev = container_of(device, struct ib_device, dev);
696
697	return sprintf(buf, "%.64s\n", dev->node_desc);
698}
699
700static ssize_t set_node_desc(struct device *device,
701			     struct device_attribute *attr,
702			     const char *buf, size_t count)
703{
704	struct ib_device *dev = container_of(device, struct ib_device, dev);
705	struct ib_device_modify desc = {};
706	int ret;
707
708	if (!dev->modify_device)
709		return -EIO;
710
711	memcpy(desc.node_desc, buf, min_t(int, count, 64));
712	ret = ib_modify_device(dev, IB_DEVICE_MODIFY_NODE_DESC, &desc);
713	if (ret)
714		return ret;
715
716	return count;
717}
718
719static DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
720static DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL);
721static DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL);
722static DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc, set_node_desc);
723
724static struct device_attribute *ib_class_attributes[] = {
725	&dev_attr_node_type,
726	&dev_attr_sys_image_guid,
727	&dev_attr_node_guid,
728	&dev_attr_node_desc
729};
730
731static struct class ib_class = {
732	.name    = "infiniband",
733	.dev_release = ib_device_release,
734#ifdef __linux__
735	.dev_uevent = ib_device_uevent,
736#endif
737};
738
739/* Show a given an attribute in the statistics group */
740static ssize_t show_protocol_stat(const struct device *device,
741			    struct device_attribute *attr, char *buf,
742			    unsigned offset)
743{
744	struct ib_device *dev = container_of(__DECONST(struct device *, device), struct ib_device, dev);
745	union rdma_protocol_stats stats;
746	ssize_t ret;
747
748	ret = dev->get_protocol_stats(dev, &stats);
749	if (ret)
750		return ret;
751
752	return sprintf(buf, "%llu\n",
753		       (unsigned long long) ((u64 *) &stats)[offset]);
754}
755
756/* generate a read-only iwarp statistics attribute */
757#define IW_STATS_ENTRY(name)						\
758static ssize_t show_##name(struct device *device,			\
759			   struct device_attribute *attr, char *buf)	\
760{									\
761	return show_protocol_stat(device, attr, buf,			\
762				  offsetof(struct iw_protocol_stats, name) / \
763				  sizeof (u64));			\
764}									\
765static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
766
767IW_STATS_ENTRY(ipInReceives);
768IW_STATS_ENTRY(ipInHdrErrors);
769IW_STATS_ENTRY(ipInTooBigErrors);
770IW_STATS_ENTRY(ipInNoRoutes);
771IW_STATS_ENTRY(ipInAddrErrors);
772IW_STATS_ENTRY(ipInUnknownProtos);
773IW_STATS_ENTRY(ipInTruncatedPkts);
774IW_STATS_ENTRY(ipInDiscards);
775IW_STATS_ENTRY(ipInDelivers);
776IW_STATS_ENTRY(ipOutForwDatagrams);
777IW_STATS_ENTRY(ipOutRequests);
778IW_STATS_ENTRY(ipOutDiscards);
779IW_STATS_ENTRY(ipOutNoRoutes);
780IW_STATS_ENTRY(ipReasmTimeout);
781IW_STATS_ENTRY(ipReasmReqds);
782IW_STATS_ENTRY(ipReasmOKs);
783IW_STATS_ENTRY(ipReasmFails);
784IW_STATS_ENTRY(ipFragOKs);
785IW_STATS_ENTRY(ipFragFails);
786IW_STATS_ENTRY(ipFragCreates);
787IW_STATS_ENTRY(ipInMcastPkts);
788IW_STATS_ENTRY(ipOutMcastPkts);
789IW_STATS_ENTRY(ipInBcastPkts);
790IW_STATS_ENTRY(ipOutBcastPkts);
791IW_STATS_ENTRY(tcpRtoAlgorithm);
792IW_STATS_ENTRY(tcpRtoMin);
793IW_STATS_ENTRY(tcpRtoMax);
794IW_STATS_ENTRY(tcpMaxConn);
795IW_STATS_ENTRY(tcpActiveOpens);
796IW_STATS_ENTRY(tcpPassiveOpens);
797IW_STATS_ENTRY(tcpAttemptFails);
798IW_STATS_ENTRY(tcpEstabResets);
799IW_STATS_ENTRY(tcpCurrEstab);
800IW_STATS_ENTRY(tcpInSegs);
801IW_STATS_ENTRY(tcpOutSegs);
802IW_STATS_ENTRY(tcpRetransSegs);
803IW_STATS_ENTRY(tcpInErrs);
804IW_STATS_ENTRY(tcpOutRsts);
805
806static struct attribute *iw_proto_stats_attrs[] = {
807	&dev_attr_ipInReceives.attr,
808	&dev_attr_ipInHdrErrors.attr,
809	&dev_attr_ipInTooBigErrors.attr,
810	&dev_attr_ipInNoRoutes.attr,
811	&dev_attr_ipInAddrErrors.attr,
812	&dev_attr_ipInUnknownProtos.attr,
813	&dev_attr_ipInTruncatedPkts.attr,
814	&dev_attr_ipInDiscards.attr,
815	&dev_attr_ipInDelivers.attr,
816	&dev_attr_ipOutForwDatagrams.attr,
817	&dev_attr_ipOutRequests.attr,
818	&dev_attr_ipOutDiscards.attr,
819	&dev_attr_ipOutNoRoutes.attr,
820	&dev_attr_ipReasmTimeout.attr,
821	&dev_attr_ipReasmReqds.attr,
822	&dev_attr_ipReasmOKs.attr,
823	&dev_attr_ipReasmFails.attr,
824	&dev_attr_ipFragOKs.attr,
825	&dev_attr_ipFragFails.attr,
826	&dev_attr_ipFragCreates.attr,
827	&dev_attr_ipInMcastPkts.attr,
828	&dev_attr_ipOutMcastPkts.attr,
829	&dev_attr_ipInBcastPkts.attr,
830	&dev_attr_ipOutBcastPkts.attr,
831	&dev_attr_tcpRtoAlgorithm.attr,
832	&dev_attr_tcpRtoMin.attr,
833	&dev_attr_tcpRtoMax.attr,
834	&dev_attr_tcpMaxConn.attr,
835	&dev_attr_tcpActiveOpens.attr,
836	&dev_attr_tcpPassiveOpens.attr,
837	&dev_attr_tcpAttemptFails.attr,
838	&dev_attr_tcpEstabResets.attr,
839	&dev_attr_tcpCurrEstab.attr,
840	&dev_attr_tcpInSegs.attr,
841	&dev_attr_tcpOutSegs.attr,
842	&dev_attr_tcpRetransSegs.attr,
843	&dev_attr_tcpInErrs.attr,
844	&dev_attr_tcpOutRsts.attr,
845	NULL
846};
847
848static struct attribute_group iw_stats_group = {
849	.name	= "proto_stats",
850	.attrs	= iw_proto_stats_attrs,
851};
852
853int ib_device_register_sysfs(struct ib_device *device,
854                                int (*port_callback)(struct ib_device *, u8, struct kobject *))
855{
856	struct device *class_dev = &device->dev;
857	int ret;
858	int i;
859
860	class_dev->class      = &ib_class;
861	class_dev->parent     = device->dma_device;
862        dev_set_name(class_dev, device->name);
863        dev_set_drvdata(class_dev, device);
864
865	INIT_LIST_HEAD(&device->port_list);
866
867	ret = device_register(class_dev);
868	if (ret)
869		goto err;
870
871	for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) {
872		ret = device_create_file(class_dev, ib_class_attributes[i]);
873		if (ret)
874			goto err_unregister;
875	}
876
877	device->ports_parent = kobject_create_and_add("ports",
878                        	        kobject_get(&class_dev->kobj));
879        if (!device->ports_parent) {
880		ret = -ENOMEM;
881		goto err_put;
882	}
883
884	if (device->node_type == RDMA_NODE_IB_SWITCH) {
885		ret = add_port(device, 0, port_callback);
886		if (ret)
887			goto err_put;
888	} else {
889		for (i = 1; i <= device->phys_port_cnt; ++i) {
890			ret = add_port(device, i, port_callback);
891			if (ret)
892				goto err_put;
893		}
894	}
895
896	if (device->node_type == RDMA_NODE_RNIC && device->get_protocol_stats) {
897		ret = sysfs_create_group(&class_dev->kobj, &iw_stats_group);
898		if (ret)
899			goto err_put;
900	}
901
902	return 0;
903
904err_put:
905	{
906		struct kobject *p, *t;
907		struct ib_port *port;
908
909		list_for_each_entry_safe(p, t, &device->port_list, entry) {
910			list_del(&p->entry);
911			port = container_of(p, struct ib_port, kobj);
912			sysfs_remove_group(p, &pma_group);
913			sysfs_remove_group(p, &port->pkey_group);
914			sysfs_remove_group(p, &port->gid_group);
915			kobject_put(p);
916		}
917	}
918
919	kobject_put(&class_dev->kobj);
920
921err_unregister:
922	device_unregister(class_dev);
923
924err:
925	return ret;
926}
927
928void ib_device_unregister_sysfs(struct ib_device *device)
929{
930	struct kobject *p, *t;
931	struct ib_port *port;
932	int i;
933
934	/* Hold kobject until ib_dealloc_device() */
935	kobject_get(&device->dev.kobj);
936
937	for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) {
938			device_remove_file(&device->dev, ib_class_attributes[i]);
939	}
940
941	list_for_each_entry_safe(p, t, &device->port_list, entry) {
942		list_del(&p->entry);
943		port = container_of(p, struct ib_port, kobj);
944		sysfs_remove_group(p, &pma_group);
945		sysfs_remove_group(p, &port->pkey_group);
946		sysfs_remove_group(p, &port->gid_group);
947		kobject_put(p);
948	}
949
950	kobject_put(device->ports_parent);
951	device_unregister(&device->dev);
952}
953
954int ib_sysfs_setup(void)
955{
956	return class_register(&ib_class);
957}
958
959void ib_sysfs_cleanup(void)
960{
961	class_unregister(&ib_class);
962}
963
964/*int ib_sysfs_create_port_files(struct ib_device *device,
965			       int (*create)(struct ib_device *dev, u8 port_num,
966					     struct kobject *kobj))
967{
968	struct kobject *p;
969	struct ib_port *port;
970	int ret = 0;
971
972	list_for_each_entry(p, &device->port_list, entry) {
973		port = container_of(p, struct ib_port, kobj);
974		ret = create(device, port->port_num, &port->kobj);
975		if (ret)
976			break;
977	}
978
979	return ret;
980}
981EXPORT_SYMBOL(ib_sysfs_create_port_files);*/
982