18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved. 38c2ecf20Sopenharmony_ci * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 68c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 78c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 88c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 98c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 128c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 138c2ecf20Sopenharmony_ci * conditions are met: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 168c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 178c2ecf20Sopenharmony_ci * disclaimer. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 208c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 218c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 228c2ecf20Sopenharmony_ci * provided with the distribution. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 258c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 268c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 278c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 288c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 298c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 308c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 318c2ecf20Sopenharmony_ci * SOFTWARE. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#include <linux/io.h> 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include "qib.h" 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* cut down ridiculously long IB macro names */ 398c2ecf20Sopenharmony_ci#define OP(x) IB_OPCODE_RC_##x 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic u32 restart_sge(struct rvt_sge_state *ss, struct rvt_swqe *wqe, 438c2ecf20Sopenharmony_ci u32 psn, u32 pmtu) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci u32 len; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci len = ((psn - wqe->psn) & QIB_PSN_MASK) * pmtu; 488c2ecf20Sopenharmony_ci return rvt_restart_sge(ss, wqe, len); 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/** 528c2ecf20Sopenharmony_ci * qib_make_rc_ack - construct a response packet (ACK, NAK, or RDMA read) 538c2ecf20Sopenharmony_ci * @dev: the device for this QP 548c2ecf20Sopenharmony_ci * @qp: a pointer to the QP 558c2ecf20Sopenharmony_ci * @ohdr: a pointer to the IB header being constructed 568c2ecf20Sopenharmony_ci * @pmtu: the path MTU 578c2ecf20Sopenharmony_ci * 588c2ecf20Sopenharmony_ci * Return 1 if constructed; otherwise, return 0. 598c2ecf20Sopenharmony_ci * Note that we are in the responder's side of the QP context. 608c2ecf20Sopenharmony_ci * Note the QP s_lock must be held. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_cistatic int qib_make_rc_ack(struct qib_ibdev *dev, struct rvt_qp *qp, 638c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr, u32 pmtu) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci struct rvt_ack_entry *e; 668c2ecf20Sopenharmony_ci u32 hwords; 678c2ecf20Sopenharmony_ci u32 len; 688c2ecf20Sopenharmony_ci u32 bth0; 698c2ecf20Sopenharmony_ci u32 bth2; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci /* Don't send an ACK if we aren't supposed to. */ 728c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) 738c2ecf20Sopenharmony_ci goto bail; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* header size in 32-bit words LRH+BTH = (8+12)/4. */ 768c2ecf20Sopenharmony_ci hwords = 5; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci switch (qp->s_ack_state) { 798c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_LAST): 808c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_ONLY): 818c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 828c2ecf20Sopenharmony_ci if (e->rdma_sge.mr) { 838c2ecf20Sopenharmony_ci rvt_put_mr(e->rdma_sge.mr); 848c2ecf20Sopenharmony_ci e->rdma_sge.mr = NULL; 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci fallthrough; 878c2ecf20Sopenharmony_ci case OP(ATOMIC_ACKNOWLEDGE): 888c2ecf20Sopenharmony_ci /* 898c2ecf20Sopenharmony_ci * We can increment the tail pointer now that the last 908c2ecf20Sopenharmony_ci * response has been sent instead of only being 918c2ecf20Sopenharmony_ci * constructed. 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_ci if (++qp->s_tail_ack_queue > QIB_MAX_RDMA_ATOMIC) 948c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = 0; 958c2ecf20Sopenharmony_ci fallthrough; 968c2ecf20Sopenharmony_ci case OP(SEND_ONLY): 978c2ecf20Sopenharmony_ci case OP(ACKNOWLEDGE): 988c2ecf20Sopenharmony_ci /* Check for no next entry in the queue. */ 998c2ecf20Sopenharmony_ci if (qp->r_head_ack_queue == qp->s_tail_ack_queue) { 1008c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_ACK_PENDING) 1018c2ecf20Sopenharmony_ci goto normal; 1028c2ecf20Sopenharmony_ci goto bail; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 1068c2ecf20Sopenharmony_ci if (e->opcode == OP(RDMA_READ_REQUEST)) { 1078c2ecf20Sopenharmony_ci /* 1088c2ecf20Sopenharmony_ci * If a RDMA read response is being resent and 1098c2ecf20Sopenharmony_ci * we haven't seen the duplicate request yet, 1108c2ecf20Sopenharmony_ci * then stop sending the remaining responses the 1118c2ecf20Sopenharmony_ci * responder has seen until the requester resends it. 1128c2ecf20Sopenharmony_ci */ 1138c2ecf20Sopenharmony_ci len = e->rdma_sge.sge_length; 1148c2ecf20Sopenharmony_ci if (len && !e->rdma_sge.mr) { 1158c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = qp->r_head_ack_queue; 1168c2ecf20Sopenharmony_ci goto bail; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci /* Copy SGE state in case we need to resend */ 1198c2ecf20Sopenharmony_ci qp->s_rdma_mr = e->rdma_sge.mr; 1208c2ecf20Sopenharmony_ci if (qp->s_rdma_mr) 1218c2ecf20Sopenharmony_ci rvt_get_mr(qp->s_rdma_mr); 1228c2ecf20Sopenharmony_ci qp->s_ack_rdma_sge.sge = e->rdma_sge; 1238c2ecf20Sopenharmony_ci qp->s_ack_rdma_sge.num_sge = 1; 1248c2ecf20Sopenharmony_ci qp->s_cur_sge = &qp->s_ack_rdma_sge; 1258c2ecf20Sopenharmony_ci if (len > pmtu) { 1268c2ecf20Sopenharmony_ci len = pmtu; 1278c2ecf20Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST); 1288c2ecf20Sopenharmony_ci } else { 1298c2ecf20Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY); 1308c2ecf20Sopenharmony_ci e->sent = 1; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 1338c2ecf20Sopenharmony_ci hwords++; 1348c2ecf20Sopenharmony_ci qp->s_ack_rdma_psn = e->psn; 1358c2ecf20Sopenharmony_ci bth2 = qp->s_ack_rdma_psn++ & QIB_PSN_MASK; 1368c2ecf20Sopenharmony_ci } else { 1378c2ecf20Sopenharmony_ci /* COMPARE_SWAP or FETCH_ADD */ 1388c2ecf20Sopenharmony_ci qp->s_cur_sge = NULL; 1398c2ecf20Sopenharmony_ci len = 0; 1408c2ecf20Sopenharmony_ci qp->s_ack_state = OP(ATOMIC_ACKNOWLEDGE); 1418c2ecf20Sopenharmony_ci ohdr->u.at.aeth = rvt_compute_aeth(qp); 1428c2ecf20Sopenharmony_ci ib_u64_put(e->atomic_data, &ohdr->u.at.atomic_ack_eth); 1438c2ecf20Sopenharmony_ci hwords += sizeof(ohdr->u.at) / sizeof(u32); 1448c2ecf20Sopenharmony_ci bth2 = e->psn & QIB_PSN_MASK; 1458c2ecf20Sopenharmony_ci e->sent = 1; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci bth0 = qp->s_ack_state << 24; 1488c2ecf20Sopenharmony_ci break; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_FIRST): 1518c2ecf20Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE); 1528c2ecf20Sopenharmony_ci fallthrough; 1538c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_MIDDLE): 1548c2ecf20Sopenharmony_ci qp->s_cur_sge = &qp->s_ack_rdma_sge; 1558c2ecf20Sopenharmony_ci qp->s_rdma_mr = qp->s_ack_rdma_sge.sge.mr; 1568c2ecf20Sopenharmony_ci if (qp->s_rdma_mr) 1578c2ecf20Sopenharmony_ci rvt_get_mr(qp->s_rdma_mr); 1588c2ecf20Sopenharmony_ci len = qp->s_ack_rdma_sge.sge.sge_length; 1598c2ecf20Sopenharmony_ci if (len > pmtu) 1608c2ecf20Sopenharmony_ci len = pmtu; 1618c2ecf20Sopenharmony_ci else { 1628c2ecf20Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 1638c2ecf20Sopenharmony_ci hwords++; 1648c2ecf20Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST); 1658c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 1668c2ecf20Sopenharmony_ci e->sent = 1; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci bth0 = qp->s_ack_state << 24; 1698c2ecf20Sopenharmony_ci bth2 = qp->s_ack_rdma_psn++ & QIB_PSN_MASK; 1708c2ecf20Sopenharmony_ci break; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci default: 1738c2ecf20Sopenharmony_cinormal: 1748c2ecf20Sopenharmony_ci /* 1758c2ecf20Sopenharmony_ci * Send a regular ACK. 1768c2ecf20Sopenharmony_ci * Set the s_ack_state so we wait until after sending 1778c2ecf20Sopenharmony_ci * the ACK before setting s_ack_state to ACKNOWLEDGE 1788c2ecf20Sopenharmony_ci * (see above). 1798c2ecf20Sopenharmony_ci */ 1808c2ecf20Sopenharmony_ci qp->s_ack_state = OP(SEND_ONLY); 1818c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_ACK_PENDING; 1828c2ecf20Sopenharmony_ci qp->s_cur_sge = NULL; 1838c2ecf20Sopenharmony_ci if (qp->s_nak_state) 1848c2ecf20Sopenharmony_ci ohdr->u.aeth = 1858c2ecf20Sopenharmony_ci cpu_to_be32((qp->r_msn & IB_MSN_MASK) | 1868c2ecf20Sopenharmony_ci (qp->s_nak_state << 1878c2ecf20Sopenharmony_ci IB_AETH_CREDIT_SHIFT)); 1888c2ecf20Sopenharmony_ci else 1898c2ecf20Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 1908c2ecf20Sopenharmony_ci hwords++; 1918c2ecf20Sopenharmony_ci len = 0; 1928c2ecf20Sopenharmony_ci bth0 = OP(ACKNOWLEDGE) << 24; 1938c2ecf20Sopenharmony_ci bth2 = qp->s_ack_psn & QIB_PSN_MASK; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci qp->s_rdma_ack_cnt++; 1968c2ecf20Sopenharmony_ci qp->s_hdrwords = hwords; 1978c2ecf20Sopenharmony_ci qp->s_cur_size = len; 1988c2ecf20Sopenharmony_ci qib_make_ruc_header(qp, ohdr, bth0, bth2); 1998c2ecf20Sopenharmony_ci return 1; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cibail: 2028c2ecf20Sopenharmony_ci qp->s_ack_state = OP(ACKNOWLEDGE); 2038c2ecf20Sopenharmony_ci qp->s_flags &= ~(RVT_S_RESP_PENDING | RVT_S_ACK_PENDING); 2048c2ecf20Sopenharmony_ci return 0; 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci/** 2088c2ecf20Sopenharmony_ci * qib_make_rc_req - construct a request packet (SEND, RDMA r/w, ATOMIC) 2098c2ecf20Sopenharmony_ci * @qp: a pointer to the QP 2108c2ecf20Sopenharmony_ci * 2118c2ecf20Sopenharmony_ci * Assumes the s_lock is held. 2128c2ecf20Sopenharmony_ci * 2138c2ecf20Sopenharmony_ci * Return 1 if constructed; otherwise, return 0. 2148c2ecf20Sopenharmony_ci */ 2158c2ecf20Sopenharmony_ciint qib_make_rc_req(struct rvt_qp *qp, unsigned long *flags) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct qib_qp_priv *priv = qp->priv; 2188c2ecf20Sopenharmony_ci struct qib_ibdev *dev = to_idev(qp->ibqp.device); 2198c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr; 2208c2ecf20Sopenharmony_ci struct rvt_sge_state *ss; 2218c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 2228c2ecf20Sopenharmony_ci u32 hwords; 2238c2ecf20Sopenharmony_ci u32 len; 2248c2ecf20Sopenharmony_ci u32 bth0; 2258c2ecf20Sopenharmony_ci u32 bth2; 2268c2ecf20Sopenharmony_ci u32 pmtu = qp->pmtu; 2278c2ecf20Sopenharmony_ci char newreq; 2288c2ecf20Sopenharmony_ci int ret = 0; 2298c2ecf20Sopenharmony_ci int delta; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci ohdr = &priv->s_hdr->u.oth; 2328c2ecf20Sopenharmony_ci if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) 2338c2ecf20Sopenharmony_ci ohdr = &priv->s_hdr->u.l.oth; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci /* Sending responses has higher priority over sending requests. */ 2368c2ecf20Sopenharmony_ci if ((qp->s_flags & RVT_S_RESP_PENDING) && 2378c2ecf20Sopenharmony_ci qib_make_rc_ack(dev, qp, ohdr, pmtu)) 2388c2ecf20Sopenharmony_ci goto done; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_SEND_OK)) { 2418c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_FLUSH_SEND)) 2428c2ecf20Sopenharmony_ci goto bail; 2438c2ecf20Sopenharmony_ci /* We are in the error state, flush the work request. */ 2448c2ecf20Sopenharmony_ci if (qp->s_last == READ_ONCE(qp->s_head)) 2458c2ecf20Sopenharmony_ci goto bail; 2468c2ecf20Sopenharmony_ci /* If DMAs are in progress, we can't flush immediately. */ 2478c2ecf20Sopenharmony_ci if (atomic_read(&priv->s_dma_busy)) { 2488c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_DMA; 2498c2ecf20Sopenharmony_ci goto bail; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_last); 2528c2ecf20Sopenharmony_ci rvt_send_complete(qp, wqe, qp->s_last != qp->s_acked ? 2538c2ecf20Sopenharmony_ci IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR); 2548c2ecf20Sopenharmony_ci /* will get called again */ 2558c2ecf20Sopenharmony_ci goto done; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci if (qp->s_flags & (RVT_S_WAIT_RNR | RVT_S_WAIT_ACK)) 2598c2ecf20Sopenharmony_ci goto bail; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci if (qib_cmp24(qp->s_psn, qp->s_sending_hpsn) <= 0) { 2628c2ecf20Sopenharmony_ci if (qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) <= 0) { 2638c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_PSN; 2648c2ecf20Sopenharmony_ci goto bail; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci qp->s_sending_psn = qp->s_psn; 2678c2ecf20Sopenharmony_ci qp->s_sending_hpsn = qp->s_psn - 1; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci /* header size in 32-bit words LRH+BTH = (8+12)/4. */ 2718c2ecf20Sopenharmony_ci hwords = 5; 2728c2ecf20Sopenharmony_ci bth0 = 0; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci /* Send a request. */ 2758c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_cur); 2768c2ecf20Sopenharmony_ci switch (qp->s_state) { 2778c2ecf20Sopenharmony_ci default: 2788c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_NEXT_SEND_OK)) 2798c2ecf20Sopenharmony_ci goto bail; 2808c2ecf20Sopenharmony_ci /* 2818c2ecf20Sopenharmony_ci * Resend an old request or start a new one. 2828c2ecf20Sopenharmony_ci * 2838c2ecf20Sopenharmony_ci * We keep track of the current SWQE so that 2848c2ecf20Sopenharmony_ci * we don't reset the "furthest progress" state 2858c2ecf20Sopenharmony_ci * if we need to back up. 2868c2ecf20Sopenharmony_ci */ 2878c2ecf20Sopenharmony_ci newreq = 0; 2888c2ecf20Sopenharmony_ci if (qp->s_cur == qp->s_tail) { 2898c2ecf20Sopenharmony_ci /* Check if send work queue is empty. */ 2908c2ecf20Sopenharmony_ci if (qp->s_tail == READ_ONCE(qp->s_head)) 2918c2ecf20Sopenharmony_ci goto bail; 2928c2ecf20Sopenharmony_ci /* 2938c2ecf20Sopenharmony_ci * If a fence is requested, wait for previous 2948c2ecf20Sopenharmony_ci * RDMA read and atomic operations to finish. 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ci if ((wqe->wr.send_flags & IB_SEND_FENCE) && 2978c2ecf20Sopenharmony_ci qp->s_num_rd_atomic) { 2988c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_FENCE; 2998c2ecf20Sopenharmony_ci goto bail; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci newreq = 1; 3028c2ecf20Sopenharmony_ci qp->s_psn = wqe->psn; 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci /* 3058c2ecf20Sopenharmony_ci * Note that we have to be careful not to modify the 3068c2ecf20Sopenharmony_ci * original work request since we may need to resend 3078c2ecf20Sopenharmony_ci * it. 3088c2ecf20Sopenharmony_ci */ 3098c2ecf20Sopenharmony_ci len = wqe->length; 3108c2ecf20Sopenharmony_ci ss = &qp->s_sge; 3118c2ecf20Sopenharmony_ci bth2 = qp->s_psn & QIB_PSN_MASK; 3128c2ecf20Sopenharmony_ci switch (wqe->wr.opcode) { 3138c2ecf20Sopenharmony_ci case IB_WR_SEND: 3148c2ecf20Sopenharmony_ci case IB_WR_SEND_WITH_IMM: 3158c2ecf20Sopenharmony_ci /* If no credit, return. */ 3168c2ecf20Sopenharmony_ci if (!rvt_rc_credit_avail(qp, wqe)) 3178c2ecf20Sopenharmony_ci goto bail; 3188c2ecf20Sopenharmony_ci if (len > pmtu) { 3198c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_FIRST); 3208c2ecf20Sopenharmony_ci len = pmtu; 3218c2ecf20Sopenharmony_ci break; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_SEND) 3248c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_ONLY); 3258c2ecf20Sopenharmony_ci else { 3268c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE); 3278c2ecf20Sopenharmony_ci /* Immediate data comes after the BTH */ 3288c2ecf20Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 3298c2ecf20Sopenharmony_ci hwords += 1; 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 3328c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 3338c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 3348c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 3358c2ecf20Sopenharmony_ci qp->s_cur = 0; 3368c2ecf20Sopenharmony_ci break; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE: 3398c2ecf20Sopenharmony_ci if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 3408c2ecf20Sopenharmony_ci qp->s_lsn++; 3418c2ecf20Sopenharmony_ci goto no_flow_control; 3428c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE_WITH_IMM: 3438c2ecf20Sopenharmony_ci /* If no credit, return. */ 3448c2ecf20Sopenharmony_ci if (!rvt_rc_credit_avail(qp, wqe)) 3458c2ecf20Sopenharmony_ci goto bail; 3468c2ecf20Sopenharmony_cino_flow_control: 3478c2ecf20Sopenharmony_ci ohdr->u.rc.reth.vaddr = 3488c2ecf20Sopenharmony_ci cpu_to_be64(wqe->rdma_wr.remote_addr); 3498c2ecf20Sopenharmony_ci ohdr->u.rc.reth.rkey = 3508c2ecf20Sopenharmony_ci cpu_to_be32(wqe->rdma_wr.rkey); 3518c2ecf20Sopenharmony_ci ohdr->u.rc.reth.length = cpu_to_be32(len); 3528c2ecf20Sopenharmony_ci hwords += sizeof(struct ib_reth) / sizeof(u32); 3538c2ecf20Sopenharmony_ci if (len > pmtu) { 3548c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_FIRST); 3558c2ecf20Sopenharmony_ci len = pmtu; 3568c2ecf20Sopenharmony_ci break; 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci if (wqe->rdma_wr.wr.opcode == IB_WR_RDMA_WRITE) 3598c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_ONLY); 3608c2ecf20Sopenharmony_ci else { 3618c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE); 3628c2ecf20Sopenharmony_ci /* Immediate data comes after RETH */ 3638c2ecf20Sopenharmony_ci ohdr->u.rc.imm_data = 3648c2ecf20Sopenharmony_ci wqe->rdma_wr.wr.ex.imm_data; 3658c2ecf20Sopenharmony_ci hwords += 1; 3668c2ecf20Sopenharmony_ci if (wqe->rdma_wr.wr.send_flags & IB_SEND_SOLICITED) 3678c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 3708c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 3718c2ecf20Sopenharmony_ci qp->s_cur = 0; 3728c2ecf20Sopenharmony_ci break; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci case IB_WR_RDMA_READ: 3758c2ecf20Sopenharmony_ci /* 3768c2ecf20Sopenharmony_ci * Don't allow more operations to be started 3778c2ecf20Sopenharmony_ci * than the QP limits allow. 3788c2ecf20Sopenharmony_ci */ 3798c2ecf20Sopenharmony_ci if (newreq) { 3808c2ecf20Sopenharmony_ci if (qp->s_num_rd_atomic >= 3818c2ecf20Sopenharmony_ci qp->s_max_rd_atomic) { 3828c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_RDMAR; 3838c2ecf20Sopenharmony_ci goto bail; 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci qp->s_num_rd_atomic++; 3868c2ecf20Sopenharmony_ci if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 3878c2ecf20Sopenharmony_ci qp->s_lsn++; 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci ohdr->u.rc.reth.vaddr = 3918c2ecf20Sopenharmony_ci cpu_to_be64(wqe->rdma_wr.remote_addr); 3928c2ecf20Sopenharmony_ci ohdr->u.rc.reth.rkey = 3938c2ecf20Sopenharmony_ci cpu_to_be32(wqe->rdma_wr.rkey); 3948c2ecf20Sopenharmony_ci ohdr->u.rc.reth.length = cpu_to_be32(len); 3958c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_REQUEST); 3968c2ecf20Sopenharmony_ci hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32); 3978c2ecf20Sopenharmony_ci ss = NULL; 3988c2ecf20Sopenharmony_ci len = 0; 3998c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 4008c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 4018c2ecf20Sopenharmony_ci qp->s_cur = 0; 4028c2ecf20Sopenharmony_ci break; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci case IB_WR_ATOMIC_CMP_AND_SWP: 4058c2ecf20Sopenharmony_ci case IB_WR_ATOMIC_FETCH_AND_ADD: 4068c2ecf20Sopenharmony_ci /* 4078c2ecf20Sopenharmony_ci * Don't allow more operations to be started 4088c2ecf20Sopenharmony_ci * than the QP limits allow. 4098c2ecf20Sopenharmony_ci */ 4108c2ecf20Sopenharmony_ci if (newreq) { 4118c2ecf20Sopenharmony_ci if (qp->s_num_rd_atomic >= 4128c2ecf20Sopenharmony_ci qp->s_max_rd_atomic) { 4138c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_RDMAR; 4148c2ecf20Sopenharmony_ci goto bail; 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci qp->s_num_rd_atomic++; 4178c2ecf20Sopenharmony_ci if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 4188c2ecf20Sopenharmony_ci qp->s_lsn++; 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci if (wqe->atomic_wr.wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) { 4218c2ecf20Sopenharmony_ci qp->s_state = OP(COMPARE_SWAP); 4228c2ecf20Sopenharmony_ci put_ib_ateth_swap(wqe->atomic_wr.swap, 4238c2ecf20Sopenharmony_ci &ohdr->u.atomic_eth); 4248c2ecf20Sopenharmony_ci put_ib_ateth_compare(wqe->atomic_wr.compare_add, 4258c2ecf20Sopenharmony_ci &ohdr->u.atomic_eth); 4268c2ecf20Sopenharmony_ci } else { 4278c2ecf20Sopenharmony_ci qp->s_state = OP(FETCH_ADD); 4288c2ecf20Sopenharmony_ci put_ib_ateth_swap(wqe->atomic_wr.compare_add, 4298c2ecf20Sopenharmony_ci &ohdr->u.atomic_eth); 4308c2ecf20Sopenharmony_ci put_ib_ateth_compare(0, &ohdr->u.atomic_eth); 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci put_ib_ateth_vaddr(wqe->atomic_wr.remote_addr, 4338c2ecf20Sopenharmony_ci &ohdr->u.atomic_eth); 4348c2ecf20Sopenharmony_ci ohdr->u.atomic_eth.rkey = cpu_to_be32( 4358c2ecf20Sopenharmony_ci wqe->atomic_wr.rkey); 4368c2ecf20Sopenharmony_ci hwords += sizeof(struct ib_atomic_eth) / sizeof(u32); 4378c2ecf20Sopenharmony_ci ss = NULL; 4388c2ecf20Sopenharmony_ci len = 0; 4398c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 4408c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 4418c2ecf20Sopenharmony_ci qp->s_cur = 0; 4428c2ecf20Sopenharmony_ci break; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci default: 4458c2ecf20Sopenharmony_ci goto bail; 4468c2ecf20Sopenharmony_ci } 4478c2ecf20Sopenharmony_ci qp->s_sge.sge = wqe->sg_list[0]; 4488c2ecf20Sopenharmony_ci qp->s_sge.sg_list = wqe->sg_list + 1; 4498c2ecf20Sopenharmony_ci qp->s_sge.num_sge = wqe->wr.num_sge; 4508c2ecf20Sopenharmony_ci qp->s_sge.total_len = wqe->length; 4518c2ecf20Sopenharmony_ci qp->s_len = wqe->length; 4528c2ecf20Sopenharmony_ci if (newreq) { 4538c2ecf20Sopenharmony_ci qp->s_tail++; 4548c2ecf20Sopenharmony_ci if (qp->s_tail >= qp->s_size) 4558c2ecf20Sopenharmony_ci qp->s_tail = 0; 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ) 4588c2ecf20Sopenharmony_ci qp->s_psn = wqe->lpsn + 1; 4598c2ecf20Sopenharmony_ci else 4608c2ecf20Sopenharmony_ci qp->s_psn++; 4618c2ecf20Sopenharmony_ci break; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_FIRST): 4648c2ecf20Sopenharmony_ci /* 4658c2ecf20Sopenharmony_ci * qp->s_state is normally set to the opcode of the 4668c2ecf20Sopenharmony_ci * last packet constructed for new requests and therefore 4678c2ecf20Sopenharmony_ci * is never set to RDMA read response. 4688c2ecf20Sopenharmony_ci * RDMA_READ_RESPONSE_FIRST is used by the ACK processing 4698c2ecf20Sopenharmony_ci * thread to indicate a SEND needs to be restarted from an 4708c2ecf20Sopenharmony_ci * earlier PSN without interferring with the sending thread. 4718c2ecf20Sopenharmony_ci * See qib_restart_rc(). 4728c2ecf20Sopenharmony_ci */ 4738c2ecf20Sopenharmony_ci qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, pmtu); 4748c2ecf20Sopenharmony_ci fallthrough; 4758c2ecf20Sopenharmony_ci case OP(SEND_FIRST): 4768c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_MIDDLE); 4778c2ecf20Sopenharmony_ci fallthrough; 4788c2ecf20Sopenharmony_ci case OP(SEND_MIDDLE): 4798c2ecf20Sopenharmony_ci bth2 = qp->s_psn++ & QIB_PSN_MASK; 4808c2ecf20Sopenharmony_ci ss = &qp->s_sge; 4818c2ecf20Sopenharmony_ci len = qp->s_len; 4828c2ecf20Sopenharmony_ci if (len > pmtu) { 4838c2ecf20Sopenharmony_ci len = pmtu; 4848c2ecf20Sopenharmony_ci break; 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_SEND) 4878c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 4888c2ecf20Sopenharmony_ci else { 4898c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE); 4908c2ecf20Sopenharmony_ci /* Immediate data comes after the BTH */ 4918c2ecf20Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 4928c2ecf20Sopenharmony_ci hwords += 1; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 4958c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 4968c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 4978c2ecf20Sopenharmony_ci qp->s_cur++; 4988c2ecf20Sopenharmony_ci if (qp->s_cur >= qp->s_size) 4998c2ecf20Sopenharmony_ci qp->s_cur = 0; 5008c2ecf20Sopenharmony_ci break; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_LAST): 5038c2ecf20Sopenharmony_ci /* 5048c2ecf20Sopenharmony_ci * qp->s_state is normally set to the opcode of the 5058c2ecf20Sopenharmony_ci * last packet constructed for new requests and therefore 5068c2ecf20Sopenharmony_ci * is never set to RDMA read response. 5078c2ecf20Sopenharmony_ci * RDMA_READ_RESPONSE_LAST is used by the ACK processing 5088c2ecf20Sopenharmony_ci * thread to indicate a RDMA write needs to be restarted from 5098c2ecf20Sopenharmony_ci * an earlier PSN without interferring with the sending thread. 5108c2ecf20Sopenharmony_ci * See qib_restart_rc(). 5118c2ecf20Sopenharmony_ci */ 5128c2ecf20Sopenharmony_ci qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, pmtu); 5138c2ecf20Sopenharmony_ci fallthrough; 5148c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 5158c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_MIDDLE); 5168c2ecf20Sopenharmony_ci fallthrough; 5178c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 5188c2ecf20Sopenharmony_ci bth2 = qp->s_psn++ & QIB_PSN_MASK; 5198c2ecf20Sopenharmony_ci ss = &qp->s_sge; 5208c2ecf20Sopenharmony_ci len = qp->s_len; 5218c2ecf20Sopenharmony_ci if (len > pmtu) { 5228c2ecf20Sopenharmony_ci len = pmtu; 5238c2ecf20Sopenharmony_ci break; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_WRITE) 5268c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_LAST); 5278c2ecf20Sopenharmony_ci else { 5288c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_LAST_WITH_IMMEDIATE); 5298c2ecf20Sopenharmony_ci /* Immediate data comes after the BTH */ 5308c2ecf20Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 5318c2ecf20Sopenharmony_ci hwords += 1; 5328c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 5338c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 5368c2ecf20Sopenharmony_ci qp->s_cur++; 5378c2ecf20Sopenharmony_ci if (qp->s_cur >= qp->s_size) 5388c2ecf20Sopenharmony_ci qp->s_cur = 0; 5398c2ecf20Sopenharmony_ci break; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_MIDDLE): 5428c2ecf20Sopenharmony_ci /* 5438c2ecf20Sopenharmony_ci * qp->s_state is normally set to the opcode of the 5448c2ecf20Sopenharmony_ci * last packet constructed for new requests and therefore 5458c2ecf20Sopenharmony_ci * is never set to RDMA read response. 5468c2ecf20Sopenharmony_ci * RDMA_READ_RESPONSE_MIDDLE is used by the ACK processing 5478c2ecf20Sopenharmony_ci * thread to indicate a RDMA read needs to be restarted from 5488c2ecf20Sopenharmony_ci * an earlier PSN without interferring with the sending thread. 5498c2ecf20Sopenharmony_ci * See qib_restart_rc(). 5508c2ecf20Sopenharmony_ci */ 5518c2ecf20Sopenharmony_ci len = ((qp->s_psn - wqe->psn) & QIB_PSN_MASK) * pmtu; 5528c2ecf20Sopenharmony_ci ohdr->u.rc.reth.vaddr = 5538c2ecf20Sopenharmony_ci cpu_to_be64(wqe->rdma_wr.remote_addr + len); 5548c2ecf20Sopenharmony_ci ohdr->u.rc.reth.rkey = 5558c2ecf20Sopenharmony_ci cpu_to_be32(wqe->rdma_wr.rkey); 5568c2ecf20Sopenharmony_ci ohdr->u.rc.reth.length = cpu_to_be32(wqe->length - len); 5578c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_REQUEST); 5588c2ecf20Sopenharmony_ci hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32); 5598c2ecf20Sopenharmony_ci bth2 = (qp->s_psn & QIB_PSN_MASK) | IB_BTH_REQ_ACK; 5608c2ecf20Sopenharmony_ci qp->s_psn = wqe->lpsn + 1; 5618c2ecf20Sopenharmony_ci ss = NULL; 5628c2ecf20Sopenharmony_ci len = 0; 5638c2ecf20Sopenharmony_ci qp->s_cur++; 5648c2ecf20Sopenharmony_ci if (qp->s_cur == qp->s_size) 5658c2ecf20Sopenharmony_ci qp->s_cur = 0; 5668c2ecf20Sopenharmony_ci break; 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci qp->s_sending_hpsn = bth2; 5698c2ecf20Sopenharmony_ci delta = (((int) bth2 - (int) wqe->psn) << 8) >> 8; 5708c2ecf20Sopenharmony_ci if (delta && delta % QIB_PSN_CREDIT == 0) 5718c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 5728c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_SEND_ONE) { 5738c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_SEND_ONE; 5748c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_ACK; 5758c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 5768c2ecf20Sopenharmony_ci } 5778c2ecf20Sopenharmony_ci qp->s_len -= len; 5788c2ecf20Sopenharmony_ci qp->s_hdrwords = hwords; 5798c2ecf20Sopenharmony_ci qp->s_cur_sge = ss; 5808c2ecf20Sopenharmony_ci qp->s_cur_size = len; 5818c2ecf20Sopenharmony_ci qib_make_ruc_header(qp, ohdr, bth0 | (qp->s_state << 24), bth2); 5828c2ecf20Sopenharmony_cidone: 5838c2ecf20Sopenharmony_ci return 1; 5848c2ecf20Sopenharmony_cibail: 5858c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_BUSY; 5868c2ecf20Sopenharmony_ci return ret; 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci/** 5908c2ecf20Sopenharmony_ci * qib_send_rc_ack - Construct an ACK packet and send it 5918c2ecf20Sopenharmony_ci * @qp: a pointer to the QP 5928c2ecf20Sopenharmony_ci * 5938c2ecf20Sopenharmony_ci * This is called from qib_rc_rcv() and qib_kreceive(). 5948c2ecf20Sopenharmony_ci * Note that RDMA reads and atomics are handled in the 5958c2ecf20Sopenharmony_ci * send side QP state and tasklet. 5968c2ecf20Sopenharmony_ci */ 5978c2ecf20Sopenharmony_civoid qib_send_rc_ack(struct rvt_qp *qp) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(qp->ibqp.device); 6008c2ecf20Sopenharmony_ci struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); 6018c2ecf20Sopenharmony_ci struct qib_pportdata *ppd = ppd_from_ibp(ibp); 6028c2ecf20Sopenharmony_ci u64 pbc; 6038c2ecf20Sopenharmony_ci u16 lrh0; 6048c2ecf20Sopenharmony_ci u32 bth0; 6058c2ecf20Sopenharmony_ci u32 hwords; 6068c2ecf20Sopenharmony_ci u32 pbufn; 6078c2ecf20Sopenharmony_ci u32 __iomem *piobuf; 6088c2ecf20Sopenharmony_ci struct ib_header hdr; 6098c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr; 6108c2ecf20Sopenharmony_ci u32 control; 6118c2ecf20Sopenharmony_ci unsigned long flags; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) 6168c2ecf20Sopenharmony_ci goto unlock; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci /* Don't send ACK or NAK if a RDMA read or atomic is pending. */ 6198c2ecf20Sopenharmony_ci if ((qp->s_flags & RVT_S_RESP_PENDING) || qp->s_rdma_ack_cnt) 6208c2ecf20Sopenharmony_ci goto queue_ack; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci /* Construct the header with s_lock held so APM doesn't change it. */ 6238c2ecf20Sopenharmony_ci ohdr = &hdr.u.oth; 6248c2ecf20Sopenharmony_ci lrh0 = QIB_LRH_BTH; 6258c2ecf20Sopenharmony_ci /* header size in 32-bit words LRH+BTH+AETH = (8+12+4)/4. */ 6268c2ecf20Sopenharmony_ci hwords = 6; 6278c2ecf20Sopenharmony_ci if (unlikely(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & 6288c2ecf20Sopenharmony_ci IB_AH_GRH)) { 6298c2ecf20Sopenharmony_ci hwords += qib_make_grh(ibp, &hdr.u.l.grh, 6308c2ecf20Sopenharmony_ci rdma_ah_read_grh(&qp->remote_ah_attr), 6318c2ecf20Sopenharmony_ci hwords, 0); 6328c2ecf20Sopenharmony_ci ohdr = &hdr.u.l.oth; 6338c2ecf20Sopenharmony_ci lrh0 = QIB_LRH_GRH; 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci /* read pkey_index w/o lock (its atomic) */ 6368c2ecf20Sopenharmony_ci bth0 = qib_get_pkey(ibp, qp->s_pkey_index) | (OP(ACKNOWLEDGE) << 24); 6378c2ecf20Sopenharmony_ci if (qp->s_mig_state == IB_MIG_MIGRATED) 6388c2ecf20Sopenharmony_ci bth0 |= IB_BTH_MIG_REQ; 6398c2ecf20Sopenharmony_ci if (qp->r_nak_state) 6408c2ecf20Sopenharmony_ci ohdr->u.aeth = cpu_to_be32((qp->r_msn & IB_MSN_MASK) | 6418c2ecf20Sopenharmony_ci (qp->r_nak_state << 6428c2ecf20Sopenharmony_ci IB_AETH_CREDIT_SHIFT)); 6438c2ecf20Sopenharmony_ci else 6448c2ecf20Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 6458c2ecf20Sopenharmony_ci lrh0 |= ibp->sl_to_vl[rdma_ah_get_sl(&qp->remote_ah_attr)] << 12 | 6468c2ecf20Sopenharmony_ci rdma_ah_get_sl(&qp->remote_ah_attr) << 4; 6478c2ecf20Sopenharmony_ci hdr.lrh[0] = cpu_to_be16(lrh0); 6488c2ecf20Sopenharmony_ci hdr.lrh[1] = cpu_to_be16(rdma_ah_get_dlid(&qp->remote_ah_attr)); 6498c2ecf20Sopenharmony_ci hdr.lrh[2] = cpu_to_be16(hwords + SIZE_OF_CRC); 6508c2ecf20Sopenharmony_ci hdr.lrh[3] = cpu_to_be16(ppd->lid | 6518c2ecf20Sopenharmony_ci rdma_ah_get_path_bits(&qp->remote_ah_attr)); 6528c2ecf20Sopenharmony_ci ohdr->bth[0] = cpu_to_be32(bth0); 6538c2ecf20Sopenharmony_ci ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); 6548c2ecf20Sopenharmony_ci ohdr->bth[2] = cpu_to_be32(qp->r_ack_psn & QIB_PSN_MASK); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci /* Don't try to send ACKs if the link isn't ACTIVE */ 6598c2ecf20Sopenharmony_ci if (!(ppd->lflags & QIBL_LINKACTIVE)) 6608c2ecf20Sopenharmony_ci goto done; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci control = dd->f_setpbc_control(ppd, hwords + SIZE_OF_CRC, 6638c2ecf20Sopenharmony_ci qp->s_srate, lrh0 >> 12); 6648c2ecf20Sopenharmony_ci /* length is + 1 for the control dword */ 6658c2ecf20Sopenharmony_ci pbc = ((u64) control << 32) | (hwords + 1); 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci piobuf = dd->f_getsendbuf(ppd, pbc, &pbufn); 6688c2ecf20Sopenharmony_ci if (!piobuf) { 6698c2ecf20Sopenharmony_ci /* 6708c2ecf20Sopenharmony_ci * We are out of PIO buffers at the moment. 6718c2ecf20Sopenharmony_ci * Pass responsibility for sending the ACK to the 6728c2ecf20Sopenharmony_ci * send tasklet so that when a PIO buffer becomes 6738c2ecf20Sopenharmony_ci * available, the ACK is sent ahead of other outgoing 6748c2ecf20Sopenharmony_ci * packets. 6758c2ecf20Sopenharmony_ci */ 6768c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 6778c2ecf20Sopenharmony_ci goto queue_ack; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci /* 6818c2ecf20Sopenharmony_ci * Write the pbc. 6828c2ecf20Sopenharmony_ci * We have to flush after the PBC for correctness 6838c2ecf20Sopenharmony_ci * on some cpus or WC buffer can be written out of order. 6848c2ecf20Sopenharmony_ci */ 6858c2ecf20Sopenharmony_ci writeq(pbc, piobuf); 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci if (dd->flags & QIB_PIO_FLUSH_WC) { 6888c2ecf20Sopenharmony_ci u32 *hdrp = (u32 *) &hdr; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci qib_flush_wc(); 6918c2ecf20Sopenharmony_ci qib_pio_copy(piobuf + 2, hdrp, hwords - 1); 6928c2ecf20Sopenharmony_ci qib_flush_wc(); 6938c2ecf20Sopenharmony_ci __raw_writel(hdrp[hwords - 1], piobuf + hwords + 1); 6948c2ecf20Sopenharmony_ci } else 6958c2ecf20Sopenharmony_ci qib_pio_copy(piobuf + 2, (u32 *) &hdr, hwords); 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci if (dd->flags & QIB_USE_SPCL_TRIG) { 6988c2ecf20Sopenharmony_ci u32 spcl_off = (pbufn >= dd->piobcnt2k) ? 2047 : 1023; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci qib_flush_wc(); 7018c2ecf20Sopenharmony_ci __raw_writel(0xaebecede, piobuf + spcl_off); 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci qib_flush_wc(); 7058c2ecf20Sopenharmony_ci qib_sendbuf_done(dd, pbufn); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci this_cpu_inc(ibp->pmastats->n_unicast_xmit); 7088c2ecf20Sopenharmony_ci goto done; 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ciqueue_ack: 7118c2ecf20Sopenharmony_ci if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) { 7128c2ecf20Sopenharmony_ci this_cpu_inc(*ibp->rvp.rc_qacks); 7138c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_ACK_PENDING | RVT_S_RESP_PENDING; 7148c2ecf20Sopenharmony_ci qp->s_nak_state = qp->r_nak_state; 7158c2ecf20Sopenharmony_ci qp->s_ack_psn = qp->r_ack_psn; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci /* Schedule the send tasklet. */ 7188c2ecf20Sopenharmony_ci qib_schedule_send(qp); 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ciunlock: 7218c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 7228c2ecf20Sopenharmony_cidone: 7238c2ecf20Sopenharmony_ci return; 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci/** 7278c2ecf20Sopenharmony_ci * reset_psn - reset the QP state to send starting from PSN 7288c2ecf20Sopenharmony_ci * @qp: the QP 7298c2ecf20Sopenharmony_ci * @psn: the packet sequence number to restart at 7308c2ecf20Sopenharmony_ci * 7318c2ecf20Sopenharmony_ci * This is called from qib_rc_rcv() to process an incoming RC ACK 7328c2ecf20Sopenharmony_ci * for the given QP. 7338c2ecf20Sopenharmony_ci * Called at interrupt level with the QP s_lock held. 7348c2ecf20Sopenharmony_ci */ 7358c2ecf20Sopenharmony_cistatic void reset_psn(struct rvt_qp *qp, u32 psn) 7368c2ecf20Sopenharmony_ci{ 7378c2ecf20Sopenharmony_ci u32 n = qp->s_acked; 7388c2ecf20Sopenharmony_ci struct rvt_swqe *wqe = rvt_get_swqe_ptr(qp, n); 7398c2ecf20Sopenharmony_ci u32 opcode; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci qp->s_cur = n; 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci /* 7448c2ecf20Sopenharmony_ci * If we are starting the request from the beginning, 7458c2ecf20Sopenharmony_ci * let the normal send code handle initialization. 7468c2ecf20Sopenharmony_ci */ 7478c2ecf20Sopenharmony_ci if (qib_cmp24(psn, wqe->psn) <= 0) { 7488c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 7498c2ecf20Sopenharmony_ci goto done; 7508c2ecf20Sopenharmony_ci } 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci /* Find the work request opcode corresponding to the given PSN. */ 7538c2ecf20Sopenharmony_ci opcode = wqe->wr.opcode; 7548c2ecf20Sopenharmony_ci for (;;) { 7558c2ecf20Sopenharmony_ci int diff; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci if (++n == qp->s_size) 7588c2ecf20Sopenharmony_ci n = 0; 7598c2ecf20Sopenharmony_ci if (n == qp->s_tail) 7608c2ecf20Sopenharmony_ci break; 7618c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, n); 7628c2ecf20Sopenharmony_ci diff = qib_cmp24(psn, wqe->psn); 7638c2ecf20Sopenharmony_ci if (diff < 0) 7648c2ecf20Sopenharmony_ci break; 7658c2ecf20Sopenharmony_ci qp->s_cur = n; 7668c2ecf20Sopenharmony_ci /* 7678c2ecf20Sopenharmony_ci * If we are starting the request from the beginning, 7688c2ecf20Sopenharmony_ci * let the normal send code handle initialization. 7698c2ecf20Sopenharmony_ci */ 7708c2ecf20Sopenharmony_ci if (diff == 0) { 7718c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 7728c2ecf20Sopenharmony_ci goto done; 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci opcode = wqe->wr.opcode; 7758c2ecf20Sopenharmony_ci } 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci /* 7788c2ecf20Sopenharmony_ci * Set the state to restart in the middle of a request. 7798c2ecf20Sopenharmony_ci * Don't change the s_sge, s_cur_sge, or s_cur_size. 7808c2ecf20Sopenharmony_ci * See qib_make_rc_req(). 7818c2ecf20Sopenharmony_ci */ 7828c2ecf20Sopenharmony_ci switch (opcode) { 7838c2ecf20Sopenharmony_ci case IB_WR_SEND: 7848c2ecf20Sopenharmony_ci case IB_WR_SEND_WITH_IMM: 7858c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_RESPONSE_FIRST); 7868c2ecf20Sopenharmony_ci break; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE: 7898c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE_WITH_IMM: 7908c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_RESPONSE_LAST); 7918c2ecf20Sopenharmony_ci break; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci case IB_WR_RDMA_READ: 7948c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_RESPONSE_MIDDLE); 7958c2ecf20Sopenharmony_ci break; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci default: 7988c2ecf20Sopenharmony_ci /* 7998c2ecf20Sopenharmony_ci * This case shouldn't happen since its only 8008c2ecf20Sopenharmony_ci * one PSN per req. 8018c2ecf20Sopenharmony_ci */ 8028c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 8038c2ecf20Sopenharmony_ci } 8048c2ecf20Sopenharmony_cidone: 8058c2ecf20Sopenharmony_ci qp->s_psn = psn; 8068c2ecf20Sopenharmony_ci /* 8078c2ecf20Sopenharmony_ci * Set RVT_S_WAIT_PSN as qib_rc_complete() may start the timer 8088c2ecf20Sopenharmony_ci * asynchronously before the send tasklet can get scheduled. 8098c2ecf20Sopenharmony_ci * Doing it in qib_make_rc_req() is too late. 8108c2ecf20Sopenharmony_ci */ 8118c2ecf20Sopenharmony_ci if ((qib_cmp24(qp->s_psn, qp->s_sending_hpsn) <= 0) && 8128c2ecf20Sopenharmony_ci (qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)) 8138c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_PSN; 8148c2ecf20Sopenharmony_ci} 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci/* 8178c2ecf20Sopenharmony_ci * Back up requester to resend the last un-ACKed request. 8188c2ecf20Sopenharmony_ci * The QP r_lock and s_lock should be held and interrupts disabled. 8198c2ecf20Sopenharmony_ci */ 8208c2ecf20Sopenharmony_civoid qib_restart_rc(struct rvt_qp *qp, u32 psn, int wait) 8218c2ecf20Sopenharmony_ci{ 8228c2ecf20Sopenharmony_ci struct rvt_swqe *wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 8238c2ecf20Sopenharmony_ci struct qib_ibport *ibp; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci if (qp->s_retry == 0) { 8268c2ecf20Sopenharmony_ci if (qp->s_mig_state == IB_MIG_ARMED) { 8278c2ecf20Sopenharmony_ci qib_migrate_qp(qp); 8288c2ecf20Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 8298c2ecf20Sopenharmony_ci } else if (qp->s_last == qp->s_acked) { 8308c2ecf20Sopenharmony_ci rvt_send_complete(qp, wqe, IB_WC_RETRY_EXC_ERR); 8318c2ecf20Sopenharmony_ci rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 8328c2ecf20Sopenharmony_ci return; 8338c2ecf20Sopenharmony_ci } else /* XXX need to handle delayed completion */ 8348c2ecf20Sopenharmony_ci return; 8358c2ecf20Sopenharmony_ci } else 8368c2ecf20Sopenharmony_ci qp->s_retry--; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci ibp = to_iport(qp->ibqp.device, qp->port_num); 8398c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ) 8408c2ecf20Sopenharmony_ci ibp->rvp.n_rc_resends++; 8418c2ecf20Sopenharmony_ci else 8428c2ecf20Sopenharmony_ci ibp->rvp.n_rc_resends += (qp->s_psn - psn) & QIB_PSN_MASK; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_FENCE | RVT_S_WAIT_RDMAR | 8458c2ecf20Sopenharmony_ci RVT_S_WAIT_SSN_CREDIT | RVT_S_WAIT_PSN | 8468c2ecf20Sopenharmony_ci RVT_S_WAIT_ACK); 8478c2ecf20Sopenharmony_ci if (wait) 8488c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_SEND_ONE; 8498c2ecf20Sopenharmony_ci reset_psn(qp, psn); 8508c2ecf20Sopenharmony_ci} 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci/* 8538c2ecf20Sopenharmony_ci * Set qp->s_sending_psn to the next PSN after the given one. 8548c2ecf20Sopenharmony_ci * This would be psn+1 except when RDMA reads are present. 8558c2ecf20Sopenharmony_ci */ 8568c2ecf20Sopenharmony_cistatic void reset_sending_psn(struct rvt_qp *qp, u32 psn) 8578c2ecf20Sopenharmony_ci{ 8588c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 8598c2ecf20Sopenharmony_ci u32 n = qp->s_last; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci /* Find the work request corresponding to the given PSN. */ 8628c2ecf20Sopenharmony_ci for (;;) { 8638c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, n); 8648c2ecf20Sopenharmony_ci if (qib_cmp24(psn, wqe->lpsn) <= 0) { 8658c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ) 8668c2ecf20Sopenharmony_ci qp->s_sending_psn = wqe->lpsn + 1; 8678c2ecf20Sopenharmony_ci else 8688c2ecf20Sopenharmony_ci qp->s_sending_psn = psn + 1; 8698c2ecf20Sopenharmony_ci break; 8708c2ecf20Sopenharmony_ci } 8718c2ecf20Sopenharmony_ci if (++n == qp->s_size) 8728c2ecf20Sopenharmony_ci n = 0; 8738c2ecf20Sopenharmony_ci if (n == qp->s_tail) 8748c2ecf20Sopenharmony_ci break; 8758c2ecf20Sopenharmony_ci } 8768c2ecf20Sopenharmony_ci} 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci/* 8798c2ecf20Sopenharmony_ci * This should be called with the QP s_lock held and interrupts disabled. 8808c2ecf20Sopenharmony_ci */ 8818c2ecf20Sopenharmony_civoid qib_rc_send_complete(struct rvt_qp *qp, struct ib_header *hdr) 8828c2ecf20Sopenharmony_ci{ 8838c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr; 8848c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 8858c2ecf20Sopenharmony_ci u32 opcode; 8868c2ecf20Sopenharmony_ci u32 psn; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_SEND_OR_FLUSH_OR_RECV_OK)) 8898c2ecf20Sopenharmony_ci return; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci /* Find out where the BTH is */ 8928c2ecf20Sopenharmony_ci if ((be16_to_cpu(hdr->lrh[0]) & 3) == QIB_LRH_BTH) 8938c2ecf20Sopenharmony_ci ohdr = &hdr->u.oth; 8948c2ecf20Sopenharmony_ci else 8958c2ecf20Sopenharmony_ci ohdr = &hdr->u.l.oth; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci opcode = be32_to_cpu(ohdr->bth[0]) >> 24; 8988c2ecf20Sopenharmony_ci if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) && 8998c2ecf20Sopenharmony_ci opcode <= OP(ATOMIC_ACKNOWLEDGE)) { 9008c2ecf20Sopenharmony_ci WARN_ON(!qp->s_rdma_ack_cnt); 9018c2ecf20Sopenharmony_ci qp->s_rdma_ack_cnt--; 9028c2ecf20Sopenharmony_ci return; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci psn = be32_to_cpu(ohdr->bth[2]); 9068c2ecf20Sopenharmony_ci reset_sending_psn(qp, psn); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci /* 9098c2ecf20Sopenharmony_ci * Start timer after a packet requesting an ACK has been sent and 9108c2ecf20Sopenharmony_ci * there are still requests that haven't been acked. 9118c2ecf20Sopenharmony_ci */ 9128c2ecf20Sopenharmony_ci if ((psn & IB_BTH_REQ_ACK) && qp->s_acked != qp->s_tail && 9138c2ecf20Sopenharmony_ci !(qp->s_flags & (RVT_S_TIMER | RVT_S_WAIT_RNR | RVT_S_WAIT_PSN)) && 9148c2ecf20Sopenharmony_ci (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) 9158c2ecf20Sopenharmony_ci rvt_add_retry_timer(qp); 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci while (qp->s_last != qp->s_acked) { 9188c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_last); 9198c2ecf20Sopenharmony_ci if (qib_cmp24(wqe->lpsn, qp->s_sending_psn) >= 0 && 9208c2ecf20Sopenharmony_ci qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) <= 0) 9218c2ecf20Sopenharmony_ci break; 9228c2ecf20Sopenharmony_ci rvt_qp_complete_swqe(qp, 9238c2ecf20Sopenharmony_ci wqe, 9248c2ecf20Sopenharmony_ci ib_qib_wc_opcode[wqe->wr.opcode], 9258c2ecf20Sopenharmony_ci IB_WC_SUCCESS); 9268c2ecf20Sopenharmony_ci } 9278c2ecf20Sopenharmony_ci /* 9288c2ecf20Sopenharmony_ci * If we were waiting for sends to complete before resending, 9298c2ecf20Sopenharmony_ci * and they are now complete, restart sending. 9308c2ecf20Sopenharmony_ci */ 9318c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_PSN && 9328c2ecf20Sopenharmony_ci qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) > 0) { 9338c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_PSN; 9348c2ecf20Sopenharmony_ci qp->s_sending_psn = qp->s_psn; 9358c2ecf20Sopenharmony_ci qp->s_sending_hpsn = qp->s_psn - 1; 9368c2ecf20Sopenharmony_ci qib_schedule_send(qp); 9378c2ecf20Sopenharmony_ci } 9388c2ecf20Sopenharmony_ci} 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_cistatic inline void update_last_psn(struct rvt_qp *qp, u32 psn) 9418c2ecf20Sopenharmony_ci{ 9428c2ecf20Sopenharmony_ci qp->s_last_psn = psn; 9438c2ecf20Sopenharmony_ci} 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci/* 9468c2ecf20Sopenharmony_ci * Generate a SWQE completion. 9478c2ecf20Sopenharmony_ci * This is similar to qib_send_complete but has to check to be sure 9488c2ecf20Sopenharmony_ci * that the SGEs are not being referenced if the SWQE is being resent. 9498c2ecf20Sopenharmony_ci */ 9508c2ecf20Sopenharmony_cistatic struct rvt_swqe *do_rc_completion(struct rvt_qp *qp, 9518c2ecf20Sopenharmony_ci struct rvt_swqe *wqe, 9528c2ecf20Sopenharmony_ci struct qib_ibport *ibp) 9538c2ecf20Sopenharmony_ci{ 9548c2ecf20Sopenharmony_ci /* 9558c2ecf20Sopenharmony_ci * Don't decrement refcount and don't generate a 9568c2ecf20Sopenharmony_ci * completion if the SWQE is being resent until the send 9578c2ecf20Sopenharmony_ci * is finished. 9588c2ecf20Sopenharmony_ci */ 9598c2ecf20Sopenharmony_ci if (qib_cmp24(wqe->lpsn, qp->s_sending_psn) < 0 || 9608c2ecf20Sopenharmony_ci qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) > 0) 9618c2ecf20Sopenharmony_ci rvt_qp_complete_swqe(qp, 9628c2ecf20Sopenharmony_ci wqe, 9638c2ecf20Sopenharmony_ci ib_qib_wc_opcode[wqe->wr.opcode], 9648c2ecf20Sopenharmony_ci IB_WC_SUCCESS); 9658c2ecf20Sopenharmony_ci else 9668c2ecf20Sopenharmony_ci this_cpu_inc(*ibp->rvp.rc_delayed_comp); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 9698c2ecf20Sopenharmony_ci update_last_psn(qp, wqe->lpsn); 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci /* 9728c2ecf20Sopenharmony_ci * If we are completing a request which is in the process of 9738c2ecf20Sopenharmony_ci * being resent, we can stop resending it since we know the 9748c2ecf20Sopenharmony_ci * responder has already seen it. 9758c2ecf20Sopenharmony_ci */ 9768c2ecf20Sopenharmony_ci if (qp->s_acked == qp->s_cur) { 9778c2ecf20Sopenharmony_ci if (++qp->s_cur >= qp->s_size) 9788c2ecf20Sopenharmony_ci qp->s_cur = 0; 9798c2ecf20Sopenharmony_ci qp->s_acked = qp->s_cur; 9808c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_cur); 9818c2ecf20Sopenharmony_ci if (qp->s_acked != qp->s_tail) { 9828c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 9838c2ecf20Sopenharmony_ci qp->s_psn = wqe->psn; 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci } else { 9868c2ecf20Sopenharmony_ci if (++qp->s_acked >= qp->s_size) 9878c2ecf20Sopenharmony_ci qp->s_acked = 0; 9888c2ecf20Sopenharmony_ci if (qp->state == IB_QPS_SQD && qp->s_acked == qp->s_cur) 9898c2ecf20Sopenharmony_ci qp->s_draining = 0; 9908c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 9918c2ecf20Sopenharmony_ci } 9928c2ecf20Sopenharmony_ci return wqe; 9938c2ecf20Sopenharmony_ci} 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci/** 9968c2ecf20Sopenharmony_ci * do_rc_ack - process an incoming RC ACK 9978c2ecf20Sopenharmony_ci * @qp: the QP the ACK came in on 9988c2ecf20Sopenharmony_ci * @psn: the packet sequence number of the ACK 9998c2ecf20Sopenharmony_ci * @opcode: the opcode of the request that resulted in the ACK 10008c2ecf20Sopenharmony_ci * 10018c2ecf20Sopenharmony_ci * This is called from qib_rc_rcv_resp() to process an incoming RC ACK 10028c2ecf20Sopenharmony_ci * for the given QP. 10038c2ecf20Sopenharmony_ci * Called at interrupt level with the QP s_lock held. 10048c2ecf20Sopenharmony_ci * Returns 1 if OK, 0 if current operation should be aborted (NAK). 10058c2ecf20Sopenharmony_ci */ 10068c2ecf20Sopenharmony_cistatic int do_rc_ack(struct rvt_qp *qp, u32 aeth, u32 psn, int opcode, 10078c2ecf20Sopenharmony_ci u64 val, struct qib_ctxtdata *rcd) 10088c2ecf20Sopenharmony_ci{ 10098c2ecf20Sopenharmony_ci struct qib_ibport *ibp; 10108c2ecf20Sopenharmony_ci enum ib_wc_status status; 10118c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 10128c2ecf20Sopenharmony_ci int ret = 0; 10138c2ecf20Sopenharmony_ci u32 ack_psn; 10148c2ecf20Sopenharmony_ci int diff; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci /* 10178c2ecf20Sopenharmony_ci * Note that NAKs implicitly ACK outstanding SEND and RDMA write 10188c2ecf20Sopenharmony_ci * requests and implicitly NAK RDMA read and atomic requests issued 10198c2ecf20Sopenharmony_ci * before the NAK'ed request. The MSN won't include the NAK'ed 10208c2ecf20Sopenharmony_ci * request but will include an ACK'ed request(s). 10218c2ecf20Sopenharmony_ci */ 10228c2ecf20Sopenharmony_ci ack_psn = psn; 10238c2ecf20Sopenharmony_ci if (aeth >> IB_AETH_NAK_SHIFT) 10248c2ecf20Sopenharmony_ci ack_psn--; 10258c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 10268c2ecf20Sopenharmony_ci ibp = to_iport(qp->ibqp.device, qp->port_num); 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci /* 10298c2ecf20Sopenharmony_ci * The MSN might be for a later WQE than the PSN indicates so 10308c2ecf20Sopenharmony_ci * only complete WQEs that the PSN finishes. 10318c2ecf20Sopenharmony_ci */ 10328c2ecf20Sopenharmony_ci while ((diff = qib_cmp24(ack_psn, wqe->lpsn)) >= 0) { 10338c2ecf20Sopenharmony_ci /* 10348c2ecf20Sopenharmony_ci * RDMA_READ_RESPONSE_ONLY is a special case since 10358c2ecf20Sopenharmony_ci * we want to generate completion events for everything 10368c2ecf20Sopenharmony_ci * before the RDMA read, copy the data, then generate 10378c2ecf20Sopenharmony_ci * the completion for the read. 10388c2ecf20Sopenharmony_ci */ 10398c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ && 10408c2ecf20Sopenharmony_ci opcode == OP(RDMA_READ_RESPONSE_ONLY) && 10418c2ecf20Sopenharmony_ci diff == 0) { 10428c2ecf20Sopenharmony_ci ret = 1; 10438c2ecf20Sopenharmony_ci goto bail; 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci /* 10468c2ecf20Sopenharmony_ci * If this request is a RDMA read or atomic, and the ACK is 10478c2ecf20Sopenharmony_ci * for a later operation, this ACK NAKs the RDMA read or 10488c2ecf20Sopenharmony_ci * atomic. In other words, only a RDMA_READ_LAST or ONLY 10498c2ecf20Sopenharmony_ci * can ACK a RDMA read and likewise for atomic ops. Note 10508c2ecf20Sopenharmony_ci * that the NAK case can only happen if relaxed ordering is 10518c2ecf20Sopenharmony_ci * used and requests are sent after an RDMA read or atomic 10528c2ecf20Sopenharmony_ci * is sent but before the response is received. 10538c2ecf20Sopenharmony_ci */ 10548c2ecf20Sopenharmony_ci if ((wqe->wr.opcode == IB_WR_RDMA_READ && 10558c2ecf20Sopenharmony_ci (opcode != OP(RDMA_READ_RESPONSE_LAST) || diff != 0)) || 10568c2ecf20Sopenharmony_ci ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 10578c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) && 10588c2ecf20Sopenharmony_ci (opcode != OP(ATOMIC_ACKNOWLEDGE) || diff != 0))) { 10598c2ecf20Sopenharmony_ci /* Retry this request. */ 10608c2ecf20Sopenharmony_ci if (!(qp->r_flags & RVT_R_RDMAR_SEQ)) { 10618c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RDMAR_SEQ; 10628c2ecf20Sopenharmony_ci qib_restart_rc(qp, qp->s_last_psn + 1, 0); 10638c2ecf20Sopenharmony_ci if (list_empty(&qp->rspwait)) { 10648c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RSP_SEND; 10658c2ecf20Sopenharmony_ci rvt_get_qp(qp); 10668c2ecf20Sopenharmony_ci list_add_tail(&qp->rspwait, 10678c2ecf20Sopenharmony_ci &rcd->qp_wait_list); 10688c2ecf20Sopenharmony_ci } 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci /* 10718c2ecf20Sopenharmony_ci * No need to process the ACK/NAK since we are 10728c2ecf20Sopenharmony_ci * restarting an earlier request. 10738c2ecf20Sopenharmony_ci */ 10748c2ecf20Sopenharmony_ci goto bail; 10758c2ecf20Sopenharmony_ci } 10768c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 10778c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) { 10788c2ecf20Sopenharmony_ci u64 *vaddr = wqe->sg_list[0].vaddr; 10798c2ecf20Sopenharmony_ci *vaddr = val; 10808c2ecf20Sopenharmony_ci } 10818c2ecf20Sopenharmony_ci if (qp->s_num_rd_atomic && 10828c2ecf20Sopenharmony_ci (wqe->wr.opcode == IB_WR_RDMA_READ || 10838c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 10848c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)) { 10858c2ecf20Sopenharmony_ci qp->s_num_rd_atomic--; 10868c2ecf20Sopenharmony_ci /* Restart sending task if fence is complete */ 10878c2ecf20Sopenharmony_ci if ((qp->s_flags & RVT_S_WAIT_FENCE) && 10888c2ecf20Sopenharmony_ci !qp->s_num_rd_atomic) { 10898c2ecf20Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_FENCE | 10908c2ecf20Sopenharmony_ci RVT_S_WAIT_ACK); 10918c2ecf20Sopenharmony_ci qib_schedule_send(qp); 10928c2ecf20Sopenharmony_ci } else if (qp->s_flags & RVT_S_WAIT_RDMAR) { 10938c2ecf20Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_RDMAR | 10948c2ecf20Sopenharmony_ci RVT_S_WAIT_ACK); 10958c2ecf20Sopenharmony_ci qib_schedule_send(qp); 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci wqe = do_rc_completion(qp, wqe, ibp); 10998c2ecf20Sopenharmony_ci if (qp->s_acked == qp->s_tail) 11008c2ecf20Sopenharmony_ci break; 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci switch (aeth >> IB_AETH_NAK_SHIFT) { 11048c2ecf20Sopenharmony_ci case 0: /* ACK */ 11058c2ecf20Sopenharmony_ci this_cpu_inc(*ibp->rvp.rc_acks); 11068c2ecf20Sopenharmony_ci if (qp->s_acked != qp->s_tail) { 11078c2ecf20Sopenharmony_ci /* 11088c2ecf20Sopenharmony_ci * We are expecting more ACKs so 11098c2ecf20Sopenharmony_ci * reset the retransmit timer. 11108c2ecf20Sopenharmony_ci */ 11118c2ecf20Sopenharmony_ci rvt_mod_retry_timer(qp); 11128c2ecf20Sopenharmony_ci /* 11138c2ecf20Sopenharmony_ci * We can stop resending the earlier packets and 11148c2ecf20Sopenharmony_ci * continue with the next packet the receiver wants. 11158c2ecf20Sopenharmony_ci */ 11168c2ecf20Sopenharmony_ci if (qib_cmp24(qp->s_psn, psn) <= 0) 11178c2ecf20Sopenharmony_ci reset_psn(qp, psn + 1); 11188c2ecf20Sopenharmony_ci } else { 11198c2ecf20Sopenharmony_ci /* No more acks - kill all timers */ 11208c2ecf20Sopenharmony_ci rvt_stop_rc_timers(qp); 11218c2ecf20Sopenharmony_ci if (qib_cmp24(qp->s_psn, psn) <= 0) { 11228c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 11238c2ecf20Sopenharmony_ci qp->s_psn = psn + 1; 11248c2ecf20Sopenharmony_ci } 11258c2ecf20Sopenharmony_ci } 11268c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_ACK) { 11278c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_ACK; 11288c2ecf20Sopenharmony_ci qib_schedule_send(qp); 11298c2ecf20Sopenharmony_ci } 11308c2ecf20Sopenharmony_ci rvt_get_credit(qp, aeth); 11318c2ecf20Sopenharmony_ci qp->s_rnr_retry = qp->s_rnr_retry_cnt; 11328c2ecf20Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 11338c2ecf20Sopenharmony_ci update_last_psn(qp, psn); 11348c2ecf20Sopenharmony_ci return 1; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci case 1: /* RNR NAK */ 11378c2ecf20Sopenharmony_ci ibp->rvp.n_rnr_naks++; 11388c2ecf20Sopenharmony_ci if (qp->s_acked == qp->s_tail) 11398c2ecf20Sopenharmony_ci goto bail; 11408c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_RNR) 11418c2ecf20Sopenharmony_ci goto bail; 11428c2ecf20Sopenharmony_ci if (qp->s_rnr_retry == 0) { 11438c2ecf20Sopenharmony_ci status = IB_WC_RNR_RETRY_EXC_ERR; 11448c2ecf20Sopenharmony_ci goto class_b; 11458c2ecf20Sopenharmony_ci } 11468c2ecf20Sopenharmony_ci if (qp->s_rnr_retry_cnt < 7) 11478c2ecf20Sopenharmony_ci qp->s_rnr_retry--; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci /* The last valid PSN is the previous PSN. */ 11508c2ecf20Sopenharmony_ci update_last_psn(qp, psn - 1); 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci ibp->rvp.n_rc_resends += (qp->s_psn - psn) & QIB_PSN_MASK; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci reset_psn(qp, psn); 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_SSN_CREDIT | RVT_S_WAIT_ACK); 11578c2ecf20Sopenharmony_ci rvt_stop_rc_timers(qp); 11588c2ecf20Sopenharmony_ci rvt_add_rnr_timer(qp, aeth); 11598c2ecf20Sopenharmony_ci return 0; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci case 3: /* NAK */ 11628c2ecf20Sopenharmony_ci if (qp->s_acked == qp->s_tail) 11638c2ecf20Sopenharmony_ci goto bail; 11648c2ecf20Sopenharmony_ci /* The last valid PSN is the previous PSN. */ 11658c2ecf20Sopenharmony_ci update_last_psn(qp, psn - 1); 11668c2ecf20Sopenharmony_ci switch ((aeth >> IB_AETH_CREDIT_SHIFT) & 11678c2ecf20Sopenharmony_ci IB_AETH_CREDIT_MASK) { 11688c2ecf20Sopenharmony_ci case 0: /* PSN sequence error */ 11698c2ecf20Sopenharmony_ci ibp->rvp.n_seq_naks++; 11708c2ecf20Sopenharmony_ci /* 11718c2ecf20Sopenharmony_ci * Back up to the responder's expected PSN. 11728c2ecf20Sopenharmony_ci * Note that we might get a NAK in the middle of an 11738c2ecf20Sopenharmony_ci * RDMA READ response which terminates the RDMA 11748c2ecf20Sopenharmony_ci * READ. 11758c2ecf20Sopenharmony_ci */ 11768c2ecf20Sopenharmony_ci qib_restart_rc(qp, psn, 0); 11778c2ecf20Sopenharmony_ci qib_schedule_send(qp); 11788c2ecf20Sopenharmony_ci break; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci case 1: /* Invalid Request */ 11818c2ecf20Sopenharmony_ci status = IB_WC_REM_INV_REQ_ERR; 11828c2ecf20Sopenharmony_ci ibp->rvp.n_other_naks++; 11838c2ecf20Sopenharmony_ci goto class_b; 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci case 2: /* Remote Access Error */ 11868c2ecf20Sopenharmony_ci status = IB_WC_REM_ACCESS_ERR; 11878c2ecf20Sopenharmony_ci ibp->rvp.n_other_naks++; 11888c2ecf20Sopenharmony_ci goto class_b; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci case 3: /* Remote Operation Error */ 11918c2ecf20Sopenharmony_ci status = IB_WC_REM_OP_ERR; 11928c2ecf20Sopenharmony_ci ibp->rvp.n_other_naks++; 11938c2ecf20Sopenharmony_ciclass_b: 11948c2ecf20Sopenharmony_ci if (qp->s_last == qp->s_acked) { 11958c2ecf20Sopenharmony_ci rvt_send_complete(qp, wqe, status); 11968c2ecf20Sopenharmony_ci rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 11978c2ecf20Sopenharmony_ci } 11988c2ecf20Sopenharmony_ci break; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci default: 12018c2ecf20Sopenharmony_ci /* Ignore other reserved NAK error codes */ 12028c2ecf20Sopenharmony_ci goto reserved; 12038c2ecf20Sopenharmony_ci } 12048c2ecf20Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 12058c2ecf20Sopenharmony_ci qp->s_rnr_retry = qp->s_rnr_retry_cnt; 12068c2ecf20Sopenharmony_ci goto bail; 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci default: /* 2: reserved */ 12098c2ecf20Sopenharmony_cireserved: 12108c2ecf20Sopenharmony_ci /* Ignore reserved NAK codes. */ 12118c2ecf20Sopenharmony_ci goto bail; 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_cibail: 12158c2ecf20Sopenharmony_ci rvt_stop_rc_timers(qp); 12168c2ecf20Sopenharmony_ci return ret; 12178c2ecf20Sopenharmony_ci} 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci/* 12208c2ecf20Sopenharmony_ci * We have seen an out of sequence RDMA read middle or last packet. 12218c2ecf20Sopenharmony_ci * This ACKs SENDs and RDMA writes up to the first RDMA read or atomic SWQE. 12228c2ecf20Sopenharmony_ci */ 12238c2ecf20Sopenharmony_cistatic void rdma_seq_err(struct rvt_qp *qp, struct qib_ibport *ibp, u32 psn, 12248c2ecf20Sopenharmony_ci struct qib_ctxtdata *rcd) 12258c2ecf20Sopenharmony_ci{ 12268c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci /* Remove QP from retry timer */ 12298c2ecf20Sopenharmony_ci rvt_stop_rc_timers(qp); 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci while (qib_cmp24(psn, wqe->lpsn) > 0) { 12348c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ || 12358c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 12368c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) 12378c2ecf20Sopenharmony_ci break; 12388c2ecf20Sopenharmony_ci wqe = do_rc_completion(qp, wqe, ibp); 12398c2ecf20Sopenharmony_ci } 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci ibp->rvp.n_rdma_seq++; 12428c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RDMAR_SEQ; 12438c2ecf20Sopenharmony_ci qib_restart_rc(qp, qp->s_last_psn + 1, 0); 12448c2ecf20Sopenharmony_ci if (list_empty(&qp->rspwait)) { 12458c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RSP_SEND; 12468c2ecf20Sopenharmony_ci rvt_get_qp(qp); 12478c2ecf20Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 12488c2ecf20Sopenharmony_ci } 12498c2ecf20Sopenharmony_ci} 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci/** 12528c2ecf20Sopenharmony_ci * qib_rc_rcv_resp - process an incoming RC response packet 12538c2ecf20Sopenharmony_ci * @ibp: the port this packet came in on 12548c2ecf20Sopenharmony_ci * @ohdr: the other headers for this packet 12558c2ecf20Sopenharmony_ci * @data: the packet data 12568c2ecf20Sopenharmony_ci * @tlen: the packet length 12578c2ecf20Sopenharmony_ci * @qp: the QP for this packet 12588c2ecf20Sopenharmony_ci * @opcode: the opcode for this packet 12598c2ecf20Sopenharmony_ci * @psn: the packet sequence number for this packet 12608c2ecf20Sopenharmony_ci * @hdrsize: the header length 12618c2ecf20Sopenharmony_ci * @pmtu: the path MTU 12628c2ecf20Sopenharmony_ci * 12638c2ecf20Sopenharmony_ci * This is called from qib_rc_rcv() to process an incoming RC response 12648c2ecf20Sopenharmony_ci * packet for the given QP. 12658c2ecf20Sopenharmony_ci * Called at interrupt level. 12668c2ecf20Sopenharmony_ci */ 12678c2ecf20Sopenharmony_cistatic void qib_rc_rcv_resp(struct qib_ibport *ibp, 12688c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr, 12698c2ecf20Sopenharmony_ci void *data, u32 tlen, 12708c2ecf20Sopenharmony_ci struct rvt_qp *qp, 12718c2ecf20Sopenharmony_ci u32 opcode, 12728c2ecf20Sopenharmony_ci u32 psn, u32 hdrsize, u32 pmtu, 12738c2ecf20Sopenharmony_ci struct qib_ctxtdata *rcd) 12748c2ecf20Sopenharmony_ci{ 12758c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 12768c2ecf20Sopenharmony_ci struct qib_pportdata *ppd = ppd_from_ibp(ibp); 12778c2ecf20Sopenharmony_ci enum ib_wc_status status; 12788c2ecf20Sopenharmony_ci unsigned long flags; 12798c2ecf20Sopenharmony_ci int diff; 12808c2ecf20Sopenharmony_ci u32 pad; 12818c2ecf20Sopenharmony_ci u32 aeth; 12828c2ecf20Sopenharmony_ci u64 val; 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci if (opcode != OP(RDMA_READ_RESPONSE_MIDDLE)) { 12858c2ecf20Sopenharmony_ci /* 12868c2ecf20Sopenharmony_ci * If ACK'd PSN on SDMA busy list try to make progress to 12878c2ecf20Sopenharmony_ci * reclaim SDMA credits. 12888c2ecf20Sopenharmony_ci */ 12898c2ecf20Sopenharmony_ci if ((qib_cmp24(psn, qp->s_sending_psn) >= 0) && 12908c2ecf20Sopenharmony_ci (qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)) { 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci /* 12938c2ecf20Sopenharmony_ci * If send tasklet not running attempt to progress 12948c2ecf20Sopenharmony_ci * SDMA queue. 12958c2ecf20Sopenharmony_ci */ 12968c2ecf20Sopenharmony_ci if (!(qp->s_flags & RVT_S_BUSY)) { 12978c2ecf20Sopenharmony_ci /* Acquire SDMA Lock */ 12988c2ecf20Sopenharmony_ci spin_lock_irqsave(&ppd->sdma_lock, flags); 12998c2ecf20Sopenharmony_ci /* Invoke sdma make progress */ 13008c2ecf20Sopenharmony_ci qib_sdma_make_progress(ppd); 13018c2ecf20Sopenharmony_ci /* Release SDMA Lock */ 13028c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ppd->sdma_lock, flags); 13038c2ecf20Sopenharmony_ci } 13048c2ecf20Sopenharmony_ci } 13058c2ecf20Sopenharmony_ci } 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 13088c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) 13098c2ecf20Sopenharmony_ci goto ack_done; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci /* Ignore invalid responses. */ 13128c2ecf20Sopenharmony_ci if (qib_cmp24(psn, READ_ONCE(qp->s_next_psn)) >= 0) 13138c2ecf20Sopenharmony_ci goto ack_done; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci /* Ignore duplicate responses. */ 13168c2ecf20Sopenharmony_ci diff = qib_cmp24(psn, qp->s_last_psn); 13178c2ecf20Sopenharmony_ci if (unlikely(diff <= 0)) { 13188c2ecf20Sopenharmony_ci /* Update credits for "ghost" ACKs */ 13198c2ecf20Sopenharmony_ci if (diff == 0 && opcode == OP(ACKNOWLEDGE)) { 13208c2ecf20Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 13218c2ecf20Sopenharmony_ci if ((aeth >> IB_AETH_NAK_SHIFT) == 0) 13228c2ecf20Sopenharmony_ci rvt_get_credit(qp, aeth); 13238c2ecf20Sopenharmony_ci } 13248c2ecf20Sopenharmony_ci goto ack_done; 13258c2ecf20Sopenharmony_ci } 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci /* 13288c2ecf20Sopenharmony_ci * Skip everything other than the PSN we expect, if we are waiting 13298c2ecf20Sopenharmony_ci * for a reply to a restarted RDMA read or atomic op. 13308c2ecf20Sopenharmony_ci */ 13318c2ecf20Sopenharmony_ci if (qp->r_flags & RVT_R_RDMAR_SEQ) { 13328c2ecf20Sopenharmony_ci if (qib_cmp24(psn, qp->s_last_psn + 1) != 0) 13338c2ecf20Sopenharmony_ci goto ack_done; 13348c2ecf20Sopenharmony_ci qp->r_flags &= ~RVT_R_RDMAR_SEQ; 13358c2ecf20Sopenharmony_ci } 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci if (unlikely(qp->s_acked == qp->s_tail)) 13388c2ecf20Sopenharmony_ci goto ack_done; 13398c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 13408c2ecf20Sopenharmony_ci status = IB_WC_SUCCESS; 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci switch (opcode) { 13438c2ecf20Sopenharmony_ci case OP(ACKNOWLEDGE): 13448c2ecf20Sopenharmony_ci case OP(ATOMIC_ACKNOWLEDGE): 13458c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_FIRST): 13468c2ecf20Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 13478c2ecf20Sopenharmony_ci if (opcode == OP(ATOMIC_ACKNOWLEDGE)) 13488c2ecf20Sopenharmony_ci val = ib_u64_get(&ohdr->u.at.atomic_ack_eth); 13498c2ecf20Sopenharmony_ci else 13508c2ecf20Sopenharmony_ci val = 0; 13518c2ecf20Sopenharmony_ci if (!do_rc_ack(qp, aeth, psn, opcode, val, rcd) || 13528c2ecf20Sopenharmony_ci opcode != OP(RDMA_READ_RESPONSE_FIRST)) 13538c2ecf20Sopenharmony_ci goto ack_done; 13548c2ecf20Sopenharmony_ci hdrsize += 4; 13558c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 13568c2ecf20Sopenharmony_ci if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) 13578c2ecf20Sopenharmony_ci goto ack_op_err; 13588c2ecf20Sopenharmony_ci /* 13598c2ecf20Sopenharmony_ci * If this is a response to a resent RDMA read, we 13608c2ecf20Sopenharmony_ci * have to be careful to copy the data to the right 13618c2ecf20Sopenharmony_ci * location. 13628c2ecf20Sopenharmony_ci */ 13638c2ecf20Sopenharmony_ci qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge, 13648c2ecf20Sopenharmony_ci wqe, psn, pmtu); 13658c2ecf20Sopenharmony_ci goto read_middle; 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_MIDDLE): 13688c2ecf20Sopenharmony_ci /* no AETH, no ACK */ 13698c2ecf20Sopenharmony_ci if (unlikely(qib_cmp24(psn, qp->s_last_psn + 1))) 13708c2ecf20Sopenharmony_ci goto ack_seq_err; 13718c2ecf20Sopenharmony_ci if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) 13728c2ecf20Sopenharmony_ci goto ack_op_err; 13738c2ecf20Sopenharmony_ciread_middle: 13748c2ecf20Sopenharmony_ci if (unlikely(tlen != (hdrsize + pmtu + 4))) 13758c2ecf20Sopenharmony_ci goto ack_len_err; 13768c2ecf20Sopenharmony_ci if (unlikely(pmtu >= qp->s_rdma_read_len)) 13778c2ecf20Sopenharmony_ci goto ack_len_err; 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci /* 13808c2ecf20Sopenharmony_ci * We got a response so update the timeout. 13818c2ecf20Sopenharmony_ci * 4.096 usec. * (1 << qp->timeout) 13828c2ecf20Sopenharmony_ci */ 13838c2ecf20Sopenharmony_ci rvt_mod_retry_timer(qp); 13848c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_ACK) { 13858c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_ACK; 13868c2ecf20Sopenharmony_ci qib_schedule_send(qp); 13878c2ecf20Sopenharmony_ci } 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci if (opcode == OP(RDMA_READ_RESPONSE_MIDDLE)) 13908c2ecf20Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci /* 13938c2ecf20Sopenharmony_ci * Update the RDMA receive state but do the copy w/o 13948c2ecf20Sopenharmony_ci * holding the locks and blocking interrupts. 13958c2ecf20Sopenharmony_ci */ 13968c2ecf20Sopenharmony_ci qp->s_rdma_read_len -= pmtu; 13978c2ecf20Sopenharmony_ci update_last_psn(qp, psn); 13988c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 13998c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->s_rdma_read_sge, 14008c2ecf20Sopenharmony_ci data, pmtu, false, false); 14018c2ecf20Sopenharmony_ci goto bail; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_ONLY): 14048c2ecf20Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 14058c2ecf20Sopenharmony_ci if (!do_rc_ack(qp, aeth, psn, opcode, 0, rcd)) 14068c2ecf20Sopenharmony_ci goto ack_done; 14078c2ecf20Sopenharmony_ci /* Get the number of bytes the message was padded by. */ 14088c2ecf20Sopenharmony_ci pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; 14098c2ecf20Sopenharmony_ci /* 14108c2ecf20Sopenharmony_ci * Check that the data size is >= 0 && <= pmtu. 14118c2ecf20Sopenharmony_ci * Remember to account for the AETH header (4) and 14128c2ecf20Sopenharmony_ci * ICRC (4). 14138c2ecf20Sopenharmony_ci */ 14148c2ecf20Sopenharmony_ci if (unlikely(tlen < (hdrsize + pad + 8))) 14158c2ecf20Sopenharmony_ci goto ack_len_err; 14168c2ecf20Sopenharmony_ci /* 14178c2ecf20Sopenharmony_ci * If this is a response to a resent RDMA read, we 14188c2ecf20Sopenharmony_ci * have to be careful to copy the data to the right 14198c2ecf20Sopenharmony_ci * location. 14208c2ecf20Sopenharmony_ci */ 14218c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 14228c2ecf20Sopenharmony_ci qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge, 14238c2ecf20Sopenharmony_ci wqe, psn, pmtu); 14248c2ecf20Sopenharmony_ci goto read_last; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_LAST): 14278c2ecf20Sopenharmony_ci /* ACKs READ req. */ 14288c2ecf20Sopenharmony_ci if (unlikely(qib_cmp24(psn, qp->s_last_psn + 1))) 14298c2ecf20Sopenharmony_ci goto ack_seq_err; 14308c2ecf20Sopenharmony_ci if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) 14318c2ecf20Sopenharmony_ci goto ack_op_err; 14328c2ecf20Sopenharmony_ci /* Get the number of bytes the message was padded by. */ 14338c2ecf20Sopenharmony_ci pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; 14348c2ecf20Sopenharmony_ci /* 14358c2ecf20Sopenharmony_ci * Check that the data size is >= 1 && <= pmtu. 14368c2ecf20Sopenharmony_ci * Remember to account for the AETH header (4) and 14378c2ecf20Sopenharmony_ci * ICRC (4). 14388c2ecf20Sopenharmony_ci */ 14398c2ecf20Sopenharmony_ci if (unlikely(tlen <= (hdrsize + pad + 8))) 14408c2ecf20Sopenharmony_ci goto ack_len_err; 14418c2ecf20Sopenharmony_ciread_last: 14428c2ecf20Sopenharmony_ci tlen -= hdrsize + pad + 8; 14438c2ecf20Sopenharmony_ci if (unlikely(tlen != qp->s_rdma_read_len)) 14448c2ecf20Sopenharmony_ci goto ack_len_err; 14458c2ecf20Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 14468c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->s_rdma_read_sge, 14478c2ecf20Sopenharmony_ci data, tlen, false, false); 14488c2ecf20Sopenharmony_ci WARN_ON(qp->s_rdma_read_sge.num_sge); 14498c2ecf20Sopenharmony_ci (void) do_rc_ack(qp, aeth, psn, 14508c2ecf20Sopenharmony_ci OP(RDMA_READ_RESPONSE_LAST), 0, rcd); 14518c2ecf20Sopenharmony_ci goto ack_done; 14528c2ecf20Sopenharmony_ci } 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ciack_op_err: 14558c2ecf20Sopenharmony_ci status = IB_WC_LOC_QP_OP_ERR; 14568c2ecf20Sopenharmony_ci goto ack_err; 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ciack_seq_err: 14598c2ecf20Sopenharmony_ci rdma_seq_err(qp, ibp, psn, rcd); 14608c2ecf20Sopenharmony_ci goto ack_done; 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ciack_len_err: 14638c2ecf20Sopenharmony_ci status = IB_WC_LOC_LEN_ERR; 14648c2ecf20Sopenharmony_ciack_err: 14658c2ecf20Sopenharmony_ci if (qp->s_last == qp->s_acked) { 14668c2ecf20Sopenharmony_ci rvt_send_complete(qp, wqe, status); 14678c2ecf20Sopenharmony_ci rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 14688c2ecf20Sopenharmony_ci } 14698c2ecf20Sopenharmony_ciack_done: 14708c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 14718c2ecf20Sopenharmony_cibail: 14728c2ecf20Sopenharmony_ci return; 14738c2ecf20Sopenharmony_ci} 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci/** 14768c2ecf20Sopenharmony_ci * qib_rc_rcv_error - process an incoming duplicate or error RC packet 14778c2ecf20Sopenharmony_ci * @ohdr: the other headers for this packet 14788c2ecf20Sopenharmony_ci * @data: the packet data 14798c2ecf20Sopenharmony_ci * @qp: the QP for this packet 14808c2ecf20Sopenharmony_ci * @opcode: the opcode for this packet 14818c2ecf20Sopenharmony_ci * @psn: the packet sequence number for this packet 14828c2ecf20Sopenharmony_ci * @diff: the difference between the PSN and the expected PSN 14838c2ecf20Sopenharmony_ci * 14848c2ecf20Sopenharmony_ci * This is called from qib_rc_rcv() to process an unexpected 14858c2ecf20Sopenharmony_ci * incoming RC packet for the given QP. 14868c2ecf20Sopenharmony_ci * Called at interrupt level. 14878c2ecf20Sopenharmony_ci * Return 1 if no more processing is needed; otherwise return 0 to 14888c2ecf20Sopenharmony_ci * schedule a response to be sent. 14898c2ecf20Sopenharmony_ci */ 14908c2ecf20Sopenharmony_cistatic int qib_rc_rcv_error(struct ib_other_headers *ohdr, 14918c2ecf20Sopenharmony_ci void *data, 14928c2ecf20Sopenharmony_ci struct rvt_qp *qp, 14938c2ecf20Sopenharmony_ci u32 opcode, 14948c2ecf20Sopenharmony_ci u32 psn, 14958c2ecf20Sopenharmony_ci int diff, 14968c2ecf20Sopenharmony_ci struct qib_ctxtdata *rcd) 14978c2ecf20Sopenharmony_ci{ 14988c2ecf20Sopenharmony_ci struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); 14998c2ecf20Sopenharmony_ci struct rvt_ack_entry *e; 15008c2ecf20Sopenharmony_ci unsigned long flags; 15018c2ecf20Sopenharmony_ci u8 i, prev; 15028c2ecf20Sopenharmony_ci int old_req; 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci if (diff > 0) { 15058c2ecf20Sopenharmony_ci /* 15068c2ecf20Sopenharmony_ci * Packet sequence error. 15078c2ecf20Sopenharmony_ci * A NAK will ACK earlier sends and RDMA writes. 15088c2ecf20Sopenharmony_ci * Don't queue the NAK if we already sent one. 15098c2ecf20Sopenharmony_ci */ 15108c2ecf20Sopenharmony_ci if (!qp->r_nak_state) { 15118c2ecf20Sopenharmony_ci ibp->rvp.n_rc_seqnak++; 15128c2ecf20Sopenharmony_ci qp->r_nak_state = IB_NAK_PSN_ERROR; 15138c2ecf20Sopenharmony_ci /* Use the expected PSN. */ 15148c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 15158c2ecf20Sopenharmony_ci /* 15168c2ecf20Sopenharmony_ci * Wait to send the sequence NAK until all packets 15178c2ecf20Sopenharmony_ci * in the receive queue have been processed. 15188c2ecf20Sopenharmony_ci * Otherwise, we end up propagating congestion. 15198c2ecf20Sopenharmony_ci */ 15208c2ecf20Sopenharmony_ci if (list_empty(&qp->rspwait)) { 15218c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RSP_NAK; 15228c2ecf20Sopenharmony_ci rvt_get_qp(qp); 15238c2ecf20Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 15248c2ecf20Sopenharmony_ci } 15258c2ecf20Sopenharmony_ci } 15268c2ecf20Sopenharmony_ci goto done; 15278c2ecf20Sopenharmony_ci } 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci /* 15308c2ecf20Sopenharmony_ci * Handle a duplicate request. Don't re-execute SEND, RDMA 15318c2ecf20Sopenharmony_ci * write or atomic op. Don't NAK errors, just silently drop 15328c2ecf20Sopenharmony_ci * the duplicate request. Note that r_sge, r_len, and 15338c2ecf20Sopenharmony_ci * r_rcv_len may be in use so don't modify them. 15348c2ecf20Sopenharmony_ci * 15358c2ecf20Sopenharmony_ci * We are supposed to ACK the earliest duplicate PSN but we 15368c2ecf20Sopenharmony_ci * can coalesce an outstanding duplicate ACK. We have to 15378c2ecf20Sopenharmony_ci * send the earliest so that RDMA reads can be restarted at 15388c2ecf20Sopenharmony_ci * the requester's expected PSN. 15398c2ecf20Sopenharmony_ci * 15408c2ecf20Sopenharmony_ci * First, find where this duplicate PSN falls within the 15418c2ecf20Sopenharmony_ci * ACKs previously sent. 15428c2ecf20Sopenharmony_ci * old_req is true if there is an older response that is scheduled 15438c2ecf20Sopenharmony_ci * to be sent before sending this one. 15448c2ecf20Sopenharmony_ci */ 15458c2ecf20Sopenharmony_ci e = NULL; 15468c2ecf20Sopenharmony_ci old_req = 1; 15478c2ecf20Sopenharmony_ci ibp->rvp.n_rc_dupreq++; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci for (i = qp->r_head_ack_queue; ; i = prev) { 15528c2ecf20Sopenharmony_ci if (i == qp->s_tail_ack_queue) 15538c2ecf20Sopenharmony_ci old_req = 0; 15548c2ecf20Sopenharmony_ci if (i) 15558c2ecf20Sopenharmony_ci prev = i - 1; 15568c2ecf20Sopenharmony_ci else 15578c2ecf20Sopenharmony_ci prev = QIB_MAX_RDMA_ATOMIC; 15588c2ecf20Sopenharmony_ci if (prev == qp->r_head_ack_queue) { 15598c2ecf20Sopenharmony_ci e = NULL; 15608c2ecf20Sopenharmony_ci break; 15618c2ecf20Sopenharmony_ci } 15628c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[prev]; 15638c2ecf20Sopenharmony_ci if (!e->opcode) { 15648c2ecf20Sopenharmony_ci e = NULL; 15658c2ecf20Sopenharmony_ci break; 15668c2ecf20Sopenharmony_ci } 15678c2ecf20Sopenharmony_ci if (qib_cmp24(psn, e->psn) >= 0) { 15688c2ecf20Sopenharmony_ci if (prev == qp->s_tail_ack_queue && 15698c2ecf20Sopenharmony_ci qib_cmp24(psn, e->lpsn) <= 0) 15708c2ecf20Sopenharmony_ci old_req = 0; 15718c2ecf20Sopenharmony_ci break; 15728c2ecf20Sopenharmony_ci } 15738c2ecf20Sopenharmony_ci } 15748c2ecf20Sopenharmony_ci switch (opcode) { 15758c2ecf20Sopenharmony_ci case OP(RDMA_READ_REQUEST): { 15768c2ecf20Sopenharmony_ci struct ib_reth *reth; 15778c2ecf20Sopenharmony_ci u32 offset; 15788c2ecf20Sopenharmony_ci u32 len; 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci /* 15818c2ecf20Sopenharmony_ci * If we didn't find the RDMA read request in the ack queue, 15828c2ecf20Sopenharmony_ci * we can ignore this request. 15838c2ecf20Sopenharmony_ci */ 15848c2ecf20Sopenharmony_ci if (!e || e->opcode != OP(RDMA_READ_REQUEST)) 15858c2ecf20Sopenharmony_ci goto unlock_done; 15868c2ecf20Sopenharmony_ci /* RETH comes after BTH */ 15878c2ecf20Sopenharmony_ci reth = &ohdr->u.rc.reth; 15888c2ecf20Sopenharmony_ci /* 15898c2ecf20Sopenharmony_ci * Address range must be a subset of the original 15908c2ecf20Sopenharmony_ci * request and start on pmtu boundaries. 15918c2ecf20Sopenharmony_ci * We reuse the old ack_queue slot since the requester 15928c2ecf20Sopenharmony_ci * should not back up and request an earlier PSN for the 15938c2ecf20Sopenharmony_ci * same request. 15948c2ecf20Sopenharmony_ci */ 15958c2ecf20Sopenharmony_ci offset = ((psn - e->psn) & QIB_PSN_MASK) * 15968c2ecf20Sopenharmony_ci qp->pmtu; 15978c2ecf20Sopenharmony_ci len = be32_to_cpu(reth->length); 15988c2ecf20Sopenharmony_ci if (unlikely(offset + len != e->rdma_sge.sge_length)) 15998c2ecf20Sopenharmony_ci goto unlock_done; 16008c2ecf20Sopenharmony_ci if (e->rdma_sge.mr) { 16018c2ecf20Sopenharmony_ci rvt_put_mr(e->rdma_sge.mr); 16028c2ecf20Sopenharmony_ci e->rdma_sge.mr = NULL; 16038c2ecf20Sopenharmony_ci } 16048c2ecf20Sopenharmony_ci if (len != 0) { 16058c2ecf20Sopenharmony_ci u32 rkey = be32_to_cpu(reth->rkey); 16068c2ecf20Sopenharmony_ci u64 vaddr = be64_to_cpu(reth->vaddr); 16078c2ecf20Sopenharmony_ci int ok; 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci ok = rvt_rkey_ok(qp, &e->rdma_sge, len, vaddr, rkey, 16108c2ecf20Sopenharmony_ci IB_ACCESS_REMOTE_READ); 16118c2ecf20Sopenharmony_ci if (unlikely(!ok)) 16128c2ecf20Sopenharmony_ci goto unlock_done; 16138c2ecf20Sopenharmony_ci } else { 16148c2ecf20Sopenharmony_ci e->rdma_sge.vaddr = NULL; 16158c2ecf20Sopenharmony_ci e->rdma_sge.length = 0; 16168c2ecf20Sopenharmony_ci e->rdma_sge.sge_length = 0; 16178c2ecf20Sopenharmony_ci } 16188c2ecf20Sopenharmony_ci e->psn = psn; 16198c2ecf20Sopenharmony_ci if (old_req) 16208c2ecf20Sopenharmony_ci goto unlock_done; 16218c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = prev; 16228c2ecf20Sopenharmony_ci break; 16238c2ecf20Sopenharmony_ci } 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ci case OP(COMPARE_SWAP): 16268c2ecf20Sopenharmony_ci case OP(FETCH_ADD): { 16278c2ecf20Sopenharmony_ci /* 16288c2ecf20Sopenharmony_ci * If we didn't find the atomic request in the ack queue 16298c2ecf20Sopenharmony_ci * or the send tasklet is already backed up to send an 16308c2ecf20Sopenharmony_ci * earlier entry, we can ignore this request. 16318c2ecf20Sopenharmony_ci */ 16328c2ecf20Sopenharmony_ci if (!e || e->opcode != (u8) opcode || old_req) 16338c2ecf20Sopenharmony_ci goto unlock_done; 16348c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = prev; 16358c2ecf20Sopenharmony_ci break; 16368c2ecf20Sopenharmony_ci } 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci default: 16398c2ecf20Sopenharmony_ci /* 16408c2ecf20Sopenharmony_ci * Ignore this operation if it doesn't request an ACK 16418c2ecf20Sopenharmony_ci * or an earlier RDMA read or atomic is going to be resent. 16428c2ecf20Sopenharmony_ci */ 16438c2ecf20Sopenharmony_ci if (!(psn & IB_BTH_REQ_ACK) || old_req) 16448c2ecf20Sopenharmony_ci goto unlock_done; 16458c2ecf20Sopenharmony_ci /* 16468c2ecf20Sopenharmony_ci * Resend the most recent ACK if this request is 16478c2ecf20Sopenharmony_ci * after all the previous RDMA reads and atomics. 16488c2ecf20Sopenharmony_ci */ 16498c2ecf20Sopenharmony_ci if (i == qp->r_head_ack_queue) { 16508c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 16518c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 16528c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn - 1; 16538c2ecf20Sopenharmony_ci goto send_ack; 16548c2ecf20Sopenharmony_ci } 16558c2ecf20Sopenharmony_ci /* 16568c2ecf20Sopenharmony_ci * Try to send a simple ACK to work around a Mellanox bug 16578c2ecf20Sopenharmony_ci * which doesn't accept a RDMA read response or atomic 16588c2ecf20Sopenharmony_ci * response as an ACK for earlier SENDs or RDMA writes. 16598c2ecf20Sopenharmony_ci */ 16608c2ecf20Sopenharmony_ci if (!(qp->s_flags & RVT_S_RESP_PENDING)) { 16618c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 16628c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 16638c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->s_ack_queue[i].psn - 1; 16648c2ecf20Sopenharmony_ci goto send_ack; 16658c2ecf20Sopenharmony_ci } 16668c2ecf20Sopenharmony_ci /* 16678c2ecf20Sopenharmony_ci * Resend the RDMA read or atomic op which 16688c2ecf20Sopenharmony_ci * ACKs this duplicate request. 16698c2ecf20Sopenharmony_ci */ 16708c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = i; 16718c2ecf20Sopenharmony_ci break; 16728c2ecf20Sopenharmony_ci } 16738c2ecf20Sopenharmony_ci qp->s_ack_state = OP(ACKNOWLEDGE); 16748c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_RESP_PENDING; 16758c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 16768c2ecf20Sopenharmony_ci qib_schedule_send(qp); 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_ciunlock_done: 16798c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 16808c2ecf20Sopenharmony_cidone: 16818c2ecf20Sopenharmony_ci return 1; 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_cisend_ack: 16848c2ecf20Sopenharmony_ci return 0; 16858c2ecf20Sopenharmony_ci} 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_cistatic inline void qib_update_ack_queue(struct rvt_qp *qp, unsigned n) 16888c2ecf20Sopenharmony_ci{ 16898c2ecf20Sopenharmony_ci unsigned next; 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci next = n + 1; 16928c2ecf20Sopenharmony_ci if (next > QIB_MAX_RDMA_ATOMIC) 16938c2ecf20Sopenharmony_ci next = 0; 16948c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = next; 16958c2ecf20Sopenharmony_ci qp->s_ack_state = OP(ACKNOWLEDGE); 16968c2ecf20Sopenharmony_ci} 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci/** 16998c2ecf20Sopenharmony_ci * qib_rc_rcv - process an incoming RC packet 17008c2ecf20Sopenharmony_ci * @rcd: the context pointer 17018c2ecf20Sopenharmony_ci * @hdr: the header of this packet 17028c2ecf20Sopenharmony_ci * @has_grh: true if the header has a GRH 17038c2ecf20Sopenharmony_ci * @data: the packet data 17048c2ecf20Sopenharmony_ci * @tlen: the packet length 17058c2ecf20Sopenharmony_ci * @qp: the QP for this packet 17068c2ecf20Sopenharmony_ci * 17078c2ecf20Sopenharmony_ci * This is called from qib_qp_rcv() to process an incoming RC packet 17088c2ecf20Sopenharmony_ci * for the given QP. 17098c2ecf20Sopenharmony_ci * Called at interrupt level. 17108c2ecf20Sopenharmony_ci */ 17118c2ecf20Sopenharmony_civoid qib_rc_rcv(struct qib_ctxtdata *rcd, struct ib_header *hdr, 17128c2ecf20Sopenharmony_ci int has_grh, void *data, u32 tlen, struct rvt_qp *qp) 17138c2ecf20Sopenharmony_ci{ 17148c2ecf20Sopenharmony_ci struct qib_ibport *ibp = &rcd->ppd->ibport_data; 17158c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr; 17168c2ecf20Sopenharmony_ci u32 opcode; 17178c2ecf20Sopenharmony_ci u32 hdrsize; 17188c2ecf20Sopenharmony_ci u32 psn; 17198c2ecf20Sopenharmony_ci u32 pad; 17208c2ecf20Sopenharmony_ci struct ib_wc wc; 17218c2ecf20Sopenharmony_ci u32 pmtu = qp->pmtu; 17228c2ecf20Sopenharmony_ci int diff; 17238c2ecf20Sopenharmony_ci struct ib_reth *reth; 17248c2ecf20Sopenharmony_ci unsigned long flags; 17258c2ecf20Sopenharmony_ci int ret; 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci /* Check for GRH */ 17288c2ecf20Sopenharmony_ci if (!has_grh) { 17298c2ecf20Sopenharmony_ci ohdr = &hdr->u.oth; 17308c2ecf20Sopenharmony_ci hdrsize = 8 + 12; /* LRH + BTH */ 17318c2ecf20Sopenharmony_ci } else { 17328c2ecf20Sopenharmony_ci ohdr = &hdr->u.l.oth; 17338c2ecf20Sopenharmony_ci hdrsize = 8 + 40 + 12; /* LRH + GRH + BTH */ 17348c2ecf20Sopenharmony_ci } 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci opcode = be32_to_cpu(ohdr->bth[0]); 17378c2ecf20Sopenharmony_ci if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode)) 17388c2ecf20Sopenharmony_ci return; 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci psn = be32_to_cpu(ohdr->bth[2]); 17418c2ecf20Sopenharmony_ci opcode >>= 24; 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci /* 17448c2ecf20Sopenharmony_ci * Process responses (ACKs) before anything else. Note that the 17458c2ecf20Sopenharmony_ci * packet sequence number will be for something in the send work 17468c2ecf20Sopenharmony_ci * queue rather than the expected receive packet sequence number. 17478c2ecf20Sopenharmony_ci * In other words, this QP is the requester. 17488c2ecf20Sopenharmony_ci */ 17498c2ecf20Sopenharmony_ci if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) && 17508c2ecf20Sopenharmony_ci opcode <= OP(ATOMIC_ACKNOWLEDGE)) { 17518c2ecf20Sopenharmony_ci qib_rc_rcv_resp(ibp, ohdr, data, tlen, qp, opcode, psn, 17528c2ecf20Sopenharmony_ci hdrsize, pmtu, rcd); 17538c2ecf20Sopenharmony_ci return; 17548c2ecf20Sopenharmony_ci } 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci /* Compute 24 bits worth of difference. */ 17578c2ecf20Sopenharmony_ci diff = qib_cmp24(psn, qp->r_psn); 17588c2ecf20Sopenharmony_ci if (unlikely(diff)) { 17598c2ecf20Sopenharmony_ci if (qib_rc_rcv_error(ohdr, data, qp, opcode, psn, diff, rcd)) 17608c2ecf20Sopenharmony_ci return; 17618c2ecf20Sopenharmony_ci goto send_ack; 17628c2ecf20Sopenharmony_ci } 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci /* Check for opcode sequence errors. */ 17658c2ecf20Sopenharmony_ci switch (qp->r_state) { 17668c2ecf20Sopenharmony_ci case OP(SEND_FIRST): 17678c2ecf20Sopenharmony_ci case OP(SEND_MIDDLE): 17688c2ecf20Sopenharmony_ci if (opcode == OP(SEND_MIDDLE) || 17698c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST) || 17708c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST_WITH_IMMEDIATE)) 17718c2ecf20Sopenharmony_ci break; 17728c2ecf20Sopenharmony_ci goto nack_inv; 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 17758c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 17768c2ecf20Sopenharmony_ci if (opcode == OP(RDMA_WRITE_MIDDLE) || 17778c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST) || 17788c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) 17798c2ecf20Sopenharmony_ci break; 17808c2ecf20Sopenharmony_ci goto nack_inv; 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci default: 17838c2ecf20Sopenharmony_ci if (opcode == OP(SEND_MIDDLE) || 17848c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST) || 17858c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST_WITH_IMMEDIATE) || 17868c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_MIDDLE) || 17878c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST) || 17888c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) 17898c2ecf20Sopenharmony_ci goto nack_inv; 17908c2ecf20Sopenharmony_ci /* 17918c2ecf20Sopenharmony_ci * Note that it is up to the requester to not send a new 17928c2ecf20Sopenharmony_ci * RDMA read or atomic operation before receiving an ACK 17938c2ecf20Sopenharmony_ci * for the previous operation. 17948c2ecf20Sopenharmony_ci */ 17958c2ecf20Sopenharmony_ci break; 17968c2ecf20Sopenharmony_ci } 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci if (qp->state == IB_QPS_RTR && !(qp->r_flags & RVT_R_COMM_EST)) 17998c2ecf20Sopenharmony_ci rvt_comm_est(qp); 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci /* OK, process the packet. */ 18028c2ecf20Sopenharmony_ci switch (opcode) { 18038c2ecf20Sopenharmony_ci case OP(SEND_FIRST): 18048c2ecf20Sopenharmony_ci ret = rvt_get_rwqe(qp, false); 18058c2ecf20Sopenharmony_ci if (ret < 0) 18068c2ecf20Sopenharmony_ci goto nack_op_err; 18078c2ecf20Sopenharmony_ci if (!ret) 18088c2ecf20Sopenharmony_ci goto rnr_nak; 18098c2ecf20Sopenharmony_ci qp->r_rcv_len = 0; 18108c2ecf20Sopenharmony_ci fallthrough; 18118c2ecf20Sopenharmony_ci case OP(SEND_MIDDLE): 18128c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 18138c2ecf20Sopenharmony_cisend_middle: 18148c2ecf20Sopenharmony_ci /* Check for invalid length PMTU or posted rwqe len. */ 18158c2ecf20Sopenharmony_ci if (unlikely(tlen != (hdrsize + pmtu + 4))) 18168c2ecf20Sopenharmony_ci goto nack_inv; 18178c2ecf20Sopenharmony_ci qp->r_rcv_len += pmtu; 18188c2ecf20Sopenharmony_ci if (unlikely(qp->r_rcv_len > qp->r_len)) 18198c2ecf20Sopenharmony_ci goto nack_inv; 18208c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, pmtu, true, false); 18218c2ecf20Sopenharmony_ci break; 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE): 18248c2ecf20Sopenharmony_ci /* consume RWQE */ 18258c2ecf20Sopenharmony_ci ret = rvt_get_rwqe(qp, true); 18268c2ecf20Sopenharmony_ci if (ret < 0) 18278c2ecf20Sopenharmony_ci goto nack_op_err; 18288c2ecf20Sopenharmony_ci if (!ret) 18298c2ecf20Sopenharmony_ci goto rnr_nak; 18308c2ecf20Sopenharmony_ci goto send_last_imm; 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci case OP(SEND_ONLY): 18338c2ecf20Sopenharmony_ci case OP(SEND_ONLY_WITH_IMMEDIATE): 18348c2ecf20Sopenharmony_ci ret = rvt_get_rwqe(qp, false); 18358c2ecf20Sopenharmony_ci if (ret < 0) 18368c2ecf20Sopenharmony_ci goto nack_op_err; 18378c2ecf20Sopenharmony_ci if (!ret) 18388c2ecf20Sopenharmony_ci goto rnr_nak; 18398c2ecf20Sopenharmony_ci qp->r_rcv_len = 0; 18408c2ecf20Sopenharmony_ci if (opcode == OP(SEND_ONLY)) 18418c2ecf20Sopenharmony_ci goto no_immediate_data; 18428c2ecf20Sopenharmony_ci fallthrough; /* for SEND_ONLY_WITH_IMMEDIATE */ 18438c2ecf20Sopenharmony_ci case OP(SEND_LAST_WITH_IMMEDIATE): 18448c2ecf20Sopenharmony_cisend_last_imm: 18458c2ecf20Sopenharmony_ci wc.ex.imm_data = ohdr->u.imm_data; 18468c2ecf20Sopenharmony_ci hdrsize += 4; 18478c2ecf20Sopenharmony_ci wc.wc_flags = IB_WC_WITH_IMM; 18488c2ecf20Sopenharmony_ci goto send_last; 18498c2ecf20Sopenharmony_ci case OP(SEND_LAST): 18508c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_LAST): 18518c2ecf20Sopenharmony_cino_immediate_data: 18528c2ecf20Sopenharmony_ci wc.wc_flags = 0; 18538c2ecf20Sopenharmony_ci wc.ex.imm_data = 0; 18548c2ecf20Sopenharmony_cisend_last: 18558c2ecf20Sopenharmony_ci /* Get the number of bytes the message was padded by. */ 18568c2ecf20Sopenharmony_ci pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; 18578c2ecf20Sopenharmony_ci /* Check for invalid length. */ 18588c2ecf20Sopenharmony_ci /* XXX LAST len should be >= 1 */ 18598c2ecf20Sopenharmony_ci if (unlikely(tlen < (hdrsize + pad + 4))) 18608c2ecf20Sopenharmony_ci goto nack_inv; 18618c2ecf20Sopenharmony_ci /* Don't count the CRC. */ 18628c2ecf20Sopenharmony_ci tlen -= (hdrsize + pad + 4); 18638c2ecf20Sopenharmony_ci wc.byte_len = tlen + qp->r_rcv_len; 18648c2ecf20Sopenharmony_ci if (unlikely(wc.byte_len > qp->r_len)) 18658c2ecf20Sopenharmony_ci goto nack_inv; 18668c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, tlen, true, false); 18678c2ecf20Sopenharmony_ci rvt_put_ss(&qp->r_sge); 18688c2ecf20Sopenharmony_ci qp->r_msn++; 18698c2ecf20Sopenharmony_ci if (!test_and_clear_bit(RVT_R_WRID_VALID, &qp->r_aflags)) 18708c2ecf20Sopenharmony_ci break; 18718c2ecf20Sopenharmony_ci wc.wr_id = qp->r_wr_id; 18728c2ecf20Sopenharmony_ci wc.status = IB_WC_SUCCESS; 18738c2ecf20Sopenharmony_ci if (opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE) || 18748c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) 18758c2ecf20Sopenharmony_ci wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; 18768c2ecf20Sopenharmony_ci else 18778c2ecf20Sopenharmony_ci wc.opcode = IB_WC_RECV; 18788c2ecf20Sopenharmony_ci wc.qp = &qp->ibqp; 18798c2ecf20Sopenharmony_ci wc.src_qp = qp->remote_qpn; 18808c2ecf20Sopenharmony_ci wc.slid = rdma_ah_get_dlid(&qp->remote_ah_attr); 18818c2ecf20Sopenharmony_ci wc.sl = rdma_ah_get_sl(&qp->remote_ah_attr); 18828c2ecf20Sopenharmony_ci /* zero fields that are N/A */ 18838c2ecf20Sopenharmony_ci wc.vendor_err = 0; 18848c2ecf20Sopenharmony_ci wc.pkey_index = 0; 18858c2ecf20Sopenharmony_ci wc.dlid_path_bits = 0; 18868c2ecf20Sopenharmony_ci wc.port_num = 0; 18878c2ecf20Sopenharmony_ci /* Signal completion event if the solicited bit is set. */ 18888c2ecf20Sopenharmony_ci rvt_recv_cq(qp, &wc, ib_bth_is_solicited(ohdr)); 18898c2ecf20Sopenharmony_ci break; 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 18928c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_ONLY): 18938c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): 18948c2ecf20Sopenharmony_ci if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE))) 18958c2ecf20Sopenharmony_ci goto nack_inv; 18968c2ecf20Sopenharmony_ci /* consume RWQE */ 18978c2ecf20Sopenharmony_ci reth = &ohdr->u.rc.reth; 18988c2ecf20Sopenharmony_ci hdrsize += sizeof(*reth); 18998c2ecf20Sopenharmony_ci qp->r_len = be32_to_cpu(reth->length); 19008c2ecf20Sopenharmony_ci qp->r_rcv_len = 0; 19018c2ecf20Sopenharmony_ci qp->r_sge.sg_list = NULL; 19028c2ecf20Sopenharmony_ci if (qp->r_len != 0) { 19038c2ecf20Sopenharmony_ci u32 rkey = be32_to_cpu(reth->rkey); 19048c2ecf20Sopenharmony_ci u64 vaddr = be64_to_cpu(reth->vaddr); 19058c2ecf20Sopenharmony_ci int ok; 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci /* Check rkey & NAK */ 19088c2ecf20Sopenharmony_ci ok = rvt_rkey_ok(qp, &qp->r_sge.sge, qp->r_len, vaddr, 19098c2ecf20Sopenharmony_ci rkey, IB_ACCESS_REMOTE_WRITE); 19108c2ecf20Sopenharmony_ci if (unlikely(!ok)) 19118c2ecf20Sopenharmony_ci goto nack_acc; 19128c2ecf20Sopenharmony_ci qp->r_sge.num_sge = 1; 19138c2ecf20Sopenharmony_ci } else { 19148c2ecf20Sopenharmony_ci qp->r_sge.num_sge = 0; 19158c2ecf20Sopenharmony_ci qp->r_sge.sge.mr = NULL; 19168c2ecf20Sopenharmony_ci qp->r_sge.sge.vaddr = NULL; 19178c2ecf20Sopenharmony_ci qp->r_sge.sge.length = 0; 19188c2ecf20Sopenharmony_ci qp->r_sge.sge.sge_length = 0; 19198c2ecf20Sopenharmony_ci } 19208c2ecf20Sopenharmony_ci if (opcode == OP(RDMA_WRITE_FIRST)) 19218c2ecf20Sopenharmony_ci goto send_middle; 19228c2ecf20Sopenharmony_ci else if (opcode == OP(RDMA_WRITE_ONLY)) 19238c2ecf20Sopenharmony_ci goto no_immediate_data; 19248c2ecf20Sopenharmony_ci ret = rvt_get_rwqe(qp, true); 19258c2ecf20Sopenharmony_ci if (ret < 0) 19268c2ecf20Sopenharmony_ci goto nack_op_err; 19278c2ecf20Sopenharmony_ci if (!ret) { 19288c2ecf20Sopenharmony_ci rvt_put_ss(&qp->r_sge); 19298c2ecf20Sopenharmony_ci goto rnr_nak; 19308c2ecf20Sopenharmony_ci } 19318c2ecf20Sopenharmony_ci wc.ex.imm_data = ohdr->u.rc.imm_data; 19328c2ecf20Sopenharmony_ci hdrsize += 4; 19338c2ecf20Sopenharmony_ci wc.wc_flags = IB_WC_WITH_IMM; 19348c2ecf20Sopenharmony_ci goto send_last; 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci case OP(RDMA_READ_REQUEST): { 19378c2ecf20Sopenharmony_ci struct rvt_ack_entry *e; 19388c2ecf20Sopenharmony_ci u32 len; 19398c2ecf20Sopenharmony_ci u8 next; 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ))) 19428c2ecf20Sopenharmony_ci goto nack_inv; 19438c2ecf20Sopenharmony_ci next = qp->r_head_ack_queue + 1; 19448c2ecf20Sopenharmony_ci /* s_ack_queue is size QIB_MAX_RDMA_ATOMIC+1 so use > not >= */ 19458c2ecf20Sopenharmony_ci if (next > QIB_MAX_RDMA_ATOMIC) 19468c2ecf20Sopenharmony_ci next = 0; 19478c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 19488c2ecf20Sopenharmony_ci if (unlikely(next == qp->s_tail_ack_queue)) { 19498c2ecf20Sopenharmony_ci if (!qp->s_ack_queue[next].sent) 19508c2ecf20Sopenharmony_ci goto nack_inv_unlck; 19518c2ecf20Sopenharmony_ci qib_update_ack_queue(qp, next); 19528c2ecf20Sopenharmony_ci } 19538c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->r_head_ack_queue]; 19548c2ecf20Sopenharmony_ci if (e->opcode == OP(RDMA_READ_REQUEST) && e->rdma_sge.mr) { 19558c2ecf20Sopenharmony_ci rvt_put_mr(e->rdma_sge.mr); 19568c2ecf20Sopenharmony_ci e->rdma_sge.mr = NULL; 19578c2ecf20Sopenharmony_ci } 19588c2ecf20Sopenharmony_ci reth = &ohdr->u.rc.reth; 19598c2ecf20Sopenharmony_ci len = be32_to_cpu(reth->length); 19608c2ecf20Sopenharmony_ci if (len) { 19618c2ecf20Sopenharmony_ci u32 rkey = be32_to_cpu(reth->rkey); 19628c2ecf20Sopenharmony_ci u64 vaddr = be64_to_cpu(reth->vaddr); 19638c2ecf20Sopenharmony_ci int ok; 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci /* Check rkey & NAK */ 19668c2ecf20Sopenharmony_ci ok = rvt_rkey_ok(qp, &e->rdma_sge, len, vaddr, 19678c2ecf20Sopenharmony_ci rkey, IB_ACCESS_REMOTE_READ); 19688c2ecf20Sopenharmony_ci if (unlikely(!ok)) 19698c2ecf20Sopenharmony_ci goto nack_acc_unlck; 19708c2ecf20Sopenharmony_ci /* 19718c2ecf20Sopenharmony_ci * Update the next expected PSN. We add 1 later 19728c2ecf20Sopenharmony_ci * below, so only add the remainder here. 19738c2ecf20Sopenharmony_ci */ 19748c2ecf20Sopenharmony_ci qp->r_psn += rvt_div_mtu(qp, len - 1); 19758c2ecf20Sopenharmony_ci } else { 19768c2ecf20Sopenharmony_ci e->rdma_sge.mr = NULL; 19778c2ecf20Sopenharmony_ci e->rdma_sge.vaddr = NULL; 19788c2ecf20Sopenharmony_ci e->rdma_sge.length = 0; 19798c2ecf20Sopenharmony_ci e->rdma_sge.sge_length = 0; 19808c2ecf20Sopenharmony_ci } 19818c2ecf20Sopenharmony_ci e->opcode = opcode; 19828c2ecf20Sopenharmony_ci e->sent = 0; 19838c2ecf20Sopenharmony_ci e->psn = psn; 19848c2ecf20Sopenharmony_ci e->lpsn = qp->r_psn; 19858c2ecf20Sopenharmony_ci /* 19868c2ecf20Sopenharmony_ci * We need to increment the MSN here instead of when we 19878c2ecf20Sopenharmony_ci * finish sending the result since a duplicate request would 19888c2ecf20Sopenharmony_ci * increment it more than once. 19898c2ecf20Sopenharmony_ci */ 19908c2ecf20Sopenharmony_ci qp->r_msn++; 19918c2ecf20Sopenharmony_ci qp->r_psn++; 19928c2ecf20Sopenharmony_ci qp->r_state = opcode; 19938c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 19948c2ecf20Sopenharmony_ci qp->r_head_ack_queue = next; 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci /* Schedule the send tasklet. */ 19978c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_RESP_PENDING; 19988c2ecf20Sopenharmony_ci qib_schedule_send(qp); 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci goto sunlock; 20018c2ecf20Sopenharmony_ci } 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci case OP(COMPARE_SWAP): 20048c2ecf20Sopenharmony_ci case OP(FETCH_ADD): { 20058c2ecf20Sopenharmony_ci struct ib_atomic_eth *ateth; 20068c2ecf20Sopenharmony_ci struct rvt_ack_entry *e; 20078c2ecf20Sopenharmony_ci u64 vaddr; 20088c2ecf20Sopenharmony_ci atomic64_t *maddr; 20098c2ecf20Sopenharmony_ci u64 sdata; 20108c2ecf20Sopenharmony_ci u32 rkey; 20118c2ecf20Sopenharmony_ci u8 next; 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC))) 20148c2ecf20Sopenharmony_ci goto nack_inv; 20158c2ecf20Sopenharmony_ci next = qp->r_head_ack_queue + 1; 20168c2ecf20Sopenharmony_ci if (next > QIB_MAX_RDMA_ATOMIC) 20178c2ecf20Sopenharmony_ci next = 0; 20188c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 20198c2ecf20Sopenharmony_ci if (unlikely(next == qp->s_tail_ack_queue)) { 20208c2ecf20Sopenharmony_ci if (!qp->s_ack_queue[next].sent) 20218c2ecf20Sopenharmony_ci goto nack_inv_unlck; 20228c2ecf20Sopenharmony_ci qib_update_ack_queue(qp, next); 20238c2ecf20Sopenharmony_ci } 20248c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->r_head_ack_queue]; 20258c2ecf20Sopenharmony_ci if (e->opcode == OP(RDMA_READ_REQUEST) && e->rdma_sge.mr) { 20268c2ecf20Sopenharmony_ci rvt_put_mr(e->rdma_sge.mr); 20278c2ecf20Sopenharmony_ci e->rdma_sge.mr = NULL; 20288c2ecf20Sopenharmony_ci } 20298c2ecf20Sopenharmony_ci ateth = &ohdr->u.atomic_eth; 20308c2ecf20Sopenharmony_ci vaddr = get_ib_ateth_vaddr(ateth); 20318c2ecf20Sopenharmony_ci if (unlikely(vaddr & (sizeof(u64) - 1))) 20328c2ecf20Sopenharmony_ci goto nack_inv_unlck; 20338c2ecf20Sopenharmony_ci rkey = be32_to_cpu(ateth->rkey); 20348c2ecf20Sopenharmony_ci /* Check rkey & NAK */ 20358c2ecf20Sopenharmony_ci if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64), 20368c2ecf20Sopenharmony_ci vaddr, rkey, 20378c2ecf20Sopenharmony_ci IB_ACCESS_REMOTE_ATOMIC))) 20388c2ecf20Sopenharmony_ci goto nack_acc_unlck; 20398c2ecf20Sopenharmony_ci /* Perform atomic OP and save result. */ 20408c2ecf20Sopenharmony_ci maddr = (atomic64_t *) qp->r_sge.sge.vaddr; 20418c2ecf20Sopenharmony_ci sdata = get_ib_ateth_swap(ateth); 20428c2ecf20Sopenharmony_ci e->atomic_data = (opcode == OP(FETCH_ADD)) ? 20438c2ecf20Sopenharmony_ci (u64) atomic64_add_return(sdata, maddr) - sdata : 20448c2ecf20Sopenharmony_ci (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr, 20458c2ecf20Sopenharmony_ci get_ib_ateth_compare(ateth), 20468c2ecf20Sopenharmony_ci sdata); 20478c2ecf20Sopenharmony_ci rvt_put_mr(qp->r_sge.sge.mr); 20488c2ecf20Sopenharmony_ci qp->r_sge.num_sge = 0; 20498c2ecf20Sopenharmony_ci e->opcode = opcode; 20508c2ecf20Sopenharmony_ci e->sent = 0; 20518c2ecf20Sopenharmony_ci e->psn = psn; 20528c2ecf20Sopenharmony_ci e->lpsn = psn; 20538c2ecf20Sopenharmony_ci qp->r_msn++; 20548c2ecf20Sopenharmony_ci qp->r_psn++; 20558c2ecf20Sopenharmony_ci qp->r_state = opcode; 20568c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 20578c2ecf20Sopenharmony_ci qp->r_head_ack_queue = next; 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ci /* Schedule the send tasklet. */ 20608c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_RESP_PENDING; 20618c2ecf20Sopenharmony_ci qib_schedule_send(qp); 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_ci goto sunlock; 20648c2ecf20Sopenharmony_ci } 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_ci default: 20678c2ecf20Sopenharmony_ci /* NAK unknown opcodes. */ 20688c2ecf20Sopenharmony_ci goto nack_inv; 20698c2ecf20Sopenharmony_ci } 20708c2ecf20Sopenharmony_ci qp->r_psn++; 20718c2ecf20Sopenharmony_ci qp->r_state = opcode; 20728c2ecf20Sopenharmony_ci qp->r_ack_psn = psn; 20738c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 20748c2ecf20Sopenharmony_ci /* Send an ACK if requested or required. */ 20758c2ecf20Sopenharmony_ci if (psn & (1 << 31)) 20768c2ecf20Sopenharmony_ci goto send_ack; 20778c2ecf20Sopenharmony_ci return; 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_cirnr_nak: 20808c2ecf20Sopenharmony_ci qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer; 20818c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 20828c2ecf20Sopenharmony_ci /* Queue RNR NAK for later */ 20838c2ecf20Sopenharmony_ci if (list_empty(&qp->rspwait)) { 20848c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RSP_NAK; 20858c2ecf20Sopenharmony_ci rvt_get_qp(qp); 20868c2ecf20Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 20878c2ecf20Sopenharmony_ci } 20888c2ecf20Sopenharmony_ci return; 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_cinack_op_err: 20918c2ecf20Sopenharmony_ci rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR); 20928c2ecf20Sopenharmony_ci qp->r_nak_state = IB_NAK_REMOTE_OPERATIONAL_ERROR; 20938c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 20948c2ecf20Sopenharmony_ci /* Queue NAK for later */ 20958c2ecf20Sopenharmony_ci if (list_empty(&qp->rspwait)) { 20968c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RSP_NAK; 20978c2ecf20Sopenharmony_ci rvt_get_qp(qp); 20988c2ecf20Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 20998c2ecf20Sopenharmony_ci } 21008c2ecf20Sopenharmony_ci return; 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_cinack_inv_unlck: 21038c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 21048c2ecf20Sopenharmony_cinack_inv: 21058c2ecf20Sopenharmony_ci rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR); 21068c2ecf20Sopenharmony_ci qp->r_nak_state = IB_NAK_INVALID_REQUEST; 21078c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 21088c2ecf20Sopenharmony_ci /* Queue NAK for later */ 21098c2ecf20Sopenharmony_ci if (list_empty(&qp->rspwait)) { 21108c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RSP_NAK; 21118c2ecf20Sopenharmony_ci rvt_get_qp(qp); 21128c2ecf20Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 21138c2ecf20Sopenharmony_ci } 21148c2ecf20Sopenharmony_ci return; 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_cinack_acc_unlck: 21178c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 21188c2ecf20Sopenharmony_cinack_acc: 21198c2ecf20Sopenharmony_ci rvt_rc_error(qp, IB_WC_LOC_PROT_ERR); 21208c2ecf20Sopenharmony_ci qp->r_nak_state = IB_NAK_REMOTE_ACCESS_ERROR; 21218c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 21228c2ecf20Sopenharmony_cisend_ack: 21238c2ecf20Sopenharmony_ci qib_send_rc_ack(qp); 21248c2ecf20Sopenharmony_ci return; 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_cisunlock: 21278c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 21288c2ecf20Sopenharmony_ci} 2129