uc.c 15.8 KB
Newer Older
M
Mike Marciniszyn 已提交
1
/*
2
 * Copyright(c) 2015 - 2018 Intel Corporation.
M
Mike Marciniszyn 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
 *
 * This file is provided under a dual BSD/GPLv2 license.  When using or
 * redistributing this file, you may do so under either license.
 *
 * GPL LICENSE SUMMARY
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * BSD LICENSE
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  - Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  - Neither the name of Intel Corporation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "hfi.h"
49
#include "verbs_txreq.h"
M
Mike Marciniszyn 已提交
50 51 52
#include "qp.h"

/* cut down ridiculously long IB macro names */
53
#define OP(x) UC_OP(x)
54

M
Mike Marciniszyn 已提交
55 56 57 58
/**
 * hfi1_make_uc_req - construct a request packet (SEND, RDMA write)
 * @qp: a pointer to the QP
 *
59 60
 * Assume s_lock is held.
 *
M
Mike Marciniszyn 已提交
61 62
 * Return 1 if constructed; otherwise, return 0.
 */
63
int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
M
Mike Marciniszyn 已提交
64
{
65
	struct hfi1_qp_priv *priv = qp->priv;
66
	struct ib_other_headers *ohdr;
67
	struct rvt_swqe *wqe;
D
Don Hiatt 已提交
68
	u32 hwords;
M
Mike Marciniszyn 已提交
69 70 71 72 73
	u32 bth0 = 0;
	u32 len;
	u32 pmtu = qp->pmtu;
	int middle = 0;

74
	ps->s_txreq = get_txreq(ps->dev, qp);
75
	if (!ps->s_txreq)
76 77
		goto bail_no_tx;

78 79
	if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_SEND_OK)) {
		if (!(ib_rvt_state_ops[qp->state] & RVT_FLUSH_SEND))
M
Mike Marciniszyn 已提交
80 81
			goto bail;
		/* We are in the error state, flush the work request. */
82
		if (qp->s_last == READ_ONCE(qp->s_head))
M
Mike Marciniszyn 已提交
83 84
			goto bail;
		/* If DMAs are in progress, we can't flush immediately. */
85
		if (iowait_sdma_pending(&priv->s_iowait)) {
86
			qp->s_flags |= RVT_S_WAIT_DMA;
M
Mike Marciniszyn 已提交
87 88 89
			goto bail;
		}
		clear_ahg(qp);
90
		wqe = rvt_get_swqe_ptr(qp, qp->s_last);
91
		rvt_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR);
92
		goto done_free_tx;
M
Mike Marciniszyn 已提交
93 94
	}

D
Don Hiatt 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
	if (priv->hdr_type == HFI1_PKT_TYPE_9B) {
		/* header size in 32-bit words LRH+BTH = (8+12)/4. */
		hwords = 5;
		if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH)
			ohdr = &ps->s_txreq->phdr.hdr.ibh.u.l.oth;
		else
			ohdr = &ps->s_txreq->phdr.hdr.ibh.u.oth;
	} else {
		/* header size in 32-bit words 16B LRH+BTH = (16+12)/4. */
		hwords = 7;
		if ((rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) &&
		    (hfi1_check_mcast(rdma_ah_get_dlid(&qp->remote_ah_attr))))
			ohdr = &ps->s_txreq->phdr.hdr.opah.u.l.oth;
		else
			ohdr = &ps->s_txreq->phdr.hdr.opah.u.oth;
	}
M
Mike Marciniszyn 已提交
111 112

	/* Get the next send request. */
113
	wqe = rvt_get_swqe_ptr(qp, qp->s_cur);
