[openib-general] [PATCH] move PMA counters to sysfs

Roland Dreier roland at topspin.com
Mon Sep 13 20:28:59 PDT 2004


This puts the PMA counters under /sys/class/infiniband/DEV/ports/N/counters/
and kills off the last of /proc/infiniband/core.

 - R.

Index: infiniband/core/Makefile
===================================================================
--- infiniband/core/Makefile	(revision 803)
+++ infiniband/core/Makefile	(working copy)
@@ -39,8 +39,7 @@
     ib_device.o \
     core_main.o \
     core_fmr_pool.o \
-    core_cache.o \
-    core_proc.o
+    core_cache.o
 
 ib_mad-objs := \
     mad_main.o \
Index: infiniband/core/core_proc.c
===================================================================
--- infiniband/core/core_proc.c	(revision 803)
+++ infiniband/core/core_proc.c	(working copy)
@@ -1,329 +0,0 @@
-/*
-  This software is available to you under a choice of one of two
-  licenses.  You may choose to be licensed under the terms of the GNU
-  General Public License (GPL) Version 2, available at
-  <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD
-  license, available in the LICENSE.TXT file accompanying this
-  software.  These details are also available at
-  <http://openib.org/license.html>.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-  SOFTWARE.
-
-  Copyright (c) 2004 Topspin Communications.  All rights reserved.
-
-  $Id$
-*/
-
-/*
-  We want to make a directory tree like:
-
-  /proc/infiniband/core/
-  hca1/
-  info
-  port1/
-  counters
-  info
-  gid_table
-  pkey_table
-  port2...
-  hca2...
-*/
-
-#include "core_priv.h"
-
-#include "pm_access.h"
-
-#include "ts_kernel_trace.h"
-#include "ts_kernel_services.h"
-
-#include <linux/version.h>
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-
-struct ib_core_proc {
-	int                    index;
-	char                   dev_dir_name[16];
-	struct proc_dir_entry *dev_dir;
-	struct ib_port_proc   *port;
-};
-
-struct ib_port_proc {
-	struct ib_device      *device;
-	int                    port_num;
-	struct proc_dir_entry *port_dir;
-	struct proc_dir_entry *counters;
-};
-
-static int index = 1;
-static struct proc_dir_entry *core_dir;
-
-static void *ib_counters_seq_start(struct seq_file *file,
-				   loff_t *pos)
-{
-	if (*pos)
-		return NULL;
-	else
-		return (void *) 1UL;
-}
-
-static void *ib_counters_seq_next(struct seq_file *file,
-				  void *iter_ptr,
-				  loff_t *pos)
-{
-	(*pos)++;
-	return NULL;
-}
-
-static void ib_counters_seq_stop(struct seq_file *file,
-				 void *iter_ptr)
-{
-	/* nothing for now */
-}
-
-static int ib_counters_seq_show(struct seq_file *file,
-				void *iter_ptr)
-{
-	struct ib_port_proc *proc_port = file->private;
-	struct ib_mad       *in_mad = NULL;
-	struct ib_mad       *out_mad = NULL;
-
-	struct ib_pm_port_counters *counters = NULL;
-
-	if (!proc_port->device->mad_process) {
-		seq_puts(file, "<No performance management agent available>\n");
-		return 0;
-	}
-
-	in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
-	out_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
-	if (!in_mad || !out_mad) {
-		seq_puts(file, "<Failed to allocate MAD buffer>\n");
-		goto out;
-	}
-
-	counters = kmalloc(sizeof *counters, GFP_KERNEL);
-	if (!counters) {
-		seq_puts(file, "<Failed to allocate counters buffer>\n");
-		goto out;
-	}
-
-	memset(in_mad, 0, sizeof *in_mad);
-	in_mad->format_version = 1;
-	in_mad->mgmt_class     = IB_MGMT_CLASS_PERF;
-	in_mad->class_version  = 1;
-	in_mad->r_method       = IB_MGMT_METHOD_GET;
-	in_mad->attribute_id   = cpu_to_be16(IB_PM_ATTRIB_PORT_COUNTERS);
-	in_mad->dqpn           = 1;
-	in_mad->port           = proc_port->port_num;
-
-	memset(counters, 0, sizeof *counters);
-	counters->port_select = proc_port->port_num;
-	ib_pm_port_counters_pack(counters, IB_MAD_TO_PM_DATA(in_mad));
-
-	if ((proc_port->device->mad_process(proc_port->device,
-					    1,
-					    in_mad,
-					    out_mad) &
-	     (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) !=
-	    (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) {
-		seq_puts(file, "<Performance management query failed>\n");
-		goto out;
-	}
-
-	ib_pm_port_counters_unpack(IB_MAD_TO_PM_DATA(out_mad), counters);
-
-	seq_printf(file, "Symbol error counter:                %10u\n",
-		   counters->symbol_error_counter);
-	seq_printf(file, "Link error recovery counter:         %10u\n",
-		   counters->link_error_recovery_counter);
-	seq_printf(file, "Link downed counter:                 %10u\n",
-		   counters->link_downed_counter);
-	seq_printf(file, "Port receive errors:                 %10u\n",
-		   counters->port_rcv_errors);
-	seq_printf(file, "Port receive remote physical errors: %10u\n",
-		   counters->port_rcv_remote_physical_errors);
-	seq_printf(file, "Port receive switch relay errors:    %10u\n",
-		   counters->port_rcv_switch_relay_errors);
-	seq_printf(file, "Port transmit discards:              %10u\n",
-		   counters->port_xmit_discards);
-	seq_printf(file, "Port transmit constrain errors:      %10u\n",
-		   counters->port_xmit_constrain_errors);
-	seq_printf(file, "Port receive constrain errors:       %10u\n",
-		   counters->port_rcv_constrain_errors);
-	seq_printf(file, "Local link integrity errors:         %10u\n",
-		   counters->local_link_integrity_errors);
-	seq_printf(file, "Excessive buffer overrun errors:     %10u\n",
-		   counters->excessive_buffer_overrun_errors);
-	seq_printf(file, "VL15 dropped:                        %10u\n",
-		   counters->vl15_dropped);
-	seq_printf(file, "Port transmit data:                  %10u\n",
-		   counters->port_xmit_data);
-	seq_printf(file, "Port receive data:                   %10u\n",
-		   counters->port_rcv_data);
-	seq_printf(file, "Port transmit packets:               %10u\n",
-		   counters->port_xmit_pkts);
-	seq_printf(file, "Port receive packets:                %10u\n",
-		   counters->port_rcv_pkts);
-
- out:
-	kfree(in_mad);
-	kfree(out_mad);
-	kfree(counters);
-	return 0;
-}
-
-static struct seq_operations counters_seq_ops = {
-	.start = ib_counters_seq_start,
-	.next  = ib_counters_seq_next,
-	.stop  = ib_counters_seq_stop,
-	.show  = ib_counters_seq_show
-};
-
-static int ib_counters_open(struct inode *inode,
-			    struct file *file)
-{
-	int ret;
-
-	ret = seq_open(file, &counters_seq_ops);
-	if (ret) {
-		return ret;
-	}
-	((struct seq_file *) file->private_data)->private = PDE(inode)->data;
-
-	return 0;
-}
-
-static int ib_proc_file_release(struct inode *inode,
-				struct file *file)
-{
-	return seq_release(inode, file);
-}
-
-static struct file_operations counters_ops = {
-	.owner   = THIS_MODULE,
-	.open    = ib_counters_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = ib_proc_file_release
-};
-
-int ib_proc_setup(struct ib_device *device,
-		  int               is_switch)
-{
-	struct ib_device_private *priv = device->core;
-	struct ib_core_proc      *core_proc;
-	char                      port_name[] = "portNN";
-	int p;
-
-	core_proc = kmalloc(sizeof *core_proc, GFP_KERNEL);
-	if (!core_proc) {
-		return -ENOMEM;
-	}
-
-	core_proc->index = index;
-
-	if (is_switch) {
-		sprintf(core_proc->dev_dir_name, "switch%d", index);
-	} else {
-		sprintf(core_proc->dev_dir_name, "ca%d", index);
-	}
-	core_proc->dev_dir = proc_mkdir(core_proc->dev_dir_name, core_dir);
-	if (!core_proc) {
-		goto out_free;
-	}
-
-	core_proc->port = kmalloc((priv->end_port + 1) * sizeof (struct ib_port_proc),
-				  GFP_KERNEL);
-	if (!core_proc->port)
-		goto out_topdir;
-
-	for (p = priv->start_port; p <= priv->end_port; ++p) {
-		core_proc->port[p].device     = device;
-		core_proc->port[p].port_num   = p;
-		core_proc->port[p].port_dir   = NULL;
-		core_proc->port[p].counters   = NULL;
-	}
-
-	for (p = priv->start_port; p <= priv->end_port; ++p) {
-		snprintf(port_name, sizeof port_name, "port%d", p);
-		core_proc->port[p].port_dir = proc_mkdir(port_name, core_proc->dev_dir);
-		if (!core_proc->port[p].port_dir)
-			goto out_port;
-
-		core_proc->port[p].counters = create_proc_entry("counters", S_IRUGO,
-								core_proc->port[p].port_dir);
-		if (!core_proc->port[p].counters)
-			goto out_port;
-
-		core_proc->port[p].counters->proc_fops = &counters_ops;
-		core_proc->port[p].counters->data      = &core_proc->port[p];
-	}
-
-	priv->proc = core_proc;
-	++index;
-	return 0;
-
- out_port:
-	for (p = priv->start_port; p <= priv->end_port; ++p) {
-		if (core_proc->port[p].counters)
-			remove_proc_entry("counters", core_proc->port[p].port_dir);
-
-		if (core_proc->port[p].port_dir) {
-			snprintf(port_name, sizeof port_name, "port%d", p);
-			remove_proc_entry(port_name, core_proc->dev_dir);
-		}
-	}
-
- out_topdir:
-	remove_proc_entry(core_proc->dev_dir_name, core_dir);
-
- out_free:
-	kfree(core_proc);
-	return -ENOMEM;
-}
-
-void ib_proc_cleanup(struct ib_device *device)
-{
-	struct ib_device_private *priv = device->core;
-	struct ib_core_proc      *core_proc = priv->proc;
-	char                      port_name[] = "portNN";
-	int p;
-
-	for (p = priv->start_port; p <= priv->end_port; ++p) {
-		remove_proc_entry("counters", core_proc->port[p].port_dir);
-		snprintf(port_name, sizeof port_name, "port%d", p);
-		remove_proc_entry(port_name, core_proc->dev_dir);
-	}
-
-	remove_proc_entry(core_proc->dev_dir_name, core_dir);
-
-	kfree(priv->proc);
-}
-
-int ib_create_proc_dir(void)
-{
-	core_dir = proc_mkdir("core", tsKernelProcDirGet());
-	return core_dir ? 0 : -ENOMEM;
-}
-
-void ib_remove_proc_dir(void)
-{
-	remove_proc_entry("core", tsKernelProcDirGet());
-}
-
-/*
-  Local Variables:
-  c-file-style: "linux"
-  indent-tabs-mode: t
-  End:
-*/
Index: infiniband/core/core_main.c
===================================================================
--- infiniband/core/core_main.c	(revision 803)
+++ infiniband/core/core_main.c	(working copy)
@@ -35,24 +35,14 @@
 	int ret;
 
 	ret = ib_sysfs_setup();
-	if (ret) {
+	if (ret)
 		printk(KERN_WARNING "Couldn't create InfiniBand device class\n");
-		return ret;
-	}
 
-	ret = ib_create_proc_dir();
-	if (ret) {
-		ib_sysfs_cleanup();
-		printk(KERN_WARNING "Couldn't create IB core proc directory\n");
-		return ret;
-	}
-
-	return 0;
+	return ret;
 }
 
 static void __exit ib_core_cleanup(void)
 {
-	ib_remove_proc_dir();
 	ib_sysfs_cleanup();
 }
 
Index: infiniband/core/core_priv.h
===================================================================
--- infiniband/core/core_priv.h	(revision 803)
+++ infiniband/core/core_priv.h	(working copy)
@@ -45,8 +45,6 @@
 	int                     end_port;
 	tTS_IB_GUID             node_guid;
 	struct ib_port_data    *port_data;
-
-	struct ib_core_proc    *proc;
 };
 
 struct ib_port_data {
@@ -70,10 +68,6 @@
 
 int  ib_cache_setup(struct ib_device *device);
 void ib_cache_cleanup(struct ib_device *device);
-int  ib_proc_setup(struct ib_device *device, int is_switch);
-void ib_proc_cleanup(struct ib_device *device);
-int  ib_create_proc_dir(void);
-void ib_remove_proc_dir(void);
 void ib_completion_thread(struct list_head *entry, void *device_ptr);
 void ib_async_thread(struct list_head *entry, void *device_ptr);
 
Index: infiniband/core/ib_sysfs.c
===================================================================
--- infiniband/core/ib_sysfs.c	(revision 803)
+++ infiniband/core/ib_sysfs.c	(working copy)
@@ -23,6 +23,8 @@
 
 #include "core_priv.h"
 
+#include <ib_mad.h>
+
 struct ib_port {
 	struct kobject         kobj;
 	struct ib_device      *ibdev;
@@ -212,6 +214,119 @@
 	return sprintf(buf, "0x%04x\n", pkey);
 }
 
+#define PORT_PMA_ATTR(_name, _counter, _width, _offset)			\
+struct port_table_attribute port_pma_attr_##_name = {			\
+	.attr  = __ATTR(_name, S_IRUGO, show_pma_counter, NULL),	\
+	.index = (_offset) | ((_width) << 16) | ((_counter) << 24)	\
+}
+
+static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
+				char *buf)
+{
+	struct port_table_attribute *tab_attr =
+		container_of(attr, struct port_table_attribute, attr);
+	int offset = tab_attr->index & 0xffff;
+	int width  = (tab_attr->index >> 16) & 0xff;
+	struct ib_mad *in_mad  = NULL;
+	struct ib_mad *out_mad = NULL;
+	ssize_t ret;
+
+	if (!p->ibdev->process_mad)
+		return sprintf(buf, "N/A (no PMA)\n");
+
+	in_mad  = kmalloc(sizeof *in_mad, GFP_KERNEL);
+	out_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+	if (!in_mad || !out_mad) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memset(in_mad, 0, sizeof *in_mad);
+	in_mad->mad_hdr.base_version  = 1;
+	in_mad->mad_hdr.mgmt_class    = IB_MGMT_CLASS_PERF_MGMT;
+	in_mad->mad_hdr.class_version = 1;
+	in_mad->mad_hdr.method        = IB_MGMT_METHOD_GET;
+	in_mad->mad_hdr.attr_id       = cpu_to_be16(0x12); /* PortCounters */
+
+	in_mad->data[41] = p->port_num;	/* PortSelect field */
+
+	if ((p->ibdev->process_mad(p->ibdev, IB_MAD_IGNORE_MKEY, p->port_num, 0xffff,
+				   in_mad, out_mad) &
+	     (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) !=
+	    (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	switch (width) {
+	case 4:
+		ret = sprintf(buf, "%d\n", (out_mad->data[40 + offset / 8] >>
+					    (offset % 4)) & 0xf);
+		break;
+	case 8:
+		ret = sprintf(buf, "%d\n", out_mad->data[40 + offset / 8]);
+		break;
+	case 16:
+		ret = sprintf(buf, "%d\n",
+			      be16_to_cpup((u16 *)(out_mad->data + 40 + offset / 8)));
+		break;
+	case 32:
+		ret = sprintf(buf, "%d\n",
+			      be32_to_cpup((u32 *)(out_mad->data + 40 + offset / 8)));
+		break;
+	default:
+		ret = 0;
+	}
+
+out:
+	kfree(in_mad);
+	kfree(out_mad);
+
+	return ret;
+}
+
+static PORT_PMA_ATTR(symbol_error, 0, 16, 32);
+static PORT_PMA_ATTR(link_error_recovery, 1, 8, 48);
+static PORT_PMA_ATTR(link_downed, 2, 8, 56);
+static PORT_PMA_ATTR(port_rcv_errors, 3, 16, 64);
+static PORT_PMA_ATTR(port_rcv_remote_physical_errors, 4, 16, 80);
+static PORT_PMA_ATTR(port_rcv_switch_relay_errors, 5, 16, 96);
+static PORT_PMA_ATTR(port_xmit_discards, 6, 16, 112);
+static PORT_PMA_ATTR(port_xmit_constraint_errors, 7, 8, 128);
+static PORT_PMA_ATTR(port_rcv_constraint_errors, 8, 8, 136);
+static PORT_PMA_ATTR(local_link_integrity_errors, 9, 4, 152);
+static PORT_PMA_ATTR(excessive_buffer_overrun_errors, 10, 4, 156);
+static PORT_PMA_ATTR(VL15_dropped, 11, 16, 176);
+static PORT_PMA_ATTR(port_xmit_data, 12, 32, 192);
+static PORT_PMA_ATTR(port_rcv_data, 13, 32, 224);
+static PORT_PMA_ATTR(port_xmit_packets, 14, 32, 256);
+static PORT_PMA_ATTR(port_rcv_packets, 15, 32, 288);
+
+static struct attribute *pma_attrs[] = {
+	&port_pma_attr_symbol_error.attr.attr,
+	&port_pma_attr_link_error_recovery.attr.attr,
+	&port_pma_attr_link_downed.attr.attr,
+	&port_pma_attr_port_rcv_errors.attr.attr,
+	&port_pma_attr_port_rcv_remote_physical_errors.attr.attr,
+	&port_pma_attr_port_rcv_switch_relay_errors.attr.attr,
+	&port_pma_attr_port_xmit_discards.attr.attr,
+	&port_pma_attr_port_xmit_constraint_errors.attr.attr,
+	&port_pma_attr_port_rcv_constraint_errors.attr.attr,
+	&port_pma_attr_local_link_integrity_errors.attr.attr,
+	&port_pma_attr_excessive_buffer_overrun_errors.attr.attr,
+	&port_pma_attr_VL15_dropped.attr.attr,
+	&port_pma_attr_port_xmit_data.attr.attr,
+	&port_pma_attr_port_rcv_data.attr.attr,
+	&port_pma_attr_port_xmit_packets.attr.attr,
+	&port_pma_attr_port_rcv_packets.attr.attr,
+	NULL
+};
+
+static struct attribute_group pma_group = {
+	.name  = "counters",
+	.attrs  = pma_attrs
+};
+
 static void ib_port_release(struct kobject *kobj)
 {
 	struct ib_port *p = container_of(kobj, struct ib_port, kobj);
@@ -373,10 +488,14 @@
 	if (ret)
 		goto err_put;
 
-	ret = alloc_group(&p->gid_attr, show_port_gid, attr.gid_tbl_len);
+	ret = sysfs_create_group(&p->kobj, &pma_group);
 	if (ret)
 		goto err_put;
 
+	ret = alloc_group(&p->gid_attr, show_port_gid, attr.gid_tbl_len);
+	if (ret)
+		goto err_remove_pma;
+
 	p->gid_group.name  = "gids";
 	p->gid_group.attrs = p->gid_attr;
 
@@ -418,6 +537,9 @@
 
 	kfree(p->gid_attr);
 
+err_remove_pma:
+	sysfs_remove_group(&p->kobj, &pma_group);
+
 err_put:
 	kobject_put(&device->ports_parent);
 
@@ -537,6 +659,7 @@
 		list_for_each_entry_safe(p, t, &device->port_list, entry) {
 			list_del(&p->entry);
 			port = container_of(p, struct ib_port, kobj);
+			sysfs_remove_group(p, &pma_group);
 			sysfs_remove_group(p, &port->pkey_group);
 			sysfs_remove_group(p, &port->gid_group);
 			kobject_unregister(p);
@@ -560,7 +683,9 @@
 	list_for_each_entry_safe(p, t, &device->port_list, entry) {
 		list_del(&p->entry);
 		port = container_of(p, struct ib_port, kobj);
-		sysfs_remove_group(p,&port->gid_group);
+		sysfs_remove_group(p, &pma_group);
+		sysfs_remove_group(p, &port->pkey_group);
+		sysfs_remove_group(p, &port->gid_group);
 		kobject_unregister(p);
 	}
 



More information about the general mailing list