diff options
Diffstat (limited to 'drivers/infiniband/hw/nes/nes_mgt.c')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_mgt.c | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c index 3ba7be369452..416645259b0f 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 | |||
210 | } | 210 | } |
211 | 211 | ||
212 | while (1) { | 212 | while (1) { |
213 | if (skb_queue_empty(&nesqp->pau_list)) | ||
214 | goto out; | ||
215 | |||
213 | seq = nes_get_seq(skb, ack, wnd, fin_rcvd, rst_rcvd); | 216 | seq = nes_get_seq(skb, ack, wnd, fin_rcvd, rst_rcvd); |
214 | if (seq == nextseq) { | 217 | if (seq == nextseq) { |
215 | if (skb->len || processacks) | 218 | if (skb->len || processacks) |
@@ -218,14 +221,13 @@ static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp | |||
218 | goto out; | 221 | goto out; |
219 | } | 222 | } |
220 | 223 | ||
221 | if (skb->next == (struct sk_buff *)&nesqp->pau_list) | ||
222 | goto out; | ||
223 | |||
224 | old_skb = skb; | 224 | old_skb = skb; |
225 | skb = skb->next; | 225 | skb = skb->next; |
226 | skb_unlink(old_skb, &nesqp->pau_list); | 226 | skb_unlink(old_skb, &nesqp->pau_list); |
227 | nes_mgt_free_skb(nesdev, old_skb, PCI_DMA_TODEVICE); | 227 | nes_mgt_free_skb(nesdev, old_skb, PCI_DMA_TODEVICE); |
228 | nes_rem_ref_cm_node(nesqp->cm_node); | 228 | nes_rem_ref_cm_node(nesqp->cm_node); |
229 | if (skb == (struct sk_buff *)&nesqp->pau_list) | ||
230 | goto out; | ||
229 | } | 231 | } |
230 | return skb; | 232 | return skb; |
231 | 233 | ||
@@ -245,7 +247,6 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp, | |||
245 | struct nes_rskb_cb *cb; | 247 | struct nes_rskb_cb *cb; |
246 | struct pau_fpdu_info *fpdu_info = NULL; | 248 | struct pau_fpdu_info *fpdu_info = NULL; |
247 | struct pau_fpdu_frag frags[MAX_FPDU_FRAGS]; | 249 | struct pau_fpdu_frag frags[MAX_FPDU_FRAGS]; |
248 | unsigned long flags; | ||
249 | u32 fpdu_len = 0; | 250 | u32 fpdu_len = 0; |
250 | u32 tmp_len; | 251 | u32 tmp_len; |
251 | int frag_cnt = 0; | 252 | int frag_cnt = 0; |
@@ -260,12 +261,10 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp, | |||
260 | 261 | ||
261 | *pau_fpdu_info = NULL; | 262 | *pau_fpdu_info = NULL; |
262 | 263 | ||
263 | spin_lock_irqsave(&nesqp->pau_lock, flags); | ||
264 | skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, &wnd, &fin_rcvd, &rst_rcvd); | 264 | skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, &wnd, &fin_rcvd, &rst_rcvd); |
265 | if (!skb) { | 265 | if (!skb) |
266 | spin_unlock_irqrestore(&nesqp->pau_lock, flags); | ||
267 | goto out; | 266 | goto out; |
268 | } | 267 | |
269 | cb = (struct nes_rskb_cb *)&skb->cb[0]; | 268 | cb = (struct nes_rskb_cb *)&skb->cb[0]; |
270 | if (skb->len) { | 269 | if (skb->len) { |
271 | fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING; | 270 | fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING; |
@@ -290,10 +289,9 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp, | |||
290 | 289 | ||
291 | skb = nes_get_next_skb(nesdev, nesqp, skb, | 290 | skb = nes_get_next_skb(nesdev, nesqp, skb, |
292 | nesqp->pau_rcv_nxt + frag_tot, &ack, &wnd, &fin_rcvd, &rst_rcvd); | 291 | nesqp->pau_rcv_nxt + frag_tot, &ack, &wnd, &fin_rcvd, &rst_rcvd); |
293 | if (!skb) { | 292 | if (!skb) |
294 | spin_unlock_irqrestore(&nesqp->pau_lock, flags); | ||
295 | goto out; | 293 | goto out; |
296 | } else if (rst_rcvd) { | 294 | if (rst_rcvd) { |
297 | /* rst received in the middle of fpdu */ | 295 | /* rst received in the middle of fpdu */ |
298 | for (; i >= 0; i--) { | 296 | for (; i >= 0; i--) { |
299 | skb_unlink(frags[i].skb, &nesqp->pau_list); | 297 | skb_unlink(frags[i].skb, &nesqp->pau_list); |
@@ -320,8 +318,6 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp, | |||
320 | frag_cnt = 1; | 318 | frag_cnt = 1; |
321 | } | 319 | } |
322 | 320 | ||
323 | spin_unlock_irqrestore(&nesqp->pau_lock, flags); | ||
324 | |||
325 | /* Found one */ | 321 | /* Found one */ |
326 | fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC); | 322 | fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC); |
327 | if (fpdu_info == NULL) { | 323 | if (fpdu_info == NULL) { |
@@ -383,9 +379,8 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp, | |||
383 | 379 | ||
384 | if (frags[i].skb->len == 0) { | 380 | if (frags[i].skb->len == 0) { |
385 | /* Pull skb off the list - it will be freed in the callback */ | 381 | /* Pull skb off the list - it will be freed in the callback */ |
386 | spin_lock_irqsave(&nesqp->pau_lock, flags); | 382 | if (!skb_queue_empty(&nesqp->pau_list)) |
387 | skb_unlink(frags[i].skb, &nesqp->pau_list); | 383 | skb_unlink(frags[i].skb, &nesqp->pau_list); |
388 | spin_unlock_irqrestore(&nesqp->pau_lock, flags); | ||
389 | } else { | 384 | } else { |
390 | /* Last skb still has data so update the seq */ | 385 | /* Last skb still has data so update the seq */ |
391 | iph = (struct iphdr *)(cb->data_start + ETH_HLEN); | 386 | iph = (struct iphdr *)(cb->data_start + ETH_HLEN); |
@@ -414,14 +409,18 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp) | |||
414 | struct pau_fpdu_info *fpdu_info; | 409 | struct pau_fpdu_info *fpdu_info; |
415 | struct nes_hw_cqp_wqe *cqp_wqe; | 410 | struct nes_hw_cqp_wqe *cqp_wqe; |
416 | struct nes_cqp_request *cqp_request; | 411 | struct nes_cqp_request *cqp_request; |
412 | unsigned long flags; | ||
417 | u64 u64tmp; | 413 | u64 u64tmp; |
418 | u32 u32tmp; | 414 | u32 u32tmp; |
419 | int rc; | 415 | int rc; |
420 | 416 | ||
421 | while (1) { | 417 | while (1) { |
418 | spin_lock_irqsave(&nesqp->pau_lock, flags); | ||
422 | rc = get_fpdu_info(nesdev, nesqp, &fpdu_info); | 419 | rc = get_fpdu_info(nesdev, nesqp, &fpdu_info); |
423 | if (fpdu_info == NULL) | 420 | if (rc || (fpdu_info == NULL)) { |
421 | spin_unlock_irqrestore(&nesqp->pau_lock, flags); | ||
424 | return rc; | 422 | return rc; |
423 | } | ||
425 | 424 | ||
426 | cqp_request = fpdu_info->cqp_request; | 425 | cqp_request = fpdu_info->cqp_request; |
427 | cqp_wqe = &cqp_request->cqp_wqe; | 426 | cqp_wqe = &cqp_request->cqp_wqe; |
@@ -447,7 +446,7 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp) | |||
447 | set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX, | 446 | set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX, |
448 | lower_32_bits(u64tmp)); | 447 | lower_32_bits(u64tmp)); |
449 | set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_HIGH_IDX, | 448 | set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_HIGH_IDX, |
450 | upper_32_bits(u64tmp >> 32)); | 449 | upper_32_bits(u64tmp)); |
451 | 450 | ||
452 | set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX, | 451 | set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX, |
453 | lower_32_bits(fpdu_info->frags[0].physaddr)); | 452 | lower_32_bits(fpdu_info->frags[0].physaddr)); |
@@ -475,6 +474,7 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp) | |||
475 | 474 | ||
476 | atomic_set(&cqp_request->refcount, 1); | 475 | atomic_set(&cqp_request->refcount, 1); |
477 | nes_post_cqp_request(nesdev, cqp_request); | 476 | nes_post_cqp_request(nesdev, cqp_request); |
477 | spin_unlock_irqrestore(&nesqp->pau_lock, flags); | ||
478 | } | 478 | } |
479 | 479 | ||
480 | return 0; | 480 | return 0; |
@@ -649,11 +649,9 @@ static void nes_chg_qh_handler(struct nes_device *nesdev, struct nes_cqp_request | |||
649 | nesqp = qh_chg->nesqp; | 649 | nesqp = qh_chg->nesqp; |
650 | 650 | ||
651 | /* Should we handle the bad completion */ | 651 | /* Should we handle the bad completion */ |
652 | if (cqp_request->major_code) { | 652 | if (cqp_request->major_code) |
653 | printk(KERN_ERR PFX "Invalid cqp_request major_code=0x%x\n", | 653 | WARN(1, PFX "Invalid cqp_request major_code=0x%x\n", |
654 | cqp_request->major_code); | 654 | cqp_request->major_code); |
655 | WARN_ON(1); | ||
656 | } | ||
657 | 655 | ||
658 | switch (nesqp->pau_state) { | 656 | switch (nesqp->pau_state) { |
659 | case PAU_DEL_QH: | 657 | case PAU_DEL_QH: |