[ewg] [PATCH] RDMA/nes: Locking fix to prevent race conditions

Tatyana Nikolova Tatyana.E.Nikolova at intel.com
Fri Nov 2 13:38:21 PDT 2012


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 at intel.com>
---
 .../0009-RDMA-nes-Fix-for-unlinking-NULL-skb.patch |   62 ------------
 .../0009-RDMA-nes-Forward-fpdus-inorder.patch      |  100 ++++++++++++++++++++
 2 files changed, 100 insertions(+), 62 deletions(-)
 delete mode 100644 linux-next-pending/0009-RDMA-nes-Fix-for-unlinking-NULL-skb.patch
 create mode 100644 linux-next-pending/0009-RDMA-nes-Forward-fpdus-inorder.patch

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
index f2250fd..0000000
--- a/linux-next-pending/0009-RDMA-nes-Fix-for-unlinking-NULL-skb.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-Fix for unlinking NULL skb because of race condition
-
-Signed-off-by: Tatyana Nikolova <Tatyana.E.Nikolova at 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
index 0000000..a2a3a4f
--- /dev/null
+++ b/linux-next-pending/0009-RDMA-nes-Forward-fpdus-inorder.patch
@@ -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 at intel.com>
+Signed-off-by: Donald Wood <Donald.E.Wood at 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
+
-- 
1.7.1




More information about the ewg mailing list