[PATCH] infiniband-diags/ibportstate.c: Changes for extended link speeds

Hal Rosenstock
2011-08-16T09:14:39Z

Signed-off-by: Hal Rosenstock <hal-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
diff --git a/src/ibportstate.c b/src/ibportstate.c
index 1f0f42e..f7ad37f 100644
--- a/src/ibportstate.c
+++ b/src/ibportstate.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
- * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2010,2011 Mellanox Technologies LTD. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -53,6 +53,7 @@ enum port_ops {
RESET,
DISABLE,
SPEED,
+ ESPEED,
WIDTH,
DOWN,
ARM,
@@ -66,6 +67,7 @@ enum port_ops {

struct ibmad_port *srcport;
int speed = 0; /* no state change */
+int espeed = 0; /* no state change */
int width = 0; /* no state change */
int lid;
int smlid;
@@ -83,6 +85,7 @@ struct {
{"reset", NULL, 0}, /* RESET */
{"disable", NULL, 0}, /* DISABLE */
{"speed", &speed, 0}, /* SPEED */
+ {"espeed", &espeed, 0}, /* EXTENDED SPEED */
{"width", &width, 0}, /* WIDTH */
{"down", NULL, 0}, /* DOWN */
{"arm", NULL, 0}, /* ARM */
@@ -99,7 +102,7 @@ struct {
/*******************************************/

/*
- * Return 1 if port is a switch, else zero.
+ * Return 1 if node is a switch, else zero.
*/
static int get_node_info(ib_portid_t * dest, uint8_t * data)
{
@@ -115,15 +118,30 @@ static int get_node_info(ib_portid_t * dest, uint8_t * data)
return 0;
}

-static void get_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
+static int get_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
+ int is_switch)
{
+ uint8_t smp[IB_SMP_DATA_SIZE];
+ uint8_t *info;
+ int cap_mask;
+
+ if (is_switch) {
+ if (!smp_query_via(smp, dest, IB_ATTR_PORT_INFO, 0, 0, srcport))
+ IBERROR("smp query port 0 portinfo failed");
+ info = smp;
+ } else
+ info = data;
+
if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
IBERROR("smp query portinfo failed");
+ cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
+ return (cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS);
}

-static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
+static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
+ int espeed_cap)
{
- char buf[2048];
+ char buf[2300];
char val[64];

mad_dump_portstates(buf, sizeof buf, data, sizeof *data);
@@ -163,17 +181,35 @@ static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf),
sizeof buf - strlen(buf), val);
sprintf(buf + strlen(buf), "%s", "\n");
+ if (espeed_cap) {
+ mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_SUPPORTED_F, val);
+ mad_dump_field(IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
+ buf + strlen(buf), sizeof buf - strlen(buf),
+ val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ENABLED_F, val);
+ mad_dump_field(IB_PORT_LINK_SPEED_EXT_ENABLED_F,
+ buf + strlen(buf), sizeof buf - strlen(buf),
+ val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ACTIVE_F, val);
+ mad_dump_field(IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
+ buf + strlen(buf), sizeof buf - strlen(buf),
+ val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ }

printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
}

-static void set_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
+static void set_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
+ int espeed_cap)
{
if (!smp_set_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
IBERROR("smp set portinfo failed");

printf("\nAfter PortInfo set:\n");
- show_port_info(dest, data, portnum);
+ show_port_info(dest, data, portnum, espeed_cap);
}

static int get_link_width(int lwe, int lws)
@@ -192,6 +228,14 @@ static int get_link_speed(int lse, int lss)
return lse;
}

