Skip to content

Commit

Permalink
RDMA/nes: Fix for sending fpdus in order to hardware
Browse files Browse the repository at this point in the history
Locking fix to prevent race conditions. Fpdus (per qp) need to be
forwarded to hardware in the order of their sequence numbers.

Signed-off-by: Tatyana Nikolova <Tatyana.E.Nikolova@intel.com>
Signed-off-by: Donald Wood <Donald.E.Wood@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
  • Loading branch information
Tatyana Nikolova authored and Roland Dreier committed Nov 22, 2012
1 parent bff3976 commit fc8d754
Showing 1 changed file with 10 additions and 13 deletions.
23 changes: 10 additions & 13 deletions drivers/infiniband/hw/nes/nes_mgt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit fc8d754

Please sign in to comment.