[openib-general] [PATCH] Add support for querying port width/speed

Roland Dreier roland at topspin.com
Mon Dec 27 21:40:06 PST 2004


Here's a patch that adds active_width and active_speed members to the
port attributes structure.  This is one step towards having IPoIB set
the static rate of its address handles properly.

I also added a "rate" sysfs attribute for each port, which shows the
data rate.  I don't have any 12X or DDR ports to test with, but 1X and
4X display correctly for me.

While I was at it, I killed off the ib_static_rate enum, because the
1.2 spec adds a ton more IPD values (due to the addition of DDR and
QDR as well as 8X), and it seemed like there wasn't really a good way
to name all of them.  For example, should the IPD value 1 be called
IB_STATIC_RATE_8X_TO_4X?  IB_STATIC_RATE_DDR_TO_SDR?  IB_STATIC_RATE_QDR_TO_DDR?
Should it have three different names?

The enum wasn't used anywhere so it didn't seem worth struggling with
this issue.  In actual code it seems better to compute the ratio of
data rates and derive the IPD value from that.

Look OK to commit?

Thanks,
  Roland

Index: infiniband/include/ib_verbs.h
===================================================================
--- infiniband/include/ib_verbs.h	(revision 1387)
+++ infiniband/include/ib_verbs.h	(working copy)
@@ -144,13 +144,6 @@
 	}
 }
 
-enum ib_static_rate {
-	IB_STATIC_RATE_FULL		=  0,
-	IB_STATIC_RATE_12X_TO_4X	=  2,
-	IB_STATIC_RATE_4X_TO_1X		=  3,
-	IB_STATIC_RATE_12X_TO_1X	= 11
-};
-
 enum ib_port_state {
 	IB_PORT_NOP		= 0,
 	IB_PORT_DOWN		= 1,
@@ -182,6 +175,24 @@
 	IB_PORT_BOOT_MGMT_SUP			= (1<<9)
 };
 
+enum ib_port_width {
+	IB_WIDTH_1X	= 1,
+	IB_WIDTH_4X	= 2,
+	IB_WIDTH_8X	= 4,
+	IB_WIDTH_12X	= 8
+};
+
+static inline int ib_width_enum_to_int(enum ib_port_width width)
+{
+	switch (width) {
+	case IB_WIDTH_1X:  return  1;
+	case IB_WIDTH_4X:  return  4;
+	case IB_WIDTH_8X:  return  8;
+	case IB_WIDTH_12X: return 12;
+	default: 	  return -1;
+	}
+}
+
 struct ib_port_attr {
 	enum ib_port_state	state;
 	enum ib_mtu		max_mtu;
@@ -199,6 +210,8 @@
 	u8			sm_sl;
 	u8			subnet_timeout;
 	u8			init_type_reply;
+	u8			active_width;
+	u8			active_speed;
 };
 
 enum ib_device_modify_flags {
Index: infiniband/core/sysfs.c
===================================================================
--- infiniband/core/sysfs.c	(revision 1387)
+++ infiniband/core/sysfs.c	(working copy)
@@ -171,12 +171,41 @@
 	return sprintf(buf, "0x%08x\n", attr.port_cap_flags);
 }
 
+static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,
+			 char *buf)
+{
+	struct ib_port_attr attr;
+	char *speed = "";
+	int rate;
+	ssize_t ret;
+
+	ret = ib_query_port(p->ibdev, p->port_num, &attr);
+	if (ret)
+		return ret;
+
+	switch (attr.active_speed) {
+	case 2: speed = " DDR"; break;
+	case 4: speed = " QDR"; break;
+	}
+
+	printk(KERN_ERR "width %d speed %d\n", attr.active_width, attr.active_speed);
+
+	rate = 25 * ib_width_enum_to_int(attr.active_width) * attr.active_speed;
+	if (rate < 0)
+		return -EINVAL;
+
+	return sprintf(buf, "%d%s Gb/sec (%dX%s)\n",
+		       rate / 10, rate % 10 ? ".5" : "",
+		       ib_width_enum_to_int(attr.active_width), speed);
+}
+
 static PORT_ATTR_RO(state);
 static PORT_ATTR_RO(lid);
 static PORT_ATTR_RO(lid_mask_count);
 static PORT_ATTR_RO(sm_lid);
 static PORT_ATTR_RO(sm_sl);
 static PORT_ATTR_RO(cap_mask);
+static PORT_ATTR_RO(rate);
 
 static struct attribute *port_default_attrs[] = {
 	&port_attr_state.attr,
@@ -185,6 +214,7 @@
 	&port_attr_sm_lid.attr,
 	&port_attr_sm_sl.attr,
 	&port_attr_cap_mask.attr,
+	&port_attr_rate.attr,
 	NULL
 };
 
Index: infiniband/hw/mthca/mthca_provider.c
===================================================================
--- infiniband/hw/mthca/mthca_provider.c	(revision 1397)
+++ infiniband/hw/mthca/mthca_provider.c	(working copy)
@@ -115,14 +115,16 @@
 	}
 
 	props->lid               = be16_to_cpup((u16 *) (out_mad->data + 16));
-	props->lmc               = (*(u8 *) (out_mad->data + 34)) & 0x7;
+	props->lmc               = out_mad->data[34] & 0x7;
 	props->sm_lid            = be16_to_cpup((u16 *) (out_mad->data + 18));
-	props->sm_sl             = (*(u8 *) (out_mad->data + 36)) & 0xf;
-	props->state             = (*(u8 *) (out_mad->data + 32)) & 0xf;
+	props->sm_sl             = out_mad->data[36] & 0xf;
+	props->state             = out_mad->data[32] & 0xf;
 	props->port_cap_flags    = be32_to_cpup((u32 *) (out_mad->data + 20));
 	props->gid_tbl_len       = to_mdev(ibdev)->limits.gid_table_len;
 	props->pkey_tbl_len      = to_mdev(ibdev)->limits.pkey_table_len;
 	props->qkey_viol_cntr    = be16_to_cpup((u16 *) (out_mad->data + 48));
+	props->active_width      = out_mad->data[31] & 0xf;
+	props->active_speed      = out_mad->data[35] >> 4;
 
  out:
 	kfree(in_mad);
Index: docs/sysfs.txt
===================================================================
--- docs/sysfs.txt	(revision 1387)
+++ docs/sysfs.txt	(working copy)
@@ -21,6 +21,7 @@
     cap_mask       - Port capability mask
     lid            - Port LID
     lid_mask_count - Port LID mask count
+    rate           - Port data rate (active width * active speed)
     sm_lid         - Subnet manager LID for port's subnet
     sm_sl          - Subnet manager SL for port's subnet
     state          - Port state (DOWN, INIT, ARMED, ACTIVE or ACTIVE_DEFER)



More information about the general mailing list