[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