M
Mike Marciniszyn 已提交
114 115 116
	qp->s_wqe = NULL;
	switch (qp->s_state) {
	default:
117 118
		if (!(ib_rvt_state_ops[qp->state] &
		    RVT_PROCESS_NEXT_SEND_OK))
M
Mike Marciniszyn 已提交
119 120
			goto bail;
		/* Check if send work queue is empty. */
121
		if (qp->s_cur == READ_ONCE(qp->s_head)) {
M
Mike Marciniszyn 已提交
122 123 124
			clear_ahg(qp);
			goto bail;
		}
125 126 127 128 129 130
		/*
		 * Local operations are processed immediately
		 * after all prior requests have completed.
		 */
		if (wqe->wr.opcode == IB_WR_REG_MR ||
		    wqe->wr.opcode == IB_WR_LOCAL_INV) {
131 132 133
			int local_ops = 0;
			int err = 0;

134 135 136 137
			if (qp->s_last != qp->s_cur)
				goto bail;
			if (++qp->s_cur == qp->s_size)
				qp->s_cur = 0;
138
			if (!(wqe->wr.send_flags & RVT_SEND_COMPLETION_ONLY)) {
139 140
				err = rvt_invalidate_rkey(
					qp, wqe->wr.ex.invalidate_rkey);
141 142
				local_ops = 1;
			}
143
			rvt_send_complete(qp, wqe, err ? IB_WC_LOC_PROT_ERR
144
							: IB_WC_SUCCESS);
145 146
			if (local_ops)
				atomic_dec(&qp->local_ops_pending);
147 148
			goto done_free_tx;
		}
M
Mike Marciniszyn 已提交
149 150 151
		/*
		 * Start a new request.
		 */
152
		qp->s_psn = wqe->psn;
M
Mike Marciniszyn 已提交
153 154 155 156 157 158 159 160 161 162 163 164 165 166
		qp->s_sge.sge = wqe->sg_list[0];
		qp->s_sge.sg_list = wqe->sg_list + 1;
		qp->s_sge.num_sge = wqe->wr.num_sge;
		qp->s_sge.total_len = wqe->length;
		len = wqe->length;
		qp->s_len = len;
		switch (wqe->wr.opcode) {
		case IB_WR_SEND:
		case IB_WR_SEND_WITH_IMM:
			if (len > pmtu) {
				qp->s_state = OP(SEND_FIRST);
				len = pmtu;
				break;
			}
167
			if (wqe->wr.opcode == IB_WR_SEND) {
M
Mike Marciniszyn 已提交
168
				qp->s_state = OP(SEND_ONLY);
169
			} else {
M
Mike Marciniszyn 已提交
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
				qp->s_state =
					OP(SEND_ONLY_WITH_IMMEDIATE);
				/* Immediate data comes after the BTH */
				ohdr->u.imm_data = wqe->wr.ex.imm_data;
				hwords += 1;
			}
			if (wqe->wr.send_flags & IB_SEND_SOLICITED)
				bth0 |= IB_BTH_SOLICITED;
			qp->s_wqe = wqe;
			if (++qp->s_cur >= qp->s_size)
				qp->s_cur = 0;
			break;

		case IB_WR_RDMA_WRITE:
		case IB_WR_RDMA_WRITE_WITH_IMM:
			ohdr->u.rc.reth.vaddr =
C
Christoph Hellwig 已提交
186
				cpu_to_be64(wqe->rdma_wr.remote_addr);
M
Mike Marciniszyn 已提交
187
			ohdr->u.rc.reth.rkey =
C
Christoph Hellwig 已提交
188
				cpu_to_be32(wqe->rdma_wr.rkey);
M
Mike Marciniszyn 已提交
189 190 191 192 193 194 195
			ohdr->u.rc.reth.length = cpu_to_be32(len);
			hwords += sizeof(struct ib_reth) / 4;
			if (len > pmtu) {
				qp->s_state = OP(RDMA_WRITE_FIRST);
				len = pmtu;
				break;
			}
196
			if (wqe->wr.opcode == IB_WR_RDMA_WRITE) {
M
Mike Marciniszyn 已提交
197
				qp->s_state = OP(RDMA_WRITE_ONLY);
198
			} else {
M
Mike Marciniszyn 已提交
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
				qp->s_state =
					OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
				/* Immediate data comes after the RETH */
				ohdr->u.rc.imm_data = wqe->wr.ex.imm_data;
				hwords += 1;
				if (wqe->wr.send_flags & IB_SEND_SOLICITED)
					bth0 |= IB_BTH_SOLICITED;
			}
			qp->s_wqe = wqe;
			if (++qp->s_cur >= qp->s_size)
				qp->s_cur = 0;
			break;

		default:
			goto bail;
		}
		break;

	case OP(SEND_FIRST):
		qp->s_state = OP(SEND_MIDDLE);
		/* FALLTHROUGH */
	case OP(SEND_MIDDLE):
		len = qp->s_len;
		if (len > pmtu) {
			len = pmtu;
			middle = HFI1_CAP_IS_KSET(SDMA_AHG);
			break;
		}
227
		if (wqe->wr.opcode == IB_WR_SEND) {
M
Mike Marciniszyn 已提交
228
			qp->s_state = OP(SEND_LAST);
229
		} else {
M
Mike Marciniszyn 已提交
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
			qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
			/* Immediate data comes after the BTH */
			ohdr->u.imm_data = wqe->wr.ex.imm_data;
			hwords += 1;
		}
		if (wqe->wr.send_flags & IB_SEND_SOLICITED)
			bth0 |= IB_BTH_SOLICITED;
		qp->s_wqe = wqe;
		if (++qp->s_cur >= qp->s_size)
			qp->s_cur = 0;
		break;

	case OP(RDMA_WRITE_FIRST):
		qp->s_state = OP(RDMA_WRITE_MIDDLE);
		/* FALLTHROUGH */
	case OP(RDMA_WRITE_MIDDLE):
		len = qp->s_len;
		if (len > pmtu) {
			len = pmtu;
			middle = HFI1_CAP_IS_KSET(SDMA_AHG);
			break;
		}
252
		if (wqe->wr.opcode == IB_WR_RDMA_WRITE) {
M
Mike Marciniszyn 已提交
253
			qp->s_state = OP(RDMA_WRITE_LAST);
254
		} else {
M
Mike Marciniszyn 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267 268
			qp->s_state =
				OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
			/* Immediate data comes after the BTH */
			ohdr->u.imm_data = wqe->wr.ex.imm_data;
			hwords += 1;
			if (wqe->wr.send_flags & IB_SEND_SOLICITED)
				bth0 |= IB_BTH_SOLICITED;
		}
		qp->s_wqe = wqe;
		if (++qp->s_cur >= qp->s_size)
			qp->s_cur = 0;
		break;
	}
	qp->s_len -= len;
