.. | .. |
---|
171 | 171 | } |
---|
172 | 172 | |
---|
173 | 173 | /** |
---|
174 | | - * qib_ruc_loopback - handle UC and RC lookback requests |
---|
175 | | - * @sqp: the sending QP |
---|
176 | | - * |
---|
177 | | - * This is called from qib_do_send() to |
---|
178 | | - * forward a WQE addressed to the same HCA. |
---|
179 | | - * Note that although we are single threaded due to the tasklet, we still |
---|
180 | | - * have to protect against post_send(). We don't have to worry about |
---|
181 | | - * receive interrupts since this is a connected protocol and all packets |
---|
182 | | - * will pass through here. |
---|
183 | | - */ |
---|
184 | | -static void qib_ruc_loopback(struct rvt_qp *sqp) |
---|
185 | | -{ |
---|
186 | | - struct qib_ibport *ibp = to_iport(sqp->ibqp.device, sqp->port_num); |
---|
187 | | - struct qib_pportdata *ppd = ppd_from_ibp(ibp); |
---|
188 | | - struct qib_devdata *dd = ppd->dd; |
---|
189 | | - struct rvt_dev_info *rdi = &dd->verbs_dev.rdi; |
---|
190 | | - struct rvt_qp *qp; |
---|
191 | | - struct rvt_swqe *wqe; |
---|
192 | | - struct rvt_sge *sge; |
---|
193 | | - unsigned long flags; |
---|
194 | | - struct ib_wc wc; |
---|
195 | | - u64 sdata; |
---|
196 | | - atomic64_t *maddr; |
---|
197 | | - enum ib_wc_status send_status; |
---|
198 | | - int release; |
---|
199 | | - int ret; |
---|
200 | | - |
---|
201 | | - rcu_read_lock(); |
---|
202 | | - /* |
---|
203 | | - * Note that we check the responder QP state after |
---|
204 | | - * checking the requester's state. |
---|
205 | | - */ |
---|
206 | | - qp = rvt_lookup_qpn(rdi, &ibp->rvp, sqp->remote_qpn); |
---|
207 | | - if (!qp) |
---|
208 | | - goto done; |
---|
209 | | - |
---|
210 | | - spin_lock_irqsave(&sqp->s_lock, flags); |
---|
211 | | - |
---|
212 | | - /* Return if we are already busy processing a work request. */ |
---|
213 | | - if ((sqp->s_flags & (RVT_S_BUSY | RVT_S_ANY_WAIT)) || |
---|
214 | | - !(ib_rvt_state_ops[sqp->state] & RVT_PROCESS_OR_FLUSH_SEND)) |
---|
215 | | - goto unlock; |
---|
216 | | - |
---|
217 | | - sqp->s_flags |= RVT_S_BUSY; |
---|
218 | | - |
---|
219 | | -again: |
---|
220 | | - if (sqp->s_last == READ_ONCE(sqp->s_head)) |
---|
221 | | - goto clr_busy; |
---|
222 | | - wqe = rvt_get_swqe_ptr(sqp, sqp->s_last); |
---|
223 | | - |
---|
224 | | - /* Return if it is not OK to start a new work reqeust. */ |
---|
225 | | - if (!(ib_rvt_state_ops[sqp->state] & RVT_PROCESS_NEXT_SEND_OK)) { |
---|
226 | | - if (!(ib_rvt_state_ops[sqp->state] & RVT_FLUSH_SEND)) |
---|
227 | | - goto clr_busy; |
---|
228 | | - /* We are in the error state, flush the work request. */ |
---|
229 | | - send_status = IB_WC_WR_FLUSH_ERR; |
---|
230 | | - goto flush_send; |
---|
231 | | - } |
---|
232 | | - |
---|
233 | | - /* |
---|
234 | | - * We can rely on the entry not changing without the s_lock |
---|
235 | | - * being held until we update s_last. |
---|
236 | | - * We increment s_cur to indicate s_last is in progress. |
---|
237 | | - */ |
---|
238 | | - if (sqp->s_last == sqp->s_cur) { |
---|
239 | | - if (++sqp->s_cur >= sqp->s_size) |
---|
240 | | - sqp->s_cur = 0; |
---|
241 | | - } |
---|
242 | | - spin_unlock_irqrestore(&sqp->s_lock, flags); |
---|
243 | | - |
---|
244 | | - if (!qp || !(ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) || |
---|
245 | | - qp->ibqp.qp_type != sqp->ibqp.qp_type) { |
---|
246 | | - ibp->rvp.n_pkt_drops++; |
---|
247 | | - /* |
---|
248 | | - * For RC, the requester would timeout and retry so |
---|
249 | | - * shortcut the timeouts and just signal too many retries. |
---|
250 | | - */ |
---|
251 | | - if (sqp->ibqp.qp_type == IB_QPT_RC) |
---|
252 | | - send_status = IB_WC_RETRY_EXC_ERR; |
---|
253 | | - else |
---|
254 | | - send_status = IB_WC_SUCCESS; |
---|
255 | | - goto serr; |
---|
256 | | - } |
---|
257 | | - |
---|
258 | | - memset(&wc, 0, sizeof(wc)); |
---|
259 | | - send_status = IB_WC_SUCCESS; |
---|
260 | | - |
---|
261 | | - release = 1; |
---|
262 | | - sqp->s_sge.sge = wqe->sg_list[0]; |
---|
263 | | - sqp->s_sge.sg_list = wqe->sg_list + 1; |
---|
264 | | - sqp->s_sge.num_sge = wqe->wr.num_sge; |
---|
265 | | - sqp->s_len = wqe->length; |
---|
266 | | - switch (wqe->wr.opcode) { |
---|
267 | | - case IB_WR_SEND_WITH_IMM: |
---|
268 | | - wc.wc_flags = IB_WC_WITH_IMM; |
---|
269 | | - wc.ex.imm_data = wqe->wr.ex.imm_data; |
---|
270 | | - /* FALLTHROUGH */ |
---|
271 | | - case IB_WR_SEND: |
---|
272 | | - ret = rvt_get_rwqe(qp, false); |
---|
273 | | - if (ret < 0) |
---|
274 | | - goto op_err; |
---|
275 | | - if (!ret) |
---|
276 | | - goto rnr_nak; |
---|
277 | | - if (wqe->length > qp->r_len) |
---|
278 | | - goto inv_err; |
---|
279 | | - break; |
---|
280 | | - |
---|
281 | | - case IB_WR_RDMA_WRITE_WITH_IMM: |
---|
282 | | - if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE))) |
---|
283 | | - goto inv_err; |
---|
284 | | - wc.wc_flags = IB_WC_WITH_IMM; |
---|
285 | | - wc.ex.imm_data = wqe->wr.ex.imm_data; |
---|
286 | | - ret = rvt_get_rwqe(qp, true); |
---|
287 | | - if (ret < 0) |
---|
288 | | - goto op_err; |
---|
289 | | - if (!ret) |
---|
290 | | - goto rnr_nak; |
---|
291 | | - /* FALLTHROUGH */ |
---|
292 | | - case IB_WR_RDMA_WRITE: |
---|
293 | | - if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE))) |
---|
294 | | - goto inv_err; |
---|
295 | | - if (wqe->length == 0) |
---|
296 | | - break; |
---|
297 | | - if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, wqe->length, |
---|
298 | | - wqe->rdma_wr.remote_addr, |
---|
299 | | - wqe->rdma_wr.rkey, |
---|
300 | | - IB_ACCESS_REMOTE_WRITE))) |
---|
301 | | - goto acc_err; |
---|
302 | | - qp->r_sge.sg_list = NULL; |
---|
303 | | - qp->r_sge.num_sge = 1; |
---|
304 | | - qp->r_sge.total_len = wqe->length; |
---|
305 | | - break; |
---|
306 | | - |
---|
307 | | - case IB_WR_RDMA_READ: |
---|
308 | | - if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ))) |
---|
309 | | - goto inv_err; |
---|
310 | | - if (unlikely(!rvt_rkey_ok(qp, &sqp->s_sge.sge, wqe->length, |
---|
311 | | - wqe->rdma_wr.remote_addr, |
---|
312 | | - wqe->rdma_wr.rkey, |
---|
313 | | - IB_ACCESS_REMOTE_READ))) |
---|
314 | | - goto acc_err; |
---|
315 | | - release = 0; |
---|
316 | | - sqp->s_sge.sg_list = NULL; |
---|
317 | | - sqp->s_sge.num_sge = 1; |
---|
318 | | - qp->r_sge.sge = wqe->sg_list[0]; |
---|
319 | | - qp->r_sge.sg_list = wqe->sg_list + 1; |
---|
320 | | - qp->r_sge.num_sge = wqe->wr.num_sge; |
---|
321 | | - qp->r_sge.total_len = wqe->length; |
---|
322 | | - break; |
---|
323 | | - |
---|
324 | | - case IB_WR_ATOMIC_CMP_AND_SWP: |
---|
325 | | - case IB_WR_ATOMIC_FETCH_AND_ADD: |
---|
326 | | - if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC))) |
---|
327 | | - goto inv_err; |
---|
328 | | - if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64), |
---|
329 | | - wqe->atomic_wr.remote_addr, |
---|
330 | | - wqe->atomic_wr.rkey, |
---|
331 | | - IB_ACCESS_REMOTE_ATOMIC))) |
---|
332 | | - goto acc_err; |
---|
333 | | - /* Perform atomic OP and save result. */ |
---|
334 | | - maddr = (atomic64_t *) qp->r_sge.sge.vaddr; |
---|
335 | | - sdata = wqe->atomic_wr.compare_add; |
---|
336 | | - *(u64 *) sqp->s_sge.sge.vaddr = |
---|
337 | | - (wqe->atomic_wr.wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) ? |
---|
338 | | - (u64) atomic64_add_return(sdata, maddr) - sdata : |
---|
339 | | - (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr, |
---|
340 | | - sdata, wqe->atomic_wr.swap); |
---|
341 | | - rvt_put_mr(qp->r_sge.sge.mr); |
---|
342 | | - qp->r_sge.num_sge = 0; |
---|
343 | | - goto send_comp; |
---|
344 | | - |
---|
345 | | - default: |
---|
346 | | - send_status = IB_WC_LOC_QP_OP_ERR; |
---|
347 | | - goto serr; |
---|
348 | | - } |
---|
349 | | - |
---|
350 | | - sge = &sqp->s_sge.sge; |
---|
351 | | - while (sqp->s_len) { |
---|
352 | | - u32 len = sqp->s_len; |
---|
353 | | - |
---|
354 | | - if (len > sge->length) |
---|
355 | | - len = sge->length; |
---|
356 | | - if (len > sge->sge_length) |
---|
357 | | - len = sge->sge_length; |
---|
358 | | - BUG_ON(len == 0); |
---|
359 | | - qib_copy_sge(&qp->r_sge, sge->vaddr, len, release); |
---|
360 | | - sge->vaddr += len; |
---|
361 | | - sge->length -= len; |
---|
362 | | - sge->sge_length -= len; |
---|
363 | | - if (sge->sge_length == 0) { |
---|
364 | | - if (!release) |
---|
365 | | - rvt_put_mr(sge->mr); |
---|
366 | | - if (--sqp->s_sge.num_sge) |
---|
367 | | - *sge = *sqp->s_sge.sg_list++; |
---|
368 | | - } else if (sge->length == 0 && sge->mr->lkey) { |
---|
369 | | - if (++sge->n >= RVT_SEGSZ) { |
---|
370 | | - if (++sge->m >= sge->mr->mapsz) |
---|
371 | | - break; |
---|
372 | | - sge->n = 0; |
---|
373 | | - } |
---|
374 | | - sge->vaddr = |
---|
375 | | - sge->mr->map[sge->m]->segs[sge->n].vaddr; |
---|
376 | | - sge->length = |
---|
377 | | - sge->mr->map[sge->m]->segs[sge->n].length; |
---|
378 | | - } |
---|
379 | | - sqp->s_len -= len; |
---|
380 | | - } |
---|
381 | | - if (release) |
---|
382 | | - rvt_put_ss(&qp->r_sge); |
---|
383 | | - |
---|
384 | | - if (!test_and_clear_bit(RVT_R_WRID_VALID, &qp->r_aflags)) |
---|
385 | | - goto send_comp; |
---|
386 | | - |
---|
387 | | - if (wqe->wr.opcode == IB_WR_RDMA_WRITE_WITH_IMM) |
---|
388 | | - wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; |
---|
389 | | - else |
---|
390 | | - wc.opcode = IB_WC_RECV; |
---|
391 | | - wc.wr_id = qp->r_wr_id; |
---|
392 | | - wc.status = IB_WC_SUCCESS; |
---|
393 | | - wc.byte_len = wqe->length; |
---|
394 | | - wc.qp = &qp->ibqp; |
---|
395 | | - wc.src_qp = qp->remote_qpn; |
---|
396 | | - wc.slid = rdma_ah_get_dlid(&qp->remote_ah_attr); |
---|
397 | | - wc.sl = rdma_ah_get_sl(&qp->remote_ah_attr); |
---|
398 | | - wc.port_num = 1; |
---|
399 | | - /* Signal completion event if the solicited bit is set. */ |
---|
400 | | - rvt_cq_enter(ibcq_to_rvtcq(qp->ibqp.recv_cq), &wc, |
---|
401 | | - wqe->wr.send_flags & IB_SEND_SOLICITED); |
---|
402 | | - |
---|
403 | | -send_comp: |
---|
404 | | - spin_lock_irqsave(&sqp->s_lock, flags); |
---|
405 | | - ibp->rvp.n_loop_pkts++; |
---|
406 | | -flush_send: |
---|
407 | | - sqp->s_rnr_retry = sqp->s_rnr_retry_cnt; |
---|
408 | | - qib_send_complete(sqp, wqe, send_status); |
---|
409 | | - goto again; |
---|
410 | | - |
---|
411 | | -rnr_nak: |
---|
412 | | - /* Handle RNR NAK */ |
---|
413 | | - if (qp->ibqp.qp_type == IB_QPT_UC) |
---|
414 | | - goto send_comp; |
---|
415 | | - ibp->rvp.n_rnr_naks++; |
---|
416 | | - /* |
---|
417 | | - * Note: we don't need the s_lock held since the BUSY flag |
---|
418 | | - * makes this single threaded. |
---|
419 | | - */ |
---|
420 | | - if (sqp->s_rnr_retry == 0) { |
---|
421 | | - send_status = IB_WC_RNR_RETRY_EXC_ERR; |
---|
422 | | - goto serr; |
---|
423 | | - } |
---|
424 | | - if (sqp->s_rnr_retry_cnt < 7) |
---|
425 | | - sqp->s_rnr_retry--; |
---|
426 | | - spin_lock_irqsave(&sqp->s_lock, flags); |
---|
427 | | - if (!(ib_rvt_state_ops[sqp->state] & RVT_PROCESS_RECV_OK)) |
---|
428 | | - goto clr_busy; |
---|
429 | | - rvt_add_rnr_timer(sqp, qp->r_min_rnr_timer << |
---|
430 | | - IB_AETH_CREDIT_SHIFT); |
---|
431 | | - goto clr_busy; |
---|
432 | | - |
---|
433 | | -op_err: |
---|
434 | | - send_status = IB_WC_REM_OP_ERR; |
---|
435 | | - wc.status = IB_WC_LOC_QP_OP_ERR; |
---|
436 | | - goto err; |
---|
437 | | - |
---|
438 | | -inv_err: |
---|
439 | | - send_status = |
---|
440 | | - sqp->ibqp.qp_type == IB_QPT_RC ? |
---|
441 | | - IB_WC_REM_INV_REQ_ERR : |
---|
442 | | - IB_WC_SUCCESS; |
---|
443 | | - wc.status = IB_WC_LOC_QP_OP_ERR; |
---|
444 | | - goto err; |
---|
445 | | - |
---|
446 | | -acc_err: |
---|
447 | | - send_status = IB_WC_REM_ACCESS_ERR; |
---|
448 | | - wc.status = IB_WC_LOC_PROT_ERR; |
---|
449 | | -err: |
---|
450 | | - /* responder goes to error state */ |
---|
451 | | - rvt_rc_error(qp, wc.status); |
---|
452 | | - |
---|
453 | | -serr: |
---|
454 | | - spin_lock_irqsave(&sqp->s_lock, flags); |
---|
455 | | - qib_send_complete(sqp, wqe, send_status); |
---|
456 | | - if (sqp->ibqp.qp_type == IB_QPT_RC) { |
---|
457 | | - int lastwqe = rvt_error_qp(sqp, IB_WC_WR_FLUSH_ERR); |
---|
458 | | - |
---|
459 | | - sqp->s_flags &= ~RVT_S_BUSY; |
---|
460 | | - spin_unlock_irqrestore(&sqp->s_lock, flags); |
---|
461 | | - if (lastwqe) { |
---|
462 | | - struct ib_event ev; |
---|
463 | | - |
---|
464 | | - ev.device = sqp->ibqp.device; |
---|
465 | | - ev.element.qp = &sqp->ibqp; |
---|
466 | | - ev.event = IB_EVENT_QP_LAST_WQE_REACHED; |
---|
467 | | - sqp->ibqp.event_handler(&ev, sqp->ibqp.qp_context); |
---|
468 | | - } |
---|
469 | | - goto done; |
---|
470 | | - } |
---|
471 | | -clr_busy: |
---|
472 | | - sqp->s_flags &= ~RVT_S_BUSY; |
---|
473 | | -unlock: |
---|
474 | | - spin_unlock_irqrestore(&sqp->s_lock, flags); |
---|
475 | | -done: |
---|
476 | | - rcu_read_unlock(); |
---|
477 | | -} |
---|
478 | | - |
---|
479 | | -/** |
---|
480 | 174 | * qib_make_grh - construct a GRH header |
---|
481 | 175 | * @ibp: a pointer to the IB port |
---|
482 | 176 | * @hdr: a pointer to the GRH header being constructed |
---|
.. | .. |
---|
578 | 272 | qp->ibqp.qp_type == IB_QPT_UC) && |
---|
579 | 273 | (rdma_ah_get_dlid(&qp->remote_ah_attr) & |
---|
580 | 274 | ~((1 << ppd->lmc) - 1)) == ppd->lid) { |
---|
581 | | - qib_ruc_loopback(qp); |
---|
| 275 | + rvt_ruc_loopback(qp); |
---|
582 | 276 | return; |
---|
583 | 277 | } |
---|
584 | 278 | |
---|
.. | .. |
---|
617 | 311 | } while (make_req(qp, &flags)); |
---|
618 | 312 | |
---|
619 | 313 | spin_unlock_irqrestore(&qp->s_lock, flags); |
---|
620 | | -} |
---|
621 | | - |
---|
622 | | -/* |
---|
623 | | - * This should be called with s_lock held. |
---|
624 | | - */ |
---|
625 | | -void qib_send_complete(struct rvt_qp *qp, struct rvt_swqe *wqe, |
---|
626 | | - enum ib_wc_status status) |
---|
627 | | -{ |
---|
628 | | - u32 old_last, last; |
---|
629 | | - |
---|
630 | | - if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_OR_FLUSH_SEND)) |
---|
631 | | - return; |
---|
632 | | - |
---|
633 | | - last = qp->s_last; |
---|
634 | | - old_last = last; |
---|
635 | | - if (++last >= qp->s_size) |
---|
636 | | - last = 0; |
---|
637 | | - qp->s_last = last; |
---|
638 | | - /* See post_send() */ |
---|
639 | | - barrier(); |
---|
640 | | - rvt_put_swqe(wqe); |
---|
641 | | - if (qp->ibqp.qp_type == IB_QPT_UD || |
---|
642 | | - qp->ibqp.qp_type == IB_QPT_SMI || |
---|
643 | | - qp->ibqp.qp_type == IB_QPT_GSI) |
---|
644 | | - atomic_dec(&ibah_to_rvtah(wqe->ud_wr.ah)->refcount); |
---|
645 | | - |
---|
646 | | - rvt_qp_swqe_complete(qp, |
---|
647 | | - wqe, |
---|
648 | | - ib_qib_wc_opcode[wqe->wr.opcode], |
---|
649 | | - status); |
---|
650 | | - |
---|
651 | | - if (qp->s_acked == old_last) |
---|
652 | | - qp->s_acked = last; |
---|
653 | | - if (qp->s_cur == old_last) |
---|
654 | | - qp->s_cur = last; |
---|
655 | | - if (qp->s_tail == old_last) |
---|
656 | | - qp->s_tail = last; |
---|
657 | | - if (qp->state == IB_QPS_SQD && last == qp->s_cur) |
---|
658 | | - qp->s_draining = 0; |
---|
659 | 314 | } |
---|