[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