Commit 4bb02e95 authored by Mike Marciniszyn's avatar Mike Marciniszyn Committed by Doug Ledford

IB/hfi1: Use aborts to trigger RC throttling

SDMA and pio flushes will cause a lot of packets to be transmitted
after a link has gone down, using a lot of CPU to retransmit
packets.

Fix for RC QPs by recognizing the flush status and:
- Forcing a timer start
- Putting the QP into a "send one" mode

Fixes: 77241056 ("IB/hfi1: add driver files")
Reviewed-by: default avatarKaike Wan <kaike.wan@intel.com>
Signed-off-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 9755f724
...@@ -1701,6 +1701,36 @@ static void reset_sending_psn(struct rvt_qp *qp, u32 psn) ...@@ -1701,6 +1701,36 @@ static void reset_sending_psn(struct rvt_qp *qp, u32 psn)
} }
} }
/**
* hfi1_rc_verbs_aborted - handle abort status
* @qp: the QP
* @opah: the opa header
*
* This code modifies both ACK bit in BTH[2]
* and the s_flags to go into send one mode.
*
* This serves to throttle the send engine to only
* send a single packet in the likely case the
* a link has gone down.
*/
void hfi1_rc_verbs_aborted(struct rvt_qp *qp, struct hfi1_opa_header *opah)
{
struct ib_other_headers *ohdr = hfi1_get_rc_ohdr(opah);
u8 opcode = ib_bth_get_opcode(ohdr);
u32 psn;
/* ignore responses */
if ((opcode >= OP(RDMA_READ_RESPONSE_FIRST) &&
opcode <= OP(ATOMIC_ACKNOWLEDGE)) ||
opcode == TID_OP(READ_RESP) ||
opcode == TID_OP(WRITE_RESP))
return;
psn = ib_bth_get_psn(ohdr) | IB_BTH_REQ_ACK;
ohdr->bth[2] = cpu_to_be32(psn);
qp->s_flags |= RVT_S_SEND_ONE;
}
/* /*
* This should be called with the QP s_lock held and interrupts disabled. * This should be called with the QP s_lock held and interrupts disabled.
*/ */
......
...@@ -638,6 +638,8 @@ static void verbs_sdma_complete( ...@@ -638,6 +638,8 @@ static void verbs_sdma_complete(
struct hfi1_opa_header *hdr; struct hfi1_opa_header *hdr;
hdr = &tx->phdr.hdr; hdr = &tx->phdr.hdr;
if (unlikely(status == SDMA_TXREQ_S_ABORTED))
hfi1_rc_verbs_aborted(qp, hdr);
hfi1_rc_send_complete(qp, hdr); hfi1_rc_send_complete(qp, hdr);
} }
spin_unlock(&qp->s_lock); spin_unlock(&qp->s_lock);
...@@ -1095,15 +1097,15 @@ int hfi1_verbs_send_pio(struct rvt_qp *qp, struct hfi1_pkt_state *ps, ...@@ -1095,15 +1097,15 @@ int hfi1_verbs_send_pio(struct rvt_qp *qp, struct hfi1_pkt_state *ps,
&ps->s_txreq->phdr.hdr, ib_is_sc5(sc5)); &ps->s_txreq->phdr.hdr, ib_is_sc5(sc5));
pio_bail: pio_bail:
spin_lock_irqsave(&qp->s_lock, flags);
if (qp->s_wqe) { if (qp->s_wqe) {
spin_lock_irqsave(&qp->s_lock, flags);
rvt_send_complete(qp, qp->s_wqe, wc_status); rvt_send_complete(qp, qp->s_wqe, wc_status);
spin_unlock_irqrestore(&qp->s_lock, flags);
} else if (qp->ibqp.qp_type == IB_QPT_RC) { } else if (qp->ibqp.qp_type == IB_QPT_RC) {
spin_lock_irqsave(&qp->s_lock, flags); if (unlikely(wc_status == IB_WC_GENERAL_ERR))
hfi1_rc_verbs_aborted(qp, &ps->s_txreq->phdr.hdr);
hfi1_rc_send_complete(qp, &ps->s_txreq->phdr.hdr); hfi1_rc_send_complete(qp, &ps->s_txreq->phdr.hdr);
spin_unlock_irqrestore(&qp->s_lock, flags);
} }
spin_unlock_irqrestore(&qp->s_lock, flags);
ret = 0; ret = 0;
......
...@@ -416,6 +416,7 @@ void hfi1_rc_hdrerr( ...@@ -416,6 +416,7 @@ void hfi1_rc_hdrerr(
u8 ah_to_sc(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr); u8 ah_to_sc(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr);
void hfi1_rc_verbs_aborted(struct rvt_qp *qp, struct hfi1_opa_header *opah);
void hfi1_rc_send_complete(struct rvt_qp *qp, struct hfi1_opa_header *opah); void hfi1_rc_send_complete(struct rvt_qp *qp, struct hfi1_opa_header *opah);
void hfi1_ud_rcv(struct hfi1_packet *packet); void hfi1_ud_rcv(struct hfi1_packet *packet);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment