static void irdma_process_aeq()

in hw/irdma/hw.c [202:413]


static void irdma_process_aeq(struct irdma_pci_f *rf)
{
	struct irdma_sc_dev *dev = &rf->sc_dev;
	struct irdma_aeq *aeq = &rf->aeq;
	struct irdma_sc_aeq *sc_aeq = &aeq->sc_aeq;
	struct irdma_aeqe_info aeinfo;
	struct irdma_aeqe_info *info = &aeinfo;
	int ret;
	struct irdma_qp *iwqp = NULL;
	struct irdma_sc_cq *cq = NULL;
	struct irdma_cq *iwcq = NULL;
	struct irdma_sc_qp *qp = NULL;
	struct irdma_qp_host_ctx_info *ctx_info = NULL;
	struct irdma_device *iwdev = rf->iwdev;
	unsigned long flags;

	u32 aeqcnt = 0;

	if (!sc_aeq->size)
		return;

	do {
		memset(info, 0, sizeof(*info));
		ret = irdma_sc_get_next_aeqe(sc_aeq, info);
		if (ret)
			break;

		aeqcnt++;
		ibdev_dbg(&iwdev->ibdev,
			  "AEQ: ae_id = 0x%x bool qp=%d qp_id = %d tcp_state=%d iwarp_state=%d ae_src=%d\n",
			  info->ae_id, info->qp, info->qp_cq_id, info->tcp_state,
			  info->iwarp_state, info->ae_src);

		if (info->qp) {
			spin_lock_irqsave(&rf->qptable_lock, flags);
			iwqp = rf->qp_table[info->qp_cq_id];
			if (!iwqp) {
				spin_unlock_irqrestore(&rf->qptable_lock,
						       flags);
				if (info->ae_id == IRDMA_AE_QP_SUSPEND_COMPLETE) {
					atomic_dec(&iwdev->vsi.qp_suspend_reqs);
					wake_up(&iwdev->suspend_wq);
					continue;
				}
				ibdev_dbg(&iwdev->ibdev, "AEQ: qp_id %d is already freed\n",
					  info->qp_cq_id);
				continue;
			}
			irdma_qp_add_ref(&iwqp->ibqp);
			spin_unlock_irqrestore(&rf->qptable_lock, flags);
			qp = &iwqp->sc_qp;
			spin_lock_irqsave(&iwqp->lock, flags);
			iwqp->hw_tcp_state = info->tcp_state;
			iwqp->hw_iwarp_state = info->iwarp_state;
			if (info->ae_id != IRDMA_AE_QP_SUSPEND_COMPLETE)
				iwqp->last_aeq = info->ae_id;
			spin_unlock_irqrestore(&iwqp->lock, flags);
			ctx_info = &iwqp->ctx_info;
			if (rdma_protocol_roce(&iwqp->iwdev->ibdev, 1))
				ctx_info->roce_info->err_rq_idx_valid = true;
			else
				ctx_info->iwarp_info->err_rq_idx_valid = true;
		} else {
			if (info->ae_id != IRDMA_AE_CQ_OPERATION_ERROR)
				continue;
		}

		switch (info->ae_id) {
			struct irdma_cm_node *cm_node;
		case IRDMA_AE_LLP_CONNECTION_ESTABLISHED:
			cm_node = iwqp->cm_node;
			if (cm_node->accept_pend) {
				atomic_dec(&cm_node->listener->pend_accepts_cnt);
				cm_node->accept_pend = 0;
			}
			iwqp->rts_ae_rcvd = 1;
			wake_up_interruptible(&iwqp->waitq);
			break;
		case IRDMA_AE_LLP_FIN_RECEIVED:
		case IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE:
			if (qp->term_flags)
				break;
			if (atomic_inc_return(&iwqp->close_timer_started) == 1) {
				iwqp->hw_tcp_state = IRDMA_TCP_STATE_CLOSE_WAIT;
				if (iwqp->hw_tcp_state == IRDMA_TCP_STATE_CLOSE_WAIT &&
				    iwqp->ibqp_state == IB_QPS_RTS) {
					irdma_next_iw_state(iwqp,
							    IRDMA_QP_STATE_CLOSING,
							    0, 0, 0);
					irdma_cm_disconn(iwqp);
				}
				irdma_schedule_cm_timer(iwqp->cm_node,
							(struct irdma_puda_buf *)iwqp,
							IRDMA_TIMER_TYPE_CLOSE,
							1, 0);
			}
			break;
		case IRDMA_AE_LLP_CLOSE_COMPLETE:
			if (qp->term_flags)
				irdma_terminate_done(qp, 0);
			else
				irdma_cm_disconn(iwqp);
			break;
		case IRDMA_AE_BAD_CLOSE:
		case IRDMA_AE_RESET_SENT:
			irdma_next_iw_state(iwqp, IRDMA_QP_STATE_ERROR, 1, 0,
					    0);
			irdma_cm_disconn(iwqp);
			break;
		case IRDMA_AE_LLP_CONNECTION_RESET:
			if (atomic_read(&iwqp->close_timer_started))
				break;
			irdma_cm_disconn(iwqp);
			break;
		case IRDMA_AE_QP_SUSPEND_COMPLETE:
			if (iwqp->iwdev->vsi.tc_change_pending) {
				atomic_dec(&iwqp->sc_qp.vsi->qp_suspend_reqs);
				wake_up(&iwqp->iwdev->suspend_wq);
			}
			break;
		case IRDMA_AE_TERMINATE_SENT:
			irdma_terminate_send_fin(qp);
			break;
		case IRDMA_AE_LLP_TERMINATE_RECEIVED:
			irdma_terminate_received(qp, info);
			break;
		case IRDMA_AE_CQ_OPERATION_ERROR:
			ibdev_err(&iwdev->ibdev,
				  "Processing an iWARP related AE for CQ misc = 0x%04X\n",
				  info->ae_id);
			cq = (struct irdma_sc_cq *)(unsigned long)
			     info->compl_ctx;

			iwcq = cq->back_cq;

			if (iwcq->ibcq.event_handler) {
				struct ib_event ibevent;

				ibevent.device = iwcq->ibcq.device;
				ibevent.event = IB_EVENT_CQ_ERR;
				ibevent.element.cq = &iwcq->ibcq;
				iwcq->ibcq.event_handler(&ibevent,
							 iwcq->ibcq.cq_context);
			}
			break;
		case IRDMA_AE_RESET_NOT_SENT:
		case IRDMA_AE_LLP_DOUBT_REACHABILITY:
		case IRDMA_AE_RESOURCE_EXHAUSTION:
			break;
		case IRDMA_AE_PRIV_OPERATION_DENIED:
		case IRDMA_AE_STAG_ZERO_INVALID:
		case IRDMA_AE_IB_RREQ_AND_Q1_FULL:
		case IRDMA_AE_DDP_UBE_INVALID_DDP_VERSION:
		case IRDMA_AE_DDP_UBE_INVALID_MO:
		case IRDMA_AE_DDP_UBE_INVALID_QN:
		case IRDMA_AE_DDP_NO_L_BIT:
		case IRDMA_AE_RDMAP_ROE_INVALID_RDMAP_VERSION:
		case IRDMA_AE_RDMAP_ROE_UNEXPECTED_OPCODE:
		case IRDMA_AE_ROE_INVALID_RDMA_READ_REQUEST:
		case IRDMA_AE_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
		case IRDMA_AE_INVALID_ARP_ENTRY:
		case IRDMA_AE_INVALID_TCP_OPTION_RCVD:
		case IRDMA_AE_STALE_ARP_ENTRY:
		case IRDMA_AE_LLP_RECEIVED_MPA_CRC_ERROR:
		case IRDMA_AE_LLP_SEGMENT_TOO_SMALL:
		case IRDMA_AE_LLP_SYN_RECEIVED:
		case IRDMA_AE_LLP_TOO_MANY_RETRIES:
		case IRDMA_AE_LCE_QP_CATASTROPHIC:
		case IRDMA_AE_LCE_FUNCTION_CATASTROPHIC:
		case IRDMA_AE_LCE_CQ_CATASTROPHIC:
		case IRDMA_AE_UDA_XMIT_DGRAM_TOO_LONG:
			if (rdma_protocol_roce(&iwdev->ibdev, 1))
				ctx_info->roce_info->err_rq_idx_valid = false;
			else
				ctx_info->iwarp_info->err_rq_idx_valid = false;
			fallthrough;
		default:
			ibdev_err(&iwdev->ibdev, "abnormal ae_id = 0x%x bool qp=%d qp_id = %d\n",
				  info->ae_id, info->qp, info->qp_cq_id);
			if (rdma_protocol_roce(&iwdev->ibdev, 1)) {
				if (!info->sq && ctx_info->roce_info->err_rq_idx_valid) {
					ctx_info->roce_info->err_rq_idx = info->wqe_idx;
					irdma_sc_qp_setctx_roce(&iwqp->sc_qp, iwqp->host_ctx.va,
								ctx_info);
				}
				irdma_set_flush_fields(qp, info);
				irdma_cm_disconn(iwqp);
				break;
			}
			if (!info->sq && ctx_info->iwarp_info->err_rq_idx_valid) {
				ctx_info->iwarp_info->err_rq_idx = info->wqe_idx;
				ctx_info->tcp_info_valid = false;
				ctx_info->iwarp_info_valid = true;
				irdma_sc_qp_setctx(&iwqp->sc_qp, iwqp->host_ctx.va,
						   ctx_info);
			}
			if (iwqp->hw_iwarp_state != IRDMA_QP_STATE_RTS &&
			    iwqp->hw_iwarp_state != IRDMA_QP_STATE_TERMINATE) {
				irdma_next_iw_state(iwqp, IRDMA_QP_STATE_ERROR, 1, 0, 0);
				irdma_cm_disconn(iwqp);
			} else {
				irdma_terminate_connection(qp, info);
			}
			break;
		}
		if (info->qp)
			irdma_qp_rem_ref(&iwqp->ibqp);
	} while (1);

	if (aeqcnt)
		irdma_sc_repost_aeq_entries(dev, aeqcnt);
}