269
	ps->s_txreq->hdr_dwords = hwords;
270
	ps->s_txreq->sde = priv->s_sde;
271
	ps->s_txreq->ss = &qp->s_sge;
272
	ps->s_txreq->s_cur_size = len;
M
Mike Marciniszyn 已提交
273
	hfi1_make_ruc_header(qp, ohdr, bth0 | (qp->s_state << 24),
274 275
			     qp->remote_qpn, mask_psn(qp->s_psn++),
			     middle, ps);
276 277 278 279 280
	return 1;

done_free_tx:
	hfi1_put_txreq(ps->s_txreq);
	ps->s_txreq = NULL;
281
	return 1;
M
Mike Marciniszyn 已提交
282 283

bail:
284 285 286 287
	hfi1_put_txreq(ps->s_txreq);

bail_no_tx:
	ps->s_txreq = NULL;
288
	qp->s_flags &= ~RVT_S_BUSY;
289
	return 0;
M
Mike Marciniszyn 已提交
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
}

/**
 * hfi1_uc_rcv - handle an incoming UC packet
 * @ibp: the port the packet came in on
 * @hdr: the header of the packet
 * @rcv_flags: flags relevant to rcv processing
 * @data: the packet data
 * @tlen: the length of the packet
 * @qp: the QP for this packet.
 *
 * This is called from qp_rcv() to process an incoming UC packet
 * for the given QP.
 * Called at interrupt level.
 */
void hfi1_uc_rcv(struct hfi1_packet *packet)
{
307
	struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd);
308
	void *data = packet->payload;
M
Mike Marciniszyn 已提交
309
	u32 tlen = packet->tlen;
310
	struct rvt_qp *qp = packet->qp;
311
	struct ib_other_headers *ohdr = packet->ohdr;
312
	u32 opcode = packet->opcode;
M
Mike Marciniszyn 已提交
313 314
	u32 hdrsize = packet->hlen;
	u32 psn;
315
	u32 pad = packet->pad;
M
Mike Marciniszyn 已提交
316 317 318 319
	struct ib_wc wc;
	u32 pmtu = qp->pmtu;
	struct ib_reth *reth;
	int ret;
