diff options
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_rc.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_rc.c | 151 |
1 files changed, 97 insertions, 54 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index b4b26c3aa613..5b5276a270bc 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c | |||
@@ -92,6 +92,10 @@ static int ipath_make_rc_ack(struct ipath_ibdev *dev, struct ipath_qp *qp, | |||
92 | u32 bth0; | 92 | u32 bth0; |
93 | u32 bth2; | 93 | u32 bth2; |
94 | 94 | ||
95 | /* Don't send an ACK if we aren't supposed to. */ | ||
96 | if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) | ||
97 | goto bail; | ||
98 | |||
95 | /* header size in 32-bit words LRH+BTH = (8+12)/4. */ | 99 | /* header size in 32-bit words LRH+BTH = (8+12)/4. */ |
96 | hwords = 5; | 100 | hwords = 5; |
97 | 101 | ||
@@ -238,14 +242,25 @@ int ipath_make_rc_req(struct ipath_qp *qp) | |||
238 | ipath_make_rc_ack(dev, qp, ohdr, pmtu)) | 242 | ipath_make_rc_ack(dev, qp, ohdr, pmtu)) |
239 | goto done; | 243 | goto done; |
240 | 244 | ||
241 | if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) || | 245 | if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) { |
242 | qp->s_rnr_timeout || qp->s_wait_credit) | 246 | if (!(ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND)) |
243 | goto bail; | 247 | goto bail; |
248 | /* We are in the error state, flush the work request. */ | ||
249 | if (qp->s_last == qp->s_head) | ||
250 | goto bail; | ||
251 | /* If DMAs are in progress, we can't flush immediately. */ | ||
252 | if (atomic_read(&qp->s_dma_busy)) { | ||
253 | qp->s_flags |= IPATH_S_WAIT_DMA; | ||
254 | goto bail; | ||
255 | } | ||
256 | wqe = get_swqe_ptr(qp, qp->s_last); | ||
257 | ipath_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR); | ||
258 | goto done; | ||
259 | } | ||
244 | 260 | ||
245 | /* Limit the number of packets sent without an ACK. */ | 261 | /* Leave BUSY set until RNR timeout. */ |
246 | if (ipath_cmp24(qp->s_psn, qp->s_last_psn + IPATH_PSN_CREDIT) > 0) { | 262 | if (qp->s_rnr_timeout) { |
247 | qp->s_wait_credit = 1; | 263 | qp->s_flags |= IPATH_S_WAITING; |
248 | dev->n_rc_stalls++; | ||
249 | goto bail; | 264 | goto bail; |
250 | } | 265 | } |
251 | 266 | ||
@@ -257,6 +272,9 @@ int ipath_make_rc_req(struct ipath_qp *qp) | |||
257 | wqe = get_swqe_ptr(qp, qp->s_cur); | 272 | wqe = get_swqe_ptr(qp, qp->s_cur); |
258 | switch (qp->s_state) { | 273 | switch (qp->s_state) { |
259 | default: | 274 | default: |
275 | if (!(ib_ipath_state_ops[qp->state] & | ||
276 | IPATH_PROCESS_NEXT_SEND_OK)) | ||
277 | goto bail; | ||
260 | /* | 278 | /* |
261 | * Resend an old request or start a new one. | 279 | * Resend an old request or start a new one. |
262 | * | 280 | * |
@@ -294,8 +312,10 @@ int ipath_make_rc_req(struct ipath_qp *qp) | |||
294 | case IB_WR_SEND_WITH_IMM: | 312 | case IB_WR_SEND_WITH_IMM: |
295 | /* If no credit, return. */ | 313 | /* If no credit, return. */ |
296 | if (qp->s_lsn != (u32) -1 && | 314 | if (qp->s_lsn != (u32) -1 && |
297 | ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0) | 315 | ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0) { |
316 | qp->s_flags |= IPATH_S_WAIT_SSN_CREDIT; | ||
298 | goto bail; | 317 | goto bail; |
318 | } | ||
299 | wqe->lpsn = wqe->psn; | 319 | wqe->lpsn = wqe->psn; |
300 | if (len > pmtu) { | 320 | if (len > pmtu) { |
301 | wqe->lpsn += (len - 1) / pmtu; | 321 | wqe->lpsn += (len - 1) / pmtu; |
@@ -325,8 +345,10 @@ int ipath_make_rc_req(struct ipath_qp *qp) | |||
325 | case IB_WR_RDMA_WRITE_WITH_IMM: | 345 | case IB_WR_RDMA_WRITE_WITH_IMM: |
326 | /* If no credit, return. */ | 346 | /* If no credit, return. */ |
327 | if (qp->s_lsn != (u32) -1 && | 347 | if (qp->s_lsn != (u32) -1 && |
328 | ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0) | 348 | ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0) { |
349 | qp->s_flags |= IPATH_S_WAIT_SSN_CREDIT; | ||
329 | goto bail; | 350 | goto bail; |
351 | } | ||
330 | ohdr->u.rc.reth.vaddr = | 352 | ohdr->u.rc.reth.vaddr = |
331 | cpu_to_be64(wqe->wr.wr.rdma.remote_addr); | 353 | cpu_to_be64(wqe->wr.wr.rdma.remote_addr); |
332 | ohdr->u.rc.reth.rkey = | 354 | ohdr->u.rc.reth.rkey = |
@@ -570,7 +592,11 @@ int ipath_make_rc_req(struct ipath_qp *qp) | |||
570 | ipath_make_ruc_header(dev, qp, ohdr, bth0 | (qp->s_state << 24), bth2); | 592 | ipath_make_ruc_header(dev, qp, ohdr, bth0 | (qp->s_state << 24), bth2); |
571 | done: | 593 | done: |
572 | ret = 1; | 594 | ret = 1; |
595 | goto unlock; | ||
596 | |||
573 | bail: | 597 | bail: |
598 | qp->s_flags &= ~IPATH_S_BUSY; | ||
599 | unlock: | ||
574 | spin_unlock_irqrestore(&qp->s_lock, flags); | 600 | spin_unlock_irqrestore(&qp->s_lock, flags); |
575 | return ret; | 601 | return ret; |
576 | } | 602 | } |
@@ -606,7 +632,11 @@ static void send_rc_ack(struct ipath_qp *qp) | |||
606 | 632 | ||
607 | spin_unlock_irqrestore(&qp->s_lock, flags); | 633 | spin_unlock_irqrestore(&qp->s_lock, flags); |
608 | 634 | ||
635 | /* Don't try to send ACKs if the link isn't ACTIVE */ | ||
609 | dd = dev->dd; | 636 | dd = dev->dd; |
637 | if (!(dd->ipath_flags & IPATH_LINKACTIVE)) | ||
638 | goto done; | ||
639 | |||
610 | piobuf = ipath_getpiobuf(dd, 0, NULL); | 640 | piobuf = ipath_getpiobuf(dd, 0, NULL); |
611 | if (!piobuf) { | 641 | if (!piobuf) { |
612 | /* | 642 | /* |
@@ -668,15 +698,16 @@ static void send_rc_ack(struct ipath_qp *qp) | |||
668 | goto done; | 698 | goto done; |
669 | 699 | ||
670 | queue_ack: | 700 | queue_ack: |
671 | dev->n_rc_qacks++; | 701 | if (ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK) { |
672 | qp->s_flags |= IPATH_S_ACK_PENDING; | 702 | dev->n_rc_qacks++; |
673 | qp->s_nak_state = qp->r_nak_state; | 703 | qp->s_flags |= IPATH_S_ACK_PENDING; |
674 | qp->s_ack_psn = qp->r_ack_psn; | 704 | qp->s_nak_state = qp->r_nak_state; |
705 | qp->s_ack_psn = qp->r_ack_psn; | ||
706 | |||
707 | /* Schedule the send tasklet. */ | ||
708 | ipath_schedule_send(qp); | ||
709 | } | ||
675 | spin_unlock_irqrestore(&qp->s_lock, flags); | 710 | spin_unlock_irqrestore(&qp->s_lock, flags); |
676 | |||
677 | /* Call ipath_do_rc_send() in another thread. */ | ||
678 | tasklet_hi_schedule(&qp->s_task); | ||
679 | |||
680 | done: | 711 | done: |
681 | return; | 712 | return; |
682 | } | 713 | } |
@@ -735,7 +766,7 @@ static void reset_psn(struct ipath_qp *qp, u32 psn) | |||
735 | /* | 766 | /* |
736 | * Set the state to restart in the middle of a request. | 767 | * Set the state to restart in the middle of a request. |
737 | * Don't change the s_sge, s_cur_sge, or s_cur_size. | 768 | * Don't change the s_sge, s_cur_sge, or s_cur_size. |
738 | * See ipath_do_rc_send(). | 769 | * See ipath_make_rc_req(). |
739 | */ | 770 | */ |
740 | switch (opcode) { | 771 | switch (opcode) { |
741 | case IB_WR_SEND: | 772 | case IB_WR_SEND: |
@@ -801,7 +832,7 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn) | |||
801 | dev->n_rc_resends += (qp->s_psn - psn) & IPATH_PSN_MASK; | 832 | dev->n_rc_resends += (qp->s_psn - psn) & IPATH_PSN_MASK; |
802 | 833 | ||
803 | reset_psn(qp, psn); | 834 | reset_psn(qp, psn); |
804 | tasklet_hi_schedule(&qp->s_task); | 835 | ipath_schedule_send(qp); |
805 | 836 | ||
806 | bail: | 837 | bail: |
807 | return; | 838 | return; |
@@ -809,13 +840,7 @@ bail: | |||
809 | 840 | ||
810 | static inline void update_last_psn(struct ipath_qp *qp, u32 psn) | 841 | static inline void update_last_psn(struct ipath_qp *qp, u32 psn) |
811 | { | 842 | { |
812 | if (qp->s_last_psn != psn) { | 843 | qp->s_last_psn = psn; |
813 | qp->s_last_psn = psn; | ||
814 | if (qp->s_wait_credit) { | ||
815 | qp->s_wait_credit = 0; | ||
816 | tasklet_hi_schedule(&qp->s_task); | ||
817 | } | ||
818 | } | ||
819 | } | 844 | } |
820 | 845 | ||
821 | /** | 846 | /** |
@@ -915,14 +940,10 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, | |||
915 | wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)) { | 940 | wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)) { |
916 | qp->s_num_rd_atomic--; | 941 | qp->s_num_rd_atomic--; |
917 | /* Restart sending task if fence is complete */ | 942 | /* Restart sending task if fence is complete */ |
918 | if ((qp->s_flags & IPATH_S_FENCE_PENDING) && | 943 | if (((qp->s_flags & IPATH_S_FENCE_PENDING) && |
919 | !qp->s_num_rd_atomic) { | 944 | !qp->s_num_rd_atomic) || |
920 | qp->s_flags &= ~IPATH_S_FENCE_PENDING; | 945 | qp->s_flags & IPATH_S_RDMAR_PENDING) |
921 | tasklet_hi_schedule(&qp->s_task); | 946 | ipath_schedule_send(qp); |
922 | } else if (qp->s_flags & IPATH_S_RDMAR_PENDING) { | ||
923 | qp->s_flags &= ~IPATH_S_RDMAR_PENDING; | ||
924 | tasklet_hi_schedule(&qp->s_task); | ||
925 | } | ||
926 | } | 947 | } |
927 | /* Post a send completion queue entry if requested. */ | 948 | /* Post a send completion queue entry if requested. */ |
928 | if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) || | 949 | if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) || |
@@ -956,6 +977,8 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, | |||
956 | } else { | 977 | } else { |
957 | if (++qp->s_last >= qp->s_size) | 978 | if (++qp->s_last >= qp->s_size) |
958 | qp->s_last = 0; | 979 | qp->s_last = 0; |
980 | if (qp->state == IB_QPS_SQD && qp->s_last == qp->s_cur) | ||
981 | qp->s_draining = 0; | ||
959 | if (qp->s_last == qp->s_tail) | 982 | if (qp->s_last == qp->s_tail) |
960 | break; | 983 | break; |
961 | wqe = get_swqe_ptr(qp, qp->s_last); | 984 | wqe = get_swqe_ptr(qp, qp->s_last); |
@@ -979,7 +1002,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, | |||
979 | */ | 1002 | */ |
980 | if (ipath_cmp24(qp->s_psn, psn) <= 0) { | 1003 | if (ipath_cmp24(qp->s_psn, psn) <= 0) { |
981 | reset_psn(qp, psn + 1); | 1004 | reset_psn(qp, psn + 1); |
982 | tasklet_hi_schedule(&qp->s_task); | 1005 | ipath_schedule_send(qp); |
983 | } | 1006 | } |
984 | } else if (ipath_cmp24(qp->s_psn, psn) <= 0) { | 1007 | } else if (ipath_cmp24(qp->s_psn, psn) <= 0) { |
985 | qp->s_state = OP(SEND_LAST); | 1008 | qp->s_state = OP(SEND_LAST); |
@@ -1018,6 +1041,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, | |||
1018 | ib_ipath_rnr_table[(aeth >> IPATH_AETH_CREDIT_SHIFT) & | 1041 | ib_ipath_rnr_table[(aeth >> IPATH_AETH_CREDIT_SHIFT) & |
1019 | IPATH_AETH_CREDIT_MASK]; | 1042 | IPATH_AETH_CREDIT_MASK]; |
1020 | ipath_insert_rnr_queue(qp); | 1043 | ipath_insert_rnr_queue(qp); |
1044 | ipath_schedule_send(qp); | ||
1021 | goto bail; | 1045 | goto bail; |
1022 | 1046 | ||
1023 | case 3: /* NAK */ | 1047 | case 3: /* NAK */ |
@@ -1108,6 +1132,10 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, | |||
1108 | 1132 | ||
1109 | spin_lock_irqsave(&qp->s_lock, flags); | 1133 | spin_lock_irqsave(&qp->s_lock, flags); |
1110 | 1134 | ||
1135 | /* Double check we can process this now that we hold the s_lock. */ | ||
1136 | if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) | ||
1137 | goto ack_done; | ||
1138 | |||
1111 | /* Ignore invalid responses. */ | 1139 | /* Ignore invalid responses. */ |
1112 | if (ipath_cmp24(psn, qp->s_next_psn) >= 0) | 1140 | if (ipath_cmp24(psn, qp->s_next_psn) >= 0) |
1113 | goto ack_done; | 1141 | goto ack_done; |
@@ -1343,7 +1371,12 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev, | |||
1343 | psn &= IPATH_PSN_MASK; | 1371 | psn &= IPATH_PSN_MASK; |
1344 | e = NULL; | 1372 | e = NULL; |
1345 | old_req = 1; | 1373 | old_req = 1; |
1374 | |||
1346 | spin_lock_irqsave(&qp->s_lock, flags); | 1375 | spin_lock_irqsave(&qp->s_lock, flags); |
1376 | /* Double check we can process this now that we hold the s_lock. */ | ||
1377 | if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) | ||
1378 | goto unlock_done; | ||
1379 | |||
1347 | for (i = qp->r_head_ack_queue; ; i = prev) { | 1380 | for (i = qp->r_head_ack_queue; ; i = prev) { |
1348 | if (i == qp->s_tail_ack_queue) | 1381 | if (i == qp->s_tail_ack_queue) |
1349 | old_req = 0; | 1382 | old_req = 0; |
@@ -1471,7 +1504,7 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev, | |||
1471 | break; | 1504 | break; |
1472 | } | 1505 | } |
1473 | qp->r_nak_state = 0; | 1506 | qp->r_nak_state = 0; |
1474 | tasklet_hi_schedule(&qp->s_task); | 1507 | ipath_schedule_send(qp); |
1475 | 1508 | ||
1476 | unlock_done: | 1509 | unlock_done: |
1477 | spin_unlock_irqrestore(&qp->s_lock, flags); | 1510 | spin_unlock_irqrestore(&qp->s_lock, flags); |
@@ -1503,18 +1536,15 @@ void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err) | |||
1503 | 1536 | ||
1504 | static inline void ipath_update_ack_queue(struct ipath_qp *qp, unsigned n) | 1537 | static inline void ipath_update_ack_queue(struct ipath_qp *qp, unsigned n) |
1505 | { | 1538 | { |
1506 | unsigned long flags; | ||
1507 | unsigned next; | 1539 | unsigned next; |
1508 | 1540 | ||
1509 | next = n + 1; | 1541 | next = n + 1; |
1510 | if (next > IPATH_MAX_RDMA_ATOMIC) | 1542 | if (next > IPATH_MAX_RDMA_ATOMIC) |
1511 | next = 0; | 1543 | next = 0; |
1512 | spin_lock_irqsave(&qp->s_lock, flags); | ||
1513 | if (n == qp->s_tail_ack_queue) { | 1544 | if (n == qp->s_tail_ack_queue) { |
1514 | qp->s_tail_ack_queue = next; | 1545 | qp->s_tail_ack_queue = next; |
1515 | qp->s_ack_state = OP(ACKNOWLEDGE); | 1546 | qp->s_ack_state = OP(ACKNOWLEDGE); |
1516 | } | 1547 | } |
1517 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
1518 | } | 1548 | } |
1519 | 1549 | ||
1520 | /** | 1550 | /** |
@@ -1543,6 +1573,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1543 | int diff; | 1573 | int diff; |
1544 | struct ib_reth *reth; | 1574 | struct ib_reth *reth; |
1545 | int header_in_data; | 1575 | int header_in_data; |
1576 | unsigned long flags; | ||
1546 | 1577 | ||
1547 | /* Validate the SLID. See Ch. 9.6.1.5 */ | 1578 | /* Validate the SLID. See Ch. 9.6.1.5 */ |
1548 | if (unlikely(be16_to_cpu(hdr->lrh[3]) != qp->remote_ah_attr.dlid)) | 1579 | if (unlikely(be16_to_cpu(hdr->lrh[3]) != qp->remote_ah_attr.dlid)) |
@@ -1690,9 +1721,8 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1690 | goto nack_inv; | 1721 | goto nack_inv; |
1691 | ipath_copy_sge(&qp->r_sge, data, tlen); | 1722 | ipath_copy_sge(&qp->r_sge, data, tlen); |
1692 | qp->r_msn++; | 1723 | qp->r_msn++; |
1693 | if (!qp->r_wrid_valid) | 1724 | if (!test_and_clear_bit(IPATH_R_WRID_VALID, &qp->r_aflags)) |
1694 | break; | 1725 | break; |
1695 | qp->r_wrid_valid = 0; | ||
1696 | wc.wr_id = qp->r_wr_id; | 1726 | wc.wr_id = qp->r_wr_id; |
1697 | wc.status = IB_WC_SUCCESS; | 1727 | wc.status = IB_WC_SUCCESS; |
1698 | if (opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE) || | 1728 | if (opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE) || |
@@ -1764,9 +1794,13 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1764 | next = qp->r_head_ack_queue + 1; | 1794 | next = qp->r_head_ack_queue + 1; |
1765 | if (next > IPATH_MAX_RDMA_ATOMIC) | 1795 | if (next > IPATH_MAX_RDMA_ATOMIC) |
1766 | next = 0; | 1796 | next = 0; |
1797 | spin_lock_irqsave(&qp->s_lock, flags); | ||
1798 | /* Double check we can process this while holding the s_lock. */ | ||
1799 | if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) | ||
1800 | goto unlock; | ||
1767 | if (unlikely(next == qp->s_tail_ack_queue)) { | 1801 | if (unlikely(next == qp->s_tail_ack_queue)) { |
1768 | if (!qp->s_ack_queue[next].sent) | 1802 | if (!qp->s_ack_queue[next].sent) |
1769 | goto nack_inv; | 1803 | goto nack_inv_unlck; |
1770 | ipath_update_ack_queue(qp, next); | 1804 | ipath_update_ack_queue(qp, next); |
1771 | } | 1805 | } |
1772 | e = &qp->s_ack_queue[qp->r_head_ack_queue]; | 1806 | e = &qp->s_ack_queue[qp->r_head_ack_queue]; |
@@ -1787,7 +1821,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1787 | ok = ipath_rkey_ok(qp, &e->rdma_sge, len, vaddr, | 1821 | ok = ipath_rkey_ok(qp, &e->rdma_sge, len, vaddr, |
1788 | rkey, IB_ACCESS_REMOTE_READ); | 1822 | rkey, IB_ACCESS_REMOTE_READ); |
1789 | if (unlikely(!ok)) | 1823 | if (unlikely(!ok)) |
1790 | goto nack_acc; | 1824 | goto nack_acc_unlck; |
1791 | /* | 1825 | /* |
1792 | * Update the next expected PSN. We add 1 later | 1826 | * Update the next expected PSN. We add 1 later |
1793 | * below, so only add the remainder here. | 1827 | * below, so only add the remainder here. |
@@ -1814,13 +1848,12 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1814 | qp->r_psn++; | 1848 | qp->r_psn++; |
1815 | qp->r_state = opcode; | 1849 | qp->r_state = opcode; |
1816 | qp->r_nak_state = 0; | 1850 | qp->r_nak_state = 0; |
1817 | barrier(); | ||
1818 | qp->r_head_ack_queue = next; | 1851 | qp->r_head_ack_queue = next; |
1819 | 1852 | ||
1820 | /* Call ipath_do_rc_send() in another thread. */ | 1853 | /* Schedule the send tasklet. */ |
1821 | tasklet_hi_schedule(&qp->s_task); | 1854 | ipath_schedule_send(qp); |
1822 | 1855 | ||
1823 | goto done; | 1856 | goto unlock; |
1824 | } | 1857 | } |
1825 | 1858 | ||
1826 | case OP(COMPARE_SWAP): | 1859 | case OP(COMPARE_SWAP): |
@@ -1839,9 +1872,13 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1839 | next = qp->r_head_ack_queue + 1; | 1872 | next = qp->r_head_ack_queue + 1; |
1840 | if (next > IPATH_MAX_RDMA_ATOMIC) | 1873 | if (next > IPATH_MAX_RDMA_ATOMIC) |
1841 | next = 0; | 1874 | next = 0; |
1875 | spin_lock_irqsave(&qp->s_lock, flags); | ||
1876 | /* Double check we can process this while holding the s_lock. */ | ||
1877 | if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) | ||
1878 | goto unlock; | ||
1842 | if (unlikely(next == qp->s_tail_ack_queue)) { | 1879 | if (unlikely(next == qp->s_tail_ack_queue)) { |
1843 | if (!qp->s_ack_queue[next].sent) | 1880 | if (!qp->s_ack_queue[next].sent) |
1844 | goto nack_inv; | 1881 | goto nack_inv_unlck; |
1845 | ipath_update_ack_queue(qp, next); | 1882 | ipath_update_ack_queue(qp, next); |
1846 | } | 1883 | } |
1847 | if (!header_in_data) | 1884 | if (!header_in_data) |
@@ -1851,13 +1888,13 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1851 | vaddr = ((u64) be32_to_cpu(ateth->vaddr[0]) << 32) | | 1888 | vaddr = ((u64) be32_to_cpu(ateth->vaddr[0]) << 32) | |
1852 | be32_to_cpu(ateth->vaddr[1]); | 1889 | be32_to_cpu(ateth->vaddr[1]); |
1853 | if (unlikely(vaddr & (sizeof(u64) - 1))) | 1890 | if (unlikely(vaddr & (sizeof(u64) - 1))) |
1854 | goto nack_inv; | 1891 | goto nack_inv_unlck; |
1855 | rkey = be32_to_cpu(ateth->rkey); | 1892 | rkey = be32_to_cpu(ateth->rkey); |
1856 | /* Check rkey & NAK */ | 1893 | /* Check rkey & NAK */ |
1857 | if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, | 1894 | if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, |
1858 | sizeof(u64), vaddr, rkey, | 1895 | sizeof(u64), vaddr, rkey, |
1859 | IB_ACCESS_REMOTE_ATOMIC))) | 1896 | IB_ACCESS_REMOTE_ATOMIC))) |
1860 | goto nack_acc; | 1897 | goto nack_acc_unlck; |
1861 | /* Perform atomic OP and save result. */ | 1898 | /* Perform atomic OP and save result. */ |
1862 | maddr = (atomic64_t *) qp->r_sge.sge.vaddr; | 1899 | maddr = (atomic64_t *) qp->r_sge.sge.vaddr; |
1863 | sdata = be64_to_cpu(ateth->swap_data); | 1900 | sdata = be64_to_cpu(ateth->swap_data); |
@@ -1874,13 +1911,12 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1874 | qp->r_psn++; | 1911 | qp->r_psn++; |
1875 | qp->r_state = opcode; | 1912 | qp->r_state = opcode; |
1876 | qp->r_nak_state = 0; | 1913 | qp->r_nak_state = 0; |
1877 | barrier(); | ||
1878 | qp->r_head_ack_queue = next; | 1914 | qp->r_head_ack_queue = next; |
1879 | 1915 | ||
1880 | /* Call ipath_do_rc_send() in another thread. */ | 1916 | /* Schedule the send tasklet. */ |
1881 | tasklet_hi_schedule(&qp->s_task); | 1917 | ipath_schedule_send(qp); |
1882 | 1918 | ||
1883 | goto done; | 1919 | goto unlock; |
1884 | } | 1920 | } |
1885 | 1921 | ||
1886 | default: | 1922 | default: |
@@ -1901,19 +1937,26 @@ rnr_nak: | |||
1901 | qp->r_ack_psn = qp->r_psn; | 1937 | qp->r_ack_psn = qp->r_psn; |
1902 | goto send_ack; | 1938 | goto send_ack; |
1903 | 1939 | ||
1940 | nack_inv_unlck: | ||
1941 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
1904 | nack_inv: | 1942 | nack_inv: |
1905 | ipath_rc_error(qp, IB_WC_LOC_QP_OP_ERR); | 1943 | ipath_rc_error(qp, IB_WC_LOC_QP_OP_ERR); |
1906 | qp->r_nak_state = IB_NAK_INVALID_REQUEST; | 1944 | qp->r_nak_state = IB_NAK_INVALID_REQUEST; |
1907 | qp->r_ack_psn = qp->r_psn; | 1945 | qp->r_ack_psn = qp->r_psn; |
1908 | goto send_ack; | 1946 | goto send_ack; |
1909 | 1947 | ||
1948 | nack_acc_unlck: | ||
1949 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
1910 | nack_acc: | 1950 | nack_acc: |
1911 | ipath_rc_error(qp, IB_WC_LOC_PROT_ERR); | 1951 | ipath_rc_error(qp, IB_WC_LOC_PROT_ERR); |
1912 | qp->r_nak_state = IB_NAK_REMOTE_ACCESS_ERROR; | 1952 | qp->r_nak_state = IB_NAK_REMOTE_ACCESS_ERROR; |
1913 | qp->r_ack_psn = qp->r_psn; | 1953 | qp->r_ack_psn = qp->r_psn; |
1914 | send_ack: | 1954 | send_ack: |
1915 | send_rc_ack(qp); | 1955 | send_rc_ack(qp); |
1956 | goto done; | ||
1916 | 1957 | ||
1958 | unlock: | ||
1959 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
1917 | done: | 1960 | done: |
1918 | return; | 1961 | return; |
1919 | } | 1962 | } |