Add ib_rpc_v1_t structure like ib_rpc_t structure
with additional error field like errno.

mgtclass is only a byte so use next nibble to indicate
rpc version. Original rpc version is 0; now adding version 1.

In mad_rpc code, make sure error is cleared and
in _do_madrpc, set ETIMEDOUT.

error field could also be used to distinguish other errors if needed.

Bump library version accordingly.

Signed-off-by: Hal Rosenstock <[email protected]>
---
diff --git a/include/infiniband/mad.h b/include/infiniband/mad.h
index 5d18ec3..be85ed6 100644
--- a/include/infiniband/mad.h
+++ b/include/infiniband/mad.h
@@ -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
@@ -235,6 +238,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;
diff --git a/libibmad.ver b/libibmad.ver
index 857a99b..9a10851 100644
--- a/libibmad.ver
+++ b/libibmad.ver
@@ -6,4 +6,4 @@
 # API_REV - advance on any added API
 # RUNNING_REV - advance any change to the vendor files
 # AGE - number of backward versions the API still supports
-LIBVERSION=6:2:1
+LIBVERSION=7:2:2
diff --git a/src/mad.c b/src/mad.c
index acd0e85..463c61d 100644
--- a/src/mad.c
+++ b/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/src/rpc.c b/src/rpc.c
index a702046..88e43e7 100644
--- a/src/rpc.c
+++ b/src/rpc.c
@@ -127,7 +127,7 @@ int mad_rpc_class_agent(struct ibmad_port *port, int 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;
@@ -182,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;
 }
@@ -213,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);
@@ -222,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;
@@ -244,6 +252,8 @@ 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) {
@@ -268,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/src/serv.c b/src/serv.c
index df61f25..2e3b7ef 100644
--- a/src/serv.c
+++ b/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");
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to