Locking fix to prevent race conditions. Fpdus (per qp) need to be forwarded 
to hardware in the order of their sequence numbers.

Signed-off-by: Tatyana Nikolova <[email protected]>
Signed-off-by: Donald Wood <[email protected]>
---
 drivers/infiniband/hw/nes/nes_mgt.c |   23 ++++++++++-------------
 1 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/drivers/infiniband/hw/nes/nes_mgt.c 
b/drivers/infiniband/hw/nes/nes_mgt.c
index 2d710e1..07cbf86 100644
--- a/drivers/infiniband/hw/nes/nes_mgt.c
+++ b/drivers/infiniband/hw/nes/nes_mgt.c
@@ -247,7 +247,6 @@ static int get_fpdu_info(struct nes_device *nesdev, struct 
nes_qp *nesqp,
        struct nes_rskb_cb *cb;
        struct pau_fpdu_info *fpdu_info = NULL;
        struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
-       unsigned long flags;
        u32 fpdu_len = 0;
        u32 tmp_len;
        int frag_cnt = 0;
@@ -262,12 +261,10 @@ static int get_fpdu_info(struct nes_device *nesdev, 
struct nes_qp *nesqp,
 
        *pau_fpdu_info = NULL;
 
-       spin_lock_irqsave(&nesqp->pau_lock, flags);
        skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, 
&wnd, &fin_rcvd, &rst_rcvd);
-       if (!skb) {
-               spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+       if (!skb)
                goto out;
-       }
+
        cb = (struct nes_rskb_cb *)&skb->cb[0];
        if (skb->len) {
                fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING;
@@ -292,10 +289,9 @@ static int get_fpdu_info(struct nes_device *nesdev, struct 
nes_qp *nesqp,
 
                        skb = nes_get_next_skb(nesdev, nesqp, skb,
                                               nesqp->pau_rcv_nxt + frag_tot, 
&ack, &wnd, &fin_rcvd, &rst_rcvd);
-                       if (!skb) {
-                               spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+                       if (!skb)
                                goto out;
-                       } else if (rst_rcvd) {
+                       if (rst_rcvd) {
                                /* rst received in the middle of fpdu */
                                for (; i >= 0; i--) {
                                        skb_unlink(frags[i].skb, 
&nesqp->pau_list);
@@ -322,8 +318,6 @@ static int get_fpdu_info(struct nes_device *nesdev, struct 
nes_qp *nesqp,
                frag_cnt = 1;
        }
 
-       spin_unlock_irqrestore(&nesqp->pau_lock, flags);
-
        /* Found one */
        fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC);
        if (fpdu_info == NULL) {
@@ -385,10 +379,8 @@ static int get_fpdu_info(struct nes_device *nesdev, struct 
nes_qp *nesqp,
 
                if (frags[i].skb->len == 0) {
                        /* Pull skb off the list - it will be freed in the 
callback */
-                       spin_lock_irqsave(&nesqp->pau_lock, flags);
                        if (!skb_queue_empty(&nesqp->pau_list))
                                skb_unlink(frags[i].skb, &nesqp->pau_list);
-                       spin_unlock_irqrestore(&nesqp->pau_lock, flags);
                } else {
                        /* Last skb still has data so update the seq */
                        iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
@@ -417,14 +409,18 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct 
nes_qp *nesqp)
        struct pau_fpdu_info *fpdu_info;
        struct nes_hw_cqp_wqe *cqp_wqe;
        struct nes_cqp_request *cqp_request;
+       unsigned long flags;
        u64 u64tmp;
        u32 u32tmp;
        int rc;
 
        while (1) {
+               spin_lock_irqsave(&nesqp->pau_lock, flags);
                rc = get_fpdu_info(nesdev, nesqp, &fpdu_info);
-               if (fpdu_info == NULL)
+               if (rc || (fpdu_info == NULL)) {
+                       spin_unlock_irqrestore(&nesqp->pau_lock, flags);
                        return rc;
+               }
 
                cqp_request = fpdu_info->cqp_request;
                cqp_wqe = &cqp_request->cqp_wqe;
@@ -478,6 +474,7 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct 
nes_qp *nesqp)
 
                atomic_set(&cqp_request->refcount, 1);
                nes_post_cqp_request(nesdev, cqp_request);
+               spin_unlock_irqrestore(&nesqp->pau_lock, flags);
        }
 
        return 0;
-- 
1.7.4.2

--
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