18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright(c) 2015 - 2018 Intel Corporation. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license. When using or 58c2ecf20Sopenharmony_ci * redistributing this file, you may do so under either license. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * GPL LICENSE SUMMARY 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 108c2ecf20Sopenharmony_ci * it under the terms of version 2 of the GNU General Public License as 118c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 148c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 158c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 168c2ecf20Sopenharmony_ci * General Public License for more details. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * BSD LICENSE 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 218c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 228c2ecf20Sopenharmony_ci * are met: 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above copyright 258c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 268c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above copyright 278c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 288c2ecf20Sopenharmony_ci * the documentation and/or other materials provided with the 298c2ecf20Sopenharmony_ci * distribution. 308c2ecf20Sopenharmony_ci * - Neither the name of Intel Corporation nor the names of its 318c2ecf20Sopenharmony_ci * contributors may be used to endorse or promote products derived 328c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 358c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 368c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 378c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 388c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 398c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 408c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 418c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 428c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 438c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 448c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#include <linux/io.h> 498c2ecf20Sopenharmony_ci#include <rdma/rdma_vt.h> 508c2ecf20Sopenharmony_ci#include <rdma/rdmavt_qp.h> 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#include "hfi.h" 538c2ecf20Sopenharmony_ci#include "qp.h" 548c2ecf20Sopenharmony_ci#include "rc.h" 558c2ecf20Sopenharmony_ci#include "verbs_txreq.h" 568c2ecf20Sopenharmony_ci#include "trace.h" 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistruct rvt_ack_entry *find_prev_entry(struct rvt_qp *qp, u32 psn, u8 *prev, 598c2ecf20Sopenharmony_ci u8 *prev_ack, bool *scheduled) 608c2ecf20Sopenharmony_ci __must_hold(&qp->s_lock) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci struct rvt_ack_entry *e = NULL; 638c2ecf20Sopenharmony_ci u8 i, p; 648c2ecf20Sopenharmony_ci bool s = true; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci for (i = qp->r_head_ack_queue; ; i = p) { 678c2ecf20Sopenharmony_ci if (i == qp->s_tail_ack_queue) 688c2ecf20Sopenharmony_ci s = false; 698c2ecf20Sopenharmony_ci if (i) 708c2ecf20Sopenharmony_ci p = i - 1; 718c2ecf20Sopenharmony_ci else 728c2ecf20Sopenharmony_ci p = rvt_size_atomic(ib_to_rvt(qp->ibqp.device)); 738c2ecf20Sopenharmony_ci if (p == qp->r_head_ack_queue) { 748c2ecf20Sopenharmony_ci e = NULL; 758c2ecf20Sopenharmony_ci break; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[p]; 788c2ecf20Sopenharmony_ci if (!e->opcode) { 798c2ecf20Sopenharmony_ci e = NULL; 808c2ecf20Sopenharmony_ci break; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci if (cmp_psn(psn, e->psn) >= 0) { 838c2ecf20Sopenharmony_ci if (p == qp->s_tail_ack_queue && 848c2ecf20Sopenharmony_ci cmp_psn(psn, e->lpsn) <= 0) 858c2ecf20Sopenharmony_ci s = false; 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci if (prev) 908c2ecf20Sopenharmony_ci *prev = p; 918c2ecf20Sopenharmony_ci if (prev_ack) 928c2ecf20Sopenharmony_ci *prev_ack = i; 938c2ecf20Sopenharmony_ci if (scheduled) 948c2ecf20Sopenharmony_ci *scheduled = s; 958c2ecf20Sopenharmony_ci return e; 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/** 998c2ecf20Sopenharmony_ci * make_rc_ack - construct a response packet (ACK, NAK, or RDMA read) 1008c2ecf20Sopenharmony_ci * @dev: the device for this QP 1018c2ecf20Sopenharmony_ci * @qp: a pointer to the QP 1028c2ecf20Sopenharmony_ci * @ohdr: a pointer to the IB header being constructed 1038c2ecf20Sopenharmony_ci * @ps: the xmit packet state 1048c2ecf20Sopenharmony_ci * 1058c2ecf20Sopenharmony_ci * Return 1 if constructed; otherwise, return 0. 1068c2ecf20Sopenharmony_ci * Note that we are in the responder's side of the QP context. 1078c2ecf20Sopenharmony_ci * Note the QP s_lock must be held. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_cistatic int make_rc_ack(struct hfi1_ibdev *dev, struct rvt_qp *qp, 1108c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr, 1118c2ecf20Sopenharmony_ci struct hfi1_pkt_state *ps) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci struct rvt_ack_entry *e; 1148c2ecf20Sopenharmony_ci u32 hwords, hdrlen; 1158c2ecf20Sopenharmony_ci u32 len = 0; 1168c2ecf20Sopenharmony_ci u32 bth0 = 0, bth2 = 0; 1178c2ecf20Sopenharmony_ci u32 bth1 = qp->remote_qpn | (HFI1_CAP_IS_KSET(OPFN) << IB_BTHE_E_SHIFT); 1188c2ecf20Sopenharmony_ci int middle = 0; 1198c2ecf20Sopenharmony_ci u32 pmtu = qp->pmtu; 1208c2ecf20Sopenharmony_ci struct hfi1_qp_priv *qpriv = qp->priv; 1218c2ecf20Sopenharmony_ci bool last_pkt; 1228c2ecf20Sopenharmony_ci u32 delta; 1238c2ecf20Sopenharmony_ci u8 next = qp->s_tail_ack_queue; 1248c2ecf20Sopenharmony_ci struct tid_rdma_request *req; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci trace_hfi1_rsp_make_rc_ack(qp, 0); 1278c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 1288c2ecf20Sopenharmony_ci /* Don't send an ACK if we aren't supposed to. */ 1298c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) 1308c2ecf20Sopenharmony_ci goto bail; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci if (qpriv->hdr_type == HFI1_PKT_TYPE_9B) 1338c2ecf20Sopenharmony_ci /* header size in 32-bit words LRH+BTH = (8+12)/4. */ 1348c2ecf20Sopenharmony_ci hwords = 5; 1358c2ecf20Sopenharmony_ci else 1368c2ecf20Sopenharmony_ci /* header size in 32-bit words 16B LRH+BTH = (16+12)/4. */ 1378c2ecf20Sopenharmony_ci hwords = 7; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci switch (qp->s_ack_state) { 1408c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_LAST): 1418c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_ONLY): 1428c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 1438c2ecf20Sopenharmony_ci release_rdma_sge_mr(e); 1448c2ecf20Sopenharmony_ci fallthrough; 1458c2ecf20Sopenharmony_ci case OP(ATOMIC_ACKNOWLEDGE): 1468c2ecf20Sopenharmony_ci /* 1478c2ecf20Sopenharmony_ci * We can increment the tail pointer now that the last 1488c2ecf20Sopenharmony_ci * response has been sent instead of only being 1498c2ecf20Sopenharmony_ci * constructed. 1508c2ecf20Sopenharmony_ci */ 1518c2ecf20Sopenharmony_ci if (++next > rvt_size_atomic(&dev->rdi)) 1528c2ecf20Sopenharmony_ci next = 0; 1538c2ecf20Sopenharmony_ci /* 1548c2ecf20Sopenharmony_ci * Only advance the s_acked_ack_queue pointer if there 1558c2ecf20Sopenharmony_ci * have been no TID RDMA requests. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 1588c2ecf20Sopenharmony_ci if (e->opcode != TID_OP(WRITE_REQ) && 1598c2ecf20Sopenharmony_ci qp->s_acked_ack_queue == qp->s_tail_ack_queue) 1608c2ecf20Sopenharmony_ci qp->s_acked_ack_queue = next; 1618c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = next; 1628c2ecf20Sopenharmony_ci trace_hfi1_rsp_make_rc_ack(qp, e->psn); 1638c2ecf20Sopenharmony_ci fallthrough; 1648c2ecf20Sopenharmony_ci case OP(SEND_ONLY): 1658c2ecf20Sopenharmony_ci case OP(ACKNOWLEDGE): 1668c2ecf20Sopenharmony_ci /* Check for no next entry in the queue. */ 1678c2ecf20Sopenharmony_ci if (qp->r_head_ack_queue == qp->s_tail_ack_queue) { 1688c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_ACK_PENDING) 1698c2ecf20Sopenharmony_ci goto normal; 1708c2ecf20Sopenharmony_ci goto bail; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 1748c2ecf20Sopenharmony_ci /* Check for tid write fence */ 1758c2ecf20Sopenharmony_ci if ((qpriv->s_flags & HFI1_R_TID_WAIT_INTERLCK) || 1768c2ecf20Sopenharmony_ci hfi1_tid_rdma_ack_interlock(qp, e)) { 1778c2ecf20Sopenharmony_ci iowait_set_flag(&qpriv->s_iowait, IOWAIT_PENDING_IB); 1788c2ecf20Sopenharmony_ci goto bail; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci if (e->opcode == OP(RDMA_READ_REQUEST)) { 1818c2ecf20Sopenharmony_ci /* 1828c2ecf20Sopenharmony_ci * If a RDMA read response is being resent and 1838c2ecf20Sopenharmony_ci * we haven't seen the duplicate request yet, 1848c2ecf20Sopenharmony_ci * then stop sending the remaining responses the 1858c2ecf20Sopenharmony_ci * responder has seen until the requester re-sends it. 1868c2ecf20Sopenharmony_ci */ 1878c2ecf20Sopenharmony_ci len = e->rdma_sge.sge_length; 1888c2ecf20Sopenharmony_ci if (len && !e->rdma_sge.mr) { 1898c2ecf20Sopenharmony_ci if (qp->s_acked_ack_queue == 1908c2ecf20Sopenharmony_ci qp->s_tail_ack_queue) 1918c2ecf20Sopenharmony_ci qp->s_acked_ack_queue = 1928c2ecf20Sopenharmony_ci qp->r_head_ack_queue; 1938c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = qp->r_head_ack_queue; 1948c2ecf20Sopenharmony_ci goto bail; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci /* Copy SGE state in case we need to resend */ 1978c2ecf20Sopenharmony_ci ps->s_txreq->mr = e->rdma_sge.mr; 1988c2ecf20Sopenharmony_ci if (ps->s_txreq->mr) 1998c2ecf20Sopenharmony_ci rvt_get_mr(ps->s_txreq->mr); 2008c2ecf20Sopenharmony_ci qp->s_ack_rdma_sge.sge = e->rdma_sge; 2018c2ecf20Sopenharmony_ci qp->s_ack_rdma_sge.num_sge = 1; 2028c2ecf20Sopenharmony_ci ps->s_txreq->ss = &qp->s_ack_rdma_sge; 2038c2ecf20Sopenharmony_ci if (len > pmtu) { 2048c2ecf20Sopenharmony_ci len = pmtu; 2058c2ecf20Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST); 2068c2ecf20Sopenharmony_ci } else { 2078c2ecf20Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY); 2088c2ecf20Sopenharmony_ci e->sent = 1; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 2118c2ecf20Sopenharmony_ci hwords++; 2128c2ecf20Sopenharmony_ci qp->s_ack_rdma_psn = e->psn; 2138c2ecf20Sopenharmony_ci bth2 = mask_psn(qp->s_ack_rdma_psn++); 2148c2ecf20Sopenharmony_ci } else if (e->opcode == TID_OP(WRITE_REQ)) { 2158c2ecf20Sopenharmony_ci /* 2168c2ecf20Sopenharmony_ci * If a TID RDMA WRITE RESP is being resent, we have to 2178c2ecf20Sopenharmony_ci * wait for the actual request. All requests that are to 2188c2ecf20Sopenharmony_ci * be resent will have their state set to 2198c2ecf20Sopenharmony_ci * TID_REQUEST_RESEND. When the new request arrives, the 2208c2ecf20Sopenharmony_ci * state will be changed to TID_REQUEST_RESEND_ACTIVE. 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_ci req = ack_to_tid_req(e); 2238c2ecf20Sopenharmony_ci if (req->state == TID_REQUEST_RESEND || 2248c2ecf20Sopenharmony_ci req->state == TID_REQUEST_INIT_RESEND) 2258c2ecf20Sopenharmony_ci goto bail; 2268c2ecf20Sopenharmony_ci qp->s_ack_state = TID_OP(WRITE_RESP); 2278c2ecf20Sopenharmony_ci qp->s_ack_rdma_psn = mask_psn(e->psn + req->cur_seg); 2288c2ecf20Sopenharmony_ci goto write_resp; 2298c2ecf20Sopenharmony_ci } else if (e->opcode == TID_OP(READ_REQ)) { 2308c2ecf20Sopenharmony_ci /* 2318c2ecf20Sopenharmony_ci * If a TID RDMA read response is being resent and 2328c2ecf20Sopenharmony_ci * we haven't seen the duplicate request yet, 2338c2ecf20Sopenharmony_ci * then stop sending the remaining responses the 2348c2ecf20Sopenharmony_ci * responder has seen until the requester re-sends it. 2358c2ecf20Sopenharmony_ci */ 2368c2ecf20Sopenharmony_ci len = e->rdma_sge.sge_length; 2378c2ecf20Sopenharmony_ci if (len && !e->rdma_sge.mr) { 2388c2ecf20Sopenharmony_ci if (qp->s_acked_ack_queue == 2398c2ecf20Sopenharmony_ci qp->s_tail_ack_queue) 2408c2ecf20Sopenharmony_ci qp->s_acked_ack_queue = 2418c2ecf20Sopenharmony_ci qp->r_head_ack_queue; 2428c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = qp->r_head_ack_queue; 2438c2ecf20Sopenharmony_ci goto bail; 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci /* Copy SGE state in case we need to resend */ 2468c2ecf20Sopenharmony_ci ps->s_txreq->mr = e->rdma_sge.mr; 2478c2ecf20Sopenharmony_ci if (ps->s_txreq->mr) 2488c2ecf20Sopenharmony_ci rvt_get_mr(ps->s_txreq->mr); 2498c2ecf20Sopenharmony_ci qp->s_ack_rdma_sge.sge = e->rdma_sge; 2508c2ecf20Sopenharmony_ci qp->s_ack_rdma_sge.num_sge = 1; 2518c2ecf20Sopenharmony_ci qp->s_ack_state = TID_OP(READ_RESP); 2528c2ecf20Sopenharmony_ci goto read_resp; 2538c2ecf20Sopenharmony_ci } else { 2548c2ecf20Sopenharmony_ci /* COMPARE_SWAP or FETCH_ADD */ 2558c2ecf20Sopenharmony_ci ps->s_txreq->ss = NULL; 2568c2ecf20Sopenharmony_ci len = 0; 2578c2ecf20Sopenharmony_ci qp->s_ack_state = OP(ATOMIC_ACKNOWLEDGE); 2588c2ecf20Sopenharmony_ci ohdr->u.at.aeth = rvt_compute_aeth(qp); 2598c2ecf20Sopenharmony_ci ib_u64_put(e->atomic_data, &ohdr->u.at.atomic_ack_eth); 2608c2ecf20Sopenharmony_ci hwords += sizeof(ohdr->u.at) / sizeof(u32); 2618c2ecf20Sopenharmony_ci bth2 = mask_psn(e->psn); 2628c2ecf20Sopenharmony_ci e->sent = 1; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci trace_hfi1_tid_write_rsp_make_rc_ack(qp); 2658c2ecf20Sopenharmony_ci bth0 = qp->s_ack_state << 24; 2668c2ecf20Sopenharmony_ci break; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_FIRST): 2698c2ecf20Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE); 2708c2ecf20Sopenharmony_ci fallthrough; 2718c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_MIDDLE): 2728c2ecf20Sopenharmony_ci ps->s_txreq->ss = &qp->s_ack_rdma_sge; 2738c2ecf20Sopenharmony_ci ps->s_txreq->mr = qp->s_ack_rdma_sge.sge.mr; 2748c2ecf20Sopenharmony_ci if (ps->s_txreq->mr) 2758c2ecf20Sopenharmony_ci rvt_get_mr(ps->s_txreq->mr); 2768c2ecf20Sopenharmony_ci len = qp->s_ack_rdma_sge.sge.sge_length; 2778c2ecf20Sopenharmony_ci if (len > pmtu) { 2788c2ecf20Sopenharmony_ci len = pmtu; 2798c2ecf20Sopenharmony_ci middle = HFI1_CAP_IS_KSET(SDMA_AHG); 2808c2ecf20Sopenharmony_ci } else { 2818c2ecf20Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 2828c2ecf20Sopenharmony_ci hwords++; 2838c2ecf20Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST); 2848c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 2858c2ecf20Sopenharmony_ci e->sent = 1; 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci bth0 = qp->s_ack_state << 24; 2888c2ecf20Sopenharmony_ci bth2 = mask_psn(qp->s_ack_rdma_psn++); 2898c2ecf20Sopenharmony_ci break; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci case TID_OP(WRITE_RESP): 2928c2ecf20Sopenharmony_ciwrite_resp: 2938c2ecf20Sopenharmony_ci /* 2948c2ecf20Sopenharmony_ci * 1. Check if RVT_S_ACK_PENDING is set. If yes, 2958c2ecf20Sopenharmony_ci * goto normal. 2968c2ecf20Sopenharmony_ci * 2. Attempt to allocate TID resources. 2978c2ecf20Sopenharmony_ci * 3. Remove RVT_S_RESP_PENDING flags from s_flags 2988c2ecf20Sopenharmony_ci * 4. If resources not available: 2998c2ecf20Sopenharmony_ci * 4.1 Set RVT_S_WAIT_TID_SPACE 3008c2ecf20Sopenharmony_ci * 4.2 Queue QP on RCD TID queue 3018c2ecf20Sopenharmony_ci * 4.3 Put QP on iowait list. 3028c2ecf20Sopenharmony_ci * 4.4 Build IB RNR NAK with appropriate timeout value 3038c2ecf20Sopenharmony_ci * 4.5 Return indication progress made. 3048c2ecf20Sopenharmony_ci * 5. If resources are available: 3058c2ecf20Sopenharmony_ci * 5.1 Program HW flow CSRs 3068c2ecf20Sopenharmony_ci * 5.2 Build TID RDMA WRITE RESP packet 3078c2ecf20Sopenharmony_ci * 5.3 If more resources needed, do 2.1 - 2.3. 3088c2ecf20Sopenharmony_ci * 5.4 Wake up next QP on RCD TID queue. 3098c2ecf20Sopenharmony_ci * 5.5 Return indication progress made. 3108c2ecf20Sopenharmony_ci */ 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 3138c2ecf20Sopenharmony_ci req = ack_to_tid_req(e); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci /* 3168c2ecf20Sopenharmony_ci * Send scheduled RNR NAK's. RNR NAK's need to be sent at 3178c2ecf20Sopenharmony_ci * segment boundaries, not at request boundaries. Don't change 3188c2ecf20Sopenharmony_ci * s_ack_state because we are still in the middle of a request 3198c2ecf20Sopenharmony_ci */ 3208c2ecf20Sopenharmony_ci if (qpriv->rnr_nak_state == TID_RNR_NAK_SEND && 3218c2ecf20Sopenharmony_ci qp->s_tail_ack_queue == qpriv->r_tid_alloc && 3228c2ecf20Sopenharmony_ci req->cur_seg == req->alloc_seg) { 3238c2ecf20Sopenharmony_ci qpriv->rnr_nak_state = TID_RNR_NAK_SENT; 3248c2ecf20Sopenharmony_ci goto normal_no_state; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci bth2 = mask_psn(qp->s_ack_rdma_psn); 3288c2ecf20Sopenharmony_ci hdrlen = hfi1_build_tid_rdma_write_resp(qp, e, ohdr, &bth1, 3298c2ecf20Sopenharmony_ci bth2, &len, 3308c2ecf20Sopenharmony_ci &ps->s_txreq->ss); 3318c2ecf20Sopenharmony_ci if (!hdrlen) 3328c2ecf20Sopenharmony_ci return 0; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci hwords += hdrlen; 3358c2ecf20Sopenharmony_ci bth0 = qp->s_ack_state << 24; 3368c2ecf20Sopenharmony_ci qp->s_ack_rdma_psn++; 3378c2ecf20Sopenharmony_ci trace_hfi1_tid_req_make_rc_ack_write(qp, 0, e->opcode, e->psn, 3388c2ecf20Sopenharmony_ci e->lpsn, req); 3398c2ecf20Sopenharmony_ci if (req->cur_seg != req->total_segs) 3408c2ecf20Sopenharmony_ci break; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci e->sent = 1; 3438c2ecf20Sopenharmony_ci /* Do not free e->rdma_sge until all data are received */ 3448c2ecf20Sopenharmony_ci qp->s_ack_state = OP(ATOMIC_ACKNOWLEDGE); 3458c2ecf20Sopenharmony_ci break; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci case TID_OP(READ_RESP): 3488c2ecf20Sopenharmony_ciread_resp: 3498c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 3508c2ecf20Sopenharmony_ci ps->s_txreq->ss = &qp->s_ack_rdma_sge; 3518c2ecf20Sopenharmony_ci delta = hfi1_build_tid_rdma_read_resp(qp, e, ohdr, &bth0, 3528c2ecf20Sopenharmony_ci &bth1, &bth2, &len, 3538c2ecf20Sopenharmony_ci &last_pkt); 3548c2ecf20Sopenharmony_ci if (delta == 0) 3558c2ecf20Sopenharmony_ci goto error_qp; 3568c2ecf20Sopenharmony_ci hwords += delta; 3578c2ecf20Sopenharmony_ci if (last_pkt) { 3588c2ecf20Sopenharmony_ci e->sent = 1; 3598c2ecf20Sopenharmony_ci /* 3608c2ecf20Sopenharmony_ci * Increment qp->s_tail_ack_queue through s_ack_state 3618c2ecf20Sopenharmony_ci * transition. 3628c2ecf20Sopenharmony_ci */ 3638c2ecf20Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST); 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci break; 3668c2ecf20Sopenharmony_ci case TID_OP(READ_REQ): 3678c2ecf20Sopenharmony_ci goto bail; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci default: 3708c2ecf20Sopenharmony_cinormal: 3718c2ecf20Sopenharmony_ci /* 3728c2ecf20Sopenharmony_ci * Send a regular ACK. 3738c2ecf20Sopenharmony_ci * Set the s_ack_state so we wait until after sending 3748c2ecf20Sopenharmony_ci * the ACK before setting s_ack_state to ACKNOWLEDGE 3758c2ecf20Sopenharmony_ci * (see above). 3768c2ecf20Sopenharmony_ci */ 3778c2ecf20Sopenharmony_ci qp->s_ack_state = OP(SEND_ONLY); 3788c2ecf20Sopenharmony_cinormal_no_state: 3798c2ecf20Sopenharmony_ci if (qp->s_nak_state) 3808c2ecf20Sopenharmony_ci ohdr->u.aeth = 3818c2ecf20Sopenharmony_ci cpu_to_be32((qp->r_msn & IB_MSN_MASK) | 3828c2ecf20Sopenharmony_ci (qp->s_nak_state << 3838c2ecf20Sopenharmony_ci IB_AETH_CREDIT_SHIFT)); 3848c2ecf20Sopenharmony_ci else 3858c2ecf20Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 3868c2ecf20Sopenharmony_ci hwords++; 3878c2ecf20Sopenharmony_ci len = 0; 3888c2ecf20Sopenharmony_ci bth0 = OP(ACKNOWLEDGE) << 24; 3898c2ecf20Sopenharmony_ci bth2 = mask_psn(qp->s_ack_psn); 3908c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_ACK_PENDING; 3918c2ecf20Sopenharmony_ci ps->s_txreq->txreq.flags |= SDMA_TXREQ_F_VIP; 3928c2ecf20Sopenharmony_ci ps->s_txreq->ss = NULL; 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci qp->s_rdma_ack_cnt++; 3958c2ecf20Sopenharmony_ci ps->s_txreq->sde = qpriv->s_sde; 3968c2ecf20Sopenharmony_ci ps->s_txreq->s_cur_size = len; 3978c2ecf20Sopenharmony_ci ps->s_txreq->hdr_dwords = hwords; 3988c2ecf20Sopenharmony_ci hfi1_make_ruc_header(qp, ohdr, bth0, bth1, bth2, middle, ps); 3998c2ecf20Sopenharmony_ci return 1; 4008c2ecf20Sopenharmony_cierror_qp: 4018c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, ps->flags); 4028c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->r_lock, ps->flags); 4038c2ecf20Sopenharmony_ci spin_lock(&qp->s_lock); 4048c2ecf20Sopenharmony_ci rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 4058c2ecf20Sopenharmony_ci spin_unlock(&qp->s_lock); 4068c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->r_lock, ps->flags); 4078c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, ps->flags); 4088c2ecf20Sopenharmony_cibail: 4098c2ecf20Sopenharmony_ci qp->s_ack_state = OP(ACKNOWLEDGE); 4108c2ecf20Sopenharmony_ci /* 4118c2ecf20Sopenharmony_ci * Ensure s_rdma_ack_cnt changes are committed prior to resetting 4128c2ecf20Sopenharmony_ci * RVT_S_RESP_PENDING 4138c2ecf20Sopenharmony_ci */ 4148c2ecf20Sopenharmony_ci smp_wmb(); 4158c2ecf20Sopenharmony_ci qp->s_flags &= ~(RVT_S_RESP_PENDING 4168c2ecf20Sopenharmony_ci | RVT_S_ACK_PENDING 4178c2ecf20Sopenharmony_ci | HFI1_S_AHG_VALID); 4188c2ecf20Sopenharmony_ci return 0; 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci/** 4228c2ecf20Sopenharmony_ci * hfi1_make_rc_req - construct a request packet (SEND, RDMA r/w, ATOMIC) 4238c2ecf20Sopenharmony_ci * @qp: a pointer to the QP 4248c2ecf20Sopenharmony_ci * 4258c2ecf20Sopenharmony_ci * Assumes s_lock is held. 4268c2ecf20Sopenharmony_ci * 4278c2ecf20Sopenharmony_ci * Return 1 if constructed; otherwise, return 0. 4288c2ecf20Sopenharmony_ci */ 4298c2ecf20Sopenharmony_ciint hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 4328c2ecf20Sopenharmony_ci struct hfi1_ibdev *dev = to_idev(qp->ibqp.device); 4338c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr; 4348c2ecf20Sopenharmony_ci struct rvt_sge_state *ss = NULL; 4358c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 4368c2ecf20Sopenharmony_ci struct hfi1_swqe_priv *wpriv; 4378c2ecf20Sopenharmony_ci struct tid_rdma_request *req = NULL; 4388c2ecf20Sopenharmony_ci /* header size in 32-bit words LRH+BTH = (8+12)/4. */ 4398c2ecf20Sopenharmony_ci u32 hwords = 5; 4408c2ecf20Sopenharmony_ci u32 len = 0; 4418c2ecf20Sopenharmony_ci u32 bth0 = 0, bth2 = 0; 4428c2ecf20Sopenharmony_ci u32 bth1 = qp->remote_qpn | (HFI1_CAP_IS_KSET(OPFN) << IB_BTHE_E_SHIFT); 4438c2ecf20Sopenharmony_ci u32 pmtu = qp->pmtu; 4448c2ecf20Sopenharmony_ci char newreq; 4458c2ecf20Sopenharmony_ci int middle = 0; 4468c2ecf20Sopenharmony_ci int delta; 4478c2ecf20Sopenharmony_ci struct tid_rdma_flow *flow = NULL; 4488c2ecf20Sopenharmony_ci struct tid_rdma_params *remote; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci trace_hfi1_sender_make_rc_req(qp); 4518c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 4528c2ecf20Sopenharmony_ci ps->s_txreq = get_txreq(ps->dev, qp); 4538c2ecf20Sopenharmony_ci if (!ps->s_txreq) 4548c2ecf20Sopenharmony_ci goto bail_no_tx; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci if (priv->hdr_type == HFI1_PKT_TYPE_9B) { 4578c2ecf20Sopenharmony_ci /* header size in 32-bit words LRH+BTH = (8+12)/4. */ 4588c2ecf20Sopenharmony_ci hwords = 5; 4598c2ecf20Sopenharmony_ci if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) 4608c2ecf20Sopenharmony_ci ohdr = &ps->s_txreq->phdr.hdr.ibh.u.l.oth; 4618c2ecf20Sopenharmony_ci else 4628c2ecf20Sopenharmony_ci ohdr = &ps->s_txreq->phdr.hdr.ibh.u.oth; 4638c2ecf20Sopenharmony_ci } else { 4648c2ecf20Sopenharmony_ci /* header size in 32-bit words 16B LRH+BTH = (16+12)/4. */ 4658c2ecf20Sopenharmony_ci hwords = 7; 4668c2ecf20Sopenharmony_ci if ((rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) && 4678c2ecf20Sopenharmony_ci (hfi1_check_mcast(rdma_ah_get_dlid(&qp->remote_ah_attr)))) 4688c2ecf20Sopenharmony_ci ohdr = &ps->s_txreq->phdr.hdr.opah.u.l.oth; 4698c2ecf20Sopenharmony_ci else 4708c2ecf20Sopenharmony_ci ohdr = &ps->s_txreq->phdr.hdr.opah.u.oth; 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci /* Sending responses has higher priority over sending requests. */ 4748c2ecf20Sopenharmony_ci if ((qp->s_flags & RVT_S_RESP_PENDING) && 4758c2ecf20Sopenharmony_ci make_rc_ack(dev, qp, ohdr, ps)) 4768c2ecf20Sopenharmony_ci return 1; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_SEND_OK)) { 4798c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_FLUSH_SEND)) 4808c2ecf20Sopenharmony_ci goto bail; 4818c2ecf20Sopenharmony_ci /* We are in the error state, flush the work request. */ 4828c2ecf20Sopenharmony_ci if (qp->s_last == READ_ONCE(qp->s_head)) 4838c2ecf20Sopenharmony_ci goto bail; 4848c2ecf20Sopenharmony_ci /* If DMAs are in progress, we can't flush immediately. */ 4858c2ecf20Sopenharmony_ci if (iowait_sdma_pending(&priv->s_iowait)) { 4868c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_DMA; 4878c2ecf20Sopenharmony_ci goto bail; 4888c2ecf20Sopenharmony_ci } 4898c2ecf20Sopenharmony_ci clear_ahg(qp); 4908c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_last); 4918c2ecf20Sopenharmony_ci hfi1_trdma_send_complete(qp, wqe, qp->s_last != qp->s_acked ? 4928c2ecf20Sopenharmony_ci IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR); 4938c2ecf20Sopenharmony_ci /* will get called again */ 4948c2ecf20Sopenharmony_ci goto done_free_tx; 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci if (qp->s_flags & (RVT_S_WAIT_RNR | RVT_S_WAIT_ACK | HFI1_S_WAIT_HALT)) 4988c2ecf20Sopenharmony_ci goto bail; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci if (cmp_psn(qp->s_psn, qp->s_sending_hpsn) <= 0) { 5018c2ecf20Sopenharmony_ci if (cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) <= 0) { 5028c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_PSN; 5038c2ecf20Sopenharmony_ci goto bail; 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci qp->s_sending_psn = qp->s_psn; 5068c2ecf20Sopenharmony_ci qp->s_sending_hpsn = qp->s_psn - 1; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci /* Send a request. */ 5108c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_cur); 5118c2ecf20Sopenharmony_cicheck_s_state: 5128c2ecf20Sopenharmony_ci switch (qp->s_state) { 5138c2ecf20Sopenharmony_ci default: 5148c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_NEXT_SEND_OK)) 5158c2ecf20Sopenharmony_ci goto bail; 5168c2ecf20Sopenharmony_ci /* 5178c2ecf20Sopenharmony_ci * Resend an old request or start a new one. 5188c2ecf20Sopenharmony_ci * 5198c2ecf20Sopenharmony_ci * We keep track of the current SWQE so that 5208c2ecf20Sopenharmony_ci * we don't reset the "furthest progress" state 5218c2ecf20Sopenharmony_ci * if we need to back up. 5228c2ecf20Sopenharmony_ci */ 5238c2ecf20Sopenharmony_ci newreq = 0; 5248c2ecf20Sopenharmony_ci if (qp->s_cur == qp->s_tail) { 5258c2ecf20Sopenharmony_ci /* Check if send work queue is empty. */ 5268c2ecf20Sopenharmony_ci if (qp->s_tail == READ_ONCE(qp->s_head)) { 5278c2ecf20Sopenharmony_ci clear_ahg(qp); 5288c2ecf20Sopenharmony_ci goto bail; 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci /* 5318c2ecf20Sopenharmony_ci * If a fence is requested, wait for previous 5328c2ecf20Sopenharmony_ci * RDMA read and atomic operations to finish. 5338c2ecf20Sopenharmony_ci * However, there is no need to guard against 5348c2ecf20Sopenharmony_ci * TID RDMA READ after TID RDMA READ. 5358c2ecf20Sopenharmony_ci */ 5368c2ecf20Sopenharmony_ci if ((wqe->wr.send_flags & IB_SEND_FENCE) && 5378c2ecf20Sopenharmony_ci qp->s_num_rd_atomic && 5388c2ecf20Sopenharmony_ci (wqe->wr.opcode != IB_WR_TID_RDMA_READ || 5398c2ecf20Sopenharmony_ci priv->pending_tid_r_segs < qp->s_num_rd_atomic)) { 5408c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_FENCE; 5418c2ecf20Sopenharmony_ci goto bail; 5428c2ecf20Sopenharmony_ci } 5438c2ecf20Sopenharmony_ci /* 5448c2ecf20Sopenharmony_ci * Local operations are processed immediately 5458c2ecf20Sopenharmony_ci * after all prior requests have completed 5468c2ecf20Sopenharmony_ci */ 5478c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_REG_MR || 5488c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_LOCAL_INV) { 5498c2ecf20Sopenharmony_ci int local_ops = 0; 5508c2ecf20Sopenharmony_ci int err = 0; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci if (qp->s_last != qp->s_cur) 5538c2ecf20Sopenharmony_ci goto bail; 5548c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 5558c2ecf20Sopenharmony_ci qp->s_cur = 0; 5568c2ecf20Sopenharmony_ci if (++qp->s_tail == qp->s_size) 5578c2ecf20Sopenharmony_ci qp->s_tail = 0; 5588c2ecf20Sopenharmony_ci if (!(wqe->wr.send_flags & 5598c2ecf20Sopenharmony_ci RVT_SEND_COMPLETION_ONLY)) { 5608c2ecf20Sopenharmony_ci err = rvt_invalidate_rkey( 5618c2ecf20Sopenharmony_ci qp, 5628c2ecf20Sopenharmony_ci wqe->wr.ex.invalidate_rkey); 5638c2ecf20Sopenharmony_ci local_ops = 1; 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci rvt_send_complete(qp, wqe, 5668c2ecf20Sopenharmony_ci err ? IB_WC_LOC_PROT_ERR 5678c2ecf20Sopenharmony_ci : IB_WC_SUCCESS); 5688c2ecf20Sopenharmony_ci if (local_ops) 5698c2ecf20Sopenharmony_ci atomic_dec(&qp->local_ops_pending); 5708c2ecf20Sopenharmony_ci goto done_free_tx; 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci newreq = 1; 5748c2ecf20Sopenharmony_ci qp->s_psn = wqe->psn; 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci /* 5778c2ecf20Sopenharmony_ci * Note that we have to be careful not to modify the 5788c2ecf20Sopenharmony_ci * original work request since we may need to resend 5798c2ecf20Sopenharmony_ci * it. 5808c2ecf20Sopenharmony_ci */ 5818c2ecf20Sopenharmony_ci len = wqe->length; 5828c2ecf20Sopenharmony_ci ss = &qp->s_sge; 5838c2ecf20Sopenharmony_ci bth2 = mask_psn(qp->s_psn); 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci /* 5868c2ecf20Sopenharmony_ci * Interlock between various IB requests and TID RDMA 5878c2ecf20Sopenharmony_ci * if necessary. 5888c2ecf20Sopenharmony_ci */ 5898c2ecf20Sopenharmony_ci if ((priv->s_flags & HFI1_S_TID_WAIT_INTERLCK) || 5908c2ecf20Sopenharmony_ci hfi1_tid_rdma_wqe_interlock(qp, wqe)) 5918c2ecf20Sopenharmony_ci goto bail; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci switch (wqe->wr.opcode) { 5948c2ecf20Sopenharmony_ci case IB_WR_SEND: 5958c2ecf20Sopenharmony_ci case IB_WR_SEND_WITH_IMM: 5968c2ecf20Sopenharmony_ci case IB_WR_SEND_WITH_INV: 5978c2ecf20Sopenharmony_ci /* If no credit, return. */ 5988c2ecf20Sopenharmony_ci if (!rvt_rc_credit_avail(qp, wqe)) 5998c2ecf20Sopenharmony_ci goto bail; 6008c2ecf20Sopenharmony_ci if (len > pmtu) { 6018c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_FIRST); 6028c2ecf20Sopenharmony_ci len = pmtu; 6038c2ecf20Sopenharmony_ci break; 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_SEND) { 6068c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_ONLY); 6078c2ecf20Sopenharmony_ci } else if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) { 6088c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE); 6098c2ecf20Sopenharmony_ci /* Immediate data comes after the BTH */ 6108c2ecf20Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 6118c2ecf20Sopenharmony_ci hwords += 1; 6128c2ecf20Sopenharmony_ci } else { 6138c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_ONLY_WITH_INVALIDATE); 6148c2ecf20Sopenharmony_ci /* Invalidate rkey comes after the BTH */ 6158c2ecf20Sopenharmony_ci ohdr->u.ieth = cpu_to_be32( 6168c2ecf20Sopenharmony_ci wqe->wr.ex.invalidate_rkey); 6178c2ecf20Sopenharmony_ci hwords += 1; 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 6208c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 6218c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 6228c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 6238c2ecf20Sopenharmony_ci qp->s_cur = 0; 6248c2ecf20Sopenharmony_ci break; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE: 6278c2ecf20Sopenharmony_ci if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 6288c2ecf20Sopenharmony_ci qp->s_lsn++; 6298c2ecf20Sopenharmony_ci goto no_flow_control; 6308c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE_WITH_IMM: 6318c2ecf20Sopenharmony_ci /* If no credit, return. */ 6328c2ecf20Sopenharmony_ci if (!rvt_rc_credit_avail(qp, wqe)) 6338c2ecf20Sopenharmony_ci goto bail; 6348c2ecf20Sopenharmony_cino_flow_control: 6358c2ecf20Sopenharmony_ci put_ib_reth_vaddr( 6368c2ecf20Sopenharmony_ci wqe->rdma_wr.remote_addr, 6378c2ecf20Sopenharmony_ci &ohdr->u.rc.reth); 6388c2ecf20Sopenharmony_ci ohdr->u.rc.reth.rkey = 6398c2ecf20Sopenharmony_ci cpu_to_be32(wqe->rdma_wr.rkey); 6408c2ecf20Sopenharmony_ci ohdr->u.rc.reth.length = cpu_to_be32(len); 6418c2ecf20Sopenharmony_ci hwords += sizeof(struct ib_reth) / sizeof(u32); 6428c2ecf20Sopenharmony_ci if (len > pmtu) { 6438c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_FIRST); 6448c2ecf20Sopenharmony_ci len = pmtu; 6458c2ecf20Sopenharmony_ci break; 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_WRITE) { 6488c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_ONLY); 6498c2ecf20Sopenharmony_ci } else { 6508c2ecf20Sopenharmony_ci qp->s_state = 6518c2ecf20Sopenharmony_ci OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE); 6528c2ecf20Sopenharmony_ci /* Immediate data comes after RETH */ 6538c2ecf20Sopenharmony_ci ohdr->u.rc.imm_data = wqe->wr.ex.imm_data; 6548c2ecf20Sopenharmony_ci hwords += 1; 6558c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 6568c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 6598c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 6608c2ecf20Sopenharmony_ci qp->s_cur = 0; 6618c2ecf20Sopenharmony_ci break; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci case IB_WR_TID_RDMA_WRITE: 6648c2ecf20Sopenharmony_ci if (newreq) { 6658c2ecf20Sopenharmony_ci /* 6668c2ecf20Sopenharmony_ci * Limit the number of TID RDMA WRITE requests. 6678c2ecf20Sopenharmony_ci */ 6688c2ecf20Sopenharmony_ci if (atomic_read(&priv->n_tid_requests) >= 6698c2ecf20Sopenharmony_ci HFI1_TID_RDMA_WRITE_CNT) 6708c2ecf20Sopenharmony_ci goto bail; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 6738c2ecf20Sopenharmony_ci qp->s_lsn++; 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci hwords += hfi1_build_tid_rdma_write_req(qp, wqe, ohdr, 6778c2ecf20Sopenharmony_ci &bth1, &bth2, 6788c2ecf20Sopenharmony_ci &len); 6798c2ecf20Sopenharmony_ci ss = NULL; 6808c2ecf20Sopenharmony_ci if (priv->s_tid_cur == HFI1_QP_WQE_INVALID) { 6818c2ecf20Sopenharmony_ci priv->s_tid_cur = qp->s_cur; 6828c2ecf20Sopenharmony_ci if (priv->s_tid_tail == HFI1_QP_WQE_INVALID) { 6838c2ecf20Sopenharmony_ci priv->s_tid_tail = qp->s_cur; 6848c2ecf20Sopenharmony_ci priv->s_state = TID_OP(WRITE_RESP); 6858c2ecf20Sopenharmony_ci } 6868c2ecf20Sopenharmony_ci } else if (priv->s_tid_cur == priv->s_tid_head) { 6878c2ecf20Sopenharmony_ci struct rvt_swqe *__w; 6888c2ecf20Sopenharmony_ci struct tid_rdma_request *__r; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci __w = rvt_get_swqe_ptr(qp, priv->s_tid_cur); 6918c2ecf20Sopenharmony_ci __r = wqe_to_tid_req(__w); 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci /* 6948c2ecf20Sopenharmony_ci * The s_tid_cur pointer is advanced to s_cur if 6958c2ecf20Sopenharmony_ci * any of the following conditions about the WQE 6968c2ecf20Sopenharmony_ci * to which s_ti_cur currently points to are 6978c2ecf20Sopenharmony_ci * satisfied: 6988c2ecf20Sopenharmony_ci * 1. The request is not a TID RDMA WRITE 6998c2ecf20Sopenharmony_ci * request, 7008c2ecf20Sopenharmony_ci * 2. The request is in the INACTIVE or 7018c2ecf20Sopenharmony_ci * COMPLETE states (TID RDMA READ requests 7028c2ecf20Sopenharmony_ci * stay at INACTIVE and TID RDMA WRITE 7038c2ecf20Sopenharmony_ci * transition to COMPLETE when done), 7048c2ecf20Sopenharmony_ci * 3. The request is in the ACTIVE or SYNC 7058c2ecf20Sopenharmony_ci * state and the number of completed 7068c2ecf20Sopenharmony_ci * segments is equal to the total segment 7078c2ecf20Sopenharmony_ci * count. 7088c2ecf20Sopenharmony_ci * (If ACTIVE, the request is waiting for 7098c2ecf20Sopenharmony_ci * ACKs. If SYNC, the request has not 7108c2ecf20Sopenharmony_ci * received any responses because it's 7118c2ecf20Sopenharmony_ci * waiting on a sync point.) 7128c2ecf20Sopenharmony_ci */ 7138c2ecf20Sopenharmony_ci if (__w->wr.opcode != IB_WR_TID_RDMA_WRITE || 7148c2ecf20Sopenharmony_ci __r->state == TID_REQUEST_INACTIVE || 7158c2ecf20Sopenharmony_ci __r->state == TID_REQUEST_COMPLETE || 7168c2ecf20Sopenharmony_ci ((__r->state == TID_REQUEST_ACTIVE || 7178c2ecf20Sopenharmony_ci __r->state == TID_REQUEST_SYNC) && 7188c2ecf20Sopenharmony_ci __r->comp_seg == __r->total_segs)) { 7198c2ecf20Sopenharmony_ci if (priv->s_tid_tail == 7208c2ecf20Sopenharmony_ci priv->s_tid_cur && 7218c2ecf20Sopenharmony_ci priv->s_state == 7228c2ecf20Sopenharmony_ci TID_OP(WRITE_DATA_LAST)) { 7238c2ecf20Sopenharmony_ci priv->s_tid_tail = qp->s_cur; 7248c2ecf20Sopenharmony_ci priv->s_state = 7258c2ecf20Sopenharmony_ci TID_OP(WRITE_RESP); 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci priv->s_tid_cur = qp->s_cur; 7288c2ecf20Sopenharmony_ci } 7298c2ecf20Sopenharmony_ci /* 7308c2ecf20Sopenharmony_ci * A corner case: when the last TID RDMA WRITE 7318c2ecf20Sopenharmony_ci * request was completed, s_tid_head, 7328c2ecf20Sopenharmony_ci * s_tid_cur, and s_tid_tail all point to the 7338c2ecf20Sopenharmony_ci * same location. Other requests are posted and 7348c2ecf20Sopenharmony_ci * s_cur wraps around to the same location, 7358c2ecf20Sopenharmony_ci * where a new TID RDMA WRITE is posted. In 7368c2ecf20Sopenharmony_ci * this case, none of the indices need to be 7378c2ecf20Sopenharmony_ci * updated. However, the priv->s_state should. 7388c2ecf20Sopenharmony_ci */ 7398c2ecf20Sopenharmony_ci if (priv->s_tid_tail == qp->s_cur && 7408c2ecf20Sopenharmony_ci priv->s_state == TID_OP(WRITE_DATA_LAST)) 7418c2ecf20Sopenharmony_ci priv->s_state = TID_OP(WRITE_RESP); 7428c2ecf20Sopenharmony_ci } 7438c2ecf20Sopenharmony_ci req = wqe_to_tid_req(wqe); 7448c2ecf20Sopenharmony_ci if (newreq) { 7458c2ecf20Sopenharmony_ci priv->s_tid_head = qp->s_cur; 7468c2ecf20Sopenharmony_ci priv->pending_tid_w_resp += req->total_segs; 7478c2ecf20Sopenharmony_ci atomic_inc(&priv->n_tid_requests); 7488c2ecf20Sopenharmony_ci atomic_dec(&priv->n_requests); 7498c2ecf20Sopenharmony_ci } else { 7508c2ecf20Sopenharmony_ci req->state = TID_REQUEST_RESEND; 7518c2ecf20Sopenharmony_ci req->comp_seg = delta_psn(bth2, wqe->psn); 7528c2ecf20Sopenharmony_ci /* 7538c2ecf20Sopenharmony_ci * Pull back any segments since we are going 7548c2ecf20Sopenharmony_ci * to re-receive them. 7558c2ecf20Sopenharmony_ci */ 7568c2ecf20Sopenharmony_ci req->setup_head = req->clear_tail; 7578c2ecf20Sopenharmony_ci priv->pending_tid_w_resp += 7588c2ecf20Sopenharmony_ci delta_psn(wqe->lpsn, bth2) + 1; 7598c2ecf20Sopenharmony_ci } 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci trace_hfi1_tid_write_sender_make_req(qp, newreq); 7628c2ecf20Sopenharmony_ci trace_hfi1_tid_req_make_req_write(qp, newreq, 7638c2ecf20Sopenharmony_ci wqe->wr.opcode, 7648c2ecf20Sopenharmony_ci wqe->psn, wqe->lpsn, 7658c2ecf20Sopenharmony_ci req); 7668c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 7678c2ecf20Sopenharmony_ci qp->s_cur = 0; 7688c2ecf20Sopenharmony_ci break; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci case IB_WR_RDMA_READ: 7718c2ecf20Sopenharmony_ci /* 7728c2ecf20Sopenharmony_ci * Don't allow more operations to be started 7738c2ecf20Sopenharmony_ci * than the QP limits allow. 7748c2ecf20Sopenharmony_ci */ 7758c2ecf20Sopenharmony_ci if (qp->s_num_rd_atomic >= 7768c2ecf20Sopenharmony_ci qp->s_max_rd_atomic) { 7778c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_RDMAR; 7788c2ecf20Sopenharmony_ci goto bail; 7798c2ecf20Sopenharmony_ci } 7808c2ecf20Sopenharmony_ci qp->s_num_rd_atomic++; 7818c2ecf20Sopenharmony_ci if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 7828c2ecf20Sopenharmony_ci qp->s_lsn++; 7838c2ecf20Sopenharmony_ci put_ib_reth_vaddr( 7848c2ecf20Sopenharmony_ci wqe->rdma_wr.remote_addr, 7858c2ecf20Sopenharmony_ci &ohdr->u.rc.reth); 7868c2ecf20Sopenharmony_ci ohdr->u.rc.reth.rkey = 7878c2ecf20Sopenharmony_ci cpu_to_be32(wqe->rdma_wr.rkey); 7888c2ecf20Sopenharmony_ci ohdr->u.rc.reth.length = cpu_to_be32(len); 7898c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_REQUEST); 7908c2ecf20Sopenharmony_ci hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32); 7918c2ecf20Sopenharmony_ci ss = NULL; 7928c2ecf20Sopenharmony_ci len = 0; 7938c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 7948c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 7958c2ecf20Sopenharmony_ci qp->s_cur = 0; 7968c2ecf20Sopenharmony_ci break; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci case IB_WR_TID_RDMA_READ: 7998c2ecf20Sopenharmony_ci trace_hfi1_tid_read_sender_make_req(qp, newreq); 8008c2ecf20Sopenharmony_ci wpriv = wqe->priv; 8018c2ecf20Sopenharmony_ci req = wqe_to_tid_req(wqe); 8028c2ecf20Sopenharmony_ci trace_hfi1_tid_req_make_req_read(qp, newreq, 8038c2ecf20Sopenharmony_ci wqe->wr.opcode, 8048c2ecf20Sopenharmony_ci wqe->psn, wqe->lpsn, 8058c2ecf20Sopenharmony_ci req); 8068c2ecf20Sopenharmony_ci delta = cmp_psn(qp->s_psn, wqe->psn); 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci /* 8098c2ecf20Sopenharmony_ci * Don't allow more operations to be started 8108c2ecf20Sopenharmony_ci * than the QP limits allow. We could get here under 8118c2ecf20Sopenharmony_ci * three conditions; (1) It's a new request; (2) We are 8128c2ecf20Sopenharmony_ci * sending the second or later segment of a request, 8138c2ecf20Sopenharmony_ci * but the qp->s_state is set to OP(RDMA_READ_REQUEST) 8148c2ecf20Sopenharmony_ci * when the last segment of a previous request is 8158c2ecf20Sopenharmony_ci * received just before this; (3) We are re-sending a 8168c2ecf20Sopenharmony_ci * request. 8178c2ecf20Sopenharmony_ci */ 8188c2ecf20Sopenharmony_ci if (qp->s_num_rd_atomic >= qp->s_max_rd_atomic) { 8198c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_RDMAR; 8208c2ecf20Sopenharmony_ci goto bail; 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci if (newreq) { 8238c2ecf20Sopenharmony_ci struct tid_rdma_flow *flow = 8248c2ecf20Sopenharmony_ci &req->flows[req->setup_head]; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci /* 8278c2ecf20Sopenharmony_ci * Set up s_sge as it is needed for TID 8288c2ecf20Sopenharmony_ci * allocation. However, if the pages have been 8298c2ecf20Sopenharmony_ci * walked and mapped, skip it. An earlier try 8308c2ecf20Sopenharmony_ci * has failed to allocate the TID entries. 8318c2ecf20Sopenharmony_ci */ 8328c2ecf20Sopenharmony_ci if (!flow->npagesets) { 8338c2ecf20Sopenharmony_ci qp->s_sge.sge = wqe->sg_list[0]; 8348c2ecf20Sopenharmony_ci qp->s_sge.sg_list = wqe->sg_list + 1; 8358c2ecf20Sopenharmony_ci qp->s_sge.num_sge = wqe->wr.num_sge; 8368c2ecf20Sopenharmony_ci qp->s_sge.total_len = wqe->length; 8378c2ecf20Sopenharmony_ci qp->s_len = wqe->length; 8388c2ecf20Sopenharmony_ci req->isge = 0; 8398c2ecf20Sopenharmony_ci req->clear_tail = req->setup_head; 8408c2ecf20Sopenharmony_ci req->flow_idx = req->setup_head; 8418c2ecf20Sopenharmony_ci req->state = TID_REQUEST_ACTIVE; 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci } else if (delta == 0) { 8448c2ecf20Sopenharmony_ci /* Re-send a request */ 8458c2ecf20Sopenharmony_ci req->cur_seg = 0; 8468c2ecf20Sopenharmony_ci req->comp_seg = 0; 8478c2ecf20Sopenharmony_ci req->ack_pending = 0; 8488c2ecf20Sopenharmony_ci req->flow_idx = req->clear_tail; 8498c2ecf20Sopenharmony_ci req->state = TID_REQUEST_RESEND; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci req->s_next_psn = qp->s_psn; 8528c2ecf20Sopenharmony_ci /* Read one segment at a time */ 8538c2ecf20Sopenharmony_ci len = min_t(u32, req->seg_len, 8548c2ecf20Sopenharmony_ci wqe->length - req->seg_len * req->cur_seg); 8558c2ecf20Sopenharmony_ci delta = hfi1_build_tid_rdma_read_req(qp, wqe, ohdr, 8568c2ecf20Sopenharmony_ci &bth1, &bth2, 8578c2ecf20Sopenharmony_ci &len); 8588c2ecf20Sopenharmony_ci if (delta <= 0) { 8598c2ecf20Sopenharmony_ci /* Wait for TID space */ 8608c2ecf20Sopenharmony_ci goto bail; 8618c2ecf20Sopenharmony_ci } 8628c2ecf20Sopenharmony_ci if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 8638c2ecf20Sopenharmony_ci qp->s_lsn++; 8648c2ecf20Sopenharmony_ci hwords += delta; 8658c2ecf20Sopenharmony_ci ss = &wpriv->ss; 8668c2ecf20Sopenharmony_ci /* Check if this is the last segment */ 8678c2ecf20Sopenharmony_ci if (req->cur_seg >= req->total_segs && 8688c2ecf20Sopenharmony_ci ++qp->s_cur == qp->s_size) 8698c2ecf20Sopenharmony_ci qp->s_cur = 0; 8708c2ecf20Sopenharmony_ci break; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci case IB_WR_ATOMIC_CMP_AND_SWP: 8738c2ecf20Sopenharmony_ci case IB_WR_ATOMIC_FETCH_AND_ADD: 8748c2ecf20Sopenharmony_ci /* 8758c2ecf20Sopenharmony_ci * Don't allow more operations to be started 8768c2ecf20Sopenharmony_ci * than the QP limits allow. 8778c2ecf20Sopenharmony_ci */ 8788c2ecf20Sopenharmony_ci if (qp->s_num_rd_atomic >= 8798c2ecf20Sopenharmony_ci qp->s_max_rd_atomic) { 8808c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_RDMAR; 8818c2ecf20Sopenharmony_ci goto bail; 8828c2ecf20Sopenharmony_ci } 8838c2ecf20Sopenharmony_ci qp->s_num_rd_atomic++; 8848c2ecf20Sopenharmony_ci fallthrough; 8858c2ecf20Sopenharmony_ci case IB_WR_OPFN: 8868c2ecf20Sopenharmony_ci if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 8878c2ecf20Sopenharmony_ci qp->s_lsn++; 8888c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 8898c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_OPFN) { 8908c2ecf20Sopenharmony_ci qp->s_state = OP(COMPARE_SWAP); 8918c2ecf20Sopenharmony_ci put_ib_ateth_swap(wqe->atomic_wr.swap, 8928c2ecf20Sopenharmony_ci &ohdr->u.atomic_eth); 8938c2ecf20Sopenharmony_ci put_ib_ateth_compare(wqe->atomic_wr.compare_add, 8948c2ecf20Sopenharmony_ci &ohdr->u.atomic_eth); 8958c2ecf20Sopenharmony_ci } else { 8968c2ecf20Sopenharmony_ci qp->s_state = OP(FETCH_ADD); 8978c2ecf20Sopenharmony_ci put_ib_ateth_swap(wqe->atomic_wr.compare_add, 8988c2ecf20Sopenharmony_ci &ohdr->u.atomic_eth); 8998c2ecf20Sopenharmony_ci put_ib_ateth_compare(0, &ohdr->u.atomic_eth); 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci put_ib_ateth_vaddr(wqe->atomic_wr.remote_addr, 9028c2ecf20Sopenharmony_ci &ohdr->u.atomic_eth); 9038c2ecf20Sopenharmony_ci ohdr->u.atomic_eth.rkey = cpu_to_be32( 9048c2ecf20Sopenharmony_ci wqe->atomic_wr.rkey); 9058c2ecf20Sopenharmony_ci hwords += sizeof(struct ib_atomic_eth) / sizeof(u32); 9068c2ecf20Sopenharmony_ci ss = NULL; 9078c2ecf20Sopenharmony_ci len = 0; 9088c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 9098c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 9108c2ecf20Sopenharmony_ci qp->s_cur = 0; 9118c2ecf20Sopenharmony_ci break; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci default: 9148c2ecf20Sopenharmony_ci goto bail; 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci if (wqe->wr.opcode != IB_WR_TID_RDMA_READ) { 9178c2ecf20Sopenharmony_ci qp->s_sge.sge = wqe->sg_list[0]; 9188c2ecf20Sopenharmony_ci qp->s_sge.sg_list = wqe->sg_list + 1; 9198c2ecf20Sopenharmony_ci qp->s_sge.num_sge = wqe->wr.num_sge; 9208c2ecf20Sopenharmony_ci qp->s_sge.total_len = wqe->length; 9218c2ecf20Sopenharmony_ci qp->s_len = wqe->length; 9228c2ecf20Sopenharmony_ci } 9238c2ecf20Sopenharmony_ci if (newreq) { 9248c2ecf20Sopenharmony_ci qp->s_tail++; 9258c2ecf20Sopenharmony_ci if (qp->s_tail >= qp->s_size) 9268c2ecf20Sopenharmony_ci qp->s_tail = 0; 9278c2ecf20Sopenharmony_ci } 9288c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ || 9298c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_TID_RDMA_WRITE) 9308c2ecf20Sopenharmony_ci qp->s_psn = wqe->lpsn + 1; 9318c2ecf20Sopenharmony_ci else if (wqe->wr.opcode == IB_WR_TID_RDMA_READ) 9328c2ecf20Sopenharmony_ci qp->s_psn = req->s_next_psn; 9338c2ecf20Sopenharmony_ci else 9348c2ecf20Sopenharmony_ci qp->s_psn++; 9358c2ecf20Sopenharmony_ci break; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_FIRST): 9388c2ecf20Sopenharmony_ci /* 9398c2ecf20Sopenharmony_ci * qp->s_state is normally set to the opcode of the 9408c2ecf20Sopenharmony_ci * last packet constructed for new requests and therefore 9418c2ecf20Sopenharmony_ci * is never set to RDMA read response. 9428c2ecf20Sopenharmony_ci * RDMA_READ_RESPONSE_FIRST is used by the ACK processing 9438c2ecf20Sopenharmony_ci * thread to indicate a SEND needs to be restarted from an 9448c2ecf20Sopenharmony_ci * earlier PSN without interfering with the sending thread. 9458c2ecf20Sopenharmony_ci * See restart_rc(). 9468c2ecf20Sopenharmony_ci */ 9478c2ecf20Sopenharmony_ci qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, pmtu); 9488c2ecf20Sopenharmony_ci fallthrough; 9498c2ecf20Sopenharmony_ci case OP(SEND_FIRST): 9508c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_MIDDLE); 9518c2ecf20Sopenharmony_ci fallthrough; 9528c2ecf20Sopenharmony_ci case OP(SEND_MIDDLE): 9538c2ecf20Sopenharmony_ci bth2 = mask_psn(qp->s_psn++); 9548c2ecf20Sopenharmony_ci ss = &qp->s_sge; 9558c2ecf20Sopenharmony_ci len = qp->s_len; 9568c2ecf20Sopenharmony_ci if (len > pmtu) { 9578c2ecf20Sopenharmony_ci len = pmtu; 9588c2ecf20Sopenharmony_ci middle = HFI1_CAP_IS_KSET(SDMA_AHG); 9598c2ecf20Sopenharmony_ci break; 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_SEND) { 9628c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 9638c2ecf20Sopenharmony_ci } else if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) { 9648c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE); 9658c2ecf20Sopenharmony_ci /* Immediate data comes after the BTH */ 9668c2ecf20Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 9678c2ecf20Sopenharmony_ci hwords += 1; 9688c2ecf20Sopenharmony_ci } else { 9698c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST_WITH_INVALIDATE); 9708c2ecf20Sopenharmony_ci /* invalidate data comes after the BTH */ 9718c2ecf20Sopenharmony_ci ohdr->u.ieth = cpu_to_be32(wqe->wr.ex.invalidate_rkey); 9728c2ecf20Sopenharmony_ci hwords += 1; 9738c2ecf20Sopenharmony_ci } 9748c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 9758c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 9768c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 9778c2ecf20Sopenharmony_ci qp->s_cur++; 9788c2ecf20Sopenharmony_ci if (qp->s_cur >= qp->s_size) 9798c2ecf20Sopenharmony_ci qp->s_cur = 0; 9808c2ecf20Sopenharmony_ci break; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_LAST): 9838c2ecf20Sopenharmony_ci /* 9848c2ecf20Sopenharmony_ci * qp->s_state is normally set to the opcode of the 9858c2ecf20Sopenharmony_ci * last packet constructed for new requests and therefore 9868c2ecf20Sopenharmony_ci * is never set to RDMA read response. 9878c2ecf20Sopenharmony_ci * RDMA_READ_RESPONSE_LAST is used by the ACK processing 9888c2ecf20Sopenharmony_ci * thread to indicate a RDMA write needs to be restarted from 9898c2ecf20Sopenharmony_ci * an earlier PSN without interfering with the sending thread. 9908c2ecf20Sopenharmony_ci * See restart_rc(). 9918c2ecf20Sopenharmony_ci */ 9928c2ecf20Sopenharmony_ci qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, pmtu); 9938c2ecf20Sopenharmony_ci fallthrough; 9948c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 9958c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_MIDDLE); 9968c2ecf20Sopenharmony_ci fallthrough; 9978c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 9988c2ecf20Sopenharmony_ci bth2 = mask_psn(qp->s_psn++); 9998c2ecf20Sopenharmony_ci ss = &qp->s_sge; 10008c2ecf20Sopenharmony_ci len = qp->s_len; 10018c2ecf20Sopenharmony_ci if (len > pmtu) { 10028c2ecf20Sopenharmony_ci len = pmtu; 10038c2ecf20Sopenharmony_ci middle = HFI1_CAP_IS_KSET(SDMA_AHG); 10048c2ecf20Sopenharmony_ci break; 10058c2ecf20Sopenharmony_ci } 10068c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_WRITE) { 10078c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_LAST); 10088c2ecf20Sopenharmony_ci } else { 10098c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_LAST_WITH_IMMEDIATE); 10108c2ecf20Sopenharmony_ci /* Immediate data comes after the BTH */ 10118c2ecf20Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 10128c2ecf20Sopenharmony_ci hwords += 1; 10138c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 10148c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 10158c2ecf20Sopenharmony_ci } 10168c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 10178c2ecf20Sopenharmony_ci qp->s_cur++; 10188c2ecf20Sopenharmony_ci if (qp->s_cur >= qp->s_size) 10198c2ecf20Sopenharmony_ci qp->s_cur = 0; 10208c2ecf20Sopenharmony_ci break; 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_MIDDLE): 10238c2ecf20Sopenharmony_ci /* 10248c2ecf20Sopenharmony_ci * qp->s_state is normally set to the opcode of the 10258c2ecf20Sopenharmony_ci * last packet constructed for new requests and therefore 10268c2ecf20Sopenharmony_ci * is never set to RDMA read response. 10278c2ecf20Sopenharmony_ci * RDMA_READ_RESPONSE_MIDDLE is used by the ACK processing 10288c2ecf20Sopenharmony_ci * thread to indicate a RDMA read needs to be restarted from 10298c2ecf20Sopenharmony_ci * an earlier PSN without interfering with the sending thread. 10308c2ecf20Sopenharmony_ci * See restart_rc(). 10318c2ecf20Sopenharmony_ci */ 10328c2ecf20Sopenharmony_ci len = (delta_psn(qp->s_psn, wqe->psn)) * pmtu; 10338c2ecf20Sopenharmony_ci put_ib_reth_vaddr( 10348c2ecf20Sopenharmony_ci wqe->rdma_wr.remote_addr + len, 10358c2ecf20Sopenharmony_ci &ohdr->u.rc.reth); 10368c2ecf20Sopenharmony_ci ohdr->u.rc.reth.rkey = 10378c2ecf20Sopenharmony_ci cpu_to_be32(wqe->rdma_wr.rkey); 10388c2ecf20Sopenharmony_ci ohdr->u.rc.reth.length = cpu_to_be32(wqe->length - len); 10398c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_REQUEST); 10408c2ecf20Sopenharmony_ci hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32); 10418c2ecf20Sopenharmony_ci bth2 = mask_psn(qp->s_psn) | IB_BTH_REQ_ACK; 10428c2ecf20Sopenharmony_ci qp->s_psn = wqe->lpsn + 1; 10438c2ecf20Sopenharmony_ci ss = NULL; 10448c2ecf20Sopenharmony_ci len = 0; 10458c2ecf20Sopenharmony_ci qp->s_cur++; 10468c2ecf20Sopenharmony_ci if (qp->s_cur == qp->s_size) 10478c2ecf20Sopenharmony_ci qp->s_cur = 0; 10488c2ecf20Sopenharmony_ci break; 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci case TID_OP(WRITE_RESP): 10518c2ecf20Sopenharmony_ci /* 10528c2ecf20Sopenharmony_ci * This value for s_state is used for restarting a TID RDMA 10538c2ecf20Sopenharmony_ci * WRITE request. See comment in OP(RDMA_READ_RESPONSE_MIDDLE 10548c2ecf20Sopenharmony_ci * for more). 10558c2ecf20Sopenharmony_ci */ 10568c2ecf20Sopenharmony_ci req = wqe_to_tid_req(wqe); 10578c2ecf20Sopenharmony_ci req->state = TID_REQUEST_RESEND; 10588c2ecf20Sopenharmony_ci rcu_read_lock(); 10598c2ecf20Sopenharmony_ci remote = rcu_dereference(priv->tid_rdma.remote); 10608c2ecf20Sopenharmony_ci req->comp_seg = delta_psn(qp->s_psn, wqe->psn); 10618c2ecf20Sopenharmony_ci len = wqe->length - (req->comp_seg * remote->max_len); 10628c2ecf20Sopenharmony_ci rcu_read_unlock(); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci bth2 = mask_psn(qp->s_psn); 10658c2ecf20Sopenharmony_ci hwords += hfi1_build_tid_rdma_write_req(qp, wqe, ohdr, &bth1, 10668c2ecf20Sopenharmony_ci &bth2, &len); 10678c2ecf20Sopenharmony_ci qp->s_psn = wqe->lpsn + 1; 10688c2ecf20Sopenharmony_ci ss = NULL; 10698c2ecf20Sopenharmony_ci qp->s_state = TID_OP(WRITE_REQ); 10708c2ecf20Sopenharmony_ci priv->pending_tid_w_resp += delta_psn(wqe->lpsn, bth2) + 1; 10718c2ecf20Sopenharmony_ci priv->s_tid_cur = qp->s_cur; 10728c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 10738c2ecf20Sopenharmony_ci qp->s_cur = 0; 10748c2ecf20Sopenharmony_ci trace_hfi1_tid_req_make_req_write(qp, 0, wqe->wr.opcode, 10758c2ecf20Sopenharmony_ci wqe->psn, wqe->lpsn, req); 10768c2ecf20Sopenharmony_ci break; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci case TID_OP(READ_RESP): 10798c2ecf20Sopenharmony_ci if (wqe->wr.opcode != IB_WR_TID_RDMA_READ) 10808c2ecf20Sopenharmony_ci goto bail; 10818c2ecf20Sopenharmony_ci /* This is used to restart a TID read request */ 10828c2ecf20Sopenharmony_ci req = wqe_to_tid_req(wqe); 10838c2ecf20Sopenharmony_ci wpriv = wqe->priv; 10848c2ecf20Sopenharmony_ci /* 10858c2ecf20Sopenharmony_ci * Back down. The field qp->s_psn has been set to the psn with 10868c2ecf20Sopenharmony_ci * which the request should be restart. It's OK to use division 10878c2ecf20Sopenharmony_ci * as this is on the retry path. 10888c2ecf20Sopenharmony_ci */ 10898c2ecf20Sopenharmony_ci req->cur_seg = delta_psn(qp->s_psn, wqe->psn) / priv->pkts_ps; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci /* 10928c2ecf20Sopenharmony_ci * The following function need to be redefined to return the 10938c2ecf20Sopenharmony_ci * status to make sure that we find the flow. At the same 10948c2ecf20Sopenharmony_ci * time, we can use the req->state change to check if the 10958c2ecf20Sopenharmony_ci * call succeeds or not. 10968c2ecf20Sopenharmony_ci */ 10978c2ecf20Sopenharmony_ci req->state = TID_REQUEST_RESEND; 10988c2ecf20Sopenharmony_ci hfi1_tid_rdma_restart_req(qp, wqe, &bth2); 10998c2ecf20Sopenharmony_ci if (req->state != TID_REQUEST_ACTIVE) { 11008c2ecf20Sopenharmony_ci /* 11018c2ecf20Sopenharmony_ci * Failed to find the flow. Release all allocated tid 11028c2ecf20Sopenharmony_ci * resources. 11038c2ecf20Sopenharmony_ci */ 11048c2ecf20Sopenharmony_ci hfi1_kern_exp_rcv_clear_all(req); 11058c2ecf20Sopenharmony_ci hfi1_kern_clear_hw_flow(priv->rcd, qp); 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci hfi1_trdma_send_complete(qp, wqe, IB_WC_LOC_QP_OP_ERR); 11088c2ecf20Sopenharmony_ci goto bail; 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci req->state = TID_REQUEST_RESEND; 11118c2ecf20Sopenharmony_ci len = min_t(u32, req->seg_len, 11128c2ecf20Sopenharmony_ci wqe->length - req->seg_len * req->cur_seg); 11138c2ecf20Sopenharmony_ci flow = &req->flows[req->flow_idx]; 11148c2ecf20Sopenharmony_ci len -= flow->sent; 11158c2ecf20Sopenharmony_ci req->s_next_psn = flow->flow_state.ib_lpsn + 1; 11168c2ecf20Sopenharmony_ci delta = hfi1_build_tid_rdma_read_packet(wqe, ohdr, &bth1, 11178c2ecf20Sopenharmony_ci &bth2, &len); 11188c2ecf20Sopenharmony_ci if (delta <= 0) { 11198c2ecf20Sopenharmony_ci /* Wait for TID space */ 11208c2ecf20Sopenharmony_ci goto bail; 11218c2ecf20Sopenharmony_ci } 11228c2ecf20Sopenharmony_ci hwords += delta; 11238c2ecf20Sopenharmony_ci ss = &wpriv->ss; 11248c2ecf20Sopenharmony_ci /* Check if this is the last segment */ 11258c2ecf20Sopenharmony_ci if (req->cur_seg >= req->total_segs && 11268c2ecf20Sopenharmony_ci ++qp->s_cur == qp->s_size) 11278c2ecf20Sopenharmony_ci qp->s_cur = 0; 11288c2ecf20Sopenharmony_ci qp->s_psn = req->s_next_psn; 11298c2ecf20Sopenharmony_ci trace_hfi1_tid_req_make_req_read(qp, 0, wqe->wr.opcode, 11308c2ecf20Sopenharmony_ci wqe->psn, wqe->lpsn, req); 11318c2ecf20Sopenharmony_ci break; 11328c2ecf20Sopenharmony_ci case TID_OP(READ_REQ): 11338c2ecf20Sopenharmony_ci req = wqe_to_tid_req(wqe); 11348c2ecf20Sopenharmony_ci delta = cmp_psn(qp->s_psn, wqe->psn); 11358c2ecf20Sopenharmony_ci /* 11368c2ecf20Sopenharmony_ci * If the current WR is not TID RDMA READ, or this is the start 11378c2ecf20Sopenharmony_ci * of a new request, we need to change the qp->s_state so that 11388c2ecf20Sopenharmony_ci * the request can be set up properly. 11398c2ecf20Sopenharmony_ci */ 11408c2ecf20Sopenharmony_ci if (wqe->wr.opcode != IB_WR_TID_RDMA_READ || delta == 0 || 11418c2ecf20Sopenharmony_ci qp->s_cur == qp->s_tail) { 11428c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_REQUEST); 11438c2ecf20Sopenharmony_ci if (delta == 0 || qp->s_cur == qp->s_tail) 11448c2ecf20Sopenharmony_ci goto check_s_state; 11458c2ecf20Sopenharmony_ci else 11468c2ecf20Sopenharmony_ci goto bail; 11478c2ecf20Sopenharmony_ci } 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci /* Rate limiting */ 11508c2ecf20Sopenharmony_ci if (qp->s_num_rd_atomic >= qp->s_max_rd_atomic) { 11518c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_RDMAR; 11528c2ecf20Sopenharmony_ci goto bail; 11538c2ecf20Sopenharmony_ci } 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci wpriv = wqe->priv; 11568c2ecf20Sopenharmony_ci /* Read one segment at a time */ 11578c2ecf20Sopenharmony_ci len = min_t(u32, req->seg_len, 11588c2ecf20Sopenharmony_ci wqe->length - req->seg_len * req->cur_seg); 11598c2ecf20Sopenharmony_ci delta = hfi1_build_tid_rdma_read_req(qp, wqe, ohdr, &bth1, 11608c2ecf20Sopenharmony_ci &bth2, &len); 11618c2ecf20Sopenharmony_ci if (delta <= 0) { 11628c2ecf20Sopenharmony_ci /* Wait for TID space */ 11638c2ecf20Sopenharmony_ci goto bail; 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci hwords += delta; 11668c2ecf20Sopenharmony_ci ss = &wpriv->ss; 11678c2ecf20Sopenharmony_ci /* Check if this is the last segment */ 11688c2ecf20Sopenharmony_ci if (req->cur_seg >= req->total_segs && 11698c2ecf20Sopenharmony_ci ++qp->s_cur == qp->s_size) 11708c2ecf20Sopenharmony_ci qp->s_cur = 0; 11718c2ecf20Sopenharmony_ci qp->s_psn = req->s_next_psn; 11728c2ecf20Sopenharmony_ci trace_hfi1_tid_req_make_req_read(qp, 0, wqe->wr.opcode, 11738c2ecf20Sopenharmony_ci wqe->psn, wqe->lpsn, req); 11748c2ecf20Sopenharmony_ci break; 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci qp->s_sending_hpsn = bth2; 11778c2ecf20Sopenharmony_ci delta = delta_psn(bth2, wqe->psn); 11788c2ecf20Sopenharmony_ci if (delta && delta % HFI1_PSN_CREDIT == 0 && 11798c2ecf20Sopenharmony_ci wqe->wr.opcode != IB_WR_TID_RDMA_WRITE) 11808c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 11818c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_SEND_ONE) { 11828c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_SEND_ONE; 11838c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_ACK; 11848c2ecf20Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 11858c2ecf20Sopenharmony_ci } 11868c2ecf20Sopenharmony_ci qp->s_len -= len; 11878c2ecf20Sopenharmony_ci ps->s_txreq->hdr_dwords = hwords; 11888c2ecf20Sopenharmony_ci ps->s_txreq->sde = priv->s_sde; 11898c2ecf20Sopenharmony_ci ps->s_txreq->ss = ss; 11908c2ecf20Sopenharmony_ci ps->s_txreq->s_cur_size = len; 11918c2ecf20Sopenharmony_ci hfi1_make_ruc_header( 11928c2ecf20Sopenharmony_ci qp, 11938c2ecf20Sopenharmony_ci ohdr, 11948c2ecf20Sopenharmony_ci bth0 | (qp->s_state << 24), 11958c2ecf20Sopenharmony_ci bth1, 11968c2ecf20Sopenharmony_ci bth2, 11978c2ecf20Sopenharmony_ci middle, 11988c2ecf20Sopenharmony_ci ps); 11998c2ecf20Sopenharmony_ci return 1; 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_cidone_free_tx: 12028c2ecf20Sopenharmony_ci hfi1_put_txreq(ps->s_txreq); 12038c2ecf20Sopenharmony_ci ps->s_txreq = NULL; 12048c2ecf20Sopenharmony_ci return 1; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_cibail: 12078c2ecf20Sopenharmony_ci hfi1_put_txreq(ps->s_txreq); 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_cibail_no_tx: 12108c2ecf20Sopenharmony_ci ps->s_txreq = NULL; 12118c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_BUSY; 12128c2ecf20Sopenharmony_ci /* 12138c2ecf20Sopenharmony_ci * If we didn't get a txreq, the QP will be woken up later to try 12148c2ecf20Sopenharmony_ci * again. Set the flags to indicate which work item to wake 12158c2ecf20Sopenharmony_ci * up. 12168c2ecf20Sopenharmony_ci */ 12178c2ecf20Sopenharmony_ci iowait_set_flag(&priv->s_iowait, IOWAIT_PENDING_IB); 12188c2ecf20Sopenharmony_ci return 0; 12198c2ecf20Sopenharmony_ci} 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_cistatic inline void hfi1_make_bth_aeth(struct rvt_qp *qp, 12228c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr, 12238c2ecf20Sopenharmony_ci u32 bth0, u32 bth1) 12248c2ecf20Sopenharmony_ci{ 12258c2ecf20Sopenharmony_ci if (qp->r_nak_state) 12268c2ecf20Sopenharmony_ci ohdr->u.aeth = cpu_to_be32((qp->r_msn & IB_MSN_MASK) | 12278c2ecf20Sopenharmony_ci (qp->r_nak_state << 12288c2ecf20Sopenharmony_ci IB_AETH_CREDIT_SHIFT)); 12298c2ecf20Sopenharmony_ci else 12308c2ecf20Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci ohdr->bth[0] = cpu_to_be32(bth0); 12338c2ecf20Sopenharmony_ci ohdr->bth[1] = cpu_to_be32(bth1 | qp->remote_qpn); 12348c2ecf20Sopenharmony_ci ohdr->bth[2] = cpu_to_be32(mask_psn(qp->r_ack_psn)); 12358c2ecf20Sopenharmony_ci} 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_cistatic inline void hfi1_queue_rc_ack(struct hfi1_packet *packet, bool is_fecn) 12388c2ecf20Sopenharmony_ci{ 12398c2ecf20Sopenharmony_ci struct rvt_qp *qp = packet->qp; 12408c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp; 12418c2ecf20Sopenharmony_ci unsigned long flags; 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 12448c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) 12458c2ecf20Sopenharmony_ci goto unlock; 12468c2ecf20Sopenharmony_ci ibp = rcd_to_iport(packet->rcd); 12478c2ecf20Sopenharmony_ci this_cpu_inc(*ibp->rvp.rc_qacks); 12488c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_ACK_PENDING | RVT_S_RESP_PENDING; 12498c2ecf20Sopenharmony_ci qp->s_nak_state = qp->r_nak_state; 12508c2ecf20Sopenharmony_ci qp->s_ack_psn = qp->r_ack_psn; 12518c2ecf20Sopenharmony_ci if (is_fecn) 12528c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_ECN; 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci /* Schedule the send tasklet. */ 12558c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 12568c2ecf20Sopenharmony_ciunlock: 12578c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 12588c2ecf20Sopenharmony_ci} 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_cistatic inline void hfi1_make_rc_ack_9B(struct hfi1_packet *packet, 12618c2ecf20Sopenharmony_ci struct hfi1_opa_header *opa_hdr, 12628c2ecf20Sopenharmony_ci u8 sc5, bool is_fecn, 12638c2ecf20Sopenharmony_ci u64 *pbc_flags, u32 *hwords, 12648c2ecf20Sopenharmony_ci u32 *nwords) 12658c2ecf20Sopenharmony_ci{ 12668c2ecf20Sopenharmony_ci struct rvt_qp *qp = packet->qp; 12678c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd); 12688c2ecf20Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 12698c2ecf20Sopenharmony_ci struct ib_header *hdr = &opa_hdr->ibh; 12708c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr; 12718c2ecf20Sopenharmony_ci u16 lrh0 = HFI1_LRH_BTH; 12728c2ecf20Sopenharmony_ci u16 pkey; 12738c2ecf20Sopenharmony_ci u32 bth0, bth1; 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci opa_hdr->hdr_type = HFI1_PKT_TYPE_9B; 12768c2ecf20Sopenharmony_ci ohdr = &hdr->u.oth; 12778c2ecf20Sopenharmony_ci /* header size in 32-bit words LRH+BTH+AETH = (8+12+4)/4 */ 12788c2ecf20Sopenharmony_ci *hwords = 6; 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci if (unlikely(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH)) { 12818c2ecf20Sopenharmony_ci *hwords += hfi1_make_grh(ibp, &hdr->u.l.grh, 12828c2ecf20Sopenharmony_ci rdma_ah_read_grh(&qp->remote_ah_attr), 12838c2ecf20Sopenharmony_ci *hwords - 2, SIZE_OF_CRC); 12848c2ecf20Sopenharmony_ci ohdr = &hdr->u.l.oth; 12858c2ecf20Sopenharmony_ci lrh0 = HFI1_LRH_GRH; 12868c2ecf20Sopenharmony_ci } 12878c2ecf20Sopenharmony_ci /* set PBC_DC_INFO bit (aka SC[4]) in pbc_flags */ 12888c2ecf20Sopenharmony_ci *pbc_flags |= ((!!(sc5 & 0x10)) << PBC_DC_INFO_SHIFT); 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci /* read pkey_index w/o lock (its atomic) */ 12918c2ecf20Sopenharmony_ci pkey = hfi1_get_pkey(ibp, qp->s_pkey_index); 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci lrh0 |= (sc5 & IB_SC_MASK) << IB_SC_SHIFT | 12948c2ecf20Sopenharmony_ci (rdma_ah_get_sl(&qp->remote_ah_attr) & IB_SL_MASK) << 12958c2ecf20Sopenharmony_ci IB_SL_SHIFT; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci hfi1_make_ib_hdr(hdr, lrh0, *hwords + SIZE_OF_CRC, 12988c2ecf20Sopenharmony_ci opa_get_lid(rdma_ah_get_dlid(&qp->remote_ah_attr), 9B), 12998c2ecf20Sopenharmony_ci ppd->lid | rdma_ah_get_path_bits(&qp->remote_ah_attr)); 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci bth0 = pkey | (OP(ACKNOWLEDGE) << 24); 13028c2ecf20Sopenharmony_ci if (qp->s_mig_state == IB_MIG_MIGRATED) 13038c2ecf20Sopenharmony_ci bth0 |= IB_BTH_MIG_REQ; 13048c2ecf20Sopenharmony_ci bth1 = (!!is_fecn) << IB_BECN_SHIFT; 13058c2ecf20Sopenharmony_ci /* 13068c2ecf20Sopenharmony_ci * Inline ACKs go out without the use of the Verbs send engine, so 13078c2ecf20Sopenharmony_ci * we need to set the STL Verbs Extended bit here 13088c2ecf20Sopenharmony_ci */ 13098c2ecf20Sopenharmony_ci bth1 |= HFI1_CAP_IS_KSET(OPFN) << IB_BTHE_E_SHIFT; 13108c2ecf20Sopenharmony_ci hfi1_make_bth_aeth(qp, ohdr, bth0, bth1); 13118c2ecf20Sopenharmony_ci} 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_cistatic inline void hfi1_make_rc_ack_16B(struct hfi1_packet *packet, 13148c2ecf20Sopenharmony_ci struct hfi1_opa_header *opa_hdr, 13158c2ecf20Sopenharmony_ci u8 sc5, bool is_fecn, 13168c2ecf20Sopenharmony_ci u64 *pbc_flags, u32 *hwords, 13178c2ecf20Sopenharmony_ci u32 *nwords) 13188c2ecf20Sopenharmony_ci{ 13198c2ecf20Sopenharmony_ci struct rvt_qp *qp = packet->qp; 13208c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd); 13218c2ecf20Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 13228c2ecf20Sopenharmony_ci struct hfi1_16b_header *hdr = &opa_hdr->opah; 13238c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr; 13248c2ecf20Sopenharmony_ci u32 bth0, bth1 = 0; 13258c2ecf20Sopenharmony_ci u16 len, pkey; 13268c2ecf20Sopenharmony_ci bool becn = is_fecn; 13278c2ecf20Sopenharmony_ci u8 l4 = OPA_16B_L4_IB_LOCAL; 13288c2ecf20Sopenharmony_ci u8 extra_bytes; 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci opa_hdr->hdr_type = HFI1_PKT_TYPE_16B; 13318c2ecf20Sopenharmony_ci ohdr = &hdr->u.oth; 13328c2ecf20Sopenharmony_ci /* header size in 32-bit words 16B LRH+BTH+AETH = (16+12+4)/4 */ 13338c2ecf20Sopenharmony_ci *hwords = 8; 13348c2ecf20Sopenharmony_ci extra_bytes = hfi1_get_16b_padding(*hwords << 2, 0); 13358c2ecf20Sopenharmony_ci *nwords = SIZE_OF_CRC + ((extra_bytes + SIZE_OF_LT) >> 2); 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci if (unlikely(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) && 13388c2ecf20Sopenharmony_ci hfi1_check_mcast(rdma_ah_get_dlid(&qp->remote_ah_attr))) { 13398c2ecf20Sopenharmony_ci *hwords += hfi1_make_grh(ibp, &hdr->u.l.grh, 13408c2ecf20Sopenharmony_ci rdma_ah_read_grh(&qp->remote_ah_attr), 13418c2ecf20Sopenharmony_ci *hwords - 4, *nwords); 13428c2ecf20Sopenharmony_ci ohdr = &hdr->u.l.oth; 13438c2ecf20Sopenharmony_ci l4 = OPA_16B_L4_IB_GLOBAL; 13448c2ecf20Sopenharmony_ci } 13458c2ecf20Sopenharmony_ci *pbc_flags |= PBC_PACKET_BYPASS | PBC_INSERT_BYPASS_ICRC; 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci /* read pkey_index w/o lock (its atomic) */ 13488c2ecf20Sopenharmony_ci pkey = hfi1_get_pkey(ibp, qp->s_pkey_index); 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci /* Convert dwords to flits */ 13518c2ecf20Sopenharmony_ci len = (*hwords + *nwords) >> 1; 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci hfi1_make_16b_hdr(hdr, ppd->lid | 13548c2ecf20Sopenharmony_ci (rdma_ah_get_path_bits(&qp->remote_ah_attr) & 13558c2ecf20Sopenharmony_ci ((1 << ppd->lmc) - 1)), 13568c2ecf20Sopenharmony_ci opa_get_lid(rdma_ah_get_dlid(&qp->remote_ah_attr), 13578c2ecf20Sopenharmony_ci 16B), len, pkey, becn, 0, l4, sc5); 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci bth0 = pkey | (OP(ACKNOWLEDGE) << 24); 13608c2ecf20Sopenharmony_ci bth0 |= extra_bytes << 20; 13618c2ecf20Sopenharmony_ci if (qp->s_mig_state == IB_MIG_MIGRATED) 13628c2ecf20Sopenharmony_ci bth1 = OPA_BTH_MIG_REQ; 13638c2ecf20Sopenharmony_ci hfi1_make_bth_aeth(qp, ohdr, bth0, bth1); 13648c2ecf20Sopenharmony_ci} 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_citypedef void (*hfi1_make_rc_ack)(struct hfi1_packet *packet, 13678c2ecf20Sopenharmony_ci struct hfi1_opa_header *opa_hdr, 13688c2ecf20Sopenharmony_ci u8 sc5, bool is_fecn, 13698c2ecf20Sopenharmony_ci u64 *pbc_flags, u32 *hwords, 13708c2ecf20Sopenharmony_ci u32 *nwords); 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci/* We support only two types - 9B and 16B for now */ 13738c2ecf20Sopenharmony_cistatic const hfi1_make_rc_ack hfi1_make_rc_ack_tbl[2] = { 13748c2ecf20Sopenharmony_ci [HFI1_PKT_TYPE_9B] = &hfi1_make_rc_ack_9B, 13758c2ecf20Sopenharmony_ci [HFI1_PKT_TYPE_16B] = &hfi1_make_rc_ack_16B 13768c2ecf20Sopenharmony_ci}; 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci/** 13798c2ecf20Sopenharmony_ci * hfi1_send_rc_ack - Construct an ACK packet and send it 13808c2ecf20Sopenharmony_ci * @qp: a pointer to the QP 13818c2ecf20Sopenharmony_ci * 13828c2ecf20Sopenharmony_ci * This is called from hfi1_rc_rcv() and handle_receive_interrupt(). 13838c2ecf20Sopenharmony_ci * Note that RDMA reads and atomics are handled in the 13848c2ecf20Sopenharmony_ci * send side QP state and send engine. 13858c2ecf20Sopenharmony_ci */ 13868c2ecf20Sopenharmony_civoid hfi1_send_rc_ack(struct hfi1_packet *packet, bool is_fecn) 13878c2ecf20Sopenharmony_ci{ 13888c2ecf20Sopenharmony_ci struct hfi1_ctxtdata *rcd = packet->rcd; 13898c2ecf20Sopenharmony_ci struct rvt_qp *qp = packet->qp; 13908c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = rcd_to_iport(rcd); 13918c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 13928c2ecf20Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 13938c2ecf20Sopenharmony_ci u8 sc5 = ibp->sl_to_sc[rdma_ah_get_sl(&qp->remote_ah_attr)]; 13948c2ecf20Sopenharmony_ci u64 pbc, pbc_flags = 0; 13958c2ecf20Sopenharmony_ci u32 hwords = 0; 13968c2ecf20Sopenharmony_ci u32 nwords = 0; 13978c2ecf20Sopenharmony_ci u32 plen; 13988c2ecf20Sopenharmony_ci struct pio_buf *pbuf; 13998c2ecf20Sopenharmony_ci struct hfi1_opa_header opa_hdr; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci /* clear the defer count */ 14028c2ecf20Sopenharmony_ci qp->r_adefered = 0; 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci /* Don't send ACK or NAK if a RDMA read or atomic is pending. */ 14058c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_RESP_PENDING) { 14068c2ecf20Sopenharmony_ci hfi1_queue_rc_ack(packet, is_fecn); 14078c2ecf20Sopenharmony_ci return; 14088c2ecf20Sopenharmony_ci } 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci /* Ensure s_rdma_ack_cnt changes are committed */ 14118c2ecf20Sopenharmony_ci if (qp->s_rdma_ack_cnt) { 14128c2ecf20Sopenharmony_ci hfi1_queue_rc_ack(packet, is_fecn); 14138c2ecf20Sopenharmony_ci return; 14148c2ecf20Sopenharmony_ci } 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci /* Don't try to send ACKs if the link isn't ACTIVE */ 14178c2ecf20Sopenharmony_ci if (driver_lstate(ppd) != IB_PORT_ACTIVE) 14188c2ecf20Sopenharmony_ci return; 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_ci /* Make the appropriate header */ 14218c2ecf20Sopenharmony_ci hfi1_make_rc_ack_tbl[priv->hdr_type](packet, &opa_hdr, sc5, is_fecn, 14228c2ecf20Sopenharmony_ci &pbc_flags, &hwords, &nwords); 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_ci plen = 2 /* PBC */ + hwords + nwords; 14258c2ecf20Sopenharmony_ci pbc = create_pbc(ppd, pbc_flags, qp->srate_mbps, 14268c2ecf20Sopenharmony_ci sc_to_vlt(ppd->dd, sc5), plen); 14278c2ecf20Sopenharmony_ci pbuf = sc_buffer_alloc(rcd->sc, plen, NULL, NULL); 14288c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(pbuf)) { 14298c2ecf20Sopenharmony_ci /* 14308c2ecf20Sopenharmony_ci * We have no room to send at the moment. Pass 14318c2ecf20Sopenharmony_ci * responsibility for sending the ACK to the send engine 14328c2ecf20Sopenharmony_ci * so that when enough buffer space becomes available, 14338c2ecf20Sopenharmony_ci * the ACK is sent ahead of other outgoing packets. 14348c2ecf20Sopenharmony_ci */ 14358c2ecf20Sopenharmony_ci hfi1_queue_rc_ack(packet, is_fecn); 14368c2ecf20Sopenharmony_ci return; 14378c2ecf20Sopenharmony_ci } 14388c2ecf20Sopenharmony_ci trace_ack_output_ibhdr(dd_from_ibdev(qp->ibqp.device), 14398c2ecf20Sopenharmony_ci &opa_hdr, ib_is_sc5(sc5)); 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci /* write the pbc and data */ 14428c2ecf20Sopenharmony_ci ppd->dd->pio_inline_send(ppd->dd, pbuf, pbc, 14438c2ecf20Sopenharmony_ci (priv->hdr_type == HFI1_PKT_TYPE_9B ? 14448c2ecf20Sopenharmony_ci (void *)&opa_hdr.ibh : 14458c2ecf20Sopenharmony_ci (void *)&opa_hdr.opah), hwords); 14468c2ecf20Sopenharmony_ci return; 14478c2ecf20Sopenharmony_ci} 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci/** 14508c2ecf20Sopenharmony_ci * update_num_rd_atomic - update the qp->s_num_rd_atomic 14518c2ecf20Sopenharmony_ci * @qp: the QP 14528c2ecf20Sopenharmony_ci * @psn: the packet sequence number to restart at 14538c2ecf20Sopenharmony_ci * @wqe: the wqe 14548c2ecf20Sopenharmony_ci * 14558c2ecf20Sopenharmony_ci * This is called from reset_psn() to update qp->s_num_rd_atomic 14568c2ecf20Sopenharmony_ci * for the current wqe. 14578c2ecf20Sopenharmony_ci * Called at interrupt level with the QP s_lock held. 14588c2ecf20Sopenharmony_ci */ 14598c2ecf20Sopenharmony_cistatic void update_num_rd_atomic(struct rvt_qp *qp, u32 psn, 14608c2ecf20Sopenharmony_ci struct rvt_swqe *wqe) 14618c2ecf20Sopenharmony_ci{ 14628c2ecf20Sopenharmony_ci u32 opcode = wqe->wr.opcode; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci if (opcode == IB_WR_RDMA_READ || 14658c2ecf20Sopenharmony_ci opcode == IB_WR_ATOMIC_CMP_AND_SWP || 14668c2ecf20Sopenharmony_ci opcode == IB_WR_ATOMIC_FETCH_AND_ADD) { 14678c2ecf20Sopenharmony_ci qp->s_num_rd_atomic++; 14688c2ecf20Sopenharmony_ci } else if (opcode == IB_WR_TID_RDMA_READ) { 14698c2ecf20Sopenharmony_ci struct tid_rdma_request *req = wqe_to_tid_req(wqe); 14708c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci if (cmp_psn(psn, wqe->lpsn) <= 0) { 14738c2ecf20Sopenharmony_ci u32 cur_seg; 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci cur_seg = (psn - wqe->psn) / priv->pkts_ps; 14768c2ecf20Sopenharmony_ci req->ack_pending = cur_seg - req->comp_seg; 14778c2ecf20Sopenharmony_ci priv->pending_tid_r_segs += req->ack_pending; 14788c2ecf20Sopenharmony_ci qp->s_num_rd_atomic += req->ack_pending; 14798c2ecf20Sopenharmony_ci trace_hfi1_tid_req_update_num_rd_atomic(qp, 0, 14808c2ecf20Sopenharmony_ci wqe->wr.opcode, 14818c2ecf20Sopenharmony_ci wqe->psn, 14828c2ecf20Sopenharmony_ci wqe->lpsn, 14838c2ecf20Sopenharmony_ci req); 14848c2ecf20Sopenharmony_ci } else { 14858c2ecf20Sopenharmony_ci priv->pending_tid_r_segs += req->total_segs; 14868c2ecf20Sopenharmony_ci qp->s_num_rd_atomic += req->total_segs; 14878c2ecf20Sopenharmony_ci } 14888c2ecf20Sopenharmony_ci } 14898c2ecf20Sopenharmony_ci} 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci/** 14928c2ecf20Sopenharmony_ci * reset_psn - reset the QP state to send starting from PSN 14938c2ecf20Sopenharmony_ci * @qp: the QP 14948c2ecf20Sopenharmony_ci * @psn: the packet sequence number to restart at 14958c2ecf20Sopenharmony_ci * 14968c2ecf20Sopenharmony_ci * This is called from hfi1_rc_rcv() to process an incoming RC ACK 14978c2ecf20Sopenharmony_ci * for the given QP. 14988c2ecf20Sopenharmony_ci * Called at interrupt level with the QP s_lock held. 14998c2ecf20Sopenharmony_ci */ 15008c2ecf20Sopenharmony_cistatic void reset_psn(struct rvt_qp *qp, u32 psn) 15018c2ecf20Sopenharmony_ci{ 15028c2ecf20Sopenharmony_ci u32 n = qp->s_acked; 15038c2ecf20Sopenharmony_ci struct rvt_swqe *wqe = rvt_get_swqe_ptr(qp, n); 15048c2ecf20Sopenharmony_ci u32 opcode; 15058c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 15088c2ecf20Sopenharmony_ci qp->s_cur = n; 15098c2ecf20Sopenharmony_ci priv->pending_tid_r_segs = 0; 15108c2ecf20Sopenharmony_ci priv->pending_tid_w_resp = 0; 15118c2ecf20Sopenharmony_ci qp->s_num_rd_atomic = 0; 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci /* 15148c2ecf20Sopenharmony_ci * If we are starting the request from the beginning, 15158c2ecf20Sopenharmony_ci * let the normal send code handle initialization. 15168c2ecf20Sopenharmony_ci */ 15178c2ecf20Sopenharmony_ci if (cmp_psn(psn, wqe->psn) <= 0) { 15188c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 15198c2ecf20Sopenharmony_ci goto done; 15208c2ecf20Sopenharmony_ci } 15218c2ecf20Sopenharmony_ci update_num_rd_atomic(qp, psn, wqe); 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci /* Find the work request opcode corresponding to the given PSN. */ 15248c2ecf20Sopenharmony_ci for (;;) { 15258c2ecf20Sopenharmony_ci int diff; 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci if (++n == qp->s_size) 15288c2ecf20Sopenharmony_ci n = 0; 15298c2ecf20Sopenharmony_ci if (n == qp->s_tail) 15308c2ecf20Sopenharmony_ci break; 15318c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, n); 15328c2ecf20Sopenharmony_ci diff = cmp_psn(psn, wqe->psn); 15338c2ecf20Sopenharmony_ci if (diff < 0) { 15348c2ecf20Sopenharmony_ci /* Point wqe back to the previous one*/ 15358c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_cur); 15368c2ecf20Sopenharmony_ci break; 15378c2ecf20Sopenharmony_ci } 15388c2ecf20Sopenharmony_ci qp->s_cur = n; 15398c2ecf20Sopenharmony_ci /* 15408c2ecf20Sopenharmony_ci * If we are starting the request from the beginning, 15418c2ecf20Sopenharmony_ci * let the normal send code handle initialization. 15428c2ecf20Sopenharmony_ci */ 15438c2ecf20Sopenharmony_ci if (diff == 0) { 15448c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 15458c2ecf20Sopenharmony_ci goto done; 15468c2ecf20Sopenharmony_ci } 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci update_num_rd_atomic(qp, psn, wqe); 15498c2ecf20Sopenharmony_ci } 15508c2ecf20Sopenharmony_ci opcode = wqe->wr.opcode; 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci /* 15538c2ecf20Sopenharmony_ci * Set the state to restart in the middle of a request. 15548c2ecf20Sopenharmony_ci * Don't change the s_sge, s_cur_sge, or s_cur_size. 15558c2ecf20Sopenharmony_ci * See hfi1_make_rc_req(). 15568c2ecf20Sopenharmony_ci */ 15578c2ecf20Sopenharmony_ci switch (opcode) { 15588c2ecf20Sopenharmony_ci case IB_WR_SEND: 15598c2ecf20Sopenharmony_ci case IB_WR_SEND_WITH_IMM: 15608c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_RESPONSE_FIRST); 15618c2ecf20Sopenharmony_ci break; 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE: 15648c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE_WITH_IMM: 15658c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_RESPONSE_LAST); 15668c2ecf20Sopenharmony_ci break; 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci case IB_WR_TID_RDMA_WRITE: 15698c2ecf20Sopenharmony_ci qp->s_state = TID_OP(WRITE_RESP); 15708c2ecf20Sopenharmony_ci break; 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci case IB_WR_RDMA_READ: 15738c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_READ_RESPONSE_MIDDLE); 15748c2ecf20Sopenharmony_ci break; 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci case IB_WR_TID_RDMA_READ: 15778c2ecf20Sopenharmony_ci qp->s_state = TID_OP(READ_RESP); 15788c2ecf20Sopenharmony_ci break; 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci default: 15818c2ecf20Sopenharmony_ci /* 15828c2ecf20Sopenharmony_ci * This case shouldn't happen since its only 15838c2ecf20Sopenharmony_ci * one PSN per req. 15848c2ecf20Sopenharmony_ci */ 15858c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 15868c2ecf20Sopenharmony_ci } 15878c2ecf20Sopenharmony_cidone: 15888c2ecf20Sopenharmony_ci priv->s_flags &= ~HFI1_S_TID_WAIT_INTERLCK; 15898c2ecf20Sopenharmony_ci qp->s_psn = psn; 15908c2ecf20Sopenharmony_ci /* 15918c2ecf20Sopenharmony_ci * Set RVT_S_WAIT_PSN as rc_complete() may start the timer 15928c2ecf20Sopenharmony_ci * asynchronously before the send engine can get scheduled. 15938c2ecf20Sopenharmony_ci * Doing it in hfi1_make_rc_req() is too late. 15948c2ecf20Sopenharmony_ci */ 15958c2ecf20Sopenharmony_ci if ((cmp_psn(qp->s_psn, qp->s_sending_hpsn) <= 0) && 15968c2ecf20Sopenharmony_ci (cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)) 15978c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_PSN; 15988c2ecf20Sopenharmony_ci qp->s_flags &= ~HFI1_S_AHG_VALID; 15998c2ecf20Sopenharmony_ci trace_hfi1_sender_reset_psn(qp); 16008c2ecf20Sopenharmony_ci} 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci/* 16038c2ecf20Sopenharmony_ci * Back up requester to resend the last un-ACKed request. 16048c2ecf20Sopenharmony_ci * The QP r_lock and s_lock should be held and interrupts disabled. 16058c2ecf20Sopenharmony_ci */ 16068c2ecf20Sopenharmony_civoid hfi1_restart_rc(struct rvt_qp *qp, u32 psn, int wait) 16078c2ecf20Sopenharmony_ci{ 16088c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 16098c2ecf20Sopenharmony_ci struct rvt_swqe *wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 16108c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp; 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->r_lock); 16138c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 16148c2ecf20Sopenharmony_ci trace_hfi1_sender_restart_rc(qp); 16158c2ecf20Sopenharmony_ci if (qp->s_retry == 0) { 16168c2ecf20Sopenharmony_ci if (qp->s_mig_state == IB_MIG_ARMED) { 16178c2ecf20Sopenharmony_ci hfi1_migrate_qp(qp); 16188c2ecf20Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 16198c2ecf20Sopenharmony_ci } else if (qp->s_last == qp->s_acked) { 16208c2ecf20Sopenharmony_ci /* 16218c2ecf20Sopenharmony_ci * We need special handling for the OPFN request WQEs as 16228c2ecf20Sopenharmony_ci * they are not allowed to generate real user errors 16238c2ecf20Sopenharmony_ci */ 16248c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_OPFN) { 16258c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = 16268c2ecf20Sopenharmony_ci to_iport(qp->ibqp.device, qp->port_num); 16278c2ecf20Sopenharmony_ci /* 16288c2ecf20Sopenharmony_ci * Call opfn_conn_reply() with capcode and 16298c2ecf20Sopenharmony_ci * remaining data as 0 to close out the 16308c2ecf20Sopenharmony_ci * current request 16318c2ecf20Sopenharmony_ci */ 16328c2ecf20Sopenharmony_ci opfn_conn_reply(qp, priv->opfn.curr); 16338c2ecf20Sopenharmony_ci wqe = do_rc_completion(qp, wqe, ibp); 16348c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_ACK; 16358c2ecf20Sopenharmony_ci } else { 16368c2ecf20Sopenharmony_ci trace_hfi1_tid_write_sender_restart_rc(qp, 0); 16378c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_TID_RDMA_READ) { 16388c2ecf20Sopenharmony_ci struct tid_rdma_request *req; 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ci req = wqe_to_tid_req(wqe); 16418c2ecf20Sopenharmony_ci hfi1_kern_exp_rcv_clear_all(req); 16428c2ecf20Sopenharmony_ci hfi1_kern_clear_hw_flow(priv->rcd, qp); 16438c2ecf20Sopenharmony_ci } 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci hfi1_trdma_send_complete(qp, wqe, 16468c2ecf20Sopenharmony_ci IB_WC_RETRY_EXC_ERR); 16478c2ecf20Sopenharmony_ci rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 16488c2ecf20Sopenharmony_ci } 16498c2ecf20Sopenharmony_ci return; 16508c2ecf20Sopenharmony_ci } else { /* need to handle delayed completion */ 16518c2ecf20Sopenharmony_ci return; 16528c2ecf20Sopenharmony_ci } 16538c2ecf20Sopenharmony_ci } else { 16548c2ecf20Sopenharmony_ci qp->s_retry--; 16558c2ecf20Sopenharmony_ci } 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci ibp = to_iport(qp->ibqp.device, qp->port_num); 16588c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ || 16598c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_TID_RDMA_READ) 16608c2ecf20Sopenharmony_ci ibp->rvp.n_rc_resends++; 16618c2ecf20Sopenharmony_ci else 16628c2ecf20Sopenharmony_ci ibp->rvp.n_rc_resends += delta_psn(qp->s_psn, psn); 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_FENCE | RVT_S_WAIT_RDMAR | 16658c2ecf20Sopenharmony_ci RVT_S_WAIT_SSN_CREDIT | RVT_S_WAIT_PSN | 16668c2ecf20Sopenharmony_ci RVT_S_WAIT_ACK | HFI1_S_WAIT_TID_RESP); 16678c2ecf20Sopenharmony_ci if (wait) 16688c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_SEND_ONE; 16698c2ecf20Sopenharmony_ci reset_psn(qp, psn); 16708c2ecf20Sopenharmony_ci} 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci/* 16738c2ecf20Sopenharmony_ci * Set qp->s_sending_psn to the next PSN after the given one. 16748c2ecf20Sopenharmony_ci * This would be psn+1 except when RDMA reads or TID RDMA ops 16758c2ecf20Sopenharmony_ci * are present. 16768c2ecf20Sopenharmony_ci */ 16778c2ecf20Sopenharmony_cistatic void reset_sending_psn(struct rvt_qp *qp, u32 psn) 16788c2ecf20Sopenharmony_ci{ 16798c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 16808c2ecf20Sopenharmony_ci u32 n = qp->s_last; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 16838c2ecf20Sopenharmony_ci /* Find the work request corresponding to the given PSN. */ 16848c2ecf20Sopenharmony_ci for (;;) { 16858c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, n); 16868c2ecf20Sopenharmony_ci if (cmp_psn(psn, wqe->lpsn) <= 0) { 16878c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ || 16888c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_TID_RDMA_READ || 16898c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_TID_RDMA_WRITE) 16908c2ecf20Sopenharmony_ci qp->s_sending_psn = wqe->lpsn + 1; 16918c2ecf20Sopenharmony_ci else 16928c2ecf20Sopenharmony_ci qp->s_sending_psn = psn + 1; 16938c2ecf20Sopenharmony_ci break; 16948c2ecf20Sopenharmony_ci } 16958c2ecf20Sopenharmony_ci if (++n == qp->s_size) 16968c2ecf20Sopenharmony_ci n = 0; 16978c2ecf20Sopenharmony_ci if (n == qp->s_tail) 16988c2ecf20Sopenharmony_ci break; 16998c2ecf20Sopenharmony_ci } 17008c2ecf20Sopenharmony_ci} 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci/** 17038c2ecf20Sopenharmony_ci * hfi1_rc_verbs_aborted - handle abort status 17048c2ecf20Sopenharmony_ci * @qp: the QP 17058c2ecf20Sopenharmony_ci * @opah: the opa header 17068c2ecf20Sopenharmony_ci * 17078c2ecf20Sopenharmony_ci * This code modifies both ACK bit in BTH[2] 17088c2ecf20Sopenharmony_ci * and the s_flags to go into send one mode. 17098c2ecf20Sopenharmony_ci * 17108c2ecf20Sopenharmony_ci * This serves to throttle the send engine to only 17118c2ecf20Sopenharmony_ci * send a single packet in the likely case the 17128c2ecf20Sopenharmony_ci * a link has gone down. 17138c2ecf20Sopenharmony_ci */ 17148c2ecf20Sopenharmony_civoid hfi1_rc_verbs_aborted(struct rvt_qp *qp, struct hfi1_opa_header *opah) 17158c2ecf20Sopenharmony_ci{ 17168c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr = hfi1_get_rc_ohdr(opah); 17178c2ecf20Sopenharmony_ci u8 opcode = ib_bth_get_opcode(ohdr); 17188c2ecf20Sopenharmony_ci u32 psn; 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci /* ignore responses */ 17218c2ecf20Sopenharmony_ci if ((opcode >= OP(RDMA_READ_RESPONSE_FIRST) && 17228c2ecf20Sopenharmony_ci opcode <= OP(ATOMIC_ACKNOWLEDGE)) || 17238c2ecf20Sopenharmony_ci opcode == TID_OP(READ_RESP) || 17248c2ecf20Sopenharmony_ci opcode == TID_OP(WRITE_RESP)) 17258c2ecf20Sopenharmony_ci return; 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci psn = ib_bth_get_psn(ohdr) | IB_BTH_REQ_ACK; 17288c2ecf20Sopenharmony_ci ohdr->bth[2] = cpu_to_be32(psn); 17298c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_SEND_ONE; 17308c2ecf20Sopenharmony_ci} 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci/* 17338c2ecf20Sopenharmony_ci * This should be called with the QP s_lock held and interrupts disabled. 17348c2ecf20Sopenharmony_ci */ 17358c2ecf20Sopenharmony_civoid hfi1_rc_send_complete(struct rvt_qp *qp, struct hfi1_opa_header *opah) 17368c2ecf20Sopenharmony_ci{ 17378c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr; 17388c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 17398c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 17408c2ecf20Sopenharmony_ci u32 opcode, head, tail; 17418c2ecf20Sopenharmony_ci u32 psn; 17428c2ecf20Sopenharmony_ci struct tid_rdma_request *req; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 17458c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_SEND_OR_FLUSH_OR_RECV_OK)) 17468c2ecf20Sopenharmony_ci return; 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci ohdr = hfi1_get_rc_ohdr(opah); 17498c2ecf20Sopenharmony_ci opcode = ib_bth_get_opcode(ohdr); 17508c2ecf20Sopenharmony_ci if ((opcode >= OP(RDMA_READ_RESPONSE_FIRST) && 17518c2ecf20Sopenharmony_ci opcode <= OP(ATOMIC_ACKNOWLEDGE)) || 17528c2ecf20Sopenharmony_ci opcode == TID_OP(READ_RESP) || 17538c2ecf20Sopenharmony_ci opcode == TID_OP(WRITE_RESP)) { 17548c2ecf20Sopenharmony_ci WARN_ON(!qp->s_rdma_ack_cnt); 17558c2ecf20Sopenharmony_ci qp->s_rdma_ack_cnt--; 17568c2ecf20Sopenharmony_ci return; 17578c2ecf20Sopenharmony_ci } 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci psn = ib_bth_get_psn(ohdr); 17608c2ecf20Sopenharmony_ci /* 17618c2ecf20Sopenharmony_ci * Don't attempt to reset the sending PSN for packets in the 17628c2ecf20Sopenharmony_ci * KDETH PSN space since the PSN does not match anything. 17638c2ecf20Sopenharmony_ci */ 17648c2ecf20Sopenharmony_ci if (opcode != TID_OP(WRITE_DATA) && 17658c2ecf20Sopenharmony_ci opcode != TID_OP(WRITE_DATA_LAST) && 17668c2ecf20Sopenharmony_ci opcode != TID_OP(ACK) && opcode != TID_OP(RESYNC)) 17678c2ecf20Sopenharmony_ci reset_sending_psn(qp, psn); 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci /* Handle TID RDMA WRITE packets differently */ 17708c2ecf20Sopenharmony_ci if (opcode >= TID_OP(WRITE_REQ) && 17718c2ecf20Sopenharmony_ci opcode <= TID_OP(WRITE_DATA_LAST)) { 17728c2ecf20Sopenharmony_ci head = priv->s_tid_head; 17738c2ecf20Sopenharmony_ci tail = priv->s_tid_cur; 17748c2ecf20Sopenharmony_ci /* 17758c2ecf20Sopenharmony_ci * s_tid_cur is set to s_tid_head in the case, where 17768c2ecf20Sopenharmony_ci * a new TID RDMA request is being started and all 17778c2ecf20Sopenharmony_ci * previous ones have been completed. 17788c2ecf20Sopenharmony_ci * Therefore, we need to do a secondary check in order 17798c2ecf20Sopenharmony_ci * to properly determine whether we should start the 17808c2ecf20Sopenharmony_ci * RC timer. 17818c2ecf20Sopenharmony_ci */ 17828c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, tail); 17838c2ecf20Sopenharmony_ci req = wqe_to_tid_req(wqe); 17848c2ecf20Sopenharmony_ci if (head == tail && req->comp_seg < req->total_segs) { 17858c2ecf20Sopenharmony_ci if (tail == 0) 17868c2ecf20Sopenharmony_ci tail = qp->s_size - 1; 17878c2ecf20Sopenharmony_ci else 17888c2ecf20Sopenharmony_ci tail -= 1; 17898c2ecf20Sopenharmony_ci } 17908c2ecf20Sopenharmony_ci } else { 17918c2ecf20Sopenharmony_ci head = qp->s_tail; 17928c2ecf20Sopenharmony_ci tail = qp->s_acked; 17938c2ecf20Sopenharmony_ci } 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci /* 17968c2ecf20Sopenharmony_ci * Start timer after a packet requesting an ACK has been sent and 17978c2ecf20Sopenharmony_ci * there are still requests that haven't been acked. 17988c2ecf20Sopenharmony_ci */ 17998c2ecf20Sopenharmony_ci if ((psn & IB_BTH_REQ_ACK) && tail != head && 18008c2ecf20Sopenharmony_ci opcode != TID_OP(WRITE_DATA) && opcode != TID_OP(WRITE_DATA_LAST) && 18018c2ecf20Sopenharmony_ci opcode != TID_OP(RESYNC) && 18028c2ecf20Sopenharmony_ci !(qp->s_flags & 18038c2ecf20Sopenharmony_ci (RVT_S_TIMER | RVT_S_WAIT_RNR | RVT_S_WAIT_PSN)) && 18048c2ecf20Sopenharmony_ci (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) { 18058c2ecf20Sopenharmony_ci if (opcode == TID_OP(READ_REQ)) 18068c2ecf20Sopenharmony_ci rvt_add_retry_timer_ext(qp, priv->timeout_shift); 18078c2ecf20Sopenharmony_ci else 18088c2ecf20Sopenharmony_ci rvt_add_retry_timer(qp); 18098c2ecf20Sopenharmony_ci } 18108c2ecf20Sopenharmony_ci 18118c2ecf20Sopenharmony_ci /* Start TID RDMA ACK timer */ 18128c2ecf20Sopenharmony_ci if ((opcode == TID_OP(WRITE_DATA) || 18138c2ecf20Sopenharmony_ci opcode == TID_OP(WRITE_DATA_LAST) || 18148c2ecf20Sopenharmony_ci opcode == TID_OP(RESYNC)) && 18158c2ecf20Sopenharmony_ci (psn & IB_BTH_REQ_ACK) && 18168c2ecf20Sopenharmony_ci !(priv->s_flags & HFI1_S_TID_RETRY_TIMER) && 18178c2ecf20Sopenharmony_ci (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) { 18188c2ecf20Sopenharmony_ci /* 18198c2ecf20Sopenharmony_ci * The TID RDMA ACK packet could be received before this 18208c2ecf20Sopenharmony_ci * function is called. Therefore, add the timer only if TID 18218c2ecf20Sopenharmony_ci * RDMA ACK packets are actually pending. 18228c2ecf20Sopenharmony_ci */ 18238c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 18248c2ecf20Sopenharmony_ci req = wqe_to_tid_req(wqe); 18258c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_TID_RDMA_WRITE && 18268c2ecf20Sopenharmony_ci req->ack_seg < req->cur_seg) 18278c2ecf20Sopenharmony_ci hfi1_add_tid_retry_timer(qp); 18288c2ecf20Sopenharmony_ci } 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci while (qp->s_last != qp->s_acked) { 18318c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_last); 18328c2ecf20Sopenharmony_ci if (cmp_psn(wqe->lpsn, qp->s_sending_psn) >= 0 && 18338c2ecf20Sopenharmony_ci cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) <= 0) 18348c2ecf20Sopenharmony_ci break; 18358c2ecf20Sopenharmony_ci trdma_clean_swqe(qp, wqe); 18368c2ecf20Sopenharmony_ci trace_hfi1_qp_send_completion(qp, wqe, qp->s_last); 18378c2ecf20Sopenharmony_ci rvt_qp_complete_swqe(qp, 18388c2ecf20Sopenharmony_ci wqe, 18398c2ecf20Sopenharmony_ci ib_hfi1_wc_opcode[wqe->wr.opcode], 18408c2ecf20Sopenharmony_ci IB_WC_SUCCESS); 18418c2ecf20Sopenharmony_ci } 18428c2ecf20Sopenharmony_ci /* 18438c2ecf20Sopenharmony_ci * If we were waiting for sends to complete before re-sending, 18448c2ecf20Sopenharmony_ci * and they are now complete, restart sending. 18458c2ecf20Sopenharmony_ci */ 18468c2ecf20Sopenharmony_ci trace_hfi1_sendcomplete(qp, psn); 18478c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_PSN && 18488c2ecf20Sopenharmony_ci cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) > 0) { 18498c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_PSN; 18508c2ecf20Sopenharmony_ci qp->s_sending_psn = qp->s_psn; 18518c2ecf20Sopenharmony_ci qp->s_sending_hpsn = qp->s_psn - 1; 18528c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 18538c2ecf20Sopenharmony_ci } 18548c2ecf20Sopenharmony_ci} 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_cistatic inline void update_last_psn(struct rvt_qp *qp, u32 psn) 18578c2ecf20Sopenharmony_ci{ 18588c2ecf20Sopenharmony_ci qp->s_last_psn = psn; 18598c2ecf20Sopenharmony_ci} 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci/* 18628c2ecf20Sopenharmony_ci * Generate a SWQE completion. 18638c2ecf20Sopenharmony_ci * This is similar to hfi1_send_complete but has to check to be sure 18648c2ecf20Sopenharmony_ci * that the SGEs are not being referenced if the SWQE is being resent. 18658c2ecf20Sopenharmony_ci */ 18668c2ecf20Sopenharmony_cistruct rvt_swqe *do_rc_completion(struct rvt_qp *qp, 18678c2ecf20Sopenharmony_ci struct rvt_swqe *wqe, 18688c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp) 18698c2ecf20Sopenharmony_ci{ 18708c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 18738c2ecf20Sopenharmony_ci /* 18748c2ecf20Sopenharmony_ci * Don't decrement refcount and don't generate a 18758c2ecf20Sopenharmony_ci * completion if the SWQE is being resent until the send 18768c2ecf20Sopenharmony_ci * is finished. 18778c2ecf20Sopenharmony_ci */ 18788c2ecf20Sopenharmony_ci trace_hfi1_rc_completion(qp, wqe->lpsn); 18798c2ecf20Sopenharmony_ci if (cmp_psn(wqe->lpsn, qp->s_sending_psn) < 0 || 18808c2ecf20Sopenharmony_ci cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) > 0) { 18818c2ecf20Sopenharmony_ci trdma_clean_swqe(qp, wqe); 18828c2ecf20Sopenharmony_ci trace_hfi1_qp_send_completion(qp, wqe, qp->s_last); 18838c2ecf20Sopenharmony_ci rvt_qp_complete_swqe(qp, 18848c2ecf20Sopenharmony_ci wqe, 18858c2ecf20Sopenharmony_ci ib_hfi1_wc_opcode[wqe->wr.opcode], 18868c2ecf20Sopenharmony_ci IB_WC_SUCCESS); 18878c2ecf20Sopenharmony_ci } else { 18888c2ecf20Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci this_cpu_inc(*ibp->rvp.rc_delayed_comp); 18918c2ecf20Sopenharmony_ci /* 18928c2ecf20Sopenharmony_ci * If send progress not running attempt to progress 18938c2ecf20Sopenharmony_ci * SDMA queue. 18948c2ecf20Sopenharmony_ci */ 18958c2ecf20Sopenharmony_ci if (ppd->dd->flags & HFI1_HAS_SEND_DMA) { 18968c2ecf20Sopenharmony_ci struct sdma_engine *engine; 18978c2ecf20Sopenharmony_ci u8 sl = rdma_ah_get_sl(&qp->remote_ah_attr); 18988c2ecf20Sopenharmony_ci u8 sc5; 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci /* For now use sc to find engine */ 19018c2ecf20Sopenharmony_ci sc5 = ibp->sl_to_sc[sl]; 19028c2ecf20Sopenharmony_ci engine = qp_to_sdma_engine(qp, sc5); 19038c2ecf20Sopenharmony_ci sdma_engine_progress_schedule(engine); 19048c2ecf20Sopenharmony_ci } 19058c2ecf20Sopenharmony_ci } 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 19088c2ecf20Sopenharmony_ci /* 19098c2ecf20Sopenharmony_ci * Don't update the last PSN if the request being completed is 19108c2ecf20Sopenharmony_ci * a TID RDMA WRITE request. 19118c2ecf20Sopenharmony_ci * Completion of the TID RDMA WRITE requests are done by the 19128c2ecf20Sopenharmony_ci * TID RDMA ACKs and as such could be for a request that has 19138c2ecf20Sopenharmony_ci * already been ACKed as far as the IB state machine is 19148c2ecf20Sopenharmony_ci * concerned. 19158c2ecf20Sopenharmony_ci */ 19168c2ecf20Sopenharmony_ci if (wqe->wr.opcode != IB_WR_TID_RDMA_WRITE) 19178c2ecf20Sopenharmony_ci update_last_psn(qp, wqe->lpsn); 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_ci /* 19208c2ecf20Sopenharmony_ci * If we are completing a request which is in the process of 19218c2ecf20Sopenharmony_ci * being resent, we can stop re-sending it since we know the 19228c2ecf20Sopenharmony_ci * responder has already seen it. 19238c2ecf20Sopenharmony_ci */ 19248c2ecf20Sopenharmony_ci if (qp->s_acked == qp->s_cur) { 19258c2ecf20Sopenharmony_ci if (++qp->s_cur >= qp->s_size) 19268c2ecf20Sopenharmony_ci qp->s_cur = 0; 19278c2ecf20Sopenharmony_ci qp->s_acked = qp->s_cur; 19288c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_cur); 19298c2ecf20Sopenharmony_ci if (qp->s_acked != qp->s_tail) { 19308c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 19318c2ecf20Sopenharmony_ci qp->s_psn = wqe->psn; 19328c2ecf20Sopenharmony_ci } 19338c2ecf20Sopenharmony_ci } else { 19348c2ecf20Sopenharmony_ci if (++qp->s_acked >= qp->s_size) 19358c2ecf20Sopenharmony_ci qp->s_acked = 0; 19368c2ecf20Sopenharmony_ci if (qp->state == IB_QPS_SQD && qp->s_acked == qp->s_cur) 19378c2ecf20Sopenharmony_ci qp->s_draining = 0; 19388c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 19398c2ecf20Sopenharmony_ci } 19408c2ecf20Sopenharmony_ci if (priv->s_flags & HFI1_S_TID_WAIT_INTERLCK) { 19418c2ecf20Sopenharmony_ci priv->s_flags &= ~HFI1_S_TID_WAIT_INTERLCK; 19428c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 19438c2ecf20Sopenharmony_ci } 19448c2ecf20Sopenharmony_ci return wqe; 19458c2ecf20Sopenharmony_ci} 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_cistatic void set_restart_qp(struct rvt_qp *qp, struct hfi1_ctxtdata *rcd) 19488c2ecf20Sopenharmony_ci{ 19498c2ecf20Sopenharmony_ci /* Retry this request. */ 19508c2ecf20Sopenharmony_ci if (!(qp->r_flags & RVT_R_RDMAR_SEQ)) { 19518c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RDMAR_SEQ; 19528c2ecf20Sopenharmony_ci hfi1_restart_rc(qp, qp->s_last_psn + 1, 0); 19538c2ecf20Sopenharmony_ci if (list_empty(&qp->rspwait)) { 19548c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RSP_SEND; 19558c2ecf20Sopenharmony_ci rvt_get_qp(qp); 19568c2ecf20Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 19578c2ecf20Sopenharmony_ci } 19588c2ecf20Sopenharmony_ci } 19598c2ecf20Sopenharmony_ci} 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci/** 19628c2ecf20Sopenharmony_ci * update_qp_retry_state - Update qp retry state. 19638c2ecf20Sopenharmony_ci * @qp: the QP 19648c2ecf20Sopenharmony_ci * @psn: the packet sequence number of the TID RDMA WRITE RESP. 19658c2ecf20Sopenharmony_ci * @spsn: The start psn for the given TID RDMA WRITE swqe. 19668c2ecf20Sopenharmony_ci * @lpsn: The last psn for the given TID RDMA WRITE swqe. 19678c2ecf20Sopenharmony_ci * 19688c2ecf20Sopenharmony_ci * This function is called to update the qp retry state upon 19698c2ecf20Sopenharmony_ci * receiving a TID WRITE RESP after the qp is scheduled to retry 19708c2ecf20Sopenharmony_ci * a request. 19718c2ecf20Sopenharmony_ci */ 19728c2ecf20Sopenharmony_cistatic void update_qp_retry_state(struct rvt_qp *qp, u32 psn, u32 spsn, 19738c2ecf20Sopenharmony_ci u32 lpsn) 19748c2ecf20Sopenharmony_ci{ 19758c2ecf20Sopenharmony_ci struct hfi1_qp_priv *qpriv = qp->priv; 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci qp->s_psn = psn + 1; 19788c2ecf20Sopenharmony_ci /* 19798c2ecf20Sopenharmony_ci * If this is the first TID RDMA WRITE RESP packet for the current 19808c2ecf20Sopenharmony_ci * request, change the s_state so that the retry will be processed 19818c2ecf20Sopenharmony_ci * correctly. Similarly, if this is the last TID RDMA WRITE RESP 19828c2ecf20Sopenharmony_ci * packet, change the s_state and advance the s_cur. 19838c2ecf20Sopenharmony_ci */ 19848c2ecf20Sopenharmony_ci if (cmp_psn(psn, lpsn) >= 0) { 19858c2ecf20Sopenharmony_ci qp->s_cur = qpriv->s_tid_cur + 1; 19868c2ecf20Sopenharmony_ci if (qp->s_cur >= qp->s_size) 19878c2ecf20Sopenharmony_ci qp->s_cur = 0; 19888c2ecf20Sopenharmony_ci qp->s_state = TID_OP(WRITE_REQ); 19898c2ecf20Sopenharmony_ci } else if (!cmp_psn(psn, spsn)) { 19908c2ecf20Sopenharmony_ci qp->s_cur = qpriv->s_tid_cur; 19918c2ecf20Sopenharmony_ci qp->s_state = TID_OP(WRITE_RESP); 19928c2ecf20Sopenharmony_ci } 19938c2ecf20Sopenharmony_ci} 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci/** 19968c2ecf20Sopenharmony_ci * do_rc_ack - process an incoming RC ACK 19978c2ecf20Sopenharmony_ci * @qp: the QP the ACK came in on 19988c2ecf20Sopenharmony_ci * @psn: the packet sequence number of the ACK 19998c2ecf20Sopenharmony_ci * @opcode: the opcode of the request that resulted in the ACK 20008c2ecf20Sopenharmony_ci * 20018c2ecf20Sopenharmony_ci * This is called from rc_rcv_resp() to process an incoming RC ACK 20028c2ecf20Sopenharmony_ci * for the given QP. 20038c2ecf20Sopenharmony_ci * May be called at interrupt level, with the QP s_lock held. 20048c2ecf20Sopenharmony_ci * Returns 1 if OK, 0 if current operation should be aborted (NAK). 20058c2ecf20Sopenharmony_ci */ 20068c2ecf20Sopenharmony_ciint do_rc_ack(struct rvt_qp *qp, u32 aeth, u32 psn, int opcode, 20078c2ecf20Sopenharmony_ci u64 val, struct hfi1_ctxtdata *rcd) 20088c2ecf20Sopenharmony_ci{ 20098c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp; 20108c2ecf20Sopenharmony_ci enum ib_wc_status status; 20118c2ecf20Sopenharmony_ci struct hfi1_qp_priv *qpriv = qp->priv; 20128c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 20138c2ecf20Sopenharmony_ci int ret = 0; 20148c2ecf20Sopenharmony_ci u32 ack_psn; 20158c2ecf20Sopenharmony_ci int diff; 20168c2ecf20Sopenharmony_ci struct rvt_dev_info *rdi; 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 20198c2ecf20Sopenharmony_ci /* 20208c2ecf20Sopenharmony_ci * Note that NAKs implicitly ACK outstanding SEND and RDMA write 20218c2ecf20Sopenharmony_ci * requests and implicitly NAK RDMA read and atomic requests issued 20228c2ecf20Sopenharmony_ci * before the NAK'ed request. The MSN won't include the NAK'ed 20238c2ecf20Sopenharmony_ci * request but will include an ACK'ed request(s). 20248c2ecf20Sopenharmony_ci */ 20258c2ecf20Sopenharmony_ci ack_psn = psn; 20268c2ecf20Sopenharmony_ci if (aeth >> IB_AETH_NAK_SHIFT) 20278c2ecf20Sopenharmony_ci ack_psn--; 20288c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 20298c2ecf20Sopenharmony_ci ibp = rcd_to_iport(rcd); 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci /* 20328c2ecf20Sopenharmony_ci * The MSN might be for a later WQE than the PSN indicates so 20338c2ecf20Sopenharmony_ci * only complete WQEs that the PSN finishes. 20348c2ecf20Sopenharmony_ci */ 20358c2ecf20Sopenharmony_ci while ((diff = delta_psn(ack_psn, wqe->lpsn)) >= 0) { 20368c2ecf20Sopenharmony_ci /* 20378c2ecf20Sopenharmony_ci * RDMA_READ_RESPONSE_ONLY is a special case since 20388c2ecf20Sopenharmony_ci * we want to generate completion events for everything 20398c2ecf20Sopenharmony_ci * before the RDMA read, copy the data, then generate 20408c2ecf20Sopenharmony_ci * the completion for the read. 20418c2ecf20Sopenharmony_ci */ 20428c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ && 20438c2ecf20Sopenharmony_ci opcode == OP(RDMA_READ_RESPONSE_ONLY) && 20448c2ecf20Sopenharmony_ci diff == 0) { 20458c2ecf20Sopenharmony_ci ret = 1; 20468c2ecf20Sopenharmony_ci goto bail_stop; 20478c2ecf20Sopenharmony_ci } 20488c2ecf20Sopenharmony_ci /* 20498c2ecf20Sopenharmony_ci * If this request is a RDMA read or atomic, and the ACK is 20508c2ecf20Sopenharmony_ci * for a later operation, this ACK NAKs the RDMA read or 20518c2ecf20Sopenharmony_ci * atomic. In other words, only a RDMA_READ_LAST or ONLY 20528c2ecf20Sopenharmony_ci * can ACK a RDMA read and likewise for atomic ops. Note 20538c2ecf20Sopenharmony_ci * that the NAK case can only happen if relaxed ordering is 20548c2ecf20Sopenharmony_ci * used and requests are sent after an RDMA read or atomic 20558c2ecf20Sopenharmony_ci * is sent but before the response is received. 20568c2ecf20Sopenharmony_ci */ 20578c2ecf20Sopenharmony_ci if ((wqe->wr.opcode == IB_WR_RDMA_READ && 20588c2ecf20Sopenharmony_ci (opcode != OP(RDMA_READ_RESPONSE_LAST) || diff != 0)) || 20598c2ecf20Sopenharmony_ci (wqe->wr.opcode == IB_WR_TID_RDMA_READ && 20608c2ecf20Sopenharmony_ci (opcode != TID_OP(READ_RESP) || diff != 0)) || 20618c2ecf20Sopenharmony_ci ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 20628c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) && 20638c2ecf20Sopenharmony_ci (opcode != OP(ATOMIC_ACKNOWLEDGE) || diff != 0)) || 20648c2ecf20Sopenharmony_ci (wqe->wr.opcode == IB_WR_TID_RDMA_WRITE && 20658c2ecf20Sopenharmony_ci (delta_psn(psn, qp->s_last_psn) != 1))) { 20668c2ecf20Sopenharmony_ci set_restart_qp(qp, rcd); 20678c2ecf20Sopenharmony_ci /* 20688c2ecf20Sopenharmony_ci * No need to process the ACK/NAK since we are 20698c2ecf20Sopenharmony_ci * restarting an earlier request. 20708c2ecf20Sopenharmony_ci */ 20718c2ecf20Sopenharmony_ci goto bail_stop; 20728c2ecf20Sopenharmony_ci } 20738c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 20748c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) { 20758c2ecf20Sopenharmony_ci u64 *vaddr = wqe->sg_list[0].vaddr; 20768c2ecf20Sopenharmony_ci *vaddr = val; 20778c2ecf20Sopenharmony_ci } 20788c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_OPFN) 20798c2ecf20Sopenharmony_ci opfn_conn_reply(qp, val); 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_ci if (qp->s_num_rd_atomic && 20828c2ecf20Sopenharmony_ci (wqe->wr.opcode == IB_WR_RDMA_READ || 20838c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 20848c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)) { 20858c2ecf20Sopenharmony_ci qp->s_num_rd_atomic--; 20868c2ecf20Sopenharmony_ci /* Restart sending task if fence is complete */ 20878c2ecf20Sopenharmony_ci if ((qp->s_flags & RVT_S_WAIT_FENCE) && 20888c2ecf20Sopenharmony_ci !qp->s_num_rd_atomic) { 20898c2ecf20Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_FENCE | 20908c2ecf20Sopenharmony_ci RVT_S_WAIT_ACK); 20918c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 20928c2ecf20Sopenharmony_ci } else if (qp->s_flags & RVT_S_WAIT_RDMAR) { 20938c2ecf20Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_RDMAR | 20948c2ecf20Sopenharmony_ci RVT_S_WAIT_ACK); 20958c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 20968c2ecf20Sopenharmony_ci } 20978c2ecf20Sopenharmony_ci } 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci /* 21008c2ecf20Sopenharmony_ci * TID RDMA WRITE requests will be completed by the TID RDMA 21018c2ecf20Sopenharmony_ci * ACK packet handler (see tid_rdma.c). 21028c2ecf20Sopenharmony_ci */ 21038c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_TID_RDMA_WRITE) 21048c2ecf20Sopenharmony_ci break; 21058c2ecf20Sopenharmony_ci 21068c2ecf20Sopenharmony_ci wqe = do_rc_completion(qp, wqe, ibp); 21078c2ecf20Sopenharmony_ci if (qp->s_acked == qp->s_tail) 21088c2ecf20Sopenharmony_ci break; 21098c2ecf20Sopenharmony_ci } 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci trace_hfi1_rc_ack_do(qp, aeth, psn, wqe); 21128c2ecf20Sopenharmony_ci trace_hfi1_sender_do_rc_ack(qp); 21138c2ecf20Sopenharmony_ci switch (aeth >> IB_AETH_NAK_SHIFT) { 21148c2ecf20Sopenharmony_ci case 0: /* ACK */ 21158c2ecf20Sopenharmony_ci this_cpu_inc(*ibp->rvp.rc_acks); 21168c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_TID_RDMA_READ) { 21178c2ecf20Sopenharmony_ci if (wqe_to_tid_req(wqe)->ack_pending) 21188c2ecf20Sopenharmony_ci rvt_mod_retry_timer_ext(qp, 21198c2ecf20Sopenharmony_ci qpriv->timeout_shift); 21208c2ecf20Sopenharmony_ci else 21218c2ecf20Sopenharmony_ci rvt_stop_rc_timers(qp); 21228c2ecf20Sopenharmony_ci } else if (qp->s_acked != qp->s_tail) { 21238c2ecf20Sopenharmony_ci struct rvt_swqe *__w = NULL; 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci if (qpriv->s_tid_cur != HFI1_QP_WQE_INVALID) 21268c2ecf20Sopenharmony_ci __w = rvt_get_swqe_ptr(qp, qpriv->s_tid_cur); 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci /* 21298c2ecf20Sopenharmony_ci * Stop timers if we've received all of the TID RDMA 21308c2ecf20Sopenharmony_ci * WRITE * responses. 21318c2ecf20Sopenharmony_ci */ 21328c2ecf20Sopenharmony_ci if (__w && __w->wr.opcode == IB_WR_TID_RDMA_WRITE && 21338c2ecf20Sopenharmony_ci opcode == TID_OP(WRITE_RESP)) { 21348c2ecf20Sopenharmony_ci /* 21358c2ecf20Sopenharmony_ci * Normally, the loop above would correctly 21368c2ecf20Sopenharmony_ci * process all WQEs from s_acked onward and 21378c2ecf20Sopenharmony_ci * either complete them or check for correct 21388c2ecf20Sopenharmony_ci * PSN sequencing. 21398c2ecf20Sopenharmony_ci * However, for TID RDMA, due to pipelining, 21408c2ecf20Sopenharmony_ci * the response may not be for the request at 21418c2ecf20Sopenharmony_ci * s_acked so the above look would just be 21428c2ecf20Sopenharmony_ci * skipped. This does not allow for checking 21438c2ecf20Sopenharmony_ci * the PSN sequencing. It has to be done 21448c2ecf20Sopenharmony_ci * separately. 21458c2ecf20Sopenharmony_ci */ 21468c2ecf20Sopenharmony_ci if (cmp_psn(psn, qp->s_last_psn + 1)) { 21478c2ecf20Sopenharmony_ci set_restart_qp(qp, rcd); 21488c2ecf20Sopenharmony_ci goto bail_stop; 21498c2ecf20Sopenharmony_ci } 21508c2ecf20Sopenharmony_ci /* 21518c2ecf20Sopenharmony_ci * If the psn is being resent, stop the 21528c2ecf20Sopenharmony_ci * resending. 21538c2ecf20Sopenharmony_ci */ 21548c2ecf20Sopenharmony_ci if (qp->s_cur != qp->s_tail && 21558c2ecf20Sopenharmony_ci cmp_psn(qp->s_psn, psn) <= 0) 21568c2ecf20Sopenharmony_ci update_qp_retry_state(qp, psn, 21578c2ecf20Sopenharmony_ci __w->psn, 21588c2ecf20Sopenharmony_ci __w->lpsn); 21598c2ecf20Sopenharmony_ci else if (--qpriv->pending_tid_w_resp) 21608c2ecf20Sopenharmony_ci rvt_mod_retry_timer(qp); 21618c2ecf20Sopenharmony_ci else 21628c2ecf20Sopenharmony_ci rvt_stop_rc_timers(qp); 21638c2ecf20Sopenharmony_ci } else { 21648c2ecf20Sopenharmony_ci /* 21658c2ecf20Sopenharmony_ci * We are expecting more ACKs so 21668c2ecf20Sopenharmony_ci * mod the retry timer. 21678c2ecf20Sopenharmony_ci */ 21688c2ecf20Sopenharmony_ci rvt_mod_retry_timer(qp); 21698c2ecf20Sopenharmony_ci /* 21708c2ecf20Sopenharmony_ci * We can stop re-sending the earlier packets 21718c2ecf20Sopenharmony_ci * and continue with the next packet the 21728c2ecf20Sopenharmony_ci * receiver wants. 21738c2ecf20Sopenharmony_ci */ 21748c2ecf20Sopenharmony_ci if (cmp_psn(qp->s_psn, psn) <= 0) 21758c2ecf20Sopenharmony_ci reset_psn(qp, psn + 1); 21768c2ecf20Sopenharmony_ci } 21778c2ecf20Sopenharmony_ci } else { 21788c2ecf20Sopenharmony_ci /* No more acks - kill all timers */ 21798c2ecf20Sopenharmony_ci rvt_stop_rc_timers(qp); 21808c2ecf20Sopenharmony_ci if (cmp_psn(qp->s_psn, psn) <= 0) { 21818c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 21828c2ecf20Sopenharmony_ci qp->s_psn = psn + 1; 21838c2ecf20Sopenharmony_ci } 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_ACK) { 21868c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_ACK; 21878c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 21888c2ecf20Sopenharmony_ci } 21898c2ecf20Sopenharmony_ci rvt_get_credit(qp, aeth); 21908c2ecf20Sopenharmony_ci qp->s_rnr_retry = qp->s_rnr_retry_cnt; 21918c2ecf20Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 21928c2ecf20Sopenharmony_ci /* 21938c2ecf20Sopenharmony_ci * If the current request is a TID RDMA WRITE request and the 21948c2ecf20Sopenharmony_ci * response is not a TID RDMA WRITE RESP packet, s_last_psn 21958c2ecf20Sopenharmony_ci * can't be advanced. 21968c2ecf20Sopenharmony_ci */ 21978c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_TID_RDMA_WRITE && 21988c2ecf20Sopenharmony_ci opcode != TID_OP(WRITE_RESP) && 21998c2ecf20Sopenharmony_ci cmp_psn(psn, wqe->psn) >= 0) 22008c2ecf20Sopenharmony_ci return 1; 22018c2ecf20Sopenharmony_ci update_last_psn(qp, psn); 22028c2ecf20Sopenharmony_ci return 1; 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_ci case 1: /* RNR NAK */ 22058c2ecf20Sopenharmony_ci ibp->rvp.n_rnr_naks++; 22068c2ecf20Sopenharmony_ci if (qp->s_acked == qp->s_tail) 22078c2ecf20Sopenharmony_ci goto bail_stop; 22088c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_RNR) 22098c2ecf20Sopenharmony_ci goto bail_stop; 22108c2ecf20Sopenharmony_ci rdi = ib_to_rvt(qp->ibqp.device); 22118c2ecf20Sopenharmony_ci if (!(rdi->post_parms[wqe->wr.opcode].flags & 22128c2ecf20Sopenharmony_ci RVT_OPERATION_IGN_RNR_CNT)) { 22138c2ecf20Sopenharmony_ci if (qp->s_rnr_retry == 0) { 22148c2ecf20Sopenharmony_ci status = IB_WC_RNR_RETRY_EXC_ERR; 22158c2ecf20Sopenharmony_ci goto class_b; 22168c2ecf20Sopenharmony_ci } 22178c2ecf20Sopenharmony_ci if (qp->s_rnr_retry_cnt < 7 && qp->s_rnr_retry_cnt > 0) 22188c2ecf20Sopenharmony_ci qp->s_rnr_retry--; 22198c2ecf20Sopenharmony_ci } 22208c2ecf20Sopenharmony_ci 22218c2ecf20Sopenharmony_ci /* 22228c2ecf20Sopenharmony_ci * The last valid PSN is the previous PSN. For TID RDMA WRITE 22238c2ecf20Sopenharmony_ci * request, s_last_psn should be incremented only when a TID 22248c2ecf20Sopenharmony_ci * RDMA WRITE RESP is received to avoid skipping lost TID RDMA 22258c2ecf20Sopenharmony_ci * WRITE RESP packets. 22268c2ecf20Sopenharmony_ci */ 22278c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_TID_RDMA_WRITE) { 22288c2ecf20Sopenharmony_ci reset_psn(qp, qp->s_last_psn + 1); 22298c2ecf20Sopenharmony_ci } else { 22308c2ecf20Sopenharmony_ci update_last_psn(qp, psn - 1); 22318c2ecf20Sopenharmony_ci reset_psn(qp, psn); 22328c2ecf20Sopenharmony_ci } 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci ibp->rvp.n_rc_resends += delta_psn(qp->s_psn, psn); 22358c2ecf20Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_SSN_CREDIT | RVT_S_WAIT_ACK); 22368c2ecf20Sopenharmony_ci rvt_stop_rc_timers(qp); 22378c2ecf20Sopenharmony_ci rvt_add_rnr_timer(qp, aeth); 22388c2ecf20Sopenharmony_ci return 0; 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_ci case 3: /* NAK */ 22418c2ecf20Sopenharmony_ci if (qp->s_acked == qp->s_tail) 22428c2ecf20Sopenharmony_ci goto bail_stop; 22438c2ecf20Sopenharmony_ci /* The last valid PSN is the previous PSN. */ 22448c2ecf20Sopenharmony_ci update_last_psn(qp, psn - 1); 22458c2ecf20Sopenharmony_ci switch ((aeth >> IB_AETH_CREDIT_SHIFT) & 22468c2ecf20Sopenharmony_ci IB_AETH_CREDIT_MASK) { 22478c2ecf20Sopenharmony_ci case 0: /* PSN sequence error */ 22488c2ecf20Sopenharmony_ci ibp->rvp.n_seq_naks++; 22498c2ecf20Sopenharmony_ci /* 22508c2ecf20Sopenharmony_ci * Back up to the responder's expected PSN. 22518c2ecf20Sopenharmony_ci * Note that we might get a NAK in the middle of an 22528c2ecf20Sopenharmony_ci * RDMA READ response which terminates the RDMA 22538c2ecf20Sopenharmony_ci * READ. 22548c2ecf20Sopenharmony_ci */ 22558c2ecf20Sopenharmony_ci hfi1_restart_rc(qp, psn, 0); 22568c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 22578c2ecf20Sopenharmony_ci break; 22588c2ecf20Sopenharmony_ci 22598c2ecf20Sopenharmony_ci case 1: /* Invalid Request */ 22608c2ecf20Sopenharmony_ci status = IB_WC_REM_INV_REQ_ERR; 22618c2ecf20Sopenharmony_ci ibp->rvp.n_other_naks++; 22628c2ecf20Sopenharmony_ci goto class_b; 22638c2ecf20Sopenharmony_ci 22648c2ecf20Sopenharmony_ci case 2: /* Remote Access Error */ 22658c2ecf20Sopenharmony_ci status = IB_WC_REM_ACCESS_ERR; 22668c2ecf20Sopenharmony_ci ibp->rvp.n_other_naks++; 22678c2ecf20Sopenharmony_ci goto class_b; 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci case 3: /* Remote Operation Error */ 22708c2ecf20Sopenharmony_ci status = IB_WC_REM_OP_ERR; 22718c2ecf20Sopenharmony_ci ibp->rvp.n_other_naks++; 22728c2ecf20Sopenharmony_ciclass_b: 22738c2ecf20Sopenharmony_ci if (qp->s_last == qp->s_acked) { 22748c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_TID_RDMA_READ) 22758c2ecf20Sopenharmony_ci hfi1_kern_read_tid_flow_free(qp); 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_ci hfi1_trdma_send_complete(qp, wqe, status); 22788c2ecf20Sopenharmony_ci rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 22798c2ecf20Sopenharmony_ci } 22808c2ecf20Sopenharmony_ci break; 22818c2ecf20Sopenharmony_ci 22828c2ecf20Sopenharmony_ci default: 22838c2ecf20Sopenharmony_ci /* Ignore other reserved NAK error codes */ 22848c2ecf20Sopenharmony_ci goto reserved; 22858c2ecf20Sopenharmony_ci } 22868c2ecf20Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 22878c2ecf20Sopenharmony_ci qp->s_rnr_retry = qp->s_rnr_retry_cnt; 22888c2ecf20Sopenharmony_ci goto bail_stop; 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci default: /* 2: reserved */ 22918c2ecf20Sopenharmony_cireserved: 22928c2ecf20Sopenharmony_ci /* Ignore reserved NAK codes. */ 22938c2ecf20Sopenharmony_ci goto bail_stop; 22948c2ecf20Sopenharmony_ci } 22958c2ecf20Sopenharmony_ci /* cannot be reached */ 22968c2ecf20Sopenharmony_cibail_stop: 22978c2ecf20Sopenharmony_ci rvt_stop_rc_timers(qp); 22988c2ecf20Sopenharmony_ci return ret; 22998c2ecf20Sopenharmony_ci} 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_ci/* 23028c2ecf20Sopenharmony_ci * We have seen an out of sequence RDMA read middle or last packet. 23038c2ecf20Sopenharmony_ci * This ACKs SENDs and RDMA writes up to the first RDMA read or atomic SWQE. 23048c2ecf20Sopenharmony_ci */ 23058c2ecf20Sopenharmony_cistatic void rdma_seq_err(struct rvt_qp *qp, struct hfi1_ibport *ibp, u32 psn, 23068c2ecf20Sopenharmony_ci struct hfi1_ctxtdata *rcd) 23078c2ecf20Sopenharmony_ci{ 23088c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 23098c2ecf20Sopenharmony_ci 23108c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 23118c2ecf20Sopenharmony_ci /* Remove QP from retry timer */ 23128c2ecf20Sopenharmony_ci rvt_stop_rc_timers(qp); 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 23158c2ecf20Sopenharmony_ci 23168c2ecf20Sopenharmony_ci while (cmp_psn(psn, wqe->lpsn) > 0) { 23178c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ || 23188c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_TID_RDMA_READ || 23198c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_TID_RDMA_WRITE || 23208c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 23218c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) 23228c2ecf20Sopenharmony_ci break; 23238c2ecf20Sopenharmony_ci wqe = do_rc_completion(qp, wqe, ibp); 23248c2ecf20Sopenharmony_ci } 23258c2ecf20Sopenharmony_ci 23268c2ecf20Sopenharmony_ci ibp->rvp.n_rdma_seq++; 23278c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RDMAR_SEQ; 23288c2ecf20Sopenharmony_ci hfi1_restart_rc(qp, qp->s_last_psn + 1, 0); 23298c2ecf20Sopenharmony_ci if (list_empty(&qp->rspwait)) { 23308c2ecf20Sopenharmony_ci qp->r_flags |= RVT_R_RSP_SEND; 23318c2ecf20Sopenharmony_ci rvt_get_qp(qp); 23328c2ecf20Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 23338c2ecf20Sopenharmony_ci } 23348c2ecf20Sopenharmony_ci} 23358c2ecf20Sopenharmony_ci 23368c2ecf20Sopenharmony_ci/** 23378c2ecf20Sopenharmony_ci * rc_rcv_resp - process an incoming RC response packet 23388c2ecf20Sopenharmony_ci * @packet: data packet information 23398c2ecf20Sopenharmony_ci * 23408c2ecf20Sopenharmony_ci * This is called from hfi1_rc_rcv() to process an incoming RC response 23418c2ecf20Sopenharmony_ci * packet for the given QP. 23428c2ecf20Sopenharmony_ci * Called at interrupt level. 23438c2ecf20Sopenharmony_ci */ 23448c2ecf20Sopenharmony_cistatic void rc_rcv_resp(struct hfi1_packet *packet) 23458c2ecf20Sopenharmony_ci{ 23468c2ecf20Sopenharmony_ci struct hfi1_ctxtdata *rcd = packet->rcd; 23478c2ecf20Sopenharmony_ci void *data = packet->payload; 23488c2ecf20Sopenharmony_ci u32 tlen = packet->tlen; 23498c2ecf20Sopenharmony_ci struct rvt_qp *qp = packet->qp; 23508c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp; 23518c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr = packet->ohdr; 23528c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 23538c2ecf20Sopenharmony_ci enum ib_wc_status status; 23548c2ecf20Sopenharmony_ci unsigned long flags; 23558c2ecf20Sopenharmony_ci int diff; 23568c2ecf20Sopenharmony_ci u64 val; 23578c2ecf20Sopenharmony_ci u32 aeth; 23588c2ecf20Sopenharmony_ci u32 psn = ib_bth_get_psn(packet->ohdr); 23598c2ecf20Sopenharmony_ci u32 pmtu = qp->pmtu; 23608c2ecf20Sopenharmony_ci u16 hdrsize = packet->hlen; 23618c2ecf20Sopenharmony_ci u8 opcode = packet->opcode; 23628c2ecf20Sopenharmony_ci u8 pad = packet->pad; 23638c2ecf20Sopenharmony_ci u8 extra_bytes = pad + packet->extra_byte + (SIZE_OF_CRC << 2); 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 23668c2ecf20Sopenharmony_ci trace_hfi1_ack(qp, psn); 23678c2ecf20Sopenharmony_ci 23688c2ecf20Sopenharmony_ci /* Ignore invalid responses. */ 23698c2ecf20Sopenharmony_ci if (cmp_psn(psn, READ_ONCE(qp->s_next_psn)) >= 0) 23708c2ecf20Sopenharmony_ci goto ack_done; 23718c2ecf20Sopenharmony_ci 23728c2ecf20Sopenharmony_ci /* Ignore duplicate responses. */ 23738c2ecf20Sopenharmony_ci diff = cmp_psn(psn, qp->s_last_psn); 23748c2ecf20Sopenharmony_ci if (unlikely(diff <= 0)) { 23758c2ecf20Sopenharmony_ci /* Update credits for "ghost" ACKs */ 23768c2ecf20Sopenharmony_ci if (diff == 0 && opcode == OP(ACKNOWLEDGE)) { 23778c2ecf20Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 23788c2ecf20Sopenharmony_ci if ((aeth >> IB_AETH_NAK_SHIFT) == 0) 23798c2ecf20Sopenharmony_ci rvt_get_credit(qp, aeth); 23808c2ecf20Sopenharmony_ci } 23818c2ecf20Sopenharmony_ci goto ack_done; 23828c2ecf20Sopenharmony_ci } 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci /* 23858c2ecf20Sopenharmony_ci * Skip everything other than the PSN we expect, if we are waiting 23868c2ecf20Sopenharmony_ci * for a reply to a restarted RDMA read or atomic op. 23878c2ecf20Sopenharmony_ci */ 23888c2ecf20Sopenharmony_ci if (qp->r_flags & RVT_R_RDMAR_SEQ) { 23898c2ecf20Sopenharmony_ci if (cmp_psn(psn, qp->s_last_psn + 1) != 0) 23908c2ecf20Sopenharmony_ci goto ack_done; 23918c2ecf20Sopenharmony_ci qp->r_flags &= ~RVT_R_RDMAR_SEQ; 23928c2ecf20Sopenharmony_ci } 23938c2ecf20Sopenharmony_ci 23948c2ecf20Sopenharmony_ci if (unlikely(qp->s_acked == qp->s_tail)) 23958c2ecf20Sopenharmony_ci goto ack_done; 23968c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 23978c2ecf20Sopenharmony_ci status = IB_WC_SUCCESS; 23988c2ecf20Sopenharmony_ci 23998c2ecf20Sopenharmony_ci switch (opcode) { 24008c2ecf20Sopenharmony_ci case OP(ACKNOWLEDGE): 24018c2ecf20Sopenharmony_ci case OP(ATOMIC_ACKNOWLEDGE): 24028c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_FIRST): 24038c2ecf20Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 24048c2ecf20Sopenharmony_ci if (opcode == OP(ATOMIC_ACKNOWLEDGE)) 24058c2ecf20Sopenharmony_ci val = ib_u64_get(&ohdr->u.at.atomic_ack_eth); 24068c2ecf20Sopenharmony_ci else 24078c2ecf20Sopenharmony_ci val = 0; 24088c2ecf20Sopenharmony_ci if (!do_rc_ack(qp, aeth, psn, opcode, val, rcd) || 24098c2ecf20Sopenharmony_ci opcode != OP(RDMA_READ_RESPONSE_FIRST)) 24108c2ecf20Sopenharmony_ci goto ack_done; 24118c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 24128c2ecf20Sopenharmony_ci if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) 24138c2ecf20Sopenharmony_ci goto ack_op_err; 24148c2ecf20Sopenharmony_ci /* 24158c2ecf20Sopenharmony_ci * If this is a response to a resent RDMA read, we 24168c2ecf20Sopenharmony_ci * have to be careful to copy the data to the right 24178c2ecf20Sopenharmony_ci * location. 24188c2ecf20Sopenharmony_ci */ 24198c2ecf20Sopenharmony_ci qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge, 24208c2ecf20Sopenharmony_ci wqe, psn, pmtu); 24218c2ecf20Sopenharmony_ci goto read_middle; 24228c2ecf20Sopenharmony_ci 24238c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_MIDDLE): 24248c2ecf20Sopenharmony_ci /* no AETH, no ACK */ 24258c2ecf20Sopenharmony_ci if (unlikely(cmp_psn(psn, qp->s_last_psn + 1))) 24268c2ecf20Sopenharmony_ci goto ack_seq_err; 24278c2ecf20Sopenharmony_ci if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) 24288c2ecf20Sopenharmony_ci goto ack_op_err; 24298c2ecf20Sopenharmony_ciread_middle: 24308c2ecf20Sopenharmony_ci if (unlikely(tlen != (hdrsize + pmtu + extra_bytes))) 24318c2ecf20Sopenharmony_ci goto ack_len_err; 24328c2ecf20Sopenharmony_ci if (unlikely(pmtu >= qp->s_rdma_read_len)) 24338c2ecf20Sopenharmony_ci goto ack_len_err; 24348c2ecf20Sopenharmony_ci 24358c2ecf20Sopenharmony_ci /* 24368c2ecf20Sopenharmony_ci * We got a response so update the timeout. 24378c2ecf20Sopenharmony_ci * 4.096 usec. * (1 << qp->timeout) 24388c2ecf20Sopenharmony_ci */ 24398c2ecf20Sopenharmony_ci rvt_mod_retry_timer(qp); 24408c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_ACK) { 24418c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_ACK; 24428c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 24438c2ecf20Sopenharmony_ci } 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci if (opcode == OP(RDMA_READ_RESPONSE_MIDDLE)) 24468c2ecf20Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 24478c2ecf20Sopenharmony_ci 24488c2ecf20Sopenharmony_ci /* 24498c2ecf20Sopenharmony_ci * Update the RDMA receive state but do the copy w/o 24508c2ecf20Sopenharmony_ci * holding the locks and blocking interrupts. 24518c2ecf20Sopenharmony_ci */ 24528c2ecf20Sopenharmony_ci qp->s_rdma_read_len -= pmtu; 24538c2ecf20Sopenharmony_ci update_last_psn(qp, psn); 24548c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 24558c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->s_rdma_read_sge, 24568c2ecf20Sopenharmony_ci data, pmtu, false, false); 24578c2ecf20Sopenharmony_ci goto bail; 24588c2ecf20Sopenharmony_ci 24598c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_ONLY): 24608c2ecf20Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 24618c2ecf20Sopenharmony_ci if (!do_rc_ack(qp, aeth, psn, opcode, 0, rcd)) 24628c2ecf20Sopenharmony_ci goto ack_done; 24638c2ecf20Sopenharmony_ci /* 24648c2ecf20Sopenharmony_ci * Check that the data size is >= 0 && <= pmtu. 24658c2ecf20Sopenharmony_ci * Remember to account for ICRC (4). 24668c2ecf20Sopenharmony_ci */ 24678c2ecf20Sopenharmony_ci if (unlikely(tlen < (hdrsize + extra_bytes))) 24688c2ecf20Sopenharmony_ci goto ack_len_err; 24698c2ecf20Sopenharmony_ci /* 24708c2ecf20Sopenharmony_ci * If this is a response to a resent RDMA read, we 24718c2ecf20Sopenharmony_ci * have to be careful to copy the data to the right 24728c2ecf20Sopenharmony_ci * location. 24738c2ecf20Sopenharmony_ci */ 24748c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 24758c2ecf20Sopenharmony_ci qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge, 24768c2ecf20Sopenharmony_ci wqe, psn, pmtu); 24778c2ecf20Sopenharmony_ci goto read_last; 24788c2ecf20Sopenharmony_ci 24798c2ecf20Sopenharmony_ci case OP(RDMA_READ_RESPONSE_LAST): 24808c2ecf20Sopenharmony_ci /* ACKs READ req. */ 24818c2ecf20Sopenharmony_ci if (unlikely(cmp_psn(psn, qp->s_last_psn + 1))) 24828c2ecf20Sopenharmony_ci goto ack_seq_err; 24838c2ecf20Sopenharmony_ci if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) 24848c2ecf20Sopenharmony_ci goto ack_op_err; 24858c2ecf20Sopenharmony_ci /* 24868c2ecf20Sopenharmony_ci * Check that the data size is >= 1 && <= pmtu. 24878c2ecf20Sopenharmony_ci * Remember to account for ICRC (4). 24888c2ecf20Sopenharmony_ci */ 24898c2ecf20Sopenharmony_ci if (unlikely(tlen <= (hdrsize + extra_bytes))) 24908c2ecf20Sopenharmony_ci goto ack_len_err; 24918c2ecf20Sopenharmony_ciread_last: 24928c2ecf20Sopenharmony_ci tlen -= hdrsize + extra_bytes; 24938c2ecf20Sopenharmony_ci if (unlikely(tlen != qp->s_rdma_read_len)) 24948c2ecf20Sopenharmony_ci goto ack_len_err; 24958c2ecf20Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 24968c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->s_rdma_read_sge, 24978c2ecf20Sopenharmony_ci data, tlen, false, false); 24988c2ecf20Sopenharmony_ci WARN_ON(qp->s_rdma_read_sge.num_sge); 24998c2ecf20Sopenharmony_ci (void)do_rc_ack(qp, aeth, psn, 25008c2ecf20Sopenharmony_ci OP(RDMA_READ_RESPONSE_LAST), 0, rcd); 25018c2ecf20Sopenharmony_ci goto ack_done; 25028c2ecf20Sopenharmony_ci } 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_ciack_op_err: 25058c2ecf20Sopenharmony_ci status = IB_WC_LOC_QP_OP_ERR; 25068c2ecf20Sopenharmony_ci goto ack_err; 25078c2ecf20Sopenharmony_ci 25088c2ecf20Sopenharmony_ciack_seq_err: 25098c2ecf20Sopenharmony_ci ibp = rcd_to_iport(rcd); 25108c2ecf20Sopenharmony_ci rdma_seq_err(qp, ibp, psn, rcd); 25118c2ecf20Sopenharmony_ci goto ack_done; 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_ciack_len_err: 25148c2ecf20Sopenharmony_ci status = IB_WC_LOC_LEN_ERR; 25158c2ecf20Sopenharmony_ciack_err: 25168c2ecf20Sopenharmony_ci if (qp->s_last == qp->s_acked) { 25178c2ecf20Sopenharmony_ci rvt_send_complete(qp, wqe, status); 25188c2ecf20Sopenharmony_ci rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 25198c2ecf20Sopenharmony_ci } 25208c2ecf20Sopenharmony_ciack_done: 25218c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 25228c2ecf20Sopenharmony_cibail: 25238c2ecf20Sopenharmony_ci return; 25248c2ecf20Sopenharmony_ci} 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_cistatic inline void rc_cancel_ack(struct rvt_qp *qp) 25278c2ecf20Sopenharmony_ci{ 25288c2ecf20Sopenharmony_ci qp->r_adefered = 0; 25298c2ecf20Sopenharmony_ci if (list_empty(&qp->rspwait)) 25308c2ecf20Sopenharmony_ci return; 25318c2ecf20Sopenharmony_ci list_del_init(&qp->rspwait); 25328c2ecf20Sopenharmony_ci qp->r_flags &= ~RVT_R_RSP_NAK; 25338c2ecf20Sopenharmony_ci rvt_put_qp(qp); 25348c2ecf20Sopenharmony_ci} 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci/** 25378c2ecf20Sopenharmony_ci * rc_rcv_error - process an incoming duplicate or error RC packet 25388c2ecf20Sopenharmony_ci * @ohdr: the other headers for this packet 25398c2ecf20Sopenharmony_ci * @data: the packet data 25408c2ecf20Sopenharmony_ci * @qp: the QP for this packet 25418c2ecf20Sopenharmony_ci * @opcode: the opcode for this packet 25428c2ecf20Sopenharmony_ci * @psn: the packet sequence number for this packet 25438c2ecf20Sopenharmony_ci * @diff: the difference between the PSN and the expected PSN 25448c2ecf20Sopenharmony_ci * 25458c2ecf20Sopenharmony_ci * This is called from hfi1_rc_rcv() to process an unexpected 25468c2ecf20Sopenharmony_ci * incoming RC packet for the given QP. 25478c2ecf20Sopenharmony_ci * Called at interrupt level. 25488c2ecf20Sopenharmony_ci * Return 1 if no more processing is needed; otherwise return 0 to 25498c2ecf20Sopenharmony_ci * schedule a response to be sent. 25508c2ecf20Sopenharmony_ci */ 25518c2ecf20Sopenharmony_cistatic noinline int rc_rcv_error(struct ib_other_headers *ohdr, void *data, 25528c2ecf20Sopenharmony_ci struct rvt_qp *qp, u32 opcode, u32 psn, 25538c2ecf20Sopenharmony_ci int diff, struct hfi1_ctxtdata *rcd) 25548c2ecf20Sopenharmony_ci{ 25558c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = rcd_to_iport(rcd); 25568c2ecf20Sopenharmony_ci struct rvt_ack_entry *e; 25578c2ecf20Sopenharmony_ci unsigned long flags; 25588c2ecf20Sopenharmony_ci u8 prev; 25598c2ecf20Sopenharmony_ci u8 mra; /* most recent ACK */ 25608c2ecf20Sopenharmony_ci bool old_req; 25618c2ecf20Sopenharmony_ci 25628c2ecf20Sopenharmony_ci trace_hfi1_rcv_error(qp, psn); 25638c2ecf20Sopenharmony_ci if (diff > 0) { 25648c2ecf20Sopenharmony_ci /* 25658c2ecf20Sopenharmony_ci * Packet sequence error. 25668c2ecf20Sopenharmony_ci * A NAK will ACK earlier sends and RDMA writes. 25678c2ecf20Sopenharmony_ci * Don't queue the NAK if we already sent one. 25688c2ecf20Sopenharmony_ci */ 25698c2ecf20Sopenharmony_ci if (!qp->r_nak_state) { 25708c2ecf20Sopenharmony_ci ibp->rvp.n_rc_seqnak++; 25718c2ecf20Sopenharmony_ci qp->r_nak_state = IB_NAK_PSN_ERROR; 25728c2ecf20Sopenharmony_ci /* Use the expected PSN. */ 25738c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 25748c2ecf20Sopenharmony_ci /* 25758c2ecf20Sopenharmony_ci * Wait to send the sequence NAK until all packets 25768c2ecf20Sopenharmony_ci * in the receive queue have been processed. 25778c2ecf20Sopenharmony_ci * Otherwise, we end up propagating congestion. 25788c2ecf20Sopenharmony_ci */ 25798c2ecf20Sopenharmony_ci rc_defered_ack(rcd, qp); 25808c2ecf20Sopenharmony_ci } 25818c2ecf20Sopenharmony_ci goto done; 25828c2ecf20Sopenharmony_ci } 25838c2ecf20Sopenharmony_ci 25848c2ecf20Sopenharmony_ci /* 25858c2ecf20Sopenharmony_ci * Handle a duplicate request. Don't re-execute SEND, RDMA 25868c2ecf20Sopenharmony_ci * write or atomic op. Don't NAK errors, just silently drop 25878c2ecf20Sopenharmony_ci * the duplicate request. Note that r_sge, r_len, and 25888c2ecf20Sopenharmony_ci * r_rcv_len may be in use so don't modify them. 25898c2ecf20Sopenharmony_ci * 25908c2ecf20Sopenharmony_ci * We are supposed to ACK the earliest duplicate PSN but we 25918c2ecf20Sopenharmony_ci * can coalesce an outstanding duplicate ACK. We have to 25928c2ecf20Sopenharmony_ci * send the earliest so that RDMA reads can be restarted at 25938c2ecf20Sopenharmony_ci * the requester's expected PSN. 25948c2ecf20Sopenharmony_ci * 25958c2ecf20Sopenharmony_ci * First, find where this duplicate PSN falls within the 25968c2ecf20Sopenharmony_ci * ACKs previously sent. 25978c2ecf20Sopenharmony_ci * old_req is true if there is an older response that is scheduled 25988c2ecf20Sopenharmony_ci * to be sent before sending this one. 25998c2ecf20Sopenharmony_ci */ 26008c2ecf20Sopenharmony_ci e = NULL; 26018c2ecf20Sopenharmony_ci old_req = true; 26028c2ecf20Sopenharmony_ci ibp->rvp.n_rc_dupreq++; 26038c2ecf20Sopenharmony_ci 26048c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci e = find_prev_entry(qp, psn, &prev, &mra, &old_req); 26078c2ecf20Sopenharmony_ci 26088c2ecf20Sopenharmony_ci switch (opcode) { 26098c2ecf20Sopenharmony_ci case OP(RDMA_READ_REQUEST): { 26108c2ecf20Sopenharmony_ci struct ib_reth *reth; 26118c2ecf20Sopenharmony_ci u32 offset; 26128c2ecf20Sopenharmony_ci u32 len; 26138c2ecf20Sopenharmony_ci 26148c2ecf20Sopenharmony_ci /* 26158c2ecf20Sopenharmony_ci * If we didn't find the RDMA read request in the ack queue, 26168c2ecf20Sopenharmony_ci * we can ignore this request. 26178c2ecf20Sopenharmony_ci */ 26188c2ecf20Sopenharmony_ci if (!e || e->opcode != OP(RDMA_READ_REQUEST)) 26198c2ecf20Sopenharmony_ci goto unlock_done; 26208c2ecf20Sopenharmony_ci /* RETH comes after BTH */ 26218c2ecf20Sopenharmony_ci reth = &ohdr->u.rc.reth; 26228c2ecf20Sopenharmony_ci /* 26238c2ecf20Sopenharmony_ci * Address range must be a subset of the original 26248c2ecf20Sopenharmony_ci * request and start on pmtu boundaries. 26258c2ecf20Sopenharmony_ci * We reuse the old ack_queue slot since the requester 26268c2ecf20Sopenharmony_ci * should not back up and request an earlier PSN for the 26278c2ecf20Sopenharmony_ci * same request. 26288c2ecf20Sopenharmony_ci */ 26298c2ecf20Sopenharmony_ci offset = delta_psn(psn, e->psn) * qp->pmtu; 26308c2ecf20Sopenharmony_ci len = be32_to_cpu(reth->length); 26318c2ecf20Sopenharmony_ci if (unlikely(offset + len != e->rdma_sge.sge_length)) 26328c2ecf20Sopenharmony_ci goto unlock_done; 26338c2ecf20Sopenharmony_ci release_rdma_sge_mr(e); 26348c2ecf20Sopenharmony_ci if (len != 0) { 26358c2ecf20Sopenharmony_ci u32 rkey = be32_to_cpu(reth->rkey); 26368c2ecf20Sopenharmony_ci u64 vaddr = get_ib_reth_vaddr(reth); 26378c2ecf20Sopenharmony_ci int ok; 26388c2ecf20Sopenharmony_ci 26398c2ecf20Sopenharmony_ci ok = rvt_rkey_ok(qp, &e->rdma_sge, len, vaddr, rkey, 26408c2ecf20Sopenharmony_ci IB_ACCESS_REMOTE_READ); 26418c2ecf20Sopenharmony_ci if (unlikely(!ok)) 26428c2ecf20Sopenharmony_ci goto unlock_done; 26438c2ecf20Sopenharmony_ci } else { 26448c2ecf20Sopenharmony_ci e->rdma_sge.vaddr = NULL; 26458c2ecf20Sopenharmony_ci e->rdma_sge.length = 0; 26468c2ecf20Sopenharmony_ci e->rdma_sge.sge_length = 0; 26478c2ecf20Sopenharmony_ci } 26488c2ecf20Sopenharmony_ci e->psn = psn; 26498c2ecf20Sopenharmony_ci if (old_req) 26508c2ecf20Sopenharmony_ci goto unlock_done; 26518c2ecf20Sopenharmony_ci if (qp->s_acked_ack_queue == qp->s_tail_ack_queue) 26528c2ecf20Sopenharmony_ci qp->s_acked_ack_queue = prev; 26538c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = prev; 26548c2ecf20Sopenharmony_ci break; 26558c2ecf20Sopenharmony_ci } 26568c2ecf20Sopenharmony_ci 26578c2ecf20Sopenharmony_ci case OP(COMPARE_SWAP): 26588c2ecf20Sopenharmony_ci case OP(FETCH_ADD): { 26598c2ecf20Sopenharmony_ci /* 26608c2ecf20Sopenharmony_ci * If we didn't find the atomic request in the ack queue 26618c2ecf20Sopenharmony_ci * or the send engine is already backed up to send an 26628c2ecf20Sopenharmony_ci * earlier entry, we can ignore this request. 26638c2ecf20Sopenharmony_ci */ 26648c2ecf20Sopenharmony_ci if (!e || e->opcode != (u8)opcode || old_req) 26658c2ecf20Sopenharmony_ci goto unlock_done; 26668c2ecf20Sopenharmony_ci if (qp->s_tail_ack_queue == qp->s_acked_ack_queue) 26678c2ecf20Sopenharmony_ci qp->s_acked_ack_queue = prev; 26688c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = prev; 26698c2ecf20Sopenharmony_ci break; 26708c2ecf20Sopenharmony_ci } 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ci default: 26738c2ecf20Sopenharmony_ci /* 26748c2ecf20Sopenharmony_ci * Ignore this operation if it doesn't request an ACK 26758c2ecf20Sopenharmony_ci * or an earlier RDMA read or atomic is going to be resent. 26768c2ecf20Sopenharmony_ci */ 26778c2ecf20Sopenharmony_ci if (!(psn & IB_BTH_REQ_ACK) || old_req) 26788c2ecf20Sopenharmony_ci goto unlock_done; 26798c2ecf20Sopenharmony_ci /* 26808c2ecf20Sopenharmony_ci * Resend the most recent ACK if this request is 26818c2ecf20Sopenharmony_ci * after all the previous RDMA reads and atomics. 26828c2ecf20Sopenharmony_ci */ 26838c2ecf20Sopenharmony_ci if (mra == qp->r_head_ack_queue) { 26848c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 26858c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 26868c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn - 1; 26878c2ecf20Sopenharmony_ci goto send_ack; 26888c2ecf20Sopenharmony_ci } 26898c2ecf20Sopenharmony_ci 26908c2ecf20Sopenharmony_ci /* 26918c2ecf20Sopenharmony_ci * Resend the RDMA read or atomic op which 26928c2ecf20Sopenharmony_ci * ACKs this duplicate request. 26938c2ecf20Sopenharmony_ci */ 26948c2ecf20Sopenharmony_ci if (qp->s_tail_ack_queue == qp->s_acked_ack_queue) 26958c2ecf20Sopenharmony_ci qp->s_acked_ack_queue = mra; 26968c2ecf20Sopenharmony_ci qp->s_tail_ack_queue = mra; 26978c2ecf20Sopenharmony_ci break; 26988c2ecf20Sopenharmony_ci } 26998c2ecf20Sopenharmony_ci qp->s_ack_state = OP(ACKNOWLEDGE); 27008c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_RESP_PENDING; 27018c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 27028c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 27038c2ecf20Sopenharmony_ci 27048c2ecf20Sopenharmony_ciunlock_done: 27058c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 27068c2ecf20Sopenharmony_cidone: 27078c2ecf20Sopenharmony_ci return 1; 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_cisend_ack: 27108c2ecf20Sopenharmony_ci return 0; 27118c2ecf20Sopenharmony_ci} 27128c2ecf20Sopenharmony_ci 27138c2ecf20Sopenharmony_cistatic void log_cca_event(struct hfi1_pportdata *ppd, u8 sl, u32 rlid, 27148c2ecf20Sopenharmony_ci u32 lqpn, u32 rqpn, u8 svc_type) 27158c2ecf20Sopenharmony_ci{ 27168c2ecf20Sopenharmony_ci struct opa_hfi1_cong_log_event_internal *cc_event; 27178c2ecf20Sopenharmony_ci unsigned long flags; 27188c2ecf20Sopenharmony_ci 27198c2ecf20Sopenharmony_ci if (sl >= OPA_MAX_SLS) 27208c2ecf20Sopenharmony_ci return; 27218c2ecf20Sopenharmony_ci 27228c2ecf20Sopenharmony_ci spin_lock_irqsave(&ppd->cc_log_lock, flags); 27238c2ecf20Sopenharmony_ci 27248c2ecf20Sopenharmony_ci ppd->threshold_cong_event_map[sl / 8] |= 1 << (sl % 8); 27258c2ecf20Sopenharmony_ci ppd->threshold_event_counter++; 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_ci cc_event = &ppd->cc_events[ppd->cc_log_idx++]; 27288c2ecf20Sopenharmony_ci if (ppd->cc_log_idx == OPA_CONG_LOG_ELEMS) 27298c2ecf20Sopenharmony_ci ppd->cc_log_idx = 0; 27308c2ecf20Sopenharmony_ci cc_event->lqpn = lqpn & RVT_QPN_MASK; 27318c2ecf20Sopenharmony_ci cc_event->rqpn = rqpn & RVT_QPN_MASK; 27328c2ecf20Sopenharmony_ci cc_event->sl = sl; 27338c2ecf20Sopenharmony_ci cc_event->svc_type = svc_type; 27348c2ecf20Sopenharmony_ci cc_event->rlid = rlid; 27358c2ecf20Sopenharmony_ci /* keep timestamp in units of 1.024 usec */ 27368c2ecf20Sopenharmony_ci cc_event->timestamp = ktime_get_ns() / 1024; 27378c2ecf20Sopenharmony_ci 27388c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ppd->cc_log_lock, flags); 27398c2ecf20Sopenharmony_ci} 27408c2ecf20Sopenharmony_ci 27418c2ecf20Sopenharmony_civoid process_becn(struct hfi1_pportdata *ppd, u8 sl, u32 rlid, u32 lqpn, 27428c2ecf20Sopenharmony_ci u32 rqpn, u8 svc_type) 27438c2ecf20Sopenharmony_ci{ 27448c2ecf20Sopenharmony_ci struct cca_timer *cca_timer; 27458c2ecf20Sopenharmony_ci u16 ccti, ccti_incr, ccti_timer, ccti_limit; 27468c2ecf20Sopenharmony_ci u8 trigger_threshold; 27478c2ecf20Sopenharmony_ci struct cc_state *cc_state; 27488c2ecf20Sopenharmony_ci unsigned long flags; 27498c2ecf20Sopenharmony_ci 27508c2ecf20Sopenharmony_ci if (sl >= OPA_MAX_SLS) 27518c2ecf20Sopenharmony_ci return; 27528c2ecf20Sopenharmony_ci 27538c2ecf20Sopenharmony_ci cc_state = get_cc_state(ppd); 27548c2ecf20Sopenharmony_ci 27558c2ecf20Sopenharmony_ci if (!cc_state) 27568c2ecf20Sopenharmony_ci return; 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci /* 27598c2ecf20Sopenharmony_ci * 1) increase CCTI (for this SL) 27608c2ecf20Sopenharmony_ci * 2) select IPG (i.e., call set_link_ipg()) 27618c2ecf20Sopenharmony_ci * 3) start timer 27628c2ecf20Sopenharmony_ci */ 27638c2ecf20Sopenharmony_ci ccti_limit = cc_state->cct.ccti_limit; 27648c2ecf20Sopenharmony_ci ccti_incr = cc_state->cong_setting.entries[sl].ccti_increase; 27658c2ecf20Sopenharmony_ci ccti_timer = cc_state->cong_setting.entries[sl].ccti_timer; 27668c2ecf20Sopenharmony_ci trigger_threshold = 27678c2ecf20Sopenharmony_ci cc_state->cong_setting.entries[sl].trigger_threshold; 27688c2ecf20Sopenharmony_ci 27698c2ecf20Sopenharmony_ci spin_lock_irqsave(&ppd->cca_timer_lock, flags); 27708c2ecf20Sopenharmony_ci 27718c2ecf20Sopenharmony_ci cca_timer = &ppd->cca_timer[sl]; 27728c2ecf20Sopenharmony_ci if (cca_timer->ccti < ccti_limit) { 27738c2ecf20Sopenharmony_ci if (cca_timer->ccti + ccti_incr <= ccti_limit) 27748c2ecf20Sopenharmony_ci cca_timer->ccti += ccti_incr; 27758c2ecf20Sopenharmony_ci else 27768c2ecf20Sopenharmony_ci cca_timer->ccti = ccti_limit; 27778c2ecf20Sopenharmony_ci set_link_ipg(ppd); 27788c2ecf20Sopenharmony_ci } 27798c2ecf20Sopenharmony_ci 27808c2ecf20Sopenharmony_ci ccti = cca_timer->ccti; 27818c2ecf20Sopenharmony_ci 27828c2ecf20Sopenharmony_ci if (!hrtimer_active(&cca_timer->hrtimer)) { 27838c2ecf20Sopenharmony_ci /* ccti_timer is in units of 1.024 usec */ 27848c2ecf20Sopenharmony_ci unsigned long nsec = 1024 * ccti_timer; 27858c2ecf20Sopenharmony_ci 27868c2ecf20Sopenharmony_ci hrtimer_start(&cca_timer->hrtimer, ns_to_ktime(nsec), 27878c2ecf20Sopenharmony_ci HRTIMER_MODE_REL_PINNED); 27888c2ecf20Sopenharmony_ci } 27898c2ecf20Sopenharmony_ci 27908c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ppd->cca_timer_lock, flags); 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci if ((trigger_threshold != 0) && (ccti >= trigger_threshold)) 27938c2ecf20Sopenharmony_ci log_cca_event(ppd, sl, rlid, lqpn, rqpn, svc_type); 27948c2ecf20Sopenharmony_ci} 27958c2ecf20Sopenharmony_ci 27968c2ecf20Sopenharmony_ci/** 27978c2ecf20Sopenharmony_ci * hfi1_rc_rcv - process an incoming RC packet 27988c2ecf20Sopenharmony_ci * @packet: data packet information 27998c2ecf20Sopenharmony_ci * 28008c2ecf20Sopenharmony_ci * This is called from qp_rcv() to process an incoming RC packet 28018c2ecf20Sopenharmony_ci * for the given QP. 28028c2ecf20Sopenharmony_ci * May be called at interrupt level. 28038c2ecf20Sopenharmony_ci */ 28048c2ecf20Sopenharmony_civoid hfi1_rc_rcv(struct hfi1_packet *packet) 28058c2ecf20Sopenharmony_ci{ 28068c2ecf20Sopenharmony_ci struct hfi1_ctxtdata *rcd = packet->rcd; 28078c2ecf20Sopenharmony_ci void *data = packet->payload; 28088c2ecf20Sopenharmony_ci u32 tlen = packet->tlen; 28098c2ecf20Sopenharmony_ci struct rvt_qp *qp = packet->qp; 28108c2ecf20Sopenharmony_ci struct hfi1_qp_priv *qpriv = qp->priv; 28118c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = rcd_to_iport(rcd); 28128c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr = packet->ohdr; 28138c2ecf20Sopenharmony_ci u32 opcode = packet->opcode; 28148c2ecf20Sopenharmony_ci u32 hdrsize = packet->hlen; 28158c2ecf20Sopenharmony_ci u32 psn = ib_bth_get_psn(packet->ohdr); 28168c2ecf20Sopenharmony_ci u32 pad = packet->pad; 28178c2ecf20Sopenharmony_ci struct ib_wc wc; 28188c2ecf20Sopenharmony_ci u32 pmtu = qp->pmtu; 28198c2ecf20Sopenharmony_ci int diff; 28208c2ecf20Sopenharmony_ci struct ib_reth *reth; 28218c2ecf20Sopenharmony_ci unsigned long flags; 28228c2ecf20Sopenharmony_ci int ret; 28238c2ecf20Sopenharmony_ci bool copy_last = false, fecn; 28248c2ecf20Sopenharmony_ci u32 rkey; 28258c2ecf20Sopenharmony_ci u8 extra_bytes = pad + packet->extra_byte + (SIZE_OF_CRC << 2); 28268c2ecf20Sopenharmony_ci 28278c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->r_lock); 28288c2ecf20Sopenharmony_ci 28298c2ecf20Sopenharmony_ci if (hfi1_ruc_check_hdr(ibp, packet)) 28308c2ecf20Sopenharmony_ci return; 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ci fecn = process_ecn(qp, packet); 28338c2ecf20Sopenharmony_ci opfn_trigger_conn_request(qp, be32_to_cpu(ohdr->bth[1])); 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_ci /* 28368c2ecf20Sopenharmony_ci * Process responses (ACKs) before anything else. Note that the 28378c2ecf20Sopenharmony_ci * packet sequence number will be for something in the send work 28388c2ecf20Sopenharmony_ci * queue rather than the expected receive packet sequence number. 28398c2ecf20Sopenharmony_ci * In other words, this QP is the requester. 28408c2ecf20Sopenharmony_ci */ 28418c2ecf20Sopenharmony_ci if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) && 28428c2ecf20Sopenharmony_ci opcode <= OP(ATOMIC_ACKNOWLEDGE)) { 28438c2ecf20Sopenharmony_ci rc_rcv_resp(packet); 28448c2ecf20Sopenharmony_ci return; 28458c2ecf20Sopenharmony_ci } 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_ci /* Compute 24 bits worth of difference. */ 28488c2ecf20Sopenharmony_ci diff = delta_psn(psn, qp->r_psn); 28498c2ecf20Sopenharmony_ci if (unlikely(diff)) { 28508c2ecf20Sopenharmony_ci if (rc_rcv_error(ohdr, data, qp, opcode, psn, diff, rcd)) 28518c2ecf20Sopenharmony_ci return; 28528c2ecf20Sopenharmony_ci goto send_ack; 28538c2ecf20Sopenharmony_ci } 28548c2ecf20Sopenharmony_ci 28558c2ecf20Sopenharmony_ci /* Check for opcode sequence errors. */ 28568c2ecf20Sopenharmony_ci switch (qp->r_state) { 28578c2ecf20Sopenharmony_ci case OP(SEND_FIRST): 28588c2ecf20Sopenharmony_ci case OP(SEND_MIDDLE): 28598c2ecf20Sopenharmony_ci if (opcode == OP(SEND_MIDDLE) || 28608c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST) || 28618c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST_WITH_IMMEDIATE) || 28628c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST_WITH_INVALIDATE)) 28638c2ecf20Sopenharmony_ci break; 28648c2ecf20Sopenharmony_ci goto nack_inv; 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 28678c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 28688c2ecf20Sopenharmony_ci if (opcode == OP(RDMA_WRITE_MIDDLE) || 28698c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST) || 28708c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) 28718c2ecf20Sopenharmony_ci break; 28728c2ecf20Sopenharmony_ci goto nack_inv; 28738c2ecf20Sopenharmony_ci 28748c2ecf20Sopenharmony_ci default: 28758c2ecf20Sopenharmony_ci if (opcode == OP(SEND_MIDDLE) || 28768c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST) || 28778c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST_WITH_IMMEDIATE) || 28788c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST_WITH_INVALIDATE) || 28798c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_MIDDLE) || 28808c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST) || 28818c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) 28828c2ecf20Sopenharmony_ci goto nack_inv; 28838c2ecf20Sopenharmony_ci /* 28848c2ecf20Sopenharmony_ci * Note that it is up to the requester to not send a new 28858c2ecf20Sopenharmony_ci * RDMA read or atomic operation before receiving an ACK 28868c2ecf20Sopenharmony_ci * for the previous operation. 28878c2ecf20Sopenharmony_ci */ 28888c2ecf20Sopenharmony_ci break; 28898c2ecf20Sopenharmony_ci } 28908c2ecf20Sopenharmony_ci 28918c2ecf20Sopenharmony_ci if (qp->state == IB_QPS_RTR && !(qp->r_flags & RVT_R_COMM_EST)) 28928c2ecf20Sopenharmony_ci rvt_comm_est(qp); 28938c2ecf20Sopenharmony_ci 28948c2ecf20Sopenharmony_ci /* OK, process the packet. */ 28958c2ecf20Sopenharmony_ci switch (opcode) { 28968c2ecf20Sopenharmony_ci case OP(SEND_FIRST): 28978c2ecf20Sopenharmony_ci ret = rvt_get_rwqe(qp, false); 28988c2ecf20Sopenharmony_ci if (ret < 0) 28998c2ecf20Sopenharmony_ci goto nack_op_err; 29008c2ecf20Sopenharmony_ci if (!ret) 29018c2ecf20Sopenharmony_ci goto rnr_nak; 29028c2ecf20Sopenharmony_ci qp->r_rcv_len = 0; 29038c2ecf20Sopenharmony_ci fallthrough; 29048c2ecf20Sopenharmony_ci case OP(SEND_MIDDLE): 29058c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 29068c2ecf20Sopenharmony_cisend_middle: 29078c2ecf20Sopenharmony_ci /* Check for invalid length PMTU or posted rwqe len. */ 29088c2ecf20Sopenharmony_ci /* 29098c2ecf20Sopenharmony_ci * There will be no padding for 9B packet but 16B packets 29108c2ecf20Sopenharmony_ci * will come in with some padding since we always add 29118c2ecf20Sopenharmony_ci * CRC and LT bytes which will need to be flit aligned 29128c2ecf20Sopenharmony_ci */ 29138c2ecf20Sopenharmony_ci if (unlikely(tlen != (hdrsize + pmtu + extra_bytes))) 29148c2ecf20Sopenharmony_ci goto nack_inv; 29158c2ecf20Sopenharmony_ci qp->r_rcv_len += pmtu; 29168c2ecf20Sopenharmony_ci if (unlikely(qp->r_rcv_len > qp->r_len)) 29178c2ecf20Sopenharmony_ci goto nack_inv; 29188c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, pmtu, true, false); 29198c2ecf20Sopenharmony_ci break; 29208c2ecf20Sopenharmony_ci 29218c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE): 29228c2ecf20Sopenharmony_ci /* consume RWQE */ 29238c2ecf20Sopenharmony_ci ret = rvt_get_rwqe(qp, true); 29248c2ecf20Sopenharmony_ci if (ret < 0) 29258c2ecf20Sopenharmony_ci goto nack_op_err; 29268c2ecf20Sopenharmony_ci if (!ret) 29278c2ecf20Sopenharmony_ci goto rnr_nak; 29288c2ecf20Sopenharmony_ci goto send_last_imm; 29298c2ecf20Sopenharmony_ci 29308c2ecf20Sopenharmony_ci case OP(SEND_ONLY): 29318c2ecf20Sopenharmony_ci case OP(SEND_ONLY_WITH_IMMEDIATE): 29328c2ecf20Sopenharmony_ci case OP(SEND_ONLY_WITH_INVALIDATE): 29338c2ecf20Sopenharmony_ci ret = rvt_get_rwqe(qp, false); 29348c2ecf20Sopenharmony_ci if (ret < 0) 29358c2ecf20Sopenharmony_ci goto nack_op_err; 29368c2ecf20Sopenharmony_ci if (!ret) 29378c2ecf20Sopenharmony_ci goto rnr_nak; 29388c2ecf20Sopenharmony_ci qp->r_rcv_len = 0; 29398c2ecf20Sopenharmony_ci if (opcode == OP(SEND_ONLY)) 29408c2ecf20Sopenharmony_ci goto no_immediate_data; 29418c2ecf20Sopenharmony_ci if (opcode == OP(SEND_ONLY_WITH_INVALIDATE)) 29428c2ecf20Sopenharmony_ci goto send_last_inv; 29438c2ecf20Sopenharmony_ci fallthrough; /* for SEND_ONLY_WITH_IMMEDIATE */ 29448c2ecf20Sopenharmony_ci case OP(SEND_LAST_WITH_IMMEDIATE): 29458c2ecf20Sopenharmony_cisend_last_imm: 29468c2ecf20Sopenharmony_ci wc.ex.imm_data = ohdr->u.imm_data; 29478c2ecf20Sopenharmony_ci wc.wc_flags = IB_WC_WITH_IMM; 29488c2ecf20Sopenharmony_ci goto send_last; 29498c2ecf20Sopenharmony_ci case OP(SEND_LAST_WITH_INVALIDATE): 29508c2ecf20Sopenharmony_cisend_last_inv: 29518c2ecf20Sopenharmony_ci rkey = be32_to_cpu(ohdr->u.ieth); 29528c2ecf20Sopenharmony_ci if (rvt_invalidate_rkey(qp, rkey)) 29538c2ecf20Sopenharmony_ci goto no_immediate_data; 29548c2ecf20Sopenharmony_ci wc.ex.invalidate_rkey = rkey; 29558c2ecf20Sopenharmony_ci wc.wc_flags = IB_WC_WITH_INVALIDATE; 29568c2ecf20Sopenharmony_ci goto send_last; 29578c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_LAST): 29588c2ecf20Sopenharmony_ci copy_last = rvt_is_user_qp(qp); 29598c2ecf20Sopenharmony_ci fallthrough; 29608c2ecf20Sopenharmony_ci case OP(SEND_LAST): 29618c2ecf20Sopenharmony_cino_immediate_data: 29628c2ecf20Sopenharmony_ci wc.wc_flags = 0; 29638c2ecf20Sopenharmony_ci wc.ex.imm_data = 0; 29648c2ecf20Sopenharmony_cisend_last: 29658c2ecf20Sopenharmony_ci /* Check for invalid length. */ 29668c2ecf20Sopenharmony_ci /* LAST len should be >= 1 */ 29678c2ecf20Sopenharmony_ci if (unlikely(tlen < (hdrsize + extra_bytes))) 29688c2ecf20Sopenharmony_ci goto nack_inv; 29698c2ecf20Sopenharmony_ci /* Don't count the CRC(and padding and LT byte for 16B). */ 29708c2ecf20Sopenharmony_ci tlen -= (hdrsize + extra_bytes); 29718c2ecf20Sopenharmony_ci wc.byte_len = tlen + qp->r_rcv_len; 29728c2ecf20Sopenharmony_ci if (unlikely(wc.byte_len > qp->r_len)) 29738c2ecf20Sopenharmony_ci goto nack_inv; 29748c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, tlen, true, copy_last); 29758c2ecf20Sopenharmony_ci rvt_put_ss(&qp->r_sge); 29768c2ecf20Sopenharmony_ci qp->r_msn++; 29778c2ecf20Sopenharmony_ci if (!__test_and_clear_bit(RVT_R_WRID_VALID, &qp->r_aflags)) 29788c2ecf20Sopenharmony_ci break; 29798c2ecf20Sopenharmony_ci wc.wr_id = qp->r_wr_id; 29808c2ecf20Sopenharmony_ci wc.status = IB_WC_SUCCESS; 29818c2ecf20Sopenharmony_ci if (opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE) || 29828c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) 29838c2ecf20Sopenharmony_ci wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; 29848c2ecf20Sopenharmony_ci else 29858c2ecf20Sopenharmony_ci wc.opcode = IB_WC_RECV; 29868c2ecf20Sopenharmony_ci wc.qp = &qp->ibqp; 29878c2ecf20Sopenharmony_ci wc.src_qp = qp->remote_qpn; 29888c2ecf20Sopenharmony_ci wc.slid = rdma_ah_get_dlid(&qp->remote_ah_attr) & U16_MAX; 29898c2ecf20Sopenharmony_ci /* 29908c2ecf20Sopenharmony_ci * It seems that IB mandates the presence of an SL in a 29918c2ecf20Sopenharmony_ci * work completion only for the UD transport (see section 29928c2ecf20Sopenharmony_ci * 11.4.2 of IBTA Vol. 1). 29938c2ecf20Sopenharmony_ci * 29948c2ecf20Sopenharmony_ci * However, the way the SL is chosen below is consistent 29958c2ecf20Sopenharmony_ci * with the way that IB/qib works and is trying avoid 29968c2ecf20Sopenharmony_ci * introducing incompatibilities. 29978c2ecf20Sopenharmony_ci * 29988c2ecf20Sopenharmony_ci * See also OPA Vol. 1, section 9.7.6, and table 9-17. 29998c2ecf20Sopenharmony_ci */ 30008c2ecf20Sopenharmony_ci wc.sl = rdma_ah_get_sl(&qp->remote_ah_attr); 30018c2ecf20Sopenharmony_ci /* zero fields that are N/A */ 30028c2ecf20Sopenharmony_ci wc.vendor_err = 0; 30038c2ecf20Sopenharmony_ci wc.pkey_index = 0; 30048c2ecf20Sopenharmony_ci wc.dlid_path_bits = 0; 30058c2ecf20Sopenharmony_ci wc.port_num = 0; 30068c2ecf20Sopenharmony_ci /* Signal completion event if the solicited bit is set. */ 30078c2ecf20Sopenharmony_ci rvt_recv_cq(qp, &wc, ib_bth_is_solicited(ohdr)); 30088c2ecf20Sopenharmony_ci break; 30098c2ecf20Sopenharmony_ci 30108c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_ONLY): 30118c2ecf20Sopenharmony_ci copy_last = rvt_is_user_qp(qp); 30128c2ecf20Sopenharmony_ci fallthrough; 30138c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 30148c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): 30158c2ecf20Sopenharmony_ci if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE))) 30168c2ecf20Sopenharmony_ci goto nack_inv; 30178c2ecf20Sopenharmony_ci /* consume RWQE */ 30188c2ecf20Sopenharmony_ci reth = &ohdr->u.rc.reth; 30198c2ecf20Sopenharmony_ci qp->r_len = be32_to_cpu(reth->length); 30208c2ecf20Sopenharmony_ci qp->r_rcv_len = 0; 30218c2ecf20Sopenharmony_ci qp->r_sge.sg_list = NULL; 30228c2ecf20Sopenharmony_ci if (qp->r_len != 0) { 30238c2ecf20Sopenharmony_ci u32 rkey = be32_to_cpu(reth->rkey); 30248c2ecf20Sopenharmony_ci u64 vaddr = get_ib_reth_vaddr(reth); 30258c2ecf20Sopenharmony_ci int ok; 30268c2ecf20Sopenharmony_ci 30278c2ecf20Sopenharmony_ci /* Check rkey & NAK */ 30288c2ecf20Sopenharmony_ci ok = rvt_rkey_ok(qp, &qp->r_sge.sge, qp->r_len, vaddr, 30298c2ecf20Sopenharmony_ci rkey, IB_ACCESS_REMOTE_WRITE); 30308c2ecf20Sopenharmony_ci if (unlikely(!ok)) 30318c2ecf20Sopenharmony_ci goto nack_acc; 30328c2ecf20Sopenharmony_ci qp->r_sge.num_sge = 1; 30338c2ecf20Sopenharmony_ci } else { 30348c2ecf20Sopenharmony_ci qp->r_sge.num_sge = 0; 30358c2ecf20Sopenharmony_ci qp->r_sge.sge.mr = NULL; 30368c2ecf20Sopenharmony_ci qp->r_sge.sge.vaddr = NULL; 30378c2ecf20Sopenharmony_ci qp->r_sge.sge.length = 0; 30388c2ecf20Sopenharmony_ci qp->r_sge.sge.sge_length = 0; 30398c2ecf20Sopenharmony_ci } 30408c2ecf20Sopenharmony_ci if (opcode == OP(RDMA_WRITE_FIRST)) 30418c2ecf20Sopenharmony_ci goto send_middle; 30428c2ecf20Sopenharmony_ci else if (opcode == OP(RDMA_WRITE_ONLY)) 30438c2ecf20Sopenharmony_ci goto no_immediate_data; 30448c2ecf20Sopenharmony_ci ret = rvt_get_rwqe(qp, true); 30458c2ecf20Sopenharmony_ci if (ret < 0) 30468c2ecf20Sopenharmony_ci goto nack_op_err; 30478c2ecf20Sopenharmony_ci if (!ret) { 30488c2ecf20Sopenharmony_ci /* peer will send again */ 30498c2ecf20Sopenharmony_ci rvt_put_ss(&qp->r_sge); 30508c2ecf20Sopenharmony_ci goto rnr_nak; 30518c2ecf20Sopenharmony_ci } 30528c2ecf20Sopenharmony_ci wc.ex.imm_data = ohdr->u.rc.imm_data; 30538c2ecf20Sopenharmony_ci wc.wc_flags = IB_WC_WITH_IMM; 30548c2ecf20Sopenharmony_ci goto send_last; 30558c2ecf20Sopenharmony_ci 30568c2ecf20Sopenharmony_ci case OP(RDMA_READ_REQUEST): { 30578c2ecf20Sopenharmony_ci struct rvt_ack_entry *e; 30588c2ecf20Sopenharmony_ci u32 len; 30598c2ecf20Sopenharmony_ci u8 next; 30608c2ecf20Sopenharmony_ci 30618c2ecf20Sopenharmony_ci if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ))) 30628c2ecf20Sopenharmony_ci goto nack_inv; 30638c2ecf20Sopenharmony_ci next = qp->r_head_ack_queue + 1; 30648c2ecf20Sopenharmony_ci /* s_ack_queue is size rvt_size_atomic()+1 so use > not >= */ 30658c2ecf20Sopenharmony_ci if (next > rvt_size_atomic(ib_to_rvt(qp->ibqp.device))) 30668c2ecf20Sopenharmony_ci next = 0; 30678c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 30688c2ecf20Sopenharmony_ci if (unlikely(next == qp->s_acked_ack_queue)) { 30698c2ecf20Sopenharmony_ci if (!qp->s_ack_queue[next].sent) 30708c2ecf20Sopenharmony_ci goto nack_inv_unlck; 30718c2ecf20Sopenharmony_ci update_ack_queue(qp, next); 30728c2ecf20Sopenharmony_ci } 30738c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->r_head_ack_queue]; 30748c2ecf20Sopenharmony_ci release_rdma_sge_mr(e); 30758c2ecf20Sopenharmony_ci reth = &ohdr->u.rc.reth; 30768c2ecf20Sopenharmony_ci len = be32_to_cpu(reth->length); 30778c2ecf20Sopenharmony_ci if (len) { 30788c2ecf20Sopenharmony_ci u32 rkey = be32_to_cpu(reth->rkey); 30798c2ecf20Sopenharmony_ci u64 vaddr = get_ib_reth_vaddr(reth); 30808c2ecf20Sopenharmony_ci int ok; 30818c2ecf20Sopenharmony_ci 30828c2ecf20Sopenharmony_ci /* Check rkey & NAK */ 30838c2ecf20Sopenharmony_ci ok = rvt_rkey_ok(qp, &e->rdma_sge, len, vaddr, 30848c2ecf20Sopenharmony_ci rkey, IB_ACCESS_REMOTE_READ); 30858c2ecf20Sopenharmony_ci if (unlikely(!ok)) 30868c2ecf20Sopenharmony_ci goto nack_acc_unlck; 30878c2ecf20Sopenharmony_ci /* 30888c2ecf20Sopenharmony_ci * Update the next expected PSN. We add 1 later 30898c2ecf20Sopenharmony_ci * below, so only add the remainder here. 30908c2ecf20Sopenharmony_ci */ 30918c2ecf20Sopenharmony_ci qp->r_psn += rvt_div_mtu(qp, len - 1); 30928c2ecf20Sopenharmony_ci } else { 30938c2ecf20Sopenharmony_ci e->rdma_sge.mr = NULL; 30948c2ecf20Sopenharmony_ci e->rdma_sge.vaddr = NULL; 30958c2ecf20Sopenharmony_ci e->rdma_sge.length = 0; 30968c2ecf20Sopenharmony_ci e->rdma_sge.sge_length = 0; 30978c2ecf20Sopenharmony_ci } 30988c2ecf20Sopenharmony_ci e->opcode = opcode; 30998c2ecf20Sopenharmony_ci e->sent = 0; 31008c2ecf20Sopenharmony_ci e->psn = psn; 31018c2ecf20Sopenharmony_ci e->lpsn = qp->r_psn; 31028c2ecf20Sopenharmony_ci /* 31038c2ecf20Sopenharmony_ci * We need to increment the MSN here instead of when we 31048c2ecf20Sopenharmony_ci * finish sending the result since a duplicate request would 31058c2ecf20Sopenharmony_ci * increment it more than once. 31068c2ecf20Sopenharmony_ci */ 31078c2ecf20Sopenharmony_ci qp->r_msn++; 31088c2ecf20Sopenharmony_ci qp->r_psn++; 31098c2ecf20Sopenharmony_ci qp->r_state = opcode; 31108c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 31118c2ecf20Sopenharmony_ci qp->r_head_ack_queue = next; 31128c2ecf20Sopenharmony_ci qpriv->r_tid_alloc = qp->r_head_ack_queue; 31138c2ecf20Sopenharmony_ci 31148c2ecf20Sopenharmony_ci /* Schedule the send engine. */ 31158c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_RESP_PENDING; 31168c2ecf20Sopenharmony_ci if (fecn) 31178c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_ECN; 31188c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 31198c2ecf20Sopenharmony_ci 31208c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 31218c2ecf20Sopenharmony_ci return; 31228c2ecf20Sopenharmony_ci } 31238c2ecf20Sopenharmony_ci 31248c2ecf20Sopenharmony_ci case OP(COMPARE_SWAP): 31258c2ecf20Sopenharmony_ci case OP(FETCH_ADD): { 31268c2ecf20Sopenharmony_ci struct ib_atomic_eth *ateth = &ohdr->u.atomic_eth; 31278c2ecf20Sopenharmony_ci u64 vaddr = get_ib_ateth_vaddr(ateth); 31288c2ecf20Sopenharmony_ci bool opfn = opcode == OP(COMPARE_SWAP) && 31298c2ecf20Sopenharmony_ci vaddr == HFI1_VERBS_E_ATOMIC_VADDR; 31308c2ecf20Sopenharmony_ci struct rvt_ack_entry *e; 31318c2ecf20Sopenharmony_ci atomic64_t *maddr; 31328c2ecf20Sopenharmony_ci u64 sdata; 31338c2ecf20Sopenharmony_ci u32 rkey; 31348c2ecf20Sopenharmony_ci u8 next; 31358c2ecf20Sopenharmony_ci 31368c2ecf20Sopenharmony_ci if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC) && 31378c2ecf20Sopenharmony_ci !opfn)) 31388c2ecf20Sopenharmony_ci goto nack_inv; 31398c2ecf20Sopenharmony_ci next = qp->r_head_ack_queue + 1; 31408c2ecf20Sopenharmony_ci if (next > rvt_size_atomic(ib_to_rvt(qp->ibqp.device))) 31418c2ecf20Sopenharmony_ci next = 0; 31428c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 31438c2ecf20Sopenharmony_ci if (unlikely(next == qp->s_acked_ack_queue)) { 31448c2ecf20Sopenharmony_ci if (!qp->s_ack_queue[next].sent) 31458c2ecf20Sopenharmony_ci goto nack_inv_unlck; 31468c2ecf20Sopenharmony_ci update_ack_queue(qp, next); 31478c2ecf20Sopenharmony_ci } 31488c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->r_head_ack_queue]; 31498c2ecf20Sopenharmony_ci release_rdma_sge_mr(e); 31508c2ecf20Sopenharmony_ci /* Process OPFN special virtual address */ 31518c2ecf20Sopenharmony_ci if (opfn) { 31528c2ecf20Sopenharmony_ci opfn_conn_response(qp, e, ateth); 31538c2ecf20Sopenharmony_ci goto ack; 31548c2ecf20Sopenharmony_ci } 31558c2ecf20Sopenharmony_ci if (unlikely(vaddr & (sizeof(u64) - 1))) 31568c2ecf20Sopenharmony_ci goto nack_inv_unlck; 31578c2ecf20Sopenharmony_ci rkey = be32_to_cpu(ateth->rkey); 31588c2ecf20Sopenharmony_ci /* Check rkey & NAK */ 31598c2ecf20Sopenharmony_ci if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64), 31608c2ecf20Sopenharmony_ci vaddr, rkey, 31618c2ecf20Sopenharmony_ci IB_ACCESS_REMOTE_ATOMIC))) 31628c2ecf20Sopenharmony_ci goto nack_acc_unlck; 31638c2ecf20Sopenharmony_ci /* Perform atomic OP and save result. */ 31648c2ecf20Sopenharmony_ci maddr = (atomic64_t *)qp->r_sge.sge.vaddr; 31658c2ecf20Sopenharmony_ci sdata = get_ib_ateth_swap(ateth); 31668c2ecf20Sopenharmony_ci e->atomic_data = (opcode == OP(FETCH_ADD)) ? 31678c2ecf20Sopenharmony_ci (u64)atomic64_add_return(sdata, maddr) - sdata : 31688c2ecf20Sopenharmony_ci (u64)cmpxchg((u64 *)qp->r_sge.sge.vaddr, 31698c2ecf20Sopenharmony_ci get_ib_ateth_compare(ateth), 31708c2ecf20Sopenharmony_ci sdata); 31718c2ecf20Sopenharmony_ci rvt_put_mr(qp->r_sge.sge.mr); 31728c2ecf20Sopenharmony_ci qp->r_sge.num_sge = 0; 31738c2ecf20Sopenharmony_ciack: 31748c2ecf20Sopenharmony_ci e->opcode = opcode; 31758c2ecf20Sopenharmony_ci e->sent = 0; 31768c2ecf20Sopenharmony_ci e->psn = psn; 31778c2ecf20Sopenharmony_ci e->lpsn = psn; 31788c2ecf20Sopenharmony_ci qp->r_msn++; 31798c2ecf20Sopenharmony_ci qp->r_psn++; 31808c2ecf20Sopenharmony_ci qp->r_state = opcode; 31818c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 31828c2ecf20Sopenharmony_ci qp->r_head_ack_queue = next; 31838c2ecf20Sopenharmony_ci qpriv->r_tid_alloc = qp->r_head_ack_queue; 31848c2ecf20Sopenharmony_ci 31858c2ecf20Sopenharmony_ci /* Schedule the send engine. */ 31868c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_RESP_PENDING; 31878c2ecf20Sopenharmony_ci if (fecn) 31888c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_ECN; 31898c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 31908c2ecf20Sopenharmony_ci 31918c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 31928c2ecf20Sopenharmony_ci return; 31938c2ecf20Sopenharmony_ci } 31948c2ecf20Sopenharmony_ci 31958c2ecf20Sopenharmony_ci default: 31968c2ecf20Sopenharmony_ci /* NAK unknown opcodes. */ 31978c2ecf20Sopenharmony_ci goto nack_inv; 31988c2ecf20Sopenharmony_ci } 31998c2ecf20Sopenharmony_ci qp->r_psn++; 32008c2ecf20Sopenharmony_ci qp->r_state = opcode; 32018c2ecf20Sopenharmony_ci qp->r_ack_psn = psn; 32028c2ecf20Sopenharmony_ci qp->r_nak_state = 0; 32038c2ecf20Sopenharmony_ci /* Send an ACK if requested or required. */ 32048c2ecf20Sopenharmony_ci if (psn & IB_BTH_REQ_ACK || fecn) { 32058c2ecf20Sopenharmony_ci if (packet->numpkt == 0 || fecn || 32068c2ecf20Sopenharmony_ci qp->r_adefered >= HFI1_PSN_CREDIT) { 32078c2ecf20Sopenharmony_ci rc_cancel_ack(qp); 32088c2ecf20Sopenharmony_ci goto send_ack; 32098c2ecf20Sopenharmony_ci } 32108c2ecf20Sopenharmony_ci qp->r_adefered++; 32118c2ecf20Sopenharmony_ci rc_defered_ack(rcd, qp); 32128c2ecf20Sopenharmony_ci } 32138c2ecf20Sopenharmony_ci return; 32148c2ecf20Sopenharmony_ci 32158c2ecf20Sopenharmony_cirnr_nak: 32168c2ecf20Sopenharmony_ci qp->r_nak_state = qp->r_min_rnr_timer | IB_RNR_NAK; 32178c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 32188c2ecf20Sopenharmony_ci /* Queue RNR NAK for later */ 32198c2ecf20Sopenharmony_ci rc_defered_ack(rcd, qp); 32208c2ecf20Sopenharmony_ci return; 32218c2ecf20Sopenharmony_ci 32228c2ecf20Sopenharmony_cinack_op_err: 32238c2ecf20Sopenharmony_ci rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR); 32248c2ecf20Sopenharmony_ci qp->r_nak_state = IB_NAK_REMOTE_OPERATIONAL_ERROR; 32258c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 32268c2ecf20Sopenharmony_ci /* Queue NAK for later */ 32278c2ecf20Sopenharmony_ci rc_defered_ack(rcd, qp); 32288c2ecf20Sopenharmony_ci return; 32298c2ecf20Sopenharmony_ci 32308c2ecf20Sopenharmony_cinack_inv_unlck: 32318c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 32328c2ecf20Sopenharmony_cinack_inv: 32338c2ecf20Sopenharmony_ci rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR); 32348c2ecf20Sopenharmony_ci qp->r_nak_state = IB_NAK_INVALID_REQUEST; 32358c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 32368c2ecf20Sopenharmony_ci /* Queue NAK for later */ 32378c2ecf20Sopenharmony_ci rc_defered_ack(rcd, qp); 32388c2ecf20Sopenharmony_ci return; 32398c2ecf20Sopenharmony_ci 32408c2ecf20Sopenharmony_cinack_acc_unlck: 32418c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 32428c2ecf20Sopenharmony_cinack_acc: 32438c2ecf20Sopenharmony_ci rvt_rc_error(qp, IB_WC_LOC_PROT_ERR); 32448c2ecf20Sopenharmony_ci qp->r_nak_state = IB_NAK_REMOTE_ACCESS_ERROR; 32458c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 32468c2ecf20Sopenharmony_cisend_ack: 32478c2ecf20Sopenharmony_ci hfi1_send_rc_ack(packet, fecn); 32488c2ecf20Sopenharmony_ci} 32498c2ecf20Sopenharmony_ci 32508c2ecf20Sopenharmony_civoid hfi1_rc_hdrerr( 32518c2ecf20Sopenharmony_ci struct hfi1_ctxtdata *rcd, 32528c2ecf20Sopenharmony_ci struct hfi1_packet *packet, 32538c2ecf20Sopenharmony_ci struct rvt_qp *qp) 32548c2ecf20Sopenharmony_ci{ 32558c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = rcd_to_iport(rcd); 32568c2ecf20Sopenharmony_ci int diff; 32578c2ecf20Sopenharmony_ci u32 opcode; 32588c2ecf20Sopenharmony_ci u32 psn; 32598c2ecf20Sopenharmony_ci 32608c2ecf20Sopenharmony_ci if (hfi1_ruc_check_hdr(ibp, packet)) 32618c2ecf20Sopenharmony_ci return; 32628c2ecf20Sopenharmony_ci 32638c2ecf20Sopenharmony_ci psn = ib_bth_get_psn(packet->ohdr); 32648c2ecf20Sopenharmony_ci opcode = ib_bth_get_opcode(packet->ohdr); 32658c2ecf20Sopenharmony_ci 32668c2ecf20Sopenharmony_ci /* Only deal with RDMA Writes for now */ 32678c2ecf20Sopenharmony_ci if (opcode < IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) { 32688c2ecf20Sopenharmony_ci diff = delta_psn(psn, qp->r_psn); 32698c2ecf20Sopenharmony_ci if (!qp->r_nak_state && diff >= 0) { 32708c2ecf20Sopenharmony_ci ibp->rvp.n_rc_seqnak++; 32718c2ecf20Sopenharmony_ci qp->r_nak_state = IB_NAK_PSN_ERROR; 32728c2ecf20Sopenharmony_ci /* Use the expected PSN. */ 32738c2ecf20Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 32748c2ecf20Sopenharmony_ci /* 32758c2ecf20Sopenharmony_ci * Wait to send the sequence 32768c2ecf20Sopenharmony_ci * NAK until all packets 32778c2ecf20Sopenharmony_ci * in the receive queue have 32788c2ecf20Sopenharmony_ci * been processed. 32798c2ecf20Sopenharmony_ci * Otherwise, we end up 32808c2ecf20Sopenharmony_ci * propagating congestion. 32818c2ecf20Sopenharmony_ci */ 32828c2ecf20Sopenharmony_ci rc_defered_ack(rcd, qp); 32838c2ecf20Sopenharmony_ci } /* Out of sequence NAK */ 32848c2ecf20Sopenharmony_ci } /* QP Request NAKs */ 32858c2ecf20Sopenharmony_ci} 3286