+static int get_link_speed_ext(int lsee, int lses)
+{
+ if (lsee == 31)
+ return lses;
+ else
+ return lsee;
+}
+
static void validate_width(int width, int peerwidth, int lwa)
{
if ((width & peerwidth & 0x8)) {
@@ -222,7 +266,7 @@ static void validate_speed(int speed, int peerspeed, int lsa)
if ((speed & peerspeed & 0x4)) {
if (lsa != 4)
IBWARN
- ("Peer ports operating at active speed %d rather than 4 (10.0 Gbps)",
+ ("Peer ports operating at active speed %d rather than 4 (10.0 Gbps)",
lsa);
} else if ((speed & peerspeed & 0x2)) {
if (lsa != 2)
@@ -237,17 +281,32 @@ static void validate_speed(int speed, int peerspeed, int lsa)
}
}

+static void validate_extended_speed(int espeed, int peerespeed, int lsea)
+{
+ if ((espeed & peerespeed & 0x2)) {
+ if (lsea != 2)
+ IBWARN
+ ("Peer ports operating at active extended speed %d rather than 2 (25.78125 Gbps)",
+ lsea);
+ } else if ((espeed & peerespeed & 0x1)) {
+ if (lsea != 1)
+ IBWARN
+ ("Peer ports operating at active extended speed %d rather than 1 (14.0625 Gbps)",
+ lsea);
+ }
+}
+
int main(int argc, char **argv)
{
int mgmt_classes[3] =
{ IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
ib_portid_t portid = { 0 };
int port_op = -1;
- int is_switch;
- int state, physstate, lwe, lws, lwa, lse, lss, lsa;
+ int is_switch, is_peer_switch, espeed_cap, peer_espeed_cap;
+ int state, physstate, lwe, lws, lwa, lse, lss, lsa, lsee, lses, lsea;
int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss,
- peerlsa;
- int peerwidth, peerspeed;
+ peerlsa, peerlsee, peerlses, peerlsea;
+ int peerwidth, peerspeed, peerespeed;
uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
ib_portid_t peerportid = { 0 };
int portnum = 0;
@@ -316,6 +375,10 @@ int main(int argc, char **argv)
if (val < 0 || val > 15)
IBERROR("invalid speed value %ld", val);
break;
+ case ESPEED:
+ if (val < 0 || val > 31)
+ IBERROR("invalid extended speed value %ld", val);
+ break;
case WIDTH:
if (val < 0 || (val > 15 && val != 255))
IBERROR("invalid width value %ld", val);
@@ -357,9 +420,8 @@ int main(int argc, char **argv)
printf("Initial %s PortInfo:\n", is_switch ? "Switch" : "CA");
else
printf("%s PortInfo:\n", is_switch ? "Switch" : "CA");
- memset(data, 0, sizeof(data));
- get_port_info(&portid, data, portnum);
- show_port_info(&portid, data, portnum);
+ espeed_cap = get_port_info(&portid, data, portnum, is_switch);
+ show_port_info(&portid, data, portnum, espeed_cap);

if (port_op != QUERY || changed) {
/*
@@ -397,8 +459,9 @@ int main(int argc, char **argv)
break;
}

- /* always set enabled speed/width - defaults to NOP */
+ /* always set enabled speeds/width - defaults to NOP */
mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F, speed);
+ mad_set_field(data, 0, IB_PORT_LINK_SPEED_EXT_ENABLED_F, espeed);
mad_set_field(data, 0, IB_PORT_LINK_WIDTH_ENABLED_F, width);

if (port_args[VLS].set)
@@ -412,7 +475,7 @@ int main(int argc, char **argv)
if (port_args[LMC].set)
mad_set_field(data, 0, IB_PORT_LMC_F, lmc);

- set_port_info(&portid, data, portnum);
+ set_port_info(&portid, data, portnum, is_switch);

} else if (is_switch && portnum) {
/* Now, make sure PortState is Active */
@@ -432,6 +495,17 @@ int main(int argc, char **argv)
&lsa);
mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
&lse);
+ if (espeed_cap) {
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
+ &lses);
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
+ &lsea);
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_ENABLED_F,
+ &lsee);
+ }

/* Setup portid for peer port */
memcpy(&peerportid, &portid, sizeof(peerportid));
@@ -446,15 +520,18 @@ int main(int argc, char **argv)
peerportid.drpath.drdlid = 0xffff;

/* Get peer port NodeInfo to obtain peer port number */
- get_node_info(&peerportid, data);
+ is_peer_switch = get_node_info(&peerportid, data);

mad_decode_field(data, IB_NODE_LOCAL_PORT_F,
&peerlocalportnum);

printf("Peer PortInfo:\n");
/* Get peer port characteristics */
- get_port_info(&peerportid, data, peerlocalportnum);
- show_port_info(&peerportid, data, peerlocalportnum);
+ peer_espeed_cap = get_port_info(&peerportid, data,
+ peerlocalportnum,
+ is_peer_switch);
+ show_port_info(&peerportid, data, peerlocalportnum,
+ peer_espeed_cap);

mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
&peerlwe);
@@ -468,6 +545,17 @@ int main(int argc, char **argv)
&peerlsa);
mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
&peerlse);
+ if (peer_espeed_cap) {
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
+ &peerlses);
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
+ &peerlsea);
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_ENABLED_F,
+ &peerlsee);
+ }

/* Now validate peer port characteristics */
/* Examine Link Width */
@@ -475,10 +563,18 @@ int main(int argc, char **argv)
peerwidth = get_link_width(peerlwe, peerlws);
validate_width(width, peerwidth, lwa);

- /* Examine Link Speed */
+ /* Examine Link Speeds */
speed = get_link_speed(lse, lss);
peerspeed = get_link_speed(peerlse, peerlss);
validate_speed(speed, peerspeed, lsa);
+
+ if (espeed_cap && peer_espeed_cap) {
+ espeed = get_link_speed_ext(lsee, lses);
+ peerespeed = get_link_speed_ext(peerlsee,
+ peerlses);
+ validate_extended_speed(espeed, peerespeed,
+ lsea);
+ }
}
}

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html