D
Don Hiatt 已提交
320
	u8 extra_bytes = pad + packet->extra_byte + (SIZE_OF_CRC << 2);
M
Mike Marciniszyn 已提交
321

322
	if (hfi1_ruc_check_hdr(ibp, packet))
M
Mike Marciniszyn 已提交
323 324
		return;

325
	process_ecn(qp, packet);
M
Mike Marciniszyn 已提交
326

327
	psn = ib_bth_get_psn(ohdr);
M
Mike Marciniszyn 已提交
328 329 330 331 332 333 334 335 336 337
	/* Compare the PSN verses the expected PSN. */
	if (unlikely(cmp_psn(psn, qp->r_psn) != 0)) {
		/*
		 * Handle a sequence error.
		 * Silently drop any current message.
		 */
		qp->r_psn = psn;
inv:
		if (qp->r_state == OP(SEND_FIRST) ||
		    qp->r_state == OP(SEND_MIDDLE)) {
338
			set_bit(RVT_R_REWIND_SGE, &qp->r_aflags);
M
Mike Marciniszyn 已提交
339
			qp->r_sge.num_sge = 0;
340
		} else {
341
			rvt_put_ss(&qp->r_sge);
342
		}
M
Mike Marciniszyn 已提交
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
		qp->r_state = OP(SEND_LAST);
		switch (opcode) {
		case OP(SEND_FIRST):
		case OP(SEND_ONLY):
		case OP(SEND_ONLY_WITH_IMMEDIATE):
			goto send_first;

		case OP(RDMA_WRITE_FIRST):
		case OP(RDMA_WRITE_ONLY):
		case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):
			goto rdma_first;

		default:
			goto drop;
		}
	}

	/* Check for opcode sequence errors. */
	switch (qp->r_state) {
	case OP(SEND_FIRST):
	case OP(SEND_MIDDLE):
		if (opcode == OP(SEND_MIDDLE) ||
		    opcode == OP(SEND_LAST) ||
		    opcode == OP(SEND_LAST_WITH_IMMEDIATE))
			break;
		goto inv;

	case OP(RDMA_WRITE_FIRST):
	case OP(RDMA_WRITE_MIDDLE):
		if (opcode == OP(RDMA_WRITE_MIDDLE) ||
		    opcode == OP(RDMA_WRITE_LAST) ||
		    opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
			break;
		goto inv;

	default:
		if (opcode == OP(SEND_FIRST) ||
		    opcode == OP(SEND_ONLY) ||
		    opcode == OP(SEND_ONLY_WITH_IMMEDIATE) ||
		    opcode == OP(RDMA_WRITE_FIRST) ||
		    opcode == OP(RDMA_WRITE_ONLY) ||
		    opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))
			break;
		goto inv;
	}

389
	if (qp->state == IB_QPS_RTR && !(qp->r_flags & RVT_R_COMM_EST))
390
		rvt_comm_est(qp);
M
Mike Marciniszyn 已提交
391 392 393 394 395 396 397

	/* OK, process the packet. */
	switch (opcode) {
	case OP(SEND_FIRST):
	case OP(SEND_ONLY):
	case OP(SEND_ONLY_WITH_IMMEDIATE):
send_first:
398
		if (test_and_clear_bit(RVT_R_REWIND_SGE, &qp->r_aflags)) {
M
Mike Marciniszyn 已提交
399
			qp->r_sge = qp->s_rdma_read_sge;
400
		} else {
401
			ret = rvt_get_rwqe(qp, false);
M
Mike Marciniszyn 已提交
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
			if (ret < 0)
				goto op_err;
			if (!ret)
				goto drop;
			/*
			 * qp->s_rdma_read_sge will be the owner
			 * of the mr references.
			 */
			qp->s_rdma_read_sge = qp->r_sge;
		}
		qp->r_rcv_len = 0;
		if (opcode == OP(SEND_ONLY))
			goto no_immediate_data;
		else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE))
			goto send_last_imm;
		/* FALLTHROUGH */
	case OP(SEND_MIDDLE):
		/* Check for invalid length PMTU or posted rwqe len. */
