[openib-general][RFC][PATCH] core/sysfs.c: ability to reset port counters
Leonid Arsh
leonida at voltaire.com
Tue May 9 05:06:13 PDT 2006
Hello,
we need a possibility to reset the port counters in /sys/class/infiniband/mthca0/ports/1/counters/.
The attached patch implements the ability to reset the counters by writing to the sysfs counter files.
The patch uses the same process_mad() mechanism as in the counter reading, but with IB_MGMT_METHOD_SET.
The patch was checked on IBED-1.0-rc3 code, with MTHCA adaptor.
I checked also possibility to set specific counter values, but always got the counter reset instead.
The questions are:
Is it a protocol or a firmware limitation, that I couldn't set specific values?
If there is a way to set specific values, should we implement it?
Should we implement an ability to reset (or set) specific counters,
just like like I did in this patch?
(this can cause inconsistency between counter values,
for example between port_xmit_data and port_xmit_packets)
Should we create an additional sysfs entry for the counter reset purpose
(like /sys/class/infiniband/mthca0/ports/1/reset_counters) instead?
Regards,
Leonid
Signed-off-by: Leonid Arsh <leonida at voltaire.com>
--- linux-kernel/infiniband/core/sysfs.c.orig 2006-05-07 23:07:10.000000000 +0300
+++ linux-kernel/infiniband/core/sysfs.c 2006-05-09 17:55:55.000000000 +0300
@@ -88,8 +88,24 @@
return port_attr->show(p, port_attr, buf);
}
+static ssize_t port_attr_store(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t len)
+{
+ struct port_attribute *port_attr =
+ container_of(attr, struct port_attribute, attr);
+ struct ib_port *p = container_of(kobj, struct ib_port, kobj);
+
+ if (!port_attr->store)
+ return -EIO;
+ if (!ibdev_is_alive(p->ibdev))
+ return -ENODEV;
+
+ return port_attr->store(p, port_attr, buf, len);
+}
+
static struct sysfs_ops port_sysfs_ops = {
- .show = port_attr_show
+ .show = port_attr_show,
+ .store = port_attr_store
};
static ssize_t state_show(struct ib_port *p, struct port_attribute *unused,
@@ -292,10 +308,65 @@
#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), \
+ .attr = __ATTR(_name, S_IRUGO | S_IWUSR, \
+ show_pma_counter, store_pma_counter), \
.index = (_offset) | ((_width) << 16) | ((_counter) << 24) \
}
+static ssize_t store_pma_counter(struct ib_port *p, struct port_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct port_table_attribute *tab_attr =
+ container_of(attr, struct port_table_attribute, attr);
+ int counter = (tab_attr->index >> 24) & 0xff;
+ struct ib_mad *in_mad = NULL;
+ struct ib_mad *out_mad = NULL;
+ ssize_t ret;
+
+ if (!p->ibdev->process_mad)
+ {
+ printk("store_pma_counter() process_mad() == NULL");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
+ out_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ if (!in_mad || !out_mad) {
+ printk("store_pma_counter() NOMEM");
+ 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_SET;
+ in_mad->mad_hdr.attr_id = cpu_to_be16(0x12); /* PortCounters */
+
+ *(__be16 *)(in_mad->data+42) = cpu_to_be16( ((__u16)1) << counter ); /* CounterSelect field */
+
+ in_mad->data[41] = p->port_num; /* PortSelect field */
+
+ if ((p->ibdev->process_mad(p->ibdev, IB_MAD_IGNORE_MKEY,
+ p->port_num, NULL, NULL, in_mad, out_mad) &
+ (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) !=
+ (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) {
+ printk("store_pma_counter() EINVAL");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = count;
+out:
+ kfree(in_mad);
+ kfree(out_mad);
+
+ return ret;
+}
+
static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
char *buf)
{
More information about the general
mailing list