[ofw] [PATCH] Update libibmad and infiniband-diags

Hefty, Sean sean.hefty at intel.com
Mon Aug 8 12:33:36 PDT 2011


Update libibmad to commit 818fcb2260ea0308e09ad434acb76691d25ff95d and
ib-diags to commit a817e38e5275dcf75404af19b8592c03f4822118

This results in all diags needing a dependency on ibal for ib_get_err_str() and
adds one new executable, ibcacheedit.  For a separate breakout of changes, refer
to the git trees.

Signed-off-by: Sean Hefty <sean.hefty at intel.com>
---
trunk/inc/iba/ib_types.h                           |    2 
 .../tools/infiniband-diags/include/ibdiag_common.h |   55 ++
 .../infiniband-diags/include/windows/config.h      |    3 
 trunk/tools/infiniband-diags/src/dirs              |    1 
 trunk/tools/infiniband-diags/src/ibaddr.c          |    5 
 trunk/tools/infiniband-diags/src/ibaddr/SOURCES    |    1 
 .../tools/infiniband-diags/src/ibcacheedit/SOURCES |   28 +
 .../src/ibcacheedit/ibcacheedit.rc                 |   47 ++
 .../infiniband-diags/src/ibcacheedit/makefile      |    7 
 trunk/tools/infiniband-diags/src/ibdiag_common.c   |  193 ++++++++
 trunk/tools/infiniband-diags/src/iblinkinfo.c      |  416 +++++++++++++++--
 .../tools/infiniband-diags/src/iblinkinfo/SOURCES  |    1 
 trunk/tools/infiniband-diags/src/ibnetdiscover.c   |   69 +++
 .../infiniband-diags/src/ibnetdiscover/SOURCES     |    1 
 trunk/tools/infiniband-diags/src/ibping.c          |    2 
 trunk/tools/infiniband-diags/src/ibping/SOURCES    |    1 
 trunk/tools/infiniband-diags/src/ibportstate.c     |    6 
 .../tools/infiniband-diags/src/ibportstate/SOURCES |    1 
 trunk/tools/infiniband-diags/src/ibqueryerrors.c   |  491 ++++++++++++++++----
 .../infiniband-diags/src/ibqueryerrors/SOURCES     |    1 
 trunk/tools/infiniband-diags/src/ibroute.c         |   10 
 trunk/tools/infiniband-diags/src/ibroute/SOURCES   |    1 
 trunk/tools/infiniband-diags/src/ibsendtrap.c      |    5 
 .../tools/infiniband-diags/src/ibsendtrap/SOURCES  |    1 
 trunk/tools/infiniband-diags/src/ibstat.c          |   17 -
 trunk/tools/infiniband-diags/src/ibstat/SOURCES    |    1 
 trunk/tools/infiniband-diags/src/ibsysstat/SOURCES |    1 
 trunk/tools/infiniband-diags/src/ibtracert.c       |   14 -
 trunk/tools/infiniband-diags/src/ibtracert/SOURCES |    1 
 .../infiniband-diags/src/mcm_rereg_test/SOURCES    |    1 
 trunk/tools/infiniband-diags/src/perfquery.c       |  301 +++++++++++-
 trunk/tools/infiniband-diags/src/perfquery/SOURCES |    1 
 trunk/tools/infiniband-diags/src/saquery.c         |  405 ++++++----------
 trunk/tools/infiniband-diags/src/sminfo.c          |    3 
 trunk/tools/infiniband-diags/src/sminfo/SOURCES    |    1 
 trunk/tools/infiniband-diags/src/smpdump/SOURCES   |    1 
 trunk/tools/infiniband-diags/src/smpquery.c        |   48 +-
 trunk/tools/infiniband-diags/src/smpquery/SOURCES  |    1 
 trunk/tools/infiniband-diags/src/vendstat.c        |    1 
 trunk/tools/infiniband-diags/src/vendstat/SOURCES  |    1 
 trunk/ulp/libibmad/include/infiniband/mad.h        |  355 ++++++++++++++
 trunk/ulp/libibmad/include/infiniband/mad_osd.h    |    1 
 trunk/ulp/libibmad/src/dump.c                      |  207 ++++++++
 trunk/ulp/libibmad/src/fields.c                    |  364 +++++++++++++--
 trunk/ulp/libibmad/src/gs.c                        |   23 +
 trunk/ulp/libibmad/src/ibmad_exports.src           |  167 +++++--
 trunk/ulp/libibmad/src/libibmad.map                |   19 +
 trunk/ulp/libibmad/src/mad.c                       |   19 -
 trunk/ulp/libibmad/src/register.c                  |    2 
 trunk/ulp/libibmad/src/rpc.c                       |   34 +
 trunk/ulp/libibmad/src/serv.c                      |    2 
 trunk/ulp/libibmad/src/smp.c                       |   41 +-
 trunk/ulp/libibmad/src/vendor.c                    |   17 -
 .../libibnetdisc/include/infiniband/ibnetdisc.h    |   22 +
 .../include/infiniband/ibnetdisc_osd.h             |   41 ++
 trunk/ulp/libibnetdisc/src/chassis.c               |  275 ++++++++++-
 trunk/ulp/libibnetdisc/src/chassis.h               |    6 
 trunk/ulp/libibnetdisc/src/ibnetdisc.c             |  213 ++++++---
 trunk/ulp/libibnetdisc/src/ibnetdisc_cache.c       |   19 +
 trunk/ulp/libibnetdisc/src/ibnetdisc_exports.src   |    5 
 trunk/ulp/libibnetdisc/src/internal.h              |    1 
 trunk/ulp/opensm/user/opensm/osm_helper.c          |    4 
 62 files changed, 3282 insertions(+), 701 deletions(-)
 create mode 100644 trunk/tools/infiniband-diags/src/ibcacheedit/SOURCES
 create mode 100644 trunk/tools/infiniband-diags/src/ibcacheedit/ibcacheedit.rc
 create mode 100644 trunk/tools/infiniband-diags/src/ibcacheedit/makefile
 create mode 100644 trunk/ulp/libibnetdisc/include/infiniband/ibnetdisc_osd.h

diff --git a/trunk/inc/iba/ib_types.h b/trunk/inc/iba/ib_types.h
index 665bdad..21781d5 100644
--- a/trunk/inc/iba/ib_types.h
+++ b/trunk/inc/iba/ib_types.h
@@ -6228,7 +6228,7 @@ typedef struct _ib_portinfo_record
 {
 	ib_net16_t		lid;
 	uint8_t			port_num;
-	uint8_t			resv;
+	uint8_t			options;
 	ib_port_info_t	port_info;
 
 }	PACK_SUFFIX ib_portinfo_record_t;
diff --git a/trunk/tools/infiniband-diags/include/ibdiag_common.h b/trunk/tools/infiniband-diags/include/ibdiag_common.h
index 9b2add7..57bde20 100644
--- a/trunk/tools/infiniband-diags/include/ibdiag_common.h
+++ b/trunk/tools/infiniband-diags/include/ibdiag_common.h
@@ -1,6 +1,10 @@
 /*
  * Copyright (c) 2006-2007 The Regents of the University of California.
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ * Copyright (c) 2011 Lawrence Livermore National Security. 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
@@ -35,6 +39,7 @@
 #ifndef _IBDIAG_COMMON_H_
 #define _IBDIAG_COMMON_H_
 
+#include <infiniband/iba/ib_types.h>
 #include <infiniband/mad.h>
 
 extern int ibverbose;
@@ -57,6 +62,11 @@ extern int ibd_timeout;
 } while (0)
 #define IBERROR(fmt, ...) iberror(__FUNCTION__, fmt, ## __VA_ARGS__)
 
+/* not all versions of ib_types.h will have this define */
+#ifndef IB_PM_PC_XMIT_WAIT_SUP
+#define IB_PM_PC_XMIT_WAIT_SUP (CL_HTON16(((uint16_t)1)<<12))
+#endif
+
 struct ibdiag_opt {
 	const char *name;
 	char letter;
@@ -75,4 +85,49 @@ extern int ibdiag_process_opts(int argc, char *const argv[], void *context,
 extern void ibdiag_show_usage();
 extern void iberror(const char *fn, char *msg, ...);
 
+/* define an SA query structure to be common
+ * This is by no means optimal but it moves the saquery functionality out of
+ * the saquery tool and provides it to other utilities.
+ */
+struct bind_handle {
+	int fd, agent;
+	ib_portid_t dport;
+	struct ibmad_port *srcport;
+};
+typedef struct bind_handle * bind_handle_t;
+bind_handle_t sa_get_bind_handle(void);
+void sa_free_bind_handle(bind_handle_t h);
+
+struct sa_query_result {
+	uint32_t status;
+	unsigned result_cnt;
+	void *p_result_madw;
+};
+int sa_query(struct bind_handle *h, uint8_t method,
+	     uint16_t attr, uint32_t mod, uint64_t comp_mask, uint64_t sm_key,
+	     void *data, struct sa_query_result *result);
+void sa_free_result_mad(struct sa_query_result *result);
+void *sa_get_query_rec(void *mad, unsigned i);
+void sa_report_err(int status);
+
+#define cl_hton8(x) (x)
+#define CHECK_AND_SET_VAL(val, size, comp_with, target, name, mask) \
+	if ((int##size##_t) val != (int##size##_t) comp_with) { \
+		target = cl_hton##size((uint##size##_t) val); \
+		comp_mask |= IB_##name##_COMPMASK_##mask; \
+	}
+
+#define CHECK_AND_SET_GID(val, target, name, mask) \
+	if (valid_gid(&(val))) { \
+		memcpy(&(target), &(val), sizeof(val)); \
+		comp_mask |= IB_##name##_COMPMASK_##mask; \
+	}
+
+#define CHECK_AND_SET_VAL_AND_SEL(val, target, name, mask, sel) \
+	if (val) { \
+		target = val; \
+		comp_mask |= IB_##name##_COMPMASK_##mask##sel; \
+		comp_mask |= IB_##name##_COMPMASK_##mask; \
+	}
+
 #endif				/* _IBDIAG_COMMON_H_ */
diff --git a/trunk/tools/infiniband-diags/include/windows/config.h b/trunk/tools/infiniband-diags/include/windows/config.h
index c6365bf..3a46b6f 100644
--- a/trunk/tools/infiniband-diags/include/windows/config.h
+++ b/trunk/tools/infiniband-diags/include/windows/config.h
@@ -37,4 +37,7 @@
 #include <_errno.h>
 #include <_string.h>
 
+#define IBDIAG_CONFIG_PATH "."
+#define UINT16_MAX 0xffffffff
+
 #endif /* _CONFIG_H_ */
diff --git a/trunk/tools/infiniband-diags/src/dirs b/trunk/tools/infiniband-diags/src/dirs
index 822f325..c36a414 100644
--- a/trunk/tools/infiniband-diags/src/dirs
+++ b/trunk/tools/infiniband-diags/src/dirs
@@ -1,5 +1,6 @@
 DIRS = \
 	ibaddr		\
+	ibcacheedit	\
 	iblinkinfo	\
 	ibnetdiscover	\
 	ibping		\
diff --git a/trunk/tools/infiniband-diags/src/ibaddr.c b/trunk/tools/infiniband-diags/src/ibaddr.c
index 6e17458..397ef77 100644
--- a/trunk/tools/infiniband-diags/src/ibaddr.c
+++ b/trunk/tools/infiniband-diags/src/ibaddr.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 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
@@ -52,8 +53,8 @@ static int ib_resolve_addr(ib_portid_t * portid, int portnum, int show_lid,
 			   int show_gid)
 {
 	char gid_str[INET6_ADDRSTRLEN];
-	uint8_t portinfo[64];
-	uint8_t nodeinfo[64];
+	uint8_t portinfo[IB_SMP_DATA_SIZE] = { 0 };
+	uint8_t nodeinfo[IB_SMP_DATA_SIZE] = { 0 };
 	uint64_t guid, prefix;
 	ibmad_gid_t gid;
 	int lmc;
diff --git a/trunk/tools/infiniband-diags/src/ibaddr/SOURCES b/trunk/tools/infiniband-diags/src/ibaddr/SOURCES
index f7462a5..91a22fb 100644
--- a/trunk/tools/infiniband-diags/src/ibaddr/SOURCES
+++ b/trunk/tools/infiniband-diags/src/ibaddr/SOURCES
@@ -21,6 +21,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H /DUSE_INET
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	\
 	$(TARGETPATH)\*\libibnetdisc.lib
diff --git a/trunk/tools/infiniband-diags/src/ibcacheedit/SOURCES b/trunk/tools/infiniband-diags/src/ibcacheedit/SOURCES
new file mode 100644
index 0000000..c00ddb9
--- /dev/null
+++ b/trunk/tools/infiniband-diags/src/ibcacheedit/SOURCES
@@ -0,0 +1,28 @@
+TARGETNAME = ibcacheedit
+TARGETPATH = ..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)
+TARGETTYPE = PROGRAM
+
+UMTYPE = console
+UMENTRY = main
+
+USE_MSVCRT = 1
+
+SOURCES = ..\ibcacheedit.c ..\ibdiag_common.c ..\ibdiag_windows.c ibcacheedit.rc
+	
+INCLUDES = ..\..\include;..\..\include\windows;\
+		   ..\..\..\..\ulp\libibnetdisc\include;\
+		   ..\..\..\..\ulp\libibmad\include;\
+		   ..\..\..\..\ulp\libibumad\include;\
+		   ..\..\..\..\inc;..\..\..\..\inc\user;\
+		   ..\..\..\..\inc\user\linux;
+
+C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
+
+TARGETLIBS = \
+	$(SDK_LIB_PATH)\kernel32.lib	\
+	$(TARGETPATH)\*\ibal.lib		\
+	$(TARGETPATH)\*\libibmad.lib	\
+	$(TARGETPATH)\*\libibumad.lib	\
+	$(TARGETPATH)\*\libibnetdisc.lib
+
+MSC_WARNING_LEVEL = /W3 /WX /wd4007
diff --git a/trunk/tools/infiniband-diags/src/ibcacheedit/ibcacheedit.rc b/trunk/tools/infiniband-diags/src/ibcacheedit/ibcacheedit.rc
new file mode 100644
index 0000000..c358cda
--- /dev/null
+++ b/trunk/tools/infiniband-diags/src/ibcacheedit/ibcacheedit.rc
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+#include <oib_ver.h>
+
+#define VER_FILETYPE			VFT_APP
+#define VER_FILESUBTYPE			VFT2_UNKNOWN
+
+#ifdef DBG
+#define VER_FILEDESCRIPTION_STR	"Edit InfiniBand Diagnostic Cache Information (Debug)"
+#else
+#define VER_FILEDESCRIPTION_STR	"Edit InfiniBand Diagnostic Cache Information"
+#endif
+
+#define VER_INTERNALNAME_STR		"ibcacheedit.exe"
+#define VER_ORIGINALFILENAME_STR	"ibcacheedit.exe"
+
+#include <common.ver>
diff --git a/trunk/tools/infiniband-diags/src/ibcacheedit/makefile b/trunk/tools/infiniband-diags/src/ibcacheedit/makefile
new file mode 100644
index 0000000..a0c0627
--- /dev/null
+++ b/trunk/tools/infiniband-diags/src/ibcacheedit/makefile
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
+# file to this component.  This file merely indirects to the real make file
+# that is shared by all the driver components of the OpenIB Windows project.
+#
+
+!INCLUDE ..\..\..\..\inc\openib.def
diff --git a/trunk/tools/infiniband-diags/src/ibdiag_common.c b/trunk/tools/infiniband-diags/src/ibdiag_common.c
index 99861f1..e7e1590 100644
--- a/trunk/tools/infiniband-diags/src/ibdiag_common.c
+++ b/trunk/tools/infiniband-diags/src/ibdiag_common.c
@@ -1,6 +1,10 @@
 /*
  * Copyright (c) 2006-2007 The Regents of the University of California.
  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ * Copyright (c) 2011 Lawrence Livermore National Security. 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
@@ -47,6 +51,7 @@
 #include <ctype.h>
 #include <config.h>
 #include <getopt.h>
+#include <limits.h>
 
 #include <infiniband/umad.h>
 #include <infiniband/mad.h>
@@ -138,7 +143,8 @@ void ibdiag_show_usage()
 
 static int process_opt(int ch, char *optarg)
 {
-	int val;
+	char *endp;
+	long val;
 
 	switch (ch) {
 	case 'h':
@@ -175,9 +181,16 @@ static int process_opt(int ch, char *optarg)
 		ibd_dest_type = IB_DEST_GUID;
 		break;
 	case 't':
-		val = strtoul(optarg, 0, 0);
-		madrpc_set_timeout(val);
-		ibd_timeout = val;
+		errno = 0;
+		val = strtol(optarg, &endp, 0);
+		if (errno || (endp && *endp != '\0') || val <= 0 ||
+		    val > INT_MAX)
+			IBERROR("Invalid timeout \"%s\".  Timeout requires a "
+				"positive integer value < %d.", optarg, INT_MAX);
+		else {
+			madrpc_set_timeout((int)val);
+			ibd_timeout = (int)val;
+		}
 		break;
 	case 's':
 		/* srcport is not required when resolving via IB_DEST_LID */
@@ -328,3 +341,175 @@ void iberror(const char *fn, char *msg, ...)
 
 	exit(-1);
 }
+
+/* define a common SA query structure
+ * This is by no means optimal but it moves the saquery functionality out of
+ * the saquery tool and provides it to other utilities.
+ */
+bind_handle_t sa_get_bind_handle(void)
+{
+	struct ibmad_port * srcport;
+	bind_handle_t handle;
+	int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
+
+	srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 2);
+	if (!srcport) {
+		IBWARN("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+		return (NULL);
+	}
+
+	handle = calloc(1, sizeof(*handle));
+	if (!handle)
+		IBPANIC("calloc failed");
+
+	ib_resolve_smlid_via(&handle->dport, ibd_timeout, srcport);
+	if (!handle->dport.lid) {
+		IBWARN("No SM found.");
+		free(handle);
+		return (NULL);
+	}
+
+	handle->dport.qp = 1;
+	if (!handle->dport.qkey)
+		handle->dport.qkey = IB_DEFAULT_QP1_QKEY;
+
+	handle->srcport = srcport;
+	handle->fd = mad_rpc_portid(srcport);
+	handle->agent = umad_register(handle->fd, IB_SA_CLASS, 2, 1, NULL);
+
+	return handle;
+}
+
+void sa_free_bind_handle(bind_handle_t h)
+{
+	umad_unregister(h->fd, h->agent);
+	mad_rpc_close_port(h->srcport);
+	free(h);
+}
+
+int sa_query(bind_handle_t h, uint8_t method,
+		    uint16_t attr, uint32_t mod, uint64_t comp_mask,
+		    uint64_t sm_key, void *data, struct sa_query_result *result)
+{
+	ib_rpc_t rpc;
+	void *umad, *mad;
+	int ret, offset, len = 256;
+
+	memset(&rpc, 0, sizeof(rpc));
+	rpc.mgtclass = IB_SA_CLASS;
+	rpc.method = method;
+	rpc.attr.id = attr;
+	rpc.attr.mod = mod;
+	rpc.mask = comp_mask;
+	rpc.datasz = IB_SA_DATA_SIZE;
+	rpc.dataoffs = IB_SA_DATA_OFFS;
+
+	umad = calloc(1, len + umad_size());
+	if (!umad)
+		IBPANIC("cannot alloc mem for umad: %s\n", strerror(errno));
+
+	mad_build_pkt(umad, &rpc, &h->dport, NULL, data);
+
+	mad_set_field64(umad_get_mad(umad), 0, IB_SA_MKEY_F, sm_key);
+
+	if (ibdebug > 1)
+		xdump(stdout, "SA Request:\n", umad_get_mad(umad), len);
+
+	ret = umad_send(h->fd, h->agent, umad, len, ibd_timeout, 0);
+	if (ret < 0) {
+		IBWARN("umad_send failed: attr %u: %s\n",
+			attr, strerror(errno));
+		free(umad);
+		return (IB_ERROR);
+	}
+
+recv_mad:
+	ret = umad_recv(h->fd, umad, &len, ibd_timeout);
+	if (ret < 0) {
+		if (errno == ENOSPC) {
+			umad = realloc(umad, umad_size() + len);
+			goto recv_mad;
+		}
+		IBWARN("umad_recv failed: attr 0x%x: %s\n", attr,
+			strerror(errno));
+		free(umad);
+		return (IB_ERROR);
+	}
+
+	if ((ret = umad_status(umad)))
+		return ret;
+
+	mad = umad_get_mad(umad);
+
+	if (ibdebug > 1)
+		xdump(stdout, "SA Response:\n", mad, len);
+
+	method = (uint8_t) mad_get_field(mad, 0, IB_MAD_METHOD_F);
+	offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
+	result->status = mad_get_field(mad, 0, IB_MAD_STATUS_F);
+	result->p_result_madw = mad;
+	if (result->status != IB_SA_MAD_STATUS_SUCCESS)
+		result->result_cnt = 0;
+	else if (method != IB_MAD_METHOD_GET_TABLE)
+		result->result_cnt = 1;
+	else if (!offset)
+		result->result_cnt = 0;
+	else
+		result->result_cnt = (len - IB_SA_DATA_OFFS) / (offset << 3);
+
+	return 0;
+}
+
+void sa_free_result_mad(struct sa_query_result *result)
+{
+	if (result->p_result_madw) {
+		free((uint8_t *) result->p_result_madw - umad_size());
+		result->p_result_madw = NULL;
+	}
+}
+
+void *sa_get_query_rec(void *mad, unsigned i)
+{
+	int offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
+	return (uint8_t *) mad + IB_SA_DATA_OFFS + i * (offset << 3);
+}
+
+static const char *ib_sa_error_str[] = {
+	"SA_NO_ERROR",
+	"SA_ERR_NO_RESOURCES",
+	"SA_ERR_REQ_INVALID",
+	"SA_ERR_NO_RECORDS",
+	"SA_ERR_TOO_MANY_RECORDS",
+	"SA_ERR_REQ_INVALID_GID",
+	"SA_ERR_REQ_INSUFFICIENT_COMPONENTS",
+	"SA_ERR_REQ_DENIED",
+	"SA_ERR_STATUS_PRIO_SUGGESTED",
+	"SA_ERR_UNKNOWN"
+};
+
+#define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+#define SA_ERR_UNKNOWN (ARR_SIZE(ib_sa_error_str) - 1)
+
+static inline const char *ib_sa_err_str(IN uint8_t status)
+{
+	if (status > SA_ERR_UNKNOWN)
+		status = SA_ERR_UNKNOWN;
+	return (ib_sa_error_str[status]);
+}
+
+void sa_report_err(int status)
+{
+	int st = status & 0xff;
+	char sm_err_str[64] = { 0 };
+	char sa_err_str[64] = { 0 };
+
+	if (st)
+		sprintf(sm_err_str, " SM(%s)", ib_get_err_str(st));
+
+	st = status >> 8;
+	if (st)
+		sprintf(sa_err_str, " SA(%s)", ib_sa_err_str((uint8_t) st));
+
+	fprintf(stderr, "ERROR: Query result returned 0x%04x, %s%s\n",
+		status, sm_err_str, sa_err_str);
+}
diff --git a/trunk/tools/infiniband-diags/src/iblinkinfo.c b/trunk/tools/infiniband-diags/src/iblinkinfo.c
index d0c9b13..c07d33e 100644
--- a/trunk/tools/infiniband-diags/src/iblinkinfo.c
+++ b/trunk/tools/infiniband-diags/src/iblinkinfo.c
@@ -2,6 +2,7 @@
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2008 Lawrence Livermore National Lab.  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,9 +54,20 @@
 
 #include "ibdiag_common.h"
 
+#define DIFF_FLAG_PORT_CONNECTION  0x01
+#define DIFF_FLAG_PORT_STATE       0x02
+#define DIFF_FLAG_LID              0x04
+#define DIFF_FLAG_NODE_DESCRIPTION 0x08
+
+#define DIFF_FLAG_DEFAULT (DIFF_FLAG_PORT_CONNECTION | DIFF_FLAG_PORT_STATE)
+
 static char *node_name_map_file = NULL;
 static nn_map_t *node_name_map = NULL;
 static char *load_cache_file = NULL;
+static char *diff_cache_file = NULL;
+static unsigned diffcheck_flags = DIFF_FLAG_DEFAULT;
+static char *filterdownports_cache_file = NULL;
+static ibnd_fabric_t *filterdownports_fabric = NULL;
 
 static uint64_t guid = 0;
 static char *guid_str = NULL;
@@ -65,7 +77,6 @@ static int all = 0;
 static int down_links_only = 0;
 static int line_mode = 0;
 static int add_sw_settings = 0;
-static int print_port_guids = 0;
 
 static unsigned int get_max(unsigned int num)
 {
@@ -107,7 +118,31 @@ void get_msg(char *width_msg, char *speed_msg, int msg_size, ibnd_port_t * port)
 				      buf, 64, &max_speed));
 }
 
-void print_port(ibnd_node_t * node, ibnd_port_t * port)
+int filterdownport_check(ibnd_node_t * node, ibnd_port_t * port)
+{
+	ibnd_node_t *fsw;
+	ibnd_port_t *fport;
+	int fistate;
+
+	fsw = ibnd_find_node_guid(filterdownports_fabric, node->guid);
+
+	if (!fsw)
+		return 0;
+
+	if (port->portnum > fsw->numports)
+		return 0;
+
+	fport = fsw->ports[port->portnum];
+
+	if (!fport)
+		return 0;
+
+	fistate = mad_get_field(fport->info, 0, IB_PORT_STATE_F);
+
+	return (fistate == IB_LINK_DOWN) ? 1 : 0;
+}
+
+void print_port(ibnd_node_t * node, ibnd_port_t * port, char *out_prefix)
 {
 	char width[64], speed[64], state[64], physstate[64];
 	char remote_guid_str[256];
@@ -133,6 +168,11 @@ void print_port(ibnd_node_t * node, ibnd_port_t * port)
 	width_msg[0] = '\0';
 	speed_msg[0] = '\0';
 
+	if (istate == IB_LINK_DOWN
+	    && filterdownports_fabric
+	    && filterdownport_check(node, port))
+		return;
+
 	/* C14-24.2.1 states that a down port allows for invalid data to be
 	 * returned for all PortInfo components except PortState and
 	 * PortPhysicalState */
@@ -176,14 +216,9 @@ void print_port(ibnd_node_t * node, ibnd_port_t * port)
 		get_msg(width_msg, speed_msg, 256, port);
 
 		if (line_mode) {
-			if (print_port_guids)
-				snprintf(remote_guid_str, 256,
-					 "0x%016" PRIx64 " ",
-					 port->remoteport->guid);
-			else
-				snprintf(remote_guid_str, 256,
-					 "0x%016" PRIx64 " ",
-					 port->remoteport->node->guid);
+			snprintf(remote_guid_str, 256,
+				 "0x%016" PRIx64 " ",
+				 port->remoteport->guid);
 		}
 
 		snprintf(remote_str, 256, "%s%6d %4d[%2s] \"%s\" (%s %s)\n",
@@ -204,21 +239,64 @@ void print_port(ibnd_node_t * node, ibnd_port_t * port)
 	if (line_mode) {
 		char *remap = remap_node_name(node_name_map, node->guid,
 					      node->nodedesc);
-		printf("0x%016" PRIx64 " \"%30s\" ", node->guid, remap);
+		printf("%s0x%016" PRIx64 " \"%30s\" ",
+		       out_prefix ? out_prefix : "",
+		       port->guid, remap);
 		free(remap);
 	} else
-		printf("      ");
+		printf("%s      ", out_prefix ? out_prefix : "");
+
+	if (port->node->type != IB_NODE_SWITCH) {
+		if (!line_mode)
+			printf("0x%016" PRIx64 " ", port->guid);
+
+		printf("%6d %4d[%2s] ==%s==>  %s",
+			port->base_lid,
+			port->portnum, ext_port_str, link_str, remote_str);
+	} else
+		printf("%6d %4d[%2s] ==%s==>  %s",
+			node->smalid, port->portnum, ext_port_str,
+			link_str, remote_str);
+}
+
+static inline const char *nodetype_str(ibnd_node_t * node)
+{
+	switch (node->type) {
+	case IB_NODE_SWITCH:
+		return "Switch";
+	case IB_NODE_CA:
+		return "CA";
+	case IB_NODE_ROUTER:
+		return "Router";
+	}
+	return "??";
+}
 
-	printf("%6d %4d[%2s] ==%s==>  %s",
-	       node->smalid, port->portnum, ext_port_str, link_str, remote_str);
+void print_node_header(ibnd_node_t *node, int *out_header_flag,
+			char *out_prefix)
+{
+	if ((!out_header_flag || !(*out_header_flag)) && !line_mode) {
+		char *remap =
+			remap_node_name(node_name_map, node->guid, node->nodedesc);
+		if (node->type == IB_NODE_SWITCH)
+			printf("%s%s: 0x%016" PRIx64 " %s:\n",
+				out_prefix ? out_prefix : "",
+				nodetype_str(node),
+				node->ports[0]->guid, remap);
+		else
+			printf("%s%s: %s:\n",
+				out_prefix ? out_prefix : "",
+				nodetype_str(node), remap);
+		(*out_header_flag)++;
+		free(remap);
+	}
 }
 
-void print_switch(ibnd_node_t * node, void *user_data)
+void print_node(ibnd_node_t * node, void *user_data)
 {
 	int i = 0;
 	int head_print = 0;
-	char *remap =
-	    remap_node_name(node_name_map, node->guid, node->nodedesc);
+	char *out_prefix = (char *)user_data;
 
 	for (i = 1; i <= node->numports; i++) {
 		ibnd_port_t *port = node->ports[i];
@@ -227,20 +305,192 @@ void print_switch(ibnd_node_t * node, void *user_data)
 		if (!down_links_only ||
 		    mad_get_field(port->info, 0,
 				  IB_PORT_STATE_F) == IB_LINK_DOWN) {
-			if (!head_print && !line_mode) {
-				printf("Switch 0x%016" PRIx64 " %s:\n",
-				       node->guid, remap);
-				head_print = 1;
-			}
-			print_port(node, port);
+			print_node_header(node, &head_print, out_prefix);
+			print_port(node, port, out_prefix);
 		}
 	}
-	free(remap);
+}
+
+struct iter_diff_data {
+        uint32_t diff_flags;
+        ibnd_fabric_t *fabric1;
+        ibnd_fabric_t *fabric2;
+        char *fabric1_prefix;
+        char *fabric2_prefix;
+};
+
+void diff_node_ports(ibnd_node_t * fabric1_node, ibnd_node_t * fabric2_node,
+		       int *head_print, struct iter_diff_data *data)
+{
+	int i = 0;
+
+	for (i = 1; i <= fabric1_node->numports; i++) {
+		ibnd_port_t *fabric1_port, *fabric2_port;
+		int output_diff = 0;
+
+		fabric1_port = fabric1_node->ports[i];
+		fabric2_port = fabric2_node->ports[i];
+
+		if (!fabric1_port && !fabric2_port)
+			continue;
+
+		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION) {
+			if ((fabric1_port && !fabric2_port)
+			    || (!fabric1_port && fabric2_port)
+			    || (fabric1_port->remoteport
+				&& !fabric2_port->remoteport)
+			    || (!fabric1_port->remoteport
+				&& fabric2_port->remoteport)
+			    || (fabric1_port->remoteport
+				&& fabric2_port->remoteport
+				&& fabric1_port->remoteport->guid !=
+				fabric2_port->remoteport->guid))
+				output_diff++;
+		}
+
+		/* if either fabric1_port or fabric2_port NULL, should be
+		 * handled by port connection diff code
+		 */
+		if (data->diff_flags & DIFF_FLAG_PORT_STATE
+		    && fabric1_port
+		    && fabric2_port) {
+			int state1, state2;
+
+			state1 = mad_get_field(fabric1_port->info, 0,
+					       IB_PORT_STATE_F);
+			state2 = mad_get_field(fabric2_port->info, 0,
+					       IB_PORT_STATE_F);
+
+			if (state1 != state2)
+				output_diff++;
+		}
+
+		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+		    && data->diff_flags & DIFF_FLAG_LID
+		    && fabric1_port && fabric2_port
+		    && fabric1_port->remoteport && fabric2_port->remoteport
+		    && fabric1_port->remoteport->base_lid != fabric2_port->remoteport->base_lid)
+			output_diff++;
+
+		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+		    && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
+		    && fabric1_port && fabric2_port
+		    && fabric1_port->remoteport && fabric2_port->remoteport
+		    && memcmp(fabric1_port->remoteport->node->nodedesc,
+			      fabric2_port->remoteport->node->nodedesc,
+			      IB_SMP_DATA_SIZE))
+			output_diff++;
+
+		if (output_diff && fabric1_port) {
+			print_node_header(fabric1_node,
+					    head_print,
+					    NULL);
+			print_port(fabric1_node,
+				   fabric1_port,
+				   data->fabric1_prefix);
+		}
+
+		if (output_diff && fabric2_port) {
+			print_node_header(fabric1_node,
+					    head_print,
+					    NULL);
+			print_port(fabric2_node,
+				   fabric2_port,
+				   data->fabric2_prefix);
+		}
+	}
+}
+
+void diff_node_iter(ibnd_node_t * fabric1_node, void *iter_user_data)
+{
+	struct iter_diff_data *data = iter_user_data;
+	ibnd_node_t *fabric2_node;
+	int head_print = 0;
+
+	DEBUG("DEBUG: fabric1_node %p\n", fabric1_node);
+
+	fabric2_node = ibnd_find_node_guid(data->fabric2, fabric1_node->guid);
+	if (!fabric2_node)
+		print_node(fabric1_node, data->fabric1_prefix);
+	else if (data->diff_flags &
+		 (DIFF_FLAG_PORT_CONNECTION | DIFF_FLAG_PORT_STATE
+		  | DIFF_FLAG_LID | DIFF_FLAG_NODE_DESCRIPTION)) {
+
+		if ((fabric1_node->type == IB_NODE_SWITCH
+		     && data->diff_flags & DIFF_FLAG_LID
+		     && fabric1_node->smalid != fabric2_node->smalid) ||
+		    (data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
+		     && memcmp(fabric1_node->nodedesc, fabric2_node->nodedesc,
+			       IB_SMP_DATA_SIZE))) {
+			print_node_header(fabric1_node,
+					    NULL,
+					    data->fabric1_prefix);
+			print_node_header(fabric2_node,
+					    NULL,
+					    data->fabric2_prefix);
+			head_print++;
+		}
+
+		if (fabric1_node->numports != fabric2_node->numports) {
+			print_node_header(fabric1_node,
+					    &head_print,
+					    NULL);
+			printf("%snumports = %d\n", data->fabric1_prefix,
+			       fabric1_node->numports);
+			printf("%snumports = %d\n", data->fabric2_prefix,
+			       fabric2_node->numports);
+			return;
+		}
+
+		diff_node_ports(fabric1_node, fabric2_node,
+				  &head_print, data);
+	}
+}
+
+int diff_node(ibnd_node_t * node, ibnd_fabric_t * orig_fabric,
+		ibnd_fabric_t * new_fabric)
+{
+	struct iter_diff_data iter_diff_data;
+
+	iter_diff_data.diff_flags = diffcheck_flags;
+	iter_diff_data.fabric1 = orig_fabric;
+	iter_diff_data.fabric2 = new_fabric;
+	iter_diff_data.fabric1_prefix = "< ";
+	iter_diff_data.fabric2_prefix = "> ";
+	if (node)
+		diff_node_iter(node, &iter_diff_data);
+	else
+		ibnd_iter_nodes(orig_fabric, diff_node_iter, &iter_diff_data);
+
+	/* Do opposite diff to find existence of node types
+	 * in new_fabric but not in orig_fabric.
+	 *
+	 * In this diff, we don't need to check port connections,
+	 * port state, lids, or node descriptions since it has already
+	 * been done (i.e. checks are only done when guid exists on both
+	 * orig and new).
+	 */
+	iter_diff_data.diff_flags = diffcheck_flags & ~DIFF_FLAG_PORT_CONNECTION;
+	iter_diff_data.diff_flags &= ~DIFF_FLAG_PORT_STATE;
+	iter_diff_data.diff_flags &= ~DIFF_FLAG_LID;
+	iter_diff_data.diff_flags &= ~DIFF_FLAG_NODE_DESCRIPTION;
+	iter_diff_data.fabric1 = new_fabric;
+	iter_diff_data.fabric2 = orig_fabric;
+	iter_diff_data.fabric1_prefix = "> ";
+	iter_diff_data.fabric2_prefix = "< ";
+	if (node)
+		diff_node_iter(node, &iter_diff_data);
+	else
+		ibnd_iter_nodes(new_fabric, diff_node_iter, &iter_diff_data);
+
+	return 0;
 }
 
 static int process_opt(void *context, int ch, char *optarg)
 {
 	struct ibnd_config *cfg = context;
+	char *p;
+
 	switch (ch) {
 	case 1:
 		node_name_map_file = strdup(optarg);
@@ -248,7 +498,34 @@ static int process_opt(void *context, int ch, char *optarg)
 	case 2:
 		load_cache_file = strdup(optarg);
 		break;
+	case 3:
+		diff_cache_file = strdup(optarg);
+		break;
+	case 4:
+		diffcheck_flags = 0;
+		p = strtok(optarg, ",");
+		while (p) {
+			if (!strcasecmp(p, "port"))
+				diffcheck_flags |= DIFF_FLAG_PORT_CONNECTION;
+			else if (!strcasecmp(p, "state"))
+				diffcheck_flags |= DIFF_FLAG_PORT_STATE;
+			else if (!strcasecmp(p, "lid"))
+				diffcheck_flags |= DIFF_FLAG_LID;
+			else if (!strcasecmp(p, "nodedesc"))
+				diffcheck_flags |= DIFF_FLAG_NODE_DESCRIPTION;
+			else {
+				fprintf(stderr, "invalid diff check key: %s\n",
+					p);
+				return -1;
+			}
+			p = strtok(NULL, ",");
+		}
+		break;
+	case 5:
+		filterdownports_cache_file = strdup(optarg);
+		break;
 	case 'S':
+	case 'G':
 		guid_str = optarg;
 		guid = (uint64_t) strtoull(guid_str, 0, 0);
 		break;
@@ -270,9 +547,6 @@ static int process_opt(void *context, int ch, char *optarg)
 	case 'p':
 		add_sw_settings = 1;
 		break;
-	case 'g':
-		print_port_guids = 1;
-		break;
 	case 'R':		/* nop */
 		break;
 	case 'o':
@@ -291,6 +565,7 @@ int main(int argc, char **argv)
 	int rc = 0;
 	int resolved = -1;
 	ibnd_fabric_t *fabric = NULL;
+	ibnd_fabric_t *diff_fabric = NULL;
 	struct ibmad_port *ibmad_port;
 	ib_portid_t port_id = { 0 };
 	int mgmt_classes[3] =
@@ -298,23 +573,29 @@ int main(int argc, char **argv)
 
 	const struct ibdiag_opt opts[] = {
 		{"node-name-map", 1, 1, "<file>", "node name map file"},
-		{"switch", 'S', 1, "<switch_guid>",
-		 "query only <switch_guid> (hex format)"},
+		{"switch", 'S', 1, "<port_guid>",
+		 "start partial scan at the port specified by <port_guid> (hex format)"},
+		{"port-guid", 'G', 1, "<port_guid>",
+		 "(same as -S)"},
 		{"Direct", 'D', 1, "<dr_path>",
-		 "query only node specified by <dr_path>"},
+		 "start partial scan at the port specified by <dr_path>"},
 		{"all", 'a', 0, NULL,
-		 "print all switches found in a partial fabric scan"},
+		 "print all nodes found in a partial fabric scan"},
 		{"hops", 'n', 1, "<hops>",
 		 "Number of hops to include away from specified node"},
 		{"down", 'd', 0, NULL, "print only down links"},
 		{"line", 'l', 0, NULL,
 		 "(line mode) print all information for each link on a single line"},
 		{"additional", 'p', 0, NULL,
-		 "print additional switch settings (PktLifeTime, HoqLife, VLStallCount)"},
-		{"portguids", 'g', 0, NULL,
-		 "print port guids instead of node guids"},
+		 "print additional port settings (PktLifeTime, HoqLife, VLStallCount)"},
 		{"load-cache", 2, 1, "<file>",
 		 "filename of ibnetdiscover cache to load"},