D
Don Hiatt 已提交
420 421 422 423 424 425
		/*
		 * There will be no padding for 9B packet but 16B packets
		 * will come in with some padding since we always add
		 * CRC and LT bytes which will need to be flit aligned
		 */
		if (unlikely(tlen != (hdrsize + pmtu + extra_bytes)))
M
Mike Marciniszyn 已提交
426 427 428 429
			goto rewind;
		qp->r_rcv_len += pmtu;
		if (unlikely(qp->r_rcv_len > qp->r_len))
			goto rewind;
430
		rvt_copy_sge(qp, &qp->r_sge, data, pmtu, false, false);
M
Mike Marciniszyn 已提交
431 432 433 434 435 436 437 438 439 440 441 442 443 444
		break;

	case OP(SEND_LAST_WITH_IMMEDIATE):
send_last_imm:
		wc.ex.imm_data = ohdr->u.imm_data;
		wc.wc_flags = IB_WC_WITH_IMM;
		goto send_last;
	case OP(SEND_LAST):
no_immediate_data:
		wc.ex.imm_data = 0;
		wc.wc_flags = 0;
send_last:
		/* Check for invalid length. */
		/* LAST len should be >= 1 */
D
Don Hiatt 已提交
445
		if (unlikely(tlen < (hdrsize + extra_bytes)))
M
Mike Marciniszyn 已提交
446 447
			goto rewind;
		/* Don't count the CRC. */
D
Don Hiatt 已提交
448
		tlen -= (hdrsize + extra_bytes);
M
Mike Marciniszyn 已提交
449 450 451 452
		wc.byte_len = tlen + qp->r_rcv_len;
		if (unlikely(wc.byte_len > qp->r_len))
			goto rewind;
		wc.opcode = IB_WC_RECV;
453
		rvt_copy_sge(qp, &qp->r_sge, data, tlen, false, false);
454
		rvt_put_ss(&qp->s_rdma_read_sge);
M
Mike Marciniszyn 已提交
455 456 457 458 459
last_imm:
		wc.wr_id = qp->r_wr_id;
		wc.status = IB_WC_SUCCESS;
		wc.qp = &qp->ibqp;
		wc.src_qp = qp->remote_qpn;
460
		wc.slid = rdma_ah_get_dlid(&qp->remote_ah_attr) & U16_MAX;
M
Mike Marciniszyn 已提交
461 462 463 464 465 466 467 468 469 470 471
		/*
		 * It seems that IB mandates the presence of an SL in a
		 * work completion only for the UD transport (see section
		 * 11.4.2 of IBTA Vol. 1).
		 *
		 * However, the way the SL is chosen below is consistent
		 * with the way that IB/qib works and is trying avoid
		 * introducing incompatibilities.
		 *
		 * See also OPA Vol. 1, section 9.7.6, and table 9-17.
		 */
472
		wc.sl = rdma_ah_get_sl(&qp->remote_ah_attr);
M
Mike Marciniszyn 已提交
473 474 475 476 477 478
		/* zero fields that are N/A */
		wc.vendor_err = 0;
		wc.pkey_index = 0;
		wc.dlid_path_bits = 0;
		wc.port_num = 0;
		/* Signal completion event if the solicited bit is set. */
479
		rvt_recv_cq(qp, &wc, ib_bth_is_solicited(ohdr));
M
Mike Marciniszyn 已提交
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
		break;

	case OP(RDMA_WRITE_FIRST):
	case OP(RDMA_WRITE_ONLY):
	case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): /* consume RWQE */
rdma_first:
		if (unlikely(!(qp->qp_access_flags &
			       IB_ACCESS_REMOTE_WRITE))) {
			goto drop;
		}
		reth = &ohdr->u.rc.reth;
		qp->r_len = be32_to_cpu(reth->length);
		qp->r_rcv_len = 0;
		qp->r_sge.sg_list = NULL;
		if (qp->r_len != 0) {
			u32 rkey = be32_to_cpu(reth->rkey);
			u64 vaddr = be64_to_cpu(reth->vaddr);
			int ok;

			/* Check rkey */
500 501
			ok = rvt_rkey_ok(qp, &qp->r_sge.sge, qp->r_len,
					 vaddr, rkey, IB_ACCESS_REMOTE_WRITE);
M
Mike Marciniszyn 已提交
502 503 504 505 506 507 508 509 510 511
			if (unlikely(!ok))
				goto drop;
			qp->r_sge.num_sge = 1;
		} else {
			qp->r_sge.num_sge = 0;
			qp->r_sge.sge.mr = NULL;
			qp->r_sge.sge.vaddr = NULL;
			qp->r_sge.sge.length = 0;
			qp->r_sge.sge.sge_length = 0;
		}
