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 "hfi.h" 498c2ecf20Sopenharmony_ci#include "verbs_txreq.h" 508c2ecf20Sopenharmony_ci#include "qp.h" 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* cut down ridiculously long IB macro names */ 538c2ecf20Sopenharmony_ci#define OP(x) UC_OP(x) 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/** 568c2ecf20Sopenharmony_ci * hfi1_make_uc_req - construct a request packet (SEND, RDMA write) 578c2ecf20Sopenharmony_ci * @qp: a pointer to the QP 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * Assume s_lock is held. 608c2ecf20Sopenharmony_ci * 618c2ecf20Sopenharmony_ci * Return 1 if constructed; otherwise, return 0. 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_ciint hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 668c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr; 678c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 688c2ecf20Sopenharmony_ci u32 hwords; 698c2ecf20Sopenharmony_ci u32 bth0 = 0; 708c2ecf20Sopenharmony_ci u32 len; 718c2ecf20Sopenharmony_ci u32 pmtu = qp->pmtu; 728c2ecf20Sopenharmony_ci int middle = 0; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci ps->s_txreq = get_txreq(ps->dev, qp); 758c2ecf20Sopenharmony_ci if (!ps->s_txreq) 768c2ecf20Sopenharmony_ci goto bail_no_tx; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_SEND_OK)) { 798c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_FLUSH_SEND)) 808c2ecf20Sopenharmony_ci goto bail; 818c2ecf20Sopenharmony_ci /* We are in the error state, flush the work request. */ 828c2ecf20Sopenharmony_ci if (qp->s_last == READ_ONCE(qp->s_head)) 838c2ecf20Sopenharmony_ci goto bail; 848c2ecf20Sopenharmony_ci /* If DMAs are in progress, we can't flush immediately. */ 858c2ecf20Sopenharmony_ci if (iowait_sdma_pending(&priv->s_iowait)) { 868c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_DMA; 878c2ecf20Sopenharmony_ci goto bail; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci clear_ahg(qp); 908c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_last); 918c2ecf20Sopenharmony_ci rvt_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR); 928c2ecf20Sopenharmony_ci goto done_free_tx; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if (priv->hdr_type == HFI1_PKT_TYPE_9B) { 968c2ecf20Sopenharmony_ci /* header size in 32-bit words LRH+BTH = (8+12)/4. */ 978c2ecf20Sopenharmony_ci hwords = 5; 988c2ecf20Sopenharmony_ci if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) 998c2ecf20Sopenharmony_ci ohdr = &ps->s_txreq->phdr.hdr.ibh.u.l.oth; 1008c2ecf20Sopenharmony_ci else 1018c2ecf20Sopenharmony_ci ohdr = &ps->s_txreq->phdr.hdr.ibh.u.oth; 1028c2ecf20Sopenharmony_ci } else { 1038c2ecf20Sopenharmony_ci /* header size in 32-bit words 16B LRH+BTH = (16+12)/4. */ 1048c2ecf20Sopenharmony_ci hwords = 7; 1058c2ecf20Sopenharmony_ci if ((rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) && 1068c2ecf20Sopenharmony_ci (hfi1_check_mcast(rdma_ah_get_dlid(&qp->remote_ah_attr)))) 1078c2ecf20Sopenharmony_ci ohdr = &ps->s_txreq->phdr.hdr.opah.u.l.oth; 1088c2ecf20Sopenharmony_ci else 1098c2ecf20Sopenharmony_ci ohdr = &ps->s_txreq->phdr.hdr.opah.u.oth; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci /* Get the next send request. */ 1138c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_cur); 1148c2ecf20Sopenharmony_ci qp->s_wqe = NULL; 1158c2ecf20Sopenharmony_ci switch (qp->s_state) { 1168c2ecf20Sopenharmony_ci default: 1178c2ecf20Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & 1188c2ecf20Sopenharmony_ci RVT_PROCESS_NEXT_SEND_OK)) 1198c2ecf20Sopenharmony_ci goto bail; 1208c2ecf20Sopenharmony_ci /* Check if send work queue is empty. */ 1218c2ecf20Sopenharmony_ci if (qp->s_cur == READ_ONCE(qp->s_head)) { 1228c2ecf20Sopenharmony_ci clear_ahg(qp); 1238c2ecf20Sopenharmony_ci goto bail; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci /* 1268c2ecf20Sopenharmony_ci * Local operations are processed immediately 1278c2ecf20Sopenharmony_ci * after all prior requests have completed. 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_REG_MR || 1308c2ecf20Sopenharmony_ci wqe->wr.opcode == IB_WR_LOCAL_INV) { 1318c2ecf20Sopenharmony_ci int local_ops = 0; 1328c2ecf20Sopenharmony_ci int err = 0; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (qp->s_last != qp->s_cur) 1358c2ecf20Sopenharmony_ci goto bail; 1368c2ecf20Sopenharmony_ci if (++qp->s_cur == qp->s_size) 1378c2ecf20Sopenharmony_ci qp->s_cur = 0; 1388c2ecf20Sopenharmony_ci if (!(wqe->wr.send_flags & RVT_SEND_COMPLETION_ONLY)) { 1398c2ecf20Sopenharmony_ci err = rvt_invalidate_rkey( 1408c2ecf20Sopenharmony_ci qp, wqe->wr.ex.invalidate_rkey); 1418c2ecf20Sopenharmony_ci local_ops = 1; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci rvt_send_complete(qp, wqe, err ? IB_WC_LOC_PROT_ERR 1448c2ecf20Sopenharmony_ci : IB_WC_SUCCESS); 1458c2ecf20Sopenharmony_ci if (local_ops) 1468c2ecf20Sopenharmony_ci atomic_dec(&qp->local_ops_pending); 1478c2ecf20Sopenharmony_ci goto done_free_tx; 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci /* 1508c2ecf20Sopenharmony_ci * Start a new request. 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_ci qp->s_psn = wqe->psn; 1538c2ecf20Sopenharmony_ci qp->s_sge.sge = wqe->sg_list[0]; 1548c2ecf20Sopenharmony_ci qp->s_sge.sg_list = wqe->sg_list + 1; 1558c2ecf20Sopenharmony_ci qp->s_sge.num_sge = wqe->wr.num_sge; 1568c2ecf20Sopenharmony_ci qp->s_sge.total_len = wqe->length; 1578c2ecf20Sopenharmony_ci len = wqe->length; 1588c2ecf20Sopenharmony_ci qp->s_len = len; 1598c2ecf20Sopenharmony_ci switch (wqe->wr.opcode) { 1608c2ecf20Sopenharmony_ci case IB_WR_SEND: 1618c2ecf20Sopenharmony_ci case IB_WR_SEND_WITH_IMM: 1628c2ecf20Sopenharmony_ci if (len > pmtu) { 1638c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_FIRST); 1648c2ecf20Sopenharmony_ci len = pmtu; 1658c2ecf20Sopenharmony_ci break; 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_SEND) { 1688c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_ONLY); 1698c2ecf20Sopenharmony_ci } else { 1708c2ecf20Sopenharmony_ci qp->s_state = 1718c2ecf20Sopenharmony_ci OP(SEND_ONLY_WITH_IMMEDIATE); 1728c2ecf20Sopenharmony_ci /* Immediate data comes after the BTH */ 1738c2ecf20Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 1748c2ecf20Sopenharmony_ci hwords += 1; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 1778c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 1788c2ecf20Sopenharmony_ci qp->s_wqe = wqe; 1798c2ecf20Sopenharmony_ci if (++qp->s_cur >= qp->s_size) 1808c2ecf20Sopenharmony_ci qp->s_cur = 0; 1818c2ecf20Sopenharmony_ci break; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE: 1848c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE_WITH_IMM: 1858c2ecf20Sopenharmony_ci ohdr->u.rc.reth.vaddr = 1868c2ecf20Sopenharmony_ci cpu_to_be64(wqe->rdma_wr.remote_addr); 1878c2ecf20Sopenharmony_ci ohdr->u.rc.reth.rkey = 1888c2ecf20Sopenharmony_ci cpu_to_be32(wqe->rdma_wr.rkey); 1898c2ecf20Sopenharmony_ci ohdr->u.rc.reth.length = cpu_to_be32(len); 1908c2ecf20Sopenharmony_ci hwords += sizeof(struct ib_reth) / 4; 1918c2ecf20Sopenharmony_ci if (len > pmtu) { 1928c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_FIRST); 1938c2ecf20Sopenharmony_ci len = pmtu; 1948c2ecf20Sopenharmony_ci break; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_WRITE) { 1978c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_ONLY); 1988c2ecf20Sopenharmony_ci } else { 1998c2ecf20Sopenharmony_ci qp->s_state = 2008c2ecf20Sopenharmony_ci OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE); 2018c2ecf20Sopenharmony_ci /* Immediate data comes after the RETH */ 2028c2ecf20Sopenharmony_ci ohdr->u.rc.imm_data = wqe->wr.ex.imm_data; 2038c2ecf20Sopenharmony_ci hwords += 1; 2048c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 2058c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci qp->s_wqe = wqe; 2088c2ecf20Sopenharmony_ci if (++qp->s_cur >= qp->s_size) 2098c2ecf20Sopenharmony_ci qp->s_cur = 0; 2108c2ecf20Sopenharmony_ci break; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci default: 2138c2ecf20Sopenharmony_ci goto bail; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci break; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci case OP(SEND_FIRST): 2188c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_MIDDLE); 2198c2ecf20Sopenharmony_ci fallthrough; 2208c2ecf20Sopenharmony_ci case OP(SEND_MIDDLE): 2218c2ecf20Sopenharmony_ci len = qp->s_len; 2228c2ecf20Sopenharmony_ci if (len > pmtu) { 2238c2ecf20Sopenharmony_ci len = pmtu; 2248c2ecf20Sopenharmony_ci middle = HFI1_CAP_IS_KSET(SDMA_AHG); 2258c2ecf20Sopenharmony_ci break; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_SEND) { 2288c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST); 2298c2ecf20Sopenharmony_ci } else { 2308c2ecf20Sopenharmony_ci qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE); 2318c2ecf20Sopenharmony_ci /* Immediate data comes after the BTH */ 2328c2ecf20Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 2338c2ecf20Sopenharmony_ci hwords += 1; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 2368c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 2378c2ecf20Sopenharmony_ci qp->s_wqe = wqe; 2388c2ecf20Sopenharmony_ci if (++qp->s_cur >= qp->s_size) 2398c2ecf20Sopenharmony_ci qp->s_cur = 0; 2408c2ecf20Sopenharmony_ci break; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 2438c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_MIDDLE); 2448c2ecf20Sopenharmony_ci fallthrough; 2458c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 2468c2ecf20Sopenharmony_ci len = qp->s_len; 2478c2ecf20Sopenharmony_ci if (len > pmtu) { 2488c2ecf20Sopenharmony_ci len = pmtu; 2498c2ecf20Sopenharmony_ci middle = HFI1_CAP_IS_KSET(SDMA_AHG); 2508c2ecf20Sopenharmony_ci break; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_WRITE) { 2538c2ecf20Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_LAST); 2548c2ecf20Sopenharmony_ci } else { 2558c2ecf20Sopenharmony_ci qp->s_state = 2568c2ecf20Sopenharmony_ci OP(RDMA_WRITE_LAST_WITH_IMMEDIATE); 2578c2ecf20Sopenharmony_ci /* Immediate data comes after the BTH */ 2588c2ecf20Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 2598c2ecf20Sopenharmony_ci hwords += 1; 2608c2ecf20Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 2618c2ecf20Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci qp->s_wqe = wqe; 2648c2ecf20Sopenharmony_ci if (++qp->s_cur >= qp->s_size) 2658c2ecf20Sopenharmony_ci qp->s_cur = 0; 2668c2ecf20Sopenharmony_ci break; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci qp->s_len -= len; 2698c2ecf20Sopenharmony_ci ps->s_txreq->hdr_dwords = hwords; 2708c2ecf20Sopenharmony_ci ps->s_txreq->sde = priv->s_sde; 2718c2ecf20Sopenharmony_ci ps->s_txreq->ss = &qp->s_sge; 2728c2ecf20Sopenharmony_ci ps->s_txreq->s_cur_size = len; 2738c2ecf20Sopenharmony_ci hfi1_make_ruc_header(qp, ohdr, bth0 | (qp->s_state << 24), 2748c2ecf20Sopenharmony_ci qp->remote_qpn, mask_psn(qp->s_psn++), 2758c2ecf20Sopenharmony_ci middle, ps); 2768c2ecf20Sopenharmony_ci return 1; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cidone_free_tx: 2798c2ecf20Sopenharmony_ci hfi1_put_txreq(ps->s_txreq); 2808c2ecf20Sopenharmony_ci ps->s_txreq = NULL; 2818c2ecf20Sopenharmony_ci return 1; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cibail: 2848c2ecf20Sopenharmony_ci hfi1_put_txreq(ps->s_txreq); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cibail_no_tx: 2878c2ecf20Sopenharmony_ci ps->s_txreq = NULL; 2888c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_BUSY; 2898c2ecf20Sopenharmony_ci return 0; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci/** 2938c2ecf20Sopenharmony_ci * hfi1_uc_rcv - handle an incoming UC packet 2948c2ecf20Sopenharmony_ci * @ibp: the port the packet came in on 2958c2ecf20Sopenharmony_ci * @hdr: the header of the packet 2968c2ecf20Sopenharmony_ci * @rcv_flags: flags relevant to rcv processing 2978c2ecf20Sopenharmony_ci * @data: the packet data 2988c2ecf20Sopenharmony_ci * @tlen: the length of the packet 2998c2ecf20Sopenharmony_ci * @qp: the QP for this packet. 3008c2ecf20Sopenharmony_ci * 3018c2ecf20Sopenharmony_ci * This is called from qp_rcv() to process an incoming UC packet 3028c2ecf20Sopenharmony_ci * for the given QP. 3038c2ecf20Sopenharmony_ci * Called at interrupt level. 3048c2ecf20Sopenharmony_ci */ 3058c2ecf20Sopenharmony_civoid hfi1_uc_rcv(struct hfi1_packet *packet) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd); 3088c2ecf20Sopenharmony_ci void *data = packet->payload; 3098c2ecf20Sopenharmony_ci u32 tlen = packet->tlen; 3108c2ecf20Sopenharmony_ci struct rvt_qp *qp = packet->qp; 3118c2ecf20Sopenharmony_ci struct ib_other_headers *ohdr = packet->ohdr; 3128c2ecf20Sopenharmony_ci u32 opcode = packet->opcode; 3138c2ecf20Sopenharmony_ci u32 hdrsize = packet->hlen; 3148c2ecf20Sopenharmony_ci u32 psn; 3158c2ecf20Sopenharmony_ci u32 pad = packet->pad; 3168c2ecf20Sopenharmony_ci struct ib_wc wc; 3178c2ecf20Sopenharmony_ci u32 pmtu = qp->pmtu; 3188c2ecf20Sopenharmony_ci struct ib_reth *reth; 3198c2ecf20Sopenharmony_ci int ret; 3208c2ecf20Sopenharmony_ci u8 extra_bytes = pad + packet->extra_byte + (SIZE_OF_CRC << 2); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci if (hfi1_ruc_check_hdr(ibp, packet)) 3238c2ecf20Sopenharmony_ci return; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci process_ecn(qp, packet); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci psn = ib_bth_get_psn(ohdr); 3288c2ecf20Sopenharmony_ci /* Compare the PSN verses the expected PSN. */ 3298c2ecf20Sopenharmony_ci if (unlikely(cmp_psn(psn, qp->r_psn) != 0)) { 3308c2ecf20Sopenharmony_ci /* 3318c2ecf20Sopenharmony_ci * Handle a sequence error. 3328c2ecf20Sopenharmony_ci * Silently drop any current message. 3338c2ecf20Sopenharmony_ci */ 3348c2ecf20Sopenharmony_ci qp->r_psn = psn; 3358c2ecf20Sopenharmony_ciinv: 3368c2ecf20Sopenharmony_ci if (qp->r_state == OP(SEND_FIRST) || 3378c2ecf20Sopenharmony_ci qp->r_state == OP(SEND_MIDDLE)) { 3388c2ecf20Sopenharmony_ci set_bit(RVT_R_REWIND_SGE, &qp->r_aflags); 3398c2ecf20Sopenharmony_ci qp->r_sge.num_sge = 0; 3408c2ecf20Sopenharmony_ci } else { 3418c2ecf20Sopenharmony_ci rvt_put_ss(&qp->r_sge); 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci qp->r_state = OP(SEND_LAST); 3448c2ecf20Sopenharmony_ci switch (opcode) { 3458c2ecf20Sopenharmony_ci case OP(SEND_FIRST): 3468c2ecf20Sopenharmony_ci case OP(SEND_ONLY): 3478c2ecf20Sopenharmony_ci case OP(SEND_ONLY_WITH_IMMEDIATE): 3488c2ecf20Sopenharmony_ci goto send_first; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 3518c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_ONLY): 3528c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): 3538c2ecf20Sopenharmony_ci goto rdma_first; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci default: 3568c2ecf20Sopenharmony_ci goto drop; 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci /* Check for opcode sequence errors. */ 3618c2ecf20Sopenharmony_ci switch (qp->r_state) { 3628c2ecf20Sopenharmony_ci case OP(SEND_FIRST): 3638c2ecf20Sopenharmony_ci case OP(SEND_MIDDLE): 3648c2ecf20Sopenharmony_ci if (opcode == OP(SEND_MIDDLE) || 3658c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST) || 3668c2ecf20Sopenharmony_ci opcode == OP(SEND_LAST_WITH_IMMEDIATE)) 3678c2ecf20Sopenharmony_ci break; 3688c2ecf20Sopenharmony_ci goto inv; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 3718c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 3728c2ecf20Sopenharmony_ci if (opcode == OP(RDMA_WRITE_MIDDLE) || 3738c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST) || 3748c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) 3758c2ecf20Sopenharmony_ci break; 3768c2ecf20Sopenharmony_ci goto inv; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci default: 3798c2ecf20Sopenharmony_ci if (opcode == OP(SEND_FIRST) || 3808c2ecf20Sopenharmony_ci opcode == OP(SEND_ONLY) || 3818c2ecf20Sopenharmony_ci opcode == OP(SEND_ONLY_WITH_IMMEDIATE) || 3828c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_FIRST) || 3838c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_ONLY) || 3848c2ecf20Sopenharmony_ci opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) 3858c2ecf20Sopenharmony_ci break; 3868c2ecf20Sopenharmony_ci goto inv; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci if (qp->state == IB_QPS_RTR && !(qp->r_flags & RVT_R_COMM_EST)) 3908c2ecf20Sopenharmony_ci rvt_comm_est(qp); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci /* OK, process the packet. */ 3938c2ecf20Sopenharmony_ci switch (opcode) { 3948c2ecf20Sopenharmony_ci case OP(SEND_FIRST): 3958c2ecf20Sopenharmony_ci case OP(SEND_ONLY): 3968c2ecf20Sopenharmony_ci case OP(SEND_ONLY_WITH_IMMEDIATE): 3978c2ecf20Sopenharmony_cisend_first: 3988c2ecf20Sopenharmony_ci if (test_and_clear_bit(RVT_R_REWIND_SGE, &qp->r_aflags)) { 3998c2ecf20Sopenharmony_ci qp->r_sge = qp->s_rdma_read_sge; 4008c2ecf20Sopenharmony_ci } else { 4018c2ecf20Sopenharmony_ci ret = rvt_get_rwqe(qp, false); 4028c2ecf20Sopenharmony_ci if (ret < 0) 4038c2ecf20Sopenharmony_ci goto op_err; 4048c2ecf20Sopenharmony_ci if (!ret) 4058c2ecf20Sopenharmony_ci goto drop; 4068c2ecf20Sopenharmony_ci /* 4078c2ecf20Sopenharmony_ci * qp->s_rdma_read_sge will be the owner 4088c2ecf20Sopenharmony_ci * of the mr references. 4098c2ecf20Sopenharmony_ci */ 4108c2ecf20Sopenharmony_ci qp->s_rdma_read_sge = qp->r_sge; 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci qp->r_rcv_len = 0; 4138c2ecf20Sopenharmony_ci if (opcode == OP(SEND_ONLY)) 4148c2ecf20Sopenharmony_ci goto no_immediate_data; 4158c2ecf20Sopenharmony_ci else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE)) 4168c2ecf20Sopenharmony_ci goto send_last_imm; 4178c2ecf20Sopenharmony_ci fallthrough; 4188c2ecf20Sopenharmony_ci case OP(SEND_MIDDLE): 4198c2ecf20Sopenharmony_ci /* Check for invalid length PMTU or posted rwqe len. */ 4208c2ecf20Sopenharmony_ci /* 4218c2ecf20Sopenharmony_ci * There will be no padding for 9B packet but 16B packets 4228c2ecf20Sopenharmony_ci * will come in with some padding since we always add 4238c2ecf20Sopenharmony_ci * CRC and LT bytes which will need to be flit aligned 4248c2ecf20Sopenharmony_ci */ 4258c2ecf20Sopenharmony_ci if (unlikely(tlen != (hdrsize + pmtu + extra_bytes))) 4268c2ecf20Sopenharmony_ci goto rewind; 4278c2ecf20Sopenharmony_ci qp->r_rcv_len += pmtu; 4288c2ecf20Sopenharmony_ci if (unlikely(qp->r_rcv_len > qp->r_len)) 4298c2ecf20Sopenharmony_ci goto rewind; 4308c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, pmtu, false, false); 4318c2ecf20Sopenharmony_ci break; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci case OP(SEND_LAST_WITH_IMMEDIATE): 4348c2ecf20Sopenharmony_cisend_last_imm: 4358c2ecf20Sopenharmony_ci wc.ex.imm_data = ohdr->u.imm_data; 4368c2ecf20Sopenharmony_ci wc.wc_flags = IB_WC_WITH_IMM; 4378c2ecf20Sopenharmony_ci goto send_last; 4388c2ecf20Sopenharmony_ci case OP(SEND_LAST): 4398c2ecf20Sopenharmony_cino_immediate_data: 4408c2ecf20Sopenharmony_ci wc.ex.imm_data = 0; 4418c2ecf20Sopenharmony_ci wc.wc_flags = 0; 4428c2ecf20Sopenharmony_cisend_last: 4438c2ecf20Sopenharmony_ci /* Check for invalid length. */ 4448c2ecf20Sopenharmony_ci /* LAST len should be >= 1 */ 4458c2ecf20Sopenharmony_ci if (unlikely(tlen < (hdrsize + extra_bytes))) 4468c2ecf20Sopenharmony_ci goto rewind; 4478c2ecf20Sopenharmony_ci /* Don't count the CRC. */ 4488c2ecf20Sopenharmony_ci tlen -= (hdrsize + extra_bytes); 4498c2ecf20Sopenharmony_ci wc.byte_len = tlen + qp->r_rcv_len; 4508c2ecf20Sopenharmony_ci if (unlikely(wc.byte_len > qp->r_len)) 4518c2ecf20Sopenharmony_ci goto rewind; 4528c2ecf20Sopenharmony_ci wc.opcode = IB_WC_RECV; 4538c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, tlen, false, false); 4548c2ecf20Sopenharmony_ci rvt_put_ss(&qp->s_rdma_read_sge); 4558c2ecf20Sopenharmony_cilast_imm: 4568c2ecf20Sopenharmony_ci wc.wr_id = qp->r_wr_id; 4578c2ecf20Sopenharmony_ci wc.status = IB_WC_SUCCESS; 4588c2ecf20Sopenharmony_ci wc.qp = &qp->ibqp; 4598c2ecf20Sopenharmony_ci wc.src_qp = qp->remote_qpn; 4608c2ecf20Sopenharmony_ci wc.slid = rdma_ah_get_dlid(&qp->remote_ah_attr) & U16_MAX; 4618c2ecf20Sopenharmony_ci /* 4628c2ecf20Sopenharmony_ci * It seems that IB mandates the presence of an SL in a 4638c2ecf20Sopenharmony_ci * work completion only for the UD transport (see section 4648c2ecf20Sopenharmony_ci * 11.4.2 of IBTA Vol. 1). 4658c2ecf20Sopenharmony_ci * 4668c2ecf20Sopenharmony_ci * However, the way the SL is chosen below is consistent 4678c2ecf20Sopenharmony_ci * with the way that IB/qib works and is trying avoid 4688c2ecf20Sopenharmony_ci * introducing incompatibilities. 4698c2ecf20Sopenharmony_ci * 4708c2ecf20Sopenharmony_ci * See also OPA Vol. 1, section 9.7.6, and table 9-17. 4718c2ecf20Sopenharmony_ci */ 4728c2ecf20Sopenharmony_ci wc.sl = rdma_ah_get_sl(&qp->remote_ah_attr); 4738c2ecf20Sopenharmony_ci /* zero fields that are N/A */ 4748c2ecf20Sopenharmony_ci wc.vendor_err = 0; 4758c2ecf20Sopenharmony_ci wc.pkey_index = 0; 4768c2ecf20Sopenharmony_ci wc.dlid_path_bits = 0; 4778c2ecf20Sopenharmony_ci wc.port_num = 0; 4788c2ecf20Sopenharmony_ci /* Signal completion event if the solicited bit is set. */ 4798c2ecf20Sopenharmony_ci rvt_recv_cq(qp, &wc, ib_bth_is_solicited(ohdr)); 4808c2ecf20Sopenharmony_ci break; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 4838c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_ONLY): 4848c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): /* consume RWQE */ 4858c2ecf20Sopenharmony_cirdma_first: 4868c2ecf20Sopenharmony_ci if (unlikely(!(qp->qp_access_flags & 4878c2ecf20Sopenharmony_ci IB_ACCESS_REMOTE_WRITE))) { 4888c2ecf20Sopenharmony_ci goto drop; 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci reth = &ohdr->u.rc.reth; 4918c2ecf20Sopenharmony_ci qp->r_len = be32_to_cpu(reth->length); 4928c2ecf20Sopenharmony_ci qp->r_rcv_len = 0; 4938c2ecf20Sopenharmony_ci qp->r_sge.sg_list = NULL; 4948c2ecf20Sopenharmony_ci if (qp->r_len != 0) { 4958c2ecf20Sopenharmony_ci u32 rkey = be32_to_cpu(reth->rkey); 4968c2ecf20Sopenharmony_ci u64 vaddr = be64_to_cpu(reth->vaddr); 4978c2ecf20Sopenharmony_ci int ok; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci /* Check rkey */ 5008c2ecf20Sopenharmony_ci ok = rvt_rkey_ok(qp, &qp->r_sge.sge, qp->r_len, 5018c2ecf20Sopenharmony_ci vaddr, rkey, IB_ACCESS_REMOTE_WRITE); 5028c2ecf20Sopenharmony_ci if (unlikely(!ok)) 5038c2ecf20Sopenharmony_ci goto drop; 5048c2ecf20Sopenharmony_ci qp->r_sge.num_sge = 1; 5058c2ecf20Sopenharmony_ci } else { 5068c2ecf20Sopenharmony_ci qp->r_sge.num_sge = 0; 5078c2ecf20Sopenharmony_ci qp->r_sge.sge.mr = NULL; 5088c2ecf20Sopenharmony_ci qp->r_sge.sge.vaddr = NULL; 5098c2ecf20Sopenharmony_ci qp->r_sge.sge.length = 0; 5108c2ecf20Sopenharmony_ci qp->r_sge.sge.sge_length = 0; 5118c2ecf20Sopenharmony_ci } 5128c2ecf20Sopenharmony_ci if (opcode == OP(RDMA_WRITE_ONLY)) { 5138c2ecf20Sopenharmony_ci goto rdma_last; 5148c2ecf20Sopenharmony_ci } else if (opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) { 5158c2ecf20Sopenharmony_ci wc.ex.imm_data = ohdr->u.rc.imm_data; 5168c2ecf20Sopenharmony_ci goto rdma_last_imm; 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci fallthrough; 5198c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 5208c2ecf20Sopenharmony_ci /* Check for invalid length PMTU or posted rwqe len. */ 5218c2ecf20Sopenharmony_ci if (unlikely(tlen != (hdrsize + pmtu + 4))) 5228c2ecf20Sopenharmony_ci goto drop; 5238c2ecf20Sopenharmony_ci qp->r_rcv_len += pmtu; 5248c2ecf20Sopenharmony_ci if (unlikely(qp->r_rcv_len > qp->r_len)) 5258c2ecf20Sopenharmony_ci goto drop; 5268c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, pmtu, true, false); 5278c2ecf20Sopenharmony_ci break; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE): 5308c2ecf20Sopenharmony_ci wc.ex.imm_data = ohdr->u.imm_data; 5318c2ecf20Sopenharmony_cirdma_last_imm: 5328c2ecf20Sopenharmony_ci wc.wc_flags = IB_WC_WITH_IMM; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci /* Check for invalid length. */ 5358c2ecf20Sopenharmony_ci /* LAST len should be >= 1 */ 5368c2ecf20Sopenharmony_ci if (unlikely(tlen < (hdrsize + pad + 4))) 5378c2ecf20Sopenharmony_ci goto drop; 5388c2ecf20Sopenharmony_ci /* Don't count the CRC. */ 5398c2ecf20Sopenharmony_ci tlen -= (hdrsize + extra_bytes); 5408c2ecf20Sopenharmony_ci if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) 5418c2ecf20Sopenharmony_ci goto drop; 5428c2ecf20Sopenharmony_ci if (test_and_clear_bit(RVT_R_REWIND_SGE, &qp->r_aflags)) { 5438c2ecf20Sopenharmony_ci rvt_put_ss(&qp->s_rdma_read_sge); 5448c2ecf20Sopenharmony_ci } else { 5458c2ecf20Sopenharmony_ci ret = rvt_get_rwqe(qp, true); 5468c2ecf20Sopenharmony_ci if (ret < 0) 5478c2ecf20Sopenharmony_ci goto op_err; 5488c2ecf20Sopenharmony_ci if (!ret) 5498c2ecf20Sopenharmony_ci goto drop; 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci wc.byte_len = qp->r_len; 5528c2ecf20Sopenharmony_ci wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; 5538c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, tlen, true, false); 5548c2ecf20Sopenharmony_ci rvt_put_ss(&qp->r_sge); 5558c2ecf20Sopenharmony_ci goto last_imm; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci case OP(RDMA_WRITE_LAST): 5588c2ecf20Sopenharmony_cirdma_last: 5598c2ecf20Sopenharmony_ci /* Check for invalid length. */ 5608c2ecf20Sopenharmony_ci /* LAST len should be >= 1 */ 5618c2ecf20Sopenharmony_ci if (unlikely(tlen < (hdrsize + pad + 4))) 5628c2ecf20Sopenharmony_ci goto drop; 5638c2ecf20Sopenharmony_ci /* Don't count the CRC. */ 5648c2ecf20Sopenharmony_ci tlen -= (hdrsize + extra_bytes); 5658c2ecf20Sopenharmony_ci if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) 5668c2ecf20Sopenharmony_ci goto drop; 5678c2ecf20Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, tlen, true, false); 5688c2ecf20Sopenharmony_ci rvt_put_ss(&qp->r_sge); 5698c2ecf20Sopenharmony_ci break; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci default: 5728c2ecf20Sopenharmony_ci /* Drop packet for unknown opcodes. */ 5738c2ecf20Sopenharmony_ci goto drop; 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci qp->r_psn++; 5768c2ecf20Sopenharmony_ci qp->r_state = opcode; 5778c2ecf20Sopenharmony_ci return; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_cirewind: 5808c2ecf20Sopenharmony_ci set_bit(RVT_R_REWIND_SGE, &qp->r_aflags); 5818c2ecf20Sopenharmony_ci qp->r_sge.num_sge = 0; 5828c2ecf20Sopenharmony_cidrop: 5838c2ecf20Sopenharmony_ci ibp->rvp.n_pkt_drops++; 5848c2ecf20Sopenharmony_ci return; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ciop_err: 5878c2ecf20Sopenharmony_ci rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR); 5888c2ecf20Sopenharmony_ci} 589