+		{"diff", 3, 1, "<file>",
+		 "filename of ibnetdiscover cache to diff"},
+		{"diffcheck", 4, 1, "<key(s)>",
+		 "specify checks to execute for --diff"},
+		{"filterdownports", 5, 1, "<file>",
+		 "filename of ibnetdiscover cache to filter downports"},
 		{"outstanding_smps", 'o', 1, NULL,
 		 "specify the number of outstanding SMP's which should be "
 		 "issued during the scan"},
@@ -355,7 +636,7 @@ int main(int argc, char **argv)
 		     ib_resolve_portid_str_via(&port_id, dr_path,
 					       IB_DEST_DRPATH, NULL,
 					       ibmad_port)) < 0)
-			IBWARN("Failed to resolve %s; attempting full scan\n",
+			IBWARN("Failed to resolve %s; attempting full scan",
 			       dr_path);
 	} else if (guid_str) {
 		if ((resolved =
@@ -365,17 +646,28 @@ int main(int argc, char **argv)
 			       guid_str);
 	}
 
+	if (diff_cache_file &&
+	    !(diff_fabric = ibnd_load_fabric(diff_cache_file, 0)))
+		IBERROR("loading cached fabric for diff failed\n");
+
+	if (filterdownports_cache_file &&
+	    !(filterdownports_fabric = ibnd_load_fabric(filterdownports_cache_file, 0)))
+		IBERROR("loading cached fabric for filterdownports failed\n");
+
 	if (load_cache_file) {
 		if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL) {
 			fprintf(stderr, "loading cached fabric failed\n");
 			exit(1);
 		}
 	} else {
-		if (resolved >= 0 &&
-		    !(fabric =
-		      ibnd_discover_fabric(ibd_ca, ibd_ca_port, &port_id, &config)))
-			IBWARN("Single node discover failed;"
-			       " attempting full scan\n");
+		if (resolved >= 0) {
+			if (!config.max_hops)
+				config.max_hops = 1;
+			if (!(fabric =
+			    ibnd_discover_fabric(ibd_ca, ibd_ca_port, &port_id, &config)))
+				IBWARN("Partial fabric scan failed;"
+				       " attempting full scan\n");
+		}
 
 		if (!fabric &&
 		    !(fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL, &config))) {
@@ -386,31 +678,45 @@ int main(int argc, char **argv)
 	}
 
 	if (!all && guid_str) {
-		ibnd_node_t *sw = ibnd_find_node_guid(fabric, guid);
-		if (sw)
-			print_switch(sw, NULL);
+		ibnd_port_t *p = ibnd_find_port_guid(fabric, guid);
+		if (p) {
+			ibnd_node_t *n = p->node;
+			if (diff_fabric)
+				diff_node(n, diff_fabric, fabric);
+			else
+				print_node(n, NULL);
+		}
 		else
-			fprintf(stderr, "Failed to find switch: %s\n",
-				guid_str);
+			fprintf(stderr, "Failed to find port: %s\n", guid_str);
 	} else if (!all && dr_path) {
-		ibnd_node_t *sw = NULL;
-		uint8_t ni[IB_SMP_DATA_SIZE];
+		ibnd_port_t *p = NULL;
+		uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
 
 		if (!smp_query_via(ni, &port_id, IB_ATTR_NODE_INFO, 0,
 				   ibd_timeout, ibmad_port))
 			return -1;
-		mad_decode_field(ni, IB_NODE_GUID_F, &(guid));
+		mad_decode_field(ni, IB_NODE_PORT_GUID_F, &(guid));
 
-		sw = ibnd_find_node_guid(fabric, guid);
-		if (sw)
-			print_switch(sw, NULL);
+		p = ibnd_find_port_guid(fabric, guid);
+		if (p) {
+			ibnd_node_t *n = p->node;
+			if (diff_fabric)
+				diff_node(n, diff_fabric, fabric);
+			else
+				print_node(n, NULL);
+		}
 		else
-			fprintf(stderr, "Failed to find switch: %s\n", dr_path);
-	} else
-		ibnd_iter_nodes_type(fabric, print_switch, IB_NODE_SWITCH,
-				     NULL);
+			fprintf(stderr, "Failed to find port: %s\n", dr_path);
+	} else {
+		if (diff_fabric)
+			diff_node(NULL, diff_fabric, fabric);
+		else
+			ibnd_iter_nodes(fabric, print_node, NULL);
+	}
 
 	ibnd_destroy_fabric(fabric);
+	if (diff_fabric)
+		ibnd_destroy_fabric(diff_fabric);
 
 close_port:
 	close_node_name_map(node_name_map);
diff --git a/trunk/tools/infiniband-diags/src/iblinkinfo/SOURCES b/trunk/tools/infiniband-diags/src/iblinkinfo/SOURCES
index e864598..2761041 100644
--- a/trunk/tools/infiniband-diags/src/iblinkinfo/SOURCES
+++ b/trunk/tools/infiniband-diags/src/iblinkinfo/SOURCES
@@ -22,6 +22,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(TARGETPATH)\*\complib.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	\
 	$(TARGETPATH)\*\libibnetdisc.lib
diff --git a/trunk/tools/infiniband-diags/src/ibnetdiscover.c b/trunk/tools/infiniband-diags/src/ibnetdiscover.c
index 347e7b2..59304b6 100644
--- a/trunk/tools/infiniband-diags/src/ibnetdiscover.c
+++ b/trunk/tools/infiniband-diags/src/ibnetdiscover.c
@@ -77,6 +77,7 @@ static char *diff_cache_file = NULL;
 static unsigned diffcheck_flags = DIFF_FLAG_DEFAULT;
 
 static int report_max_hops = 0;
+static int full_info;
 
 /**
  * Define our own conversion functions to maintain compatibility with the old
@@ -214,7 +215,9 @@ void out_ids(ibnd_node_t * node, int group, char *chname, char *out_prefix)
 			fprintf(f, " slot %d",
 				node->ports[1]->remoteport->portnum);
 	}
-	fprintf(f, "\n");
+	if (sysimgguid ||
+	    (group && node->chassis && node->chassis->chassisnum))
+		fprintf(f, "\n");
 }
 
 uint64_t out_chassis(ibnd_fabric_t * fabric, unsigned char chassisnum)
@@ -364,6 +367,9 @@ void out_switch_port(ibnd_port_t * port, int group, char *out_prefix)
 		port->remoteport->base_lid,
 		dump_linkwidth_compat(iwidth), dump_linkspeed_compat(ispeed));
 
+	if (full_info)
+		fprintf(f, " s=%d w=%d", ispeed, iwidth);
+
 	if (ibnd_is_xsigo_tca(port->remoteport->guid))
 		fprintf(f, " slot %d", port->portnum);
 	else if (ibnd_is_xsigo_hca(port->remoteport->guid))
@@ -397,13 +403,17 @@ void out_ca_port(ibnd_port_t * port, int group, char *out_prefix)
 				       port->remoteport->node->guid,
 				       port->remoteport->node->nodedesc);
 
-	fprintf(f, "\t\t# lid %d lmc %d \"%s\" lid %d %s%s\n",
+	fprintf(f, "\t\t# lid %d lmc %d \"%s\" lid %d %s%s",
 		port->base_lid, port->lmc, rem_nodename,
 		port->remoteport->node->type == IB_NODE_SWITCH ?
 		port->remoteport->node->smalid :
 		port->remoteport->base_lid,
 		dump_linkwidth_compat(iwidth), dump_linkspeed_compat(ispeed));
 
+	if (full_info)
+		fprintf(f, " s=%d w=%d", ispeed, iwidth);
+	fprintf(f, "\n");
+
 	free(rem_nodename);
 }
 
@@ -616,6 +626,8 @@ void dump_ports_report(ibnd_node_t * node, void *user_data)
 {
 	int p = 0;
 	ibnd_port_t *port = NULL;
+	char *nodename = NULL;
+	char *rem_nodename = NULL;
 
 	/* for each port */
 	for (p = node->numports, port = node->ports[p]; p > 0;
@@ -627,6 +639,9 @@ void dump_ports_report(ibnd_node_t * node, void *user_data)
 		    mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F);
 		ispeed =
 		    mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
+		nodename = remap_node_name(node_name_map,
+					   port->node->guid,
+					   port->node->nodedesc);
 		fprintf(stdout, "%2s %5d %2d 0x%016" PRIx64 " %s %s",
 			ports_nt_str_compat(node),
 			node->type ==
@@ -634,7 +649,10 @@ void dump_ports_report(ibnd_node_t * node, void *user_data)
 			port->portnum, port->guid,
 			dump_linkwidth_compat(iwidth),
 			dump_linkspeed_compat(ispeed));
-		if (port->remoteport)
+		if (port->remoteport) {
+			rem_nodename = remap_node_name(node_name_map,
+					      port->remoteport->node->guid,
+					      port->remoteport->node->nodedesc);
 			fprintf(stdout,
 				" - %2s %5d %2d 0x%016" PRIx64
 				" ( '%s' - '%s' )\n",
@@ -643,10 +661,12 @@ void dump_ports_report(ibnd_node_t * node, void *user_data)
 				port->remoteport->node->smalid :
 				port->remoteport->base_lid,
 				port->remoteport->portnum,
-				port->remoteport->guid, port->node->nodedesc,
-				port->remoteport->node->nodedesc);
-		else
-			fprintf(stdout, "%36s'%s'\n", "", port->node->nodedesc);
+				port->remoteport->guid, nodename, rem_nodename);
+			free(rem_nodename);
+		} else
+			fprintf(stdout, "%36s'%s'\n", "", nodename);
+
+		free(nodename);
 	}
 }
 
@@ -714,6 +734,37 @@ static void diff_ports(ibnd_node_t * fabric1_node, ibnd_node_t * fabric2_node,
 			fabric2_out++;
 		}
 
