From 90a3edd54fabb0fe3623460bffde1a8c4c1a193b Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Sat, 20 Oct 2012 17:51:40 -0500 Subject: [PATCH] RDMA/nes: Fixes for PAU handling Fixes for packed and unaligned fpdu handling Signed-off-by: Tatyana Nikolova --- .../0007-RDMA-nes-Fix-for-pau-hdr_pbase.patch | 23 +++++++ ...08-RDMA-nes-Check-for-empty-skb-list.patch | 51 +++++++++++++++ ...-RDMA-nes-Fix-for-unlinking-NULL-skb.patch | 62 +++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 linux-next-pending/0007-RDMA-nes-Fix-for-pau-hdr_pbase.patch create mode 100644 linux-next-pending/0008-RDMA-nes-Check-for-empty-skb-list.patch create mode 100644 linux-next-pending/0009-RDMA-nes-Fix-for-unlinking-NULL-skb.patch 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 index 0000000..706deff --- /dev/null +++ b/linux-next-pending/0007-RDMA-nes-Fix-for-pau-hdr_pbase.patch @@ -0,0 +1,23 @@ +Fix for incorrect hdr_pbase when forwarding fpdus to hardware + +Signed-off-by: Tatyana Nikolova +--- + 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 index 0000000..d42b67a --- /dev/null +++ b/linux-next-pending/0008-RDMA-nes-Check-for-empty-skb-list.patch @@ -0,0 +1,51 @@ +Fix for unlinking skbs from empty list + +Signed-off-by: Tatyana Nikolova +--- + 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 index 0000000..f2250fd --- /dev/null +++ b/linux-next-pending/0009-RDMA-nes-Fix-for-unlinking-NULL-skb.patch @@ -0,0 +1,62 @@ +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 + -- 2.41.0