(rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA);
 }
 
+static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr,
+                                    struct ib_mad_recv_wc *rwc)
+{
+       return ((struct ib_mad *)(wr->send_buf.mad))->mad_hdr.mgmt_class ==
+               rwc->recv_buf.mad->mad_hdr.mgmt_class;
+}
+
+static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr,
+                                  struct ib_mad_recv_wc *rwc )
+{
+       struct ib_ah_attr attr;
+       u8 send_resp, rcv_resp;
+
+       send_resp = ((struct ib_mad *)(wr->send_buf.mad))->
+                    mad_hdr.method & IB_MGMT_METHOD_RESP;
+       rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP;
+
+       if (!send_resp && rcv_resp)
+               /* is request/response. GID/LIDs are both local (same). */
+               return 1;
+
+       if (send_resp == rcv_resp)
+               /* both requests, or both responses. GIDs different */
+               return 0;
+
+       if (ib_query_ah(wr->send_buf.ah, &attr))
+               /* Assume not equal, to avoid false positives. */
+               return 0;
+
+       if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH))
+               return attr.dlid == rwc->wc->slid;
+       else if ((attr.ah_flags & IB_AH_GRH) &&
+                (rwc->wc->wc_flags & IB_WC_GRH))
+               return memcmp(attr.grh.dgid.raw,
+                             rwc->recv_buf.grh->sgid.raw, 16) == 0;
+       else
+               /* one has GID, other does not.  Assume different */
+               return 0;
+}
 struct ib_mad_send_wr_private*
-ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid)
+ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv,
+                struct ib_mad_recv_wc *mad_recv_wc)
 {
        struct ib_mad_send_wr_private *mad_send_wr;
+       struct ib_mad *mad;
+
+       mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad;
 
        list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
                            agent_list) {
-               if (mad_send_wr->tid == tid)
+               if ((mad_send_wr->tid == mad->mad_hdr.tid) &&
+                   rcv_has_same_class(mad_send_wr, mad_recv_wc) &&
+                   rcv_has_same_gid(mad_send_wr, mad_recv_wc))
                        return mad_send_wr;
        }
 
        list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
                            agent_list) {
                if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
-                   mad_send_wr->tid == tid && mad_send_wr->timeout) {
+                   mad_send_wr->tid == mad->mad_hdr.tid &&
+                   mad_send_wr->timeout &&
+                   rcv_has_same_class(mad_send_wr, mad_recv_wc) &&
+                   rcv_has_same_gid(mad_send_wr, mad_recv_wc)) {
                        /* Verify request has not been canceled */
                        return (mad_send_wr->status == IB_WC_SUCCESS) ?
                                mad_send_wr : NULL;
        struct ib_mad_send_wr_private *mad_send_wr;
        struct ib_mad_send_wc mad_send_wc;
        unsigned long flags;
-       __be64 tid;
 
        INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
        list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
 
        /* Complete corresponding request */
        if (response_mad(mad_recv_wc->recv_buf.mad)) {
-               tid = mad_recv_wc->recv_buf.mad->mad_hdr.tid;
                spin_lock_irqsave(&mad_agent_priv->lock, flags);
-               mad_send_wr = ib_find_send_mad(mad_agent_priv, tid);
+               mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc);
                if (!mad_send_wr) {
                        spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
                        ib_free_recv_mad(mad_recv_wc);
 
        return ib_send_mad(mad_send_wr);
 }
 
-static void abort_send(struct ib_mad_agent_private *agent, __be64 tid,
-                      u8 rmpp_status)
+static void abort_send(struct ib_mad_agent_private *agent,
+                      struct ib_mad_recv_wc *mad_recv_wc, u8 rmpp_status)
 {
        struct ib_mad_send_wr_private *mad_send_wr;
        struct ib_mad_send_wc wc;
        unsigned long flags;
 
        spin_lock_irqsave(&agent->lock, flags);
-       mad_send_wr = ib_find_send_mad(agent, tid);
+       mad_send_wr = ib_find_send_mad(agent, mad_recv_wc);
        if (!mad_send_wr)
                goto out;       /* Unmatched send */
 
 
        rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
        if (rmpp_mad->rmpp_hdr.rmpp_status) {
-               abort_send(agent, rmpp_mad->mad_hdr.tid,
-                          IB_MGMT_RMPP_STATUS_BAD_STATUS);
+               abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
                nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
                return;
        }
        seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num);
        newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
        if (newwin < seg_num) {
-               abort_send(agent, rmpp_mad->mad_hdr.tid,
-                          IB_MGMT_RMPP_STATUS_W2S);
+               abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S);
                nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S);
                return;
        }
 
        spin_lock_irqsave(&agent->lock, flags);
-       mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid);
+       mad_send_wr = ib_find_send_mad(agent, mad_recv_wc);
        if (!mad_send_wr)
                goto out;       /* Unmatched ACK */
 
        if (seg_num > mad_send_wr->send_buf.seg_count ||
            seg_num > mad_send_wr->newwin) {
                spin_unlock_irqrestore(&agent->lock, flags);
-               abort_send(agent, rmpp_mad->mad_hdr.tid,
-                          IB_MGMT_RMPP_STATUS_S2B);
+               abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B);
                nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B);
                return;
        }
        rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
 
        if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) {
-               abort_send(agent, rmpp_mad->mad_hdr.tid,
-                          IB_MGMT_RMPP_STATUS_BAD_STATUS);
+               abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
                nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
        } else
-               abort_send(agent, rmpp_mad->mad_hdr.tid,
-                          rmpp_mad->rmpp_hdr.rmpp_status);
+               abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status);
 }
 
 static void process_rmpp_abort(struct ib_mad_agent_private *agent,
 
        if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN ||
            rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) {
-               abort_send(agent, rmpp_mad->mad_hdr.tid,
-                          IB_MGMT_RMPP_STATUS_BAD_STATUS);
+               abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
                nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
        } else
-               abort_send(agent, rmpp_mad->mad_hdr.tid,
-                          rmpp_mad->rmpp_hdr.rmpp_status);
+               abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status);
 }
 
 struct ib_mad_recv_wc *
                return mad_recv_wc;
 
        if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) {
-               abort_send(agent, rmpp_mad->mad_hdr.tid,
-                          IB_MGMT_RMPP_STATUS_UNV);
+               abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV);
                nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV);
                goto out;
        }
                process_rmpp_abort(agent, mad_recv_wc);
                break;
        default:
-               abort_send(agent, rmpp_mad->mad_hdr.tid,
-                          IB_MGMT_RMPP_STATUS_BADT);
+               abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT);
                nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT);
                break;
        }