[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