+		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+		    && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
+		    && fabric1_port && fabric2_port
+		    && fabric1_port->remoteport && fabric2_port->remoteport
+		    && memcmp(fabric1_port->remoteport->node->nodedesc,
+			      fabric2_port->remoteport->node->nodedesc,
+			      IB_SMP_DATA_SIZE)) {
+			fabric1_out++;
+			fabric2_out++;
+		}
+
+		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+		    && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
+		    && fabric1_port && fabric2_port
+		    && fabric1_port->remoteport && fabric2_port->remoteport
+		    && memcmp(fabric1_port->remoteport->node->nodedesc,
+			      fabric2_port->remoteport->node->nodedesc,
+			      IB_SMP_DATA_SIZE)) {
+			fabric1_out++;
+			fabric2_out++;
+		}
+
+		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+		    && data->diff_flags & DIFF_FLAG_LID
+		    && fabric1_port && fabric2_port
+		    && fabric1_port->remoteport && fabric2_port->remoteport
+		    && fabric1_port->remoteport->base_lid != fabric2_port->remoteport->base_lid) {
+			fabric1_out++;
+			fabric2_out++;
+		}
+
 		if (fabric1_out) {
 			diff_iter_out_header(fabric1_node, data,
 					     out_header_flag);
@@ -895,6 +946,9 @@ static int process_opt(void *context, int ch, char *optarg)
 	case 's':
 		cfg->show_progress = 1;
 		break;
+	case 'f':
+		full_info = 1;
+		break;
 	case 'l':
 		list = LIST_CA_NODE | LIST_SWITCH_NODE | LIST_ROUTER_NODE;
 		break;
@@ -933,6 +987,7 @@ int main(int argc, char **argv)
 	ibnd_fabric_t *diff_fabric = NULL;
 
 	const struct ibdiag_opt opts[] = {
+		{"full", 'f', 0, NULL, "show full information (ports' speed and width)"},
 		{"show", 's', 0, NULL, "show more information"},
 		{"list", 'l', 0, NULL, "list of connected nodes"},
 		{"grouping", 'g', 0, NULL, "show grouping"},
diff --git a/trunk/tools/infiniband-diags/src/ibnetdiscover/SOURCES b/trunk/tools/infiniband-diags/src/ibnetdiscover/SOURCES
index 22bfc67..86eae18 100644
--- a/trunk/tools/infiniband-diags/src/ibnetdiscover/SOURCES
+++ b/trunk/tools/infiniband-diags/src/ibnetdiscover/SOURCES
@@ -22,6 +22,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(TARGETPATH)\*\complib.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	\
 	$(TARGETPATH)\*\libibnetdisc.lib
diff --git a/trunk/tools/infiniband-diags/src/ibping.c b/trunk/tools/infiniband-diags/src/ibping.c
index dafab1c..016679d 100644
--- a/trunk/tools/infiniband-diags/src/ibping.c
+++ b/trunk/tools/infiniband-diags/src/ibping.c
@@ -138,7 +138,7 @@ static uint64_t minrtt = ~0ull, maxrtt, total_rtt;
 static uint64_t start, total_time, replied, lost, ntrans;
 static ib_portid_t portid = { 0 };
 
-void __cdecl report(int sig)
+void report(int sig)
 {
 	total_time = cl_get_time_stamp() - start;
 
diff --git a/trunk/tools/infiniband-diags/src/ibping/SOURCES b/trunk/tools/infiniband-diags/src/ibping/SOURCES
index 341f589..12d3a5e 100644
--- a/trunk/tools/infiniband-diags/src/ibping/SOURCES
+++ b/trunk/tools/infiniband-diags/src/ibping/SOURCES
@@ -21,6 +21,7 @@ TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
 	$(TARGETPATH)\*\complib.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/tools/infiniband-diags/src/ibportstate.c b/trunk/tools/infiniband-diags/src/ibportstate.c
index 499dabc..1f0f42e 100644
--- a/trunk/tools/infiniband-diags/src/ibportstate.c
+++ b/trunk/tools/infiniband-diags/src/ibportstate.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 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
@@ -125,7 +126,7 @@ static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
 	char buf[2048];
 	char val[64];
 
-	mad_dump_portstates(buf, sizeof buf, data, sizeof data);
+	mad_dump_portstates(buf, sizeof buf, data, sizeof *data);
 	mad_decode_field(data, IB_PORT_LID_F, val);
 	mad_dump_field(IB_PORT_LID_F, buf + strlen(buf),
 		       sizeof buf - strlen(buf), val);
@@ -247,7 +248,7 @@ int main(int argc, char **argv)
 	int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss,
 	    peerlsa;
 	int peerwidth, peerspeed;
-	uint8_t data[IB_SMP_DATA_SIZE];
+	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
 	ib_portid_t peerportid = { 0 };
 	int portnum = 0;
 	ib_portid_t selfportid = { 0 };
@@ -356,6 +357,7 @@ 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);
 
diff --git a/trunk/tools/infiniband-diags/src/ibportstate/SOURCES b/trunk/tools/infiniband-diags/src/ibportstate/SOURCES
index 1fa9adc..851e77f 100644
--- a/trunk/tools/infiniband-diags/src/ibportstate/SOURCES
+++ b/trunk/tools/infiniband-diags/src/ibportstate/SOURCES
@@ -19,6 +19,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib
 
diff --git a/trunk/tools/infiniband-diags/src/ibqueryerrors.c b/trunk/tools/infiniband-diags/src/ibqueryerrors.c
index f04e47f..4677db4 100644
--- a/trunk/tools/infiniband-diags/src/ibqueryerrors.c
+++ b/trunk/tools/infiniband-diags/src/ibqueryerrors.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
+ * Copyright (c) 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
@@ -61,9 +62,10 @@ static nn_map_t *node_name_map = NULL;
 static char *load_cache_file = NULL;
 
 int data_counters = 0;
+int data_counters_only = 0;
 int port_config = 0;
-uint64_t node_guid = 0;
-char *node_guid_str = NULL;
+uint64_t port_guid = 0;
+char *port_guid_str = NULL;
 #define SUP_MAX 64
 int sup_total = 0;
 enum MAD_FIELDS suppressed_fields[SUP_MAX];
@@ -76,6 +78,88 @@ unsigned clear_errors = 0, clear_counts = 0, details = 0;
 #define PRINT_ROUTER 0x4
 #define PRINT_ALL 0xFF		/* all nodes default flag */
 
+struct {
+	int nodes_checked;
+	int bad_nodes;
+	int ports_checked;
+	int bad_ports;
+} summary = { 0 };
+
+#define DEF_THRES_FILE IBDIAG_CONFIG_PATH"/error_thresholds"
+static char *threshold_file = DEF_THRES_FILE;
+
+/* define a "packet" with threshold values in it */
+uint8_t thresholds[1204] = { 0 };
+char * threshold_str = "";
+
+static void set_thres(char *name, uint32_t val)
+{
+	int f;
+	int n;
+	char tmp[256];
+	for (f = IB_PC_FIRST_F; f <= IB_PC_LAST_F; f++) {
+		if (strcmp(name, mad_field_name(f)) == 0) {
+			mad_encode_field(thresholds, f, &val);
+			snprintf(tmp, 255, "[%s = %u]", name, val);
+			threshold_str = realloc(threshold_str,
+					strlen(threshold_str)+strlen(tmp)+1);
+			if (!threshold_str) {
+				fprintf(stderr, "Failed to allocate memory: "
+					"%s\n", strerror(errno));
+				exit(1);
+			}
+			n = strlen(threshold_str);
+			strcpy(threshold_str+n, tmp);
+		}
+	}
+}
+
+static void set_thresholds(char *threshold_file)
+{
+	char buf[1024];
+	int val = 0;
+	FILE *thresf = fopen(threshold_file, "r");
+	char *p_prefix, *p_last;
+	char *name;
+	char *val_str;
+	char str[64];
+
+	if (!thresf)
+		return;
+
+	snprintf(str, 63, "Thresholds: ");
+	threshold_str = malloc(strlen(str)+1);
+	if (!threshold_str) {
+		fprintf(stderr, "Failed to allocate memory: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+	strcpy(threshold_str, str);
+	while (fgets(buf, sizeof buf, thresf) != NULL) {
+		p_prefix = strtok_r(buf, "\n", &p_last);
+		if (!p_prefix)
+			continue; /* ignore blank lines */
+
+		if (*p_prefix == '#')
+			continue; /* ignore comment lines */
+
+		name = strtok_r(p_prefix, "=", &p_last);
+		val_str = strtok_r(NULL, "\n", &p_last);
+
+		val = strtoul(val_str, NULL, 0);
+		set_thres(name, val);
+	}
+
+	fclose(thresf);
+}
+
+static int exceeds_threshold(int field, unsigned val)
+{
+	uint32_t thres = 0;
+	mad_decode_field(thresholds, field, &thres);
+	return (val > thres);
+}
+
 static unsigned int get_max(unsigned int num)
 {
 	unsigned r = 0;		// r will be lg(num)
@@ -175,7 +259,7 @@ static void print_port_config(char *node_name, ibnd_node_t * node, int portnum)
 
 		snprintf(remote_str, 256,
 			 "0x%016" PRIx64 " %6d %4d[%2s] \"%s\" (%s %s)\n",
-			 port->remoteport->node->guid,
+			 port->remoteport->guid,
 			 port->remoteport->base_lid ? port->remoteport->
 			 base_lid : port->remoteport->node->smalid,
 			 port->remoteport->portnum, ext_port_str, rem_node_name,
@@ -211,12 +295,22 @@ static int suppress(enum MAD_FIELDS field)
 static void report_suppressed(void)
 {
 	int i = 0;
-	printf("Suppressing:");
+	printf("## Suppresed:");
 	for (i = 0; i < sup_total; i++)
 		printf(" %s", mad_field_name(suppressed_fields[i]));
 	printf("\n");
 }
 
+static void print_summary(void)
+{
+	printf("\n## Summary: %d nodes checked, %d bad nodes found\n",
+		summary.nodes_checked, summary.bad_nodes);
+	printf("##          %d ports checked, %d ports have errors beyond threshold\n",
+		summary.ports_checked, summary.bad_ports);
+	printf("## %s\n", threshold_str);
+	report_suppressed();
+}
+
 static int query_and_dump(char *buf, size_t size, ib_portid_t * portid,
 			  ibnd_node_t * node, char *node_name, int portnum,
 			  const char *attr_name, uint16_t attr_id,
@@ -245,9 +339,9 @@ static int query_and_dump(char *buf, size_t size, ib_portid_t * portid,
 	return n;
 }
 
-static void print_results(ib_portid_t * portid, char *node_name,
-			  ibnd_node_t * node, uint8_t * pc, int portnum,
-			  int *header_printed)
+static int print_results(ib_portid_t * portid, char *node_name,
+			 ibnd_node_t * node, uint8_t * pc, int portnum,
+			 int *header_printed, uint8_t *pce, uint16_t cap_mask)
 {
 	char buf[1024];
 	char *str = buf;
@@ -263,65 +357,91 @@ static void print_results(ib_portid_t * portid, char *node_name,
 			continue;
 
 		mad_decode_field(pc, i, (void *)&val);
-		if (val)
+		if (exceeds_threshold(i, val)) {
 			n += snprintf(str + n, 1024 - n, " [%s == %u]",
 				      mad_field_name(i), val);
 
-		/* If there are PortXmitDiscards, get details (if supported) */
-		if (i == IB_PC_XMT_DISCARDS_F && details && val) {
-			n += query_and_dump(str + n, sizeof(buf) - n, portid,
-					    node, node_name, portnum,
-					    "PortXmitDiscardDetails",
-					    IB_GSI_PORT_XMIT_DISCARD_DETAILS,
-					    IB_PC_RCV_LOCAL_PHY_ERR_F,
-					    IB_PC_RCV_ERR_LAST_F);
-			/* If there are PortRcvErrors, get details (if supported) */
-		} else if (i == IB_PC_ERR_RCV_F && details && val) {
-			n += query_and_dump(str + n, sizeof(buf) - n, portid,
-					    node, node_name, portnum,
-					    "PortRcvErrorDetails",
-					    IB_GSI_PORT_RCV_ERROR_DETAILS,
-					    IB_PC_XMT_INACT_DISC_F,
-					    IB_PC_XMT_DISC_LAST_F);
+			/* If there are PortXmitDiscards, get details (if supported) */
+			if (i == IB_PC_XMT_DISCARDS_F && details) {
+				n += query_and_dump(str + n, sizeof(buf) - n, portid,
+						    node, node_name, portnum,
+						    "PortXmitDiscardDetails",
+						    IB_GSI_PORT_XMIT_DISCARD_DETAILS,
+						    IB_PC_RCV_LOCAL_PHY_ERR_F,
+						    IB_PC_RCV_ERR_LAST_F);
+				/* If there are PortRcvErrors, get details (if supported) */
+			} else if (i == IB_PC_ERR_RCV_F && details) {
+				n += query_and_dump(str + n, sizeof(buf) - n, portid,
+						    node, node_name, portnum,
+						    "PortRcvErrorDetails",
+						    IB_GSI_PORT_RCV_ERROR_DETAILS,
+						    IB_PC_XMT_INACT_DISC_F,
+						    IB_PC_XMT_DISC_LAST_F);
+			}
 		}
 	}
 
 	if (!suppress(IB_PC_XMT_WAIT_F)) {
 		mad_decode_field(pc, IB_PC_XMT_WAIT_F, (void *)&val);
-		if (val)
+		if (exceeds_threshold(IB_PC_XMT_WAIT_F, val))
 			n += snprintf(str + n, 1024 - n, " [%s == %u]",
 				      mad_field_name(IB_PC_XMT_WAIT_F), val);
 	}
 
 	/* if we found errors. */
 	if (n != 0) {
-		if (data_counters)
-			for (i = IB_PC_XMT_BYTES_F; i <= IB_PC_RCV_PKTS_F; i++) {
+		if (data_counters) {
+			uint8_t *pkt = pc;
+			int start_field = IB_PC_XMT_BYTES_F;
+			int end_field = IB_PC_RCV_PKTS_F;
+
+			if (pce) {
+				pkt = pce;
+				start_field = IB_PC_EXT_XMT_BYTES_F;
+				if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
+					end_field = IB_PC_EXT_RCV_MPKTS_F;
+				else
+					end_field = IB_PC_EXT_RCV_PKTS_F;
+			}
+
+			for (i = start_field; i <= end_field; i++) {
 				uint64_t val64 = 0;
-				mad_decode_field(pc, i, (void *)&val64);
+				mad_decode_field(pkt, i, (void *)&val64);
 				if (val64)
 					n += snprintf(str + n, 1024 - n,
-						      " [%s == %" PRIu64 "]",
-						      mad_field_name(i), val64);
+						" [%s == %" PRIu64 "]",
+						mad_field_name(i), val64);
 			}
+		}
 
 		if (!*header_printed) {
-			printf("Errors for 0x%" PRIx64 " \"%s\"\n", node->guid,
-			       node_name);
+			if (node->type == IB_NODE_SWITCH)
+				printf("Errors for 0x%" PRIx64 " \"%s\"\n",
+					node->ports[0]->guid, node_name);
+			else
+				printf("Errors for \"%s\"\n", node_name);
 			*header_printed = 1;
+			summary.bad_nodes++;
 		}
 
-		printf("   GUID 0x%" PRIx64 " port %d:%s\n", node->guid,
-		       portnum, str);
-		if (port_config)
+		if (portnum == 0xFF)
+			printf("   GUID 0x%" PRIx64 " port ALL:%s\n",
+			       node->ports[0]->guid, str);
+		else
+			printf("   GUID 0x%" PRIx64 " port %d:%s\n",
+			       node->ports[portnum]->guid, portnum, str);
+		if (portnum != 0xFF && port_config)
 			print_port_config(node_name, node, portnum);
+
+		summary.bad_ports++;
 	}
+	return (n);
 }
 
 static int query_cap_mask(ib_portid_t * portid, char *node_name, int portnum,
 			  uint16_t * cap_mask)
 {
-	uint8_t pc[1024];
+	uint8_t pc[1024] = { 0 };
 	uint16_t rc_cap_mask;
 
 	/* PerfMgt ClassPortInfo is a required attribute */
@@ -335,63 +455,192 @@ static int query_cap_mask(ib_portid_t * portid, char *node_name, int portnum,
 	/* ClassPortInfo should be supported as part of libibmad */
 	memcpy(&rc_cap_mask, pc + 2, sizeof(rc_cap_mask));	/* CapabilityMask */
 
-	*cap_mask = ntohs(rc_cap_mask);
+	*cap_mask = rc_cap_mask;
 	return 0;
 }
 
-static void print_port(ib_portid_t * portid, uint16_t cap_mask, char *node_name,
-		       ibnd_node_t * node, int portnum, int *header_printed)
+static int print_data_cnts(ib_portid_t * portid, uint16_t cap_mask,
+			   char *node_name, ibnd_node_t * node, int portnum,
+			   int *header_printed)
+{
+	uint8_t pc[1024];
+	int i;
+	int start_field = IB_PC_XMT_BYTES_F;
+	int end_field = IB_PC_RCV_PKTS_F;
+
+	memset(pc, 0, 1024);
+
+	if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) {
+		if (!pma_query_via(pc, portid, portnum, ibd_timeout,
+				   IB_GSI_PORT_COUNTERS_EXT, ibmad_port)) {
+			IBWARN("IB_GSI_PORT_COUNTERS_EXT query failed on %s, %s port %d",
+			       node_name, portid2str(portid), portnum);
+			return (1);
+		}
+		start_field = IB_PC_EXT_XMT_BYTES_F;
+		if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
+			end_field = IB_PC_EXT_RCV_MPKTS_F;
+		else
+			end_field = IB_PC_EXT_RCV_PKTS_F;
+	} else {
+		if (!pma_query_via(pc, portid, portnum, ibd_timeout,
+				   IB_GSI_PORT_COUNTERS, ibmad_port)) {
+			IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d",
+			       node_name, portid2str(portid), portnum);
+			return (1);
+		}
+		start_field = IB_PC_XMT_BYTES_F;
+		end_field = IB_PC_RCV_PKTS_F;
+	}
+
+	if (!*header_printed) {
+		printf("Data Counters for 0x%" PRIx64 " \"%s\"\n", node->guid,
+		       node_name);
+		*header_printed = 1;
+	}
+
+	if (portnum == 0xFF)
+		printf("   GUID 0x%" PRIx64 " port ALL:", node->guid);
+	else
+		printf("   GUID 0x%" PRIx64 " port %d:",
+		       node->guid, portnum);
+
+	for (i = start_field; i <= end_field; i++) {
+		uint64_t val64 = 0;
+		mad_decode_field(pc, i, (void *)&val64);
+		printf(" [%s == %" PRIu64 "]", mad_field_name(i), val64);
+	}
+	printf("\n");
+
+	if (portnum != 0xFF && port_config)
+		print_port_config(node_name, node, portnum);
+
+	return (0);
+}
+
+static int print_errors(ib_portid_t * portid, uint16_t cap_mask,
+			char *node_name, ibnd_node_t * node, int portnum,
+			int *header_printed)
 {
 	uint8_t pc[1024];
+	uint8_t pce[1024];
+	uint8_t *pc_ext = NULL;
 
 	memset(pc, 0, 1024);
+	memset(pce, 0, 1024);
 
 	if (!pma_query_via(pc, portid, portnum, ibd_timeout,
 			   IB_GSI_PORT_COUNTERS, ibmad_port)) {
 		IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d",
 		       node_name, portid2str(portid), portnum);
-		return;
+		return (0);
+	}
+
+	if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) {
+		if (!pma_query_via(pce, portid, portnum, ibd_timeout,
+		    IB_GSI_PORT_COUNTERS_EXT, ibmad_port)) {
+			IBWARN("IB_GSI_PORT_COUNTERS_EXT query failed on %s, %s port %d",
+			       node_name, portid2str(portid), portnum);
+			return (0);
+		}
+		pc_ext = pce;
 	}
-	if (!(cap_mask & 0x1000)) {
+
+	if (!(cap_mask & IB_PM_PC_XMIT_WAIT_SUP)) {
 		/* if PortCounters:PortXmitWait not supported clear this counter */
 		uint32_t foo = 0;
 		mad_encode_field(pc, IB_PC_XMT_WAIT_F, &foo);
 	}
-	print_results(portid, node_name, node, pc, portnum, header_printed);
+	return (print_results(portid, node_name, node, pc, portnum,
+			      header_printed, pc_ext, cap_mask));
+}
+
+uint8_t *reset_pc_ext(void *rcvbuf, ib_portid_t * dest,
+		      int port, unsigned mask, unsigned timeout,
+		      const struct ibmad_port * srcport)
+{
+	ib_rpc_t rpc = { 0 };
+	int lid = dest->lid;
+
+	DEBUG("lid %u port %d mask 0x%x", lid, port, mask);
+
+	if (lid == -1) {
+		IBWARN("only lid routed is supported");
+		return NULL;
+	}
+
+	if (!mask)
+		mask = ~0;
+
+	rpc.mgtclass = IB_PERFORMANCE_CLASS;
+	rpc.method = IB_MAD_METHOD_SET;
+	rpc.attr.id = IB_GSI_PORT_COUNTERS_EXT;
+
+	memset(rcvbuf, 0, IB_MAD_SIZE);
+
+	/* Same for attribute IDs */
+	mad_set_field(rcvbuf, 0, IB_PC_EXT_PORT_SELECT_F, port);
+	mad_set_field(rcvbuf, 0, IB_PC_EXT_COUNTER_SELECT_F, mask);
+	rpc.attr.mod = 0;
+	rpc.timeout = timeout;
+	rpc.datasz = IB_PC_DATA_SZ;
+	rpc.dataoffs = IB_PC_DATA_OFFS;
+	if (!dest->qp)
+		dest->qp = 1;
+	if (!dest->qkey)
+		dest->qkey = IB_DEFAULT_QP1_QKEY;
+
+	return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf);
 }
 
 static void clear_port(ib_portid_t * portid, uint16_t cap_mask,
 		       char *node_name, int port)
 {
-	uint8_t pc[1024];
+	uint8_t pc[1024] = { 0 };
 	/* bits defined in Table 228 PortCounters CounterSelect and
 	 * CounterSelect2
 	 */
 	uint32_t mask = 0;
 
-	if (!clear_errors && !clear_counts)
-		return;
-
 	if (clear_errors) {
 		mask |= 0xFFF;
-		if (cap_mask & 0x1000)
+		if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
 			mask |= 0x10000;
 	}
 	if (clear_counts)
 		mask |= 0xF000;
 
-	if (!performance_reset_via(pc, portid, port, mask, ibd_timeout,
-				   IB_GSI_PORT_COUNTERS, ibmad_port))
-		IBERROR("Failed to reset errors %s port %d", node_name, port);
+	if (mask)
+		if (!performance_reset_via(pc, portid, port, mask, ibd_timeout,
+					   IB_GSI_PORT_COUNTERS, ibmad_port))
+			IBERROR("Failed to reset errors %s port %d", node_name,
+				port);
 
-	if (details && clear_errors) {
+	if (clear_errors && details) {
+		memset(pc, 0, 1024);
 		performance_reset_via(pc, portid, port, 0xf, ibd_timeout,
 				      IB_GSI_PORT_XMIT_DISCARD_DETAILS,
 				      ibmad_port);
+		memset(pc, 0, 1024);
 		performance_reset_via(pc, portid, port, 0x3f, ibd_timeout,
 				      IB_GSI_PORT_RCV_ERROR_DETAILS,
 				      ibmad_port);
 	}
+
+	if (clear_counts &&
+	    (cap_mask &
+	     (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP))) {
+		if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
+			mask = 0xFF;
+		else
+			mask = 0x0F;
+
+		if (!reset_pc_ext(pc, portid, port, mask, ibd_timeout,
+		    ibmad_port))
+			IBERROR("Failed to reset extended data counters %s, "
+				"%s port %d", node_name, portid2str(portid),
+				port);
+	}
 }
 
 void print_node(ibnd_node_t * node, void *user_data)
@@ -425,28 +674,67 @@ void print_node(ibnd_node_t * node, void *user_data)
 
 	node_name = remap_node_name(node_name_map, node->guid, node->nodedesc);
 
-	for (p = startport; p <= node->numports; p++) {
-		if (node->ports[p]) {
-			if (node->type == IB_NODE_SWITCH)
-				ib_portid_set(&portid, node->smalid, 0, 0);
-			else
-				ib_portid_set(&portid, node->ports[p]->base_lid,
+	if (node->type == IB_NODE_SWITCH) {
+		ib_portid_set(&portid, node->smalid, 0, 0);
+		p = 0;
+	} else {
+		for (p = 1; p <= node->numports; p++) {
+			if (node->ports[p]) {
+				ib_portid_set(&portid,
+					      node->ports[p]->base_lid,
 					      0, 0);
+				break;
+			}
+		}
+	}
 
-			if (query_cap_mask(&portid, node_name, p, &cap_mask) <
-			    0)
-				continue;
-
-			if (cap_mask & 0x100)
-				all_port_sup = 1;
+	if ((query_cap_mask(&portid, node_name, p, &cap_mask) == 0) &&
+	    (cap_mask & IB_PM_ALL_PORT_SELECT))
+		all_port_sup = 1;
+
+	if (data_counters_only) {
+		for (p = startport; p <= node->numports; p++) {
+			if (node->ports[p]) {
+				if (node->type == IB_NODE_SWITCH)
+					ib_portid_set(&portid, node->smalid, 0, 0);
+				else
+					ib_portid_set(&portid, node->ports[p]->base_lid,
+						      0, 0);
+
+				print_data_cnts(&portid, cap_mask, node_name, node, p,
+						&header_printed);
+				summary.ports_checked++;
+				if (!all_port_sup)
+					clear_port(&portid, cap_mask, node_name, p);
+			}
+		}
+	} else {
+		if (all_port_sup)
+			if (!print_errors(&portid, cap_mask, node_name, node,
+					  0xFF, &header_printed)) {
+				summary.ports_checked += node->numports;
+				goto clear;
+			}
 
-			print_port(&portid, cap_mask, node_name, node, p,
-				   &header_printed);
-			if (!all_port_sup)
-				clear_port(&portid, cap_mask, node_name, p);
+		for (p = startport; p <= node->numports; p++) {
+			if (node->ports[p]) {
+				if (node->type == IB_NODE_SWITCH)
+					ib_portid_set(&portid, node->smalid, 0, 0);
+				else
+					ib_portid_set(&portid, node->ports[p]->base_lid,
+						      0, 0);
+
+				print_errors(&portid, cap_mask, node_name, node, p,
+					     &header_printed);
+				summary.ports_checked++;
+				if (!all_port_sup)
+					clear_port(&portid, cap_mask, node_name, p);
+			}
 		}
 	}
 
+clear:
+	summary.nodes_checked++;
 	if (all_port_sup)
 		clear_port(&portid, cap_mask, node_name, 0xFF);
 
@@ -512,10 +800,16 @@ static int process_opt(void *context, int ch, char *optarg)
 	case 7:
 		load_cache_file = strdup(optarg);
 		break;
+	case 8:
+		threshold_file = strdup(optarg);
+		break;
+	case 9:
+		data_counters_only = 1;
+		break;
 	case 'G':
 	case 'S':
-		node_guid_str = optarg;
-		node_guid = strtoull(optarg, 0, 0);
+		port_guid_str = optarg;
+		port_guid = strtoull(optarg, 0, 0);
 		break;
 	case 'D':
 		dr_path = strdup(optarg);
@@ -559,20 +853,24 @@ int main(int argc, char **argv)
 		{"suppress-common", 'c', 0, NULL,
 		 "suppress some of the common counters"},
 		{"node-name-map", 1, 1, "<file>", "node name map file"},
-		{"node-guid", 'G', 1, "<node_guid>", "query only <node_guid>"},
-		{"", 'S', 1, "<node_guid>",
+		{"port-guid", 'G', 1, "<port_guid>",
+		 "report the node containing the port specified by <port_guid>"},
+		{"", 'S', 1, "<port_guid>",
 		 "Same as \"-G\" for backward compatibility"},
 		{"Direct", 'D', 1, "<dr_path>",
-		 "query only switch specified by <dr_path>"},
+		 "report the node containing the port specified by <dr_path>"},
 		{"report-port", 'r', 0, NULL,
-		 "report port configuration information"},
+		 "report port link information"},
+		{"threshold-file", 8, 1, NULL,
+		 "specify an alternate threshold file, default: " DEF_THRES_FILE},
 		{"GNDN", 'R', 0, NULL,
 		 "(This option is obsolete and does nothing)"},
-		{"data", 2, 0, NULL, "include the data counters in the output"},
+		{"data", 2, 0, NULL, "include data counters for ports with errors"},
 		{"switch", 3, 0, NULL, "print data for switches only"},
 		{"ca", 4, 0, NULL, "print data for CA's only"},
 		{"router", 5, 0, NULL, "print data for routers only"},
 		{"details", 6, 0, NULL, "include transmit discard details"},
+		{"counters", 9, 0, NULL, "print data counters only"},
 		{"clear-errors", 'k', 0, NULL,
 		 "Clear error counters after read"},
 		{"clear-counts", 'K', 0, NULL,
@@ -619,13 +917,13 @@ int main(int argc, char **argv)
 					       NULL, ibmad_port)) < 0)
 			IBWARN("Failed to resolve %s; attempting full scan",
 			       dr_path);
-	} else if (node_guid_str) {
+	} else if (port_guid_str) {
 		if ((resolved =
-		     ib_resolve_portid_str_via(&portid, node_guid_str,
+		     ib_resolve_portid_str_via(&portid, port_guid_str,
 					       IB_DEST_GUID, ibd_sm_id,
 					       ibmad_port)) < 0)
 			IBWARN("Failed to resolve %s; attempting full scan",
-			       node_guid_str);
+			       port_guid_str);
 	}
 
 	if (load_cache_file) {
@@ -634,11 +932,14 @@ int main(int argc, char **argv)
 			exit(1);
 		}
 	} else {
-		if (resolved >= 0 &&
-		    !(fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port,
+		if (resolved >= 0) {
+			if (!config.max_hops)
+				config.max_hops = 1;
+			if (!(fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port,
 						    &portid, &config)))
-			IBWARN("Single node discover failed;"
-			       " attempting full scan");
+				IBWARN("Single node discover failed;"
+				       " attempting full scan");
+		}
 
 		if (!fabric && !(fabric = ibnd_discover_fabric(ibd_ca,
 							       ibd_ca_port,
@@ -650,34 +951,36 @@ int main(int argc, char **argv)
 		}
 	}
 
-	report_suppressed();
+	set_thresholds(threshold_file);
 
-	if (node_guid_str) {
-		ibnd_node_t *node = ibnd_find_node_guid(fabric, node_guid);
-		if (node)
-			print_node(node, NULL);
+	if (port_guid_str) {
+		ibnd_port_t *port = ibnd_find_port_guid(fabric, port_guid);
+		if (port)
+			print_node(port->node, NULL);
 		else
 			fprintf(stderr, "Failed to find node: %s\n",
-				node_guid_str);
+				port_guid_str);
 	} else if (dr_path) {
-		ibnd_node_t *node = ibnd_find_node_dr(fabric, dr_path);
-		uint8_t ni[IB_SMP_DATA_SIZE];
+		ibnd_port_t *port = ibnd_find_port_dr(fabric, dr_path);
+		uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
 
 		if (!smp_query_via(ni, &portid, IB_ATTR_NODE_INFO, 0,
 				   ibd_timeout, ibmad_port)) {
 			rc = -1;
 			goto destroy_fabric;
 		}
-		mad_decode_field(ni, IB_NODE_GUID_F, &(node_guid));
+		mad_decode_field(ni, IB_NODE_PORT_GUID_F, &(port_guid));
 
-		node = ibnd_find_node_guid(fabric, node_guid);
-		if (node)
-			print_node(node, NULL);
-		else
+		port = ibnd_find_port_guid(fabric, port_guid);
+		if (port) {
+			print_node(port->node, NULL);
+		} else
 			fprintf(stderr, "Failed to find node: %s\n", dr_path);
 	} else
 		ibnd_iter_nodes(fabric, print_node, NULL);
 
+	print_summary();
+
 destroy_fabric:
 	ibnd_destroy_fabric(fabric);
 
diff --git a/trunk/tools/infiniband-diags/src/ibqueryerrors/SOURCES b/trunk/tools/infiniband-diags/src/ibqueryerrors/SOURCES
index 8c529dd..ab323bc 100644
--- a/trunk/tools/infiniband-diags/src/ibqueryerrors/SOURCES
+++ b/trunk/tools/infiniband-diags/src/ibqueryerrors/SOURCES
@@ -22,6 +22,7 @@ TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
 	$(TARGETPATH)\*\complib.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	\
 	$(TARGETPATH)\*\libibnetdisc.lib
diff --git a/trunk/tools/infiniband-diags/src/ibroute.c b/trunk/tools/infiniband-diags/src/ibroute.c
index b765c84..7339218 100644
--- a/trunk/tools/infiniband-diags/src/ibroute.c
+++ b/trunk/tools/infiniband-diags/src/ibroute.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
- * Copyright (c) 2009 Mellanox Technologies LTD.  All rights reserved.
+ * Copyright (c) 2009-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
@@ -130,7 +130,7 @@ int dump_mlid(char *str, int strlen, unsigned mlid, unsigned nports,
 	return i * 2;
 }
 
-uint16_t mft[16][IB_MLIDS_IN_BLOCK];
+uint16_t mft[16][IB_MLIDS_IN_BLOCK] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0}, { 0 }, { 0 } };
 
 char *dump_multicast_tables(ib_portid_t * portid, unsigned startlid,
 			    unsigned endlid)
@@ -303,9 +303,9 @@ int dump_lid(char *str, int strlen, int lid, int valid)
 
 char *dump_unicast_tables(ib_portid_t * portid, int startlid, int endlid)
 {
-	char lft[IB_SMP_DATA_SIZE];
-	char nd[IB_SMP_DATA_SIZE];
-	uint8_t sw[IB_SMP_DATA_SIZE];
+	char lft[IB_SMP_DATA_SIZE] = { 0 };
+	char nd[IB_SMP_DATA_SIZE] = { 0 };
+	uint8_t sw[IB_SMP_DATA_SIZE] = { 0 };
 	char str[200], *s;
 	uint64_t nodeguid;
 	int block, i, e, top;
diff --git a/trunk/tools/infiniband-diags/src/ibroute/SOURCES b/trunk/tools/infiniband-diags/src/ibroute/SOURCES
index 5e7763d..26bf224 100644
--- a/trunk/tools/infiniband-diags/src/ibroute/SOURCES
+++ b/trunk/tools/infiniband-diags/src/ibroute/SOURCES
@@ -21,6 +21,7 @@ TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
 	$(TARGETPATH)\*\complib.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/tools/infiniband-diags/src/ibsendtrap.c b/trunk/tools/infiniband-diags/src/ibsendtrap.c
index 1b91595..618706b 100644
--- a/trunk/tools/infiniband-diags/src/ibsendtrap.c
+++ b/trunk/tools/infiniband-diags/src/ibsendtrap.c
@@ -2,6 +2,7 @@
  * Copyright (c) 2008 Lawrence Livermore National Security
  * Copyright (c) 2008-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
+ * Copyright (c) 2011 Mellanox Technologies LTD.  All rights reserved.
  *
  * Produced at Lawrence Livermore National Laboratory.
  * Written by Ira Weiny <weiny2 at llnl.gov>.
@@ -56,7 +57,7 @@ int error_port = 1;
 static uint16_t get_node_type(ib_portid_t * port)
 {
 	uint16_t node_type = IB_NODE_TYPE_CA;
-	uint8_t data[IB_SMP_DATA_SIZE];
+	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
 
 	if (smp_query_via(data, port, IB_ATTR_NODE_INFO, 0, 0, srcport))
 		node_type = (uint16_t) mad_get_field(data, 0, IB_NODE_TYPE_F);
@@ -65,7 +66,7 @@ static uint16_t get_node_type(ib_portid_t * port)
 
 static uint32_t get_cap_mask(ib_portid_t * port)
 {
-	uint8_t data[IB_SMP_DATA_SIZE];
+	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
 	uint32_t cap_mask = 0;
 
 	if (smp_query_via(data, port, IB_ATTR_PORT_INFO, 0, 0, srcport))
diff --git a/trunk/tools/infiniband-diags/src/ibsendtrap/SOURCES b/trunk/tools/infiniband-diags/src/ibsendtrap/SOURCES
index 6ebf711..51b9ddd 100644
--- a/trunk/tools/infiniband-diags/src/ibsendtrap/SOURCES
+++ b/trunk/tools/infiniband-diags/src/ibsendtrap/SOURCES
@@ -19,6 +19,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/tools/infiniband-diags/src/ibstat.c b/trunk/tools/infiniband-diags/src/ibstat.c
index c44d8c4..92fcd0f 100644
--- a/trunk/tools/infiniband-diags/src/ibstat.c
+++ b/trunk/tools/infiniband-diags/src/ibstat.c
@@ -72,10 +72,9 @@ static void ca_dump(umad_ca_t * ca)
 	printf("\tNumber of ports: %d\n", ca->numports);
 	printf("\tFirmware version: %s\n", ca->fw_ver);
 	printf("\tHardware version: %s\n", ca->hw_ver);
-	printf("\tNode GUID: 0x%016llx\n",
-	       (long long unsigned)ntohll(ca->node_guid));
-	printf("\tSystem image GUID: 0x%016llx\n",
-	       (long long unsigned)ntohll(ca->system_guid));
+	printf("\tNode GUID: 0x%016" PRIx64 "\n", ntohll(ca->node_guid));
+	printf("\tSystem image GUID: 0x%016" PRIx64 "\n",
+	       ntohll(ca->system_guid));
 }
 
 static char *port_state_str[] = {
@@ -115,16 +114,17 @@ static int port_dump(umad_port_t * port, int alone)
 	       (unsigned)port->state <=
 	       4 ? port_state_str[port->state] : "???");
 	printf("%sPhysical state: %s\n", pre,
-	       (unsigned)port->state <=
+	       (unsigned)port->phys_state <=
 	       7 ? port_phy_state_str[port->phys_state] : "???");
 	printf("%sRate: %d\n", pre, port->rate);
 	printf("%sBase lid: %d\n", pre, port->base_lid);
 	printf("%sLMC: %d\n", pre, port->lmc);
 	printf("%sSM lid: %d\n", pre, port->sm_lid);
 	printf("%sCapability mask: 0x%08x\n", pre, ntohl(port->capmask));
-	printf("%sPort GUID: 0x%016llx\n", pre,
-	       (long long unsigned)ntohll(port->port_guid));
+	printf("%sPort GUID: 0x%016" PRIx64 "\n", pre, ntohll(port->port_guid));
+#ifdef HAVE_UMAD_PORT_LINK_LAYER
 	printf("%sLink layer: %s\n", pre, port->link_layer);
+#endif
 	return 0;
 }
 
@@ -182,8 +182,7 @@ static int ports_list(char names[][UMAD_CA_NAME_LEN], int n)
 
 	for (i = 0; i < found; i++)
 		if (guids[i])
-			printf("0x%016llx\n",
-			       (long long unsigned)ntohll(guids[i]));
+			printf("0x%016" PRIx64 "\n", ntohll(guids[i]));
 	return found;
 }
 
diff --git a/trunk/tools/infiniband-diags/src/ibstat/SOURCES b/trunk/tools/infiniband-diags/src/ibstat/SOURCES
index 03c809c..599e656 100644
--- a/trunk/tools/infiniband-diags/src/ibstat/SOURCES
+++ b/trunk/tools/infiniband-diags/src/ibstat/SOURCES
@@ -20,6 +20,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/tools/infiniband-diags/src/ibsysstat/SOURCES b/trunk/tools/infiniband-diags/src/ibsysstat/SOURCES
index d1add5c..f7c92f5 100644
--- a/trunk/tools/infiniband-diags/src/ibsysstat/SOURCES
+++ b/trunk/tools/infiniband-diags/src/ibsysstat/SOURCES
@@ -20,6 +20,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/tools/infiniband-diags/src/ibtracert.c b/trunk/tools/infiniband-diags/src/ibtracert.c
index 80694f2..c9f511b 100644
--- a/trunk/tools/infiniband-diags/src/ibtracert.c
+++ b/trunk/tools/infiniband-diags/src/ibtracert.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  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
@@ -118,9 +119,11 @@ static int get_node(Node * node, Port * port, ib_portid_t * portid)
 	void *pi = port->portinfo, *ni = node->nodeinfo, *nd = node->nodedesc;
 	char *s, *e;
 
+	memset(ni, 0, sizeof(node->nodeinfo));
 	if (!smp_query_via(ni, portid, IB_ATTR_NODE_INFO, 0, timeout, srcport))
 		return -1;
 
+	memset(nd, 0, sizeof(node->nodedesc));
 	if (!smp_query_via(nd, portid, IB_ATTR_NODE_DESC, 0, timeout, srcport))
 		return -1;
 
@@ -131,6 +134,7 @@ static int get_node(Node * node, Port * port, ib_portid_t * portid)
 			*s = ' ';
 	}
 
+	memset(pi, 0, sizeof(port->portinfo));
 	if (!smp_query_via(pi, portid, IB_ATTR_PORT_INFO, 0, timeout, srcport))
 		return -1;
 
@@ -153,6 +157,7 @@ static int switch_lookup(Switch * sw, ib_portid_t * portid, int lid)
 {
 	void *si = sw->switchinfo, *fdb = sw->fdb;
 
+	memset(si, 0, sizeof(sw->switchinfo));
 	if (!smp_query_via(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout,
 			   srcport))
 		return -1;
@@ -163,6 +168,7 @@ static int switch_lookup(Switch * sw, ib_portid_t * portid, int lid)
 	if (lid >= sw->linearcap && lid > sw->linearFDBtop)
 		return -1;
 
+	memset(fdb, 0, sizeof(sw->fdb));
 	if (!smp_query_via(fdb, portid, IB_ATTR_LINEARFORWTBL, lid / 64,
 			   timeout, srcport))
 		return -1;
@@ -382,7 +388,7 @@ static int insert_node(Node * new)
 
 static int get_port(Port * port, int portnum, ib_portid_t * portid)
 {
-	char portinfo[64];
+	char portinfo[64] = { 0 };
 	void *pi = portinfo;
 
 	port->portnum = portnum;
@@ -445,6 +451,7 @@ static int switch_mclookup(Node * node, ib_portid_t * portid, int mlid,
 
 	memset(map, 0, 256);
 
+	memset(si, 0, sizeof(sw.switchinfo));
 	if (!smp_query_via(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout,
 			   srcport))
 		return -1;
@@ -460,6 +467,7 @@ static int switch_mclookup(Node * node, ib_portid_t * portid, int mlid,
 	maxsets = (node->numports + 15) / 16;	/* round up */
 
 	for (set = 0; set < maxsets; set++) {
+		memset(mdb, 0, sizeof(mdb));
 		if (!smp_query_via(mdb, portid, IB_ATTR_MULTICASTFORWTBL,
 				   block | (set << 28), timeout, srcport))
 			return -1;
@@ -685,7 +693,7 @@ free_name:
 
 static int resolve_lid(ib_portid_t * portid, const void *srcport)
 {
-	uint8_t portinfo[64];
+	uint8_t portinfo[64] = { 0 };
 	uint16_t lid;
 
 	if (!smp_query_via(portinfo, portid, IB_ATTR_PORT_INFO, 0, 0, srcport))
@@ -749,7 +757,7 @@ int main(int argc, char **argv)
 		NULL,
 	};
 
-	ibdiag_process_opts(argc, argv, NULL, NULL, opts, process_opt,
+	ibdiag_process_opts(argc, argv, NULL, "D", opts, process_opt,
 			    usage_args, usage_examples);
 
 	f = stdout;
diff --git a/trunk/tools/infiniband-diags/src/ibtracert/SOURCES b/trunk/tools/infiniband-diags/src/ibtracert/SOURCES
index 65f8c0d..63c9982 100644
--- a/trunk/tools/infiniband-diags/src/ibtracert/SOURCES
+++ b/trunk/tools/infiniband-diags/src/ibtracert/SOURCES
@@ -21,6 +21,7 @@ TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
 	$(TARGETPATH)\*\complib.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/tools/infiniband-diags/src/mcm_rereg_test/SOURCES b/trunk/tools/infiniband-diags/src/mcm_rereg_test/SOURCES
index d026c0e..65b2fa5 100644
--- a/trunk/tools/infiniband-diags/src/mcm_rereg_test/SOURCES
+++ b/trunk/tools/infiniband-diags/src/mcm_rereg_test/SOURCES
@@ -19,6 +19,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/tools/infiniband-diags/src/perfquery.c b/trunk/tools/infiniband-diags/src/perfquery.c
index 07a9226..0ea68aa 100644
--- a/trunk/tools/infiniband-diags/src/perfquery.c
+++ b/trunk/tools/infiniband-diags/src/perfquery.c
@@ -2,6 +2,7 @@
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
+ * Copyright (c) 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
@@ -45,6 +46,7 @@
 
 #include <infiniband/umad.h>
 #include <infiniband/mad.h>
+#include <infiniband/iba/ib_types.h>
 
 #include "ibdiag_common.h"
 
@@ -186,7 +188,8 @@ static void aggregate_perfcounters(void)
 	aggregate_32bit(&perf_count.xmtwait, val);
 }
 
-static void output_aggregate_perfcounters(ib_portid_t * portid)
+static void output_aggregate_perfcounters(ib_portid_t * portid,
+					  uint16_t cap_mask)
 {
 	char buf[1024];
 	uint32_t val = ALL_PORTS;
@@ -220,11 +223,11 @@ static void output_aggregate_perfcounters(ib_portid_t * portid)
 
 	mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
 
-	printf("# Port counters: %s port %d\n%s", portid2str(portid), ALL_PORTS,
-	       buf);
+	printf("# Port counters: %s port %d (CapMask: 0x%02X)\n%s",
+	       portid2str(portid), ALL_PORTS, ntohs(cap_mask), buf);
 }
 
-static void aggregate_perfcounters_ext(void)
+static void aggregate_perfcounters_ext(uint16_t cap_mask)
 {
 	uint32_t val;
 	uint64_t val64;
@@ -241,21 +244,27 @@ static void aggregate_perfcounters_ext(void)
 	aggregate_64bit(&perf_count_ext.portxmitpkts, val64);
 	mad_decode_field(pc, IB_PC_EXT_RCV_PKTS_F, &val64);
 	aggregate_64bit(&perf_count_ext.portrcvpkts, val64);
-	mad_decode_field(pc, IB_PC_EXT_XMT_UPKTS_F, &val64);
-	aggregate_64bit(&perf_count_ext.portunicastxmitpkts, val64);
-	mad_decode_field(pc, IB_PC_EXT_RCV_UPKTS_F, &val64);
-	aggregate_64bit(&perf_count_ext.portunicastrcvpkts, val64);
-	mad_decode_field(pc, IB_PC_EXT_XMT_MPKTS_F, &val64);
-	aggregate_64bit(&perf_count_ext.portmulticastxmitpkits, val64);
-	mad_decode_field(pc, IB_PC_EXT_RCV_MPKTS_F, &val64);
-	aggregate_64bit(&perf_count_ext.portmulticastrcvpkts, val64);
+
+	if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) {
+		mad_decode_field(pc, IB_PC_EXT_XMT_UPKTS_F, &val64);
+		aggregate_64bit(&perf_count_ext.portunicastxmitpkts, val64);
+		mad_decode_field(pc, IB_PC_EXT_RCV_UPKTS_F, &val64);
+		aggregate_64bit(&perf_count_ext.portunicastrcvpkts, val64);
+		mad_decode_field(pc, IB_PC_EXT_XMT_MPKTS_F, &val64);
+		aggregate_64bit(&perf_count_ext.portmulticastxmitpkits, val64);
+		mad_decode_field(pc, IB_PC_EXT_RCV_MPKTS_F, &val64);
+		aggregate_64bit(&perf_count_ext.portmulticastrcvpkts, val64);
+	}
 }
 
-static void output_aggregate_perfcounters_ext(ib_portid_t * portid)
+static void output_aggregate_perfcounters_ext(ib_portid_t * portid,
+					      uint16_t cap_mask)
 {
 	char buf[1024];
 	uint32_t val = ALL_PORTS;
 
+	memset(buf, 0, 1024);
+
 	/* set port_select to 255 to emulate AllPortSelect */
 	mad_encode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);
 	mad_encode_field(pc, IB_PC_EXT_COUNTER_SELECT_F,
@@ -267,19 +276,22 @@ static void output_aggregate_perfcounters_ext(ib_portid_t * portid)
 	mad_encode_field(pc, IB_PC_EXT_XMT_PKTS_F,
 			 &perf_count_ext.portxmitpkts);
 	mad_encode_field(pc, IB_PC_EXT_RCV_PKTS_F, &perf_count_ext.portrcvpkts);
-	mad_encode_field(pc, IB_PC_EXT_XMT_UPKTS_F,
-			 &perf_count_ext.portunicastxmitpkts);
-	mad_encode_field(pc, IB_PC_EXT_RCV_UPKTS_F,
-			 &perf_count_ext.portunicastrcvpkts);
-	mad_encode_field(pc, IB_PC_EXT_XMT_MPKTS_F,
-			 &perf_count_ext.portmulticastxmitpkits);
-	mad_encode_field(pc, IB_PC_EXT_RCV_MPKTS_F,
-			 &perf_count_ext.portmulticastrcvpkts);
+
+	if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) {
+		mad_encode_field(pc, IB_PC_EXT_XMT_UPKTS_F,
+				 &perf_count_ext.portunicastxmitpkts);
+		mad_encode_field(pc, IB_PC_EXT_RCV_UPKTS_F,
+				 &perf_count_ext.portunicastrcvpkts);
+		mad_encode_field(pc, IB_PC_EXT_XMT_MPKTS_F,
+				 &perf_count_ext.portmulticastxmitpkits);
+		mad_encode_field(pc, IB_PC_EXT_RCV_MPKTS_F,
+				 &perf_count_ext.portmulticastrcvpkts);
+	}
 
 	mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc);
 
-	printf("# Port extended counters: %s port %d\n%s", portid2str(portid),
-	       ALL_PORTS, buf);
+	printf("# Port extended counters: %s port %d (CapMask: 0x%02X)\n%s",
+	       portid2str(portid), ALL_PORTS, ntohs(cap_mask), buf);
 }
 
 static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask,
@@ -288,10 +300,11 @@ static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask,
 	char buf[1024];
 
 	if (extended != 1) {
+		memset(pc, 0, sizeof(pc));
 		if (!pma_query_via(pc, portid, port, timeout,
 				   IB_GSI_PORT_COUNTERS, srcport))
 			IBERROR("perfquery");
-		if (!(cap_mask & 0x1000)) {
+		if (!(cap_mask & IB_PM_PC_XMIT_WAIT_SUP)) {
 			/* if PortCounters:PortXmitWait not supported clear this counter */
 			VERBOSE("PortXmitWait not indicated"
 				" so ignore this counter");
@@ -304,19 +317,24 @@ static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask,
 		else
 			mad_dump_fields(buf, sizeof buf, pc, sizeof pc,
 							IB_PC_FIRST_F,
-							(cap_mask & 0x1000)?IB_PC_LAST_F:(IB_PC_RCV_PKTS_F+1));
+							(cap_mask & IB_PM_PC_XMIT_WAIT_SUP)?IB_PC_LAST_F:(IB_PC_RCV_PKTS_F+1));
 
 	} else {
-		if (!(cap_mask & 0x200))	/* 1.2 errata: bit 9 is extended counter support */
+		/* 1.2 errata: bit 9 is extended counter support
+		 * bit 10 is extended counter NoIETF
+		 */
+		if (!(cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) &&
+		    !(cap_mask & IB_PM_EXT_WIDTH_NOIETF_SUP))
 			IBWARN
-			    ("PerfMgt ClassPortInfo 0x%x extended counters not indicated\n",
-			     cap_mask);
+			    ("PerfMgt ClassPortInfo 0x%x; No extended counter support indicated\n",
+			     ntohs(cap_mask));
 
+		memset(pc, 0, sizeof(pc));
 		if (!pma_query_via(pc, portid, port, timeout,
 				   IB_GSI_PORT_COUNTERS_EXT, srcport))
 			IBERROR("perfextquery");
 		if (aggregate)
-			aggregate_perfcounters_ext();
+			aggregate_perfcounters_ext(cap_mask);
 		else
 			mad_dump_perfcounters_ext(buf, sizeof buf, pc,
 						  sizeof pc);
@@ -324,17 +342,20 @@ static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask,
 
 	if (!aggregate) {
 		if (extended)
-			printf("# Port extended counters: %s port %d\n%s",
-			       portid2str(portid), port, buf);
+			printf("# Port extended counters: %s port %d "
+			       "(CapMask: 0x%02X)\n%s",
+			       portid2str(portid), port, ntohs(cap_mask), buf);
 		else
-			printf("# Port counters: %s port %d\n%s",
-			       portid2str(portid), port, buf);
+			printf("# Port counters: %s port %d "
+			       "(CapMask: 0x%02X)\n%s",
+			       portid2str(portid), port, ntohs(cap_mask), buf);
 	}
 }
 
 static void reset_counters(int extended, int timeout, int mask,
 			   ib_portid_t * portid, int port)
 {
+	memset(pc, 0, sizeof(pc));
 	if (extended != 1) {
 		if (!performance_reset_via(pc, portid, port, mask, timeout,
 					   IB_GSI_PORT_COUNTERS, srcport))
@@ -347,7 +368,9 @@ static void reset_counters(int extended, int timeout, int mask,
 }
 
 static int reset, reset_only, all_ports, loop_ports, port, extended, xmt_sl,
-    rcv_sl, xmt_disc, rcv_err, smpl_ctl;
+    rcv_sl, xmt_disc, rcv_err, smpl_ctl, oprcvcounters, flowctlcounters,
+    vloppackets, vlopdata, vlxmitflowctlerrors, vlxmitcounters, swportvlcong,
+    rcvcc, slrcvfecn, slrcvbecn, xmitcc, vlxmittimecc;
 
 static void common_func(ib_portid_t * portid, int port_num, int mask,
 			unsigned query, unsigned reset,
@@ -357,6 +380,7 @@ static void common_func(ib_portid_t * portid, int port_num, int mask,
 	char buf[1024];
 
 	if (query) {
+		memset(pc, 0, sizeof(pc));
 		if (!pma_query_via(pc, portid, port_num, ibd_timeout, attr,
 				   srcport))
 			IBERROR("cannot query %s", name);
@@ -367,6 +391,7 @@ static void common_func(ib_portid_t * portid, int port_num, int mask,
 		       portid2str(portid), port_num, buf);
 	}
 
+	memset(pc, 0, sizeof(pc));
 	if (reset && !performance_reset_via(pc, portid, port, mask, ibd_timeout,
 					    attr, srcport))
 		IBERROR("cannot reset %s", name);
@@ -400,10 +425,95 @@ static void rcv_err_query(ib_portid_t * portid, int port, int mask)
 		    mad_dump_perfcounters_rcv_err);
 }
 
+static void oprcvcounters_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortOpRcvCounters", IB_GSI_PORT_PORT_OP_RCV_COUNTERS,
+		    mad_dump_perfcounters_port_op_rcv_counters);
+}
+
+static void flowctlcounters_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortFlowCtlCounters", IB_GSI_PORT_PORT_FLOW_CTL_COUNTERS,
+		    mad_dump_perfcounters_port_flow_ctl_counters);
+}
+
+static void vloppackets_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortVLOpPackets", IB_GSI_PORT_PORT_VL_OP_PACKETS,
+		    mad_dump_perfcounters_port_vl_op_packet);
+}
+
+static void vlopdata_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortVLOpData", IB_GSI_PORT_PORT_VL_OP_DATA,
+		    mad_dump_perfcounters_port_vl_op_data);
+}
+
+static void vlxmitflowctlerrors_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortVLXmitFlowCtlUpdateErrors", IB_GSI_PORT_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS,
+		    mad_dump_perfcounters_port_vl_xmit_flow_ctl_update_errors);
+}
+
+static void vlxmitcounters_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortVLXmitWaitCounters", IB_GSI_PORT_PORT_VL_XMIT_WAIT_COUNTERS,
+		    mad_dump_perfcounters_port_vl_xmit_wait_counters);
+}
+
+static void swportvlcong_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "SwPortVLCongestion", IB_GSI_SW_PORT_VL_CONGESTION,
+		    mad_dump_perfcounters_sw_port_vl_congestion);
+}
+
+static void rcvcc_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortRcvConCtrl", IB_GSI_PORT_RCV_CON_CTRL,
+		    mad_dump_perfcounters_rcv_con_ctrl);
+}
+
+static void slrcvfecn_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortSLRcvFECN", IB_GSI_PORT_SL_RCV_FECN,
+		    mad_dump_perfcounters_sl_rcv_fecn);
+}
+
+static void slrcvbecn_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortSLRcvBECN", IB_GSI_PORT_SL_RCV_BECN,
+		    mad_dump_perfcounters_sl_rcv_becn);
+}
+
+static void xmitcc_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortXmitConCtrl", IB_GSI_PORT_XMIT_CON_CTRL,
+		    mad_dump_perfcounters_xmit_con_ctrl);
+}
+
+static void vlxmittimecc_query(ib_portid_t * portid, int port, int mask)
+{
+	common_func(portid, port, mask, !reset_only, (reset_only || reset),
+		    "PortVLXmitTimeCong", IB_GSI_PORT_VL_XMIT_TIME_CONG,
+		    mad_dump_perfcounters_vl_xmit_time_cong);
+}
+
 void dump_portsamples_control(ib_portid_t * portid, int port)
 {
 	char buf[1024];
 
+	memset(pc, 0, sizeof(pc));
 	if (!pma_query_via(pc, portid, port, ibd_timeout,
 			   IB_GSI_PORT_SAMPLES_CONTROL, srcport))
 		IBERROR("sampctlquery");
@@ -434,6 +544,42 @@ static int process_opt(void *context, int ch, char *optarg)
 	case 'c':
 		smpl_ctl = 1;
 		break;
+	case 1:
+		oprcvcounters = 1;
+		break;
+	case 2:
+		flowctlcounters = 1;
+		break;
+	case 3:
+		vloppackets = 1;
+		break;
+	case 4:
+		vlopdata = 1;
+		break;
+	case 5:
+		vlxmitflowctlerrors = 1;
+		break;
+	case 6:
+		vlxmitcounters = 1;
+		break;
+	case 7:
+		swportvlcong = 1;
+		break;
+	case 8:
+		rcvcc = 1;
+		break;
+	case 9:
+		slrcvfecn = 1;
+		break;
+	case 10:
+		slrcvbecn = 1;
+		break;
+	case 11:
+		xmitcc = 1;
+		break;
+	case 12:
+		vlxmittimecc = 1;
+		break;
 	case 'a':
 		all_ports++;
 		port = ALL_PORTS;
@@ -463,7 +609,7 @@ int main(int argc, char **argv)
 	uint16_t cap_mask;
 	int all_ports_loop = 0;
 	int node_type, num_ports = 0;
-	uint8_t data[IB_SMP_DATA_SIZE];
+	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
 	int start_port = 1;
 	int enhancedport0;
 	int i;
@@ -474,6 +620,18 @@ int main(int argc, char **argv)
 		{"rcvsl", 'S', 0, NULL, "show Rcv SL port counters"},
 		{"xmtdisc", 'D', 0, NULL, "show Xmt Discard Details"},
 		{"rcverr", 'E', 0, NULL, "show Rcv Error Details"},
+		{"oprcvcounters", 1, 0, NULL, "show Rcv Counters per Op code"},
+		{"flowctlcounters", 2, 0, NULL, "show flow control counters"},
+		{"vloppackets", 3, 0, NULL, "show packets received per Op code per VL"},
+		{"vlopdata", 4, 0, NULL, "show data received per Op code per VL"},
+		{"vlxmitflowctlerrors", 5, 0, NULL, "show flow control update errors per VL"},
+		{"vlxmitcounters", 6, 0, NULL, "show ticks waiting to transmit counters per VL"},
+		{"swportvlcong", 7, 0, NULL, "show sw port VL congestion"},
+		{"rcvcc", 8, 0, NULL, "show Rcv congestion control counters"},
+		{"slrcvfecn", 9, 0, NULL, "show SL Rcv FECN counters"},
+		{"slrcvbecn", 10, 0, NULL, "show SL Rcv BECN counters"},
+		{"xmitcc", 11, 0, NULL, "show Xmit congestion control counters"},
+		{"vlxmittimecc", 12, 0, NULL, "show VL Xmit Time congestion control counters"},
 		{"smplctl", 'c', 0, NULL, "show samples control"},
 		{"all_ports", 'a', 0, NULL, "show aggregated counters"},
 		{"loop_ports", 'l', 0, NULL, "iterate through each port"},
@@ -522,13 +680,13 @@ int main(int argc, char **argv)
 	}
 
 	/* PerfMgt ClassPortInfo is a required attribute */
