Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=dd5190b6be0f3e27b6a4933a6a6d2d59957fc748
Commit:     dd5190b6be0f3e27b6a4933a6a6d2d59957fc748
Parent:     c7e29ff11f23ec78b3caf691789c2b791bb596bf
Author:     Ralph Campbell <[EMAIL PROTECTED]>
AuthorDate: Thu Mar 15 14:45:00 2007 -0700
Committer:  Roland Dreier <[EMAIL PROTECTED]>
CommitDate: Wed Apr 18 20:20:57 2007 -0700

    IB/ipath: Fix RDMA reads of length zero and error handling
    
    Fix RDMA read response length checking for RDMA_READ_RESPONSE_ONLY to
    allow a zero length response.  RDMA read responses which don't match
    the expected length or occur in response to some other operation
    should generate a completion queue error (see table 56, ch. 9.9.2.3 in
    the IB spec).
    
    Signed-off-by: Bryan O'Sullivan <[EMAIL PROTECTED]>
    Signed-off-by: Roland Dreier <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ipath/ipath_rc.c |   63 ++++++++++++++++++++++----------
 1 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c 
b/drivers/infiniband/hw/ipath/ipath_rc.c
index d6aa14a..b4b88d0 100644
--- a/drivers/infiniband/hw/ipath/ipath_rc.c
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -1136,7 +1136,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev 
*dev,
                        goto ack_done;
                hdrsize += 4;
                if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ))
-                       goto ack_done;
+                       goto ack_op_err;
                /*
                 * If this is a response to a resent RDMA read, we
                 * have to be careful to copy the data to the right
@@ -1154,12 +1154,12 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev 
*dev,
                        goto ack_done;
                }
                if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ))
-                       goto ack_done;
+                       goto ack_op_err;
        read_middle:
                if (unlikely(tlen != (hdrsize + pmtu + 4)))
-                       goto ack_done;
+                       goto ack_len_err;
                if (unlikely(pmtu >= qp->s_rdma_read_len))
-                       goto ack_done;
+                       goto ack_len_err;
 
                /* We got a response so update the timeout. */
                spin_lock(&dev->pending_lock);
@@ -1184,12 +1184,20 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev 
*dev,
                        goto ack_done;
                }
                if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ))
-                       goto ack_done;
+                       goto ack_op_err;
+               /* Get the number of bytes the message was padded by. */
+               pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+               /*
+                * Check that the data size is >= 0 && <= pmtu.
+                * Remember to account for the AETH header (4) and
+                * ICRC (4).
+                */
+               if (unlikely(tlen < (hdrsize + pad + 8)))
+                       goto ack_len_err;
                /*
                 * If this is a response to a resent RDMA read, we
                 * have to be careful to copy the data to the right
                 * location.
-                * XXX should check PSN and wqe opcode first.
                 */
                qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge,
                                                  wqe, psn, pmtu);
@@ -1203,26 +1211,20 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev 
*dev,
                        goto ack_done;
                }
                if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ))
-                       goto ack_done;
-       read_last:
-               /*
-                * Get the number of bytes the message was padded by.
-                */
+                       goto ack_op_err;
+               /* Get the number of bytes the message was padded by. */
                pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
                /*
                 * Check that the data size is >= 1 && <= pmtu.
                 * Remember to account for the AETH header (4) and
                 * ICRC (4).
                 */
-               if (unlikely(tlen <= (hdrsize + pad + 8))) {
-                       /* XXX Need to generate an error CQ entry. */
-                       goto ack_done;
-               }
+               if (unlikely(tlen <= (hdrsize + pad + 8)))
+                       goto ack_len_err;
+       read_last:
                tlen -= hdrsize + pad + 8;
-               if (unlikely(tlen != qp->s_rdma_read_len)) {
-                       /* XXX Need to generate an error CQ entry. */
-                       goto ack_done;
-               }
+               if (unlikely(tlen != qp->s_rdma_read_len))
+                       goto ack_len_err;
                if (!header_in_data)
                        aeth = be32_to_cpu(ohdr->u.aeth);
                else {
@@ -1236,6 +1238,29 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev 
*dev,
 
 ack_done:
        spin_unlock_irqrestore(&qp->s_lock, flags);
+       goto bail;
+
+ack_op_err:
+       wc.status = IB_WC_LOC_QP_OP_ERR;
+       goto ack_err;
+
+ack_len_err:
+       wc.status = IB_WC_LOC_LEN_ERR;
+ack_err:
+       wc.wr_id = wqe->wr.wr_id;
+       wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+       wc.vendor_err = 0;
+       wc.byte_len = 0;
+       wc.imm_data = 0;
+       wc.qp = &qp->ibqp;
+       wc.src_qp = qp->remote_qpn;
+       wc.wc_flags = 0;
+       wc.pkey_index = 0;
+       wc.slid = qp->remote_ah_attr.dlid;
+       wc.sl = qp->remote_ah_attr.sl;
+       wc.dlid_path_bits = 0;
+       wc.port_num = 0;
+       ipath_sqerror_qp(qp, &wc);
 bail:
        return;
 }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to