sysfs.c revision 338615
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;		/* in deci-Gb/sec */
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 IB_SPEED_DDR:
192		speed = " DDR";
193		rate = 50;
194		break;
195	case IB_SPEED_QDR:
196		speed = " QDR";
197		rate = 100;
198		break;
199	case IB_SPEED_FDR10:
200		speed = " FDR10";
201		rate = 100;
202		break;
203	case IB_SPEED_FDR:
204		speed = " FDR";
205		rate = 140;
206		break;
207	case IB_SPEED_EDR:
208		speed = " EDR";
209		rate = 250;
210		break;
211	case IB_SPEED_SDR:
212	default:		/* default to SDR for invalid rates */
213		rate = 25;
214		break;
215	}
216
217	rate *= ib_width_enum_to_int(attr.active_width);
218	if (rate < 0)
219		return -EINVAL;
220
221	return sprintf(buf, "%d%s Gb/sec (%dX%s)\n",
222		       rate / 10, rate % 10 ? ".5" : "",
223		       ib_width_enum_to_int(attr.active_width), speed);
224}
225
226static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused,
227			       char *buf)
228{
229	struct ib_port_attr attr;
230
231	ssize_t ret;
232
233	ret = ib_query_port(p->ibdev, p->port_num, &attr);
234	if (ret)
235		return ret;
236
237	switch (attr.phys_state) {
238	case 1:  return sprintf(buf, "1: Sleep\n");
239	case 2:  return sprintf(buf, "2: Polling\n");
240	case 3:  return sprintf(buf, "3: Disabled\n");
241	case 4:  return sprintf(buf, "4: PortConfigurationTraining\n");
242	case 5:  return sprintf(buf, "5: LinkUp\n");
243	case 6:  return sprintf(buf, "6: LinkErrorRecovery\n");
244	case 7:  return sprintf(buf, "7: Phy Test\n");
245	default: return sprintf(buf, "%d: <unknown>\n", attr.phys_state);
246	}
247}
248
249static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused,
250			       char *buf)
251{
252	switch (rdma_port_get_link_layer(p->ibdev, p->port_num)) {
253	case IB_LINK_LAYER_INFINIBAND:
254		return sprintf(buf, "%s\n", "IB");
255	case IB_LINK_LAYER_ETHERNET:
256		return sprintf(buf, "%s\n", "Ethernet");
257	default:
258		return sprintf(buf, "%s\n", "Unknown");
259	}
260}
261
262static PORT_ATTR_RO(state);
263static PORT_ATTR_RO(lid);
264static PORT_ATTR_RO(lid_mask_count);
265static PORT_ATTR_RO(sm_lid);
266static PORT_ATTR_RO(sm_sl);
267static PORT_ATTR_RO(cap_mask);
268static PORT_ATTR_RO(rate);
269static PORT_ATTR_RO(phys_state);
270static PORT_ATTR_RO(link_layer);
271
272static struct attribute *port_default_attrs[] = {
273	&port_attr_state.attr,
274	&port_attr_lid.attr,
275	&port_attr_lid_mask_count.attr,
276	&port_attr_sm_lid.attr,
277	&port_attr_sm_sl.attr,
278	&port_attr_cap_mask.attr,
279	&port_attr_rate.attr,
280	&port_attr_phys_state.attr,
281	&port_attr_link_layer.attr,
282	NULL
283};
284
285static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
286			     char *buf)
287{
288	struct port_table_attribute *tab_attr =
289		container_of(attr, struct port_table_attribute, attr);
290	union ib_gid gid;
291	ssize_t ret;
292	u16 *raw;
293
294	ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid);
295	if (ret)
296		return ret;
297
298	raw = (u16 *)gid.raw;
299	return sprintf(buf, "%.4x:%.4x:%.4x:%.4x:%.4x:%.4x:%.4x:%.4x\n",
300	    htons(raw[0]), htons(raw[1]), htons(raw[2]), htons(raw[3]),
301	    htons(raw[4]), htons(raw[5]), htons(raw[6]), htons(raw[7]));
302}
303
304static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr,
305			      char *buf)
306{
307	struct port_table_attribute *tab_attr =
308		container_of(attr, struct port_table_attribute, attr);
309	u16 pkey;
310	ssize_t ret;
311
312	ret = ib_query_pkey(p->ibdev, p->port_num, tab_attr->index, &pkey);
313	if (ret)
314		return ret;
315
316	return sprintf(buf, "0x%04x\n", pkey);
317}
318
319static ssize_t get_pma_counters(struct ib_port *p, struct port_attribute *attr,
320                                char *buf, int c_ext)
321{
322        struct port_table_attribute *tab_attr =
323                container_of(attr, struct port_table_attribute, attr);
324        int offset = tab_attr->index & 0xffff;
325        int width  = (tab_attr->index >> 16) & 0xff;
326        struct ib_mad *in_mad  = NULL;
327        struct ib_mad *out_mad = NULL;
328        ssize_t ret;
329
330        if (!p->ibdev->process_mad)
331                return -ENXIO;
332
333        in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
334        out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
335        if (!in_mad || !out_mad) {
336                ret = -ENOMEM;
337                goto out;
338        }
339
340        in_mad->mad_hdr.base_version  = 1;
341        in_mad->mad_hdr.mgmt_class    = IB_MGMT_CLASS_PERF_MGMT;
342        in_mad->mad_hdr.class_version = 1;
343        in_mad->mad_hdr.method        = IB_MGMT_METHOD_GET;
344        if (c_ext)
345                in_mad->mad_hdr.attr_id = IB_PMA_PORT_COUNTERS_EXT;
346        else
347                in_mad->mad_hdr.attr_id = IB_PMA_PORT_COUNTERS;
348
349        in_mad->data[41] = p->port_num; /* PortSelect field */
350
351        if ((p->ibdev->process_mad(p->ibdev, IB_MAD_IGNORE_MKEY,
352                 p->port_num, NULL, NULL, in_mad, out_mad) &
353             (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) !=
354            (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) {
355                ret = -EINVAL;
356                goto out;
357        }
358
359        switch (width) {
360        case 4:
361                ret = sprintf(buf, "%u\n", (out_mad->data[40 + offset / 8] >>
362                                            (4 - (offset % 8))) & 0xf);
363                break;
364        case 8:
365                ret = sprintf(buf, "%u\n", out_mad->data[40 + offset / 8]);
366                break;
367        case 16:
368                ret = sprintf(buf, "%u\n",
369                              be16_to_cpup((__be16 *)(out_mad->data + 40 + offset / 8)));
370                break;
371        case 32:
372                ret = sprintf(buf, "%u\n",
373                              be32_to_cpup((__be32 *)(out_mad->data + 40 + offset / 8)));
374                break;
375        case 64:
376                ret = sprintf(buf, "%llu\n", (unsigned long long)
377                              be64_to_cpup((__be64 *)(out_mad->data + 40 + offset / 8)));
378                break;
379        default:
380                ret = 0;
381        }
382
383out:
384        kfree(in_mad);
385        kfree(out_mad);
386
387        return ret;
388}
389
390#define PORT_PMA_ATTR(_name, _counter, _width, _offset)                 \
391struct port_table_attribute port_pma_attr_##_name = {                   \
392        .attr  = __ATTR(_name, S_IRUGO, show_pma_counter, NULL),        \
393        .index = (_offset) | ((_width) << 16) | ((_counter) << 24)      \
394}
395
396static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
397                                char *buf)
398{
399        return get_pma_counters(p, attr, buf, 0);
400}
401
402static PORT_PMA_ATTR(symbol_error                   ,  0, 16,  32);
403static PORT_PMA_ATTR(link_error_recovery            ,  1,  8,  48);
404static PORT_PMA_ATTR(link_downed                    ,  2,  8,  56);
405static PORT_PMA_ATTR(port_rcv_errors                ,  3, 16,  64);
406static PORT_PMA_ATTR(port_rcv_remote_physical_errors,  4, 16,  80);
407static PORT_PMA_ATTR(port_rcv_switch_relay_errors   ,  5, 16,  96);
408static PORT_PMA_ATTR(port_xmit_discards             ,  6, 16, 112);
409static PORT_PMA_ATTR(port_xmit_constraint_errors    ,  7,  8, 128);
410static PORT_PMA_ATTR(port_rcv_constraint_errors     ,  8,  8, 136);
411static PORT_PMA_ATTR(local_link_integrity_errors    ,  9,  4, 152);
412static PORT_PMA_ATTR(excessive_buffer_overrun_errors, 10,  4, 156);
413static PORT_PMA_ATTR(VL15_dropped                   , 11, 16, 176);
414static PORT_PMA_ATTR(port_xmit_data                 , 12, 32, 192);
415static PORT_PMA_ATTR(port_rcv_data                  , 13, 32, 224);
416static PORT_PMA_ATTR(port_xmit_packets              , 14, 32, 256);
417static PORT_PMA_ATTR(port_rcv_packets               , 15, 32, 288);
418
419static struct attribute *pma_attrs[] = {
420        &port_pma_attr_symbol_error.attr.attr,
421        &port_pma_attr_link_error_recovery.attr.attr,
422        &port_pma_attr_link_downed.attr.attr,
423        &port_pma_attr_port_rcv_errors.attr.attr,
424        &port_pma_attr_port_rcv_remote_physical_errors.attr.attr,
425        &port_pma_attr_port_rcv_switch_relay_errors.attr.attr,
426        &port_pma_attr_port_xmit_discards.attr.attr,
427        &port_pma_attr_port_xmit_constraint_errors.attr.attr,
428        &port_pma_attr_port_rcv_constraint_errors.attr.attr,
429        &port_pma_attr_local_link_integrity_errors.attr.attr,
430        &port_pma_attr_excessive_buffer_overrun_errors.attr.attr,
431        &port_pma_attr_VL15_dropped.attr.attr,
432        &port_pma_attr_port_xmit_data.attr.attr,
433        &port_pma_attr_port_rcv_data.attr.attr,
434        &port_pma_attr_port_xmit_packets.attr.attr,
435        &port_pma_attr_port_rcv_packets.attr.attr,
436        NULL
437};
438
439static struct attribute_group pma_group = {
440	.name  = "counters",
441	.attrs  = pma_attrs
442};
443
444#define PORT_PMA_ATTR_EXT(_name, _counter, _width, _offset)             \
445struct port_table_attribute port_pma_attr_ext_##_name = {               \
446        .attr  = __ATTR(_name, S_IRUGO, show_pma_counter_ext, NULL),    \
447        .index = (_offset) | ((_width) << 16) | ((_counter) << 24)      \
448}
449
450static ssize_t show_pma_counter_ext(struct ib_port *p,
451                                    struct port_attribute *attr, char *buf)
452{
453        return get_pma_counters(p, attr, buf, 1);
454}
455
456static PORT_PMA_ATTR_EXT(port_xmit_data_64           ,  0, 64,  64);
457static PORT_PMA_ATTR_EXT(port_rcv_data_64            ,  0, 64,  128);
458static PORT_PMA_ATTR_EXT(port_xmit_packets_64        ,  0, 64,  192);
459static PORT_PMA_ATTR_EXT(port_rcv_packets_64         ,  0, 64,  256);
460static PORT_PMA_ATTR_EXT(port_unicast_xmit_packets   ,  0, 64,  320);
461static PORT_PMA_ATTR_EXT(port_unicast_rcv_packets    ,  0, 64,  384);
462static PORT_PMA_ATTR_EXT(port_multicast_xmit_packets ,  0, 64,  448);
463static PORT_PMA_ATTR_EXT(port_multicast_rcv_packets  ,  0, 64,  512);
464
465static struct attribute *pma_attrs_ext[] = {
466        &port_pma_attr_ext_port_xmit_data_64.attr.attr,
467        &port_pma_attr_ext_port_rcv_data_64.attr.attr,
468        &port_pma_attr_ext_port_xmit_packets_64.attr.attr,
469        &port_pma_attr_ext_port_rcv_packets_64.attr.attr,
470        &port_pma_attr_ext_port_unicast_xmit_packets.attr.attr,
471        &port_pma_attr_ext_port_unicast_rcv_packets.attr.attr,
472        &port_pma_attr_ext_port_multicast_xmit_packets.attr.attr,
473        &port_pma_attr_ext_port_multicast_rcv_packets.attr.attr,
474        NULL
475};
476
477static struct attribute_group pma_ext_group = {
478        .name  = "counters_ext",
479        .attrs  = pma_attrs_ext
480};
481
482static void ib_port_release(struct kobject *kobj)
483{
484	struct ib_port *p = container_of(kobj, struct ib_port, kobj);
485	struct attribute *a;
486	int i;
487
488	for (i = 0; (a = p->gid_group.attrs[i]); ++i)
489		kfree(a);
490
491	kfree(p->gid_group.attrs);
492
493	for (i = 0; (a = p->pkey_group.attrs[i]); ++i)
494		kfree(a);
495
496	kfree(p->pkey_group.attrs);
497
498	kfree(p);
499}
500
501static struct kobj_type port_type = {
502	.release       = ib_port_release,
503	.sysfs_ops     = &port_sysfs_ops,
504	.default_attrs = port_default_attrs
505};
506
507static void ib_device_release(struct device *device)
508{
509	struct ib_device *dev = container_of(device, struct ib_device, dev);
510
511	kfree(dev);
512}
513
514#ifdef __linux__
515/* BSD supports this through devfs(5) and devd(8). */
516static int ib_device_uevent(struct device *device,
517			    struct kobj_uevent_env *env)
518{
519	struct ib_device *dev = container_of(device, struct ib_device, dev);
520
521	if (add_uevent_var(env, "NAME=%s", dev->name))
522		return -ENOMEM;
523
524	/*
525	 * It would be nice to pass the node GUID with the event...
526	 */
527
528	return 0;
529}
530#endif
531
532static struct attribute **
533alloc_group_attrs(ssize_t (*show)(struct ib_port *,
534				  struct port_attribute *, char *buf),
535		  int len)
536{
537	struct attribute **tab_attr;
538	struct port_table_attribute *element;
539	int i;
540
541	tab_attr = kcalloc(1 + len, sizeof(struct attribute *), GFP_KERNEL);
542	if (!tab_attr)
543		return NULL;
544
545	for (i = 0; i < len; i++) {
546		element = kzalloc(sizeof(struct port_table_attribute),
547				  GFP_KERNEL);
548		if (!element)
549			goto err;
550
551		if (snprintf(element->name, sizeof(element->name),
552			     "%d", i) >= sizeof(element->name)) {
553			kfree(element);
554			goto err;
555		}
556
557		element->attr.attr.name  = element->name;
558		element->attr.attr.mode  = S_IRUGO;
559		element->attr.show       = show;
560		element->index		 = i;
561
562		tab_attr[i] = &element->attr.attr;
563	}
564
565	return tab_attr;
566
567err:
568	while (--i >= 0)
569		kfree(tab_attr[i]);
570	kfree(tab_attr);
571	return NULL;
572}
573
574static int add_port(struct ib_device *device, int port_num,
575                    int (*port_callback)(struct ib_device *,
576                                         u8, struct kobject *))
577{
578	struct ib_port *p;
579	struct ib_port_attr attr;
580	int i;
581	int ret;
582
583	ret = ib_query_port(device, port_num, &attr);
584	if (ret)
585		return ret;
586
587	p = kzalloc(sizeof *p, GFP_KERNEL);
588	if (!p)
589		return -ENOMEM;
590
591	p->ibdev      = device;
592	p->port_num   = port_num;
593
594	ret = kobject_init_and_add(&p->kobj, &port_type,
595				   kobject_get(device->ports_parent),
596				   "%d", port_num);
597	if (ret)
598		goto err_put;
599
600	ret = sysfs_create_group(&p->kobj, &pma_group);
601	if (ret)
602		goto err_put;
603
604        ret = sysfs_create_group(&p->kobj, &pma_ext_group);
605        if (ret)
606                goto err_remove_pma;
607
608	p->gid_group.name  = "gids";
609	p->gid_group.attrs = alloc_group_attrs(show_port_gid, attr.gid_tbl_len);
610	if (!p->gid_group.attrs)
611		goto err_remove_pma_ext;
612
613	ret = sysfs_create_group(&p->kobj, &p->gid_group);
614	if (ret)
615		goto err_free_gid;
616
617	p->pkey_group.name  = "pkeys";
618	p->pkey_group.attrs = alloc_group_attrs(show_port_pkey,
619						attr.pkey_tbl_len);
620	if (!p->pkey_group.attrs)
621		goto err_remove_gid;
622
623	ret = sysfs_create_group(&p->kobj, &p->pkey_group);
624	if (ret)
625		goto err_free_pkey;
626
627        if (port_callback) {
628                ret = port_callback(device, port_num, &p->kobj);
629                if (ret)
630                        goto err_remove_pkey;
631        }
632
633	list_add_tail(&p->kobj.entry, &device->port_list);
634
635#ifdef __linux__
636	kobject_uevent(&p->kobj, KOBJ_ADD);
637#endif
638	return 0;
639
640err_remove_pkey:
641        sysfs_remove_group(&p->kobj, &p->pkey_group);
642
643err_free_pkey:
644	for (i = 0; i < attr.pkey_tbl_len; ++i)
645		kfree(p->pkey_group.attrs[i]);
646
647	kfree(p->pkey_group.attrs);
648
649err_remove_gid:
650	sysfs_remove_group(&p->kobj, &p->gid_group);
651
652err_free_gid:
653	for (i = 0; i < attr.gid_tbl_len; ++i)
654		kfree(p->gid_group.attrs[i]);
655
656	kfree(p->gid_group.attrs);
657
658err_remove_pma_ext:
659        sysfs_remove_group(&p->kobj, &pma_ext_group);
660
661err_remove_pma:
662	sysfs_remove_group(&p->kobj, &pma_group);
663
664err_put:
665	kobject_put(device->ports_parent);
666	kfree(p);
667	return ret;
668}
669
670static ssize_t show_node_type(struct device *device,
671			      struct device_attribute *attr, char *buf)
672{
673	struct ib_device *dev = container_of(device, struct ib_device, dev);
674
675	switch (dev->node_type) {
676	case RDMA_NODE_IB_CA:	  return sprintf(buf, "%d: CA\n", dev->node_type);
677	case RDMA_NODE_RNIC:	  return sprintf(buf, "%d: RNIC\n", dev->node_type);
678	case RDMA_NODE_IB_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type);
679	case RDMA_NODE_IB_ROUTER: return sprintf(buf, "%d: router\n", dev->node_type);
680	default:		  return sprintf(buf, "%d: <unknown>\n", dev->node_type);
681	}
682}
683
684static ssize_t show_sys_image_guid(struct device *device,
685				   struct device_attribute *dev_attr, char *buf)
686{
687	struct ib_device *dev = container_of(device, struct ib_device, dev);
688	struct ib_device_attr attr;
689	ssize_t ret;
690
691	ret = ib_query_device(dev, &attr);
692	if (ret)
693		return ret;
694
695	return sprintf(buf, "%04x:%04x:%04x:%04x\n",
696		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[0]),
697		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[1]),
698		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[2]),
699		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[3]));
700}
701
702static ssize_t show_node_guid(struct device *device,
703			      struct device_attribute *attr, char *buf)
704{
705	struct ib_device *dev = container_of(device, struct ib_device, dev);
706
707	return sprintf(buf, "%04x:%04x:%04x:%04x\n",
708		       be16_to_cpu(((__be16 *) &dev->node_guid)[0]),
709		       be16_to_cpu(((__be16 *) &dev->node_guid)[1]),
710		       be16_to_cpu(((__be16 *) &dev->node_guid)[2]),
711		       be16_to_cpu(((__be16 *) &dev->node_guid)[3]));
712}
713
714static ssize_t show_node_desc(struct device *device,
715			      struct device_attribute *attr, char *buf)
716{
717	struct ib_device *dev = container_of(device, struct ib_device, dev);
718
719	return sprintf(buf, "%.64s\n", dev->node_desc);
720}
721
722static ssize_t set_node_desc(struct device *device,
723			     struct device_attribute *attr,
724			     const char *buf, size_t count)
725{
726	struct ib_device *dev = container_of(device, struct ib_device, dev);
727	struct ib_device_modify desc = {};
728	int ret;
729
730	if (!dev->modify_device)
731		return -EIO;
732
733	memcpy(desc.node_desc, buf, min_t(int, count, 64));
734	ret = ib_modify_device(dev, IB_DEVICE_MODIFY_NODE_DESC, &desc);
735	if (ret)
736		return ret;
737
738	return count;
739}
740
741static DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
742static DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL);
743static DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL);
744static DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc, set_node_desc);
745
746static struct device_attribute *ib_class_attributes[] = {
747	&dev_attr_node_type,
748	&dev_attr_sys_image_guid,
749	&dev_attr_node_guid,
750	&dev_attr_node_desc
751};
752
753static struct class ib_class = {
754	.name    = "infiniband",
755	.dev_release = ib_device_release,
756#ifdef __linux__
757	.dev_uevent = ib_device_uevent,
758#endif
759};
760
761/* Show a given an attribute in the statistics group */
762static ssize_t show_protocol_stat(const struct device *device,
763			    struct device_attribute *attr, char *buf,
764			    unsigned offset)
765{
766	struct ib_device *dev = container_of(__DECONST(struct device *, device), struct ib_device, dev);
767	union rdma_protocol_stats stats;
768	ssize_t ret;
769
770	ret = dev->get_protocol_stats(dev, &stats);
771	if (ret)
772		return ret;
773
774	return sprintf(buf, "%llu\n",
775		       (unsigned long long) ((u64 *) &stats)[offset]);
776}
777
778/* generate a read-only iwarp statistics attribute */
779#define IW_STATS_ENTRY(name)						\
780static ssize_t show_##name(struct device *device,			\
781			   struct device_attribute *attr, char *buf)	\
782{									\
783	return show_protocol_stat(device, attr, buf,			\
784				  offsetof(struct iw_protocol_stats, name) / \
785				  sizeof (u64));			\
786}									\
787static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
788
789IW_STATS_ENTRY(ipInReceives);
790IW_STATS_ENTRY(ipInHdrErrors);
791IW_STATS_ENTRY(ipInTooBigErrors);
792IW_STATS_ENTRY(ipInNoRoutes);
793IW_STATS_ENTRY(ipInAddrErrors);
794IW_STATS_ENTRY(ipInUnknownProtos);
795IW_STATS_ENTRY(ipInTruncatedPkts);
796IW_STATS_ENTRY(ipInDiscards);
797IW_STATS_ENTRY(ipInDelivers);
798IW_STATS_ENTRY(ipOutForwDatagrams);
799IW_STATS_ENTRY(ipOutRequests);
800IW_STATS_ENTRY(ipOutDiscards);
801IW_STATS_ENTRY(ipOutNoRoutes);
802IW_STATS_ENTRY(ipReasmTimeout);
803IW_STATS_ENTRY(ipReasmReqds);
804IW_STATS_ENTRY(ipReasmOKs);
805IW_STATS_ENTRY(ipReasmFails);
806IW_STATS_ENTRY(ipFragOKs);
807IW_STATS_ENTRY(ipFragFails);
808IW_STATS_ENTRY(ipFragCreates);
809IW_STATS_ENTRY(ipInMcastPkts);
810IW_STATS_ENTRY(ipOutMcastPkts);
811IW_STATS_ENTRY(ipInBcastPkts);
812IW_STATS_ENTRY(ipOutBcastPkts);
813IW_STATS_ENTRY(tcpRtoAlgorithm);
814IW_STATS_ENTRY(tcpRtoMin);
815IW_STATS_ENTRY(tcpRtoMax);
816IW_STATS_ENTRY(tcpMaxConn);
817IW_STATS_ENTRY(tcpActiveOpens);
818IW_STATS_ENTRY(tcpPassiveOpens);
819IW_STATS_ENTRY(tcpAttemptFails);
820IW_STATS_ENTRY(tcpEstabResets);
821IW_STATS_ENTRY(tcpCurrEstab);
822IW_STATS_ENTRY(tcpInSegs);
823IW_STATS_ENTRY(tcpOutSegs);
824IW_STATS_ENTRY(tcpRetransSegs);
825IW_STATS_ENTRY(tcpInErrs);
826IW_STATS_ENTRY(tcpOutRsts);
827
828static struct attribute *iw_proto_stats_attrs[] = {
829	&dev_attr_ipInReceives.attr,
830	&dev_attr_ipInHdrErrors.attr,
831	&dev_attr_ipInTooBigErrors.attr,
832	&dev_attr_ipInNoRoutes.attr,
833	&dev_attr_ipInAddrErrors.attr,
834	&dev_attr_ipInUnknownProtos.attr,
835	&dev_attr_ipInTruncatedPkts.attr,
836	&dev_attr_ipInDiscards.attr,
837	&dev_attr_ipInDelivers.attr,
838	&dev_attr_ipOutForwDatagrams.attr,
839	&dev_attr_ipOutRequests.attr,
840	&dev_attr_ipOutDiscards.attr,
841	&dev_attr_ipOutNoRoutes.attr,
842	&dev_attr_ipReasmTimeout.attr,
843	&dev_attr_ipReasmReqds.attr,
844	&dev_attr_ipReasmOKs.attr,
845	&dev_attr_ipReasmFails.attr,
846	&dev_attr_ipFragOKs.attr,
847	&dev_attr_ipFragFails.attr,
848	&dev_attr_ipFragCreates.attr,
849	&dev_attr_ipInMcastPkts.attr,
850	&dev_attr_ipOutMcastPkts.attr,
851	&dev_attr_ipInBcastPkts.attr,
852	&dev_attr_ipOutBcastPkts.attr,
853	&dev_attr_tcpRtoAlgorithm.attr,
854	&dev_attr_tcpRtoMin.attr,
855	&dev_attr_tcpRtoMax.attr,
856	&dev_attr_tcpMaxConn.attr,
857	&dev_attr_tcpActiveOpens.attr,
858	&dev_attr_tcpPassiveOpens.attr,
859	&dev_attr_tcpAttemptFails.attr,
860	&dev_attr_tcpEstabResets.attr,
861	&dev_attr_tcpCurrEstab.attr,
862	&dev_attr_tcpInSegs.attr,
863	&dev_attr_tcpOutSegs.attr,
864	&dev_attr_tcpRetransSegs.attr,
865	&dev_attr_tcpInErrs.attr,
866	&dev_attr_tcpOutRsts.attr,
867	NULL
868};
869
870static struct attribute_group iw_stats_group = {
871	.name	= "proto_stats",
872	.attrs	= iw_proto_stats_attrs,
873};
874
875int ib_device_register_sysfs(struct ib_device *device,
876                                int (*port_callback)(struct ib_device *, u8, struct kobject *))
877{
878	struct device *class_dev = &device->dev;
879	int ret;
880	int i;
881
882	class_dev->class      = &ib_class;
883	class_dev->parent     = device->dma_device;
884        dev_set_name(class_dev, device->name);
885        dev_set_drvdata(class_dev, device);
886
887	INIT_LIST_HEAD(&device->port_list);
888
889	ret = device_register(class_dev);
890	if (ret)
891		goto err;
892
893	for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) {
894		ret = device_create_file(class_dev, ib_class_attributes[i]);
895		if (ret)
896			goto err_unregister;
897	}
898
899	device->ports_parent = kobject_create_and_add("ports",
900                        	        kobject_get(&class_dev->kobj));
901        if (!device->ports_parent) {
902		ret = -ENOMEM;
903		goto err_put;
904	}
905
906	if (device->node_type == RDMA_NODE_IB_SWITCH) {
907		ret = add_port(device, 0, port_callback);
908		if (ret)
909			goto err_put;
910	} else {
911		for (i = 1; i <= device->phys_port_cnt; ++i) {
912			ret = add_port(device, i, port_callback);
913			if (ret)
914				goto err_put;
915		}
916	}
917
918	if (device->node_type == RDMA_NODE_RNIC && device->get_protocol_stats) {
919		ret = sysfs_create_group(&class_dev->kobj, &iw_stats_group);
920		if (ret)
921			goto err_put;
922	}
923
924	return 0;
925
926err_put:
927	{
928		struct kobject *p, *t;
929		struct ib_port *port;
930
931		list_for_each_entry_safe(p, t, &device->port_list, entry) {
932			list_del(&p->entry);
933			port = container_of(p, struct ib_port, kobj);
934			sysfs_remove_group(p, &pma_group);
935			sysfs_remove_group(p, &port->pkey_group);
936			sysfs_remove_group(p, &port->gid_group);
937			kobject_put(p);
938		}
939	}
940
941	kobject_put(&class_dev->kobj);
942
943err_unregister:
944	device_unregister(class_dev);
945
946err:
947	return ret;
948}
949
950void ib_device_unregister_sysfs(struct ib_device *device)
951{
952	struct kobject *p, *t;
953	struct ib_port *port;
954	int i;
955
956	/* Hold kobject until ib_dealloc_device() */
957	kobject_get(&device->dev.kobj);
958
959	for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) {
960			device_remove_file(&device->dev, ib_class_attributes[i]);
961	}
962
963	list_for_each_entry_safe(p, t, &device->port_list, entry) {
964		list_del(&p->entry);
965		port = container_of(p, struct ib_port, kobj);
966		sysfs_remove_group(p, &pma_group);
967		sysfs_remove_group(p, &port->pkey_group);
968		sysfs_remove_group(p, &port->gid_group);
969		kobject_put(p);
970	}
971
972	kobject_put(device->ports_parent);
973	device_unregister(&device->dev);
974}
975
976int ib_sysfs_setup(void)
977{
978	return class_register(&ib_class);
979}
980
981void ib_sysfs_cleanup(void)
982{
983	class_unregister(&ib_class);
984}
985
986/*int ib_sysfs_create_port_files(struct ib_device *device,
987			       int (*create)(struct ib_device *dev, u8 port_num,
988					     struct kobject *kobj))
989{
990	struct kobject *p;
991	struct ib_port *port;
992	int ret = 0;
993
994	list_for_each_entry(p, &device->port_list, entry) {
995		port = container_of(p, struct ib_port, kobj);
996		ret = create(device, port->port_num, &port->kobj);
997		if (ret)
998			break;
999	}
1000
1001	return ret;
1002}
1003EXPORT_SYMBOL(ib_sysfs_create_port_files);*/
1004