+	memset(pc, 0, sizeof(pc));
 	if (!pma_query_via(pc, &portid, port, ibd_timeout, CLASS_PORT_INFO,
 			   srcport))
 		IBERROR("classportinfo query");
 	/* ClassPortInfo should be supported as part of libibmad */
 	memcpy(&cap_mask, pc + 2, sizeof(cap_mask));	/* CapabilityMask */
-	cap_mask = ntohs(cap_mask);
-	if (!(cap_mask & 0x100)) {	/* bit 8 is AllPortSelect */
+	if (!(cap_mask & IB_PM_ALL_PORT_SELECT)) {	/* bit 8 is AllPortSelect */
 		if (!all_ports && port == ALL_PORTS)
 			IBERROR("AllPortSelect not supported");
 		if (all_ports)
@@ -555,11 +713,72 @@ int main(int argc, char **argv)
 		goto done;
 	}
 
+	if (oprcvcounters) {
+		oprcvcounters_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (flowctlcounters) {
+		flowctlcounters_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (vloppackets) {
+		vloppackets_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (vlopdata) {
+		vlopdata_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (vlxmitflowctlerrors) {
+		vlxmitflowctlerrors_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (vlxmitcounters) {
+		vlxmitcounters_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (swportvlcong) {
+		swportvlcong_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (rcvcc) {
+		rcvcc_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (slrcvfecn) {
+		slrcvfecn_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (slrcvbecn) {
+		slrcvbecn_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (xmitcc) {
+		xmitcc_query(&portid, port, mask);
+		goto done;
+	}
+
+	if (vlxmittimecc) {
+		vlxmittimecc_query(&portid, port, mask);
+		goto done;
+	}
+
 	if (smpl_ctl) {
 		dump_portsamples_control(&portid, port);
 		goto done;
 	}
 
+
 	if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
 		if (smp_query_via(data, &portid, IB_ATTR_NODE_INFO, 0, 0,
 				  srcport) < 0)
@@ -593,9 +812,11 @@ int main(int argc, char **argv)
 						       && !loop_ports));
 		if (all_ports_loop && !loop_ports) {
 			if (extended != 1)
-				output_aggregate_perfcounters(&portid);
+				output_aggregate_perfcounters(&portid,
+							      cap_mask);
 			else
-				output_aggregate_perfcounters_ext(&portid);
+				output_aggregate_perfcounters_ext(&portid,
+								  cap_mask);
 		}
 	} else
 		dump_perfcounters(extended, ibd_timeout, cap_mask, &portid,
@@ -605,7 +826,7 @@ int main(int argc, char **argv)
 		goto done;
 
 do_reset:
-	if (argc <= 2 && !extended && (cap_mask & 0x1000))
+	if (argc <= 2 && !extended && (cap_mask & IB_PM_PC_XMIT_WAIT_SUP))
 		mask |= (1 << 16);	/* reset portxmitwait */
 
 	if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
diff --git a/trunk/tools/infiniband-diags/src/perfquery/SOURCES b/trunk/tools/infiniband-diags/src/perfquery/SOURCES
index 7e0079b..c71dfac 100644
--- a/trunk/tools/infiniband-diags/src/perfquery/SOURCES
+++ b/trunk/tools/infiniband-diags/src/perfquery/SOURCES
@@ -20,6 +20,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/tools/infiniband-diags/src/saquery.c b/trunk/tools/infiniband-diags/src/saquery.c
index 5e9a5ad..f82772f 100644
--- a/trunk/tools/infiniband-diags/src/saquery.c
+++ b/trunk/tools/infiniband-diags/src/saquery.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2006,2007 The Regents of the University of California.
  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
- * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2009 HNR Consulting. All rights reserved.
  *
@@ -48,7 +48,6 @@
 #include <ctype.h>
 #include <string.h>
 #include <errno.h>
-#include <assert.h>
 
 #define _GNU_SOURCE
 #include <getopt.h>
@@ -60,19 +59,6 @@
 
 #include "ibdiag_common.h"
 
-struct bind_handle {
-	int fd, agent;
-	ib_portid_t dport;
-};
-
-struct query_res {
-	int status;
-	unsigned result_cnt;
-	void *p_result_madw;
-};
-
-typedef struct bind_handle *bind_handle_t;
-
 struct query_params {
 	ib_gid_t sgid, dgid, gid, mgid;
 	uint16_t slid, dlid, mlid;
@@ -106,7 +92,6 @@ static uint64_t smkey = 1;
  */
 #define MAX_PORTS (8)
 #define DEFAULT_SA_TIMEOUT_MS (1000)
-static struct query_res result;
 
 enum {
 	ALL,
@@ -124,119 +109,6 @@ int requested_lid_flag = 0;
 uint64_t requested_guid = 0;
 int requested_guid_flag = 0;
 
-#define SA_ERR_UNKNOWN IB_SA_MAD_STATUS_PRIO_SUGGESTED
-
-const char *ib_sa_error_str[] = {
-	"SA_NO_ERROR",
-	"SA_ERR_NO_RESOURCES",
-	"SA_ERR_REQ_INVALID",
-	"SA_ERR_NO_RECORDS",
-	"SA_ERR_TOO_MANY_RECORDS",
-	"SA_ERR_REQ_INVALID_GID",
-	"SA_ERR_REQ_INSUFFICIENT_COMPONENTS",
-	"SA_ERR_REQ_DENIED",
-	"SA_ERR_STATUS_PRIO_SUGGESTED",
-	"SA_ERR_UNKNOWN"
-};
-
-static inline const char *ib_sa_err_str(IN uint8_t status)
-{
-	if (status > SA_ERR_UNKNOWN)
-		status = SA_ERR_UNKNOWN;
-	return (ib_sa_error_str[status]);
-}
-
-static inline void report_err(int status)
-{
-	int st = status & 0xff;
-	char sm_err_str[64] = { 0 };
-	char sa_err_str[64] = { 0 };
-
-	if (st)
-		sprintf(sm_err_str, " SM(%s)", ib_get_err_str(st));
-
-	st = status >> 8;
-	if (st)
-		sprintf(sa_err_str, " SA(%s)", ib_sa_err_str((uint8_t) st));
-
-	fprintf(stderr, "ERROR: Query result returned 0x%04x, %s%s\n",
-		status, sm_err_str, sa_err_str);
-}
-
-static int sa_query(struct bind_handle *h, uint8_t method,
-		    uint16_t attr, uint32_t mod, uint64_t comp_mask,
-		    uint64_t sm_key, void *data)
-{
-	ib_rpc_t rpc;
-	void *umad, *mad;
-	int ret, offset, len = 256;
-
-	memset(&rpc, 0, sizeof(rpc));
-	rpc.mgtclass = IB_SA_CLASS;
-	rpc.method = method;
-	rpc.attr.id = attr;
-	rpc.attr.mod = mod;
-	rpc.mask = comp_mask;
-	rpc.datasz = IB_SA_DATA_SIZE;
-	rpc.dataoffs = IB_SA_DATA_OFFS;
-
-	umad = calloc(1, len + umad_size());
-	if (!umad)
-		IBPANIC("cannot alloc mem for umad: %s\n", strerror(errno));
-
-	mad_build_pkt(umad, &rpc, &h->dport, NULL, data);
-
-	mad_set_field64(umad_get_mad(umad), 0, IB_SA_MKEY_F, sm_key);
-
-	if (ibdebug > 1)
-		xdump(stdout, "SA Request:\n", umad_get_mad(umad), len);
-
-	ret = umad_send(h->fd, h->agent, umad, len, ibd_timeout, 0);
-	if (ret < 0)
-		IBPANIC("umad_send failed: attr %u: %s\n",
-			attr, strerror(errno));
-
-recv_mad:
-	ret = umad_recv(h->fd, umad, &len, ibd_timeout);
-	if (ret < 0) {
-		if (errno == ENOSPC) {
-			umad = realloc(umad, umad_size() + len);
-			goto recv_mad;
-		}
-		IBPANIC("umad_recv failed: attr 0x%x: %s\n", attr,
-			strerror(errno));
-	}
-
-	if ((ret = umad_status(umad)))
-		return ret;
-
-	mad = umad_get_mad(umad);
-
-	if (ibdebug > 1)
-		xdump(stdout, "SA Response:\n", mad, len);
-
-	method = (uint8_t) mad_get_field(mad, 0, IB_MAD_METHOD_F);
-	offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
-	result.status = mad_get_field(mad, 0, IB_MAD_STATUS_F);
-	result.p_result_madw = mad;
-	if (result.status)
-		result.result_cnt = 0;
-	else if (method != IB_MAD_METHOD_GET_TABLE)
-		result.result_cnt = 1;
-	else if (!offset)
-		result.result_cnt = 0;
-	else
-		result.result_cnt = (len - IB_SA_DATA_OFFS) / (offset << 3);
-
-	return 0;
-}
-
-static void *get_query_rec(void *mad, unsigned i)
-{
-	int offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
-	return (uint8_t *) mad + IB_SA_DATA_OFFS + i * (offset << 3);
-}
-
 static unsigned valid_gid(ib_gid_t * gid)
 {
 	ib_gid_t zero_gid;
@@ -418,7 +290,7 @@ static void dump_portinfo_record(void *data)
 
 static void dump_one_portinfo_record(void *data)
 {
-	char buf[2048], buf2[4096];
+	char buf[2300], buf2[4096];
 	ib_portinfo_record_t *pir = data;
 	ib_port_info_t *pi = &pir->port_info;
 
@@ -428,9 +300,9 @@ static void dump_one_portinfo_record(void *data)
 	       "\tRID:\n"
 	       "\t\tEndPortLid..............%u\n"
 	       "\t\tPortNum.................%u\n"
-	       "\t\tReserved................0x%x\n"
+	       "\t\tOptions.................0x%x\n"
 	       "\tPortInfo dump:\n\t\t%s",
-	       cl_ntoh16(pir->lid), pir->port_num, pir->resv, buf2);
+	       cl_ntoh16(pir->lid), pir->port_num, pir->options, buf2);
 }
 
 static void dump_one_mcmember_record(void *data)
@@ -461,7 +333,7 @@ static void dump_one_mcmember_record(void *data)
 	       inet_ntop(AF_INET6, mr->port_gid.raw, gid, sizeof(gid)),
 	       cl_ntoh32(mr->qkey), cl_ntoh16(mr->mlid), mr->mtu, mr->tclass,
 	       cl_ntoh16(mr->pkey), mr->rate, mr->pkt_life, sl,
-	       cl_ntoh32(flow), hop, scope, join, mr->proxy_join);
+	       flow, hop, scope, join, mr->proxy_join);
 }
 
 static void dump_multicast_group_record(void *data)
@@ -482,11 +354,11 @@ static void dump_multicast_group_record(void *data)
 	       p_mcmr->mtu, cl_ntoh16(p_mcmr->pkey), p_mcmr->rate, sl);
 }
 
-static void dump_multicast_member_record(void *data)
+static void dump_multicast_member_record(ib_member_rec_t *p_mcmr,
+					 struct sa_query_result *nr_result)
 {
 	char gid_str[INET6_ADDRSTRLEN];
 	char gid_str2[INET6_ADDRSTRLEN];
-	ib_member_rec_t *p_mcmr = data;
 	uint16_t mlid = cl_ntoh16(p_mcmr->mlid);
 	unsigned i = 0;
 	char *node_name = "<unknown>";
@@ -495,8 +367,8 @@ static void dump_multicast_member_record(void *data)
 	 * this port gid interface id.
 	 * This gives us a node name to print, if available.
 	 */
-	for (i = 0; i < result.result_cnt; i++) {
-		ib_node_record_t *nr = get_query_rec(result.p_result_madw, i);
+	for (i = 0; i < nr_result->result_cnt; i++) {
+		ib_node_record_t *nr = sa_get_query_rec(nr_result->p_result_madw, i);
 		if (nr->node_info.port_guid ==
 		    p_mcmr->port_gid.unicast.interface_id) {
 			node_name =
@@ -781,6 +653,31 @@ static void dump_one_lft_record(void *data)
 	printf("\n");
 }
 
+static void dump_one_guidinfo_record(void *data)
+{
+	ib_guidinfo_record_t *gir = data;
+	printf("GUIDInfo Record dump:\n"
+	       "\t\tLID........................%u\n"
+	       "\t\tBlock......................%u\n"
+	       "\t\tGUID 0.....................0x%016" PRIx64 "\n"
+	       "\t\tGUID 1.....................0x%016" PRIx64 "\n"
+	       "\t\tGUID 2.....................0x%016" PRIx64 "\n"
+	       "\t\tGUID 3.....................0x%016" PRIx64 "\n"
+	       "\t\tGUID 4.....................0x%016" PRIx64 "\n"
+	       "\t\tGUID 5.....................0x%016" PRIx64 "\n"
+	       "\t\tGUID 6.....................0x%016" PRIx64 "\n"
+	       "\t\tGUID 7.....................0x%016" PRIx64 "\n",
+	       cl_ntoh16(gir->lid), gir->block_num,
+	       cl_ntoh64(gir->guid_info.guid[0]),
+	       cl_ntoh64(gir->guid_info.guid[1]),
+	       cl_ntoh64(gir->guid_info.guid[2]),
+	       cl_ntoh64(gir->guid_info.guid[3]),
+	       cl_ntoh64(gir->guid_info.guid[4]),
+	       cl_ntoh64(gir->guid_info.guid[5]),
+	       cl_ntoh64(gir->guid_info.guid[6]),
+	       cl_ntoh64(gir->guid_info.guid[7]));
+}
+
 static void dump_one_mft_record(void *data)
 {
 	ib_mft_record_t *mftr = data;
@@ -788,53 +685,48 @@ static void dump_one_mft_record(void *data)
 	unsigned block = cl_ntoh16(mftr->position_block_num) &
 	    IB_MCAST_BLOCK_ID_MASK_HO;
 	int i;
+	unsigned offset;
+
 	printf("MFT Record dump:\n"
 	       "\t\tLID........................%u\n"
 	       "\t\tPosition...................%u\n"
 	       "\t\tBlock......................%u\n"
 	       "\t\tMFT:\n\t\tMLID\tPort Mask\n",
 	       cl_ntoh16(mftr->lid), position, block);
+	offset = IB_LID_MCAST_START_HO + block * 32;
 	for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
-		printf("\t\t0x%x\t0x%x\n",
-		       IB_LID_MCAST_START_HO + block * 64 + i,
-		       cl_ntoh16(mftr->mft[i]));
+		printf("\t\t0x%04x\t0x%04x\n",
+		       offset + i, cl_ntoh16(mftr->mft[i]));
 	printf("\n");
 }
 
-static void dump_results(struct query_res *r, void (*dump_func) (void *))
+static void dump_results(struct sa_query_result *r, void (*dump_func) (void *))
 {
 	unsigned i;
 	for (i = 0; i < r->result_cnt; i++) {
-		void *data = get_query_rec(r->p_result_madw, i);
+		void *data = sa_get_query_rec(r->p_result_madw, i);
 		dump_func(data);
 	}
 }
 
-static void return_mad(void)
-{
-	if (result.p_result_madw) {
-		free((uint8_t *) result.p_result_madw - umad_size());
-		result.p_result_madw = NULL;
-	}
-}
-
 /**
  * Get any record(s)
  */
 static int get_any_records(bind_handle_t h,
 			   uint16_t attr_id, uint32_t attr_mod,
-			   ib_net64_t comp_mask, void *attr, uint64_t sm_key)
+			   ib_net64_t comp_mask, void *attr, uint64_t sm_key,
+			   struct sa_query_result *result)
 {
 	int ret = sa_query(h, IB_MAD_METHOD_GET_TABLE, attr_id, attr_mod,
-			   cl_ntoh64(comp_mask), sm_key, attr);
+			   cl_ntoh64(comp_mask), sm_key, attr, result);
 	if (ret) {
 		fprintf(stderr, "Query SA failed: %s\n", ib_get_err_str(ret));
 		return ret;
 	}
 
-	if (result.status != IB_SUCCESS) {
-		report_err(result.status);
-		return result.status;
+	if (result->status != IB_SA_MAD_STATUS_SUCCESS) {
+		sa_report_err(result->status);
+		return EIO;
 	}
 
 	return ret;
@@ -845,33 +737,37 @@ static int get_and_dump_any_records(bind_handle_t h, uint16_t attr_id,
 				    void *attr, uint64_t sm_key,
 				    void (*dump_func) (void *))
 {
+	struct sa_query_result result;
 	int ret = get_any_records(h, attr_id, attr_mod, comp_mask, attr,
-				  sm_key);
+				  sm_key, &result);
 	if (ret)
 		return ret;
 
 	dump_results(&result, dump_func);
-
+	sa_free_result_mad(&result);
 	return 0;
 }
 
 /**
  * Get all the records available for requested query type.
  */
-static int get_all_records(bind_handle_t h, uint16_t attr_id, int trusted)
+static int get_all_records(bind_handle_t h, uint16_t attr_id, int trusted,
+			   struct sa_query_result *result)
 {
-	return get_any_records(h, attr_id, 0, 0, NULL, trusted ? smkey : 0);
+	return get_any_records(h, attr_id, 0, 0, NULL, trusted ? smkey : 0,
+			       result);
 }
 
 static int get_and_dump_all_records(bind_handle_t h, uint16_t attr_id,
 				    int trusted, void (*dump_func) (void *))
 {
-	int ret = get_all_records(h, attr_id, 0);
+	struct sa_query_result result;
+	int ret = get_all_records(h, attr_id, 0, &result);
 	if (ret)
 		return ret;
 
 	dump_results(&result, dump_func);
-	return_mad();
+	sa_free_result_mad(&result);
 	return ret;
 }
 
@@ -884,24 +780,27 @@ static int get_lid_from_name(bind_handle_t h, const char *name, uint16_t * lid)
 	ib_node_info_t *p_ni = NULL;
 	unsigned i;
 	int ret;
+	struct sa_query_result result;
 
-	ret = get_all_records(h, IB_SA_ATTR_NODERECORD, 0);
+	ret = get_all_records(h, IB_SA_ATTR_NODERECORD, 0, &result);
 	if (ret)
 		return ret;
 
+	ret = IB_NOT_FOUND;
 	for (i = 0; i < result.result_cnt; i++) {
-		node_record = get_query_rec(result.p_result_madw, i);
+		node_record = sa_get_query_rec(result.p_result_madw, i);
 		p_ni = &(node_record->node_info);
 		if (name
 		    && strncmp(name, (char *)node_record->node_desc.description,
 			       sizeof(node_record->node_desc.description)) ==
 		    0) {
 			*lid = cl_ntoh16(node_record->lid);
+			ret = IB_SUCCESS;
 			break;
 		}
 	}
-	return_mad();
-	return 0;
+	sa_free_result_mad(&result);
+	return ret;
 }
 
 static uint16_t get_lid(bind_handle_t h, const char *name)
@@ -910,12 +809,22 @@ static uint16_t get_lid(bind_handle_t h, const char *name)
 
 	if (!name)
 		return 0;
-	if (isalpha(name[0]))
-		assert(get_lid_from_name(h, name, &rc_lid) == IB_SUCCESS);
-	else
-		rc_lid = (uint16_t) atoi(name);
-	if (rc_lid == 0)
-		fprintf(stderr, "Failed to find lid for \"%s\"\n", name);
+	if (isalpha(name[0])) {
+		if (get_lid_from_name(h, name, &rc_lid) != IB_SUCCESS) {
+			fprintf(stderr, "Failed to find lid for \"%s\"\n", name);
+			exit(EINVAL);
+		}
+	} else {
+		long val;
+		errno = 0;
+		val = strtol(name, NULL, 0);
+		if (errno != 0 || val <= 0 || val > UINT16_MAX) {
+			fprintf(stderr, "Invalid lid specified: \"%s\"\n", name);
+			exit(EINVAL);
+		}
+		rc_lid = (uint16_t)val;
+	}
+
 	return rc_lid;
 }
 
@@ -959,30 +868,11 @@ static int parse_lid_and_ports(bind_handle_t h,
 	return 0;
 }
 
-#define cl_hton8(x) (x)
-#define CHECK_AND_SET_VAL(val, size, comp_with, target, name, mask) \
-	if ((int##size##_t) val != (int##size##_t) comp_with) { \
-		target = cl_hton##size((uint##size##_t) val); \
-		comp_mask |= IB_##name##_COMPMASK_##mask; \
-	}
-
-#define CHECK_AND_SET_GID(val, target, name, mask) \
-	if (valid_gid(&(val))) { \
-		memcpy(&(target), &(val), sizeof(val)); \
-		comp_mask |= IB_##name##_COMPMASK_##mask; \
-	}
-
-#define CHECK_AND_SET_VAL_AND_SEL(val, target, name, mask, sel) \
-	if (val) { \
-		target = val; \
-		comp_mask |= IB_##name##_COMPMASK_##mask##sel; \
-		comp_mask |= IB_##name##_COMPMASK_##mask; \
-	}
-
 /*
  * Get the portinfo records available with IsSM or IsSMdisabled CapabilityMask bit on.
  */
-static int get_issm_records(bind_handle_t h, ib_net32_t capability_mask)
+static int get_issm_records(bind_handle_t h, ib_net32_t capability_mask,
+			    struct sa_query_result *result)
 {
 	ib_portinfo_record_t attr;
 
@@ -990,15 +880,16 @@ static int get_issm_records(bind_handle_t h, ib_net32_t capability_mask)
 	attr.port_info.capability_mask = capability_mask;
 
 	return get_any_records(h, IB_SA_ATTR_PORTINFORECORD, 1 << 31,
-			       IB_PIR_COMPMASK_CAPMASK, &attr, 0);
+			       IB_PIR_COMPMASK_CAPMASK, &attr, 0, result);
 }
 
 static int print_node_records(bind_handle_t h)
 {
 	unsigned i;
 	int ret;
+	struct sa_query_result result;
 
-	ret = get_all_records(h, IB_SA_ATTR_NODERECORD, 0);
+	ret = get_all_records(h, IB_SA_ATTR_NODERECORD, 0, &result);
 	if (ret)
 		return ret;
 
@@ -1008,7 +899,7 @@ static int print_node_records(bind_handle_t h)
 	}
 	for (i = 0; i < result.result_cnt; i++) {
 		ib_node_record_t *node_record;
-		node_record = get_query_rec(result.p_result_madw, i);
+		node_record = sa_get_query_rec(result.p_result_madw, i);
 		if (node_print_desc == ALL_DESC) {
 			print_node_desc(node_record);
 		} else if (node_print_desc == NAME_OF_LID) {
@@ -1027,31 +918,34 @@ static int print_node_records(bind_handle_t h)
 					    node_desc.description)) == 0)) {
 				print_node_record(node_record);
 				if (node_print_desc == UNIQUE_LID_ONLY) {
-					return_mad();
+					sa_free_result_mad(&result);
 					exit(0);
 				}
 			}
 		}
 	}
-	return_mad();
+	sa_free_result_mad(&result);
 	return ret;
 }
 
 static int get_print_class_port_info(bind_handle_t h)
 {
+	struct sa_query_result result;
 	int ret = sa_query(h, IB_MAD_METHOD_GET, CLASS_PORT_INFO, 0, 0,
-			   0, NULL);
+			   0, NULL, &result);
 	if (ret) {
 		fprintf(stderr, "ERROR: Query SA failed: %s\n",
 			ib_get_err_str(ret));
 		return ret;
 	}
-	if (result.status != IB_SUCCESS) {
-		report_err(result.status);
-		return (result.status);
+	if (result.status != IB_SA_MAD_STATUS_SUCCESS) {
+		sa_report_err(result.status);
+		ret = EIO;
+		goto Exit;
 	}
 	dump_results(&result, dump_class_port_info);
-	return_mad();
+Exit:
+	sa_free_result_mad(&result);
 	return ret;
 }
 
@@ -1089,52 +983,58 @@ static int query_path_records(const struct query_cmd *q, bind_handle_t h,
 					&pr, 0, dump_path_record);
 }
 
-static ib_api_status_t print_issm_records(bind_handle_t h)
+static int print_issm_records(bind_handle_t h)
 {
-	ib_api_status_t status;
+	struct sa_query_result result;
+	int ret = 0;
 
 	/* First, get IsSM records */
-	status = get_issm_records(h, IB_PORT_CAP_IS_SM);
-	if (status != IB_SUCCESS)
-		return (status);
+	ret = get_issm_records(h, IB_PORT_CAP_IS_SM, &result);
+	if (ret != 0)
+		return (ret);
 
 	printf("IsSM ports\n");
 	dump_results(&result, dump_portinfo_record);
-	return_mad();
+	sa_free_result_mad(&result);
 
 	/* Now, get IsSMdisabled records */
-	status = get_issm_records(h, IB_PORT_CAP_SM_DISAB);
-	if (status != IB_SUCCESS)
-		return (status);
+	ret = get_issm_records(h, IB_PORT_CAP_SM_DISAB, &result);
+	if (ret != 0)
+		return (ret);
 
 	printf("\nIsSMdisabled ports\n");
 	dump_results(&result, dump_portinfo_record);
-	return_mad();
+	sa_free_result_mad(&result);
 
-	return (status);
+	return (ret);
 }
 
 static int print_multicast_member_records(bind_handle_t h)
 {
-	struct query_res mc_group_result;
+	struct sa_query_result mc_group_result;
+	struct sa_query_result nr_result;
 	int ret;
+	unsigned i;
 
-	ret = get_all_records(h, IB_SA_ATTR_MCRECORD, 1);
+	ret = get_all_records(h, IB_SA_ATTR_MCRECORD, 1, &mc_group_result);
 	if (ret)
 		return ret;
 
-	mc_group_result = result;
-
-	ret = get_all_records(h, IB_SA_ATTR_NODERECORD, 0);
+	ret = get_all_records(h, IB_SA_ATTR_NODERECORD, 0, &nr_result);
 	if (ret)
 		goto return_mc;
 
-	dump_results(&mc_group_result, dump_multicast_member_record);
-	return_mad();
+	for (i = 0; i < mc_group_result.result_cnt; i++) {
+		ib_member_rec_t *rec = (ib_member_rec_t *)
+				sa_get_query_rec(mc_group_result.p_result_madw,
+					      i);
+		dump_multicast_member_record(rec, &nr_result);
+	}
+
+	sa_free_result_mad(&nr_result);
 
 return_mc:
-	if (mc_group_result.p_result_madw)
-		free((uint8_t *) mc_group_result.p_result_madw - umad_size());
+	sa_free_result_mad(&mc_group_result);
 
 	return ret;
 }
@@ -1337,6 +1237,25 @@ static int query_lft_records(const struct query_cmd *q, bind_handle_t h,
 					&lftr, 0, dump_one_lft_record);
 }
 
+static int query_guidinfo_records(const struct query_cmd *q, bind_handle_t h,
+				  struct query_params *p, int argc, char *argv[])
+{
+	ib_guidinfo_record_t gir;
+	ib_net64_t comp_mask = 0;
+	int lid = 0, block = -1;
+
+	if (argc > 0)
+		parse_lid_and_ports(h, argv[0], &lid, &block, NULL);
+
+	memset(&gir, 0, sizeof(gir));
+	CHECK_AND_SET_VAL(lid, 16, 0, gir.lid, GIR, LID);
+	CHECK_AND_SET_VAL(block, 8, -1, gir.block_num, GIR, BLOCKNUM);
+
+	return get_and_dump_any_records(h, IB_SA_ATTR_GUIDINFORECORD, 0,
+					comp_mask, &gir, 0,
+					dump_one_guidinfo_record);
+}
+
 static int query_mft_records(const struct query_cmd *q, bind_handle_t h,
 			     struct query_params *p, int argc, char *argv[])
 {
@@ -1359,37 +1278,6 @@ static int query_mft_records(const struct query_cmd *q, bind_handle_t h,
 					&mftr, 0, dump_one_mft_record);
 }
 
-static bind_handle_t get_bind_handle(void)
-{
-	static struct ibmad_port *srcport;
-	static struct bind_handle handle;
-	int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
-
-	srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 2);
-	if (!srcport)
-		IBERROR("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
-
-	ib_resolve_smlid_via(&handle.dport, ibd_timeout, srcport);
-	if (!handle.dport.lid)
-		IBPANIC("No SM found.");
-
-	handle.dport.qp = 1;
-	if (!handle.dport.qkey)
-		handle.dport.qkey = IB_DEFAULT_QP1_QKEY;
-
-	handle.fd = mad_rpc_portid(srcport);
-	handle.agent = umad_register(handle.fd, IB_SA_CLASS, 2, 1, NULL);
-
-	return &handle;
-}
-
-static void clean_up(struct bind_handle *h)
-{
-	umad_unregister(h->fd, h->agent);
-	umad_close_port(h->fd);
-	umad_done();
-}
-
 static const struct query_cmd query_cmds[] = {
 	{"ClassPortInfo", "CPI", CLASS_PORT_INFO,
 	 NULL, query_class_port_info},
@@ -1417,6 +1305,8 @@ static const struct query_cmd query_cmds[] = {
 	 "[[lid]/[block]]", query_lft_records},
 	{"MFTRecord", "MFTR", IB_SA_ATTR_MFTRECORD,
 	 "[[mlid]/[position]/[block]]", query_mft_records},
+	{"GUIDInfoRecord", "GIR", IB_SA_ATTR_GUIDINFORECORD,
+	 "[[lid]/[block]]", query_guidinfo_records},
 	{0}
 };
 
@@ -1639,7 +1529,7 @@ int main(int argc, char **argv)
 	bind_handle_t h;
 	struct query_params params;
 	const struct query_cmd *q;
-	ib_api_status_t status;
+	int status;
 	int n;
 
 	const struct ibdiag_opt opts[] = {
@@ -1784,7 +1674,10 @@ int main(int argc, char **argv)
 		ibdiag_show_usage();
 	}
 
-	h = get_bind_handle();
+	h = sa_get_bind_handle();
+	if (!h)
+		IBPANIC("Failed to bind to the SA");
+
 	node_name_map = open_node_name_map(node_name_map_file);
 
 	if (src_lid && *src_lid)
@@ -1821,7 +1714,7 @@ int main(int argc, char **argv)
 
 	if (src_lid)
 		free(src_lid);
-	clean_up(h);
+	sa_free_bind_handle(h);
 	close_node_name_map(node_name_map);
 	return (status);
 }
diff --git a/trunk/tools/infiniband-diags/src/sminfo.c b/trunk/tools/infiniband-diags/src/sminfo.c
index ef13911..b02906f 100644
--- a/trunk/tools/infiniband-diags/src/sminfo.c
+++ b/trunk/tools/infiniband-diags/src/sminfo.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 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
@@ -46,7 +47,7 @@
 
 #include "ibdiag_common.h"
 
-static uint8_t sminfo[1024];
+static uint8_t sminfo[1024] = { 0 };
 
 struct ibmad_port *srcport;
 
diff --git a/trunk/tools/infiniband-diags/src/sminfo/SOURCES b/trunk/tools/infiniband-diags/src/sminfo/SOURCES
index 9596c16..0910bf0 100644
--- a/trunk/tools/infiniband-diags/src/sminfo/SOURCES
+++ b/trunk/tools/infiniband-diags/src/sminfo/SOURCES
@@ -19,6 +19,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/tools/infiniband-diags/src/smpdump/SOURCES b/trunk/tools/infiniband-diags/src/smpdump/SOURCES
index 8e308ce..d8f7d6d 100644
--- a/trunk/tools/infiniband-diags/src/smpdump/SOURCES
+++ b/trunk/tools/infiniband-diags/src/smpdump/SOURCES
@@ -20,6 +20,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/tools/infiniband-diags/src/smpquery.c b/trunk/tools/infiniband-diags/src/smpquery.c
index a1559e8..6753ba9 100644
--- a/trunk/tools/infiniband-diags/src/smpquery.c
+++ b/trunk/tools/infiniband-diags/src/smpquery.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 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
@@ -62,7 +63,7 @@ typedef struct match_rec {
 } match_rec_t;
 
 static op_fn_t node_desc, node_info, port_info, switch_info, pkey_table,
-    sl2vl_table, vlarb_table, guid_info;
+    sl2vl_table, vlarb_table, guid_info, mlnx_ext_port_info;
 
 static const match_rec_t match_tbl[] = {
 	{"NodeInfo", "NI", node_info},
@@ -73,6 +74,7 @@ static const match_rec_t match_tbl[] = {
 	{"SL2VLTable", "SL2VL", sl2vl_table, 1},
 	{"VLArbitration", "VLArb", vlarb_table, 1},
 	{"GUIDInfo", "GI", guid_info},
+	{"MlnxExtPortInfo", "MEPI", mlnx_ext_port_info, 1},
 	{0}
 };
 
@@ -84,8 +86,8 @@ static char *node_desc(ib_portid_t * dest, char **argv, int argc)
 {
 	int node_type, l;
 	uint64_t node_guid;
-	char nd[IB_SMP_DATA_SIZE];
-	uint8_t data[IB_SMP_DATA_SIZE];
+	char nd[IB_SMP_DATA_SIZE] = { 0 };
+	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
 	char dots[128];
 	char *nodename = NULL;
 
@@ -117,7 +119,7 @@ static char *node_desc(ib_portid_t * dest, char **argv, int argc)
 static char *node_info(ib_portid_t * dest, char **argv, int argc)
 {
 	char buf[2048];
-	char data[IB_SMP_DATA_SIZE];
+	char data[IB_SMP_DATA_SIZE] = { 0 };
 
 	if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
 		return "node info query failed";
@@ -130,8 +132,8 @@ static char *node_info(ib_portid_t * dest, char **argv, int argc)
 
 static char *port_info(ib_portid_t * dest, char **argv, int argc)
 {
-	char buf[2048];
-	char data[IB_SMP_DATA_SIZE];
+	char buf[2300];
+	char data[IB_SMP_DATA_SIZE] = { 0 };
 	int portnum = 0;
 
 	if (argc > 0)
@@ -146,10 +148,28 @@ static char *port_info(ib_portid_t * dest, char **argv, int argc)
 	return 0;
 }
 
+static char *mlnx_ext_port_info(ib_portid_t * dest, char **argv, int argc)
+{
+	char buf[2300];
+	char data[IB_SMP_DATA_SIZE];
+	int portnum = 0;
+
+	if (argc > 0)
+		portnum = strtol(argv[0], 0, 0);
+
+	if (!smp_query_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO, portnum, 0, srcport))
+		return "Mellanox ext port info query failed";
+
+	mad_dump_mlnx_ext_port_info(buf, sizeof buf, data, sizeof data);
+
+	printf("# MLNX ext Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
+	return 0;
+}
+
 static char *switch_info(ib_portid_t * dest, char **argv, int argc)
 {
 	char buf[2048];
-	char data[IB_SMP_DATA_SIZE];
+	char data[IB_SMP_DATA_SIZE] = { 0 };
 
 	if (!smp_query_via(data, dest, IB_ATTR_SWITCH_INFO, 0, 0, srcport))
 		return "switch info query failed";
@@ -162,7 +182,7 @@ static char *switch_info(ib_portid_t * dest, char **argv, int argc)
 
 static char *pkey_table(ib_portid_t * dest, char **argv, int argc)
 {
-	uint8_t data[IB_SMP_DATA_SIZE];
+	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
 	int i, j, k;
 	uint16_t *p;
 	unsigned mod;
@@ -215,7 +235,7 @@ static char *pkey_table(ib_portid_t * dest, char **argv, int argc)
 static char *sl2vl_dump_table_entry(ib_portid_t * dest, int in, int out)
 {
 	char buf[2048];
-	char data[IB_SMP_DATA_SIZE];
+	char data[IB_SMP_DATA_SIZE] = { 0 };
 	int portnum = (in << 8) | out;
 
 	if (!smp_query_via(data, dest, IB_ATTR_SLVL_TABLE, portnum, 0, srcport))
@@ -229,7 +249,7 @@ static char *sl2vl_dump_table_entry(ib_portid_t * dest, int in, int out)
 
 static char *sl2vl_table(ib_portid_t * dest, char **argv, int argc)
 {
-	uint8_t data[IB_SMP_DATA_SIZE];
+	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
 	int type, num_ports, portnum = 0;
 	int i;
 	char *ret;
@@ -266,7 +286,7 @@ static char *vlarb_dump_table_entry(ib_portid_t * dest, int portnum, int offset,
 				    unsigned cap)
 {
 	char buf[2048];
-	char data[IB_SMP_DATA_SIZE];
+	char data[IB_SMP_DATA_SIZE] = { 0 };
 
 	if (!smp_query_via(data, dest, IB_ATTR_VL_ARBITRATION,
 			   (offset << 16) | portnum, 0, srcport))
@@ -292,7 +312,7 @@ static char *vlarb_dump_table(ib_portid_t * dest, int portnum,
 
 static char *vlarb_table(ib_portid_t * dest, char **argv, int argc)
 {
-	uint8_t data[IB_SMP_DATA_SIZE];
+	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
 	int portnum = 0;
 	int type, enhsp0, lowcap, highcap;
 	char *ret = 0;
@@ -308,6 +328,7 @@ static char *vlarb_table(ib_portid_t * dest, char **argv, int argc)
 
 		mad_decode_field(data, IB_NODE_TYPE_F, &type);
 		if (type == IB_NODE_SWITCH) {
+			memset(data, 0, sizeof(data));
 			if (!smp_query_via(data, dest, IB_ATTR_SWITCH_INFO, 0,
 					   0, srcport))
 				return "switch info query failed";
@@ -318,6 +339,7 @@ static char *vlarb_table(ib_portid_t * dest, char **argv, int argc)
 				     portid2str(dest), 0);
 				return 0;
 			}
+			memset(data, 0, sizeof(data));
 		}
 	}
 
@@ -341,7 +363,7 @@ static char *vlarb_table(ib_portid_t * dest, char **argv, int argc)
 
 static char *guid_info(ib_portid_t * dest, char **argv, int argc)
 {
-	uint8_t data[IB_SMP_DATA_SIZE];
+	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
 	int i, j, k;
 	uint64_t *p;
 	unsigned mod;
diff --git a/trunk/tools/infiniband-diags/src/smpquery/SOURCES b/trunk/tools/infiniband-diags/src/smpquery/SOURCES
index a6ecae4..b276a21 100644
--- a/trunk/tools/infiniband-diags/src/smpquery/SOURCES
+++ b/trunk/tools/infiniband-diags/src/smpquery/SOURCES
@@ -21,6 +21,7 @@ TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
 	$(TARGETPATH)\*\complib.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib
 
diff --git a/trunk/tools/infiniband-diags/src/vendstat.c b/trunk/tools/infiniband-diags/src/vendstat.c
index 92a90c8..8dbd1ee 100644
--- a/trunk/tools/infiniband-diags/src/vendstat.c
+++ b/trunk/tools/infiniband-diags/src/vendstat.c
@@ -375,6 +375,7 @@ int main(int argc, char **argv)
 	gi = (is3_general_info_t *) & buf;
 	if (do_vendor(&portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_GET,
 		      IB_MLX_IS3_GENERAL_INFO, 0, gi))
+		IBERROR("generalinfo query");
 
 	if (general_info) {
 		/* dump IS3 or IS4 general info here */
diff --git a/trunk/tools/infiniband-diags/src/vendstat/SOURCES b/trunk/tools/infiniband-diags/src/vendstat/SOURCES
index 06fd5f4..450502b 100644
--- a/trunk/tools/infiniband-diags/src/vendstat/SOURCES
+++ b/trunk/tools/infiniband-diags/src/vendstat/SOURCES
@@ -20,6 +20,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 TARGETLIBS = \
 	$(SDK_LIB_PATH)\kernel32.lib	\
 	$(SDK_LIB_PATH)\ws2_32.lib		\
+	$(TARGETPATH)\*\ibal.lib		\
 	$(TARGETPATH)\*\libibmad.lib	\
 	$(TARGETPATH)\*\libibumad.lib	
 
diff --git a/trunk/ulp/libibmad/include/infiniband/mad.h b/trunk/ulp/libibmad/include/infiniband/mad.h
index 7571a61..6d65a29 100644
--- a/trunk/ulp/libibmad/include/infiniband/mad.h
+++ b/trunk/ulp/libibmad/include/infiniband/mad.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
- * Copyright (c) 2009 Mellanox Technologies LTD.  All rights reserved.
+ * Copyright (c) 2009-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
@@ -46,6 +46,9 @@
 #endif				/* __cplusplus */
 
 BEGIN_C_DECLS
+#define IB_MAD_RPC_VERSION_MASK	0x0f00
+#define IB_MAD_RPC_VERSION1	(1<<8)
+
 #define IB_SUBNET_PATH_HOPS_MAX	64
 #define IB_DEFAULT_SUBN_PREFIX	0xfe80000000000000ULL
 #define IB_DEFAULT_QP1_QKEY	0x80010000
@@ -62,6 +65,7 @@ BEGIN_C_DECLS
 #define IB_PC_DATA_SZ		(IB_MAD_SIZE - IB_PC_DATA_OFFS)
 #define IB_SA_MCM_RECSZ		53
 #define IB_SA_PR_RECSZ		64
+#define IB_SA_GIR_RECSZ		72
 #define IB_BM_DATA_OFFS		64
 #define IB_BM_DATA_SZ		(IB_MAD_SIZE - IB_BM_DATA_OFFS)
 #define IB_BM_BKEY_OFFS		24
@@ -137,7 +141,9 @@ enum SMI_ATTR_ID {
 	IB_ATTR_VENDORMADSTBL = 0x1d,
 	IB_ATTR_SMINFO = 0x20,
 
-	IB_ATTR_LAST
+	IB_ATTR_LAST,
+
+	IB_ATTR_MLNX_EXT_PORT_INFO = 0xff90,
 };
 
 enum SA_ATTR_ID {
@@ -170,7 +176,20 @@ enum GSI_ATTR_ID {
 	IB_GSI_PORT_COUNTERS = 0x12,
 	IB_GSI_PORT_RCV_ERROR_DETAILS = 0x15,
 	IB_GSI_PORT_XMIT_DISCARD_DETAILS = 0x16,
+	IB_GSI_PORT_PORT_OP_RCV_COUNTERS = 0x17,
+	IB_GSI_PORT_PORT_FLOW_CTL_COUNTERS = 0x18,
+	IB_GSI_PORT_PORT_VL_OP_PACKETS = 0x19,
+	IB_GSI_PORT_PORT_VL_OP_DATA = 0x1A,
+	IB_GSI_PORT_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS = 0x1B,
+	IB_GSI_PORT_PORT_VL_XMIT_WAIT_COUNTERS = 0x1C,
 	IB_GSI_PORT_COUNTERS_EXT = 0x1D,
+	IB_GSI_PORT_EXT_SPEEDS_COUNTERS = 0x1F,
+	IB_GSI_SW_PORT_VL_CONGESTION = 0x30,
+	IB_GSI_PORT_RCV_CON_CTRL = 0x31,
+	IB_GSI_PORT_SL_RCV_FECN = 0x32,
+	IB_GSI_PORT_SL_RCV_BECN = 0x33,
+	IB_GSI_PORT_XMIT_CON_CTRL = 0x34,
+	IB_GSI_PORT_VL_XMIT_TIME_CONG = 0x35,
 	IB_GSI_PORT_XMIT_DATA_SL = 0x36,
 	IB_GSI_PORT_RCV_DATA_SL = 0x37,
 	IB_GSI_ATTR_LAST
@@ -234,6 +253,22 @@ typedef struct {
 	uint32_t oui;		/* for vendor range 2 mads */
 } ib_rpc_t;
 
+typedef struct {
+	int mgtclass;
+	int method;
+	ib_attr_t attr;
+	uint32_t rstatus;	/* return status */
+	int dataoffs;
+	int datasz;
+	uint64_t mkey;
+	uint64_t trid;		/* used for out mad if nonzero, return real val */
+	uint64_t mask;		/* for sa mads */
+	unsigned recsz;		/* for sa mads (attribute offset) */
+	int timeout;
+	uint32_t oui;		/* for vendor range 2 mads */
+	int error;		/* errno */
+} ib_rpc_v1_t;
+
 typedef struct portid {
 	int lid;		/* lid or 0 if directed route */
 	ib_dr_path_t drpath;
@@ -579,7 +614,8 @@ enum MAD_FIELDS {
 	/*
 	 * GUIDInfo fields
 	 */
-	IB_GUID_GUID0_F,
+	IB_GUID_GUID0_F, /* Obsolete, kept for compatibility
+			    Use IB_GI_GUID0_F going forward */
 
 	/*
 	 * ClassPortInfo fields
@@ -706,6 +742,301 @@ enum MAD_FIELDS {
 	IB_PSC_SAMPLES_ONLY_OPT_MASK_F,
 	IB_PSC_LAST_F,
 
+	/*
+	 * GUIDInfo fields
+	 */
+	IB_GI_GUID0_F, /* a duplicate of IB_GUID_GUID0_F for backwards
+			  compatibility */
+	IB_GI_GUID1_F,
+	IB_GI_GUID2_F,
+	IB_GI_GUID3_F,
+	IB_GI_GUID4_F,
+	IB_GI_GUID5_F,
+	IB_GI_GUID6_F,
+	IB_GI_GUID7_F,
+
+	/*
+	 * GUID Info Record
+	 */
+	IB_SA_GIR_LID_F,
+	IB_SA_GIR_BLOCKNUM_F,
+	IB_SA_GIR_GUID0_F,
+	IB_SA_GIR_GUID1_F,
+	IB_SA_GIR_GUID2_F,
+	IB_SA_GIR_GUID3_F,
+	IB_SA_GIR_GUID4_F,
+	IB_SA_GIR_GUID5_F,
+	IB_SA_GIR_GUID6_F,
+	IB_SA_GIR_GUID7_F,
+
+	/*
+	 * More PortInfo fields
+	 */
+	IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
+	IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
+	IB_PORT_LINK_SPEED_EXT_ENABLED_F,
+	IB_PORT_LINK_SPEED_EXT_LAST_F,
+
+	/*
+	 * PortExtendedSpeedsCounters fields
+	 */
+	IB_PESC_PORT_SELECT_F,
+	IB_PESC_COUNTER_SELECT_F,
+	IB_PESC_SYNC_HDR_ERR_CTR_F,
+	IB_PESC_UNK_BLOCK_CTR_F,
+	IB_PESC_ERR_DET_CTR_LANE0_F,
+	IB_PESC_ERR_DET_CTR_LANE1_F,
+	IB_PESC_ERR_DET_CTR_LANE2_F,
+	IB_PESC_ERR_DET_CTR_LANE3_F,
+	IB_PESC_ERR_DET_CTR_LANE4_F,
+	IB_PESC_ERR_DET_CTR_LANE5_F,
+	IB_PESC_ERR_DET_CTR_LANE6_F,
+	IB_PESC_ERR_DET_CTR_LANE7_F,
+	IB_PESC_ERR_DET_CTR_LANE8_F,
+	IB_PESC_ERR_DET_CTR_LANE9_F,
+	IB_PESC_ERR_DET_CTR_LANE10_F,
+	IB_PESC_ERR_DET_CTR_LANE11_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE0_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE1_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE2_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE3_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE4_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE5_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE6_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE7_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE8_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE9_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE10_F,
+	IB_PESC_FEC_CORR_BLOCK_CTR_LANE11_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE0_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE1_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE2_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE3_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE4_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE5_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE6_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE7_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE8_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE9_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE10_F,
+	IB_PESC_FEC_UNCORR_BLOCK_CTR_LANE11_F,
+	IB_PESC_LAST_F,
+
+	/*
+	 * PortOpRcvCounters fields
+	 */
+	IB_PC_PORT_OP_RCV_COUNTERS_FIRST_F,
+	IB_PC_PORT_OP_RCV_PKTS_F = IB_PC_PORT_OP_RCV_COUNTERS_FIRST_F,
+	IB_PC_PORT_OP_RCV_DATA_F,
+	IB_PC_PORT_OP_RCV_COUNTERS_LAST_F,
+
+	/*
+	 * PortFlowCtlCounters fields
+	 */
+	IB_PC_PORT_FLOW_CTL_COUNTERS_FIRST_F,
+	IB_PC_PORT_XMIT_FLOW_PKTS_F = IB_PC_PORT_FLOW_CTL_COUNTERS_FIRST_F,
+	IB_PC_PORT_RCV_FLOW_PKTS_F,
+	IB_PC_PORT_FLOW_CTL_COUNTERS_LAST_F,
+
+	/*
+	 * PortVLOpPackets fields
+	 */
+	IB_PC_PORT_VL_OP_PACKETS_FIRST_F,
+	IB_PC_PORT_VL_OP_PACKETS0_F = IB_PC_PORT_VL_OP_PACKETS_FIRST_F,
+	IB_PC_PORT_VL_OP_PACKETS1_F,
+	IB_PC_PORT_VL_OP_PACKETS2_F,
+	IB_PC_PORT_VL_OP_PACKETS3_F,
+	IB_PC_PORT_VL_OP_PACKETS4_F,
+	IB_PC_PORT_VL_OP_PACKETS5_F,
+	IB_PC_PORT_VL_OP_PACKETS6_F,
+	IB_PC_PORT_VL_OP_PACKETS7_F,
+	IB_PC_PORT_VL_OP_PACKETS8_F,
+	IB_PC_PORT_VL_OP_PACKETS9_F,
+	IB_PC_PORT_VL_OP_PACKETS10_F,
+	IB_PC_PORT_VL_OP_PACKETS11_F,
+	IB_PC_PORT_VL_OP_PACKETS12_F,
+	IB_PC_PORT_VL_OP_PACKETS13_F,
+	IB_PC_PORT_VL_OP_PACKETS14_F,
+	IB_PC_PORT_VL_OP_PACKETS15_F,
+	IB_PC_PORT_VL_OP_PACKETS_LAST_F,
+
+	/*
+	 * PortVLOpData fields
+	 */
+	IB_PC_PORT_VL_OP_DATA_FIRST_F,
+	IB_PC_PORT_VL_OP_DATA0_F = IB_PC_PORT_VL_OP_DATA_FIRST_F,
+	IB_PC_PORT_VL_OP_DATA1_F,
+	IB_PC_PORT_VL_OP_DATA2_F,
+	IB_PC_PORT_VL_OP_DATA3_F,
+	IB_PC_PORT_VL_OP_DATA4_F,
+	IB_PC_PORT_VL_OP_DATA5_F,
+	IB_PC_PORT_VL_OP_DATA6_F,
+	IB_PC_PORT_VL_OP_DATA7_F,
+	IB_PC_PORT_VL_OP_DATA8_F,
+	IB_PC_PORT_VL_OP_DATA9_F,
+	IB_PC_PORT_VL_OP_DATA10_F,
+	IB_PC_PORT_VL_OP_DATA11_F,
+	IB_PC_PORT_VL_OP_DATA12_F,
+	IB_PC_PORT_VL_OP_DATA13_F,
+	IB_PC_PORT_VL_OP_DATA14_F,
+	IB_PC_PORT_VL_OP_DATA15_F,
+	IB_PC_PORT_VL_OP_DATA_LAST_F,
+
+	/*
+	 * PortVLXmitFlowCtlUpdateErrors fields
+	 */
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS_FIRST_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS0_F = IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS_FIRST_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS1_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS2_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS3_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS4_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS5_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS6_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS7_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS8_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS9_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS10_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS11_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS12_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS13_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS14_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS15_F,
+	IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS_LAST_F,
+
+	/*
+	 * PortVLXmitWaitCounters fields
+	 */
+	IB_PC_PORT_VL_XMIT_WAIT_COUNTERS_FIRST_F,
+	IB_PC_PORT_VL_XMIT_WAIT0_F = IB_PC_PORT_VL_XMIT_WAIT_COUNTERS_FIRST_F,
+	IB_PC_PORT_VL_XMIT_WAIT1_F,
+	IB_PC_PORT_VL_XMIT_WAIT2_F,
+	IB_PC_PORT_VL_XMIT_WAIT3_F,
+	IB_PC_PORT_VL_XMIT_WAIT4_F,
+	IB_PC_PORT_VL_XMIT_WAIT5_F,
+	IB_PC_PORT_VL_XMIT_WAIT6_F,
+	IB_PC_PORT_VL_XMIT_WAIT7_F,
+	IB_PC_PORT_VL_XMIT_WAIT8_F,
+	IB_PC_PORT_VL_XMIT_WAIT9_F,
+	IB_PC_PORT_VL_XMIT_WAIT10_F,
+	IB_PC_PORT_VL_XMIT_WAIT11_F,
+	IB_PC_PORT_VL_XMIT_WAIT12_F,
+	IB_PC_PORT_VL_XMIT_WAIT13_F,
+	IB_PC_PORT_VL_XMIT_WAIT14_F,
+	IB_PC_PORT_VL_XMIT_WAIT15_F,
+	IB_PC_PORT_VL_XMIT_WAIT_COUNTERS_LAST_F,
+
+	/*
+	 * SwPortVLCongestion fields
+	 */
+	IB_PC_SW_PORT_VL_CONGESTION_FIRST_F,
+	IB_PC_SW_PORT_VL_CONGESTION0_F = IB_PC_SW_PORT_VL_CONGESTION_FIRST_F,
+	IB_PC_SW_PORT_VL_CONGESTION1_F,
+	IB_PC_SW_PORT_VL_CONGESTION2_F,
+	IB_PC_SW_PORT_VL_CONGESTION3_F,
+	IB_PC_SW_PORT_VL_CONGESTION4_F,
+	IB_PC_SW_PORT_VL_CONGESTION5_F,
+	IB_PC_SW_PORT_VL_CONGESTION6_F,
+	IB_PC_SW_PORT_VL_CONGESTION7_F,
+	IB_PC_SW_PORT_VL_CONGESTION8_F,
+	IB_PC_SW_PORT_VL_CONGESTION9_F,
+	IB_PC_SW_PORT_VL_CONGESTION10_F,
+	IB_PC_SW_PORT_VL_CONGESTION11_F,
+	IB_PC_SW_PORT_VL_CONGESTION12_F,
+	IB_PC_SW_PORT_VL_CONGESTION13_F,
+	IB_PC_SW_PORT_VL_CONGESTION14_F,
+	IB_PC_SW_PORT_VL_CONGESTION15_F,
+	IB_PC_SW_PORT_VL_CONGESTION_LAST_F,
+
+	/*
+	 * PortRcvConCtrl fields
+	 */
+	IB_PC_RCV_CON_CTRL_FIRST_F,
+	IB_PC_RCV_CON_CTRL_PKT_RCV_FECN_F = IB_PC_RCV_CON_CTRL_FIRST_F,
+	IB_PC_RCV_CON_CTRL_PKT_RCV_BECN_F,
+	IB_PC_RCV_CON_CTRL_LAST_F,
+
+	/*
+	 * PortSLRcvFECN fields
+	 */
+	IB_PC_SL_RCV_FECN_FIRST_F,
+	IB_PC_SL_RCV_FECN0_F = IB_PC_SL_RCV_FECN_FIRST_F,
+	IB_PC_SL_RCV_FECN1_F,
+	IB_PC_SL_RCV_FECN2_F,
+	IB_PC_SL_RCV_FECN3_F,
+	IB_PC_SL_RCV_FECN4_F,
+	IB_PC_SL_RCV_FECN5_F,
+	IB_PC_SL_RCV_FECN6_F,
+	IB_PC_SL_RCV_FECN7_F,
+	IB_PC_SL_RCV_FECN8_F,
+	IB_PC_SL_RCV_FECN9_F,
+	IB_PC_SL_RCV_FECN10_F,
+	IB_PC_SL_RCV_FECN11_F,
+	IB_PC_SL_RCV_FECN12_F,
+	IB_PC_SL_RCV_FECN13_F,
+	IB_PC_SL_RCV_FECN14_F,
+	IB_PC_SL_RCV_FECN15_F,
+	IB_PC_SL_RCV_FECN_LAST_F,
+
+	/*
+	 * PortSLRcvBECN fields
+	 */
+	IB_PC_SL_RCV_BECN_FIRST_F,
+	IB_PC_SL_RCV_BECN0_F = IB_PC_SL_RCV_BECN_FIRST_F,
+	IB_PC_SL_RCV_BECN1_F,
+	IB_PC_SL_RCV_BECN2_F,
+	IB_PC_SL_RCV_BECN3_F,
+	IB_PC_SL_RCV_BECN4_F,
+	IB_PC_SL_RCV_BECN5_F,
+	IB_PC_SL_RCV_BECN6_F,
+	IB_PC_SL_RCV_BECN7_F,
+	IB_PC_SL_RCV_BECN8_F,
+	IB_PC_SL_RCV_BECN9_F,
+	IB_PC_SL_RCV_BECN10_F,
+	IB_PC_SL_RCV_BECN11_F,
+	IB_PC_SL_RCV_BECN12_F,
+	IB_PC_SL_RCV_BECN13_F,
+	IB_PC_SL_RCV_BECN14_F,
+	IB_PC_SL_RCV_BECN15_F,
+	IB_PC_SL_RCV_BECN_LAST_F,
+
+	/*
+	 * PortXmitConCtrl fields
+	 */
+	IB_PC_XMIT_CON_CTRL_FIRST_F,
+	IB_PC_XMIT_CON_CTRL_TIME_CONG_F = IB_PC_XMIT_CON_CTRL_FIRST_F,
+	IB_PC_XMIT_CON_CTRL_LAST_F,
+
+	/*
+	 * PortVLXmitTimeCong fields
+	 */
+	IB_PC_VL_XMIT_TIME_CONG_FIRST_F,
+	IB_PC_VL_XMIT_TIME_CONG0_F = IB_PC_VL_XMIT_TIME_CONG_FIRST_F,
+	IB_PC_VL_XMIT_TIME_CONG1_F,
+	IB_PC_VL_XMIT_TIME_CONG2_F,
+	IB_PC_VL_XMIT_TIME_CONG3_F,
+	IB_PC_VL_XMIT_TIME_CONG4_F,
+	IB_PC_VL_XMIT_TIME_CONG5_F,
+	IB_PC_VL_XMIT_TIME_CONG6_F,
+	IB_PC_VL_XMIT_TIME_CONG7_F,
+	IB_PC_VL_XMIT_TIME_CONG8_F,
+	IB_PC_VL_XMIT_TIME_CONG9_F,
+	IB_PC_VL_XMIT_TIME_CONG10_F,
+	IB_PC_VL_XMIT_TIME_CONG11_F,
+	IB_PC_VL_XMIT_TIME_CONG12_F,
+	IB_PC_VL_XMIT_TIME_CONG13_F,
+	IB_PC_VL_XMIT_TIME_CONG14_F,
+	IB_PC_VL_XMIT_TIME_CONG_LAST_F,
+
+	/*
+	 * Mellanox ExtendedPortInfo fields
+	 */
+	IB_MLNX_EXT_PORT_STATE_CHG_ENABLE_F,
+	IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
+	IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
+	IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
+	IB_MLNX_EXT_PORT_LAST_F,
+
 	IB_FIELD_LAST_		/* must be last */
 };
 
@@ -959,6 +1290,14 @@ MAD_EXPORT uint8_t *smp_query_via(void *buf, ib_portid_t * id, unsigned attrid,
 MAD_EXPORT uint8_t *smp_set_via(void *buf, ib_portid_t * id, unsigned attrid,
 				unsigned mod, unsigned timeout,
 				const struct ibmad_port *srcport);
+MAD_EXPORT uint8_t *smp_query_status_via(void *rcvbuf, ib_portid_t * portid,
+					 unsigned attrid, unsigned mod,
+					 unsigned timeout, int *rstatus,
+					 const struct ibmad_port *srcport);
+MAD_EXPORT uint8_t *smp_set_status_via(void *data, ib_portid_t * portid,
+				       unsigned attrid, unsigned mod,
+				       unsigned timeout, int *rstatus,
+				       const struct ibmad_port *srcport);
 
 /* sa.c */
 uint8_t *sa_call(void *rcvbuf, ib_portid_t * portid, ib_sa_call_t * sa,
@@ -1021,6 +1360,7 @@ MAD_EXPORT ib_mad_dump_fn
     mad_dump_linkwidth, mad_dump_linkwidthsup, mad_dump_linkwidthen,
     mad_dump_linkdowndefstate,
     mad_dump_linkspeed, mad_dump_linkspeedsup, mad_dump_linkspeeden,
+    mad_dump_linkspeedext, mad_dump_linkspeedextsup, mad_dump_linkspeedexten,
     mad_dump_portstate, mad_dump_portstates,
     mad_dump_physportstate, mad_dump_portcapmask,
     mad_dump_mtu, mad_dump_vlcap, mad_dump_opervls,
@@ -1029,7 +1369,14 @@ MAD_EXPORT ib_mad_dump_fn
     mad_dump_switchinfo, mad_dump_perfcounters, mad_dump_perfcounters_ext,
     mad_dump_perfcounters_xmt_sl, mad_dump_perfcounters_rcv_sl,
     mad_dump_perfcounters_xmt_disc, mad_dump_perfcounters_rcv_err,
-    mad_dump_portsamples_control;
+    mad_dump_portsamples_control, mad_dump_port_ext_speeds_counters,
+    mad_dump_perfcounters_port_op_rcv_counters, mad_dump_perfcounters_port_flow_ctl_counters,
+    mad_dump_perfcounters_port_vl_op_packet, mad_dump_perfcounters_port_vl_op_data,
+    mad_dump_perfcounters_port_vl_xmit_flow_ctl_update_errors, mad_dump_perfcounters_port_vl_xmit_wait_counters,
+    mad_dump_perfcounters_sw_port_vl_congestion, mad_dump_perfcounters_rcv_con_ctrl,
+    mad_dump_perfcounters_sl_rcv_fecn, mad_dump_perfcounters_sl_rcv_becn,
+    mad_dump_perfcounters_xmit_con_ctrl, mad_dump_perfcounters_vl_xmit_time_cong,
+    mad_dump_mlnx_ext_port_info;
 
 MAD_EXPORT void mad_dump_fields(char *buf, int bufsz, void *val, int valsz,
 				int start, int end);
diff --git a/trunk/ulp/libibmad/include/infiniband/mad_osd.h b/trunk/ulp/libibmad/include/infiniband/mad_osd.h
index faabaec..c32e666 100644
--- a/trunk/ulp/libibmad/include/infiniband/mad_osd.h
+++ b/trunk/ulp/libibmad/include/infiniband/mad_osd.h
@@ -35,6 +35,7 @@
 #include <windows.h>
 #include <winsock2.h>
 #include <ws2tcpip.h>
+#include <_errno.h>
 
 typedef unsigned __int8		uint8_t;
 typedef unsigned __int16	uint16_t;
diff --git a/trunk/ulp/libibmad/src/dump.c b/trunk/ulp/libibmad/src/dump.c
index c29f625..29fb742 100644
--- a/trunk/ulp/libibmad/src/dump.c
+++ b/trunk/ulp/libibmad/src/dump.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
- * Copyright (c) 2009 Mellanox Technologies LTD.  All rights reserved.
+ * Copyright (c) 2009-2011 Mellanox Technologies LTD.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -308,6 +308,70 @@ void mad_dump_linkspeeden(char *buf, int bufsz, void *val, int valsz)
 	dump_linkspeed(buf, bufsz, speed);
 }
 
+void mad_dump_linkspeedext(char *buf, int bufsz, void *val, int valsz)
+{
+	int speed = *(int *)val;
+
+	switch (speed) {
+	case 0:
+		snprintf(buf, bufsz, "No Extended Speed");
+		break;
+	case 1:
+		snprintf(buf, bufsz, "14.0625 Gbps");
+		break;
+	case 2:
+		snprintf(buf, bufsz, "25.78125 Gbps");
+		break;
+	default:
+		snprintf(buf, bufsz, "undefined (%d)", speed);
+		break;
+	}
+}
+
+static void dump_linkspeedext(char *buf, int bufsz, int speed)
+{
+	int n = 0;
+
+	if (speed == 0) {
+		sprintf(buf, "%d", speed);
+		return;
+	}
+
+	if (speed & 0x1)
+		n += snprintf(buf + n, bufsz - n, "14.0625 Gbps or ");
+	if (n < bufsz && speed & 0x2)
+		n += snprintf(buf + n, bufsz - n, "25.78125 Gbps or ");
+	if (n >= bufsz) {
+		if (bufsz > 3)
+			buf[n - 4] = '\0';
+		return;
+	}
+
+	if (speed >> 2) {
+		n += snprintf(buf + n, bufsz - n, "undefined (%d)", speed);
+		return;
+	} else if (bufsz > 3)
+		buf[n - 4] = '\0';
+}
+
+void mad_dump_linkspeedextsup(char *buf, int bufsz, void *val, int valsz)
+{
+	int speed = *(int *)val;
+
+	dump_linkspeedext(buf, bufsz, speed);
+}
+
+void mad_dump_linkspeedexten(char *buf, int bufsz, void *val, int valsz)
+{
+	int speed = *(int *)val;
+
+	if (speed == 30) {
+		sprintf(buf, "%s", "Extended link speeds disabled");
+		return;
+	}
+	dump_linkspeedext(buf, bufsz, speed);
+}
+
 void mad_dump_portstate(char *buf, int bufsz, void *val, int valsz)
 {
 	int state = *(int *)val;
@@ -495,6 +559,8 @@ void mad_dump_portcapmask(char *buf, int bufsz, void *val, int valsz)
 	if (mask & (1 << 12))
 		s += sprintf(s,
 			     "\t\t\t\tIsPkeySwitchExternalPortTrapSupported\n");
+	if (mask & (1 << 14))
+		s += sprintf(s, "\t\t\t\tIsExtendedSpeedsSupported\n");
 	if (mask & (1 << 16))
 		s += sprintf(s, "\t\t\t\tIsCommunicatonManagementSupported\n");
 	if (mask & (1 << 17))
@@ -692,7 +758,12 @@ void mad_dump_nodeinfo(char *buf, int bufsz, void *val, int valsz)
 
 void mad_dump_portinfo(char *buf, int bufsz, void *val, int valsz)
 {
-	_dump_fields(buf, bufsz, val, IB_PORT_FIRST_F, IB_PORT_LAST_F);
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PORT_FIRST_F, IB_PORT_LAST_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val,
+		     IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
+		     IB_PORT_LINK_SPEED_EXT_LAST_F);
 }
 
 void mad_dump_portstates(char *buf, int bufsz, void *val, int valsz)
@@ -760,6 +831,138 @@ void mad_dump_portsamples_control(char *buf, int bufsz, void *val, int valsz)
 	_dump_fields(buf, bufsz, val, IB_PSC_OPCODE_F, IB_PSC_LAST_F);
 }
 
+void mad_dump_port_ext_speeds_counters(char *buf, int bufsz, void *val, int valsz)
+{
+	_dump_fields(buf, bufsz, val, IB_PESC_PORT_SELECT_F, IB_PESC_LAST_F);
+}
+
+void mad_dump_perfcounters_port_op_rcv_counters(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_OP_RCV_COUNTERS_FIRST_F,
+		     IB_PC_PORT_OP_RCV_COUNTERS_LAST_F);
+}
+
+void mad_dump_perfcounters_port_flow_ctl_counters(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_FLOW_CTL_COUNTERS_FIRST_F,
+		     IB_PC_PORT_FLOW_CTL_COUNTERS_LAST_F);
+}
+
+void mad_dump_perfcounters_port_vl_op_packet(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_VL_OP_PACKETS_FIRST_F,
+		     IB_PC_PORT_VL_OP_PACKETS_LAST_F);
+}
+
+void mad_dump_perfcounters_port_vl_op_data(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_VL_OP_DATA_FIRST_F,
+		     IB_PC_PORT_VL_OP_DATA_LAST_F);
+}
+
+void mad_dump_perfcounters_port_vl_xmit_flow_ctl_update_errors(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS_FIRST_F,
+		     IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS_LAST_F);
+}
+
+void mad_dump_perfcounters_port_vl_xmit_wait_counters(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_VL_XMIT_WAIT_COUNTERS_FIRST_F,
+		     IB_PC_PORT_VL_XMIT_WAIT_COUNTERS_LAST_F);
+}
+
+void mad_dump_perfcounters_sw_port_vl_congestion(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_SW_PORT_VL_CONGESTION_FIRST_F,
+		     IB_PC_SW_PORT_VL_CONGESTION_LAST_F);
+}
+
+void mad_dump_perfcounters_rcv_con_ctrl(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_RCV_CON_CTRL_FIRST_F,
+		     IB_PC_RCV_CON_CTRL_LAST_F);
+}
+
+
+void mad_dump_perfcounters_sl_rcv_fecn(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_SL_RCV_FECN_FIRST_F,
+		     IB_PC_SL_RCV_FECN_LAST_F);
+}
+
+void mad_dump_perfcounters_sl_rcv_becn(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_SL_RCV_BECN_FIRST_F,
+		     IB_PC_SL_RCV_BECN_LAST_F);
+}
+
+void mad_dump_perfcounters_xmit_con_ctrl(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_XMIT_CON_CTRL_FIRST_F,
+		     IB_PC_XMIT_CON_CTRL_LAST_F);
+}
+
+void mad_dump_perfcounters_vl_xmit_time_cong(char *buf, int bufsz, void *val, int valsz)
+{
+	int cnt;
+
+	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+			   IB_PC_EXT_XMT_BYTES_F);
+	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_VL_XMIT_TIME_CONG_FIRST_F,
+		     IB_PC_VL_XMIT_TIME_CONG_LAST_F);
+}
+
+void mad_dump_mlnx_ext_port_info(char *buf, int bufsz, void *val, int valsz)
+{
+	_dump_fields(buf, bufsz, val, IB_MLNX_EXT_PORT_STATE_CHG_ENABLE_F,
+		     IB_MLNX_EXT_PORT_LAST_F);
+}
+
 void xdump(FILE * file, char *msg, void *p, int size)
 {
 #define HEX(x)  ((x) < 10 ? '0' + (x) : 'a' + ((x) -10))
diff --git a/trunk/ulp/libibmad/src/fields.c b/trunk/ulp/libibmad/src/fields.c
index a5a510a..7e5ac7d 100644
--- a/trunk/ulp/libibmad/src/fields.c
+++ b/trunk/ulp/libibmad/src/fields.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
- * Copyright (c) 2009 Mellanox Technologies LTD.  All rights reserved.
+ * Copyright (c) 2009-2010 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
@@ -246,24 +246,24 @@ static const ib_field_t ib_mad_f[] = {
 	 */
 	{BITSOFFS(8, 8), "PortSelect", mad_dump_uint},
 	{BITSOFFS(16, 16), "CounterSelect", mad_dump_hex},
-	{BITSOFFS(32, 16), "SymbolErrors", mad_dump_uint},
-	{BITSOFFS(48, 8), "LinkRecovers", mad_dump_uint},
-	{BITSOFFS(56, 8), "LinkDowned", mad_dump_uint},
-	{BITSOFFS(64, 16), "RcvErrors", mad_dump_uint},
-	{BITSOFFS(80, 16), "RcvRemotePhysErrors", mad_dump_uint},
-	{BITSOFFS(96, 16), "RcvSwRelayErrors", mad_dump_uint},
-	{BITSOFFS(112, 16), "XmtDiscards", mad_dump_uint},
-	{BITSOFFS(128, 8), "XmtConstraintErrors", mad_dump_uint},
-	{BITSOFFS(136, 8), "RcvConstraintErrors", mad_dump_uint},
+	{BITSOFFS(32, 16), "SymbolErrorCounter", mad_dump_uint},
+	{BITSOFFS(48, 8), "LinkErrorRecoveryCounter", mad_dump_uint},
+	{BITSOFFS(56, 8), "LinkDownedCounter", mad_dump_uint},
+	{BITSOFFS(64, 16), "PortRcvErrors", mad_dump_uint},
+	{BITSOFFS(80, 16), "PortRcvRemotePhysicalErrors", mad_dump_uint},
+	{BITSOFFS(96, 16), "PortRcvSwitchRelayErrors", mad_dump_uint},
+	{BITSOFFS(112, 16), "PortXmitDiscards", mad_dump_uint},
+	{BITSOFFS(128, 8), "PortXmitConstraintErrors", mad_dump_uint},
+	{BITSOFFS(136, 8), "PortRcvConstraintErrors", mad_dump_uint},
 	{BITSOFFS(144, 8), "CounterSelect2", mad_dump_hex},
-	{BITSOFFS(152, 4), "LinkIntegrityErrors", mad_dump_uint},
-	{BITSOFFS(156, 4), "ExcBufOverrunErrors", mad_dump_uint},
+	{BITSOFFS(152, 4), "LocalLinkIntegrityErrors", mad_dump_uint},
+	{BITSOFFS(156, 4), "ExcessiveBufferOverrunErrors", mad_dump_uint},
 	{BITSOFFS(176, 16), "VL15Dropped", mad_dump_uint},
-	{192, 32, "XmtData", mad_dump_uint},
-	{224, 32, "RcvData", mad_dump_uint},
-	{256, 32, "XmtPkts", mad_dump_uint},
-	{288, 32, "RcvPkts", mad_dump_uint},
-	{320, 32, "XmtWait", mad_dump_uint},
+	{192, 32, "PortXmitData", mad_dump_uint},
+	{224, 32, "PortRcvData", mad_dump_uint},
+	{256, 32, "PortXmitPkts", mad_dump_uint},
+	{288, 32, "PortRcvPkts", mad_dump_uint},
+	{320, 32, "PortXmitWait", mad_dump_uint},
 	{0, 0},			/* IB_PC_LAST_F */
 
 	/*
@@ -452,21 +452,21 @@ static const ib_field_t ib_mad_f[] = {
 	/*
 	 * PortXmitDiscardDetails fields
 	 */
-	{32, 16, "PortInactiveDiscards", mad_dump_uint},
-	{48, 16, "PortNeighborMTUDiscards", mad_dump_uint},
-	{64, 16, "PortSwLifetimeLimitDiscards", mad_dump_uint},
-	{80, 16, "PortSwHOQLifetimeLimitDiscards", mad_dump_uint},
+	{BITSOFFS(32, 16), "PortInactiveDiscards", mad_dump_uint},
+	{BITSOFFS(48, 16), "PortNeighborMTUDiscards", mad_dump_uint},
+	{BITSOFFS(64, 16), "PortSwLifetimeLimitDiscards", mad_dump_uint},
+	{BITSOFFS(80, 16), "PortSwHOQLifetimeLimitDiscards", mad_dump_uint},
 	{0, 0},			/* IB_PC_XMT_DISC_LAST_F */
 
 	/*
 	 * PortRcvErrorDetails fields
 	 */
-	{32, 16, "PortLocalPhysicalErrors", mad_dump_uint},
-	{48, 16, "PortMalformedPktErrors", mad_dump_uint},
-	{64, 16, "PortBufferOverrunErrors", mad_dump_uint},
-	{80, 16, "PortDLIDMappingErrors", mad_dump_uint},
-	{96, 16, "PortVLMappingErrors", mad_dump_uint},
-	{112, 16, "PortLoopingErrors", mad_dump_uint},
+	{BITSOFFS(32, 16), "PortLocalPhysicalErrors", mad_dump_uint},
+	{BITSOFFS(48, 16), "PortMalformedPktErrors", mad_dump_uint},
+	{BITSOFFS(64, 16), "PortBufferOverrunErrors", mad_dump_uint},
+	{BITSOFFS(80, 16), "PortDLIDMappingErrors", mad_dump_uint},
+	{BITSOFFS(96, 16), "PortVLMappingErrors", mad_dump_uint},
+	{BITSOFFS(112, 16), "PortLoopingErrors", mad_dump_uint},
 	{0, 0},                 /* IB_PC_RCV_ERR_LAST_F */
 
 	/*
@@ -485,25 +485,303 @@ static const ib_field_t ib_mad_f[] = {
 	{160, 64, "VendorMask", mad_dump_hex},
 	{224, 32, "SampleStart", mad_dump_uint},
 	{256, 32, "SampleInterval", mad_dump_uint},
-	{288, 16, "Tag", mad_dump_hex},
-	{304, 16, "CounterSelect0", mad_dump_hex},
-	{320, 16, "CounterSelect1", mad_dump_hex},
-	{336, 16, "CounterSelect2", mad_dump_hex},
-	{352, 16, "CounterSelect3", mad_dump_hex},
-	{368, 16, "CounterSelect4", mad_dump_hex},
-	{384, 16, "CounterSelect5", mad_dump_hex},
-	{400, 16, "CounterSelect6", mad_dump_hex},
-	{416, 16, "CounterSelect7", mad_dump_hex},
-	{432, 16, "CounterSelect8", mad_dump_hex},
-	{448, 16, "CounterSelect9", mad_dump_hex},
-	{464, 16, "CounterSelect10", mad_dump_hex},
-	{480, 16, "CounterSelect11", mad_dump_hex},
-	{496, 16, "CounterSelect12", mad_dump_hex},
-	{512, 16, "CounterSelect13", mad_dump_hex},
-	{528, 16, "CounterSelect14", mad_dump_hex},
+	{BITSOFFS(288, 16), "Tag", mad_dump_hex},
+	{BITSOFFS(304, 16), "CounterSelect0", mad_dump_hex},
+	{BITSOFFS(320, 16), "CounterSelect1", mad_dump_hex},
+	{BITSOFFS(336, 16), "CounterSelect2", mad_dump_hex},
+	{BITSOFFS(352, 16), "CounterSelect3", mad_dump_hex},
+	{BITSOFFS(368, 16), "CounterSelect4", mad_dump_hex},
+	{BITSOFFS(384, 16), "CounterSelect5", mad_dump_hex},
+	{BITSOFFS(400, 16), "CounterSelect6", mad_dump_hex},
+	{BITSOFFS(416, 16), "CounterSelect7", mad_dump_hex},
+	{BITSOFFS(432, 16), "CounterSelect8", mad_dump_hex},
+	{BITSOFFS(448, 16), "CounterSelect9", mad_dump_hex},
+	{BITSOFFS(464, 16), "CounterSelect10", mad_dump_hex},
+	{BITSOFFS(480, 16), "CounterSelect11", mad_dump_hex},
+	{BITSOFFS(496, 16), "CounterSelect12", mad_dump_hex},
+	{BITSOFFS(512, 16), "CounterSelect13", mad_dump_hex},
+	{BITSOFFS(528, 16), "CounterSelect14", mad_dump_hex},
 	{576, 64, "SamplesOnlyOptionMask", mad_dump_hex},
 	{0, 0},			/* IB_PSC_LAST_F */
 
+	/* GUIDInfo fields */
+	{0, 64, "GUID0", mad_dump_hex},
+	{64, 64, "GUID1", mad_dump_hex},
+	{128, 64, "GUID2", mad_dump_hex},
+	{192, 64, "GUID3", mad_dump_hex},
+	{256, 64, "GUID4", mad_dump_hex},
+	{320, 64, "GUID5", mad_dump_hex},
+	{384, 64, "GUID6", mad_dump_hex},
+	{448, 64, "GUID7", mad_dump_hex},
+
+	/* GUID Info Record */
+	{BITSOFFS(0, 16), "Lid", mad_dump_uint},
+	{BITSOFFS(16, 8), "BlockNum", mad_dump_uint},
+	{64, 64, "Guid0", mad_dump_hex},
+	{128, 64, "Guid1", mad_dump_hex},
+	{192, 64, "Guid2", mad_dump_hex},
+	{256, 64, "Guid3", mad_dump_hex},
+	{320, 64, "Guid4", mad_dump_hex},
+	{384, 64, "Guid5", mad_dump_hex},
+	{448, 64, "Guid6", mad_dump_hex},
+	{512, 64, "Guid7", mad_dump_hex},
+
+	/*
+	 * More PortInfo fields
+	 */
+	{BITSOFFS(496, 4), "LinkSpeedExtActive", mad_dump_linkspeedext},
+	{BITSOFFS(500, 4), "LinkSpeedExtSupported", mad_dump_linkspeedextsup},
+	{BITSOFFS(507, 5), "LinkSpeedExtEnabled", mad_dump_linkspeedexten},
+	{0, 0},			/* IB_PORT_LINK_SPEED_EXT_LAST_F */
+
+	/*
+	 * PortExtendedSpeedsCounters fields
+	 */
+	{BITSOFFS(8, 8), "PortSelect", mad_dump_uint},
+	{64, 64, "CounterSelect", mad_dump_hex},
+	{BITSOFFS(128, 8), "SyncHeaderErrorCounter", mad_dump_uint},
+	{BITSOFFS(136, 8), "UnknownBlockCounter", mad_dump_uint},
+	{BITSOFFS(144, 8), "ErrorDetectionCounterLane0", mad_dump_uint},
+	{BITSOFFS(152, 8), "ErrorDetectionCounterLane1", mad_dump_uint},
+	{BITSOFFS(160, 8), "ErrorDetectionCounterLane2", mad_dump_uint},
+	{BITSOFFS(168, 8), "ErrorDetectionCounterLane3", mad_dump_uint},
+	{BITSOFFS(176, 8), "ErrorDetectionCounterLane4", mad_dump_uint},
+	{BITSOFFS(184, 8), "ErrorDetectionCounterLane5", mad_dump_uint},
+	{BITSOFFS(192, 8), "ErrorDetectionCounterLane6", mad_dump_uint},
+	{BITSOFFS(200, 8), "ErrorDetectionCounterLane7", mad_dump_uint},
+	{BITSOFFS(208, 8), "ErrorDetectionCounterLane8", mad_dump_uint},
+	{BITSOFFS(216, 8), "ErrorDetectionCounterLane9", mad_dump_uint},
+	{BITSOFFS(224, 8), "ErrorDetectionCounterLane10", mad_dump_uint},
+	{BITSOFFS(232, 8), "ErrorDetectionCounterLane11", mad_dump_uint},
+	{256, 32, "FECCorrectableBlockCtrLane0", mad_dump_uint},
+	{288, 32, "FECCorrectableBlockCtrLane1", mad_dump_uint},
+	{320, 32, "FECCorrectableBlockCtrLane2", mad_dump_uint},
+	{352, 32, "FECCorrectableBlockCtrLane3", mad_dump_uint},
+	{384, 32, "FECCorrectableBlockCtrLane4", mad_dump_uint},
+	{416, 32, "FECCorrectableBlockCtrLane5", mad_dump_uint},
+	{448, 32, "FECCorrectableBlockCtrLane6", mad_dump_uint},
+	{480, 32, "FECCorrectableBlockCtrLane7", mad_dump_uint},
+	{512, 32, "FECCorrectableBlockCtrLane8", mad_dump_uint},
+	{544, 32, "FECCorrectableBlockCtrLane9", mad_dump_uint},
+	{580, 32, "FECCorrectableBlockCtrLane10", mad_dump_uint},
+	{608, 32, "FECCorrectableBlockCtrLane11", mad_dump_uint},
+	{640, 32, "FECUncorrectableBlockCtrLane0", mad_dump_uint},
+	{672, 32, "FECUncorrectableBlockCtrLane1", mad_dump_uint},
+	{704, 32, "FECUncorrectableBlockCtrLane2", mad_dump_uint},
+	{736, 32, "FECUncorrectableBlockCtrLane3", mad_dump_uint},
+	{768, 32, "FECUncorrectableBlockCtrLane4", mad_dump_uint},
+	{800, 32, "FECUncorrectableBlockCtrLane5", mad_dump_uint},
+	{832, 32, "FECUncorrectableBlockCtrLane6", mad_dump_uint},
+	{864, 32, "FECUncorrectableBlockCtrLane7", mad_dump_uint},
+	{896, 32, "FECUncorrectableBlockCtrLane8", mad_dump_uint},
+	{928, 32, "FECUncorrectableBlockCtrLane9", mad_dump_uint},
+	{960, 32, "FECUncorrectableBlockCtrLane10", mad_dump_uint},
+	{992, 32, "FECUncorrectableBlockCtrLane11", mad_dump_uint},
+	{0, 0},			/* IB_PESC_LAST_F */
+
+	/*
+	 * PortOpRcvCounters fields
+	 */
+	{32, 32, "PortOpRcvPkts", mad_dump_uint},
+	{64, 32, "PortOpRcvData", mad_dump_uint},
+	{0, 0},			/* IB_PC_PORT_OP_RCV_COUNTERS_LAST_F */
+
+	/*
+	 * PortFlowCtlCounters fields
+	 */
+	{32, 32, "PortXmitFlowPkts", mad_dump_uint},
+	{64, 32, "PortRcvFlowPkts", mad_dump_uint},
+	{0, 0},			/* IB_PC_PORT_FLOW_CTL_COUNTERS_LAST_F */
+
+	/*
+	 * PortVLOpPackets fields
+	 */
+	{BITSOFFS(32, 16), "PortVLOpPackets0", mad_dump_uint},
+	{BITSOFFS(48, 16), "PortVLOpPackets1", mad_dump_uint},
+	{BITSOFFS(64, 16), "PortVLOpPackets2", mad_dump_uint},
+	{BITSOFFS(80, 16), "PortVLOpPackets3", mad_dump_uint},
+	{BITSOFFS(96, 16), "PortVLOpPackets4", mad_dump_uint},
+	{BITSOFFS(112, 16), "PortVLOpPackets5", mad_dump_uint},
+	{BITSOFFS(128, 16), "PortVLOpPackets6", mad_dump_uint},
+	{BITSOFFS(144, 16), "PortVLOpPackets7", mad_dump_uint},
+	{BITSOFFS(160, 16), "PortVLOpPackets8", mad_dump_uint},
+	{BITSOFFS(176, 16), "PortVLOpPackets9", mad_dump_uint},
+	{BITSOFFS(192, 16), "PortVLOpPackets10", mad_dump_uint},
+	{BITSOFFS(208, 16), "PortVLOpPackets11", mad_dump_uint},
+	{BITSOFFS(224, 16), "PortVLOpPackets12", mad_dump_uint},
+	{BITSOFFS(240, 16), "PortVLOpPackets13", mad_dump_uint},
+	{BITSOFFS(256, 16), "PortVLOpPackets14", mad_dump_uint},
+	{BITSOFFS(272, 16), "PortVLOpPackets15", mad_dump_uint},
+	{0, 0},			/* IB_PC_PORT_VL_OP_PACKETS_LAST_F */
+
+	/*
+	 * PortVLOpData fields
+	 */
+	{32, 32, "PortVLOpData0", mad_dump_uint},
+	{64, 32, "PortVLOpData1", mad_dump_uint},
+	{96, 32, "PortVLOpData2", mad_dump_uint},
+	{128, 32, "PortVLOpData3", mad_dump_uint},
+	{160, 32, "PortVLOpData4", mad_dump_uint},
+	{192, 32, "PortVLOpData5", mad_dump_uint},
+	{224, 32, "PortVLOpData6", mad_dump_uint},
+	{256, 32, "PortVLOpData7", mad_dump_uint},
+	{288, 32, "PortVLOpData8", mad_dump_uint},
+	{320, 32, "PortVLOpData9", mad_dump_uint},
+	{352, 32, "PortVLOpData10", mad_dump_uint},
+	{384, 32, "PortVLOpData11", mad_dump_uint},
+	{416, 32, "PortVLOpData12", mad_dump_uint},
+	{448, 32, "PortVLOpData13", mad_dump_uint},
+	{480, 32, "PortVLOpData14", mad_dump_uint},
+	{512, 32, "PortVLOpData15", mad_dump_uint},
+	{0, 0},			/* IB_PC_PORT_VL_OP_DATA_LAST_F */
+
+	/*
+	 * PortVLXmitFlowCtlUpdateErrors fields
+	 */
+	{BITSOFFS(32, 2), "PortVLXmitFlowCtlUpdateErrors0", mad_dump_uint},
+	{BITSOFFS(34, 2), "PortVLXmitFlowCtlUpdateErrors1", mad_dump_uint},
+	{BITSOFFS(36, 2), "PortVLXmitFlowCtlUpdateErrors2", mad_dump_uint},
+	{BITSOFFS(38, 2), "PortVLXmitFlowCtlUpdateErrors3", mad_dump_uint},
+	{BITSOFFS(40, 2), "PortVLXmitFlowCtlUpdateErrors4", mad_dump_uint},
+	{BITSOFFS(42, 2), "PortVLXmitFlowCtlUpdateErrors5", mad_dump_uint},
+	{BITSOFFS(44, 2), "PortVLXmitFlowCtlUpdateErrors6", mad_dump_uint},
+	{BITSOFFS(46, 2), "PortVLXmitFlowCtlUpdateErrors7", mad_dump_uint},
+	{BITSOFFS(48, 2), "PortVLXmitFlowCtlUpdateErrors8", mad_dump_uint},
+	{BITSOFFS(50, 2), "PortVLXmitFlowCtlUpdateErrors9", mad_dump_uint},
+	{BITSOFFS(52, 2), "PortVLXmitFlowCtlUpdateErrors10", mad_dump_uint},
+	{BITSOFFS(54, 2), "PortVLXmitFlowCtlUpdateErrors11", mad_dump_uint},
+	{BITSOFFS(56, 2), "PortVLXmitFlowCtlUpdateErrors12", mad_dump_uint},
+	{BITSOFFS(58, 2), "PortVLXmitFlowCtlUpdateErrors13", mad_dump_uint},
+	{BITSOFFS(60, 2), "PortVLXmitFlowCtlUpdateErrors14", mad_dump_uint},
+	{BITSOFFS(62, 2), "PortVLXmitFlowCtlUpdateErrors15", mad_dump_uint},
+	{0, 0},			/* IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS_LAST_F */
+
+	/*
+	 * PortVLXmitWaitCounters fields
+	 */
+	{BITSOFFS(32, 16), "PortVLXmitWait0", mad_dump_uint},
+	{BITSOFFS(48, 16), "PortVLXmitWait1", mad_dump_uint},
+	{BITSOFFS(64, 16), "PortVLXmitWait2", mad_dump_uint},
+	{BITSOFFS(80, 16), "PortVLXmitWait3", mad_dump_uint},
+	{BITSOFFS(96, 16), "PortVLXmitWait4", mad_dump_uint},
+	{BITSOFFS(112, 16), "PortVLXmitWait5", mad_dump_uint},
+	{BITSOFFS(128, 16), "PortVLXmitWait6", mad_dump_uint},
+	{BITSOFFS(144, 16), "PortVLXmitWait7", mad_dump_uint},
+	{BITSOFFS(160, 16), "PortVLXmitWait8", mad_dump_uint},
+	{BITSOFFS(176, 16), "PortVLXmitWait9", mad_dump_uint},
+	{BITSOFFS(192, 16), "PortVLXmitWait10", mad_dump_uint},
+	{BITSOFFS(208, 16), "PortVLXmitWait11", mad_dump_uint},
+	{BITSOFFS(224, 16), "PortVLXmitWait12", mad_dump_uint},
+	{BITSOFFS(240, 16), "PortVLXmitWait13", mad_dump_uint},
+	{BITSOFFS(256, 16), "PortVLXmitWait14", mad_dump_uint},
+	{BITSOFFS(272, 16), "PortVLXmitWait15", mad_dump_uint},
+	{0, 0},			/* IB_PC_PORT_VL_XMIT_WAIT_COUNTERS_LAST_F */
+
+	/*
+	 * SwPortVLCongestion fields
+	 */
+	{BITSOFFS(32, 16), "SWPortVLCongestion0", mad_dump_uint},
+	{BITSOFFS(48, 16), "SWPortVLCongestion1", mad_dump_uint},
+	{BITSOFFS(64, 16), "SWPortVLCongestion2", mad_dump_uint},
+	{BITSOFFS(80, 16), "SWPortVLCongestion3", mad_dump_uint},
+	{BITSOFFS(96, 16), "SWPortVLCongestion4", mad_dump_uint},
+	{BITSOFFS(112, 16), "SWPortVLCongestion5", mad_dump_uint},
+	{BITSOFFS(128, 16), "SWPortVLCongestion6", mad_dump_uint},
+	{BITSOFFS(144, 16), "SWPortVLCongestion7", mad_dump_uint},
+	{BITSOFFS(160, 16), "SWPortVLCongestion8", mad_dump_uint},
+	{BITSOFFS(176, 16), "SWPortVLCongestion9", mad_dump_uint},
+	{BITSOFFS(192, 16), "SWPortVLCongestion10", mad_dump_uint},
+	{BITSOFFS(208, 16), "SWPortVLCongestion11", mad_dump_uint},
+	{BITSOFFS(224, 16), "SWPortVLCongestion12", mad_dump_uint},
+	{BITSOFFS(240, 16), "SWPortVLCongestion13", mad_dump_uint},
+	{BITSOFFS(256, 16), "SWPortVLCongestion14", mad_dump_uint},
+	{BITSOFFS(272, 16), "SWPortVLCongestion15", mad_dump_uint},
+	{0, 0},			/* IB_PC_SW_PORT_VL_CONGESTION_LAST_F */
+
+	/*
+	 * PortRcvConCtrl fields
+	 */
+	{32, 32, "PortPktRcvFECN", mad_dump_uint},
+	{64, 32, "PortPktRcvBECN", mad_dump_uint},
+	{0, 0},			/* IB_PC_RCV_CON_CTRL_LAST_F */
+
+	/*
+	 * PortSLRcvFECN fields
+	 */
+	{32, 32, "PortSLRcvFECN0", mad_dump_uint},
+	{64, 32, "PortSLRcvFECN1", mad_dump_uint},
+	{96, 32, "PortSLRcvFECN2", mad_dump_uint},
+	{128, 32, "PortSLRcvFECN3", mad_dump_uint},
+	{160, 32, "PortSLRcvFECN4", mad_dump_uint},
+	{192, 32, "PortSLRcvFECN5", mad_dump_uint},
+	{224, 32, "PortSLRcvFECN6", mad_dump_uint},
+	{256, 32, "PortSLRcvFECN7", mad_dump_uint},
+	{288, 32, "PortSLRcvFECN8", mad_dump_uint},
+	{320, 32, "PortSLRcvFECN9", mad_dump_uint},
+	{352, 32, "PortSLRcvFECN10", mad_dump_uint},
+	{384, 32, "PortSLRcvFECN11", mad_dump_uint},
+	{416, 32, "PortSLRcvFECN12", mad_dump_uint},
+	{448, 32, "PortSLRcvFECN13", mad_dump_uint},
+	{480, 32, "PortSLRcvFECN14", mad_dump_uint},
+	{512, 32, "PortSLRcvFECN15", mad_dump_uint},
+	{0, 0},			/* IB_PC_SL_RCV_FECN_LAST_F */
+
+	/*
+	 * PortSLRcvBECN fields
+	 */
+	{32, 32, "PortSLRcvBECN0", mad_dump_uint},
+	{64, 32, "PortSLRcvBECN1", mad_dump_uint},
+	{96, 32, "PortSLRcvBECN2", mad_dump_uint},
+	{128, 32, "PortSLRcvBECN3", mad_dump_uint},
+	{160, 32, "PortSLRcvBECN4", mad_dump_uint},
+	{192, 32, "PortSLRcvBECN5", mad_dump_uint},
+	{224, 32, "PortSLRcvBECN6", mad_dump_uint},
+	{256, 32, "PortSLRcvBECN7", mad_dump_uint},
+	{288, 32, "PortSLRcvBECN8", mad_dump_uint},
+	{320, 32, "PortSLRcvBECN9", mad_dump_uint},
+	{352, 32, "PortSLRcvBECN10", mad_dump_uint},
+	{384, 32, "PortSLRcvBECN11", mad_dump_uint},
+	{416, 32, "PortSLRcvBECN12", mad_dump_uint},
+	{448, 32, "PortSLRcvBECN13", mad_dump_uint},
+	{480, 32, "PortSLRcvBECN14", mad_dump_uint},
+	{512, 32, "PortSLRcvBECN15", mad_dump_uint},
+	{0, 0},			/* IB_PC_SL_RCV_BECN_LAST_F */
+
+	/*
+	 * PortXmitConCtrl fields
+	 */
+	{32, 32, "PortXmitTimeCong", mad_dump_uint},
+	{0, 0},			/* IB_PC_XMIT_CON_CTRL_LAST_F */
+
+	/*
+	 * PortVLXmitTimeCong fields
+	 */
+	{32, 32, "PortVLXmitTimeCong0", mad_dump_uint},
+	{64, 32, "PortVLXmitTimeCong1", mad_dump_uint},
+	{96, 32, "PortVLXmitTimeCong2", mad_dump_uint},
+	{128, 32, "PortVLXmitTimeCong3", mad_dump_uint},
+	{160, 32, "PortVLXmitTimeCong4", mad_dump_uint},
+	{192, 32, "PortVLXmitTimeCong5", mad_dump_uint},
+	{224, 32, "PortVLXmitTimeCong6", mad_dump_uint},
+	{256, 32, "PortVLXmitTimeCong7", mad_dump_uint},
+	{288, 32, "PortVLXmitTimeCong8", mad_dump_uint},
+	{320, 32, "PortVLXmitTimeCong9", mad_dump_uint},
+	{352, 32, "PortVLXmitTimeCong10", mad_dump_uint},
+	{384, 32, "PortVLXmitTimeCong11", mad_dump_uint},
+	{416, 32, "PortVLXmitTimeCong12", mad_dump_uint},
+	{448, 32, "PortVLXmitTimeCong13", mad_dump_uint},
+	{480, 32, "PortVLXmitTimeCong14", mad_dump_uint},
+	{0, 0},			/* IB_PC_VL_XMIT_TIME_CONG_LAST_F */
+
+	/*
+	 * Mellanox ExtendedPortInfo fields
+	 */
+	{BITSOFFS(24, 8), "StateChangeEnable", mad_dump_hex},
+	{BITSOFFS(56, 8), "LinkSpeedSupported", mad_dump_hex},
+	{BITSOFFS(88, 8), "LinkSpeedEnabled", mad_dump_hex},
+	{BITSOFFS(120, 8), "LinkSpeedActive", mad_dump_hex},
+	{0, 0},			/* IB_MLNX_EXT_PORT_LAST_F */
+
 	{0, 0}			/* IB_FIELD_LAST_ */
 
 };
diff --git a/trunk/ulp/libibmad/src/gs.c b/trunk/ulp/libibmad/src/gs.c
index 3cb2b25..5541b6b 100644
--- a/trunk/ulp/libibmad/src/gs.c
+++ b/trunk/ulp/libibmad/src/gs.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 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
@@ -38,6 +39,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #include <infiniband/umad.h>
 #include <infiniband/mad.h>
@@ -49,8 +51,10 @@ uint8_t *pma_query_via(void *rcvbuf, ib_portid_t * dest, int port,
 		       unsigned timeout, unsigned id,
 		       const struct ibmad_port * srcport)
 {
-	ib_rpc_t rpc = { 0 };
+	ib_rpc_v1_t rpc = { 0 };
+	ib_rpc_t *rpcold = (ib_rpc_t *)(void *)&rpc;
 	int lid = dest->lid;
+	void *p_ret;
 
 	DEBUG("lid %u port %d", lid, port);
 
@@ -59,7 +63,7 @@ uint8_t *pma_query_via(void *rcvbuf, ib_portid_t * dest, int port,
 		return NULL;
 	}
 
-	rpc.mgtclass = IB_PERFORMANCE_CLASS;
+	rpc.mgtclass = IB_PERFORMANCE_CLASS | IB_MAD_RPC_VERSION1;
 	rpc.method = IB_MAD_METHOD_GET;
 	rpc.attr.id = id;
 
@@ -75,15 +79,20 @@ uint8_t *pma_query_via(void *rcvbuf, ib_portid_t * dest, int port,
 	if (!dest->qkey)
 		dest->qkey = IB_DEFAULT_QP1_QKEY;
 
-	return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf);
+	p_ret = mad_rpc(srcport, rpcold, dest, rcvbuf, rcvbuf);
+	errno = rpc.error;
+	return p_ret;
 }
 
 uint8_t *performance_reset_via(void *rcvbuf, ib_portid_t * dest,
 			       int port, unsigned mask, unsigned timeout,
 			       unsigned id, const struct ibmad_port * srcport)
 {
-	ib_rpc_t rpc = { 0 };
+	ib_rpc_v1_t rpc = { 0 };
+	ib_rpc_t *rpcold = (ib_rpc_t *)(void *)&rpc;
+
 	int lid = dest->lid;
+	void *p_ret;
 
 	DEBUG("lid %u port %d mask 0x%x", lid, port, mask);
 
@@ -95,7 +104,7 @@ uint8_t *performance_reset_via(void *rcvbuf, ib_portid_t * dest,
 	if (!mask)
 		mask = ~0;
 
-	rpc.mgtclass = IB_PERFORMANCE_CLASS;
+	rpc.mgtclass = IB_PERFORMANCE_CLASS | IB_MAD_RPC_VERSION1;
 	rpc.method = IB_MAD_METHOD_SET;
 	rpc.attr.id = id;
 
@@ -115,5 +124,7 @@ uint8_t *performance_reset_via(void *rcvbuf, ib_portid_t * dest,
 	if (!dest->qkey)
 		dest->qkey = IB_DEFAULT_QP1_QKEY;
 
-	return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf);
+	p_ret = mad_rpc(srcport, rpcold, dest, rcvbuf, rcvbuf);
+	errno = rpc.error;
+	return p_ret;
 }
diff --git a/trunk/ulp/libibmad/src/ibmad_exports.src b/trunk/ulp/libibmad/src/ibmad_exports.src
index d0f9480..c0d3489 100644
--- a/trunk/ulp/libibmad/src/ibmad_exports.src
+++ b/trunk/ulp/libibmad/src/ibmad_exports.src
@@ -2,42 +2,133 @@ LIBRARY libibmad.dll
 
 #ifndef _WIN64
 EXPORTS
-	mad_set_field;
-	mad_get_field;
-	mad_set_array;
-	mad_get_array;
-	mad_set_field64;
-	mad_get_field64;
-	mad_decode_field;
-	mad_encode_field;
-	mad_encode;
-	mad_trid;
-	mad_build_pkt;
-	mad_register_port_client;
-	mad_register_client;
-	mad_register_server;
-	mad_class_agent;
-	mad_send;
-	mad_receive;
-	mad_respond;
-	mad_alloc;
-	mad_free;
-	madrpc_portid;
-	madrpc_init;
-	madrpc_set_retries;
-	madrpc_set_timeout;
-	madrpc_show_errors;
-	smp_query;
-	smp_set;
-	smp_query_via;
-	ib_vendor_call;
-	ib_path_query;
-	ib_resolve_smlid;
-	ib_resolve_portid_str;
-	ib_resolve_self;
-	portid2str;
-	portid2portnum;
-	str2drpath;
-	drpath2str;
-	xdump
+		xdump;
+		mad_dump_field;
+		mad_dump_val;
+		mad_print_field;
+		mad_dump_array;
+		mad_dump_bitfield;
+		mad_dump_hex;
+		mad_dump_int;
+		mad_dump_linkdowndefstate;
+		mad_dump_linkspeed;
+		mad_dump_linkspeeden;
+		mad_dump_linkspeedsup;
+		mad_dump_linkspeedext;
+		mad_dump_linkspeedexten;
+		mad_dump_linkspeedextsup;
+		mad_dump_linkwidth;
+		mad_dump_linkwidthen;
+		mad_dump_linkwidthsup;
+		mad_dump_mlnx_ext_port_info;
+		mad_dump_mtu;
+		mad_dump_node_type;
+		mad_dump_nodedesc;
+		mad_dump_nodeinfo;
+		mad_dump_opervls;
+		mad_dump_fields;
+		mad_dump_perfcounters;
+		mad_dump_perfcounters_ext;
+		mad_dump_perfcounters_xmt_sl;
+		mad_dump_perfcounters_rcv_sl;
+		mad_dump_perfcounters_xmt_disc;
+		mad_dump_perfcounters_rcv_err;
+		mad_dump_physportstate;
+		mad_dump_portcapmask;
+		mad_dump_portinfo;
+		mad_dump_portsamples_control;
+		mad_dump_perfcounters_port_op_rcv_counters;
+		mad_dump_perfcounters_port_flow_ctl_counters;
+		mad_dump_perfcounters_port_vl_op_packet;
+		mad_dump_perfcounters_port_vl_op_data;
+		mad_dump_perfcounters_port_vl_xmit_flow_ctl_update_errors;
+		mad_dump_perfcounters_port_vl_xmit_wait_counters;
+		mad_dump_perfcounters_sw_port_vl_congestion;
+		mad_dump_perfcounters_rcv_con_ctrl;
+		mad_dump_perfcounters_sl_rcv_fecn;
+		mad_dump_perfcounters_sl_rcv_becn;
+		mad_dump_perfcounters_xmit_con_ctrl;
+		mad_dump_perfcounters_vl_xmit_time_cong;
+		mad_dump_portstates;
+		mad_dump_portstate;
+		mad_dump_rhex;
+		mad_dump_sltovl;
+		mad_dump_string;
+		mad_dump_switchinfo;
+		mad_dump_uint;
+		mad_dump_vlarbitration;
+		mad_dump_vlcap;
+		mad_get_field;
+		mad_set_field;
+		mad_get_field64;
+		mad_set_field64;
+		mad_get_array;
+		mad_set_array;
+		pma_query_via;
+		performance_reset_via;
+		mad_build_pkt;
+		mad_decode_field;
+		mad_encode;
+		mad_encode_field;
+		mad_trid;
+		portid2portnum;
+		portid2str;
+		str2drpath;
+		drpath2str;
+		mad_class_agent;
+		mad_register_client;
+		mad_register_server;
+		mad_register_client_via;
+		mad_register_server_via;
+		ib_resolve_portid_str;
+		ib_resolve_self;
+		ib_resolve_smlid;
+		ibdebug;
+		mad_rpc_open_port;
+		mad_rpc_close_port;
+		mad_rpc;
+		mad_rpc_rmpp;
+		mad_rpc_portid;
+		mad_rpc_class_agent;
+		mad_rpc_set_retries;
+		mad_rpc_set_timeout;
+		mad_get_timeout;
+		mad_get_retries;
+		madrpc;
+		madrpc_def_timeout;
+		madrpc_init;
+		madrpc_portid;
+		madrpc_rmpp;
+		madrpc_save_mad;
+		madrpc_set_retries;
+		madrpc_set_timeout;
+		madrpc_show_errors;
+		ib_path_query;
+		sa_call;
+		sa_rpc_call;
+		mad_alloc;
+		mad_free;
+		mad_receive;
+		mad_respond;
+		mad_receive_via;
+		mad_respond_via;
+		mad_send;
+		mad_send_via;
+		smp_query;
+		smp_set;
+		ib_vendor_call;
+		ib_vendor_call_via;
+		smp_query_via;
+		smp_query_status_via;
+		smp_set_via;
+		smp_set_status_via;
+		ib_path_query_via;
+		ib_resolve_smlid_via;
+		ib_resolve_guid_via;
+		ib_resolve_gid_via;
+		ib_resolve_portid_str_via;
+		ib_resolve_self_via;
+		mad_field_name;
+		bm_call_via;
+		mad_dump_port_ext_speeds_counters;
 #endif
diff --git a/trunk/ulp/libibmad/src/libibmad.map b/trunk/ulp/libibmad/src/libibmad.map
index 5778e3e..508c18b 100644
--- a/trunk/ulp/libibmad/src/libibmad.map
+++ b/trunk/ulp/libibmad/src/libibmad.map
@@ -12,9 +12,13 @@ IBMAD_1.3 {
 		mad_dump_linkspeed;
 		mad_dump_linkspeeden;
 		mad_dump_linkspeedsup;
+		mad_dump_linkspeedext;
+		mad_dump_linkspeedexten;
+		mad_dump_linkspeedextsup;
 		mad_dump_linkwidth;
 		mad_dump_linkwidthen;
 		mad_dump_linkwidthsup;
+		mad_dump_mlnx_ext_port_info;
 		mad_dump_mtu;
 		mad_dump_node_type;
 		mad_dump_nodedesc;
@@ -31,6 +35,18 @@ IBMAD_1.3 {
 		mad_dump_portcapmask;
 		mad_dump_portinfo;
 		mad_dump_portsamples_control;
+		mad_dump_perfcounters_port_op_rcv_counters;
+		mad_dump_perfcounters_port_flow_ctl_counters;
+		mad_dump_perfcounters_port_vl_op_packet;
+		mad_dump_perfcounters_port_vl_op_data;
+		mad_dump_perfcounters_port_vl_xmit_flow_ctl_update_errors;
+		mad_dump_perfcounters_port_vl_xmit_wait_counters;
+		mad_dump_perfcounters_sw_port_vl_congestion;
+		mad_dump_perfcounters_rcv_con_ctrl;
+		mad_dump_perfcounters_sl_rcv_fecn;
+		mad_dump_perfcounters_sl_rcv_becn;
+		mad_dump_perfcounters_xmit_con_ctrl;
+		mad_dump_perfcounters_vl_xmit_time_cong;
 		mad_dump_portstates;
 		mad_dump_portstate;
 		mad_dump_rhex;
@@ -101,7 +117,9 @@ IBMAD_1.3 {
 		ib_vendor_call;
 		ib_vendor_call_via;
 		smp_query_via;
+		smp_query_status_via;
 		smp_set_via;
+		smp_set_status_via;
 		ib_path_query_via;
 		ib_resolve_smlid_via;
 		ib_resolve_guid_via;
@@ -110,5 +128,6 @@ IBMAD_1.3 {
 		ib_resolve_self_via;
 		mad_field_name;
 		bm_call_via;
+		mad_dump_port_ext_speeds_counters;
 	local: *;
 };
diff --git a/trunk/ulp/libibmad/src/mad.c b/trunk/ulp/libibmad/src/mad.c
index acd0e85..463c61d 100644
--- a/trunk/ulp/libibmad/src/mad.c
+++ b/trunk/ulp/libibmad/src/mad.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
+ * Copyright (c) 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
@@ -83,12 +84,12 @@ void *mad_encode(void *buf, ib_rpc_t * rpc, ib_dr_path_t * drpath, void *data)
 	mad_set_field(buf, 0, IB_MAD_METHOD_F, rpc->method);
 	mad_set_field(buf, 0, IB_MAD_RESPONSE_F, is_resp ? 1 : 0);
 	mad_set_field(buf, 0, IB_MAD_CLASSVER_F,
-		      rpc->mgtclass == IB_SA_CLASS ? 2 : 1);
-	mad_set_field(buf, 0, IB_MAD_MGMTCLASS_F, rpc->mgtclass);
+		      (rpc->mgtclass & 0xff) == IB_SA_CLASS ? 2 : 1);
+	mad_set_field(buf, 0, IB_MAD_MGMTCLASS_F, rpc->mgtclass & 0xff);
 	mad_set_field(buf, 0, IB_MAD_BASEVER_F, 1);
 
 	/* second word */
-	if (rpc->mgtclass == IB_SMI_DIRECT_CLASS) {
+	if ((rpc->mgtclass & 0xff) == IB_SMI_DIRECT_CLASS) {
 		if (!drpath) {
 			IBWARN("encoding dr mad without drpath (null)");
 			return NULL;
@@ -116,7 +117,7 @@ void *mad_encode(void *buf, ib_rpc_t * rpc, ib_dr_path_t * drpath, void *data)
 	/* words 7,8 */
 	mad_set_field64(buf, 0, IB_MAD_MKEY_F, rpc->mkey);
 
-	if (rpc->mgtclass == IB_SMI_DIRECT_CLASS) {
+	if ((rpc->mgtclass & 0xff) == IB_SMI_DIRECT_CLASS) {
 		/* word 9 */
 		mad_set_field(buf, 0, IB_DRSMP_DRDLID_F,
 			      drpath->drdlid ? drpath->drdlid : 0xffff);
@@ -130,14 +131,14 @@ void *mad_encode(void *buf, ib_rpc_t * rpc, ib_dr_path_t * drpath, void *data)
 			mad_set_array(buf, 0, IB_DRSMP_PATH_F, drpath->p);
 	}
 
-	if (rpc->mgtclass == IB_SA_CLASS)
+	if ((rpc->mgtclass & 0xff) == IB_SA_CLASS)
 		mad_set_field64(buf, 0, IB_SA_COMPMASK_F, rpc->mask);
 
 	if (data)
 		memcpy((char *)buf + rpc->dataoffs, data, rpc->datasz);
 
 	/* vendor mads range 2 */
-	if (mad_is_vendor_range2(rpc->mgtclass))
+	if (mad_is_vendor_range2(rpc->mgtclass & 0xff))
 		mad_set_field(buf, 0, IB_VEND2_OUI_F, rpc->oui);
 
 	return (uint8_t *) buf + IB_MAD_SIZE;
@@ -147,9 +148,9 @@ int mad_build_pkt(void *umad, ib_rpc_t * rpc, ib_portid_t * dport,
 		  ib_rmpp_hdr_t * rmpp, void *data)
 {
 	uint8_t *p, *mad;
-	int lid_routed = rpc->mgtclass != IB_SMI_DIRECT_CLASS;
-	int is_smi = (rpc->mgtclass == IB_SMI_CLASS ||
-		      rpc->mgtclass == IB_SMI_DIRECT_CLASS);
+	int lid_routed = (rpc->mgtclass & 0xff) != IB_SMI_DIRECT_CLASS;
+	int is_smi = ((rpc->mgtclass & 0xff) == IB_SMI_CLASS ||
+		      (rpc->mgtclass & 0xff) == IB_SMI_DIRECT_CLASS);
 	struct ib_mad_addr addr;
 
 	if (!is_smi)
diff --git a/trunk/ulp/libibmad/src/register.c b/trunk/ulp/libibmad/src/register.c
index 0ff8006..1fdb64a 100644
--- a/trunk/ulp/libibmad/src/register.c
+++ b/trunk/ulp/libibmad/src/register.c
@@ -77,7 +77,7 @@ static int mgmt_class_vers(int mgmt_class)
 
 int mad_class_agent(int mgmt)
 {
-	if (mgmt < 1 || mgmt > MAX_CLASS)
+	if (mgmt < 1 || mgmt >= MAX_CLASS)
 		return -1;
 	return ibmp->class_agents[mgmt];
 }
diff --git a/trunk/ulp/libibmad/src/rpc.c b/trunk/ulp/libibmad/src/rpc.c
index c5246fe..d20c321 100644
--- a/trunk/ulp/libibmad/src/rpc.c
+++ b/trunk/ulp/libibmad/src/rpc.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
+ * Copyright (c) 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
@@ -119,14 +120,14 @@ int mad_rpc_portid(struct ibmad_port *srcport)
 
 int mad_rpc_class_agent(struct ibmad_port *port, int class)
 {
-	if (class < 1 || class > MAX_CLASS)
+	if (class < 1 || class >= MAX_CLASS)
 		return -1;
 	return port->class_agents[class];
 }
 
 static int
 _do_madrpc(int port_id, void *sndbuf, void *rcvbuf, int agentid, int len,
-	   int timeout, int max_retries)
+	   int timeout, int max_retries, int *p_error)
 {
 	uint32_t trid;		/* only low 32 bits */
 	int retries;
@@ -181,6 +182,7 @@ _do_madrpc(int port_id, void *sndbuf, void *rcvbuf, int agentid, int len,
 			return length;
 	}
 
+	*p_error = ETIMEDOUT;
 	ERRS("timeout after %d retries, %d ms", retries, timeout * retries);
 	return -1;
 }
@@ -212,7 +214,11 @@ void *mad_rpc(const struct ibmad_port *port, ib_rpc_t * rpc,
 	int status, len;
 	uint8_t sndbuf[1024], rcvbuf[1024], *mad;
 	int redirect = 1;
+	ib_rpc_v1_t *rpcv1 = (ib_rpc_v1_t *)rpc;
+	int error = 0;
 
+	if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) == IB_MAD_RPC_VERSION1)
+		rpcv1->error = 0;
 	while (redirect) {
 		len = 0;
 		memset(sndbuf, 0, umad_size() + IB_MAD_SIZE);
@@ -221,9 +227,12 @@ void *mad_rpc(const struct ibmad_port *port, ib_rpc_t * rpc,
 			return NULL;
 
 		if ((len = _do_madrpc(port->port_id, sndbuf, rcvbuf,
-				      port->class_agents[rpc->mgtclass],
+				      port->class_agents[rpc->mgtclass & 0xff],
 				      len, mad_get_timeout(port, rpc->timeout),
-				      mad_get_retries(port))) < 0) {
+				      mad_get_retries(port), &error)) < 0) {
+			if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) ==
+			    IB_MAD_RPC_VERSION1)
+				rpcv1->error = error;
 			IBWARN("_do_madrpc failed; dport (%s)",
 			       portid2str(dport));
 			return NULL;
@@ -243,6 +252,10 @@ void *mad_rpc(const struct ibmad_port *port, ib_rpc_t * rpc,
 			redirect = 0;
 	}
 
+	if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) == IB_MAD_RPC_VERSION1)
+		rpcv1->error = error;
+	rpc->rstatus = status;
+
 	if (status != 0) {
 		ERRS("MAD completed with error status 0x%x; dport (%s)",
 		     status, portid2str(dport));
@@ -265,22 +278,31 @@ void *mad_rpc_rmpp(const struct ibmad_port *port, ib_rpc_t * rpc,
 {
 	int status, len;
 	uint8_t sndbuf[1024], rcvbuf[1024], *mad;
+	ib_rpc_v1_t *rpcv1 = (ib_rpc_v1_t *)rpc;
+	int error = 0;
 
 	memset(sndbuf, 0, umad_size() + IB_MAD_SIZE);
 
 	DEBUG("rmpp %p data %p", rmpp, data);
 
+	if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) == IB_MAD_RPC_VERSION1)
+		rpcv1->error = 0;
 	if ((len = mad_build_pkt(sndbuf, rpc, dport, rmpp, data)) < 0)
 		return NULL;
 
 	if ((len = _do_madrpc(port->port_id, sndbuf, rcvbuf,
-			      port->class_agents[rpc->mgtclass],
+			      port->class_agents[rpc->mgtclass & 0xff],
 			      len, mad_get_timeout(port, rpc->timeout),
-			      mad_get_retries(port))) < 0) {
+			      mad_get_retries(port), &error)) < 0) {
+		if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) == IB_MAD_RPC_VERSION1)
+			rpcv1->error = error;
 		IBWARN("_do_madrpc failed; dport (%s)", portid2str(dport));
 		return NULL;
 	}
 
+	if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) == IB_MAD_RPC_VERSION1)
+		rpcv1->error = error;
+
 	mad = umad_get_mad(rcvbuf);
 
 	if ((status = mad_get_field(mad, 0, IB_MAD_STATUS_F)) != 0) {
diff --git a/trunk/ulp/libibmad/src/serv.c b/trunk/ulp/libibmad/src/serv.c
index df61f25..2e3b7ef 100644
--- a/trunk/ulp/libibmad/src/serv.c
+++ b/trunk/ulp/libibmad/src/serv.c
@@ -72,7 +72,7 @@ int mad_send_via(ib_rpc_t * rpc, ib_portid_t * dport, ib_rmpp_hdr_t * rmpp,
 		      (char *)umad_get_mad(umad) + rpc->dataoffs, rpc->datasz);
 	}
 
