From 0489dc73b0681da9cf42a455493f5d24406648ef Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Fri, 2 Nov 2012 15:38:21 -0500 Subject: [PATCH] RDMA/nes: Locking fix to prevent race conditions 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 --- ...-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 ---- - 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..e3069a5 --- /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 +Signed-off-by: Donald Wood +--- + 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 + -- 2.41.0