]> git.openfabrics.org - ~emulex/for-vlad/old/compat-rdma.git/commitdiff
RDMA/nes: Locking fix to prevent race conditions
authorTatyana Nikolova <Tatyana.E.Nikolova@intel.com>
Fri, 2 Nov 2012 20:38:21 +0000 (15:38 -0500)
committerVladimir Sokolovsky <vlad@mellanox.com>
Sun, 4 Nov 2012 08:47:51 +0000 (10:47 +0200)
RDMA/nes: Replace 0009-RDMA-nes-Fix-for-unlinking-NULL-skb.patch with 0009-RDMA-nes-Forward-fpdus-inorder.patch
Locking fix to prevent race conditions.
It forces all fpdus per QP to be forwarded to hardware in order of their tcp sequence numbers.

Signed-off-by: Tatyana Nikolova <Tatyana.E.Nikolova@intel.com>
linux-next-pending/0009-RDMA-nes-Fix-for-unlinking-NULL-skb.patch [deleted file]
linux-next-pending/0009-RDMA-nes-Forward-fpdus-inorder.patch [new file with mode: 0644]

diff --git a/linux-next-pending/0009-RDMA-nes-Fix-for-unlinking-NULL-skb.patch b/linux-next-pending/0009-RDMA-nes-Fix-for-unlinking-NULL-skb.patch
deleted file mode 100644 (file)
index f2250fd..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-Fix for unlinking NULL skb because of race condition
-
-Signed-off-by: Tatyana Nikolova <Tatyana.E.Nikolova@intel.com>
----
- drivers/infiniband/hw/nes/nes_mgt.c |    8 ++++----
- 1 files changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
-index 2d710e1..9d0fd2b 100644
---- a/drivers/infiniband/hw/nes/nes_mgt.c
-+++ b/drivers/infiniband/hw/nes/nes_mgt.c
-@@ -322,11 +322,10 @@ 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) {
-+              spin_unlock_irqrestore(&nesqp->pau_lock, flags);
-               nes_debug(NES_DBG_PAU, "Failed to alloc a fpdu_info.\n");
-               rc = -ENOMEM;
-               goto out;
-@@ -334,6 +333,7 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
-       fpdu_info->cqp_request = nes_get_cqp_request(nesdev);
-       if (fpdu_info->cqp_request == NULL) {
-+              spin_unlock_irqrestore(&nesqp->pau_lock, flags);
-               nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
-               rc = -ENOMEM;
-               goto out;
-@@ -353,6 +353,7 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
-               fpdu_info->hdr_vbase = pci_alloc_consistent(nesdev->pcidev,
-                                                           fpdu_info->hdr_len, &fpdu_info->hdr_pbase);
-               if (!fpdu_info->hdr_vbase) {
-+                      spin_unlock_irqrestore(&nesqp->pau_lock, flags);
-                       nes_debug(NES_DBG_PAU, "Unable to allocate memory for pau first frag\n");
-                       rc = -ENOMEM;
-                       goto out;
-@@ -385,10 +386,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);
-@@ -396,6 +395,7 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
-                       tcph->seq = cpu_to_be32(nesqp->pau_rcv_nxt);
-               }
-       }
-+      spin_unlock_irqrestore(&nesqp->pau_lock, flags);
- out:
-       if (rc) {
--- 
-1.7.4.2
-
diff --git a/linux-next-pending/0009-RDMA-nes-Forward-fpdus-inorder.patch b/linux-next-pending/0009-RDMA-nes-Forward-fpdus-inorder.patch
new file mode 100644 (file)
index 0000000..e3069a5
--- /dev/null
@@ -0,0 +1,100 @@
+Locking fix to prevent race conditions, forcing fpdus (per qp) to be forwarded 
+to hardware in the order of their sequence numbers.
+
+Signed-off-by: Tatyana Nikolova <Tatyana.E.Nikolova@intel.com>
+Signed-off-by: Donald Wood <Donald.E.Wood@intel.com>
+---
+ 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
+