-	if (umad_send(srcport->port_id, srcport->class_agents[rpc->mgtclass],
+	if (umad_send(srcport->port_id, srcport->class_agents[rpc->mgtclass & 0xff],
 		      umad, IB_MAD_SIZE, mad_get_timeout(srcport, rpc->timeout),
 		      0) < 0) {
 		IBWARN("send failed; %m");
diff --git a/trunk/ulp/libibmad/src/smp.c b/trunk/ulp/libibmad/src/smp.c
index 3ff58ce..a337663 100644
--- a/trunk/ulp/libibmad/src/smp.c
+++ b/trunk/ulp/libibmad/src/smp.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 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
@@ -45,11 +46,12 @@
 #undef DEBUG
 #define DEBUG 	if (ibdebug)	IBWARN
 
-uint8_t *smp_set_via(void *data, ib_portid_t * portid, unsigned attrid,
-		     unsigned mod, unsigned timeout,
-		     const struct ibmad_port *srcport)
+uint8_t *smp_set_status_via(void *data, ib_portid_t * portid, unsigned attrid,
+			    unsigned mod, unsigned timeout, int *rstatus,
+			    const struct ibmad_port *srcport)
 {
 	ib_rpc_t rpc = { 0 };
+	uint8_t *res;
 
 	DEBUG("attr 0x%x mod 0x%x route %s", attrid, mod, portid2str(portid));
 	if ((portid->lid <= 0) ||
@@ -69,7 +71,18 @@ uint8_t *smp_set_via(void *data, ib_portid_t * portid, unsigned attrid,
 	portid->sl = 0;
 	portid->qp = 0;
 
-	return mad_rpc(srcport, &rpc, portid, data, data);
+	res = mad_rpc(srcport, &rpc, portid, data, data);
+	if (rstatus)
+		*rstatus = rpc.rstatus;
+	return res;
+}
+
+uint8_t *smp_set_via(void *data, ib_portid_t * portid, unsigned attrid,
+		     unsigned mod, unsigned timeout,
+		     const struct ibmad_port *srcport)
+{
+	return smp_set_status_via(data, portid, attrid, mod, timeout, NULL,
+				  srcport);
 }
 
 uint8_t *smp_set(void *data, ib_portid_t * portid, unsigned attrid,
@@ -78,11 +91,12 @@ uint8_t *smp_set(void *data, ib_portid_t * portid, unsigned attrid,
 	return smp_set_via(data, portid, attrid, mod, timeout, ibmp);
 }
 
-uint8_t *smp_query_via(void *rcvbuf, ib_portid_t * portid, unsigned attrid,
-		       unsigned mod, unsigned timeout,
-		       const struct ibmad_port * srcport)
+uint8_t *smp_query_status_via(void *rcvbuf, ib_portid_t * portid,
+			      unsigned attrid, unsigned mod, unsigned timeout,
+			      int *rstatus, const struct ibmad_port * srcport)
 {
 	ib_rpc_t rpc = { 0 };
+	uint8_t *res;
 
 	DEBUG("attr 0x%x mod 0x%x route %s", attrid, mod, portid2str(portid));
 	rpc.method = IB_MAD_METHOD_GET;
@@ -102,7 +116,18 @@ uint8_t *smp_query_via(void *rcvbuf, ib_portid_t * portid, unsigned attrid,
 	portid->sl = 0;
 	portid->qp = 0;
 
-	return mad_rpc(srcport, &rpc, portid, 0, rcvbuf);
+	res = mad_rpc(srcport, &rpc, portid, rcvbuf, rcvbuf);
+	if (rstatus)
+		*rstatus = rpc.rstatus;
+	return res;
+}
+
+uint8_t *smp_query_via(void *rcvbuf, ib_portid_t * portid, unsigned attrid,
+		       unsigned mod, unsigned timeout,
+		       const struct ibmad_port * srcport)
+{
+	return smp_query_status_via(rcvbuf, portid, attrid, mod, timeout, NULL,
+				    srcport);
 }
 
 uint8_t *smp_query(void *rcvbuf, ib_portid_t * portid, unsigned attrid,
diff --git a/trunk/ulp/libibmad/src/vendor.c b/trunk/ulp/libibmad/src/vendor.c
index 11efd76..22d6843 100644
--- a/trunk/ulp/libibmad/src/vendor.c
+++ b/trunk/ulp/libibmad/src/vendor.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 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
@@ -38,6 +39,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #include <infiniband/mad.h>
 #include "mad_internal.h"
@@ -61,8 +63,10 @@ uint8_t *ib_vendor_call_via(void *data, ib_portid_t * portid,
 			    ib_vendor_call_t * call,
 			    struct ibmad_port * srcport)
 {
-	ib_rpc_t rpc = { 0 };
+	ib_rpc_v1_t rpc = { 0 };
+	ib_rpc_t *rpcold = (ib_rpc_t *)(void *)&rpc;
 	int range1 = 0, resp_expected;
+	void *p_ret;
 
 	DEBUG("route %s data %p", portid2str(portid), data);
 	if (portid->lid <= 0)
@@ -74,7 +78,7 @@ uint8_t *ib_vendor_call_via(void *data, ib_portid_t * portid,
 
 	resp_expected = response_expected(call->method);
 
-	rpc.mgtclass = call->mgmt_class;
+	rpc.mgtclass = call->mgmt_class | IB_MAD_RPC_VERSION1;
 
 	rpc.method = call->method;
 	rpc.attr.id = call->attrid;
@@ -97,8 +101,11 @@ uint8_t *ib_vendor_call_via(void *data, ib_portid_t * portid,
 	if (!portid->qkey)
 		portid->qkey = IB_DEFAULT_QP1_QKEY;
 
-	if (resp_expected)
-		return mad_rpc_rmpp(srcport, &rpc, portid, 0, data);	/* FIXME: no RMPP for now */
+	if (resp_expected) {
+		p_ret = mad_rpc_rmpp(srcport, rpcold, portid, 0, data);	/* FIXME: no RMPP for now */
+		errno = rpc.error;
+		return p_ret;
+	}
 
-	return mad_send_via(&rpc, portid, 0, data, srcport) < 0 ? 0 : data;	/* FIXME: no RMPP for now */
+	return mad_send_via(rpcold, portid, 0, data, srcport) < 0 ? 0 : data;	/* FIXME: no RMPP for now */
 }
diff --git a/trunk/ulp/libibnetdisc/include/infiniband/ibnetdisc.h b/trunk/ulp/libibnetdisc/include/infiniband/ibnetdisc.h
index 49ff743..300094e 100644
--- a/trunk/ulp/libibnetdisc/include/infiniband/ibnetdisc.h
+++ b/trunk/ulp/libibnetdisc/include/infiniband/ibnetdisc.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
+ * Copyright (c) 2010 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
@@ -39,9 +40,13 @@
 #include <infiniband/mad.h>
 #include <iba/ib_types.h>
 
+#include <infiniband/ibnetdisc_osd.h>
+
 struct ibnd_chassis;		/* forward declare */
 struct ibnd_port;		/* forward declare */
 
+#define CHASSIS_TYPE_SIZE 20
+
 /** =========================================================================
  * Node
  */
@@ -79,6 +84,7 @@ typedef struct ibnd_node {
 	struct ibnd_node *next_chassis_node;	/* next node in ibnd_chassis_t->nodes */
 	struct ibnd_chassis *chassis;	/* if != NULL the chassis this node belongs to */
 	unsigned char ch_type;
+	char ch_type_str[CHASSIS_TYPE_SIZE];
 	unsigned char ch_anafanum;
 	unsigned char ch_slotnum;
 	unsigned char ch_slot;
@@ -149,6 +155,8 @@ typedef struct ibnd_fabric {
 	 * or by default the node you ar running on
 	 */
 	ibnd_node_t *from_node;
+	int from_portnum;
+
 	/* NULL term list of all nodes in the fabric */
 	ibnd_node_t *nodes;
 	/* NULL terminated list of all chassis found in the fabric */
@@ -187,6 +195,9 @@ IBND_EXPORT ibnd_fabric_t *ibnd_load_fabric(const char *file,
 IBND_EXPORT int ibnd_cache_fabric(ibnd_fabric_t * fabric, const char *file,
 				 unsigned int flags);
 
+#define IBND_CACHE_FABRIC_FLAG_DEFAULT      0x0000
+#define IBND_CACHE_FABRIC_FLAG_NO_OVERWRITE 0x0001
+
 /** =========================================================================
  * Node operations
  */
@@ -202,6 +213,17 @@ IBND_EXPORT void ibnd_iter_nodes_type(ibnd_fabric_t * fabric,
 				     int node_type, void *user_data);
 
 /** =========================================================================
+ * Port operations
+ */
+IBND_EXPORT ibnd_port_t *ibnd_find_port_guid(ibnd_fabric_t * fabric,
+					uint64_t guid);
+IBND_EXPORT ibnd_port_t *ibnd_find_port_dr(ibnd_fabric_t * fabric,
+					char *dr_str);
+typedef void (*ibnd_iter_port_func_t) (ibnd_port_t * port, void *user_data);
+IBND_EXPORT void ibnd_iter_ports(ibnd_fabric_t * fabric,
+				ibnd_iter_port_func_t func, void *user_data);
+
+/** =========================================================================
  * Chassis queries
  */
 IBND_EXPORT uint64_t ibnd_get_chassis_guid(ibnd_fabric_t * fabric,
diff --git a/trunk/ulp/libibnetdisc/include/infiniband/ibnetdisc_osd.h b/trunk/ulp/libibnetdisc/include/infiniband/ibnetdisc_osd.h
new file mode 100644
index 0000000..b25104a
--- /dev/null
+++ b/trunk/ulp/libibnetdisc/include/infiniband/ibnetdisc_osd.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 Lawrence Livermore National Security.  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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _IBNETDISC_OSD_H_
+#define _IBNETDISC_OSD_H_
+
+/* Define OS specific bits */
+
+/* Windows */
+
+#endif				/* _IBNETDISC_OSD_H_ */
diff --git a/trunk/ulp/libibnetdisc/src/chassis.c b/trunk/ulp/libibnetdisc/src/chassis.c
index 25d7473..5726f8e 100644
--- a/trunk/ulp/libibnetdisc/src/chassis.c
+++ b/trunk/ulp/libibnetdisc/src/chassis.c
@@ -50,9 +50,9 @@
 #include "internal.h"
 #include "chassis.h"
 
-static char *ChassisTypeStr[6] =
-{ "", "ISR9288", "ISR9096", "ISR2012", "ISR2004", "ISR4700" };
-static char *ChassisSlotTypeStr[4] = { "", "Line", "Spine", "SRBD" };
+static char *ChassisTypeStr[] =
+{ "", "ISR9288", "ISR9096", "ISR2012", "ISR2004", "ISR4700", "ISR4200" };
+static char *ChassisSlotTypeStr[] = { "", "Line", "Spine", "SRBD" };
 
 typedef struct chassis_scan {
 	ibnd_chassis_t *first_chassis;
@@ -62,30 +62,53 @@ typedef struct chassis_scan {
 
 char *ibnd_get_chassis_type(ibnd_node_t * node)
 {
+	int chassis_type;
+
 	if (!node) {
 		IBND_DEBUG("node parameter NULL\n");
 		return NULL;
 	}
 
-	/* Currently, only if Voltaire chassis */
-	if (mad_get_field(node->info, 0, IB_NODE_VENDORID_F) != VTR_VENDOR_ID)
-		return NULL;
 	if (!node->chassis)
 		return NULL;
-	if (node->ch_type == UNRESOLVED_CT || node->ch_type > ISR4700_CT)
-		return NULL;
-	return ChassisTypeStr[node->ch_type];
+
+	chassis_type = mad_get_field(node->info, 0, IB_NODE_VENDORID_F);
+
+	switch (chassis_type)
+	{
+		case VTR_VENDOR_ID: /* Voltaire chassis */
+		{
+			if (node->ch_type == UNRESOLVED_CT || node->ch_type > ISR4200_CT)
+				return NULL;
+			return ChassisTypeStr[node->ch_type];
+		}
+		case MLX_VENDOR_ID:
+		{
+			if (node->ch_type_str[0] == '\0')
+				return NULL;
+			return node->ch_type_str;
+		}
+		default:
+		{
+			break;
+		}
+	}
+	return NULL;
 }
 
 char *ibnd_get_chassis_slot_str(ibnd_node_t * node, char *str, size_t size)
 {
+	int vendor_id;
+
 	if (!node) {
 		IBND_DEBUG("node parameter NULL\n");
 		return NULL;
 	}
 
-	/* Currently, only if Voltaire chassis */
-	if (mad_get_field(node->info, 0, IB_NODE_VENDORID_F) != VTR_VENDOR_ID)
+	/* Currently, only if Voltaire or Mellanox chassis */
+	vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
+
+	if ((vendor_id != VTR_VENDOR_ID) && (vendor_id != MLX_VENDOR_ID))
 		return NULL;
 	if (!node->chassis)
 		return NULL;
@@ -286,11 +309,18 @@ static int is_spine_4700x2(ibnd_node_t * n)
 	return (devid == VTR_DEVID_SFB4700X2);
 }
 
+static int is_spine_4200(ibnd_node_t * n)
+{
+	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
+	return (devid == VTR_DEVID_SFB4200);
+}
+
 static int is_spine(ibnd_node_t * n)
 {
 	return (is_spine_9096(n) || is_spine_9288(n) ||
 		is_spine_2004(n) || is_spine_2012(n) ||
-		is_spine_4700(n) || is_spine_4700x2(n));
+		is_spine_4700(n) || is_spine_4700x2(n) ||
+		is_spine_4200(n));
 }
 
 static int is_line_24(ibnd_node_t * n)
@@ -376,6 +406,18 @@ char anafa_line_slot_2_sfb18x2[37] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
+/* LB slot = table[spine port] */
+char line_slot_2_sfb4200[37] = {
+	0,
+	1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5,
+	5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9};
+/* LB asic num = table[spine port] */
+char anafa_line_slot_2_sfb4200[37] = {
+	0,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
 /* IPR FCR modules connectivity while using sFB4 port as reference */
 char ipr_slot_2_sfb4_port[37] = {
 	0,
@@ -424,6 +466,18 @@ char anafa_spine18x2_slot_2_slb[37] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
+/* FB slot = table[line port] */
+char sfb4200_slot_2_slb[37] = {
+	0,
+	1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+/* FB asic = table[line port] */
+char anafa_sfb4200_slot_2_slb[37] = {
+	0,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
 
 /*	reference                     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; */
 
@@ -454,10 +508,13 @@ static int get_sfb_slot(ibnd_node_t * n, ibnd_port_t * lineport)
 		n->ch_type = ISR4700_CT;
 		n->ch_slotnum = spine18_slot_2_slb[lineport->portnum];
 		n->ch_anafanum = anafa_spine18x2_slot_2_slb[lineport->portnum];
+	} else if (is_spine_4200(n)) {
+		n->ch_type = ISR4200_CT;
+		n->ch_slotnum = sfb4200_slot_2_slb[lineport->portnum];
+		n->ch_anafanum = anafa_sfb4200_slot_2_slb[lineport->portnum];
 	} else {
 		IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
 			   n->guid);
-		return -1;
 	}
 	return 0;
 }
@@ -498,7 +555,6 @@ static int get_router_slot(ibnd_node_t * n, ibnd_port_t * spineport)
 	} else {
 		IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
 			   spineport->node->guid);
-		return -1;
 	}
 	return 0;
 }
@@ -530,14 +586,177 @@ static int get_slb_slot(ibnd_node_t * n, ibnd_port_t * spineport)
 		n->ch_type = ISR4700_CT;
 		n->ch_slotnum = line_slot_2_sfb18x2[spineport->portnum];
 		n->ch_anafanum = anafa_line_slot_2_sfb18x2[spineport->portnum];
+	} else if (is_spine_4200(spineport->node)) {
+		n->ch_type = ISR4200_CT;
+		n->ch_slotnum = line_slot_2_sfb4200[spineport->portnum];
+		n->ch_anafanum = anafa_line_slot_2_sfb4200[spineport->portnum];
 	} else {
 		IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
 			   spineport->node->guid);
-		return -1;
 	}
 	return 0;
 }
 
+
+/*
+	This function called for every Mellanox node in fabric
+*/
+static int fill_mellanox_chassis_record(ibnd_node_t * node)
+{
+	int p = 0;
+	ibnd_port_t *port;
+
+	char node_desc[IB_SMP_DATA_SIZE];
+	char *system_name;
+	char *system_type;
+	char *system_slot_name;
+	char *node_index;
+	char *iter;
+	int dev_id;
+
+	/*
+	The node description has the following format:
+
+	'MF0;<system name>:<system type>/<system slot name>[:board type]/U<node index>'
+
+     - System slot name in our systems can be L[01-36] , S[01-18]
+     - Node index is always 1 (we don.t have boards with multiple IS4 chips).
+     - System name is taken from the currently configured host name.
+     -The board type is optional and we don.t set it currently  - A leaf or spine slot can currently hold a single type of board.
+	 */
+
+	memcpy(node_desc, node->nodedesc, IB_SMP_DATA_SIZE);
+
+	IBND_DEBUG("fill_mellanox_chassis_record: node_desc:%s \n",node_desc);
+
+	if (node->ch_found)	/* somehow this node has already been passed */
+		return 0;
+
+	/* All mellanox IS4 switches have the same vendor id*/
+	dev_id = mad_get_field(node->info, 0,IB_NODE_DEVID_F);
+	if (dev_id != MLX_DEVID_IS4)
+		return 0;
+
+	if((node_desc[0] != 'M') ||
+	   (node_desc[1] != 'F') ||
+	   (node_desc[2] != '0') ||
+	   (node_desc[3] != ';')) {
+		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s \n",node_desc);
+		return 0;
+	}
+
+	/* parse system name*/
+	system_name = &node_desc[4];
+	for (iter = system_name ; (*iter != ':') && (*iter != '\0') ; iter++);
+	if(*iter == '\0'){
+		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_name failed) \n",node_desc);
+		return 0;
+	}
+	*iter = '\0';
+	iter++;
+	/* parse system type*/
+	system_type = iter;
+	for ( ; (*iter != '/') && (*iter != '\0') ; iter++);
+	if(*iter == '\0'){
+		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_type failed) \n",node_desc);
+		return 0;
+	}
+	*iter = '\0';
+	iter++;
+	/* parse system slot name*/
+	system_slot_name = iter;
+	for ( ; (*iter != '/') && (*iter != ':') && (*iter != '\0') ; iter++);
+	if(*iter == '\0'){
+		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_slot_name failed) \n",node_desc);
+		return 0;
+	}
+	if(*iter == ':'){
+		*iter = '\0';
+		iter++;
+		for ( ; (*iter != '/') && (*iter != '\0') ; iter++);
+		if(*iter == '\0'){
+			IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get board type failed) \n",node_desc);
+			return 0;
+		}
+	}
+	*iter = '\0';
+	iter++;
+	node_index = iter;
+	if(node_index[0] != 'U'){
+		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get node index) \n",node_desc);
+		return 0;
+	}
+
+	/* set Chip number (node index) */
+	node->ch_anafanum = (unsigned char) atoi(&node_index[1]);
+	if(node->ch_anafanum != 1){
+		IBND_DEBUG("Unexpected Chip number:%d \n",node->ch_anafanum);
+	}
+
+
+	/* set Line Spine numbers */
+	if(system_slot_name[0] == 'L')
+		node->ch_slot = LINE_CS;
+	else if(system_slot_name[0] == 'S')
+		node->ch_slot = SPINE_CS;
+	else{
+		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported system_slot_name:%s \n",system_slot_name);
+		return 0;
+	}
+
+	/* The switch will be displayed under Line or Spine and not under Chassis switches */
+	node->ch_found = 1;
+
+	node->ch_slotnum = (unsigned char) atoi(&system_slot_name[1]);
+	if((node->ch_slot == LINE_CS && (node->ch_slotnum >  (LINES_MAX_NUM + 1))) ||
+	   (node->ch_slot == SPINE_CS && (node->ch_slotnum > (SPINES_MAX_NUM + 1)))){
+		IBND_ERROR("fill_mellanox_chassis_record: invalid slot number:%d \n",node->ch_slotnum);
+		node->ch_slotnum = 0;
+		return 0;
+	}
+
+	/*set ch_type_str*/
+	strncpy(node->ch_type_str , system_type, sizeof(node->ch_type_str)-1);
+
+	/* Line ports 1-18 are mapped to external ports 1-18*/
+	if(node->ch_slot == LINE_CS)
+	{
+		for (p = 1; p <= node->numports && p <= 18 ; p++) {
+			port = node->ports[p];
+			if (!port)
+				continue;
+			port->ext_portnum = p;
+		}
+	}
+
+	return 0;
+}
+
+static int insert_mellanox_line_and_spine(ibnd_node_t * node, ibnd_chassis_t * chassis)
+{
+	if (node->ch_slot == LINE_CS){
+
+		if (chassis->linenode[node->ch_slotnum])
+			return 0;	/* already filled slot */
+
+		chassis->linenode[node->ch_slotnum] = node;
+	}
+	else if (node->ch_slot == SPINE_CS){
+
+		if (chassis->spinenode[node->ch_slotnum])
+			return 0;	/* already filled slot */
+
+		chassis->spinenode[node->ch_slotnum] = node;
+	}
+	else
+		return 0;
+
+	node->chassis = chassis;
+
+	return 0;
+}
+
+
 /* forward declare this */
 static void voltaire_portmap(ibnd_port_t * port);
 /*
@@ -588,8 +807,7 @@ static int fill_voltaire_chassis_record(ibnd_node_t * node)
 			}
 			if (!node->ch_type)
 				/* we assume here that remoteport belongs to line */
-				if (get_sfb_slot(node, port->remoteport))
-					return -1;
+				get_sfb_slot(node, port->remoteport);
 
 			/* we could break here, but need to find if more routers connected */
 		}
@@ -607,8 +825,7 @@ static int fill_voltaire_chassis_record(ibnd_node_t * node)
 				continue;
 
 			/* we assume here that remoteport belongs to spine */
-			if (get_slb_slot(node, port->remoteport))
-				return -1;
+			get_slb_slot(node, port->remoteport);
 			break;
 		}
 	}
@@ -1025,6 +1242,7 @@ int group_nodes(ibnd_fabric_t * fabric)
 	ibnd_chassis_t *chassis;
 	ibnd_chassis_t *ch, *ch_next;
 	chassis_scan_t chassis_scan;
+	int vendor_id;
 
 	chassis_scan.first_chassis = NULL;
 	chassis_scan.current_chassis = NULL;
@@ -1035,10 +1253,16 @@ int group_nodes(ibnd_fabric_t * fabric)
 	/* according to internal connectivity */
 	/* not very efficient but clear code so... */
 	for (node = fabric->switches; node; node = node->type_next) {
-		if (mad_get_field(node->info, 0,
-				  IB_NODE_VENDORID_F) == VTR_VENDOR_ID
+
+		vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
+
+		if (vendor_id == VTR_VENDOR_ID
 		    && fill_voltaire_chassis_record(node))
 			goto cleanup;
+		else if (vendor_id == MLX_VENDOR_ID
+			&& fill_mellanox_chassis_record(node))
+			goto cleanup;
+
 	}
 
 	/* separate every Voltaire chassis from each other and build linked list of them */
@@ -1084,8 +1308,10 @@ int group_nodes(ibnd_fabric_t * fabric)
 	/* now, make another pass to see which nodes are part of chassis */
 	/* (defined as chassis->nodecount > 1) */
 	for (node = fabric->nodes; node; node = node->next) {
-		if (mad_get_field(node->info, 0,
-				  IB_NODE_VENDORID_F) == VTR_VENDOR_ID)
+
+		vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
+
+		if (vendor_id == VTR_VENDOR_ID)
 			continue;
 		if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) {
 			chassis = find_chassisguid(fabric, node);
@@ -1096,6 +1322,9 @@ int group_nodes(ibnd_fabric_t * fabric)
 					node->ch_found = 1;
 					add_node_to_chassis(chassis, node);
 				}
+				else if (vendor_id == MLX_VENDOR_ID){
+					insert_mellanox_line_and_spine(node, chassis);
+				}
 			}
 		}
 	}
