/* * Move all CQEs from the HWCQ into the SWCQ. */ void c4iw_flush_hw_cq(struct t4_cq *cq) { struct t4_cqe *cqe = NULL, *swcqe; int ret; PDBG("%s cq %p cqid 0x%x\n", __func__, cq, cq->cqid); ret = t4_next_hw_cqe(cq, &cqe); while (!ret) { PDBG("%s flushing hwcq cidx 0x%x swcq pidx 0x%x\n", __func__, cq->cidx, cq->sw_pidx); swcqe = &cq->sw_queue[cq->sw_pidx]; *swcqe = *cqe; swcqe->header |= cpu_to_be32(V_CQE_SWCQE(1)); t4_swcq_produce(cq); t4_hwcq_consume(cq); ret = t4_next_hw_cqe(cq, &cqe); } }
/* * Move all CQEs from the HWCQ into the SWCQ. * Deal with out-of-order and/or completions that complete * prior unsignalled WRs. */ void c4iw_flush_hw_cq(struct c4iw_cq *chp, struct c4iw_qp *flush_qhp) { struct t4_cqe *hw_cqe, *swcqe, read_cqe; struct c4iw_qp *qhp; struct t4_swsqe *swsqe; int ret; pr_debug("cqid 0x%x\n", chp->cq.cqid); ret = t4_next_hw_cqe(&chp->cq, &hw_cqe); /* * This logic is similar to poll_cq(), but not quite the same * unfortunately. Need to move pertinent HW CQEs to the SW CQ but * also do any translation magic that poll_cq() normally does. */ while (!ret) { qhp = get_qhp(chp->rhp, CQE_QPID(hw_cqe)); /* * drop CQEs with no associated QP */ if (qhp == NULL) goto next_cqe; if (flush_qhp != qhp) { spin_lock(&qhp->lock); if (qhp->wq.flushed == 1) goto next_cqe; } if (CQE_OPCODE(hw_cqe) == FW_RI_TERMINATE) goto next_cqe; if (CQE_OPCODE(hw_cqe) == FW_RI_READ_RESP) { /* If we have reached here because of async * event or other error, and have egress error * then drop */ if (CQE_TYPE(hw_cqe) == 1) goto next_cqe; /* drop peer2peer RTR reads. */ if (CQE_WRID_STAG(hw_cqe) == 1) goto next_cqe; /* * Eat completions for unsignaled read WRs. */ if (!qhp->wq.sq.oldest_read->signaled) { advance_oldest_read(&qhp->wq); goto next_cqe; } /* * Don't write to the HWCQ, create a new read req CQE * in local memory and move it into the swcq. */ create_read_req_cqe(&qhp->wq, hw_cqe, &read_cqe); hw_cqe = &read_cqe; advance_oldest_read(&qhp->wq); } /* if its a SQ completion, then do the magic to move all the * unsignaled and now in-order completions into the swcq. */ if (SQ_TYPE(hw_cqe)) { swsqe = &qhp->wq.sq.sw_sq[CQE_WRID_SQ_IDX(hw_cqe)]; swsqe->cqe = *hw_cqe; swsqe->complete = 1; flush_completed_wrs(&qhp->wq, &chp->cq); } else { swcqe = &chp->cq.sw_queue[chp->cq.sw_pidx]; *swcqe = *hw_cqe; swcqe->header |= cpu_to_be32(CQE_SWCQE_V(1)); t4_swcq_produce(&chp->cq); } next_cqe: t4_hwcq_consume(&chp->cq); ret = t4_next_hw_cqe(&chp->cq, &hw_cqe); if (qhp && flush_qhp != qhp) spin_unlock(&qhp->lock); } }