From: Wei Lin Guay Date: Fri, 5 Aug 2016 13:02:07 +0000 (+0200) Subject: sif: sq/rq: Do not generate completion if target CQ is full X-Git-Tag: v4.1.12-92~87^2~10 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=9745683626e951ef513b95769f937cfbba2f3b3e;p=users%2Fjedix%2Flinux-maple.git sif: sq/rq: Do not generate completion if target CQ is full Orabug: 24378690 SIF driver needs to generate FLUSHED-IN-ERR completions using pqp during the QP tear down phase. Neverthelss, a faulty application or an application that does not rely on the completion (e.g ibv_*pingpong) might cause pqp to generate completion to a full CQ. Consequently, the pqp transitions to ERR state, and this will eventually cause the system to crash. This patch checks for this scenario to prevent system crash. Signed-off-by: Wei Lin Guay Reviewed-by: HÃ¥kon Bugge Reviewed-by: Knut Omang --- diff --git a/drivers/infiniband/hw/sif/sif_r3.c b/drivers/infiniband/hw/sif/sif_r3.c index b9a996ec12ce..133f952a31d7 100644 --- a/drivers/infiniband/hw/sif/sif_r3.c +++ b/drivers/infiniband/hw/sif/sif_r3.c @@ -694,6 +694,12 @@ flush_sq_again: last_seq, last_gen_seq); for (; (!GREATER_16(last_seq, last_gen_seq)); ++last_seq) { + if (unlikely(cq->entries < ((u32) (last_seq - sq_sw->head_seq)))) { + sif_log(sdev, SIF_INFO, "cq (%d) is full! (len = %d, used = %d)", + cq->index, cq->entries, last_seq - sq_sw->head_seq - 1 ); + goto err_post_wa4074; + } + sif_log(sdev, SIF_WCE_V, "generate completion %x", last_seq); diff --git a/drivers/infiniband/hw/sif/sif_rq.c b/drivers/infiniband/hw/sif/sif_rq.c index 387192695c8e..8cad3c75fd28 100644 --- a/drivers/infiniband/hw/sif/sif_rq.c +++ b/drivers/infiniband/hw/sif/sif_rq.c @@ -336,6 +336,7 @@ static void sif_flush_rq(struct work_struct *work) u32 head, tail; unsigned long flags; enum sif_mqp_type mqp_type = SIF_MQP_SW; + struct sif_cq *cq = rq ? get_sif_cq(sdev, rq->cq_idx) : NULL; DECLARE_SIF_CQE_POLL(sdev, lcqe); /* if flush RQ is in progress, set FLUSH_RQ_IN_FLIGHT. @@ -468,7 +469,6 @@ flush_rq_again: if ((lqps.state.expected_opcode != NO_OPERATION_IN_PROGRESS) && (lqps.state.committed_received_psn + 1 == lqps.state.expected_psn)) { int entries; - struct sif_cq *cq = get_sif_cq(sdev, lqps.state.rcv_cq_indx); struct sif_cq_sw *cq_sw; unsigned long timeout; @@ -514,7 +514,14 @@ flush_rq_again: * these give no pqp completions but may in theory fail */ while (real_len > 0) { + if (unlikely(cq->entries < ((u32) atomic_read(&rq_sw->length)))) { + sif_log(sdev, SIF_INFO, "cq (%d) is full! (len = %d, used = %d)", + cq->index, cq->entries, atomic_read(&rq_sw->length)); + goto free_rq_error; + } + sif_log(sdev, SIF_PQP, "rq %d, len %d", rq->index, real_len); + ret = sif_gen_rq_flush_cqe(sdev, rq, head, target_qp); if (ret) sif_log(sdev, SIF_INFO, "rq %d, len %d, sif_gen_rq_flush_cqe returned %d",