diff --git a/trunk/ulp/libibnetdisc/src/chassis.h b/trunk/ulp/libibnetdisc/src/chassis.h
index f8e0ee2..7a91be3 100644
--- a/trunk/ulp/libibnetdisc/src/chassis.h
+++ b/trunk/ulp/libibnetdisc/src/chassis.h
@@ -73,16 +73,20 @@
 #define VTR_DEVID_SLB4018		0x5a5b
 #define VTR_DEVID_SFB4700		0x5a5c
 #define VTR_DEVID_SFB4700X2		0x5a5d
+#define VTR_DEVID_SFB4200		0x5a60
+
+#define MLX_DEVID_IS4			0xbd36
 
 /* Vendor IDs (for chassis based systems) */
 #define VTR_VENDOR_ID			0x8f1	/* Voltaire */
+#define MLX_VENDOR_ID			0x2c9	/* Mellanox */
 #define TS_VENDOR_ID			0x5ad	/* Cisco */
 #define SS_VENDOR_ID			0x66a	/* InfiniCon */
 #define XS_VENDOR_ID			0x1397	/* Xsigo */
 
 enum ibnd_chassis_type {
 	UNRESOLVED_CT, ISR9288_CT, ISR9096_CT, ISR2012_CT, ISR2004_CT,
-	ISR4700_CT
+	ISR4700_CT, ISR4200_CT
 };
 enum ibnd_chassis_slot_type { UNRESOLVED_CS, LINE_CS, SPINE_CS, SRBD_CS };
 
diff --git a/trunk/ulp/libibnetdisc/src/ibnetdisc.c b/trunk/ulp/libibnetdisc/src/ibnetdisc.c
index f525d71..9800c9d 100644
--- a/trunk/ulp/libibnetdisc/src/ibnetdisc.c
+++ b/trunk/ulp/libibnetdisc/src/ibnetdisc.c
@@ -2,6 +2,7 @@
  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2008 Lawrence Livermore National Laboratory
+ * Copyright (c) 2010 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
@@ -55,8 +56,13 @@
 #include "chassis.h"
 
 /* forward declare */
+struct ni_cbdata
+{
+	ibnd_node_t *node;
+	int port_num;
+};
 static int query_node_info(smp_engine_t * engine, ib_portid_t * portid,
-			   ibnd_node_t * node);
+			   struct ni_cbdata * cbdata);
 
 static int recv_switch_info(smp_engine_t * engine, ibnd_smp_t * smp,
 			    uint8_t * mad, void *cb_data)
@@ -79,13 +85,33 @@ static int query_switch_info(smp_engine_t * engine, ib_portid_t * portid,
 
 static int add_port_to_dpath(ib_dr_path_t * path, int nextport)
 {
-	if (path->cnt > sizeof(path->p) - 1)
+	if (path->cnt > sizeof(path->p) - 2)
 		return -1;
 	++path->cnt;
 	path->p[path->cnt] = (uint8_t) nextport;
 	return path->cnt;
 }
 
+static int retract_dpath(smp_engine_t * engine, ib_portid_t * portid)
+{
+	ibnd_scan_t *scan = engine->user_data;
+	ibnd_fabric_t *fabric = scan->fabric;
+
+	if (scan->cfg->max_hops &&
+	    fabric->maxhops_discovered > scan->cfg->max_hops)
+		return 0;
+
+	/* this may seem wrong but the only time we would retract the path is
+	 * if the user specified a CA for the DR path and we are retracting
+	 * from that to find the node it is connected to.  This counts as a
+	 * positive hop discovered
+	 */
+	fabric->maxhops_discovered++;
+	portid->drpath.p[portid->drpath.cnt] = 0;
+	portid->drpath.cnt--;
+	return 1;
+}
+
 static int extend_dpath(smp_engine_t * engine, ib_portid_t * portid,
 			int nextport)
 {
@@ -93,7 +119,7 @@ static int extend_dpath(smp_engine_t * engine, ib_portid_t * portid,
 	ibnd_fabric_t *fabric = scan->fabric;
 
 	if (scan->cfg->max_hops &&
-	    fabric->maxhops_discovered >= scan->cfg->max_hops)
+	    fabric->maxhops_discovered > scan->cfg->max_hops)
 		return 0;
 
 	if (portid->lid) {
@@ -114,8 +140,9 @@ static int extend_dpath(smp_engine_t * engine, ib_portid_t * portid,
 		return -1;
 	}
 
-	if ((unsigned) portid->drpath.cnt > fabric->maxhops_discovered)
-		fabric->maxhops_discovered = portid->drpath.cnt;
+	if (((unsigned) portid->drpath.cnt - scan->initial_hops) >
+	    fabric->maxhops_discovered)
+		fabric->maxhops_discovered++;
 
 	return 1;
 }
@@ -170,7 +197,8 @@ static int recv_port_info(smp_engine_t * engine, ibnd_smp_t * smp,
 	if (!port) {
 		port = node->ports[port_num] = calloc(1, sizeof(*port));
 		if (!port) {
-			IBND_ERROR("Failed to allocate port\n");
+			IBND_ERROR("Failed to allocate 0x%" PRIx64 " port %u\n",
+				    node->guid, port_num);
 			return -1;
 		}
 		port->guid =
@@ -199,10 +227,27 @@ static int recv_port_info(smp_engine_t * engine, ibnd_smp_t * smp,
 	if (port_num && mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F)
 	    == IB_PORT_PHYS_STATE_LINKUP
 	    && ((node->type == IB_NODE_SWITCH && port_num != local_port) ||
-		(node == fabric->from_node && port_num == local_port))) {
+		(node == fabric->from_node && port_num == fabric->from_portnum))) {
+
+		int rc = 0;
 		ib_portid_t path = smp->path;
-		if (extend_dpath(engine, &path, port_num) > 0)
-			query_node_info(engine, &path, node);
+
+		if (node->type != IB_NODE_SWITCH &&
+		    node == fabric->from_node &&
+		    path.drpath.cnt > 1)
+			rc = retract_dpath(engine, &path);
+		else {
+			/* we can't proceed through an HCA with DR */
+			if (path.lid == 0 || node->type == IB_NODE_SWITCH)
+				rc = extend_dpath(engine, &path, port_num);
+		}
+
+		if (rc > 0) {
+			struct ni_cbdata * cbdata = malloc(sizeof(*cbdata));
+			cbdata->node = node;
+			cbdata->port_num = port_num;
+			query_node_info(engine, &path, cbdata);
+		}
 	}
 
 	return 0;
@@ -253,11 +298,6 @@ static ibnd_node_t *create_node(smp_engine_t * engine, ib_portid_t * path,
 	return rc;
 }
 
-static int get_last_port(ib_portid_t * path)
-{
-	return path->drpath.p[path->drpath.cnt];
-}
-
 static void link_ports(ibnd_node_t * node, ibnd_port_t * port,
 		       ibnd_node_t * remotenode, ibnd_port_t * remoteport)
 {
@@ -292,7 +332,9 @@ static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp,
 	ibnd_fabric_t *fabric = scan->fabric;
 	int i = 0;
 	uint8_t *node_info = mad + IB_SMP_DATA_OFFS;
-	ibnd_node_t *rem_node = cb_data;
+	struct ni_cbdata *ni_cbdata = (struct ni_cbdata *)cb_data;
+	ibnd_node_t *rem_node = NULL;
+	int rem_port_num = 0;
 	ibnd_node_t *node;
 	int node_is_new = 0;
 	uint64_t node_guid = mad_get_field64(node_info, 0, IB_NODE_GUID_F);
@@ -300,6 +342,12 @@ static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp,
 	int port_num = mad_get_field(node_info, 0, IB_NODE_LOCAL_PORT_F);
 	ibnd_port_t *port = NULL;
 
+	if (ni_cbdata) {
+		rem_node = ni_cbdata->node;
+		rem_port_num = ni_cbdata->port_num;
+		free(ni_cbdata);
+	}
+
 	node = ibnd_find_node_guid(fabric, node_guid);
 	if (!node) {
 		node = create_node(engine, &smp->path, node_info);
@@ -315,6 +363,8 @@ static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp,
 	if (!port) {
 		/* If we have not see this port before create a shell for it */
 		port = node->ports[port_num] = calloc(1, sizeof(*port));
+		if (!port)
+			return -1;
 		port->node = node;
 		port->portnum = port_num;
 	}
@@ -324,12 +374,11 @@ static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp,
 		dump_endnode(&smp->path, node_is_new ? "new" : "known",
 			     node, port);
 
-	if (rem_node == NULL)	/* this is the start node */
+	if (rem_node == NULL) {	/* this is the start node */
 		fabric->from_node = node;
-	else {
+		fabric->from_portnum = port_num;
+	} else {
 		/* link ports... */
-		int rem_port_num = get_last_port(&smp->path);
-
 		if (!rem_node->ports[rem_port_num]) {
 			IBND_ERROR("Internal Error; "
 				   "Node(%p) 0x%" PRIx64
@@ -358,11 +407,11 @@ static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp,
 }
 
 static int query_node_info(smp_engine_t * engine, ib_portid_t * portid,
-			   ibnd_node_t * node)
+			   struct ni_cbdata * cbdata)
 {
 	IBND_DEBUG("Query Node Info; %s\n", portid2str(portid));
 	return issue_smp(engine, portid, IB_ATTR_NODE_INFO, 0,
-			 recv_node_info, node);
+			 recv_node_info, (void *)cbdata);
 }
 
 ibnd_node_t *ibnd_find_node_guid(ibnd_fabric_t * fabric, uint64_t guid)
@@ -382,37 +431,13 @@ ibnd_node_t *ibnd_find_node_guid(ibnd_fabric_t * fabric, uint64_t guid)
 	return NULL;
 }
 
+/* forward declare */
+ibnd_port_t *ibnd_find_port_dr(ibnd_fabric_t * fabric, char *dr_str);
+
 ibnd_node_t *ibnd_find_node_dr(ibnd_fabric_t * fabric, char *dr_str)
 {
-	int i = 0;
-	ibnd_node_t *rc;
-	ib_dr_path_t path;
-
-	if (!fabric) {
-		IBND_DEBUG("fabric parameter NULL\n");
-		return NULL;
-	}
-
-	rc = fabric->from_node;
-
-	if (str2drpath(&path, dr_str, 0, 0) == -1)
-		return NULL;
-
-	for (i = 0; i <= path.cnt; i++) {
-		ibnd_port_t *remote_port = NULL;
-		if (path.p[i] == 0)
-			continue;
-		if (!rc->ports)
-			return NULL;
-
-		remote_port = rc->ports[path.p[i]]->remoteport;
-		if (!remote_port)
-			return NULL;
-
-		rc = remote_port->node;
-	}
-
-	return rc;
+	ibnd_port_t *rc = ibnd_find_port_dr(fabric, dr_str);
+	return rc->node;
 }
 
 void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[])
@@ -479,15 +504,15 @@ ibnd_fabric_t *ibnd_discover_fabric(char * ca_name, int ca_port,
 	int nc = 2;
 	int mc[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
 
+	/* If not specified start from "my" port */
+	if (!from)
+		from = &my_portid;
+
 	if (set_config(&config, cfg)) {
 		IBND_ERROR("Invalid ibnd_config\n");
 		return NULL;
 	}
 
-	/* If not specified start from "my" port */
-	if (!from)
-		from = &my_portid;
-
 	fabric = calloc(1, sizeof(*fabric));
 	if (!fabric) {
 		IBND_ERROR("OOM: failed to calloc ibnd_fabric_t\n");
@@ -499,6 +524,7 @@ ibnd_fabric_t *ibnd_discover_fabric(char * ca_name, int ca_port,
 	memset(&scan.selfportid, 0, sizeof(scan.selfportid));
 	scan.fabric = fabric;
 	scan.cfg = &config;
+	scan.initial_hops = from->drpath.cnt;
 
 	if (smp_engine_init(&engine, ca_name, ca_port, &scan, &config)) {
 		free(fabric);
@@ -521,6 +547,7 @@ ibnd_fabric_t *ibnd_discover_fabric(char * ca_name, int ca_port,
 			goto error;
 
 	fabric->total_mads_used = engine.total_smps;
+	fabric->maxhops_discovered += scan.initial_hops;
 
 	if (group_nodes(fabric))
 		goto error;
@@ -624,3 +651,81 @@ void ibnd_iter_nodes_type(ibnd_fabric_t * fabric, ibnd_iter_node_func_t func,
 	for (cur = list; cur; cur = cur->type_next)
 		func(cur, user_data);
 }
+
+ibnd_port_t *ibnd_find_port_guid(ibnd_fabric_t * fabric, uint64_t guid)
+{
+	int hash = HASHGUID(guid) % HTSZ;
+	ibnd_port_t *port;
+
+	if (!fabric) {
+		IBND_DEBUG("fabric parameter NULL\n");
+		return NULL;
+	}
+
+	for (port = fabric->portstbl[hash]; port; port = port->htnext)
+		if (port->guid == guid)
+			return port;
+
+	return NULL;
+}
+
+ibnd_port_t *ibnd_find_port_dr(ibnd_fabric_t * fabric, char *dr_str)
+{
+	int i = 0;
+	ibnd_node_t *cur_node;
+	ibnd_port_t *rc = NULL;
+	ib_dr_path_t path;
+
+	if (!fabric) {
+		IBND_DEBUG("fabric parameter NULL\n");
+		return NULL;
+	}
+
+	if (!dr_str) {
+		IBND_DEBUG("dr_str parameter NULL\n");
+		return NULL;
+	}
+
+	cur_node = fabric->from_node;
+
+	if (str2drpath(&path, dr_str, 0, 0) == -1)
+		return NULL;
+
+	for (i = 0; i <= path.cnt; i++) {
+		ibnd_port_t *remote_port = NULL;
+		if (path.p[i] == 0)
+			continue;
+		if (!cur_node->ports)
+			return NULL;
+
+		remote_port = cur_node->ports[path.p[i]]->remoteport;
+		if (!remote_port)
+			return NULL;
+
+		rc = remote_port;
+		cur_node = remote_port->node;
+	}
+
+	return rc;
+}
+
+void ibnd_iter_ports(ibnd_fabric_t * fabric, ibnd_iter_port_func_t func,
+			void *user_data)
+{
+	int i = 0;
+	ibnd_port_t *cur = NULL;
+
+	if (!fabric) {
+		IBND_DEBUG("fabric parameter NULL\n");
+		return;
+	}
+
+	if (!func) {
+		IBND_DEBUG("func parameter NULL\n");
+		return;
+	}
+
+	for (i = 0; i<HTSZ; i++)
+		for (cur = fabric->portstbl[i]; cur; cur = cur->htnext)
+			func(cur, user_data);
+}
diff --git a/trunk/ulp/libibnetdisc/src/ibnetdisc_cache.c b/trunk/ulp/libibnetdisc/src/ibnetdisc_cache.c
index 5151f63..2690373 100644
--- a/trunk/ulp/libibnetdisc/src/ibnetdisc_cache.c
+++ b/trunk/ulp/libibnetdisc/src/ibnetdisc_cache.c
@@ -326,6 +326,7 @@ static int _load_node(int fd, ibnd_fabric_cache_t * fabric_cache)
 	node = (ibnd_node_t *) malloc(sizeof(ibnd_node_t));
 	if (!node) {
 		IBND_DEBUG("OOM: node\n");
+		free(node_cache);
 		return -1;
 	}
 	memset(node, '\0', sizeof(ibnd_node_t));
@@ -426,6 +427,7 @@ static int _load_port(int fd, ibnd_fabric_cache_t * fabric_cache)
 	port = (ibnd_port_t *) malloc(sizeof(ibnd_port_t));
 	if (!port) {
 		IBND_DEBUG("OOM: port\n");
+		free(port_cache);
 		return -1;
 	}
 	memset(port, '\0', sizeof(ibnd_port_t));
@@ -887,9 +889,20 @@ int ibnd_cache_fabric(ibnd_fabric_t * fabric, const char *file,
 		return -1;
 	}
 
-	if (!stat(file, &statbuf)) {
-		IBND_DEBUG("file '%s' already exists\n", file);
-		return -1;
+	if (!(flags & IBND_CACHE_FABRIC_FLAG_NO_OVERWRITE)) {
+		if (!stat(file, &statbuf)) {
+			if (unlink(file) < 0) {
+				IBND_DEBUG("error removing '%s': %s\n",
+					   file, strerror(errno));
+				return -1;
+			}
+		}
+	}
+	else {
+		if (!stat(file, &statbuf)) {
+			IBND_DEBUG("file '%s' already exists\n", file);
+			return -1;
+		}
 	}
 
 	if ((fd = open(file, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
diff --git a/trunk/ulp/libibnetdisc/src/ibnetdisc_exports.src b/trunk/ulp/libibnetdisc/src/ibnetdisc_exports.src
index 018bd17..776e154 100644
--- a/trunk/ulp/libibnetdisc/src/ibnetdisc_exports.src
+++ b/trunk/ulp/libibnetdisc/src/ibnetdisc_exports.src
@@ -4,6 +4,8 @@ LIBRARY libibnetdisc.dll
 EXPORTS
 		ibnd_discover_fabric;
 		ibnd_destroy_fabric;
+		ibnd_load_fabric;
+		ibnd_cache_fabric;
 		ibnd_find_node_guid;
 		ibnd_find_node_dr;
 		ibnd_is_xsigo_guid;
@@ -14,4 +16,7 @@ EXPORTS
 		ibnd_get_chassis_slot_str;
 		ibnd_iter_nodes;
 		ibnd_iter_nodes_type;
+		ibnd_find_port_guid;
+		ibnd_find_port_dr;
+		ibnd_iter_ports;
 #endif
diff --git a/trunk/ulp/libibnetdisc/src/internal.h b/trunk/ulp/libibnetdisc/src/internal.h
index 3c599ec..80918c4 100644
--- a/trunk/ulp/libibnetdisc/src/internal.h
+++ b/trunk/ulp/libibnetdisc/src/internal.h
@@ -62,6 +62,7 @@ typedef struct ibnd_scan {
 	ibnd_fabric_t *fabric;
 	struct ibnd_config *cfg;
 	struct ibmad_port *ibmad_port;
+	unsigned initial_hops;
 } ibnd_scan_t;
 
 typedef struct ibnd_smp ibnd_smp_t;
diff --git a/trunk/ulp/opensm/user/opensm/osm_helper.c b/trunk/ulp/opensm/user/opensm/osm_helper.c
index 54680da..fcb2597 100644
--- a/trunk/ulp/opensm/user/opensm/osm_helper.c
+++ b/trunk/ulp/opensm/user/opensm/osm_helper.c
@@ -860,7 +860,7 @@ void osm_dump_portinfo_record(IN osm_log_t * p_log,
 			"\t\t\t\tRID\n"
 			"\t\t\t\tEndPortLid..............%u\n"
 			"\t\t\t\tPortNum.................%u\n"
-			"\t\t\t\tReserved................0x%X\n"
+			"\t\t\t\tOptions.................0x%X\n"
 			"\t\t\t\tPortInfo dump:\n"
 			"\t\t\t\tm_key...................0x%016" PRIx64 "\n"
 			"\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"
@@ -894,7 +894,7 @@ void osm_dump_portinfo_record(IN osm_log_t * p_log,
 			"\t\t\t\tsubnet_timeout..........0x%X\n"
 			"\t\t\t\tresp_time_value.........0x%X\n"
 			"\t\t\t\terror_threshold.........0x%X\n",
-			cl_ntoh16(p_pir->lid), p_pir->port_num, p_pir->resv,
+			cl_ntoh16(p_pir->lid), p_pir->port_num, p_pir->options,
 			cl_ntoh64(p_pi->m_key), cl_ntoh64(p_pi->subnet_prefix),
 			cl_ntoh16(p_pi->base_lid),
 			cl_ntoh16(p_pi->master_sm_base_lid),




More information about the ofw mailing list