512
		if (opcode == OP(RDMA_WRITE_ONLY)) {
M
Mike Marciniszyn 已提交
513
			goto rdma_last;
514
		} else if (opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) {
M
Mike Marciniszyn 已提交
515 516 517 518 519 520 521 522 523 524 525
			wc.ex.imm_data = ohdr->u.rc.imm_data;
			goto rdma_last_imm;
		}
		/* FALLTHROUGH */
	case OP(RDMA_WRITE_MIDDLE):
		/* Check for invalid length PMTU or posted rwqe len. */
		if (unlikely(tlen != (hdrsize + pmtu + 4)))
			goto drop;
		qp->r_rcv_len += pmtu;
		if (unlikely(qp->r_rcv_len > qp->r_len))
			goto drop;
526
		rvt_copy_sge(qp, &qp->r_sge, data, pmtu, true, false);
M
Mike Marciniszyn 已提交
527 528 529 530 531 532 533 534 535 536 537 538
		break;

	case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE):
		wc.ex.imm_data = ohdr->u.imm_data;
rdma_last_imm:
		wc.wc_flags = IB_WC_WITH_IMM;

		/* Check for invalid length. */
		/* LAST len should be >= 1 */
		if (unlikely(tlen < (hdrsize + pad + 4)))
			goto drop;
		/* Don't count the CRC. */
D
Don Hiatt 已提交
539
		tlen -= (hdrsize + extra_bytes);
M
Mike Marciniszyn 已提交
540 541
		if (unlikely(tlen + qp->r_rcv_len != qp->r_len))
			goto drop;
542
		if (test_and_clear_bit(RVT_R_REWIND_SGE, &qp->r_aflags)) {
543
			rvt_put_ss(&qp->s_rdma_read_sge);
544
		} else {
545
			ret = rvt_get_rwqe(qp, true);
M
Mike Marciniszyn 已提交
546 547 548 549 550 551 552
			if (ret < 0)
				goto op_err;
			if (!ret)
				goto drop;
		}
		wc.byte_len = qp->r_len;
		wc.opcode = IB_WC_RECV_RDMA_WITH_IMM;
553
		rvt_copy_sge(qp, &qp->r_sge, data, tlen, true, false);
554
		rvt_put_ss(&qp->r_sge);
M
Mike Marciniszyn 已提交
555 556 557 558 559 560 561 562 563
		goto last_imm;

	case OP(RDMA_WRITE_LAST):
rdma_last:
		/* Check for invalid length. */
		/* LAST len should be >= 1 */
		if (unlikely(tlen < (hdrsize + pad + 4)))
			goto drop;
		/* Don't count the CRC. */
D
Don Hiatt 已提交
564
		tlen -= (hdrsize + extra_bytes);
M
Mike Marciniszyn 已提交
565 566
		if (unlikely(tlen + qp->r_rcv_len != qp->r_len))
			goto drop;
567
		rvt_copy_sge(qp, &qp->r_sge, data, tlen, true, false);
568
		rvt_put_ss(&qp->r_sge);
M
Mike Marciniszyn 已提交
569 570 571 572 573 574 575 576 577 578 579
		break;

	default:
		/* Drop packet for unknown opcodes. */
		goto drop;
	}
	qp->r_psn++;
	qp->r_state = opcode;
	return;

rewind:
580
	set_bit(RVT_R_REWIND_SGE, &qp->r_aflags);
M
Mike Marciniszyn 已提交
581 582
	qp->r_sge.num_sge = 0;
drop:
583
	ibp->rvp.n_pkt_drops++;
M
Mike Marciniszyn 已提交
584 585 586
	return;

op_err:
587
	rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
M
Mike Marciniszyn 已提交
588
}