]> git.openfabrics.org - ~emulex/compat-rdma.git/commitdiff
RDMA/nes: Fixes for PAU handling
authorTatyana Nikolova <Tatyana.E.Nikolova@intel.com>
Sat, 20 Oct 2012 22:51:40 +0000 (17:51 -0500)
committerVladimir Sokolovsky <vlad@mellanox.com>
Mon, 22 Oct 2012 11:42:06 +0000 (13:42 +0200)
Fixes for packed and unaligned fpdu handling

Signed-off-by: Tatyana Nikolova <Tatyana.E.Nikolova@intel.com>
linux-next-pending/0007-RDMA-nes-Fix-for-pau-hdr_pbase.patch [new file with mode: 0644]
linux-next-pending/0008-RDMA-nes-Check-for-empty-skb-list.patch [new file with mode: 0644]
linux-next-pending/0009-RDMA-nes-Fix-for-unlinking-NULL-skb.patch [new file with mode: 0644]

diff --git a/linux-next-pending/0007-RDMA-nes-Fix-for-pau-hdr_pbase.patch b/linux-next-pending/0007-RDMA-nes-Fix-for-pau-hdr_pbase.patch
new file mode 100644 (file)
index 0000000..706deff
--- /dev/null
@@ -0,0 +1,23 @@
+Fix for incorrect hdr_pbase when forwarding fpdus to hardware 
+
+Signed-off-by: Tatyana Nikolova <Tatyana.E.Nikolova@intel.com>
+---
+ drivers/infiniband/hw/nes/nes_mgt.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
+index 3ba7be3..8cf74fd 100644
+--- a/drivers/infiniband/hw/nes/nes_mgt.c
++++ b/drivers/infiniband/hw/nes/nes_mgt.c
+@@ -447,7 +447,7 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+               set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX,
+                                   lower_32_bits(u64tmp));
+               set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_HIGH_IDX,
+-                                  upper_32_bits(u64tmp >> 32));
++                                  upper_32_bits(u64tmp));
+               set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
+                                   lower_32_bits(fpdu_info->frags[0].physaddr));
+-- 
+1.7.4.2
+
diff --git a/linux-next-pending/0008-RDMA-nes-Check-for-empty-skb-list.patch b/linux-next-pending/0008-RDMA-nes-Check-for-empty-skb-list.patch
new file mode 100644 (file)
index 0000000..d42b67a
--- /dev/null
@@ -0,0 +1,51 @@
+Fix for unlinking skbs from empty list
+
+Signed-off-by: Tatyana Nikolova <Tatyana.E.Nikolova@intel.com>
+---
+ drivers/infiniband/hw/nes/nes_mgt.c |   11 +++++++----
+ 1 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
+index 8cf74fd..2d710e1 100644
+--- a/drivers/infiniband/hw/nes/nes_mgt.c
++++ b/drivers/infiniband/hw/nes/nes_mgt.c
+@@ -210,6 +210,9 @@ static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp
+       }
+       while (1) {
++              if (skb_queue_empty(&nesqp->pau_list))
++                      goto out;
++
+               seq = nes_get_seq(skb, ack, wnd, fin_rcvd, rst_rcvd);
+               if (seq == nextseq) {
+                       if (skb->len || processacks)
+@@ -218,14 +221,13 @@ static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp
+                       goto out;
+               }
+-              if (skb->next == (struct sk_buff *)&nesqp->pau_list)
+-                      goto out;
+-
+               old_skb = skb;
+               skb = skb->next;
+               skb_unlink(old_skb, &nesqp->pau_list);
+               nes_mgt_free_skb(nesdev, old_skb, PCI_DMA_TODEVICE);
+               nes_rem_ref_cm_node(nesqp->cm_node);
++              if (skb == (struct sk_buff *)&nesqp->pau_list)
++                      goto out;
+       }
+       return skb;
+@@ -384,7 +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);
+-                      skb_unlink(frags[i].skb, &nesqp->pau_list);
++                      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 */
+-- 
+1.7.4.2
+
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
new file mode 100644 (file)
index 0000000..f2250fd
--- /dev/null
@@ -0,0 +1,62 @@
+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
+