[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