162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved. 362306a36Sopenharmony_ci * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This software is available to you under a choice of one of two 662306a36Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 762306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 862306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the 962306a36Sopenharmony_ci * OpenIB.org BSD license below: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or 1262306a36Sopenharmony_ci * without modification, are permitted provided that the following 1362306a36Sopenharmony_ci * conditions are met: 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * - Redistributions of source code must retain the above 1662306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 1762306a36Sopenharmony_ci * disclaimer. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * - Redistributions in binary form must reproduce the above 2062306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 2162306a36Sopenharmony_ci * disclaimer in the documentation and/or other materials 2262306a36Sopenharmony_ci * provided with the distribution. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2562306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2662306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2762306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2862306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2962306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 3062306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3162306a36Sopenharmony_ci * SOFTWARE. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#include <linux/io.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include "qib.h" 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* cut down ridiculously long IB macro names */ 3962306a36Sopenharmony_ci#define OP(x) IB_OPCODE_RC_##x 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic u32 restart_sge(struct rvt_sge_state *ss, struct rvt_swqe *wqe, 4362306a36Sopenharmony_ci u32 psn, u32 pmtu) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci u32 len; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci len = ((psn - wqe->psn) & QIB_PSN_MASK) * pmtu; 4862306a36Sopenharmony_ci return rvt_restart_sge(ss, wqe, len); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/** 5262306a36Sopenharmony_ci * qib_make_rc_ack - construct a response packet (ACK, NAK, or RDMA read) 5362306a36Sopenharmony_ci * @dev: the device for this QP 5462306a36Sopenharmony_ci * @qp: a pointer to the QP 5562306a36Sopenharmony_ci * @ohdr: a pointer to the IB header being constructed 5662306a36Sopenharmony_ci * @pmtu: the path MTU 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * Return 1 if constructed; otherwise, return 0. 5962306a36Sopenharmony_ci * Note that we are in the responder's side of the QP context. 6062306a36Sopenharmony_ci * Note the QP s_lock must be held. 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_cistatic int qib_make_rc_ack(struct qib_ibdev *dev, struct rvt_qp *qp, 6362306a36Sopenharmony_ci struct ib_other_headers *ohdr, u32 pmtu) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci struct rvt_ack_entry *e; 6662306a36Sopenharmony_ci u32 hwords; 6762306a36Sopenharmony_ci u32 len; 6862306a36Sopenharmony_ci u32 bth0; 6962306a36Sopenharmony_ci u32 bth2; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* Don't send an ACK if we aren't supposed to. */ 7262306a36Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) 7362306a36Sopenharmony_ci goto bail; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /* header size in 32-bit words LRH+BTH = (8+12)/4. */ 7662306a36Sopenharmony_ci hwords = 5; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci switch (qp->s_ack_state) { 7962306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_LAST): 8062306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_ONLY): 8162306a36Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 8262306a36Sopenharmony_ci if (e->rdma_sge.mr) { 8362306a36Sopenharmony_ci rvt_put_mr(e->rdma_sge.mr); 8462306a36Sopenharmony_ci e->rdma_sge.mr = NULL; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci fallthrough; 8762306a36Sopenharmony_ci case OP(ATOMIC_ACKNOWLEDGE): 8862306a36Sopenharmony_ci /* 8962306a36Sopenharmony_ci * We can increment the tail pointer now that the last 9062306a36Sopenharmony_ci * response has been sent instead of only being 9162306a36Sopenharmony_ci * constructed. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci if (++qp->s_tail_ack_queue > QIB_MAX_RDMA_ATOMIC) 9462306a36Sopenharmony_ci qp->s_tail_ack_queue = 0; 9562306a36Sopenharmony_ci fallthrough; 9662306a36Sopenharmony_ci case OP(SEND_ONLY): 9762306a36Sopenharmony_ci case OP(ACKNOWLEDGE): 9862306a36Sopenharmony_ci /* Check for no next entry in the queue. */ 9962306a36Sopenharmony_ci if (qp->r_head_ack_queue == qp->s_tail_ack_queue) { 10062306a36Sopenharmony_ci if (qp->s_flags & RVT_S_ACK_PENDING) 10162306a36Sopenharmony_ci goto normal; 10262306a36Sopenharmony_ci goto bail; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 10662306a36Sopenharmony_ci if (e->opcode == OP(RDMA_READ_REQUEST)) { 10762306a36Sopenharmony_ci /* 10862306a36Sopenharmony_ci * If a RDMA read response is being resent and 10962306a36Sopenharmony_ci * we haven't seen the duplicate request yet, 11062306a36Sopenharmony_ci * then stop sending the remaining responses the 11162306a36Sopenharmony_ci * responder has seen until the requester resends it. 11262306a36Sopenharmony_ci */ 11362306a36Sopenharmony_ci len = e->rdma_sge.sge_length; 11462306a36Sopenharmony_ci if (len && !e->rdma_sge.mr) { 11562306a36Sopenharmony_ci qp->s_tail_ack_queue = qp->r_head_ack_queue; 11662306a36Sopenharmony_ci goto bail; 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci /* Copy SGE state in case we need to resend */ 11962306a36Sopenharmony_ci qp->s_rdma_mr = e->rdma_sge.mr; 12062306a36Sopenharmony_ci if (qp->s_rdma_mr) 12162306a36Sopenharmony_ci rvt_get_mr(qp->s_rdma_mr); 12262306a36Sopenharmony_ci qp->s_ack_rdma_sge.sge = e->rdma_sge; 12362306a36Sopenharmony_ci qp->s_ack_rdma_sge.num_sge = 1; 12462306a36Sopenharmony_ci qp->s_cur_sge = &qp->s_ack_rdma_sge; 12562306a36Sopenharmony_ci if (len > pmtu) { 12662306a36Sopenharmony_ci len = pmtu; 12762306a36Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST); 12862306a36Sopenharmony_ci } else { 12962306a36Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY); 13062306a36Sopenharmony_ci e->sent = 1; 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 13362306a36Sopenharmony_ci hwords++; 13462306a36Sopenharmony_ci qp->s_ack_rdma_psn = e->psn; 13562306a36Sopenharmony_ci bth2 = qp->s_ack_rdma_psn++ & QIB_PSN_MASK; 13662306a36Sopenharmony_ci } else { 13762306a36Sopenharmony_ci /* COMPARE_SWAP or FETCH_ADD */ 13862306a36Sopenharmony_ci qp->s_cur_sge = NULL; 13962306a36Sopenharmony_ci len = 0; 14062306a36Sopenharmony_ci qp->s_ack_state = OP(ATOMIC_ACKNOWLEDGE); 14162306a36Sopenharmony_ci ohdr->u.at.aeth = rvt_compute_aeth(qp); 14262306a36Sopenharmony_ci ib_u64_put(e->atomic_data, &ohdr->u.at.atomic_ack_eth); 14362306a36Sopenharmony_ci hwords += sizeof(ohdr->u.at) / sizeof(u32); 14462306a36Sopenharmony_ci bth2 = e->psn & QIB_PSN_MASK; 14562306a36Sopenharmony_ci e->sent = 1; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci bth0 = qp->s_ack_state << 24; 14862306a36Sopenharmony_ci break; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_FIRST): 15162306a36Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE); 15262306a36Sopenharmony_ci fallthrough; 15362306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_MIDDLE): 15462306a36Sopenharmony_ci qp->s_cur_sge = &qp->s_ack_rdma_sge; 15562306a36Sopenharmony_ci qp->s_rdma_mr = qp->s_ack_rdma_sge.sge.mr; 15662306a36Sopenharmony_ci if (qp->s_rdma_mr) 15762306a36Sopenharmony_ci rvt_get_mr(qp->s_rdma_mr); 15862306a36Sopenharmony_ci len = qp->s_ack_rdma_sge.sge.sge_length; 15962306a36Sopenharmony_ci if (len > pmtu) 16062306a36Sopenharmony_ci len = pmtu; 16162306a36Sopenharmony_ci else { 16262306a36Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 16362306a36Sopenharmony_ci hwords++; 16462306a36Sopenharmony_ci qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST); 16562306a36Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 16662306a36Sopenharmony_ci e->sent = 1; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci bth0 = qp->s_ack_state << 24; 16962306a36Sopenharmony_ci bth2 = qp->s_ack_rdma_psn++ & QIB_PSN_MASK; 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci default: 17362306a36Sopenharmony_cinormal: 17462306a36Sopenharmony_ci /* 17562306a36Sopenharmony_ci * Send a regular ACK. 17662306a36Sopenharmony_ci * Set the s_ack_state so we wait until after sending 17762306a36Sopenharmony_ci * the ACK before setting s_ack_state to ACKNOWLEDGE 17862306a36Sopenharmony_ci * (see above). 17962306a36Sopenharmony_ci */ 18062306a36Sopenharmony_ci qp->s_ack_state = OP(SEND_ONLY); 18162306a36Sopenharmony_ci qp->s_flags &= ~RVT_S_ACK_PENDING; 18262306a36Sopenharmony_ci qp->s_cur_sge = NULL; 18362306a36Sopenharmony_ci if (qp->s_nak_state) 18462306a36Sopenharmony_ci ohdr->u.aeth = 18562306a36Sopenharmony_ci cpu_to_be32((qp->r_msn & IB_MSN_MASK) | 18662306a36Sopenharmony_ci (qp->s_nak_state << 18762306a36Sopenharmony_ci IB_AETH_CREDIT_SHIFT)); 18862306a36Sopenharmony_ci else 18962306a36Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 19062306a36Sopenharmony_ci hwords++; 19162306a36Sopenharmony_ci len = 0; 19262306a36Sopenharmony_ci bth0 = OP(ACKNOWLEDGE) << 24; 19362306a36Sopenharmony_ci bth2 = qp->s_ack_psn & QIB_PSN_MASK; 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci qp->s_rdma_ack_cnt++; 19662306a36Sopenharmony_ci qp->s_hdrwords = hwords; 19762306a36Sopenharmony_ci qp->s_cur_size = len; 19862306a36Sopenharmony_ci qib_make_ruc_header(qp, ohdr, bth0, bth2); 19962306a36Sopenharmony_ci return 1; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cibail: 20262306a36Sopenharmony_ci qp->s_ack_state = OP(ACKNOWLEDGE); 20362306a36Sopenharmony_ci qp->s_flags &= ~(RVT_S_RESP_PENDING | RVT_S_ACK_PENDING); 20462306a36Sopenharmony_ci return 0; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/** 20862306a36Sopenharmony_ci * qib_make_rc_req - construct a request packet (SEND, RDMA r/w, ATOMIC) 20962306a36Sopenharmony_ci * @qp: a pointer to the QP 21062306a36Sopenharmony_ci * @flags: unused 21162306a36Sopenharmony_ci * 21262306a36Sopenharmony_ci * Assumes the s_lock is held. 21362306a36Sopenharmony_ci * 21462306a36Sopenharmony_ci * Return 1 if constructed; otherwise, return 0. 21562306a36Sopenharmony_ci */ 21662306a36Sopenharmony_ciint qib_make_rc_req(struct rvt_qp *qp, unsigned long *flags) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci struct qib_qp_priv *priv = qp->priv; 21962306a36Sopenharmony_ci struct qib_ibdev *dev = to_idev(qp->ibqp.device); 22062306a36Sopenharmony_ci struct ib_other_headers *ohdr; 22162306a36Sopenharmony_ci struct rvt_sge_state *ss; 22262306a36Sopenharmony_ci struct rvt_swqe *wqe; 22362306a36Sopenharmony_ci u32 hwords; 22462306a36Sopenharmony_ci u32 len; 22562306a36Sopenharmony_ci u32 bth0; 22662306a36Sopenharmony_ci u32 bth2; 22762306a36Sopenharmony_ci u32 pmtu = qp->pmtu; 22862306a36Sopenharmony_ci char newreq; 22962306a36Sopenharmony_ci int ret = 0; 23062306a36Sopenharmony_ci int delta; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci ohdr = &priv->s_hdr->u.oth; 23362306a36Sopenharmony_ci if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) 23462306a36Sopenharmony_ci ohdr = &priv->s_hdr->u.l.oth; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* Sending responses has higher priority over sending requests. */ 23762306a36Sopenharmony_ci if ((qp->s_flags & RVT_S_RESP_PENDING) && 23862306a36Sopenharmony_ci qib_make_rc_ack(dev, qp, ohdr, pmtu)) 23962306a36Sopenharmony_ci goto done; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_SEND_OK)) { 24262306a36Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_FLUSH_SEND)) 24362306a36Sopenharmony_ci goto bail; 24462306a36Sopenharmony_ci /* We are in the error state, flush the work request. */ 24562306a36Sopenharmony_ci if (qp->s_last == READ_ONCE(qp->s_head)) 24662306a36Sopenharmony_ci goto bail; 24762306a36Sopenharmony_ci /* If DMAs are in progress, we can't flush immediately. */ 24862306a36Sopenharmony_ci if (atomic_read(&priv->s_dma_busy)) { 24962306a36Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_DMA; 25062306a36Sopenharmony_ci goto bail; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_last); 25362306a36Sopenharmony_ci rvt_send_complete(qp, wqe, qp->s_last != qp->s_acked ? 25462306a36Sopenharmony_ci IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR); 25562306a36Sopenharmony_ci /* will get called again */ 25662306a36Sopenharmony_ci goto done; 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (qp->s_flags & (RVT_S_WAIT_RNR | RVT_S_WAIT_ACK)) 26062306a36Sopenharmony_ci goto bail; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (qib_cmp24(qp->s_psn, qp->s_sending_hpsn) <= 0) { 26362306a36Sopenharmony_ci if (qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) <= 0) { 26462306a36Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_PSN; 26562306a36Sopenharmony_ci goto bail; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci qp->s_sending_psn = qp->s_psn; 26862306a36Sopenharmony_ci qp->s_sending_hpsn = qp->s_psn - 1; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* header size in 32-bit words LRH+BTH = (8+12)/4. */ 27262306a36Sopenharmony_ci hwords = 5; 27362306a36Sopenharmony_ci bth0 = 0; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* Send a request. */ 27662306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_cur); 27762306a36Sopenharmony_ci switch (qp->s_state) { 27862306a36Sopenharmony_ci default: 27962306a36Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_NEXT_SEND_OK)) 28062306a36Sopenharmony_ci goto bail; 28162306a36Sopenharmony_ci /* 28262306a36Sopenharmony_ci * Resend an old request or start a new one. 28362306a36Sopenharmony_ci * 28462306a36Sopenharmony_ci * We keep track of the current SWQE so that 28562306a36Sopenharmony_ci * we don't reset the "furthest progress" state 28662306a36Sopenharmony_ci * if we need to back up. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ci newreq = 0; 28962306a36Sopenharmony_ci if (qp->s_cur == qp->s_tail) { 29062306a36Sopenharmony_ci /* Check if send work queue is empty. */ 29162306a36Sopenharmony_ci if (qp->s_tail == READ_ONCE(qp->s_head)) 29262306a36Sopenharmony_ci goto bail; 29362306a36Sopenharmony_ci /* 29462306a36Sopenharmony_ci * If a fence is requested, wait for previous 29562306a36Sopenharmony_ci * RDMA read and atomic operations to finish. 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_ci if ((wqe->wr.send_flags & IB_SEND_FENCE) && 29862306a36Sopenharmony_ci qp->s_num_rd_atomic) { 29962306a36Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_FENCE; 30062306a36Sopenharmony_ci goto bail; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci newreq = 1; 30362306a36Sopenharmony_ci qp->s_psn = wqe->psn; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci /* 30662306a36Sopenharmony_ci * Note that we have to be careful not to modify the 30762306a36Sopenharmony_ci * original work request since we may need to resend 30862306a36Sopenharmony_ci * it. 30962306a36Sopenharmony_ci */ 31062306a36Sopenharmony_ci len = wqe->length; 31162306a36Sopenharmony_ci ss = &qp->s_sge; 31262306a36Sopenharmony_ci bth2 = qp->s_psn & QIB_PSN_MASK; 31362306a36Sopenharmony_ci switch (wqe->wr.opcode) { 31462306a36Sopenharmony_ci case IB_WR_SEND: 31562306a36Sopenharmony_ci case IB_WR_SEND_WITH_IMM: 31662306a36Sopenharmony_ci /* If no credit, return. */ 31762306a36Sopenharmony_ci if (!rvt_rc_credit_avail(qp, wqe)) 31862306a36Sopenharmony_ci goto bail; 31962306a36Sopenharmony_ci if (len > pmtu) { 32062306a36Sopenharmony_ci qp->s_state = OP(SEND_FIRST); 32162306a36Sopenharmony_ci len = pmtu; 32262306a36Sopenharmony_ci break; 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci if (wqe->wr.opcode == IB_WR_SEND) 32562306a36Sopenharmony_ci qp->s_state = OP(SEND_ONLY); 32662306a36Sopenharmony_ci else { 32762306a36Sopenharmony_ci qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE); 32862306a36Sopenharmony_ci /* Immediate data comes after the BTH */ 32962306a36Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 33062306a36Sopenharmony_ci hwords += 1; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 33362306a36Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 33462306a36Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 33562306a36Sopenharmony_ci if (++qp->s_cur == qp->s_size) 33662306a36Sopenharmony_ci qp->s_cur = 0; 33762306a36Sopenharmony_ci break; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci case IB_WR_RDMA_WRITE: 34062306a36Sopenharmony_ci if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 34162306a36Sopenharmony_ci qp->s_lsn++; 34262306a36Sopenharmony_ci goto no_flow_control; 34362306a36Sopenharmony_ci case IB_WR_RDMA_WRITE_WITH_IMM: 34462306a36Sopenharmony_ci /* If no credit, return. */ 34562306a36Sopenharmony_ci if (!rvt_rc_credit_avail(qp, wqe)) 34662306a36Sopenharmony_ci goto bail; 34762306a36Sopenharmony_cino_flow_control: 34862306a36Sopenharmony_ci ohdr->u.rc.reth.vaddr = 34962306a36Sopenharmony_ci cpu_to_be64(wqe->rdma_wr.remote_addr); 35062306a36Sopenharmony_ci ohdr->u.rc.reth.rkey = 35162306a36Sopenharmony_ci cpu_to_be32(wqe->rdma_wr.rkey); 35262306a36Sopenharmony_ci ohdr->u.rc.reth.length = cpu_to_be32(len); 35362306a36Sopenharmony_ci hwords += sizeof(struct ib_reth) / sizeof(u32); 35462306a36Sopenharmony_ci if (len > pmtu) { 35562306a36Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_FIRST); 35662306a36Sopenharmony_ci len = pmtu; 35762306a36Sopenharmony_ci break; 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci if (wqe->rdma_wr.wr.opcode == IB_WR_RDMA_WRITE) 36062306a36Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_ONLY); 36162306a36Sopenharmony_ci else { 36262306a36Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE); 36362306a36Sopenharmony_ci /* Immediate data comes after RETH */ 36462306a36Sopenharmony_ci ohdr->u.rc.imm_data = 36562306a36Sopenharmony_ci wqe->rdma_wr.wr.ex.imm_data; 36662306a36Sopenharmony_ci hwords += 1; 36762306a36Sopenharmony_ci if (wqe->rdma_wr.wr.send_flags & IB_SEND_SOLICITED) 36862306a36Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 37162306a36Sopenharmony_ci if (++qp->s_cur == qp->s_size) 37262306a36Sopenharmony_ci qp->s_cur = 0; 37362306a36Sopenharmony_ci break; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci case IB_WR_RDMA_READ: 37662306a36Sopenharmony_ci /* 37762306a36Sopenharmony_ci * Don't allow more operations to be started 37862306a36Sopenharmony_ci * than the QP limits allow. 37962306a36Sopenharmony_ci */ 38062306a36Sopenharmony_ci if (newreq) { 38162306a36Sopenharmony_ci if (qp->s_num_rd_atomic >= 38262306a36Sopenharmony_ci qp->s_max_rd_atomic) { 38362306a36Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_RDMAR; 38462306a36Sopenharmony_ci goto bail; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci qp->s_num_rd_atomic++; 38762306a36Sopenharmony_ci if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 38862306a36Sopenharmony_ci qp->s_lsn++; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci ohdr->u.rc.reth.vaddr = 39262306a36Sopenharmony_ci cpu_to_be64(wqe->rdma_wr.remote_addr); 39362306a36Sopenharmony_ci ohdr->u.rc.reth.rkey = 39462306a36Sopenharmony_ci cpu_to_be32(wqe->rdma_wr.rkey); 39562306a36Sopenharmony_ci ohdr->u.rc.reth.length = cpu_to_be32(len); 39662306a36Sopenharmony_ci qp->s_state = OP(RDMA_READ_REQUEST); 39762306a36Sopenharmony_ci hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32); 39862306a36Sopenharmony_ci ss = NULL; 39962306a36Sopenharmony_ci len = 0; 40062306a36Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 40162306a36Sopenharmony_ci if (++qp->s_cur == qp->s_size) 40262306a36Sopenharmony_ci qp->s_cur = 0; 40362306a36Sopenharmony_ci break; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci case IB_WR_ATOMIC_CMP_AND_SWP: 40662306a36Sopenharmony_ci case IB_WR_ATOMIC_FETCH_AND_ADD: 40762306a36Sopenharmony_ci /* 40862306a36Sopenharmony_ci * Don't allow more operations to be started 40962306a36Sopenharmony_ci * than the QP limits allow. 41062306a36Sopenharmony_ci */ 41162306a36Sopenharmony_ci if (newreq) { 41262306a36Sopenharmony_ci if (qp->s_num_rd_atomic >= 41362306a36Sopenharmony_ci qp->s_max_rd_atomic) { 41462306a36Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_RDMAR; 41562306a36Sopenharmony_ci goto bail; 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci qp->s_num_rd_atomic++; 41862306a36Sopenharmony_ci if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) 41962306a36Sopenharmony_ci qp->s_lsn++; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci if (wqe->atomic_wr.wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) { 42262306a36Sopenharmony_ci qp->s_state = OP(COMPARE_SWAP); 42362306a36Sopenharmony_ci put_ib_ateth_swap(wqe->atomic_wr.swap, 42462306a36Sopenharmony_ci &ohdr->u.atomic_eth); 42562306a36Sopenharmony_ci put_ib_ateth_compare(wqe->atomic_wr.compare_add, 42662306a36Sopenharmony_ci &ohdr->u.atomic_eth); 42762306a36Sopenharmony_ci } else { 42862306a36Sopenharmony_ci qp->s_state = OP(FETCH_ADD); 42962306a36Sopenharmony_ci put_ib_ateth_swap(wqe->atomic_wr.compare_add, 43062306a36Sopenharmony_ci &ohdr->u.atomic_eth); 43162306a36Sopenharmony_ci put_ib_ateth_compare(0, &ohdr->u.atomic_eth); 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci put_ib_ateth_vaddr(wqe->atomic_wr.remote_addr, 43462306a36Sopenharmony_ci &ohdr->u.atomic_eth); 43562306a36Sopenharmony_ci ohdr->u.atomic_eth.rkey = cpu_to_be32( 43662306a36Sopenharmony_ci wqe->atomic_wr.rkey); 43762306a36Sopenharmony_ci hwords += sizeof(struct ib_atomic_eth) / sizeof(u32); 43862306a36Sopenharmony_ci ss = NULL; 43962306a36Sopenharmony_ci len = 0; 44062306a36Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 44162306a36Sopenharmony_ci if (++qp->s_cur == qp->s_size) 44262306a36Sopenharmony_ci qp->s_cur = 0; 44362306a36Sopenharmony_ci break; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci default: 44662306a36Sopenharmony_ci goto bail; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci qp->s_sge.sge = wqe->sg_list[0]; 44962306a36Sopenharmony_ci qp->s_sge.sg_list = wqe->sg_list + 1; 45062306a36Sopenharmony_ci qp->s_sge.num_sge = wqe->wr.num_sge; 45162306a36Sopenharmony_ci qp->s_sge.total_len = wqe->length; 45262306a36Sopenharmony_ci qp->s_len = wqe->length; 45362306a36Sopenharmony_ci if (newreq) { 45462306a36Sopenharmony_ci qp->s_tail++; 45562306a36Sopenharmony_ci if (qp->s_tail >= qp->s_size) 45662306a36Sopenharmony_ci qp->s_tail = 0; 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ) 45962306a36Sopenharmony_ci qp->s_psn = wqe->lpsn + 1; 46062306a36Sopenharmony_ci else 46162306a36Sopenharmony_ci qp->s_psn++; 46262306a36Sopenharmony_ci break; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_FIRST): 46562306a36Sopenharmony_ci /* 46662306a36Sopenharmony_ci * qp->s_state is normally set to the opcode of the 46762306a36Sopenharmony_ci * last packet constructed for new requests and therefore 46862306a36Sopenharmony_ci * is never set to RDMA read response. 46962306a36Sopenharmony_ci * RDMA_READ_RESPONSE_FIRST is used by the ACK processing 47062306a36Sopenharmony_ci * thread to indicate a SEND needs to be restarted from an 47162306a36Sopenharmony_ci * earlier PSN without interferring with the sending thread. 47262306a36Sopenharmony_ci * See qib_restart_rc(). 47362306a36Sopenharmony_ci */ 47462306a36Sopenharmony_ci qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, pmtu); 47562306a36Sopenharmony_ci fallthrough; 47662306a36Sopenharmony_ci case OP(SEND_FIRST): 47762306a36Sopenharmony_ci qp->s_state = OP(SEND_MIDDLE); 47862306a36Sopenharmony_ci fallthrough; 47962306a36Sopenharmony_ci case OP(SEND_MIDDLE): 48062306a36Sopenharmony_ci bth2 = qp->s_psn++ & QIB_PSN_MASK; 48162306a36Sopenharmony_ci ss = &qp->s_sge; 48262306a36Sopenharmony_ci len = qp->s_len; 48362306a36Sopenharmony_ci if (len > pmtu) { 48462306a36Sopenharmony_ci len = pmtu; 48562306a36Sopenharmony_ci break; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci if (wqe->wr.opcode == IB_WR_SEND) 48862306a36Sopenharmony_ci qp->s_state = OP(SEND_LAST); 48962306a36Sopenharmony_ci else { 49062306a36Sopenharmony_ci qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE); 49162306a36Sopenharmony_ci /* Immediate data comes after the BTH */ 49262306a36Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 49362306a36Sopenharmony_ci hwords += 1; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 49662306a36Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 49762306a36Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 49862306a36Sopenharmony_ci qp->s_cur++; 49962306a36Sopenharmony_ci if (qp->s_cur >= qp->s_size) 50062306a36Sopenharmony_ci qp->s_cur = 0; 50162306a36Sopenharmony_ci break; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_LAST): 50462306a36Sopenharmony_ci /* 50562306a36Sopenharmony_ci * qp->s_state is normally set to the opcode of the 50662306a36Sopenharmony_ci * last packet constructed for new requests and therefore 50762306a36Sopenharmony_ci * is never set to RDMA read response. 50862306a36Sopenharmony_ci * RDMA_READ_RESPONSE_LAST is used by the ACK processing 50962306a36Sopenharmony_ci * thread to indicate a RDMA write needs to be restarted from 51062306a36Sopenharmony_ci * an earlier PSN without interferring with the sending thread. 51162306a36Sopenharmony_ci * See qib_restart_rc(). 51262306a36Sopenharmony_ci */ 51362306a36Sopenharmony_ci qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, pmtu); 51462306a36Sopenharmony_ci fallthrough; 51562306a36Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 51662306a36Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_MIDDLE); 51762306a36Sopenharmony_ci fallthrough; 51862306a36Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 51962306a36Sopenharmony_ci bth2 = qp->s_psn++ & QIB_PSN_MASK; 52062306a36Sopenharmony_ci ss = &qp->s_sge; 52162306a36Sopenharmony_ci len = qp->s_len; 52262306a36Sopenharmony_ci if (len > pmtu) { 52362306a36Sopenharmony_ci len = pmtu; 52462306a36Sopenharmony_ci break; 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_WRITE) 52762306a36Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_LAST); 52862306a36Sopenharmony_ci else { 52962306a36Sopenharmony_ci qp->s_state = OP(RDMA_WRITE_LAST_WITH_IMMEDIATE); 53062306a36Sopenharmony_ci /* Immediate data comes after the BTH */ 53162306a36Sopenharmony_ci ohdr->u.imm_data = wqe->wr.ex.imm_data; 53262306a36Sopenharmony_ci hwords += 1; 53362306a36Sopenharmony_ci if (wqe->wr.send_flags & IB_SEND_SOLICITED) 53462306a36Sopenharmony_ci bth0 |= IB_BTH_SOLICITED; 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 53762306a36Sopenharmony_ci qp->s_cur++; 53862306a36Sopenharmony_ci if (qp->s_cur >= qp->s_size) 53962306a36Sopenharmony_ci qp->s_cur = 0; 54062306a36Sopenharmony_ci break; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_MIDDLE): 54362306a36Sopenharmony_ci /* 54462306a36Sopenharmony_ci * qp->s_state is normally set to the opcode of the 54562306a36Sopenharmony_ci * last packet constructed for new requests and therefore 54662306a36Sopenharmony_ci * is never set to RDMA read response. 54762306a36Sopenharmony_ci * RDMA_READ_RESPONSE_MIDDLE is used by the ACK processing 54862306a36Sopenharmony_ci * thread to indicate a RDMA read needs to be restarted from 54962306a36Sopenharmony_ci * an earlier PSN without interferring with the sending thread. 55062306a36Sopenharmony_ci * See qib_restart_rc(). 55162306a36Sopenharmony_ci */ 55262306a36Sopenharmony_ci len = ((qp->s_psn - wqe->psn) & QIB_PSN_MASK) * pmtu; 55362306a36Sopenharmony_ci ohdr->u.rc.reth.vaddr = 55462306a36Sopenharmony_ci cpu_to_be64(wqe->rdma_wr.remote_addr + len); 55562306a36Sopenharmony_ci ohdr->u.rc.reth.rkey = 55662306a36Sopenharmony_ci cpu_to_be32(wqe->rdma_wr.rkey); 55762306a36Sopenharmony_ci ohdr->u.rc.reth.length = cpu_to_be32(wqe->length - len); 55862306a36Sopenharmony_ci qp->s_state = OP(RDMA_READ_REQUEST); 55962306a36Sopenharmony_ci hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32); 56062306a36Sopenharmony_ci bth2 = (qp->s_psn & QIB_PSN_MASK) | IB_BTH_REQ_ACK; 56162306a36Sopenharmony_ci qp->s_psn = wqe->lpsn + 1; 56262306a36Sopenharmony_ci ss = NULL; 56362306a36Sopenharmony_ci len = 0; 56462306a36Sopenharmony_ci qp->s_cur++; 56562306a36Sopenharmony_ci if (qp->s_cur == qp->s_size) 56662306a36Sopenharmony_ci qp->s_cur = 0; 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci qp->s_sending_hpsn = bth2; 57062306a36Sopenharmony_ci delta = (((int) bth2 - (int) wqe->psn) << 8) >> 8; 57162306a36Sopenharmony_ci if (delta && delta % QIB_PSN_CREDIT == 0) 57262306a36Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 57362306a36Sopenharmony_ci if (qp->s_flags & RVT_S_SEND_ONE) { 57462306a36Sopenharmony_ci qp->s_flags &= ~RVT_S_SEND_ONE; 57562306a36Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_ACK; 57662306a36Sopenharmony_ci bth2 |= IB_BTH_REQ_ACK; 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci qp->s_len -= len; 57962306a36Sopenharmony_ci qp->s_hdrwords = hwords; 58062306a36Sopenharmony_ci qp->s_cur_sge = ss; 58162306a36Sopenharmony_ci qp->s_cur_size = len; 58262306a36Sopenharmony_ci qib_make_ruc_header(qp, ohdr, bth0 | (qp->s_state << 24), bth2); 58362306a36Sopenharmony_cidone: 58462306a36Sopenharmony_ci return 1; 58562306a36Sopenharmony_cibail: 58662306a36Sopenharmony_ci qp->s_flags &= ~RVT_S_BUSY; 58762306a36Sopenharmony_ci return ret; 58862306a36Sopenharmony_ci} 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci/** 59162306a36Sopenharmony_ci * qib_send_rc_ack - Construct an ACK packet and send it 59262306a36Sopenharmony_ci * @qp: a pointer to the QP 59362306a36Sopenharmony_ci * 59462306a36Sopenharmony_ci * This is called from qib_rc_rcv() and qib_kreceive(). 59562306a36Sopenharmony_ci * Note that RDMA reads and atomics are handled in the 59662306a36Sopenharmony_ci * send side QP state and tasklet. 59762306a36Sopenharmony_ci */ 59862306a36Sopenharmony_civoid qib_send_rc_ack(struct rvt_qp *qp) 59962306a36Sopenharmony_ci{ 60062306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(qp->ibqp.device); 60162306a36Sopenharmony_ci struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); 60262306a36Sopenharmony_ci struct qib_pportdata *ppd = ppd_from_ibp(ibp); 60362306a36Sopenharmony_ci u64 pbc; 60462306a36Sopenharmony_ci u16 lrh0; 60562306a36Sopenharmony_ci u32 bth0; 60662306a36Sopenharmony_ci u32 hwords; 60762306a36Sopenharmony_ci u32 pbufn; 60862306a36Sopenharmony_ci u32 __iomem *piobuf; 60962306a36Sopenharmony_ci struct ib_header hdr; 61062306a36Sopenharmony_ci struct ib_other_headers *ohdr; 61162306a36Sopenharmony_ci u32 control; 61262306a36Sopenharmony_ci unsigned long flags; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) 61762306a36Sopenharmony_ci goto unlock; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci /* Don't send ACK or NAK if a RDMA read or atomic is pending. */ 62062306a36Sopenharmony_ci if ((qp->s_flags & RVT_S_RESP_PENDING) || qp->s_rdma_ack_cnt) 62162306a36Sopenharmony_ci goto queue_ack; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci /* Construct the header with s_lock held so APM doesn't change it. */ 62462306a36Sopenharmony_ci ohdr = &hdr.u.oth; 62562306a36Sopenharmony_ci lrh0 = QIB_LRH_BTH; 62662306a36Sopenharmony_ci /* header size in 32-bit words LRH+BTH+AETH = (8+12+4)/4. */ 62762306a36Sopenharmony_ci hwords = 6; 62862306a36Sopenharmony_ci if (unlikely(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & 62962306a36Sopenharmony_ci IB_AH_GRH)) { 63062306a36Sopenharmony_ci hwords += qib_make_grh(ibp, &hdr.u.l.grh, 63162306a36Sopenharmony_ci rdma_ah_read_grh(&qp->remote_ah_attr), 63262306a36Sopenharmony_ci hwords, 0); 63362306a36Sopenharmony_ci ohdr = &hdr.u.l.oth; 63462306a36Sopenharmony_ci lrh0 = QIB_LRH_GRH; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci /* read pkey_index w/o lock (its atomic) */ 63762306a36Sopenharmony_ci bth0 = qib_get_pkey(ibp, qp->s_pkey_index) | (OP(ACKNOWLEDGE) << 24); 63862306a36Sopenharmony_ci if (qp->s_mig_state == IB_MIG_MIGRATED) 63962306a36Sopenharmony_ci bth0 |= IB_BTH_MIG_REQ; 64062306a36Sopenharmony_ci if (qp->r_nak_state) 64162306a36Sopenharmony_ci ohdr->u.aeth = cpu_to_be32((qp->r_msn & IB_MSN_MASK) | 64262306a36Sopenharmony_ci (qp->r_nak_state << 64362306a36Sopenharmony_ci IB_AETH_CREDIT_SHIFT)); 64462306a36Sopenharmony_ci else 64562306a36Sopenharmony_ci ohdr->u.aeth = rvt_compute_aeth(qp); 64662306a36Sopenharmony_ci lrh0 |= ibp->sl_to_vl[rdma_ah_get_sl(&qp->remote_ah_attr)] << 12 | 64762306a36Sopenharmony_ci rdma_ah_get_sl(&qp->remote_ah_attr) << 4; 64862306a36Sopenharmony_ci hdr.lrh[0] = cpu_to_be16(lrh0); 64962306a36Sopenharmony_ci hdr.lrh[1] = cpu_to_be16(rdma_ah_get_dlid(&qp->remote_ah_attr)); 65062306a36Sopenharmony_ci hdr.lrh[2] = cpu_to_be16(hwords + SIZE_OF_CRC); 65162306a36Sopenharmony_ci hdr.lrh[3] = cpu_to_be16(ppd->lid | 65262306a36Sopenharmony_ci rdma_ah_get_path_bits(&qp->remote_ah_attr)); 65362306a36Sopenharmony_ci ohdr->bth[0] = cpu_to_be32(bth0); 65462306a36Sopenharmony_ci ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); 65562306a36Sopenharmony_ci ohdr->bth[2] = cpu_to_be32(qp->r_ack_psn & QIB_PSN_MASK); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci /* Don't try to send ACKs if the link isn't ACTIVE */ 66062306a36Sopenharmony_ci if (!(ppd->lflags & QIBL_LINKACTIVE)) 66162306a36Sopenharmony_ci goto done; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci control = dd->f_setpbc_control(ppd, hwords + SIZE_OF_CRC, 66462306a36Sopenharmony_ci qp->s_srate, lrh0 >> 12); 66562306a36Sopenharmony_ci /* length is + 1 for the control dword */ 66662306a36Sopenharmony_ci pbc = ((u64) control << 32) | (hwords + 1); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci piobuf = dd->f_getsendbuf(ppd, pbc, &pbufn); 66962306a36Sopenharmony_ci if (!piobuf) { 67062306a36Sopenharmony_ci /* 67162306a36Sopenharmony_ci * We are out of PIO buffers at the moment. 67262306a36Sopenharmony_ci * Pass responsibility for sending the ACK to the 67362306a36Sopenharmony_ci * send tasklet so that when a PIO buffer becomes 67462306a36Sopenharmony_ci * available, the ACK is sent ahead of other outgoing 67562306a36Sopenharmony_ci * packets. 67662306a36Sopenharmony_ci */ 67762306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 67862306a36Sopenharmony_ci goto queue_ack; 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci /* 68262306a36Sopenharmony_ci * Write the pbc. 68362306a36Sopenharmony_ci * We have to flush after the PBC for correctness 68462306a36Sopenharmony_ci * on some cpus or WC buffer can be written out of order. 68562306a36Sopenharmony_ci */ 68662306a36Sopenharmony_ci writeq(pbc, piobuf); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci if (dd->flags & QIB_PIO_FLUSH_WC) { 68962306a36Sopenharmony_ci u32 *hdrp = (u32 *) &hdr; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci qib_flush_wc(); 69262306a36Sopenharmony_ci qib_pio_copy(piobuf + 2, hdrp, hwords - 1); 69362306a36Sopenharmony_ci qib_flush_wc(); 69462306a36Sopenharmony_ci __raw_writel(hdrp[hwords - 1], piobuf + hwords + 1); 69562306a36Sopenharmony_ci } else 69662306a36Sopenharmony_ci qib_pio_copy(piobuf + 2, (u32 *) &hdr, hwords); 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci if (dd->flags & QIB_USE_SPCL_TRIG) { 69962306a36Sopenharmony_ci u32 spcl_off = (pbufn >= dd->piobcnt2k) ? 2047 : 1023; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci qib_flush_wc(); 70262306a36Sopenharmony_ci __raw_writel(0xaebecede, piobuf + spcl_off); 70362306a36Sopenharmony_ci } 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci qib_flush_wc(); 70662306a36Sopenharmony_ci qib_sendbuf_done(dd, pbufn); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci this_cpu_inc(ibp->pmastats->n_unicast_xmit); 70962306a36Sopenharmony_ci goto done; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ciqueue_ack: 71262306a36Sopenharmony_ci if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) { 71362306a36Sopenharmony_ci this_cpu_inc(*ibp->rvp.rc_qacks); 71462306a36Sopenharmony_ci qp->s_flags |= RVT_S_ACK_PENDING | RVT_S_RESP_PENDING; 71562306a36Sopenharmony_ci qp->s_nak_state = qp->r_nak_state; 71662306a36Sopenharmony_ci qp->s_ack_psn = qp->r_ack_psn; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci /* Schedule the send tasklet. */ 71962306a36Sopenharmony_ci qib_schedule_send(qp); 72062306a36Sopenharmony_ci } 72162306a36Sopenharmony_ciunlock: 72262306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 72362306a36Sopenharmony_cidone: 72462306a36Sopenharmony_ci return; 72562306a36Sopenharmony_ci} 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci/** 72862306a36Sopenharmony_ci * reset_psn - reset the QP state to send starting from PSN 72962306a36Sopenharmony_ci * @qp: the QP 73062306a36Sopenharmony_ci * @psn: the packet sequence number to restart at 73162306a36Sopenharmony_ci * 73262306a36Sopenharmony_ci * This is called from qib_rc_rcv() to process an incoming RC ACK 73362306a36Sopenharmony_ci * for the given QP. 73462306a36Sopenharmony_ci * Called at interrupt level with the QP s_lock held. 73562306a36Sopenharmony_ci */ 73662306a36Sopenharmony_cistatic void reset_psn(struct rvt_qp *qp, u32 psn) 73762306a36Sopenharmony_ci{ 73862306a36Sopenharmony_ci u32 n = qp->s_acked; 73962306a36Sopenharmony_ci struct rvt_swqe *wqe = rvt_get_swqe_ptr(qp, n); 74062306a36Sopenharmony_ci u32 opcode; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci qp->s_cur = n; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci /* 74562306a36Sopenharmony_ci * If we are starting the request from the beginning, 74662306a36Sopenharmony_ci * let the normal send code handle initialization. 74762306a36Sopenharmony_ci */ 74862306a36Sopenharmony_ci if (qib_cmp24(psn, wqe->psn) <= 0) { 74962306a36Sopenharmony_ci qp->s_state = OP(SEND_LAST); 75062306a36Sopenharmony_ci goto done; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci /* Find the work request opcode corresponding to the given PSN. */ 75462306a36Sopenharmony_ci opcode = wqe->wr.opcode; 75562306a36Sopenharmony_ci for (;;) { 75662306a36Sopenharmony_ci int diff; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci if (++n == qp->s_size) 75962306a36Sopenharmony_ci n = 0; 76062306a36Sopenharmony_ci if (n == qp->s_tail) 76162306a36Sopenharmony_ci break; 76262306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, n); 76362306a36Sopenharmony_ci diff = qib_cmp24(psn, wqe->psn); 76462306a36Sopenharmony_ci if (diff < 0) 76562306a36Sopenharmony_ci break; 76662306a36Sopenharmony_ci qp->s_cur = n; 76762306a36Sopenharmony_ci /* 76862306a36Sopenharmony_ci * If we are starting the request from the beginning, 76962306a36Sopenharmony_ci * let the normal send code handle initialization. 77062306a36Sopenharmony_ci */ 77162306a36Sopenharmony_ci if (diff == 0) { 77262306a36Sopenharmony_ci qp->s_state = OP(SEND_LAST); 77362306a36Sopenharmony_ci goto done; 77462306a36Sopenharmony_ci } 77562306a36Sopenharmony_ci opcode = wqe->wr.opcode; 77662306a36Sopenharmony_ci } 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci /* 77962306a36Sopenharmony_ci * Set the state to restart in the middle of a request. 78062306a36Sopenharmony_ci * Don't change the s_sge, s_cur_sge, or s_cur_size. 78162306a36Sopenharmony_ci * See qib_make_rc_req(). 78262306a36Sopenharmony_ci */ 78362306a36Sopenharmony_ci switch (opcode) { 78462306a36Sopenharmony_ci case IB_WR_SEND: 78562306a36Sopenharmony_ci case IB_WR_SEND_WITH_IMM: 78662306a36Sopenharmony_ci qp->s_state = OP(RDMA_READ_RESPONSE_FIRST); 78762306a36Sopenharmony_ci break; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci case IB_WR_RDMA_WRITE: 79062306a36Sopenharmony_ci case IB_WR_RDMA_WRITE_WITH_IMM: 79162306a36Sopenharmony_ci qp->s_state = OP(RDMA_READ_RESPONSE_LAST); 79262306a36Sopenharmony_ci break; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci case IB_WR_RDMA_READ: 79562306a36Sopenharmony_ci qp->s_state = OP(RDMA_READ_RESPONSE_MIDDLE); 79662306a36Sopenharmony_ci break; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci default: 79962306a36Sopenharmony_ci /* 80062306a36Sopenharmony_ci * This case shouldn't happen since its only 80162306a36Sopenharmony_ci * one PSN per req. 80262306a36Sopenharmony_ci */ 80362306a36Sopenharmony_ci qp->s_state = OP(SEND_LAST); 80462306a36Sopenharmony_ci } 80562306a36Sopenharmony_cidone: 80662306a36Sopenharmony_ci qp->s_psn = psn; 80762306a36Sopenharmony_ci /* 80862306a36Sopenharmony_ci * Set RVT_S_WAIT_PSN as qib_rc_complete() may start the timer 80962306a36Sopenharmony_ci * asynchronously before the send tasklet can get scheduled. 81062306a36Sopenharmony_ci * Doing it in qib_make_rc_req() is too late. 81162306a36Sopenharmony_ci */ 81262306a36Sopenharmony_ci if ((qib_cmp24(qp->s_psn, qp->s_sending_hpsn) <= 0) && 81362306a36Sopenharmony_ci (qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)) 81462306a36Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_PSN; 81562306a36Sopenharmony_ci} 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci/* 81862306a36Sopenharmony_ci * Back up requester to resend the last un-ACKed request. 81962306a36Sopenharmony_ci * The QP r_lock and s_lock should be held and interrupts disabled. 82062306a36Sopenharmony_ci */ 82162306a36Sopenharmony_civoid qib_restart_rc(struct rvt_qp *qp, u32 psn, int wait) 82262306a36Sopenharmony_ci{ 82362306a36Sopenharmony_ci struct rvt_swqe *wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 82462306a36Sopenharmony_ci struct qib_ibport *ibp; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci if (qp->s_retry == 0) { 82762306a36Sopenharmony_ci if (qp->s_mig_state == IB_MIG_ARMED) { 82862306a36Sopenharmony_ci qib_migrate_qp(qp); 82962306a36Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 83062306a36Sopenharmony_ci } else if (qp->s_last == qp->s_acked) { 83162306a36Sopenharmony_ci rvt_send_complete(qp, wqe, IB_WC_RETRY_EXC_ERR); 83262306a36Sopenharmony_ci rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 83362306a36Sopenharmony_ci return; 83462306a36Sopenharmony_ci } else /* XXX need to handle delayed completion */ 83562306a36Sopenharmony_ci return; 83662306a36Sopenharmony_ci } else 83762306a36Sopenharmony_ci qp->s_retry--; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci ibp = to_iport(qp->ibqp.device, qp->port_num); 84062306a36Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ) 84162306a36Sopenharmony_ci ibp->rvp.n_rc_resends++; 84262306a36Sopenharmony_ci else 84362306a36Sopenharmony_ci ibp->rvp.n_rc_resends += (qp->s_psn - psn) & QIB_PSN_MASK; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_FENCE | RVT_S_WAIT_RDMAR | 84662306a36Sopenharmony_ci RVT_S_WAIT_SSN_CREDIT | RVT_S_WAIT_PSN | 84762306a36Sopenharmony_ci RVT_S_WAIT_ACK); 84862306a36Sopenharmony_ci if (wait) 84962306a36Sopenharmony_ci qp->s_flags |= RVT_S_SEND_ONE; 85062306a36Sopenharmony_ci reset_psn(qp, psn); 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci/* 85462306a36Sopenharmony_ci * Set qp->s_sending_psn to the next PSN after the given one. 85562306a36Sopenharmony_ci * This would be psn+1 except when RDMA reads are present. 85662306a36Sopenharmony_ci */ 85762306a36Sopenharmony_cistatic void reset_sending_psn(struct rvt_qp *qp, u32 psn) 85862306a36Sopenharmony_ci{ 85962306a36Sopenharmony_ci struct rvt_swqe *wqe; 86062306a36Sopenharmony_ci u32 n = qp->s_last; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci /* Find the work request corresponding to the given PSN. */ 86362306a36Sopenharmony_ci for (;;) { 86462306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, n); 86562306a36Sopenharmony_ci if (qib_cmp24(psn, wqe->lpsn) <= 0) { 86662306a36Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ) 86762306a36Sopenharmony_ci qp->s_sending_psn = wqe->lpsn + 1; 86862306a36Sopenharmony_ci else 86962306a36Sopenharmony_ci qp->s_sending_psn = psn + 1; 87062306a36Sopenharmony_ci break; 87162306a36Sopenharmony_ci } 87262306a36Sopenharmony_ci if (++n == qp->s_size) 87362306a36Sopenharmony_ci n = 0; 87462306a36Sopenharmony_ci if (n == qp->s_tail) 87562306a36Sopenharmony_ci break; 87662306a36Sopenharmony_ci } 87762306a36Sopenharmony_ci} 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci/* 88062306a36Sopenharmony_ci * This should be called with the QP s_lock held and interrupts disabled. 88162306a36Sopenharmony_ci */ 88262306a36Sopenharmony_civoid qib_rc_send_complete(struct rvt_qp *qp, struct ib_header *hdr) 88362306a36Sopenharmony_ci{ 88462306a36Sopenharmony_ci struct ib_other_headers *ohdr; 88562306a36Sopenharmony_ci struct rvt_swqe *wqe; 88662306a36Sopenharmony_ci u32 opcode; 88762306a36Sopenharmony_ci u32 psn; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_SEND_OR_FLUSH_OR_RECV_OK)) 89062306a36Sopenharmony_ci return; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci /* Find out where the BTH is */ 89362306a36Sopenharmony_ci if ((be16_to_cpu(hdr->lrh[0]) & 3) == QIB_LRH_BTH) 89462306a36Sopenharmony_ci ohdr = &hdr->u.oth; 89562306a36Sopenharmony_ci else 89662306a36Sopenharmony_ci ohdr = &hdr->u.l.oth; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci opcode = be32_to_cpu(ohdr->bth[0]) >> 24; 89962306a36Sopenharmony_ci if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) && 90062306a36Sopenharmony_ci opcode <= OP(ATOMIC_ACKNOWLEDGE)) { 90162306a36Sopenharmony_ci WARN_ON(!qp->s_rdma_ack_cnt); 90262306a36Sopenharmony_ci qp->s_rdma_ack_cnt--; 90362306a36Sopenharmony_ci return; 90462306a36Sopenharmony_ci } 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci psn = be32_to_cpu(ohdr->bth[2]); 90762306a36Sopenharmony_ci reset_sending_psn(qp, psn); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci /* 91062306a36Sopenharmony_ci * Start timer after a packet requesting an ACK has been sent and 91162306a36Sopenharmony_ci * there are still requests that haven't been acked. 91262306a36Sopenharmony_ci */ 91362306a36Sopenharmony_ci if ((psn & IB_BTH_REQ_ACK) && qp->s_acked != qp->s_tail && 91462306a36Sopenharmony_ci !(qp->s_flags & (RVT_S_TIMER | RVT_S_WAIT_RNR | RVT_S_WAIT_PSN)) && 91562306a36Sopenharmony_ci (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) 91662306a36Sopenharmony_ci rvt_add_retry_timer(qp); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci while (qp->s_last != qp->s_acked) { 91962306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_last); 92062306a36Sopenharmony_ci if (qib_cmp24(wqe->lpsn, qp->s_sending_psn) >= 0 && 92162306a36Sopenharmony_ci qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) <= 0) 92262306a36Sopenharmony_ci break; 92362306a36Sopenharmony_ci rvt_qp_complete_swqe(qp, 92462306a36Sopenharmony_ci wqe, 92562306a36Sopenharmony_ci ib_qib_wc_opcode[wqe->wr.opcode], 92662306a36Sopenharmony_ci IB_WC_SUCCESS); 92762306a36Sopenharmony_ci } 92862306a36Sopenharmony_ci /* 92962306a36Sopenharmony_ci * If we were waiting for sends to complete before resending, 93062306a36Sopenharmony_ci * and they are now complete, restart sending. 93162306a36Sopenharmony_ci */ 93262306a36Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_PSN && 93362306a36Sopenharmony_ci qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) > 0) { 93462306a36Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_PSN; 93562306a36Sopenharmony_ci qp->s_sending_psn = qp->s_psn; 93662306a36Sopenharmony_ci qp->s_sending_hpsn = qp->s_psn - 1; 93762306a36Sopenharmony_ci qib_schedule_send(qp); 93862306a36Sopenharmony_ci } 93962306a36Sopenharmony_ci} 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_cistatic inline void update_last_psn(struct rvt_qp *qp, u32 psn) 94262306a36Sopenharmony_ci{ 94362306a36Sopenharmony_ci qp->s_last_psn = psn; 94462306a36Sopenharmony_ci} 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci/* 94762306a36Sopenharmony_ci * Generate a SWQE completion. 94862306a36Sopenharmony_ci * This is similar to qib_send_complete but has to check to be sure 94962306a36Sopenharmony_ci * that the SGEs are not being referenced if the SWQE is being resent. 95062306a36Sopenharmony_ci */ 95162306a36Sopenharmony_cistatic struct rvt_swqe *do_rc_completion(struct rvt_qp *qp, 95262306a36Sopenharmony_ci struct rvt_swqe *wqe, 95362306a36Sopenharmony_ci struct qib_ibport *ibp) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci /* 95662306a36Sopenharmony_ci * Don't decrement refcount and don't generate a 95762306a36Sopenharmony_ci * completion if the SWQE is being resent until the send 95862306a36Sopenharmony_ci * is finished. 95962306a36Sopenharmony_ci */ 96062306a36Sopenharmony_ci if (qib_cmp24(wqe->lpsn, qp->s_sending_psn) < 0 || 96162306a36Sopenharmony_ci qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) > 0) 96262306a36Sopenharmony_ci rvt_qp_complete_swqe(qp, 96362306a36Sopenharmony_ci wqe, 96462306a36Sopenharmony_ci ib_qib_wc_opcode[wqe->wr.opcode], 96562306a36Sopenharmony_ci IB_WC_SUCCESS); 96662306a36Sopenharmony_ci else 96762306a36Sopenharmony_ci this_cpu_inc(*ibp->rvp.rc_delayed_comp); 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 97062306a36Sopenharmony_ci update_last_psn(qp, wqe->lpsn); 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci /* 97362306a36Sopenharmony_ci * If we are completing a request which is in the process of 97462306a36Sopenharmony_ci * being resent, we can stop resending it since we know the 97562306a36Sopenharmony_ci * responder has already seen it. 97662306a36Sopenharmony_ci */ 97762306a36Sopenharmony_ci if (qp->s_acked == qp->s_cur) { 97862306a36Sopenharmony_ci if (++qp->s_cur >= qp->s_size) 97962306a36Sopenharmony_ci qp->s_cur = 0; 98062306a36Sopenharmony_ci qp->s_acked = qp->s_cur; 98162306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_cur); 98262306a36Sopenharmony_ci if (qp->s_acked != qp->s_tail) { 98362306a36Sopenharmony_ci qp->s_state = OP(SEND_LAST); 98462306a36Sopenharmony_ci qp->s_psn = wqe->psn; 98562306a36Sopenharmony_ci } 98662306a36Sopenharmony_ci } else { 98762306a36Sopenharmony_ci if (++qp->s_acked >= qp->s_size) 98862306a36Sopenharmony_ci qp->s_acked = 0; 98962306a36Sopenharmony_ci if (qp->state == IB_QPS_SQD && qp->s_acked == qp->s_cur) 99062306a36Sopenharmony_ci qp->s_draining = 0; 99162306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 99262306a36Sopenharmony_ci } 99362306a36Sopenharmony_ci return wqe; 99462306a36Sopenharmony_ci} 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci/* 99762306a36Sopenharmony_ci * do_rc_ack - process an incoming RC ACK 99862306a36Sopenharmony_ci * @qp: the QP the ACK came in on 99962306a36Sopenharmony_ci * @psn: the packet sequence number of the ACK 100062306a36Sopenharmony_ci * @opcode: the opcode of the request that resulted in the ACK 100162306a36Sopenharmony_ci * 100262306a36Sopenharmony_ci * This is called from qib_rc_rcv_resp() to process an incoming RC ACK 100362306a36Sopenharmony_ci * for the given QP. 100462306a36Sopenharmony_ci * Called at interrupt level with the QP s_lock held. 100562306a36Sopenharmony_ci * Returns 1 if OK, 0 if current operation should be aborted (NAK). 100662306a36Sopenharmony_ci */ 100762306a36Sopenharmony_cistatic int do_rc_ack(struct rvt_qp *qp, u32 aeth, u32 psn, int opcode, 100862306a36Sopenharmony_ci u64 val, struct qib_ctxtdata *rcd) 100962306a36Sopenharmony_ci{ 101062306a36Sopenharmony_ci struct qib_ibport *ibp; 101162306a36Sopenharmony_ci enum ib_wc_status status; 101262306a36Sopenharmony_ci struct rvt_swqe *wqe; 101362306a36Sopenharmony_ci int ret = 0; 101462306a36Sopenharmony_ci u32 ack_psn; 101562306a36Sopenharmony_ci int diff; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci /* 101862306a36Sopenharmony_ci * Note that NAKs implicitly ACK outstanding SEND and RDMA write 101962306a36Sopenharmony_ci * requests and implicitly NAK RDMA read and atomic requests issued 102062306a36Sopenharmony_ci * before the NAK'ed request. The MSN won't include the NAK'ed 102162306a36Sopenharmony_ci * request but will include an ACK'ed request(s). 102262306a36Sopenharmony_ci */ 102362306a36Sopenharmony_ci ack_psn = psn; 102462306a36Sopenharmony_ci if (aeth >> IB_AETH_NAK_SHIFT) 102562306a36Sopenharmony_ci ack_psn--; 102662306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 102762306a36Sopenharmony_ci ibp = to_iport(qp->ibqp.device, qp->port_num); 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci /* 103062306a36Sopenharmony_ci * The MSN might be for a later WQE than the PSN indicates so 103162306a36Sopenharmony_ci * only complete WQEs that the PSN finishes. 103262306a36Sopenharmony_ci */ 103362306a36Sopenharmony_ci while ((diff = qib_cmp24(ack_psn, wqe->lpsn)) >= 0) { 103462306a36Sopenharmony_ci /* 103562306a36Sopenharmony_ci * RDMA_READ_RESPONSE_ONLY is a special case since 103662306a36Sopenharmony_ci * we want to generate completion events for everything 103762306a36Sopenharmony_ci * before the RDMA read, copy the data, then generate 103862306a36Sopenharmony_ci * the completion for the read. 103962306a36Sopenharmony_ci */ 104062306a36Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ && 104162306a36Sopenharmony_ci opcode == OP(RDMA_READ_RESPONSE_ONLY) && 104262306a36Sopenharmony_ci diff == 0) { 104362306a36Sopenharmony_ci ret = 1; 104462306a36Sopenharmony_ci goto bail; 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci /* 104762306a36Sopenharmony_ci * If this request is a RDMA read or atomic, and the ACK is 104862306a36Sopenharmony_ci * for a later operation, this ACK NAKs the RDMA read or 104962306a36Sopenharmony_ci * atomic. In other words, only a RDMA_READ_LAST or ONLY 105062306a36Sopenharmony_ci * can ACK a RDMA read and likewise for atomic ops. Note 105162306a36Sopenharmony_ci * that the NAK case can only happen if relaxed ordering is 105262306a36Sopenharmony_ci * used and requests are sent after an RDMA read or atomic 105362306a36Sopenharmony_ci * is sent but before the response is received. 105462306a36Sopenharmony_ci */ 105562306a36Sopenharmony_ci if ((wqe->wr.opcode == IB_WR_RDMA_READ && 105662306a36Sopenharmony_ci (opcode != OP(RDMA_READ_RESPONSE_LAST) || diff != 0)) || 105762306a36Sopenharmony_ci ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 105862306a36Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) && 105962306a36Sopenharmony_ci (opcode != OP(ATOMIC_ACKNOWLEDGE) || diff != 0))) { 106062306a36Sopenharmony_ci /* Retry this request. */ 106162306a36Sopenharmony_ci if (!(qp->r_flags & RVT_R_RDMAR_SEQ)) { 106262306a36Sopenharmony_ci qp->r_flags |= RVT_R_RDMAR_SEQ; 106362306a36Sopenharmony_ci qib_restart_rc(qp, qp->s_last_psn + 1, 0); 106462306a36Sopenharmony_ci if (list_empty(&qp->rspwait)) { 106562306a36Sopenharmony_ci qp->r_flags |= RVT_R_RSP_SEND; 106662306a36Sopenharmony_ci rvt_get_qp(qp); 106762306a36Sopenharmony_ci list_add_tail(&qp->rspwait, 106862306a36Sopenharmony_ci &rcd->qp_wait_list); 106962306a36Sopenharmony_ci } 107062306a36Sopenharmony_ci } 107162306a36Sopenharmony_ci /* 107262306a36Sopenharmony_ci * No need to process the ACK/NAK since we are 107362306a36Sopenharmony_ci * restarting an earlier request. 107462306a36Sopenharmony_ci */ 107562306a36Sopenharmony_ci goto bail; 107662306a36Sopenharmony_ci } 107762306a36Sopenharmony_ci if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 107862306a36Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) { 107962306a36Sopenharmony_ci u64 *vaddr = wqe->sg_list[0].vaddr; 108062306a36Sopenharmony_ci *vaddr = val; 108162306a36Sopenharmony_ci } 108262306a36Sopenharmony_ci if (qp->s_num_rd_atomic && 108362306a36Sopenharmony_ci (wqe->wr.opcode == IB_WR_RDMA_READ || 108462306a36Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 108562306a36Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)) { 108662306a36Sopenharmony_ci qp->s_num_rd_atomic--; 108762306a36Sopenharmony_ci /* Restart sending task if fence is complete */ 108862306a36Sopenharmony_ci if ((qp->s_flags & RVT_S_WAIT_FENCE) && 108962306a36Sopenharmony_ci !qp->s_num_rd_atomic) { 109062306a36Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_FENCE | 109162306a36Sopenharmony_ci RVT_S_WAIT_ACK); 109262306a36Sopenharmony_ci qib_schedule_send(qp); 109362306a36Sopenharmony_ci } else if (qp->s_flags & RVT_S_WAIT_RDMAR) { 109462306a36Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_RDMAR | 109562306a36Sopenharmony_ci RVT_S_WAIT_ACK); 109662306a36Sopenharmony_ci qib_schedule_send(qp); 109762306a36Sopenharmony_ci } 109862306a36Sopenharmony_ci } 109962306a36Sopenharmony_ci wqe = do_rc_completion(qp, wqe, ibp); 110062306a36Sopenharmony_ci if (qp->s_acked == qp->s_tail) 110162306a36Sopenharmony_ci break; 110262306a36Sopenharmony_ci } 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci switch (aeth >> IB_AETH_NAK_SHIFT) { 110562306a36Sopenharmony_ci case 0: /* ACK */ 110662306a36Sopenharmony_ci this_cpu_inc(*ibp->rvp.rc_acks); 110762306a36Sopenharmony_ci if (qp->s_acked != qp->s_tail) { 110862306a36Sopenharmony_ci /* 110962306a36Sopenharmony_ci * We are expecting more ACKs so 111062306a36Sopenharmony_ci * reset the retransmit timer. 111162306a36Sopenharmony_ci */ 111262306a36Sopenharmony_ci rvt_mod_retry_timer(qp); 111362306a36Sopenharmony_ci /* 111462306a36Sopenharmony_ci * We can stop resending the earlier packets and 111562306a36Sopenharmony_ci * continue with the next packet the receiver wants. 111662306a36Sopenharmony_ci */ 111762306a36Sopenharmony_ci if (qib_cmp24(qp->s_psn, psn) <= 0) 111862306a36Sopenharmony_ci reset_psn(qp, psn + 1); 111962306a36Sopenharmony_ci } else { 112062306a36Sopenharmony_ci /* No more acks - kill all timers */ 112162306a36Sopenharmony_ci rvt_stop_rc_timers(qp); 112262306a36Sopenharmony_ci if (qib_cmp24(qp->s_psn, psn) <= 0) { 112362306a36Sopenharmony_ci qp->s_state = OP(SEND_LAST); 112462306a36Sopenharmony_ci qp->s_psn = psn + 1; 112562306a36Sopenharmony_ci } 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_ACK) { 112862306a36Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_ACK; 112962306a36Sopenharmony_ci qib_schedule_send(qp); 113062306a36Sopenharmony_ci } 113162306a36Sopenharmony_ci rvt_get_credit(qp, aeth); 113262306a36Sopenharmony_ci qp->s_rnr_retry = qp->s_rnr_retry_cnt; 113362306a36Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 113462306a36Sopenharmony_ci update_last_psn(qp, psn); 113562306a36Sopenharmony_ci return 1; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci case 1: /* RNR NAK */ 113862306a36Sopenharmony_ci ibp->rvp.n_rnr_naks++; 113962306a36Sopenharmony_ci if (qp->s_acked == qp->s_tail) 114062306a36Sopenharmony_ci goto bail; 114162306a36Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_RNR) 114262306a36Sopenharmony_ci goto bail; 114362306a36Sopenharmony_ci if (qp->s_rnr_retry == 0) { 114462306a36Sopenharmony_ci status = IB_WC_RNR_RETRY_EXC_ERR; 114562306a36Sopenharmony_ci goto class_b; 114662306a36Sopenharmony_ci } 114762306a36Sopenharmony_ci if (qp->s_rnr_retry_cnt < 7) 114862306a36Sopenharmony_ci qp->s_rnr_retry--; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci /* The last valid PSN is the previous PSN. */ 115162306a36Sopenharmony_ci update_last_psn(qp, psn - 1); 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci ibp->rvp.n_rc_resends += (qp->s_psn - psn) & QIB_PSN_MASK; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci reset_psn(qp, psn); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci qp->s_flags &= ~(RVT_S_WAIT_SSN_CREDIT | RVT_S_WAIT_ACK); 115862306a36Sopenharmony_ci rvt_stop_rc_timers(qp); 115962306a36Sopenharmony_ci rvt_add_rnr_timer(qp, aeth); 116062306a36Sopenharmony_ci return 0; 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci case 3: /* NAK */ 116362306a36Sopenharmony_ci if (qp->s_acked == qp->s_tail) 116462306a36Sopenharmony_ci goto bail; 116562306a36Sopenharmony_ci /* The last valid PSN is the previous PSN. */ 116662306a36Sopenharmony_ci update_last_psn(qp, psn - 1); 116762306a36Sopenharmony_ci switch ((aeth >> IB_AETH_CREDIT_SHIFT) & 116862306a36Sopenharmony_ci IB_AETH_CREDIT_MASK) { 116962306a36Sopenharmony_ci case 0: /* PSN sequence error */ 117062306a36Sopenharmony_ci ibp->rvp.n_seq_naks++; 117162306a36Sopenharmony_ci /* 117262306a36Sopenharmony_ci * Back up to the responder's expected PSN. 117362306a36Sopenharmony_ci * Note that we might get a NAK in the middle of an 117462306a36Sopenharmony_ci * RDMA READ response which terminates the RDMA 117562306a36Sopenharmony_ci * READ. 117662306a36Sopenharmony_ci */ 117762306a36Sopenharmony_ci qib_restart_rc(qp, psn, 0); 117862306a36Sopenharmony_ci qib_schedule_send(qp); 117962306a36Sopenharmony_ci break; 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci case 1: /* Invalid Request */ 118262306a36Sopenharmony_ci status = IB_WC_REM_INV_REQ_ERR; 118362306a36Sopenharmony_ci ibp->rvp.n_other_naks++; 118462306a36Sopenharmony_ci goto class_b; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci case 2: /* Remote Access Error */ 118762306a36Sopenharmony_ci status = IB_WC_REM_ACCESS_ERR; 118862306a36Sopenharmony_ci ibp->rvp.n_other_naks++; 118962306a36Sopenharmony_ci goto class_b; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci case 3: /* Remote Operation Error */ 119262306a36Sopenharmony_ci status = IB_WC_REM_OP_ERR; 119362306a36Sopenharmony_ci ibp->rvp.n_other_naks++; 119462306a36Sopenharmony_ciclass_b: 119562306a36Sopenharmony_ci if (qp->s_last == qp->s_acked) { 119662306a36Sopenharmony_ci rvt_send_complete(qp, wqe, status); 119762306a36Sopenharmony_ci rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 119862306a36Sopenharmony_ci } 119962306a36Sopenharmony_ci break; 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci default: 120262306a36Sopenharmony_ci /* Ignore other reserved NAK error codes */ 120362306a36Sopenharmony_ci goto reserved; 120462306a36Sopenharmony_ci } 120562306a36Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 120662306a36Sopenharmony_ci qp->s_rnr_retry = qp->s_rnr_retry_cnt; 120762306a36Sopenharmony_ci goto bail; 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci default: /* 2: reserved */ 121062306a36Sopenharmony_cireserved: 121162306a36Sopenharmony_ci /* Ignore reserved NAK codes. */ 121262306a36Sopenharmony_ci goto bail; 121362306a36Sopenharmony_ci } 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_cibail: 121662306a36Sopenharmony_ci rvt_stop_rc_timers(qp); 121762306a36Sopenharmony_ci return ret; 121862306a36Sopenharmony_ci} 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci/* 122162306a36Sopenharmony_ci * We have seen an out of sequence RDMA read middle or last packet. 122262306a36Sopenharmony_ci * This ACKs SENDs and RDMA writes up to the first RDMA read or atomic SWQE. 122362306a36Sopenharmony_ci */ 122462306a36Sopenharmony_cistatic void rdma_seq_err(struct rvt_qp *qp, struct qib_ibport *ibp, u32 psn, 122562306a36Sopenharmony_ci struct qib_ctxtdata *rcd) 122662306a36Sopenharmony_ci{ 122762306a36Sopenharmony_ci struct rvt_swqe *wqe; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci /* Remove QP from retry timer */ 123062306a36Sopenharmony_ci rvt_stop_rc_timers(qp); 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci while (qib_cmp24(psn, wqe->lpsn) > 0) { 123562306a36Sopenharmony_ci if (wqe->wr.opcode == IB_WR_RDMA_READ || 123662306a36Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || 123762306a36Sopenharmony_ci wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) 123862306a36Sopenharmony_ci break; 123962306a36Sopenharmony_ci wqe = do_rc_completion(qp, wqe, ibp); 124062306a36Sopenharmony_ci } 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci ibp->rvp.n_rdma_seq++; 124362306a36Sopenharmony_ci qp->r_flags |= RVT_R_RDMAR_SEQ; 124462306a36Sopenharmony_ci qib_restart_rc(qp, qp->s_last_psn + 1, 0); 124562306a36Sopenharmony_ci if (list_empty(&qp->rspwait)) { 124662306a36Sopenharmony_ci qp->r_flags |= RVT_R_RSP_SEND; 124762306a36Sopenharmony_ci rvt_get_qp(qp); 124862306a36Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 124962306a36Sopenharmony_ci } 125062306a36Sopenharmony_ci} 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci/** 125362306a36Sopenharmony_ci * qib_rc_rcv_resp - process an incoming RC response packet 125462306a36Sopenharmony_ci * @ibp: the port this packet came in on 125562306a36Sopenharmony_ci * @ohdr: the other headers for this packet 125662306a36Sopenharmony_ci * @data: the packet data 125762306a36Sopenharmony_ci * @tlen: the packet length 125862306a36Sopenharmony_ci * @qp: the QP for this packet 125962306a36Sopenharmony_ci * @opcode: the opcode for this packet 126062306a36Sopenharmony_ci * @psn: the packet sequence number for this packet 126162306a36Sopenharmony_ci * @hdrsize: the header length 126262306a36Sopenharmony_ci * @pmtu: the path MTU 126362306a36Sopenharmony_ci * @rcd: the context pointer 126462306a36Sopenharmony_ci * 126562306a36Sopenharmony_ci * This is called from qib_rc_rcv() to process an incoming RC response 126662306a36Sopenharmony_ci * packet for the given QP. 126762306a36Sopenharmony_ci * Called at interrupt level. 126862306a36Sopenharmony_ci */ 126962306a36Sopenharmony_cistatic void qib_rc_rcv_resp(struct qib_ibport *ibp, 127062306a36Sopenharmony_ci struct ib_other_headers *ohdr, 127162306a36Sopenharmony_ci void *data, u32 tlen, 127262306a36Sopenharmony_ci struct rvt_qp *qp, 127362306a36Sopenharmony_ci u32 opcode, 127462306a36Sopenharmony_ci u32 psn, u32 hdrsize, u32 pmtu, 127562306a36Sopenharmony_ci struct qib_ctxtdata *rcd) 127662306a36Sopenharmony_ci{ 127762306a36Sopenharmony_ci struct rvt_swqe *wqe; 127862306a36Sopenharmony_ci struct qib_pportdata *ppd = ppd_from_ibp(ibp); 127962306a36Sopenharmony_ci enum ib_wc_status status; 128062306a36Sopenharmony_ci unsigned long flags; 128162306a36Sopenharmony_ci int diff; 128262306a36Sopenharmony_ci u32 pad; 128362306a36Sopenharmony_ci u32 aeth; 128462306a36Sopenharmony_ci u64 val; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci if (opcode != OP(RDMA_READ_RESPONSE_MIDDLE)) { 128762306a36Sopenharmony_ci /* 128862306a36Sopenharmony_ci * If ACK'd PSN on SDMA busy list try to make progress to 128962306a36Sopenharmony_ci * reclaim SDMA credits. 129062306a36Sopenharmony_ci */ 129162306a36Sopenharmony_ci if ((qib_cmp24(psn, qp->s_sending_psn) >= 0) && 129262306a36Sopenharmony_ci (qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)) { 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci /* 129562306a36Sopenharmony_ci * If send tasklet not running attempt to progress 129662306a36Sopenharmony_ci * SDMA queue. 129762306a36Sopenharmony_ci */ 129862306a36Sopenharmony_ci if (!(qp->s_flags & RVT_S_BUSY)) { 129962306a36Sopenharmony_ci /* Acquire SDMA Lock */ 130062306a36Sopenharmony_ci spin_lock_irqsave(&ppd->sdma_lock, flags); 130162306a36Sopenharmony_ci /* Invoke sdma make progress */ 130262306a36Sopenharmony_ci qib_sdma_make_progress(ppd); 130362306a36Sopenharmony_ci /* Release SDMA Lock */ 130462306a36Sopenharmony_ci spin_unlock_irqrestore(&ppd->sdma_lock, flags); 130562306a36Sopenharmony_ci } 130662306a36Sopenharmony_ci } 130762306a36Sopenharmony_ci } 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 131062306a36Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK)) 131162306a36Sopenharmony_ci goto ack_done; 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci /* Ignore invalid responses. */ 131462306a36Sopenharmony_ci if (qib_cmp24(psn, READ_ONCE(qp->s_next_psn)) >= 0) 131562306a36Sopenharmony_ci goto ack_done; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci /* Ignore duplicate responses. */ 131862306a36Sopenharmony_ci diff = qib_cmp24(psn, qp->s_last_psn); 131962306a36Sopenharmony_ci if (unlikely(diff <= 0)) { 132062306a36Sopenharmony_ci /* Update credits for "ghost" ACKs */ 132162306a36Sopenharmony_ci if (diff == 0 && opcode == OP(ACKNOWLEDGE)) { 132262306a36Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 132362306a36Sopenharmony_ci if ((aeth >> IB_AETH_NAK_SHIFT) == 0) 132462306a36Sopenharmony_ci rvt_get_credit(qp, aeth); 132562306a36Sopenharmony_ci } 132662306a36Sopenharmony_ci goto ack_done; 132762306a36Sopenharmony_ci } 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci /* 133062306a36Sopenharmony_ci * Skip everything other than the PSN we expect, if we are waiting 133162306a36Sopenharmony_ci * for a reply to a restarted RDMA read or atomic op. 133262306a36Sopenharmony_ci */ 133362306a36Sopenharmony_ci if (qp->r_flags & RVT_R_RDMAR_SEQ) { 133462306a36Sopenharmony_ci if (qib_cmp24(psn, qp->s_last_psn + 1) != 0) 133562306a36Sopenharmony_ci goto ack_done; 133662306a36Sopenharmony_ci qp->r_flags &= ~RVT_R_RDMAR_SEQ; 133762306a36Sopenharmony_ci } 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci if (unlikely(qp->s_acked == qp->s_tail)) 134062306a36Sopenharmony_ci goto ack_done; 134162306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 134262306a36Sopenharmony_ci status = IB_WC_SUCCESS; 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci switch (opcode) { 134562306a36Sopenharmony_ci case OP(ACKNOWLEDGE): 134662306a36Sopenharmony_ci case OP(ATOMIC_ACKNOWLEDGE): 134762306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_FIRST): 134862306a36Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 134962306a36Sopenharmony_ci if (opcode == OP(ATOMIC_ACKNOWLEDGE)) 135062306a36Sopenharmony_ci val = ib_u64_get(&ohdr->u.at.atomic_ack_eth); 135162306a36Sopenharmony_ci else 135262306a36Sopenharmony_ci val = 0; 135362306a36Sopenharmony_ci if (!do_rc_ack(qp, aeth, psn, opcode, val, rcd) || 135462306a36Sopenharmony_ci opcode != OP(RDMA_READ_RESPONSE_FIRST)) 135562306a36Sopenharmony_ci goto ack_done; 135662306a36Sopenharmony_ci hdrsize += 4; 135762306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 135862306a36Sopenharmony_ci if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) 135962306a36Sopenharmony_ci goto ack_op_err; 136062306a36Sopenharmony_ci /* 136162306a36Sopenharmony_ci * If this is a response to a resent RDMA read, we 136262306a36Sopenharmony_ci * have to be careful to copy the data to the right 136362306a36Sopenharmony_ci * location. 136462306a36Sopenharmony_ci */ 136562306a36Sopenharmony_ci qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge, 136662306a36Sopenharmony_ci wqe, psn, pmtu); 136762306a36Sopenharmony_ci goto read_middle; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_MIDDLE): 137062306a36Sopenharmony_ci /* no AETH, no ACK */ 137162306a36Sopenharmony_ci if (unlikely(qib_cmp24(psn, qp->s_last_psn + 1))) 137262306a36Sopenharmony_ci goto ack_seq_err; 137362306a36Sopenharmony_ci if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) 137462306a36Sopenharmony_ci goto ack_op_err; 137562306a36Sopenharmony_ciread_middle: 137662306a36Sopenharmony_ci if (unlikely(tlen != (hdrsize + pmtu + 4))) 137762306a36Sopenharmony_ci goto ack_len_err; 137862306a36Sopenharmony_ci if (unlikely(pmtu >= qp->s_rdma_read_len)) 137962306a36Sopenharmony_ci goto ack_len_err; 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci /* 138262306a36Sopenharmony_ci * We got a response so update the timeout. 138362306a36Sopenharmony_ci * 4.096 usec. * (1 << qp->timeout) 138462306a36Sopenharmony_ci */ 138562306a36Sopenharmony_ci rvt_mod_retry_timer(qp); 138662306a36Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_ACK) { 138762306a36Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_ACK; 138862306a36Sopenharmony_ci qib_schedule_send(qp); 138962306a36Sopenharmony_ci } 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci if (opcode == OP(RDMA_READ_RESPONSE_MIDDLE)) 139262306a36Sopenharmony_ci qp->s_retry = qp->s_retry_cnt; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci /* 139562306a36Sopenharmony_ci * Update the RDMA receive state but do the copy w/o 139662306a36Sopenharmony_ci * holding the locks and blocking interrupts. 139762306a36Sopenharmony_ci */ 139862306a36Sopenharmony_ci qp->s_rdma_read_len -= pmtu; 139962306a36Sopenharmony_ci update_last_psn(qp, psn); 140062306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 140162306a36Sopenharmony_ci rvt_copy_sge(qp, &qp->s_rdma_read_sge, 140262306a36Sopenharmony_ci data, pmtu, false, false); 140362306a36Sopenharmony_ci goto bail; 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_ONLY): 140662306a36Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 140762306a36Sopenharmony_ci if (!do_rc_ack(qp, aeth, psn, opcode, 0, rcd)) 140862306a36Sopenharmony_ci goto ack_done; 140962306a36Sopenharmony_ci /* Get the number of bytes the message was padded by. */ 141062306a36Sopenharmony_ci pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; 141162306a36Sopenharmony_ci /* 141262306a36Sopenharmony_ci * Check that the data size is >= 0 && <= pmtu. 141362306a36Sopenharmony_ci * Remember to account for the AETH header (4) and 141462306a36Sopenharmony_ci * ICRC (4). 141562306a36Sopenharmony_ci */ 141662306a36Sopenharmony_ci if (unlikely(tlen < (hdrsize + pad + 8))) 141762306a36Sopenharmony_ci goto ack_len_err; 141862306a36Sopenharmony_ci /* 141962306a36Sopenharmony_ci * If this is a response to a resent RDMA read, we 142062306a36Sopenharmony_ci * have to be careful to copy the data to the right 142162306a36Sopenharmony_ci * location. 142262306a36Sopenharmony_ci */ 142362306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_acked); 142462306a36Sopenharmony_ci qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge, 142562306a36Sopenharmony_ci wqe, psn, pmtu); 142662306a36Sopenharmony_ci goto read_last; 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci case OP(RDMA_READ_RESPONSE_LAST): 142962306a36Sopenharmony_ci /* ACKs READ req. */ 143062306a36Sopenharmony_ci if (unlikely(qib_cmp24(psn, qp->s_last_psn + 1))) 143162306a36Sopenharmony_ci goto ack_seq_err; 143262306a36Sopenharmony_ci if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) 143362306a36Sopenharmony_ci goto ack_op_err; 143462306a36Sopenharmony_ci /* Get the number of bytes the message was padded by. */ 143562306a36Sopenharmony_ci pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; 143662306a36Sopenharmony_ci /* 143762306a36Sopenharmony_ci * Check that the data size is >= 1 && <= pmtu. 143862306a36Sopenharmony_ci * Remember to account for the AETH header (4) and 143962306a36Sopenharmony_ci * ICRC (4). 144062306a36Sopenharmony_ci */ 144162306a36Sopenharmony_ci if (unlikely(tlen <= (hdrsize + pad + 8))) 144262306a36Sopenharmony_ci goto ack_len_err; 144362306a36Sopenharmony_ciread_last: 144462306a36Sopenharmony_ci tlen -= hdrsize + pad + 8; 144562306a36Sopenharmony_ci if (unlikely(tlen != qp->s_rdma_read_len)) 144662306a36Sopenharmony_ci goto ack_len_err; 144762306a36Sopenharmony_ci aeth = be32_to_cpu(ohdr->u.aeth); 144862306a36Sopenharmony_ci rvt_copy_sge(qp, &qp->s_rdma_read_sge, 144962306a36Sopenharmony_ci data, tlen, false, false); 145062306a36Sopenharmony_ci WARN_ON(qp->s_rdma_read_sge.num_sge); 145162306a36Sopenharmony_ci (void) do_rc_ack(qp, aeth, psn, 145262306a36Sopenharmony_ci OP(RDMA_READ_RESPONSE_LAST), 0, rcd); 145362306a36Sopenharmony_ci goto ack_done; 145462306a36Sopenharmony_ci } 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ciack_op_err: 145762306a36Sopenharmony_ci status = IB_WC_LOC_QP_OP_ERR; 145862306a36Sopenharmony_ci goto ack_err; 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ciack_seq_err: 146162306a36Sopenharmony_ci rdma_seq_err(qp, ibp, psn, rcd); 146262306a36Sopenharmony_ci goto ack_done; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ciack_len_err: 146562306a36Sopenharmony_ci status = IB_WC_LOC_LEN_ERR; 146662306a36Sopenharmony_ciack_err: 146762306a36Sopenharmony_ci if (qp->s_last == qp->s_acked) { 146862306a36Sopenharmony_ci rvt_send_complete(qp, wqe, status); 146962306a36Sopenharmony_ci rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 147062306a36Sopenharmony_ci } 147162306a36Sopenharmony_ciack_done: 147262306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 147362306a36Sopenharmony_cibail: 147462306a36Sopenharmony_ci return; 147562306a36Sopenharmony_ci} 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_ci/** 147862306a36Sopenharmony_ci * qib_rc_rcv_error - process an incoming duplicate or error RC packet 147962306a36Sopenharmony_ci * @ohdr: the other headers for this packet 148062306a36Sopenharmony_ci * @data: the packet data 148162306a36Sopenharmony_ci * @qp: the QP for this packet 148262306a36Sopenharmony_ci * @opcode: the opcode for this packet 148362306a36Sopenharmony_ci * @psn: the packet sequence number for this packet 148462306a36Sopenharmony_ci * @diff: the difference between the PSN and the expected PSN 148562306a36Sopenharmony_ci * @rcd: the context pointer 148662306a36Sopenharmony_ci * 148762306a36Sopenharmony_ci * This is called from qib_rc_rcv() to process an unexpected 148862306a36Sopenharmony_ci * incoming RC packet for the given QP. 148962306a36Sopenharmony_ci * Called at interrupt level. 149062306a36Sopenharmony_ci * Return 1 if no more processing is needed; otherwise return 0 to 149162306a36Sopenharmony_ci * schedule a response to be sent. 149262306a36Sopenharmony_ci */ 149362306a36Sopenharmony_cistatic int qib_rc_rcv_error(struct ib_other_headers *ohdr, 149462306a36Sopenharmony_ci void *data, 149562306a36Sopenharmony_ci struct rvt_qp *qp, 149662306a36Sopenharmony_ci u32 opcode, 149762306a36Sopenharmony_ci u32 psn, 149862306a36Sopenharmony_ci int diff, 149962306a36Sopenharmony_ci struct qib_ctxtdata *rcd) 150062306a36Sopenharmony_ci{ 150162306a36Sopenharmony_ci struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); 150262306a36Sopenharmony_ci struct rvt_ack_entry *e; 150362306a36Sopenharmony_ci unsigned long flags; 150462306a36Sopenharmony_ci u8 i, prev; 150562306a36Sopenharmony_ci int old_req; 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci if (diff > 0) { 150862306a36Sopenharmony_ci /* 150962306a36Sopenharmony_ci * Packet sequence error. 151062306a36Sopenharmony_ci * A NAK will ACK earlier sends and RDMA writes. 151162306a36Sopenharmony_ci * Don't queue the NAK if we already sent one. 151262306a36Sopenharmony_ci */ 151362306a36Sopenharmony_ci if (!qp->r_nak_state) { 151462306a36Sopenharmony_ci ibp->rvp.n_rc_seqnak++; 151562306a36Sopenharmony_ci qp->r_nak_state = IB_NAK_PSN_ERROR; 151662306a36Sopenharmony_ci /* Use the expected PSN. */ 151762306a36Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 151862306a36Sopenharmony_ci /* 151962306a36Sopenharmony_ci * Wait to send the sequence NAK until all packets 152062306a36Sopenharmony_ci * in the receive queue have been processed. 152162306a36Sopenharmony_ci * Otherwise, we end up propagating congestion. 152262306a36Sopenharmony_ci */ 152362306a36Sopenharmony_ci if (list_empty(&qp->rspwait)) { 152462306a36Sopenharmony_ci qp->r_flags |= RVT_R_RSP_NAK; 152562306a36Sopenharmony_ci rvt_get_qp(qp); 152662306a36Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 152762306a36Sopenharmony_ci } 152862306a36Sopenharmony_ci } 152962306a36Sopenharmony_ci goto done; 153062306a36Sopenharmony_ci } 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci /* 153362306a36Sopenharmony_ci * Handle a duplicate request. Don't re-execute SEND, RDMA 153462306a36Sopenharmony_ci * write or atomic op. Don't NAK errors, just silently drop 153562306a36Sopenharmony_ci * the duplicate request. Note that r_sge, r_len, and 153662306a36Sopenharmony_ci * r_rcv_len may be in use so don't modify them. 153762306a36Sopenharmony_ci * 153862306a36Sopenharmony_ci * We are supposed to ACK the earliest duplicate PSN but we 153962306a36Sopenharmony_ci * can coalesce an outstanding duplicate ACK. We have to 154062306a36Sopenharmony_ci * send the earliest so that RDMA reads can be restarted at 154162306a36Sopenharmony_ci * the requester's expected PSN. 154262306a36Sopenharmony_ci * 154362306a36Sopenharmony_ci * First, find where this duplicate PSN falls within the 154462306a36Sopenharmony_ci * ACKs previously sent. 154562306a36Sopenharmony_ci * old_req is true if there is an older response that is scheduled 154662306a36Sopenharmony_ci * to be sent before sending this one. 154762306a36Sopenharmony_ci */ 154862306a36Sopenharmony_ci e = NULL; 154962306a36Sopenharmony_ci old_req = 1; 155062306a36Sopenharmony_ci ibp->rvp.n_rc_dupreq++; 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci for (i = qp->r_head_ack_queue; ; i = prev) { 155562306a36Sopenharmony_ci if (i == qp->s_tail_ack_queue) 155662306a36Sopenharmony_ci old_req = 0; 155762306a36Sopenharmony_ci if (i) 155862306a36Sopenharmony_ci prev = i - 1; 155962306a36Sopenharmony_ci else 156062306a36Sopenharmony_ci prev = QIB_MAX_RDMA_ATOMIC; 156162306a36Sopenharmony_ci if (prev == qp->r_head_ack_queue) { 156262306a36Sopenharmony_ci e = NULL; 156362306a36Sopenharmony_ci break; 156462306a36Sopenharmony_ci } 156562306a36Sopenharmony_ci e = &qp->s_ack_queue[prev]; 156662306a36Sopenharmony_ci if (!e->opcode) { 156762306a36Sopenharmony_ci e = NULL; 156862306a36Sopenharmony_ci break; 156962306a36Sopenharmony_ci } 157062306a36Sopenharmony_ci if (qib_cmp24(psn, e->psn) >= 0) { 157162306a36Sopenharmony_ci if (prev == qp->s_tail_ack_queue && 157262306a36Sopenharmony_ci qib_cmp24(psn, e->lpsn) <= 0) 157362306a36Sopenharmony_ci old_req = 0; 157462306a36Sopenharmony_ci break; 157562306a36Sopenharmony_ci } 157662306a36Sopenharmony_ci } 157762306a36Sopenharmony_ci switch (opcode) { 157862306a36Sopenharmony_ci case OP(RDMA_READ_REQUEST): { 157962306a36Sopenharmony_ci struct ib_reth *reth; 158062306a36Sopenharmony_ci u32 offset; 158162306a36Sopenharmony_ci u32 len; 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci /* 158462306a36Sopenharmony_ci * If we didn't find the RDMA read request in the ack queue, 158562306a36Sopenharmony_ci * we can ignore this request. 158662306a36Sopenharmony_ci */ 158762306a36Sopenharmony_ci if (!e || e->opcode != OP(RDMA_READ_REQUEST)) 158862306a36Sopenharmony_ci goto unlock_done; 158962306a36Sopenharmony_ci /* RETH comes after BTH */ 159062306a36Sopenharmony_ci reth = &ohdr->u.rc.reth; 159162306a36Sopenharmony_ci /* 159262306a36Sopenharmony_ci * Address range must be a subset of the original 159362306a36Sopenharmony_ci * request and start on pmtu boundaries. 159462306a36Sopenharmony_ci * We reuse the old ack_queue slot since the requester 159562306a36Sopenharmony_ci * should not back up and request an earlier PSN for the 159662306a36Sopenharmony_ci * same request. 159762306a36Sopenharmony_ci */ 159862306a36Sopenharmony_ci offset = ((psn - e->psn) & QIB_PSN_MASK) * 159962306a36Sopenharmony_ci qp->pmtu; 160062306a36Sopenharmony_ci len = be32_to_cpu(reth->length); 160162306a36Sopenharmony_ci if (unlikely(offset + len != e->rdma_sge.sge_length)) 160262306a36Sopenharmony_ci goto unlock_done; 160362306a36Sopenharmony_ci if (e->rdma_sge.mr) { 160462306a36Sopenharmony_ci rvt_put_mr(e->rdma_sge.mr); 160562306a36Sopenharmony_ci e->rdma_sge.mr = NULL; 160662306a36Sopenharmony_ci } 160762306a36Sopenharmony_ci if (len != 0) { 160862306a36Sopenharmony_ci u32 rkey = be32_to_cpu(reth->rkey); 160962306a36Sopenharmony_ci u64 vaddr = be64_to_cpu(reth->vaddr); 161062306a36Sopenharmony_ci int ok; 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci ok = rvt_rkey_ok(qp, &e->rdma_sge, len, vaddr, rkey, 161362306a36Sopenharmony_ci IB_ACCESS_REMOTE_READ); 161462306a36Sopenharmony_ci if (unlikely(!ok)) 161562306a36Sopenharmony_ci goto unlock_done; 161662306a36Sopenharmony_ci } else { 161762306a36Sopenharmony_ci e->rdma_sge.vaddr = NULL; 161862306a36Sopenharmony_ci e->rdma_sge.length = 0; 161962306a36Sopenharmony_ci e->rdma_sge.sge_length = 0; 162062306a36Sopenharmony_ci } 162162306a36Sopenharmony_ci e->psn = psn; 162262306a36Sopenharmony_ci if (old_req) 162362306a36Sopenharmony_ci goto unlock_done; 162462306a36Sopenharmony_ci qp->s_tail_ack_queue = prev; 162562306a36Sopenharmony_ci break; 162662306a36Sopenharmony_ci } 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci case OP(COMPARE_SWAP): 162962306a36Sopenharmony_ci case OP(FETCH_ADD): { 163062306a36Sopenharmony_ci /* 163162306a36Sopenharmony_ci * If we didn't find the atomic request in the ack queue 163262306a36Sopenharmony_ci * or the send tasklet is already backed up to send an 163362306a36Sopenharmony_ci * earlier entry, we can ignore this request. 163462306a36Sopenharmony_ci */ 163562306a36Sopenharmony_ci if (!e || e->opcode != (u8) opcode || old_req) 163662306a36Sopenharmony_ci goto unlock_done; 163762306a36Sopenharmony_ci qp->s_tail_ack_queue = prev; 163862306a36Sopenharmony_ci break; 163962306a36Sopenharmony_ci } 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ci default: 164262306a36Sopenharmony_ci /* 164362306a36Sopenharmony_ci * Ignore this operation if it doesn't request an ACK 164462306a36Sopenharmony_ci * or an earlier RDMA read or atomic is going to be resent. 164562306a36Sopenharmony_ci */ 164662306a36Sopenharmony_ci if (!(psn & IB_BTH_REQ_ACK) || old_req) 164762306a36Sopenharmony_ci goto unlock_done; 164862306a36Sopenharmony_ci /* 164962306a36Sopenharmony_ci * Resend the most recent ACK if this request is 165062306a36Sopenharmony_ci * after all the previous RDMA reads and atomics. 165162306a36Sopenharmony_ci */ 165262306a36Sopenharmony_ci if (i == qp->r_head_ack_queue) { 165362306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 165462306a36Sopenharmony_ci qp->r_nak_state = 0; 165562306a36Sopenharmony_ci qp->r_ack_psn = qp->r_psn - 1; 165662306a36Sopenharmony_ci goto send_ack; 165762306a36Sopenharmony_ci } 165862306a36Sopenharmony_ci /* 165962306a36Sopenharmony_ci * Try to send a simple ACK to work around a Mellanox bug 166062306a36Sopenharmony_ci * which doesn't accept a RDMA read response or atomic 166162306a36Sopenharmony_ci * response as an ACK for earlier SENDs or RDMA writes. 166262306a36Sopenharmony_ci */ 166362306a36Sopenharmony_ci if (!(qp->s_flags & RVT_S_RESP_PENDING)) { 166462306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 166562306a36Sopenharmony_ci qp->r_nak_state = 0; 166662306a36Sopenharmony_ci qp->r_ack_psn = qp->s_ack_queue[i].psn - 1; 166762306a36Sopenharmony_ci goto send_ack; 166862306a36Sopenharmony_ci } 166962306a36Sopenharmony_ci /* 167062306a36Sopenharmony_ci * Resend the RDMA read or atomic op which 167162306a36Sopenharmony_ci * ACKs this duplicate request. 167262306a36Sopenharmony_ci */ 167362306a36Sopenharmony_ci qp->s_tail_ack_queue = i; 167462306a36Sopenharmony_ci break; 167562306a36Sopenharmony_ci } 167662306a36Sopenharmony_ci qp->s_ack_state = OP(ACKNOWLEDGE); 167762306a36Sopenharmony_ci qp->s_flags |= RVT_S_RESP_PENDING; 167862306a36Sopenharmony_ci qp->r_nak_state = 0; 167962306a36Sopenharmony_ci qib_schedule_send(qp); 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ciunlock_done: 168262306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 168362306a36Sopenharmony_cidone: 168462306a36Sopenharmony_ci return 1; 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_cisend_ack: 168762306a36Sopenharmony_ci return 0; 168862306a36Sopenharmony_ci} 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_cistatic inline void qib_update_ack_queue(struct rvt_qp *qp, unsigned n) 169162306a36Sopenharmony_ci{ 169262306a36Sopenharmony_ci unsigned next; 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci next = n + 1; 169562306a36Sopenharmony_ci if (next > QIB_MAX_RDMA_ATOMIC) 169662306a36Sopenharmony_ci next = 0; 169762306a36Sopenharmony_ci qp->s_tail_ack_queue = next; 169862306a36Sopenharmony_ci qp->s_ack_state = OP(ACKNOWLEDGE); 169962306a36Sopenharmony_ci} 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_ci/** 170262306a36Sopenharmony_ci * qib_rc_rcv - process an incoming RC packet 170362306a36Sopenharmony_ci * @rcd: the context pointer 170462306a36Sopenharmony_ci * @hdr: the header of this packet 170562306a36Sopenharmony_ci * @has_grh: true if the header has a GRH 170662306a36Sopenharmony_ci * @data: the packet data 170762306a36Sopenharmony_ci * @tlen: the packet length 170862306a36Sopenharmony_ci * @qp: the QP for this packet 170962306a36Sopenharmony_ci * 171062306a36Sopenharmony_ci * This is called from qib_qp_rcv() to process an incoming RC packet 171162306a36Sopenharmony_ci * for the given QP. 171262306a36Sopenharmony_ci * Called at interrupt level. 171362306a36Sopenharmony_ci */ 171462306a36Sopenharmony_civoid qib_rc_rcv(struct qib_ctxtdata *rcd, struct ib_header *hdr, 171562306a36Sopenharmony_ci int has_grh, void *data, u32 tlen, struct rvt_qp *qp) 171662306a36Sopenharmony_ci{ 171762306a36Sopenharmony_ci struct qib_ibport *ibp = &rcd->ppd->ibport_data; 171862306a36Sopenharmony_ci struct ib_other_headers *ohdr; 171962306a36Sopenharmony_ci u32 opcode; 172062306a36Sopenharmony_ci u32 hdrsize; 172162306a36Sopenharmony_ci u32 psn; 172262306a36Sopenharmony_ci u32 pad; 172362306a36Sopenharmony_ci struct ib_wc wc; 172462306a36Sopenharmony_ci u32 pmtu = qp->pmtu; 172562306a36Sopenharmony_ci int diff; 172662306a36Sopenharmony_ci struct ib_reth *reth; 172762306a36Sopenharmony_ci unsigned long flags; 172862306a36Sopenharmony_ci int ret; 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci /* Check for GRH */ 173162306a36Sopenharmony_ci if (!has_grh) { 173262306a36Sopenharmony_ci ohdr = &hdr->u.oth; 173362306a36Sopenharmony_ci hdrsize = 8 + 12; /* LRH + BTH */ 173462306a36Sopenharmony_ci } else { 173562306a36Sopenharmony_ci ohdr = &hdr->u.l.oth; 173662306a36Sopenharmony_ci hdrsize = 8 + 40 + 12; /* LRH + GRH + BTH */ 173762306a36Sopenharmony_ci } 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci opcode = be32_to_cpu(ohdr->bth[0]); 174062306a36Sopenharmony_ci if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode)) 174162306a36Sopenharmony_ci return; 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci psn = be32_to_cpu(ohdr->bth[2]); 174462306a36Sopenharmony_ci opcode >>= 24; 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci /* 174762306a36Sopenharmony_ci * Process responses (ACKs) before anything else. Note that the 174862306a36Sopenharmony_ci * packet sequence number will be for something in the send work 174962306a36Sopenharmony_ci * queue rather than the expected receive packet sequence number. 175062306a36Sopenharmony_ci * In other words, this QP is the requester. 175162306a36Sopenharmony_ci */ 175262306a36Sopenharmony_ci if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) && 175362306a36Sopenharmony_ci opcode <= OP(ATOMIC_ACKNOWLEDGE)) { 175462306a36Sopenharmony_ci qib_rc_rcv_resp(ibp, ohdr, data, tlen, qp, opcode, psn, 175562306a36Sopenharmony_ci hdrsize, pmtu, rcd); 175662306a36Sopenharmony_ci return; 175762306a36Sopenharmony_ci } 175862306a36Sopenharmony_ci 175962306a36Sopenharmony_ci /* Compute 24 bits worth of difference. */ 176062306a36Sopenharmony_ci diff = qib_cmp24(psn, qp->r_psn); 176162306a36Sopenharmony_ci if (unlikely(diff)) { 176262306a36Sopenharmony_ci if (qib_rc_rcv_error(ohdr, data, qp, opcode, psn, diff, rcd)) 176362306a36Sopenharmony_ci return; 176462306a36Sopenharmony_ci goto send_ack; 176562306a36Sopenharmony_ci } 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci /* Check for opcode sequence errors. */ 176862306a36Sopenharmony_ci switch (qp->r_state) { 176962306a36Sopenharmony_ci case OP(SEND_FIRST): 177062306a36Sopenharmony_ci case OP(SEND_MIDDLE): 177162306a36Sopenharmony_ci if (opcode == OP(SEND_MIDDLE) || 177262306a36Sopenharmony_ci opcode == OP(SEND_LAST) || 177362306a36Sopenharmony_ci opcode == OP(SEND_LAST_WITH_IMMEDIATE)) 177462306a36Sopenharmony_ci break; 177562306a36Sopenharmony_ci goto nack_inv; 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 177862306a36Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 177962306a36Sopenharmony_ci if (opcode == OP(RDMA_WRITE_MIDDLE) || 178062306a36Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST) || 178162306a36Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) 178262306a36Sopenharmony_ci break; 178362306a36Sopenharmony_ci goto nack_inv; 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_ci default: 178662306a36Sopenharmony_ci if (opcode == OP(SEND_MIDDLE) || 178762306a36Sopenharmony_ci opcode == OP(SEND_LAST) || 178862306a36Sopenharmony_ci opcode == OP(SEND_LAST_WITH_IMMEDIATE) || 178962306a36Sopenharmony_ci opcode == OP(RDMA_WRITE_MIDDLE) || 179062306a36Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST) || 179162306a36Sopenharmony_ci opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) 179262306a36Sopenharmony_ci goto nack_inv; 179362306a36Sopenharmony_ci /* 179462306a36Sopenharmony_ci * Note that it is up to the requester to not send a new 179562306a36Sopenharmony_ci * RDMA read or atomic operation before receiving an ACK 179662306a36Sopenharmony_ci * for the previous operation. 179762306a36Sopenharmony_ci */ 179862306a36Sopenharmony_ci break; 179962306a36Sopenharmony_ci } 180062306a36Sopenharmony_ci 180162306a36Sopenharmony_ci if (qp->state == IB_QPS_RTR && !(qp->r_flags & RVT_R_COMM_EST)) 180262306a36Sopenharmony_ci rvt_comm_est(qp); 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci /* OK, process the packet. */ 180562306a36Sopenharmony_ci switch (opcode) { 180662306a36Sopenharmony_ci case OP(SEND_FIRST): 180762306a36Sopenharmony_ci ret = rvt_get_rwqe(qp, false); 180862306a36Sopenharmony_ci if (ret < 0) 180962306a36Sopenharmony_ci goto nack_op_err; 181062306a36Sopenharmony_ci if (!ret) 181162306a36Sopenharmony_ci goto rnr_nak; 181262306a36Sopenharmony_ci qp->r_rcv_len = 0; 181362306a36Sopenharmony_ci fallthrough; 181462306a36Sopenharmony_ci case OP(SEND_MIDDLE): 181562306a36Sopenharmony_ci case OP(RDMA_WRITE_MIDDLE): 181662306a36Sopenharmony_cisend_middle: 181762306a36Sopenharmony_ci /* Check for invalid length PMTU or posted rwqe len. */ 181862306a36Sopenharmony_ci if (unlikely(tlen != (hdrsize + pmtu + 4))) 181962306a36Sopenharmony_ci goto nack_inv; 182062306a36Sopenharmony_ci qp->r_rcv_len += pmtu; 182162306a36Sopenharmony_ci if (unlikely(qp->r_rcv_len > qp->r_len)) 182262306a36Sopenharmony_ci goto nack_inv; 182362306a36Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, pmtu, true, false); 182462306a36Sopenharmony_ci break; 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE): 182762306a36Sopenharmony_ci /* consume RWQE */ 182862306a36Sopenharmony_ci ret = rvt_get_rwqe(qp, true); 182962306a36Sopenharmony_ci if (ret < 0) 183062306a36Sopenharmony_ci goto nack_op_err; 183162306a36Sopenharmony_ci if (!ret) 183262306a36Sopenharmony_ci goto rnr_nak; 183362306a36Sopenharmony_ci goto send_last_imm; 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci case OP(SEND_ONLY): 183662306a36Sopenharmony_ci case OP(SEND_ONLY_WITH_IMMEDIATE): 183762306a36Sopenharmony_ci ret = rvt_get_rwqe(qp, false); 183862306a36Sopenharmony_ci if (ret < 0) 183962306a36Sopenharmony_ci goto nack_op_err; 184062306a36Sopenharmony_ci if (!ret) 184162306a36Sopenharmony_ci goto rnr_nak; 184262306a36Sopenharmony_ci qp->r_rcv_len = 0; 184362306a36Sopenharmony_ci if (opcode == OP(SEND_ONLY)) 184462306a36Sopenharmony_ci goto no_immediate_data; 184562306a36Sopenharmony_ci fallthrough; /* for SEND_ONLY_WITH_IMMEDIATE */ 184662306a36Sopenharmony_ci case OP(SEND_LAST_WITH_IMMEDIATE): 184762306a36Sopenharmony_cisend_last_imm: 184862306a36Sopenharmony_ci wc.ex.imm_data = ohdr->u.imm_data; 184962306a36Sopenharmony_ci hdrsize += 4; 185062306a36Sopenharmony_ci wc.wc_flags = IB_WC_WITH_IMM; 185162306a36Sopenharmony_ci goto send_last; 185262306a36Sopenharmony_ci case OP(SEND_LAST): 185362306a36Sopenharmony_ci case OP(RDMA_WRITE_LAST): 185462306a36Sopenharmony_cino_immediate_data: 185562306a36Sopenharmony_ci wc.wc_flags = 0; 185662306a36Sopenharmony_ci wc.ex.imm_data = 0; 185762306a36Sopenharmony_cisend_last: 185862306a36Sopenharmony_ci /* Get the number of bytes the message was padded by. */ 185962306a36Sopenharmony_ci pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; 186062306a36Sopenharmony_ci /* Check for invalid length. */ 186162306a36Sopenharmony_ci /* XXX LAST len should be >= 1 */ 186262306a36Sopenharmony_ci if (unlikely(tlen < (hdrsize + pad + 4))) 186362306a36Sopenharmony_ci goto nack_inv; 186462306a36Sopenharmony_ci /* Don't count the CRC. */ 186562306a36Sopenharmony_ci tlen -= (hdrsize + pad + 4); 186662306a36Sopenharmony_ci wc.byte_len = tlen + qp->r_rcv_len; 186762306a36Sopenharmony_ci if (unlikely(wc.byte_len > qp->r_len)) 186862306a36Sopenharmony_ci goto nack_inv; 186962306a36Sopenharmony_ci rvt_copy_sge(qp, &qp->r_sge, data, tlen, true, false); 187062306a36Sopenharmony_ci rvt_put_ss(&qp->r_sge); 187162306a36Sopenharmony_ci qp->r_msn++; 187262306a36Sopenharmony_ci if (!test_and_clear_bit(RVT_R_WRID_VALID, &qp->r_aflags)) 187362306a36Sopenharmony_ci break; 187462306a36Sopenharmony_ci wc.wr_id = qp->r_wr_id; 187562306a36Sopenharmony_ci wc.status = IB_WC_SUCCESS; 187662306a36Sopenharmony_ci if (opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE) || 187762306a36Sopenharmony_ci opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) 187862306a36Sopenharmony_ci wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; 187962306a36Sopenharmony_ci else 188062306a36Sopenharmony_ci wc.opcode = IB_WC_RECV; 188162306a36Sopenharmony_ci wc.qp = &qp->ibqp; 188262306a36Sopenharmony_ci wc.src_qp = qp->remote_qpn; 188362306a36Sopenharmony_ci wc.slid = rdma_ah_get_dlid(&qp->remote_ah_attr); 188462306a36Sopenharmony_ci wc.sl = rdma_ah_get_sl(&qp->remote_ah_attr); 188562306a36Sopenharmony_ci /* zero fields that are N/A */ 188662306a36Sopenharmony_ci wc.vendor_err = 0; 188762306a36Sopenharmony_ci wc.pkey_index = 0; 188862306a36Sopenharmony_ci wc.dlid_path_bits = 0; 188962306a36Sopenharmony_ci wc.port_num = 0; 189062306a36Sopenharmony_ci /* Signal completion event if the solicited bit is set. */ 189162306a36Sopenharmony_ci rvt_recv_cq(qp, &wc, ib_bth_is_solicited(ohdr)); 189262306a36Sopenharmony_ci break; 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci case OP(RDMA_WRITE_FIRST): 189562306a36Sopenharmony_ci case OP(RDMA_WRITE_ONLY): 189662306a36Sopenharmony_ci case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): 189762306a36Sopenharmony_ci if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE))) 189862306a36Sopenharmony_ci goto nack_inv; 189962306a36Sopenharmony_ci /* consume RWQE */ 190062306a36Sopenharmony_ci reth = &ohdr->u.rc.reth; 190162306a36Sopenharmony_ci hdrsize += sizeof(*reth); 190262306a36Sopenharmony_ci qp->r_len = be32_to_cpu(reth->length); 190362306a36Sopenharmony_ci qp->r_rcv_len = 0; 190462306a36Sopenharmony_ci qp->r_sge.sg_list = NULL; 190562306a36Sopenharmony_ci if (qp->r_len != 0) { 190662306a36Sopenharmony_ci u32 rkey = be32_to_cpu(reth->rkey); 190762306a36Sopenharmony_ci u64 vaddr = be64_to_cpu(reth->vaddr); 190862306a36Sopenharmony_ci int ok; 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci /* Check rkey & NAK */ 191162306a36Sopenharmony_ci ok = rvt_rkey_ok(qp, &qp->r_sge.sge, qp->r_len, vaddr, 191262306a36Sopenharmony_ci rkey, IB_ACCESS_REMOTE_WRITE); 191362306a36Sopenharmony_ci if (unlikely(!ok)) 191462306a36Sopenharmony_ci goto nack_acc; 191562306a36Sopenharmony_ci qp->r_sge.num_sge = 1; 191662306a36Sopenharmony_ci } else { 191762306a36Sopenharmony_ci qp->r_sge.num_sge = 0; 191862306a36Sopenharmony_ci qp->r_sge.sge.mr = NULL; 191962306a36Sopenharmony_ci qp->r_sge.sge.vaddr = NULL; 192062306a36Sopenharmony_ci qp->r_sge.sge.length = 0; 192162306a36Sopenharmony_ci qp->r_sge.sge.sge_length = 0; 192262306a36Sopenharmony_ci } 192362306a36Sopenharmony_ci if (opcode == OP(RDMA_WRITE_FIRST)) 192462306a36Sopenharmony_ci goto send_middle; 192562306a36Sopenharmony_ci else if (opcode == OP(RDMA_WRITE_ONLY)) 192662306a36Sopenharmony_ci goto no_immediate_data; 192762306a36Sopenharmony_ci ret = rvt_get_rwqe(qp, true); 192862306a36Sopenharmony_ci if (ret < 0) 192962306a36Sopenharmony_ci goto nack_op_err; 193062306a36Sopenharmony_ci if (!ret) { 193162306a36Sopenharmony_ci rvt_put_ss(&qp->r_sge); 193262306a36Sopenharmony_ci goto rnr_nak; 193362306a36Sopenharmony_ci } 193462306a36Sopenharmony_ci wc.ex.imm_data = ohdr->u.rc.imm_data; 193562306a36Sopenharmony_ci hdrsize += 4; 193662306a36Sopenharmony_ci wc.wc_flags = IB_WC_WITH_IMM; 193762306a36Sopenharmony_ci goto send_last; 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci case OP(RDMA_READ_REQUEST): { 194062306a36Sopenharmony_ci struct rvt_ack_entry *e; 194162306a36Sopenharmony_ci u32 len; 194262306a36Sopenharmony_ci u8 next; 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ))) 194562306a36Sopenharmony_ci goto nack_inv; 194662306a36Sopenharmony_ci next = qp->r_head_ack_queue + 1; 194762306a36Sopenharmony_ci /* s_ack_queue is size QIB_MAX_RDMA_ATOMIC+1 so use > not >= */ 194862306a36Sopenharmony_ci if (next > QIB_MAX_RDMA_ATOMIC) 194962306a36Sopenharmony_ci next = 0; 195062306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 195162306a36Sopenharmony_ci if (unlikely(next == qp->s_tail_ack_queue)) { 195262306a36Sopenharmony_ci if (!qp->s_ack_queue[next].sent) 195362306a36Sopenharmony_ci goto nack_inv_unlck; 195462306a36Sopenharmony_ci qib_update_ack_queue(qp, next); 195562306a36Sopenharmony_ci } 195662306a36Sopenharmony_ci e = &qp->s_ack_queue[qp->r_head_ack_queue]; 195762306a36Sopenharmony_ci if (e->opcode == OP(RDMA_READ_REQUEST) && e->rdma_sge.mr) { 195862306a36Sopenharmony_ci rvt_put_mr(e->rdma_sge.mr); 195962306a36Sopenharmony_ci e->rdma_sge.mr = NULL; 196062306a36Sopenharmony_ci } 196162306a36Sopenharmony_ci reth = &ohdr->u.rc.reth; 196262306a36Sopenharmony_ci len = be32_to_cpu(reth->length); 196362306a36Sopenharmony_ci if (len) { 196462306a36Sopenharmony_ci u32 rkey = be32_to_cpu(reth->rkey); 196562306a36Sopenharmony_ci u64 vaddr = be64_to_cpu(reth->vaddr); 196662306a36Sopenharmony_ci int ok; 196762306a36Sopenharmony_ci 196862306a36Sopenharmony_ci /* Check rkey & NAK */ 196962306a36Sopenharmony_ci ok = rvt_rkey_ok(qp, &e->rdma_sge, len, vaddr, 197062306a36Sopenharmony_ci rkey, IB_ACCESS_REMOTE_READ); 197162306a36Sopenharmony_ci if (unlikely(!ok)) 197262306a36Sopenharmony_ci goto nack_acc_unlck; 197362306a36Sopenharmony_ci /* 197462306a36Sopenharmony_ci * Update the next expected PSN. We add 1 later 197562306a36Sopenharmony_ci * below, so only add the remainder here. 197662306a36Sopenharmony_ci */ 197762306a36Sopenharmony_ci qp->r_psn += rvt_div_mtu(qp, len - 1); 197862306a36Sopenharmony_ci } else { 197962306a36Sopenharmony_ci e->rdma_sge.mr = NULL; 198062306a36Sopenharmony_ci e->rdma_sge.vaddr = NULL; 198162306a36Sopenharmony_ci e->rdma_sge.length = 0; 198262306a36Sopenharmony_ci e->rdma_sge.sge_length = 0; 198362306a36Sopenharmony_ci } 198462306a36Sopenharmony_ci e->opcode = opcode; 198562306a36Sopenharmony_ci e->sent = 0; 198662306a36Sopenharmony_ci e->psn = psn; 198762306a36Sopenharmony_ci e->lpsn = qp->r_psn; 198862306a36Sopenharmony_ci /* 198962306a36Sopenharmony_ci * We need to increment the MSN here instead of when we 199062306a36Sopenharmony_ci * finish sending the result since a duplicate request would 199162306a36Sopenharmony_ci * increment it more than once. 199262306a36Sopenharmony_ci */ 199362306a36Sopenharmony_ci qp->r_msn++; 199462306a36Sopenharmony_ci qp->r_psn++; 199562306a36Sopenharmony_ci qp->r_state = opcode; 199662306a36Sopenharmony_ci qp->r_nak_state = 0; 199762306a36Sopenharmony_ci qp->r_head_ack_queue = next; 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_ci /* Schedule the send tasklet. */ 200062306a36Sopenharmony_ci qp->s_flags |= RVT_S_RESP_PENDING; 200162306a36Sopenharmony_ci qib_schedule_send(qp); 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci goto sunlock; 200462306a36Sopenharmony_ci } 200562306a36Sopenharmony_ci 200662306a36Sopenharmony_ci case OP(COMPARE_SWAP): 200762306a36Sopenharmony_ci case OP(FETCH_ADD): { 200862306a36Sopenharmony_ci struct ib_atomic_eth *ateth; 200962306a36Sopenharmony_ci struct rvt_ack_entry *e; 201062306a36Sopenharmony_ci u64 vaddr; 201162306a36Sopenharmony_ci atomic64_t *maddr; 201262306a36Sopenharmony_ci u64 sdata; 201362306a36Sopenharmony_ci u32 rkey; 201462306a36Sopenharmony_ci u8 next; 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC))) 201762306a36Sopenharmony_ci goto nack_inv; 201862306a36Sopenharmony_ci next = qp->r_head_ack_queue + 1; 201962306a36Sopenharmony_ci if (next > QIB_MAX_RDMA_ATOMIC) 202062306a36Sopenharmony_ci next = 0; 202162306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 202262306a36Sopenharmony_ci if (unlikely(next == qp->s_tail_ack_queue)) { 202362306a36Sopenharmony_ci if (!qp->s_ack_queue[next].sent) 202462306a36Sopenharmony_ci goto nack_inv_unlck; 202562306a36Sopenharmony_ci qib_update_ack_queue(qp, next); 202662306a36Sopenharmony_ci } 202762306a36Sopenharmony_ci e = &qp->s_ack_queue[qp->r_head_ack_queue]; 202862306a36Sopenharmony_ci if (e->opcode == OP(RDMA_READ_REQUEST) && e->rdma_sge.mr) { 202962306a36Sopenharmony_ci rvt_put_mr(e->rdma_sge.mr); 203062306a36Sopenharmony_ci e->rdma_sge.mr = NULL; 203162306a36Sopenharmony_ci } 203262306a36Sopenharmony_ci ateth = &ohdr->u.atomic_eth; 203362306a36Sopenharmony_ci vaddr = get_ib_ateth_vaddr(ateth); 203462306a36Sopenharmony_ci if (unlikely(vaddr & (sizeof(u64) - 1))) 203562306a36Sopenharmony_ci goto nack_inv_unlck; 203662306a36Sopenharmony_ci rkey = be32_to_cpu(ateth->rkey); 203762306a36Sopenharmony_ci /* Check rkey & NAK */ 203862306a36Sopenharmony_ci if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64), 203962306a36Sopenharmony_ci vaddr, rkey, 204062306a36Sopenharmony_ci IB_ACCESS_REMOTE_ATOMIC))) 204162306a36Sopenharmony_ci goto nack_acc_unlck; 204262306a36Sopenharmony_ci /* Perform atomic OP and save result. */ 204362306a36Sopenharmony_ci maddr = (atomic64_t *) qp->r_sge.sge.vaddr; 204462306a36Sopenharmony_ci sdata = get_ib_ateth_swap(ateth); 204562306a36Sopenharmony_ci e->atomic_data = (opcode == OP(FETCH_ADD)) ? 204662306a36Sopenharmony_ci (u64) atomic64_add_return(sdata, maddr) - sdata : 204762306a36Sopenharmony_ci (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr, 204862306a36Sopenharmony_ci get_ib_ateth_compare(ateth), 204962306a36Sopenharmony_ci sdata); 205062306a36Sopenharmony_ci rvt_put_mr(qp->r_sge.sge.mr); 205162306a36Sopenharmony_ci qp->r_sge.num_sge = 0; 205262306a36Sopenharmony_ci e->opcode = opcode; 205362306a36Sopenharmony_ci e->sent = 0; 205462306a36Sopenharmony_ci e->psn = psn; 205562306a36Sopenharmony_ci e->lpsn = psn; 205662306a36Sopenharmony_ci qp->r_msn++; 205762306a36Sopenharmony_ci qp->r_psn++; 205862306a36Sopenharmony_ci qp->r_state = opcode; 205962306a36Sopenharmony_ci qp->r_nak_state = 0; 206062306a36Sopenharmony_ci qp->r_head_ack_queue = next; 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci /* Schedule the send tasklet. */ 206362306a36Sopenharmony_ci qp->s_flags |= RVT_S_RESP_PENDING; 206462306a36Sopenharmony_ci qib_schedule_send(qp); 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci goto sunlock; 206762306a36Sopenharmony_ci } 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci default: 207062306a36Sopenharmony_ci /* NAK unknown opcodes. */ 207162306a36Sopenharmony_ci goto nack_inv; 207262306a36Sopenharmony_ci } 207362306a36Sopenharmony_ci qp->r_psn++; 207462306a36Sopenharmony_ci qp->r_state = opcode; 207562306a36Sopenharmony_ci qp->r_ack_psn = psn; 207662306a36Sopenharmony_ci qp->r_nak_state = 0; 207762306a36Sopenharmony_ci /* Send an ACK if requested or required. */ 207862306a36Sopenharmony_ci if (psn & (1 << 31)) 207962306a36Sopenharmony_ci goto send_ack; 208062306a36Sopenharmony_ci return; 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_cirnr_nak: 208362306a36Sopenharmony_ci qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer; 208462306a36Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 208562306a36Sopenharmony_ci /* Queue RNR NAK for later */ 208662306a36Sopenharmony_ci if (list_empty(&qp->rspwait)) { 208762306a36Sopenharmony_ci qp->r_flags |= RVT_R_RSP_NAK; 208862306a36Sopenharmony_ci rvt_get_qp(qp); 208962306a36Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 209062306a36Sopenharmony_ci } 209162306a36Sopenharmony_ci return; 209262306a36Sopenharmony_ci 209362306a36Sopenharmony_cinack_op_err: 209462306a36Sopenharmony_ci rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR); 209562306a36Sopenharmony_ci qp->r_nak_state = IB_NAK_REMOTE_OPERATIONAL_ERROR; 209662306a36Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 209762306a36Sopenharmony_ci /* Queue NAK for later */ 209862306a36Sopenharmony_ci if (list_empty(&qp->rspwait)) { 209962306a36Sopenharmony_ci qp->r_flags |= RVT_R_RSP_NAK; 210062306a36Sopenharmony_ci rvt_get_qp(qp); 210162306a36Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 210262306a36Sopenharmony_ci } 210362306a36Sopenharmony_ci return; 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_cinack_inv_unlck: 210662306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 210762306a36Sopenharmony_cinack_inv: 210862306a36Sopenharmony_ci rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR); 210962306a36Sopenharmony_ci qp->r_nak_state = IB_NAK_INVALID_REQUEST; 211062306a36Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 211162306a36Sopenharmony_ci /* Queue NAK for later */ 211262306a36Sopenharmony_ci if (list_empty(&qp->rspwait)) { 211362306a36Sopenharmony_ci qp->r_flags |= RVT_R_RSP_NAK; 211462306a36Sopenharmony_ci rvt_get_qp(qp); 211562306a36Sopenharmony_ci list_add_tail(&qp->rspwait, &rcd->qp_wait_list); 211662306a36Sopenharmony_ci } 211762306a36Sopenharmony_ci return; 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_cinack_acc_unlck: 212062306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 212162306a36Sopenharmony_cinack_acc: 212262306a36Sopenharmony_ci rvt_rc_error(qp, IB_WC_LOC_PROT_ERR); 212362306a36Sopenharmony_ci qp->r_nak_state = IB_NAK_REMOTE_ACCESS_ERROR; 212462306a36Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 212562306a36Sopenharmony_cisend_ack: 212662306a36Sopenharmony_ci qib_send_rc_ack(qp); 212762306a36Sopenharmony_ci return; 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_cisunlock: 213062306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 213162306a36Sopenharmony_ci} 2132