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

Roland Dreier roland at topspin.com
Tue Dec 28 12:35:22 PST 2004


Here's an updated patch that actually uses this information to set
static rate in IPoIB.  Seems to work for me...

Any comments/suggestions, or does it seem OK to commit?

 - R.

Index: infiniband/ulp/ipoib/ipoib_main.c
===================================================================
--- infiniband/ulp/ipoib/ipoib_main.c	(revision 1408)
+++ infiniband/ulp/ipoib/ipoib_main.c	(working copy)
@@ -294,10 +294,18 @@
 		struct ib_ah_attr av = {
 			.dlid 	       = be16_to_cpu(pathrec->dlid),
 			.sl 	       = pathrec->sl,
-			.static_rate   = 0,
 			.port_num      = priv->port
 		};
 
+		if (ib_sa_rate_enum_to_int(pathrec->rate) > 0)
+			av.static_rate = (2 * priv->local_rate -
+					  ib_sa_rate_enum_to_int(pathrec->rate) - 1) /
+				(priv->local_rate ? priv->local_rate : 1);
+
+		ipoib_dbg(priv, "static_rate %d for local port %dX, path %dX\n",
+			  av.static_rate, priv->local_rate,
+			  ib_sa_rate_enum_to_int(pathrec->rate));
+
 		ah = ipoib_create_ah(dev, priv->pd, &av);
 	}
 
Index: infiniband/ulp/ipoib/ipoib_multicast.c
===================================================================
--- infiniband/ulp/ipoib/ipoib_multicast.c	(revision 1408)
+++ infiniband/ulp/ipoib/ipoib_multicast.c	(working copy)
@@ -238,19 +238,10 @@
 	}
 
 	{
-		/*
-		 * For now we set static_rate to 0.  This is not
-		 * really correct: we should look at the rate
-		 * component of the MC member record, compare it with
-		 * the rate of our local port (calculated from the
-		 * active link speed and link width) and set an
-		 * inter-packet delay appropriately.
-		 */
 		struct ib_ah_attr av = {
 			.dlid	       = be16_to_cpu(mcast->mcmember.mlid),
 			.port_num      = priv->port,
 			.sl	       = mcast->mcmember.sl,
-			.static_rate   = 0,
 			.ah_flags      = IB_AH_GRH,
 			.grh	       = {
 				.flow_label    = be32_to_cpu(mcast->mcmember.flow_label),
@@ -262,6 +253,15 @@
 
 		av.grh.dgid = mcast->mcmember.mgid;
 
+		if (ib_sa_rate_enum_to_int(mcast->mcmember.rate) > 0)
+			av.static_rate = (2 * priv->local_rate -
+					  ib_sa_rate_enum_to_int(mcast->mcmember.rate) - 1) /
+				(priv->local_rate ? priv->local_rate : 1);
+
+		ipoib_dbg_mcast(priv, "static_rate %d for local port %dX, mcmember %dX\n",
+				av.static_rate, priv->local_rate,
+				ib_sa_rate_enum_to_int(mcast->mcmember.rate));
+
 		mcast->ah = ipoib_create_ah(dev, priv->pd, &av);
 		if (!mcast->ah) {
 			ipoib_warn(priv, "ib_address_create failed\n");
@@ -506,6 +506,17 @@
 	else
 		memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
 
+	{
+		struct ib_port_attr attr;
+
+		if (!ib_query_port(priv->ca, priv->port, &attr)) {
+			priv->local_lid  = attr.lid;
+			priv->local_rate = attr.active_speed *
+				ib_width_enum_to_int(attr.active_width);
+		} else
+			ipoib_warn(priv, "ib_query_port failed\n");
+	}
+
 	if (!priv->broadcast) {
 		priv->broadcast = ipoib_mcast_alloc(dev, 1);
 		if (!priv->broadcast) {
@@ -554,15 +565,6 @@
 		return;
 	}
 
-	{
-		struct ib_port_attr attr;
-
-		if (!ib_query_port(priv->ca, priv->port, &attr))
-			priv->local_lid = attr.lid;
-		else
-			ipoib_warn(priv, "ib_query_port failed\n");
-	}
-
 	priv->mcast_mtu = ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu) -
 		IPOIB_ENCAP_LEN;
 	dev->mtu = min(priv->mcast_mtu, priv->admin_mtu);
Index: infiniband/ulp/ipoib/ipoib.h
===================================================================
--- infiniband/ulp/ipoib/ipoib.h	(revision 1408)
+++ infiniband/ulp/ipoib/ipoib.h	(working copy)
@@ -143,6 +143,7 @@
 
 	union ib_gid local_gid;
 	u16          local_lid;
+	u8           local_rate;
 
 	unsigned int admin_mtu;
 	unsigned int mcast_mtu;
Index: infiniband/include/ib_verbs.h
===================================================================
--- infiniband/include/ib_verbs.h	(revision 1408)
+++ 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/include/ib_sa.h
===================================================================
--- infiniband/include/ib_sa.h	(revision 1408)
+++ infiniband/include/ib_sa.h	(working copy)
@@ -59,6 +59,34 @@
 	IB_SA_BEST = 3
 };
 
+enum ib_sa_rate {
+	IB_SA_RATE_2_5_GBPS = 2,
+	IB_SA_RATE_5_GBPS   = 5,
+	IB_SA_RATE_10_GBPS  = 3,
+	IB_SA_RATE_20_GBPS  = 6,
+	IB_SA_RATE_30_GBPS  = 4,
+	IB_SA_RATE_40_GBPS  = 7,
+	IB_SA_RATE_60_GBPS  = 8,
+	IB_SA_RATE_80_GBPS  = 9,
+	IB_SA_RATE_120_GBPS = 10
+};
+
+static inline int ib_sa_rate_enum_to_int(enum ib_sa_rate rate)
+{
+	switch (rate) {
+	case IB_SA_RATE_2_5_GBPS: return  1;
+	case IB_SA_RATE_5_GBPS:   return  2;
+	case IB_SA_RATE_10_GBPS:  return  4;
+	case IB_SA_RATE_20_GBPS:  return  8;
+	case IB_SA_RATE_30_GBPS:  return 12;
+	case IB_SA_RATE_40_GBPS:  return 16;
+	case IB_SA_RATE_60_GBPS:  return 24;
+	case IB_SA_RATE_80_GBPS:  return 32;
+	case IB_SA_RATE_120_GBPS: return 48;
+	default: 	          return -1;
+	}
+}
+
 typedef u64 __bitwise ib_sa_comp_mask;
 
 #define IB_SA_COMP_MASK(n)	((__force ib_sa_comp_mask) cpu_to_be64(1ull << n))
Index: infiniband/core/sysfs.c
===================================================================
--- infiniband/core/sysfs.c	(revision 1408)
+++ 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 1408)
+++ 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 1408)
+++ 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