144d9e529SMustafa Ismail // SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB 244d9e529SMustafa Ismail /* Copyright (c) 2015 - 2021 Intel Corporation */ 344d9e529SMustafa Ismail #include "main.h" 444d9e529SMustafa Ismail 544d9e529SMustafa Ismail static struct irdma_rsrc_limits rsrc_limits_table[] = { 644d9e529SMustafa Ismail [0] = { 744d9e529SMustafa Ismail .qplimit = SZ_128, 844d9e529SMustafa Ismail }, 944d9e529SMustafa Ismail [1] = { 1044d9e529SMustafa Ismail .qplimit = SZ_1K, 1144d9e529SMustafa Ismail }, 1244d9e529SMustafa Ismail [2] = { 1344d9e529SMustafa Ismail .qplimit = SZ_2K, 1444d9e529SMustafa Ismail }, 1544d9e529SMustafa Ismail [3] = { 1644d9e529SMustafa Ismail .qplimit = SZ_4K, 1744d9e529SMustafa Ismail }, 1844d9e529SMustafa Ismail [4] = { 1944d9e529SMustafa Ismail .qplimit = SZ_16K, 2044d9e529SMustafa Ismail }, 2144d9e529SMustafa Ismail [5] = { 2244d9e529SMustafa Ismail .qplimit = SZ_64K, 2344d9e529SMustafa Ismail }, 2444d9e529SMustafa Ismail [6] = { 2544d9e529SMustafa Ismail .qplimit = SZ_128K, 2644d9e529SMustafa Ismail }, 2744d9e529SMustafa Ismail [7] = { 2844d9e529SMustafa Ismail .qplimit = SZ_256K, 2944d9e529SMustafa Ismail }, 3044d9e529SMustafa Ismail }; 3144d9e529SMustafa Ismail 3244d9e529SMustafa Ismail /* types of hmc objects */ 3344d9e529SMustafa Ismail static enum irdma_hmc_rsrc_type iw_hmc_obj_types[] = { 3444d9e529SMustafa Ismail IRDMA_HMC_IW_QP, 3544d9e529SMustafa Ismail IRDMA_HMC_IW_CQ, 3644d9e529SMustafa Ismail IRDMA_HMC_IW_HTE, 3744d9e529SMustafa Ismail IRDMA_HMC_IW_ARP, 3844d9e529SMustafa Ismail IRDMA_HMC_IW_APBVT_ENTRY, 3944d9e529SMustafa Ismail IRDMA_HMC_IW_MR, 4044d9e529SMustafa Ismail IRDMA_HMC_IW_XF, 4144d9e529SMustafa Ismail IRDMA_HMC_IW_XFFL, 4244d9e529SMustafa Ismail IRDMA_HMC_IW_Q1, 4344d9e529SMustafa Ismail IRDMA_HMC_IW_Q1FL, 4444d9e529SMustafa Ismail IRDMA_HMC_IW_TIMER, 4544d9e529SMustafa Ismail IRDMA_HMC_IW_FSIMC, 4644d9e529SMustafa Ismail IRDMA_HMC_IW_FSIAV, 4744d9e529SMustafa Ismail IRDMA_HMC_IW_RRF, 4844d9e529SMustafa Ismail IRDMA_HMC_IW_RRFFL, 4944d9e529SMustafa Ismail IRDMA_HMC_IW_HDR, 5044d9e529SMustafa Ismail IRDMA_HMC_IW_MD, 5144d9e529SMustafa Ismail IRDMA_HMC_IW_OOISC, 5244d9e529SMustafa Ismail IRDMA_HMC_IW_OOISCFFL, 5344d9e529SMustafa Ismail }; 5444d9e529SMustafa Ismail 5544d9e529SMustafa Ismail /** 5644d9e529SMustafa Ismail * irdma_iwarp_ce_handler - handle iwarp completions 5744d9e529SMustafa Ismail * @iwcq: iwarp cq receiving event 5844d9e529SMustafa Ismail */ 5944d9e529SMustafa Ismail static void irdma_iwarp_ce_handler(struct irdma_sc_cq *iwcq) 6044d9e529SMustafa Ismail { 6144d9e529SMustafa Ismail struct irdma_cq *cq = iwcq->back_cq; 6244d9e529SMustafa Ismail 6344d9e529SMustafa Ismail if (cq->ibcq.comp_handler) 6444d9e529SMustafa Ismail cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context); 6544d9e529SMustafa Ismail } 6644d9e529SMustafa Ismail 6744d9e529SMustafa Ismail /** 6844d9e529SMustafa Ismail * irdma_puda_ce_handler - handle puda completion events 6944d9e529SMustafa Ismail * @rf: RDMA PCI function 7044d9e529SMustafa Ismail * @cq: puda completion q for event 7144d9e529SMustafa Ismail */ 7244d9e529SMustafa Ismail static void irdma_puda_ce_handler(struct irdma_pci_f *rf, 7344d9e529SMustafa Ismail struct irdma_sc_cq *cq) 7444d9e529SMustafa Ismail { 7544d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 7644d9e529SMustafa Ismail enum irdma_status_code status; 7744d9e529SMustafa Ismail u32 compl_error; 7844d9e529SMustafa Ismail 7944d9e529SMustafa Ismail do { 8044d9e529SMustafa Ismail status = irdma_puda_poll_cmpl(dev, cq, &compl_error); 8144d9e529SMustafa Ismail if (status == IRDMA_ERR_Q_EMPTY) 8244d9e529SMustafa Ismail break; 8344d9e529SMustafa Ismail if (status) { 8444d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), "ERR: puda status = %d\n", status); 8544d9e529SMustafa Ismail break; 8644d9e529SMustafa Ismail } 8744d9e529SMustafa Ismail if (compl_error) { 8844d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), "ERR: puda compl_err =0x%x\n", 8944d9e529SMustafa Ismail compl_error); 9044d9e529SMustafa Ismail break; 9144d9e529SMustafa Ismail } 9244d9e529SMustafa Ismail } while (1); 9344d9e529SMustafa Ismail 9444d9e529SMustafa Ismail irdma_sc_ccq_arm(cq); 9544d9e529SMustafa Ismail } 9644d9e529SMustafa Ismail 9744d9e529SMustafa Ismail /** 9844d9e529SMustafa Ismail * irdma_process_ceq - handle ceq for completions 9944d9e529SMustafa Ismail * @rf: RDMA PCI function 10044d9e529SMustafa Ismail * @ceq: ceq having cq for completion 10144d9e529SMustafa Ismail */ 10244d9e529SMustafa Ismail static void irdma_process_ceq(struct irdma_pci_f *rf, struct irdma_ceq *ceq) 10344d9e529SMustafa Ismail { 10444d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 10544d9e529SMustafa Ismail struct irdma_sc_ceq *sc_ceq; 10644d9e529SMustafa Ismail struct irdma_sc_cq *cq; 10744d9e529SMustafa Ismail unsigned long flags; 10844d9e529SMustafa Ismail 10944d9e529SMustafa Ismail sc_ceq = &ceq->sc_ceq; 11044d9e529SMustafa Ismail do { 11144d9e529SMustafa Ismail spin_lock_irqsave(&ceq->ce_lock, flags); 11244d9e529SMustafa Ismail cq = irdma_sc_process_ceq(dev, sc_ceq); 11344d9e529SMustafa Ismail if (!cq) { 11444d9e529SMustafa Ismail spin_unlock_irqrestore(&ceq->ce_lock, flags); 11544d9e529SMustafa Ismail break; 11644d9e529SMustafa Ismail } 11744d9e529SMustafa Ismail 11844d9e529SMustafa Ismail if (cq->cq_type == IRDMA_CQ_TYPE_IWARP) 11944d9e529SMustafa Ismail irdma_iwarp_ce_handler(cq); 12044d9e529SMustafa Ismail 12144d9e529SMustafa Ismail spin_unlock_irqrestore(&ceq->ce_lock, flags); 12244d9e529SMustafa Ismail 12344d9e529SMustafa Ismail if (cq->cq_type == IRDMA_CQ_TYPE_CQP) 12444d9e529SMustafa Ismail queue_work(rf->cqp_cmpl_wq, &rf->cqp_cmpl_work); 12544d9e529SMustafa Ismail else if (cq->cq_type == IRDMA_CQ_TYPE_ILQ || 12644d9e529SMustafa Ismail cq->cq_type == IRDMA_CQ_TYPE_IEQ) 12744d9e529SMustafa Ismail irdma_puda_ce_handler(rf, cq); 12844d9e529SMustafa Ismail } while (1); 12944d9e529SMustafa Ismail } 13044d9e529SMustafa Ismail 13144d9e529SMustafa Ismail static void irdma_set_flush_fields(struct irdma_sc_qp *qp, 13244d9e529SMustafa Ismail struct irdma_aeqe_info *info) 13344d9e529SMustafa Ismail { 13444d9e529SMustafa Ismail qp->sq_flush_code = info->sq; 13544d9e529SMustafa Ismail qp->rq_flush_code = info->rq; 13644d9e529SMustafa Ismail qp->event_type = IRDMA_QP_EVENT_CATASTROPHIC; 13744d9e529SMustafa Ismail 13844d9e529SMustafa Ismail switch (info->ae_id) { 13944d9e529SMustafa Ismail case IRDMA_AE_AMP_UNALLOCATED_STAG: 14044d9e529SMustafa Ismail case IRDMA_AE_AMP_BOUNDS_VIOLATION: 14144d9e529SMustafa Ismail case IRDMA_AE_AMP_INVALID_STAG: 14244d9e529SMustafa Ismail qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR; 14344d9e529SMustafa Ismail fallthrough; 14444d9e529SMustafa Ismail case IRDMA_AE_AMP_BAD_PD: 14544d9e529SMustafa Ismail case IRDMA_AE_UDA_XMIT_BAD_PD: 14644d9e529SMustafa Ismail qp->flush_code = FLUSH_PROT_ERR; 14744d9e529SMustafa Ismail break; 14844d9e529SMustafa Ismail case IRDMA_AE_AMP_BAD_QP: 14944d9e529SMustafa Ismail qp->flush_code = FLUSH_LOC_QP_OP_ERR; 15044d9e529SMustafa Ismail break; 15144d9e529SMustafa Ismail case IRDMA_AE_AMP_BAD_STAG_KEY: 15244d9e529SMustafa Ismail case IRDMA_AE_AMP_BAD_STAG_INDEX: 15344d9e529SMustafa Ismail case IRDMA_AE_AMP_TO_WRAP: 15444d9e529SMustafa Ismail case IRDMA_AE_AMP_RIGHTS_VIOLATION: 15544d9e529SMustafa Ismail case IRDMA_AE_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS: 15644d9e529SMustafa Ismail case IRDMA_AE_PRIV_OPERATION_DENIED: 15744d9e529SMustafa Ismail case IRDMA_AE_IB_INVALID_REQUEST: 15844d9e529SMustafa Ismail case IRDMA_AE_IB_REMOTE_ACCESS_ERROR: 15944d9e529SMustafa Ismail case IRDMA_AE_IB_REMOTE_OP_ERROR: 16044d9e529SMustafa Ismail qp->flush_code = FLUSH_REM_ACCESS_ERR; 16144d9e529SMustafa Ismail qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR; 16244d9e529SMustafa Ismail break; 16344d9e529SMustafa Ismail case IRDMA_AE_LLP_SEGMENT_TOO_SMALL: 16444d9e529SMustafa Ismail case IRDMA_AE_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER: 16544d9e529SMustafa Ismail case IRDMA_AE_UDA_XMIT_DGRAM_TOO_LONG: 16644d9e529SMustafa Ismail case IRDMA_AE_UDA_XMIT_DGRAM_TOO_SHORT: 16744d9e529SMustafa Ismail case IRDMA_AE_UDA_L4LEN_INVALID: 16844d9e529SMustafa Ismail case IRDMA_AE_ROCE_RSP_LENGTH_ERROR: 16944d9e529SMustafa Ismail qp->flush_code = FLUSH_LOC_LEN_ERR; 17044d9e529SMustafa Ismail break; 17144d9e529SMustafa Ismail case IRDMA_AE_LCE_QP_CATASTROPHIC: 17244d9e529SMustafa Ismail qp->flush_code = FLUSH_FATAL_ERR; 17344d9e529SMustafa Ismail break; 17444d9e529SMustafa Ismail case IRDMA_AE_DDP_UBE_INVALID_MO: 17544d9e529SMustafa Ismail case IRDMA_AE_IB_RREQ_AND_Q1_FULL: 17644d9e529SMustafa Ismail case IRDMA_AE_LLP_RECEIVED_MPA_CRC_ERROR: 17744d9e529SMustafa Ismail qp->flush_code = FLUSH_GENERAL_ERR; 17844d9e529SMustafa Ismail break; 17944d9e529SMustafa Ismail default: 18044d9e529SMustafa Ismail qp->flush_code = FLUSH_FATAL_ERR; 18144d9e529SMustafa Ismail break; 18244d9e529SMustafa Ismail } 18344d9e529SMustafa Ismail } 18444d9e529SMustafa Ismail 18544d9e529SMustafa Ismail /** 18644d9e529SMustafa Ismail * irdma_process_aeq - handle aeq events 18744d9e529SMustafa Ismail * @rf: RDMA PCI function 18844d9e529SMustafa Ismail */ 18944d9e529SMustafa Ismail static void irdma_process_aeq(struct irdma_pci_f *rf) 19044d9e529SMustafa Ismail { 19144d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 19244d9e529SMustafa Ismail struct irdma_aeq *aeq = &rf->aeq; 19344d9e529SMustafa Ismail struct irdma_sc_aeq *sc_aeq = &aeq->sc_aeq; 19444d9e529SMustafa Ismail struct irdma_aeqe_info aeinfo; 19544d9e529SMustafa Ismail struct irdma_aeqe_info *info = &aeinfo; 19644d9e529SMustafa Ismail int ret; 19744d9e529SMustafa Ismail struct irdma_qp *iwqp = NULL; 19844d9e529SMustafa Ismail struct irdma_sc_cq *cq = NULL; 19944d9e529SMustafa Ismail struct irdma_cq *iwcq = NULL; 20044d9e529SMustafa Ismail struct irdma_sc_qp *qp = NULL; 20144d9e529SMustafa Ismail struct irdma_qp_host_ctx_info *ctx_info = NULL; 20244d9e529SMustafa Ismail struct irdma_device *iwdev = rf->iwdev; 20344d9e529SMustafa Ismail unsigned long flags; 20444d9e529SMustafa Ismail 20544d9e529SMustafa Ismail u32 aeqcnt = 0; 20644d9e529SMustafa Ismail 20744d9e529SMustafa Ismail if (!sc_aeq->size) 20844d9e529SMustafa Ismail return; 20944d9e529SMustafa Ismail 21044d9e529SMustafa Ismail do { 21144d9e529SMustafa Ismail memset(info, 0, sizeof(*info)); 21244d9e529SMustafa Ismail ret = irdma_sc_get_next_aeqe(sc_aeq, info); 21344d9e529SMustafa Ismail if (ret) 21444d9e529SMustafa Ismail break; 21544d9e529SMustafa Ismail 21644d9e529SMustafa Ismail aeqcnt++; 21744d9e529SMustafa Ismail ibdev_dbg(&iwdev->ibdev, 21844d9e529SMustafa Ismail "AEQ: ae_id = 0x%x bool qp=%d qp_id = %d tcp_state=%d iwarp_state=%d ae_src=%d\n", 21944d9e529SMustafa Ismail info->ae_id, info->qp, info->qp_cq_id, info->tcp_state, 22044d9e529SMustafa Ismail info->iwarp_state, info->ae_src); 22144d9e529SMustafa Ismail 22244d9e529SMustafa Ismail if (info->qp) { 22344d9e529SMustafa Ismail spin_lock_irqsave(&rf->qptable_lock, flags); 22444d9e529SMustafa Ismail iwqp = rf->qp_table[info->qp_cq_id]; 22544d9e529SMustafa Ismail if (!iwqp) { 22644d9e529SMustafa Ismail spin_unlock_irqrestore(&rf->qptable_lock, 22744d9e529SMustafa Ismail flags); 22844d9e529SMustafa Ismail if (info->ae_id == IRDMA_AE_QP_SUSPEND_COMPLETE) { 22944d9e529SMustafa Ismail atomic_dec(&iwdev->vsi.qp_suspend_reqs); 23044d9e529SMustafa Ismail wake_up(&iwdev->suspend_wq); 23144d9e529SMustafa Ismail continue; 23244d9e529SMustafa Ismail } 23344d9e529SMustafa Ismail ibdev_dbg(&iwdev->ibdev, "AEQ: qp_id %d is already freed\n", 23444d9e529SMustafa Ismail info->qp_cq_id); 23544d9e529SMustafa Ismail continue; 23644d9e529SMustafa Ismail } 23744d9e529SMustafa Ismail irdma_qp_add_ref(&iwqp->ibqp); 23844d9e529SMustafa Ismail spin_unlock_irqrestore(&rf->qptable_lock, flags); 23944d9e529SMustafa Ismail qp = &iwqp->sc_qp; 24044d9e529SMustafa Ismail spin_lock_irqsave(&iwqp->lock, flags); 24144d9e529SMustafa Ismail iwqp->hw_tcp_state = info->tcp_state; 24244d9e529SMustafa Ismail iwqp->hw_iwarp_state = info->iwarp_state; 24344d9e529SMustafa Ismail if (info->ae_id != IRDMA_AE_QP_SUSPEND_COMPLETE) 24444d9e529SMustafa Ismail iwqp->last_aeq = info->ae_id; 24544d9e529SMustafa Ismail spin_unlock_irqrestore(&iwqp->lock, flags); 24644d9e529SMustafa Ismail ctx_info = &iwqp->ctx_info; 24744d9e529SMustafa Ismail if (rdma_protocol_roce(&iwqp->iwdev->ibdev, 1)) 24844d9e529SMustafa Ismail ctx_info->roce_info->err_rq_idx_valid = true; 24944d9e529SMustafa Ismail else 25044d9e529SMustafa Ismail ctx_info->iwarp_info->err_rq_idx_valid = true; 25144d9e529SMustafa Ismail } else { 25244d9e529SMustafa Ismail if (info->ae_id != IRDMA_AE_CQ_OPERATION_ERROR) 25344d9e529SMustafa Ismail continue; 25444d9e529SMustafa Ismail } 25544d9e529SMustafa Ismail 25644d9e529SMustafa Ismail switch (info->ae_id) { 25744d9e529SMustafa Ismail struct irdma_cm_node *cm_node; 25844d9e529SMustafa Ismail case IRDMA_AE_LLP_CONNECTION_ESTABLISHED: 25944d9e529SMustafa Ismail cm_node = iwqp->cm_node; 26044d9e529SMustafa Ismail if (cm_node->accept_pend) { 26144d9e529SMustafa Ismail atomic_dec(&cm_node->listener->pend_accepts_cnt); 26244d9e529SMustafa Ismail cm_node->accept_pend = 0; 26344d9e529SMustafa Ismail } 26444d9e529SMustafa Ismail iwqp->rts_ae_rcvd = 1; 26544d9e529SMustafa Ismail wake_up_interruptible(&iwqp->waitq); 26644d9e529SMustafa Ismail break; 26744d9e529SMustafa Ismail case IRDMA_AE_LLP_FIN_RECEIVED: 26844d9e529SMustafa Ismail case IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE: 26944d9e529SMustafa Ismail if (qp->term_flags) 27044d9e529SMustafa Ismail break; 27144d9e529SMustafa Ismail if (atomic_inc_return(&iwqp->close_timer_started) == 1) { 27244d9e529SMustafa Ismail iwqp->hw_tcp_state = IRDMA_TCP_STATE_CLOSE_WAIT; 27344d9e529SMustafa Ismail if (iwqp->hw_tcp_state == IRDMA_TCP_STATE_CLOSE_WAIT && 27444d9e529SMustafa Ismail iwqp->ibqp_state == IB_QPS_RTS) { 27544d9e529SMustafa Ismail irdma_next_iw_state(iwqp, 27644d9e529SMustafa Ismail IRDMA_QP_STATE_CLOSING, 27744d9e529SMustafa Ismail 0, 0, 0); 27844d9e529SMustafa Ismail irdma_cm_disconn(iwqp); 27944d9e529SMustafa Ismail } 28044d9e529SMustafa Ismail irdma_schedule_cm_timer(iwqp->cm_node, 28144d9e529SMustafa Ismail (struct irdma_puda_buf *)iwqp, 28244d9e529SMustafa Ismail IRDMA_TIMER_TYPE_CLOSE, 28344d9e529SMustafa Ismail 1, 0); 28444d9e529SMustafa Ismail } 28544d9e529SMustafa Ismail break; 28644d9e529SMustafa Ismail case IRDMA_AE_LLP_CLOSE_COMPLETE: 28744d9e529SMustafa Ismail if (qp->term_flags) 28844d9e529SMustafa Ismail irdma_terminate_done(qp, 0); 28944d9e529SMustafa Ismail else 29044d9e529SMustafa Ismail irdma_cm_disconn(iwqp); 29144d9e529SMustafa Ismail break; 29244d9e529SMustafa Ismail case IRDMA_AE_BAD_CLOSE: 29344d9e529SMustafa Ismail case IRDMA_AE_RESET_SENT: 29444d9e529SMustafa Ismail irdma_next_iw_state(iwqp, IRDMA_QP_STATE_ERROR, 1, 0, 29544d9e529SMustafa Ismail 0); 29644d9e529SMustafa Ismail irdma_cm_disconn(iwqp); 29744d9e529SMustafa Ismail break; 29844d9e529SMustafa Ismail case IRDMA_AE_LLP_CONNECTION_RESET: 29944d9e529SMustafa Ismail if (atomic_read(&iwqp->close_timer_started)) 30044d9e529SMustafa Ismail break; 30144d9e529SMustafa Ismail irdma_cm_disconn(iwqp); 30244d9e529SMustafa Ismail break; 30344d9e529SMustafa Ismail case IRDMA_AE_QP_SUSPEND_COMPLETE: 30444d9e529SMustafa Ismail if (iwqp->iwdev->vsi.tc_change_pending) { 30544d9e529SMustafa Ismail atomic_dec(&iwqp->sc_qp.vsi->qp_suspend_reqs); 30644d9e529SMustafa Ismail wake_up(&iwqp->iwdev->suspend_wq); 30744d9e529SMustafa Ismail } 30844d9e529SMustafa Ismail break; 30944d9e529SMustafa Ismail case IRDMA_AE_TERMINATE_SENT: 31044d9e529SMustafa Ismail irdma_terminate_send_fin(qp); 31144d9e529SMustafa Ismail break; 31244d9e529SMustafa Ismail case IRDMA_AE_LLP_TERMINATE_RECEIVED: 31344d9e529SMustafa Ismail irdma_terminate_received(qp, info); 31444d9e529SMustafa Ismail break; 31544d9e529SMustafa Ismail case IRDMA_AE_CQ_OPERATION_ERROR: 31644d9e529SMustafa Ismail ibdev_err(&iwdev->ibdev, 31744d9e529SMustafa Ismail "Processing an iWARP related AE for CQ misc = 0x%04X\n", 31844d9e529SMustafa Ismail info->ae_id); 31944d9e529SMustafa Ismail cq = (struct irdma_sc_cq *)(unsigned long) 32044d9e529SMustafa Ismail info->compl_ctx; 32144d9e529SMustafa Ismail 32244d9e529SMustafa Ismail iwcq = cq->back_cq; 32344d9e529SMustafa Ismail 32444d9e529SMustafa Ismail if (iwcq->ibcq.event_handler) { 32544d9e529SMustafa Ismail struct ib_event ibevent; 32644d9e529SMustafa Ismail 32744d9e529SMustafa Ismail ibevent.device = iwcq->ibcq.device; 32844d9e529SMustafa Ismail ibevent.event = IB_EVENT_CQ_ERR; 32944d9e529SMustafa Ismail ibevent.element.cq = &iwcq->ibcq; 33044d9e529SMustafa Ismail iwcq->ibcq.event_handler(&ibevent, 33144d9e529SMustafa Ismail iwcq->ibcq.cq_context); 33244d9e529SMustafa Ismail } 33344d9e529SMustafa Ismail break; 33444d9e529SMustafa Ismail case IRDMA_AE_RESET_NOT_SENT: 33544d9e529SMustafa Ismail case IRDMA_AE_LLP_DOUBT_REACHABILITY: 33644d9e529SMustafa Ismail case IRDMA_AE_RESOURCE_EXHAUSTION: 33744d9e529SMustafa Ismail break; 33844d9e529SMustafa Ismail case IRDMA_AE_PRIV_OPERATION_DENIED: 33944d9e529SMustafa Ismail case IRDMA_AE_STAG_ZERO_INVALID: 34044d9e529SMustafa Ismail case IRDMA_AE_IB_RREQ_AND_Q1_FULL: 34144d9e529SMustafa Ismail case IRDMA_AE_DDP_UBE_INVALID_DDP_VERSION: 34244d9e529SMustafa Ismail case IRDMA_AE_DDP_UBE_INVALID_MO: 34344d9e529SMustafa Ismail case IRDMA_AE_DDP_UBE_INVALID_QN: 34444d9e529SMustafa Ismail case IRDMA_AE_DDP_NO_L_BIT: 34544d9e529SMustafa Ismail case IRDMA_AE_RDMAP_ROE_INVALID_RDMAP_VERSION: 34644d9e529SMustafa Ismail case IRDMA_AE_RDMAP_ROE_UNEXPECTED_OPCODE: 34744d9e529SMustafa Ismail case IRDMA_AE_ROE_INVALID_RDMA_READ_REQUEST: 34844d9e529SMustafa Ismail case IRDMA_AE_ROE_INVALID_RDMA_WRITE_OR_READ_RESP: 34944d9e529SMustafa Ismail case IRDMA_AE_INVALID_ARP_ENTRY: 35044d9e529SMustafa Ismail case IRDMA_AE_INVALID_TCP_OPTION_RCVD: 35144d9e529SMustafa Ismail case IRDMA_AE_STALE_ARP_ENTRY: 35244d9e529SMustafa Ismail case IRDMA_AE_LLP_RECEIVED_MPA_CRC_ERROR: 35344d9e529SMustafa Ismail case IRDMA_AE_LLP_SEGMENT_TOO_SMALL: 35444d9e529SMustafa Ismail case IRDMA_AE_LLP_SYN_RECEIVED: 35544d9e529SMustafa Ismail case IRDMA_AE_LLP_TOO_MANY_RETRIES: 35644d9e529SMustafa Ismail case IRDMA_AE_LCE_QP_CATASTROPHIC: 35744d9e529SMustafa Ismail case IRDMA_AE_LCE_FUNCTION_CATASTROPHIC: 35844d9e529SMustafa Ismail case IRDMA_AE_LCE_CQ_CATASTROPHIC: 35944d9e529SMustafa Ismail case IRDMA_AE_UDA_XMIT_DGRAM_TOO_LONG: 36044d9e529SMustafa Ismail if (rdma_protocol_roce(&iwdev->ibdev, 1)) 36144d9e529SMustafa Ismail ctx_info->roce_info->err_rq_idx_valid = false; 36244d9e529SMustafa Ismail else 36344d9e529SMustafa Ismail ctx_info->iwarp_info->err_rq_idx_valid = false; 36444d9e529SMustafa Ismail fallthrough; 36544d9e529SMustafa Ismail default: 36644d9e529SMustafa Ismail ibdev_err(&iwdev->ibdev, "abnormal ae_id = 0x%x bool qp=%d qp_id = %d\n", 36744d9e529SMustafa Ismail info->ae_id, info->qp, info->qp_cq_id); 36844d9e529SMustafa Ismail if (rdma_protocol_roce(&iwdev->ibdev, 1)) { 36944d9e529SMustafa Ismail if (!info->sq && ctx_info->roce_info->err_rq_idx_valid) { 37044d9e529SMustafa Ismail ctx_info->roce_info->err_rq_idx = info->wqe_idx; 37144d9e529SMustafa Ismail irdma_sc_qp_setctx_roce(&iwqp->sc_qp, iwqp->host_ctx.va, 37244d9e529SMustafa Ismail ctx_info); 37344d9e529SMustafa Ismail } 37444d9e529SMustafa Ismail irdma_set_flush_fields(qp, info); 37544d9e529SMustafa Ismail irdma_cm_disconn(iwqp); 37644d9e529SMustafa Ismail break; 37744d9e529SMustafa Ismail } 37844d9e529SMustafa Ismail if (!info->sq && ctx_info->iwarp_info->err_rq_idx_valid) { 37944d9e529SMustafa Ismail ctx_info->iwarp_info->err_rq_idx = info->wqe_idx; 38044d9e529SMustafa Ismail ctx_info->tcp_info_valid = false; 38144d9e529SMustafa Ismail ctx_info->iwarp_info_valid = true; 38244d9e529SMustafa Ismail irdma_sc_qp_setctx(&iwqp->sc_qp, iwqp->host_ctx.va, 38344d9e529SMustafa Ismail ctx_info); 38444d9e529SMustafa Ismail } 38544d9e529SMustafa Ismail if (iwqp->hw_iwarp_state != IRDMA_QP_STATE_RTS && 38644d9e529SMustafa Ismail iwqp->hw_iwarp_state != IRDMA_QP_STATE_TERMINATE) { 38744d9e529SMustafa Ismail irdma_next_iw_state(iwqp, IRDMA_QP_STATE_ERROR, 1, 0, 0); 38844d9e529SMustafa Ismail irdma_cm_disconn(iwqp); 38944d9e529SMustafa Ismail } else { 39044d9e529SMustafa Ismail irdma_terminate_connection(qp, info); 39144d9e529SMustafa Ismail } 39244d9e529SMustafa Ismail break; 39344d9e529SMustafa Ismail } 39444d9e529SMustafa Ismail if (info->qp) 39544d9e529SMustafa Ismail irdma_qp_rem_ref(&iwqp->ibqp); 39644d9e529SMustafa Ismail } while (1); 39744d9e529SMustafa Ismail 39844d9e529SMustafa Ismail if (aeqcnt) 39944d9e529SMustafa Ismail irdma_sc_repost_aeq_entries(dev, aeqcnt); 40044d9e529SMustafa Ismail } 40144d9e529SMustafa Ismail 40244d9e529SMustafa Ismail /** 40344d9e529SMustafa Ismail * irdma_ena_intr - set up device interrupts 40444d9e529SMustafa Ismail * @dev: hardware control device structure 40544d9e529SMustafa Ismail * @msix_id: id of the interrupt to be enabled 40644d9e529SMustafa Ismail */ 40744d9e529SMustafa Ismail static void irdma_ena_intr(struct irdma_sc_dev *dev, u32 msix_id) 40844d9e529SMustafa Ismail { 40944d9e529SMustafa Ismail dev->irq_ops->irdma_en_irq(dev, msix_id); 41044d9e529SMustafa Ismail } 41144d9e529SMustafa Ismail 41244d9e529SMustafa Ismail /** 41344d9e529SMustafa Ismail * irdma_dpc - tasklet for aeq and ceq 0 41444d9e529SMustafa Ismail * @t: tasklet_struct ptr 41544d9e529SMustafa Ismail */ 41644d9e529SMustafa Ismail static void irdma_dpc(struct tasklet_struct *t) 41744d9e529SMustafa Ismail { 41844d9e529SMustafa Ismail struct irdma_pci_f *rf = from_tasklet(rf, t, dpc_tasklet); 41944d9e529SMustafa Ismail 42044d9e529SMustafa Ismail if (rf->msix_shared) 42144d9e529SMustafa Ismail irdma_process_ceq(rf, rf->ceqlist); 42244d9e529SMustafa Ismail irdma_process_aeq(rf); 42344d9e529SMustafa Ismail irdma_ena_intr(&rf->sc_dev, rf->iw_msixtbl[0].idx); 42444d9e529SMustafa Ismail } 42544d9e529SMustafa Ismail 42644d9e529SMustafa Ismail /** 42744d9e529SMustafa Ismail * irdma_ceq_dpc - dpc handler for CEQ 42844d9e529SMustafa Ismail * @t: tasklet_struct ptr 42944d9e529SMustafa Ismail */ 43044d9e529SMustafa Ismail static void irdma_ceq_dpc(struct tasklet_struct *t) 43144d9e529SMustafa Ismail { 43244d9e529SMustafa Ismail struct irdma_ceq *iwceq = from_tasklet(iwceq, t, dpc_tasklet); 43344d9e529SMustafa Ismail struct irdma_pci_f *rf = iwceq->rf; 43444d9e529SMustafa Ismail 43544d9e529SMustafa Ismail irdma_process_ceq(rf, iwceq); 43644d9e529SMustafa Ismail irdma_ena_intr(&rf->sc_dev, iwceq->msix_idx); 43744d9e529SMustafa Ismail } 43844d9e529SMustafa Ismail 43944d9e529SMustafa Ismail /** 44044d9e529SMustafa Ismail * irdma_save_msix_info - copy msix vector information to iwarp device 44144d9e529SMustafa Ismail * @rf: RDMA PCI function 44244d9e529SMustafa Ismail * 44344d9e529SMustafa Ismail * Allocate iwdev msix table and copy the msix info to the table 44444d9e529SMustafa Ismail * Return 0 if successful, otherwise return error 44544d9e529SMustafa Ismail */ 44644d9e529SMustafa Ismail static enum irdma_status_code irdma_save_msix_info(struct irdma_pci_f *rf) 44744d9e529SMustafa Ismail { 44844d9e529SMustafa Ismail struct irdma_qvlist_info *iw_qvlist; 44944d9e529SMustafa Ismail struct irdma_qv_info *iw_qvinfo; 45044d9e529SMustafa Ismail struct msix_entry *pmsix; 45144d9e529SMustafa Ismail u32 ceq_idx; 45244d9e529SMustafa Ismail u32 i; 45344d9e529SMustafa Ismail size_t size; 45444d9e529SMustafa Ismail 45544d9e529SMustafa Ismail if (!rf->msix_count) 45644d9e529SMustafa Ismail return IRDMA_ERR_NO_INTR; 45744d9e529SMustafa Ismail 45844d9e529SMustafa Ismail size = sizeof(struct irdma_msix_vector) * rf->msix_count; 45944d9e529SMustafa Ismail size += struct_size(iw_qvlist, qv_info, rf->msix_count); 46044d9e529SMustafa Ismail rf->iw_msixtbl = kzalloc(size, GFP_KERNEL); 46144d9e529SMustafa Ismail if (!rf->iw_msixtbl) 46244d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 46344d9e529SMustafa Ismail 46444d9e529SMustafa Ismail rf->iw_qvlist = (struct irdma_qvlist_info *) 46544d9e529SMustafa Ismail (&rf->iw_msixtbl[rf->msix_count]); 46644d9e529SMustafa Ismail iw_qvlist = rf->iw_qvlist; 46744d9e529SMustafa Ismail iw_qvinfo = iw_qvlist->qv_info; 46844d9e529SMustafa Ismail iw_qvlist->num_vectors = rf->msix_count; 46944d9e529SMustafa Ismail if (rf->msix_count <= num_online_cpus()) 47044d9e529SMustafa Ismail rf->msix_shared = true; 47144d9e529SMustafa Ismail 47244d9e529SMustafa Ismail pmsix = rf->msix_entries; 47344d9e529SMustafa Ismail for (i = 0, ceq_idx = 0; i < rf->msix_count; i++, iw_qvinfo++) { 47444d9e529SMustafa Ismail rf->iw_msixtbl[i].idx = pmsix->entry; 47544d9e529SMustafa Ismail rf->iw_msixtbl[i].irq = pmsix->vector; 47644d9e529SMustafa Ismail rf->iw_msixtbl[i].cpu_affinity = ceq_idx; 47744d9e529SMustafa Ismail if (!i) { 47844d9e529SMustafa Ismail iw_qvinfo->aeq_idx = 0; 47944d9e529SMustafa Ismail if (rf->msix_shared) 48044d9e529SMustafa Ismail iw_qvinfo->ceq_idx = ceq_idx++; 48144d9e529SMustafa Ismail else 48244d9e529SMustafa Ismail iw_qvinfo->ceq_idx = IRDMA_Q_INVALID_IDX; 48344d9e529SMustafa Ismail } else { 48444d9e529SMustafa Ismail iw_qvinfo->aeq_idx = IRDMA_Q_INVALID_IDX; 48544d9e529SMustafa Ismail iw_qvinfo->ceq_idx = ceq_idx++; 48644d9e529SMustafa Ismail } 48744d9e529SMustafa Ismail iw_qvinfo->itr_idx = 3; 48844d9e529SMustafa Ismail iw_qvinfo->v_idx = rf->iw_msixtbl[i].idx; 48944d9e529SMustafa Ismail pmsix++; 49044d9e529SMustafa Ismail } 49144d9e529SMustafa Ismail 49244d9e529SMustafa Ismail return 0; 49344d9e529SMustafa Ismail } 49444d9e529SMustafa Ismail 49544d9e529SMustafa Ismail /** 49644d9e529SMustafa Ismail * irdma_irq_handler - interrupt handler for aeq and ceq0 49744d9e529SMustafa Ismail * @irq: Interrupt request number 49844d9e529SMustafa Ismail * @data: RDMA PCI function 49944d9e529SMustafa Ismail */ 50044d9e529SMustafa Ismail static irqreturn_t irdma_irq_handler(int irq, void *data) 50144d9e529SMustafa Ismail { 50244d9e529SMustafa Ismail struct irdma_pci_f *rf = data; 50344d9e529SMustafa Ismail 50444d9e529SMustafa Ismail tasklet_schedule(&rf->dpc_tasklet); 50544d9e529SMustafa Ismail 50644d9e529SMustafa Ismail return IRQ_HANDLED; 50744d9e529SMustafa Ismail } 50844d9e529SMustafa Ismail 50944d9e529SMustafa Ismail /** 51044d9e529SMustafa Ismail * irdma_ceq_handler - interrupt handler for ceq 51144d9e529SMustafa Ismail * @irq: interrupt request number 51244d9e529SMustafa Ismail * @data: ceq pointer 51344d9e529SMustafa Ismail */ 51444d9e529SMustafa Ismail static irqreturn_t irdma_ceq_handler(int irq, void *data) 51544d9e529SMustafa Ismail { 51644d9e529SMustafa Ismail struct irdma_ceq *iwceq = data; 51744d9e529SMustafa Ismail 51844d9e529SMustafa Ismail if (iwceq->irq != irq) 51944d9e529SMustafa Ismail ibdev_err(to_ibdev(&iwceq->rf->sc_dev), "expected irq = %d received irq = %d\n", 52044d9e529SMustafa Ismail iwceq->irq, irq); 52144d9e529SMustafa Ismail tasklet_schedule(&iwceq->dpc_tasklet); 52244d9e529SMustafa Ismail 52344d9e529SMustafa Ismail return IRQ_HANDLED; 52444d9e529SMustafa Ismail } 52544d9e529SMustafa Ismail 52644d9e529SMustafa Ismail /** 52744d9e529SMustafa Ismail * irdma_destroy_irq - destroy device interrupts 52844d9e529SMustafa Ismail * @rf: RDMA PCI function 52944d9e529SMustafa Ismail * @msix_vec: msix vector to disable irq 53044d9e529SMustafa Ismail * @dev_id: parameter to pass to free_irq (used during irq setup) 53144d9e529SMustafa Ismail * 53244d9e529SMustafa Ismail * The function is called when destroying aeq/ceq 53344d9e529SMustafa Ismail */ 53444d9e529SMustafa Ismail static void irdma_destroy_irq(struct irdma_pci_f *rf, 53544d9e529SMustafa Ismail struct irdma_msix_vector *msix_vec, void *dev_id) 53644d9e529SMustafa Ismail { 53744d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 53844d9e529SMustafa Ismail 53944d9e529SMustafa Ismail dev->irq_ops->irdma_dis_irq(dev, msix_vec->idx); 54044d9e529SMustafa Ismail irq_set_affinity_hint(msix_vec->irq, NULL); 54144d9e529SMustafa Ismail free_irq(msix_vec->irq, dev_id); 54244d9e529SMustafa Ismail } 54344d9e529SMustafa Ismail 54444d9e529SMustafa Ismail /** 54544d9e529SMustafa Ismail * irdma_destroy_cqp - destroy control qp 54644d9e529SMustafa Ismail * @rf: RDMA PCI function 54744d9e529SMustafa Ismail * @free_hwcqp: 1 if hw cqp should be freed 54844d9e529SMustafa Ismail * 54944d9e529SMustafa Ismail * Issue destroy cqp request and 55044d9e529SMustafa Ismail * free the resources associated with the cqp 55144d9e529SMustafa Ismail */ 55244d9e529SMustafa Ismail static void irdma_destroy_cqp(struct irdma_pci_f *rf, bool free_hwcqp) 55344d9e529SMustafa Ismail { 55444d9e529SMustafa Ismail enum irdma_status_code status = 0; 55544d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 55644d9e529SMustafa Ismail struct irdma_cqp *cqp = &rf->cqp; 55744d9e529SMustafa Ismail 55844d9e529SMustafa Ismail if (rf->cqp_cmpl_wq) 55944d9e529SMustafa Ismail destroy_workqueue(rf->cqp_cmpl_wq); 56044d9e529SMustafa Ismail if (free_hwcqp) 56144d9e529SMustafa Ismail status = irdma_sc_cqp_destroy(dev->cqp); 56244d9e529SMustafa Ismail if (status) 56344d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), "ERR: Destroy CQP failed %d\n", status); 56444d9e529SMustafa Ismail 56544d9e529SMustafa Ismail irdma_cleanup_pending_cqp_op(rf); 56644d9e529SMustafa Ismail dma_free_coherent(dev->hw->device, cqp->sq.size, cqp->sq.va, 56744d9e529SMustafa Ismail cqp->sq.pa); 56844d9e529SMustafa Ismail cqp->sq.va = NULL; 56944d9e529SMustafa Ismail kfree(cqp->scratch_array); 57044d9e529SMustafa Ismail cqp->scratch_array = NULL; 57144d9e529SMustafa Ismail kfree(cqp->cqp_requests); 57244d9e529SMustafa Ismail cqp->cqp_requests = NULL; 57344d9e529SMustafa Ismail } 57444d9e529SMustafa Ismail 57544d9e529SMustafa Ismail static void irdma_destroy_virt_aeq(struct irdma_pci_f *rf) 57644d9e529SMustafa Ismail { 57744d9e529SMustafa Ismail struct irdma_aeq *aeq = &rf->aeq; 57844d9e529SMustafa Ismail u32 pg_cnt = DIV_ROUND_UP(aeq->mem.size, PAGE_SIZE); 57944d9e529SMustafa Ismail dma_addr_t *pg_arr = (dma_addr_t *)aeq->palloc.level1.addr; 58044d9e529SMustafa Ismail 58144d9e529SMustafa Ismail irdma_unmap_vm_page_list(&rf->hw, pg_arr, pg_cnt); 58244d9e529SMustafa Ismail irdma_free_pble(rf->pble_rsrc, &aeq->palloc); 58344d9e529SMustafa Ismail vfree(aeq->mem.va); 58444d9e529SMustafa Ismail } 58544d9e529SMustafa Ismail 58644d9e529SMustafa Ismail /** 58744d9e529SMustafa Ismail * irdma_destroy_aeq - destroy aeq 58844d9e529SMustafa Ismail * @rf: RDMA PCI function 58944d9e529SMustafa Ismail * 59044d9e529SMustafa Ismail * Issue a destroy aeq request and 59144d9e529SMustafa Ismail * free the resources associated with the aeq 59244d9e529SMustafa Ismail * The function is called during driver unload 59344d9e529SMustafa Ismail */ 59444d9e529SMustafa Ismail static void irdma_destroy_aeq(struct irdma_pci_f *rf) 59544d9e529SMustafa Ismail { 59644d9e529SMustafa Ismail enum irdma_status_code status = IRDMA_ERR_NOT_READY; 59744d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 59844d9e529SMustafa Ismail struct irdma_aeq *aeq = &rf->aeq; 59944d9e529SMustafa Ismail 60044d9e529SMustafa Ismail if (!rf->msix_shared) { 60144d9e529SMustafa Ismail rf->sc_dev.irq_ops->irdma_cfg_aeq(&rf->sc_dev, rf->iw_msixtbl->idx, false); 60244d9e529SMustafa Ismail irdma_destroy_irq(rf, rf->iw_msixtbl, rf); 60344d9e529SMustafa Ismail } 60444d9e529SMustafa Ismail if (rf->reset) 60544d9e529SMustafa Ismail goto exit; 60644d9e529SMustafa Ismail 60744d9e529SMustafa Ismail aeq->sc_aeq.size = 0; 60844d9e529SMustafa Ismail status = irdma_cqp_aeq_cmd(dev, &aeq->sc_aeq, IRDMA_OP_AEQ_DESTROY); 60944d9e529SMustafa Ismail if (status) 61044d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), "ERR: Destroy AEQ failed %d\n", status); 61144d9e529SMustafa Ismail 61244d9e529SMustafa Ismail exit: 61344d9e529SMustafa Ismail if (aeq->virtual_map) { 61444d9e529SMustafa Ismail irdma_destroy_virt_aeq(rf); 61544d9e529SMustafa Ismail } else { 61644d9e529SMustafa Ismail dma_free_coherent(dev->hw->device, aeq->mem.size, aeq->mem.va, 61744d9e529SMustafa Ismail aeq->mem.pa); 61844d9e529SMustafa Ismail aeq->mem.va = NULL; 61944d9e529SMustafa Ismail } 62044d9e529SMustafa Ismail } 62144d9e529SMustafa Ismail 62244d9e529SMustafa Ismail /** 62344d9e529SMustafa Ismail * irdma_destroy_ceq - destroy ceq 62444d9e529SMustafa Ismail * @rf: RDMA PCI function 62544d9e529SMustafa Ismail * @iwceq: ceq to be destroyed 62644d9e529SMustafa Ismail * 62744d9e529SMustafa Ismail * Issue a destroy ceq request and 62844d9e529SMustafa Ismail * free the resources associated with the ceq 62944d9e529SMustafa Ismail */ 63044d9e529SMustafa Ismail static void irdma_destroy_ceq(struct irdma_pci_f *rf, struct irdma_ceq *iwceq) 63144d9e529SMustafa Ismail { 63244d9e529SMustafa Ismail enum irdma_status_code status; 63344d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 63444d9e529SMustafa Ismail 63544d9e529SMustafa Ismail if (rf->reset) 63644d9e529SMustafa Ismail goto exit; 63744d9e529SMustafa Ismail 63844d9e529SMustafa Ismail status = irdma_sc_ceq_destroy(&iwceq->sc_ceq, 0, 1); 63944d9e529SMustafa Ismail if (status) { 64044d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), "ERR: CEQ destroy command failed %d\n", status); 64144d9e529SMustafa Ismail goto exit; 64244d9e529SMustafa Ismail } 64344d9e529SMustafa Ismail 64444d9e529SMustafa Ismail status = irdma_sc_cceq_destroy_done(&iwceq->sc_ceq); 64544d9e529SMustafa Ismail if (status) 64644d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), "ERR: CEQ destroy completion failed %d\n", 64744d9e529SMustafa Ismail status); 64844d9e529SMustafa Ismail exit: 64944d9e529SMustafa Ismail dma_free_coherent(dev->hw->device, iwceq->mem.size, iwceq->mem.va, 65044d9e529SMustafa Ismail iwceq->mem.pa); 65144d9e529SMustafa Ismail iwceq->mem.va = NULL; 65244d9e529SMustafa Ismail } 65344d9e529SMustafa Ismail 65444d9e529SMustafa Ismail /** 65544d9e529SMustafa Ismail * irdma_del_ceq_0 - destroy ceq 0 65644d9e529SMustafa Ismail * @rf: RDMA PCI function 65744d9e529SMustafa Ismail * 65844d9e529SMustafa Ismail * Disable the ceq 0 interrupt and destroy the ceq 0 65944d9e529SMustafa Ismail */ 66044d9e529SMustafa Ismail static void irdma_del_ceq_0(struct irdma_pci_f *rf) 66144d9e529SMustafa Ismail { 66244d9e529SMustafa Ismail struct irdma_ceq *iwceq = rf->ceqlist; 66344d9e529SMustafa Ismail struct irdma_msix_vector *msix_vec; 66444d9e529SMustafa Ismail 66544d9e529SMustafa Ismail if (rf->msix_shared) { 66644d9e529SMustafa Ismail msix_vec = &rf->iw_msixtbl[0]; 66744d9e529SMustafa Ismail rf->sc_dev.irq_ops->irdma_cfg_ceq(&rf->sc_dev, 66844d9e529SMustafa Ismail msix_vec->ceq_id, 66944d9e529SMustafa Ismail msix_vec->idx, false); 67044d9e529SMustafa Ismail irdma_destroy_irq(rf, msix_vec, rf); 67144d9e529SMustafa Ismail } else { 67244d9e529SMustafa Ismail msix_vec = &rf->iw_msixtbl[1]; 67344d9e529SMustafa Ismail irdma_destroy_irq(rf, msix_vec, iwceq); 67444d9e529SMustafa Ismail } 67544d9e529SMustafa Ismail 67644d9e529SMustafa Ismail irdma_destroy_ceq(rf, iwceq); 67744d9e529SMustafa Ismail rf->sc_dev.ceq_valid = false; 67844d9e529SMustafa Ismail rf->ceqs_count = 0; 67944d9e529SMustafa Ismail } 68044d9e529SMustafa Ismail 68144d9e529SMustafa Ismail /** 68244d9e529SMustafa Ismail * irdma_del_ceqs - destroy all ceq's except CEQ 0 68344d9e529SMustafa Ismail * @rf: RDMA PCI function 68444d9e529SMustafa Ismail * 68544d9e529SMustafa Ismail * Go through all of the device ceq's, except 0, and for each 68644d9e529SMustafa Ismail * ceq disable the ceq interrupt and destroy the ceq 68744d9e529SMustafa Ismail */ 68844d9e529SMustafa Ismail static void irdma_del_ceqs(struct irdma_pci_f *rf) 68944d9e529SMustafa Ismail { 69044d9e529SMustafa Ismail struct irdma_ceq *iwceq = &rf->ceqlist[1]; 69144d9e529SMustafa Ismail struct irdma_msix_vector *msix_vec; 69244d9e529SMustafa Ismail u32 i = 0; 69344d9e529SMustafa Ismail 69444d9e529SMustafa Ismail if (rf->msix_shared) 69544d9e529SMustafa Ismail msix_vec = &rf->iw_msixtbl[1]; 69644d9e529SMustafa Ismail else 69744d9e529SMustafa Ismail msix_vec = &rf->iw_msixtbl[2]; 69844d9e529SMustafa Ismail 69944d9e529SMustafa Ismail for (i = 1; i < rf->ceqs_count; i++, msix_vec++, iwceq++) { 70044d9e529SMustafa Ismail rf->sc_dev.irq_ops->irdma_cfg_ceq(&rf->sc_dev, msix_vec->ceq_id, 70144d9e529SMustafa Ismail msix_vec->idx, false); 70244d9e529SMustafa Ismail irdma_destroy_irq(rf, msix_vec, iwceq); 70344d9e529SMustafa Ismail irdma_cqp_ceq_cmd(&rf->sc_dev, &iwceq->sc_ceq, 70444d9e529SMustafa Ismail IRDMA_OP_CEQ_DESTROY); 70544d9e529SMustafa Ismail dma_free_coherent(rf->sc_dev.hw->device, iwceq->mem.size, 70644d9e529SMustafa Ismail iwceq->mem.va, iwceq->mem.pa); 70744d9e529SMustafa Ismail iwceq->mem.va = NULL; 70844d9e529SMustafa Ismail } 70944d9e529SMustafa Ismail rf->ceqs_count = 1; 71044d9e529SMustafa Ismail } 71144d9e529SMustafa Ismail 71244d9e529SMustafa Ismail /** 71344d9e529SMustafa Ismail * irdma_destroy_ccq - destroy control cq 71444d9e529SMustafa Ismail * @rf: RDMA PCI function 71544d9e529SMustafa Ismail * 71644d9e529SMustafa Ismail * Issue destroy ccq request and 71744d9e529SMustafa Ismail * free the resources associated with the ccq 71844d9e529SMustafa Ismail */ 71944d9e529SMustafa Ismail static void irdma_destroy_ccq(struct irdma_pci_f *rf) 72044d9e529SMustafa Ismail { 72144d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 72244d9e529SMustafa Ismail struct irdma_ccq *ccq = &rf->ccq; 72344d9e529SMustafa Ismail enum irdma_status_code status = 0; 72444d9e529SMustafa Ismail 72544d9e529SMustafa Ismail if (!rf->reset) 72644d9e529SMustafa Ismail status = irdma_sc_ccq_destroy(dev->ccq, 0, true); 72744d9e529SMustafa Ismail if (status) 72844d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), "ERR: CCQ destroy failed %d\n", status); 72944d9e529SMustafa Ismail dma_free_coherent(dev->hw->device, ccq->mem_cq.size, ccq->mem_cq.va, 73044d9e529SMustafa Ismail ccq->mem_cq.pa); 73144d9e529SMustafa Ismail ccq->mem_cq.va = NULL; 73244d9e529SMustafa Ismail } 73344d9e529SMustafa Ismail 73444d9e529SMustafa Ismail /** 73544d9e529SMustafa Ismail * irdma_close_hmc_objects_type - delete hmc objects of a given type 73644d9e529SMustafa Ismail * @dev: iwarp device 73744d9e529SMustafa Ismail * @obj_type: the hmc object type to be deleted 73844d9e529SMustafa Ismail * @hmc_info: host memory info struct 73944d9e529SMustafa Ismail * @privileged: permission to close HMC objects 74044d9e529SMustafa Ismail * @reset: true if called before reset 74144d9e529SMustafa Ismail */ 74244d9e529SMustafa Ismail static void irdma_close_hmc_objects_type(struct irdma_sc_dev *dev, 74344d9e529SMustafa Ismail enum irdma_hmc_rsrc_type obj_type, 74444d9e529SMustafa Ismail struct irdma_hmc_info *hmc_info, 74544d9e529SMustafa Ismail bool privileged, bool reset) 74644d9e529SMustafa Ismail { 74744d9e529SMustafa Ismail struct irdma_hmc_del_obj_info info = {}; 74844d9e529SMustafa Ismail 74944d9e529SMustafa Ismail info.hmc_info = hmc_info; 75044d9e529SMustafa Ismail info.rsrc_type = obj_type; 75144d9e529SMustafa Ismail info.count = hmc_info->hmc_obj[obj_type].cnt; 75244d9e529SMustafa Ismail info.privileged = privileged; 75344d9e529SMustafa Ismail if (irdma_sc_del_hmc_obj(dev, &info, reset)) 75444d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), "ERR: del HMC obj of type %d failed\n", 75544d9e529SMustafa Ismail obj_type); 75644d9e529SMustafa Ismail } 75744d9e529SMustafa Ismail 75844d9e529SMustafa Ismail /** 75944d9e529SMustafa Ismail * irdma_del_hmc_objects - remove all device hmc objects 76044d9e529SMustafa Ismail * @dev: iwarp device 76144d9e529SMustafa Ismail * @hmc_info: hmc_info to free 76244d9e529SMustafa Ismail * @privileged: permission to delete HMC objects 76344d9e529SMustafa Ismail * @reset: true if called before reset 76444d9e529SMustafa Ismail * @vers: hardware version 76544d9e529SMustafa Ismail */ 76644d9e529SMustafa Ismail static void irdma_del_hmc_objects(struct irdma_sc_dev *dev, 76744d9e529SMustafa Ismail struct irdma_hmc_info *hmc_info, bool privileged, 76844d9e529SMustafa Ismail bool reset, enum irdma_vers vers) 76944d9e529SMustafa Ismail { 77044d9e529SMustafa Ismail unsigned int i; 77144d9e529SMustafa Ismail 77244d9e529SMustafa Ismail for (i = 0; i < IW_HMC_OBJ_TYPE_NUM; i++) { 77344d9e529SMustafa Ismail if (dev->hmc_info->hmc_obj[iw_hmc_obj_types[i]].cnt) 77444d9e529SMustafa Ismail irdma_close_hmc_objects_type(dev, iw_hmc_obj_types[i], 77544d9e529SMustafa Ismail hmc_info, privileged, reset); 77644d9e529SMustafa Ismail if (vers == IRDMA_GEN_1 && i == IRDMA_HMC_IW_TIMER) 77744d9e529SMustafa Ismail break; 77844d9e529SMustafa Ismail } 77944d9e529SMustafa Ismail } 78044d9e529SMustafa Ismail 78144d9e529SMustafa Ismail /** 78244d9e529SMustafa Ismail * irdma_create_hmc_obj_type - create hmc object of a given type 78344d9e529SMustafa Ismail * @dev: hardware control device structure 78444d9e529SMustafa Ismail * @info: information for the hmc object to create 78544d9e529SMustafa Ismail */ 78644d9e529SMustafa Ismail static enum irdma_status_code 78744d9e529SMustafa Ismail irdma_create_hmc_obj_type(struct irdma_sc_dev *dev, 78844d9e529SMustafa Ismail struct irdma_hmc_create_obj_info *info) 78944d9e529SMustafa Ismail { 79044d9e529SMustafa Ismail return irdma_sc_create_hmc_obj(dev, info); 79144d9e529SMustafa Ismail } 79244d9e529SMustafa Ismail 79344d9e529SMustafa Ismail /** 79444d9e529SMustafa Ismail * irdma_create_hmc_objs - create all hmc objects for the device 79544d9e529SMustafa Ismail * @rf: RDMA PCI function 79644d9e529SMustafa Ismail * @privileged: permission to create HMC objects 79744d9e529SMustafa Ismail * @vers: HW version 79844d9e529SMustafa Ismail * 79944d9e529SMustafa Ismail * Create the device hmc objects and allocate hmc pages 80044d9e529SMustafa Ismail * Return 0 if successful, otherwise clean up and return error 80144d9e529SMustafa Ismail */ 80244d9e529SMustafa Ismail static enum irdma_status_code 80344d9e529SMustafa Ismail irdma_create_hmc_objs(struct irdma_pci_f *rf, bool privileged, enum irdma_vers vers) 80444d9e529SMustafa Ismail { 80544d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 80644d9e529SMustafa Ismail struct irdma_hmc_create_obj_info info = {}; 80744d9e529SMustafa Ismail enum irdma_status_code status = 0; 80844d9e529SMustafa Ismail int i; 80944d9e529SMustafa Ismail 81044d9e529SMustafa Ismail info.hmc_info = dev->hmc_info; 81144d9e529SMustafa Ismail info.privileged = privileged; 81244d9e529SMustafa Ismail info.entry_type = rf->sd_type; 81344d9e529SMustafa Ismail 81444d9e529SMustafa Ismail for (i = 0; i < IW_HMC_OBJ_TYPE_NUM; i++) { 81544d9e529SMustafa Ismail if (dev->hmc_info->hmc_obj[iw_hmc_obj_types[i]].cnt) { 81644d9e529SMustafa Ismail info.rsrc_type = iw_hmc_obj_types[i]; 81744d9e529SMustafa Ismail info.count = dev->hmc_info->hmc_obj[info.rsrc_type].cnt; 81844d9e529SMustafa Ismail info.add_sd_cnt = 0; 81944d9e529SMustafa Ismail status = irdma_create_hmc_obj_type(dev, &info); 82044d9e529SMustafa Ismail if (status) { 82144d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), 82244d9e529SMustafa Ismail "ERR: create obj type %d status = %d\n", 82344d9e529SMustafa Ismail iw_hmc_obj_types[i], status); 82444d9e529SMustafa Ismail break; 82544d9e529SMustafa Ismail } 82644d9e529SMustafa Ismail } 82744d9e529SMustafa Ismail if (vers == IRDMA_GEN_1 && i == IRDMA_HMC_IW_TIMER) 82844d9e529SMustafa Ismail break; 82944d9e529SMustafa Ismail } 83044d9e529SMustafa Ismail 83144d9e529SMustafa Ismail if (!status) 83244d9e529SMustafa Ismail return irdma_sc_static_hmc_pages_allocated(dev->cqp, 0, dev->hmc_fn_id, 83344d9e529SMustafa Ismail true, true); 83444d9e529SMustafa Ismail 83544d9e529SMustafa Ismail while (i) { 83644d9e529SMustafa Ismail i--; 83744d9e529SMustafa Ismail /* destroy the hmc objects of a given type */ 83844d9e529SMustafa Ismail if (dev->hmc_info->hmc_obj[iw_hmc_obj_types[i]].cnt) 83944d9e529SMustafa Ismail irdma_close_hmc_objects_type(dev, iw_hmc_obj_types[i], 84044d9e529SMustafa Ismail dev->hmc_info, privileged, 84144d9e529SMustafa Ismail false); 84244d9e529SMustafa Ismail } 84344d9e529SMustafa Ismail 84444d9e529SMustafa Ismail return status; 84544d9e529SMustafa Ismail } 84644d9e529SMustafa Ismail 84744d9e529SMustafa Ismail /** 84844d9e529SMustafa Ismail * irdma_obj_aligned_mem - get aligned memory from device allocated memory 84944d9e529SMustafa Ismail * @rf: RDMA PCI function 85044d9e529SMustafa Ismail * @memptr: points to the memory addresses 85144d9e529SMustafa Ismail * @size: size of memory needed 85244d9e529SMustafa Ismail * @mask: mask for the aligned memory 85344d9e529SMustafa Ismail * 85444d9e529SMustafa Ismail * Get aligned memory of the requested size and 85544d9e529SMustafa Ismail * update the memptr to point to the new aligned memory 85644d9e529SMustafa Ismail * Return 0 if successful, otherwise return no memory error 85744d9e529SMustafa Ismail */ 85844d9e529SMustafa Ismail static enum irdma_status_code 85944d9e529SMustafa Ismail irdma_obj_aligned_mem(struct irdma_pci_f *rf, struct irdma_dma_mem *memptr, 86044d9e529SMustafa Ismail u32 size, u32 mask) 86144d9e529SMustafa Ismail { 86244d9e529SMustafa Ismail unsigned long va, newva; 86344d9e529SMustafa Ismail unsigned long extra; 86444d9e529SMustafa Ismail 86544d9e529SMustafa Ismail va = (unsigned long)rf->obj_next.va; 86644d9e529SMustafa Ismail newva = va; 86744d9e529SMustafa Ismail if (mask) 86844d9e529SMustafa Ismail newva = ALIGN(va, (unsigned long)mask + 1ULL); 86944d9e529SMustafa Ismail extra = newva - va; 87044d9e529SMustafa Ismail memptr->va = (u8 *)va + extra; 87144d9e529SMustafa Ismail memptr->pa = rf->obj_next.pa + extra; 87244d9e529SMustafa Ismail memptr->size = size; 87344d9e529SMustafa Ismail if (((u8 *)memptr->va + size) > ((u8 *)rf->obj_mem.va + rf->obj_mem.size)) 87444d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 87544d9e529SMustafa Ismail 87644d9e529SMustafa Ismail rf->obj_next.va = (u8 *)memptr->va + size; 87744d9e529SMustafa Ismail rf->obj_next.pa = memptr->pa + size; 87844d9e529SMustafa Ismail 87944d9e529SMustafa Ismail return 0; 88044d9e529SMustafa Ismail } 88144d9e529SMustafa Ismail 88244d9e529SMustafa Ismail /** 88344d9e529SMustafa Ismail * irdma_create_cqp - create control qp 88444d9e529SMustafa Ismail * @rf: RDMA PCI function 88544d9e529SMustafa Ismail * 88644d9e529SMustafa Ismail * Return 0, if the cqp and all the resources associated with it 88744d9e529SMustafa Ismail * are successfully created, otherwise return error 88844d9e529SMustafa Ismail */ 88944d9e529SMustafa Ismail static enum irdma_status_code irdma_create_cqp(struct irdma_pci_f *rf) 89044d9e529SMustafa Ismail { 89144d9e529SMustafa Ismail enum irdma_status_code status; 89244d9e529SMustafa Ismail u32 sqsize = IRDMA_CQP_SW_SQSIZE_2048; 89344d9e529SMustafa Ismail struct irdma_dma_mem mem; 89444d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 89544d9e529SMustafa Ismail struct irdma_cqp_init_info cqp_init_info = {}; 89644d9e529SMustafa Ismail struct irdma_cqp *cqp = &rf->cqp; 89744d9e529SMustafa Ismail u16 maj_err, min_err; 89844d9e529SMustafa Ismail int i; 89944d9e529SMustafa Ismail 90044d9e529SMustafa Ismail cqp->cqp_requests = kcalloc(sqsize, sizeof(*cqp->cqp_requests), GFP_KERNEL); 90144d9e529SMustafa Ismail if (!cqp->cqp_requests) 90244d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 90344d9e529SMustafa Ismail 90444d9e529SMustafa Ismail cqp->scratch_array = kcalloc(sqsize, sizeof(*cqp->scratch_array), GFP_KERNEL); 90544d9e529SMustafa Ismail if (!cqp->scratch_array) { 90644d9e529SMustafa Ismail kfree(cqp->cqp_requests); 90744d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 90844d9e529SMustafa Ismail } 90944d9e529SMustafa Ismail 91044d9e529SMustafa Ismail dev->cqp = &cqp->sc_cqp; 91144d9e529SMustafa Ismail dev->cqp->dev = dev; 91244d9e529SMustafa Ismail cqp->sq.size = ALIGN(sizeof(struct irdma_cqp_sq_wqe) * sqsize, 91344d9e529SMustafa Ismail IRDMA_CQP_ALIGNMENT); 91444d9e529SMustafa Ismail cqp->sq.va = dma_alloc_coherent(dev->hw->device, cqp->sq.size, 91544d9e529SMustafa Ismail &cqp->sq.pa, GFP_KERNEL); 91644d9e529SMustafa Ismail if (!cqp->sq.va) { 91744d9e529SMustafa Ismail kfree(cqp->scratch_array); 91844d9e529SMustafa Ismail kfree(cqp->cqp_requests); 91944d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 92044d9e529SMustafa Ismail } 92144d9e529SMustafa Ismail 92244d9e529SMustafa Ismail status = irdma_obj_aligned_mem(rf, &mem, sizeof(struct irdma_cqp_ctx), 92344d9e529SMustafa Ismail IRDMA_HOST_CTX_ALIGNMENT_M); 92444d9e529SMustafa Ismail if (status) 92544d9e529SMustafa Ismail goto exit; 92644d9e529SMustafa Ismail 92744d9e529SMustafa Ismail dev->cqp->host_ctx_pa = mem.pa; 92844d9e529SMustafa Ismail dev->cqp->host_ctx = mem.va; 92944d9e529SMustafa Ismail /* populate the cqp init info */ 93044d9e529SMustafa Ismail cqp_init_info.dev = dev; 93144d9e529SMustafa Ismail cqp_init_info.sq_size = sqsize; 93244d9e529SMustafa Ismail cqp_init_info.sq = cqp->sq.va; 93344d9e529SMustafa Ismail cqp_init_info.sq_pa = cqp->sq.pa; 93444d9e529SMustafa Ismail cqp_init_info.host_ctx_pa = mem.pa; 93544d9e529SMustafa Ismail cqp_init_info.host_ctx = mem.va; 93644d9e529SMustafa Ismail cqp_init_info.hmc_profile = rf->rsrc_profile; 93744d9e529SMustafa Ismail cqp_init_info.scratch_array = cqp->scratch_array; 93844d9e529SMustafa Ismail cqp_init_info.protocol_used = rf->protocol_used; 93944d9e529SMustafa Ismail 94044d9e529SMustafa Ismail switch (rf->rdma_ver) { 94144d9e529SMustafa Ismail case IRDMA_GEN_1: 94244d9e529SMustafa Ismail cqp_init_info.hw_maj_ver = IRDMA_CQPHC_HW_MAJVER_GEN_1; 94344d9e529SMustafa Ismail break; 94444d9e529SMustafa Ismail case IRDMA_GEN_2: 94544d9e529SMustafa Ismail cqp_init_info.hw_maj_ver = IRDMA_CQPHC_HW_MAJVER_GEN_2; 94644d9e529SMustafa Ismail break; 94744d9e529SMustafa Ismail } 94844d9e529SMustafa Ismail status = irdma_sc_cqp_init(dev->cqp, &cqp_init_info); 94944d9e529SMustafa Ismail if (status) { 95044d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), "ERR: cqp init status %d\n", status); 95144d9e529SMustafa Ismail goto exit; 95244d9e529SMustafa Ismail } 95344d9e529SMustafa Ismail 95444d9e529SMustafa Ismail spin_lock_init(&cqp->req_lock); 95544d9e529SMustafa Ismail spin_lock_init(&cqp->compl_lock); 95644d9e529SMustafa Ismail 95744d9e529SMustafa Ismail status = irdma_sc_cqp_create(dev->cqp, &maj_err, &min_err); 95844d9e529SMustafa Ismail if (status) { 95944d9e529SMustafa Ismail ibdev_dbg(to_ibdev(dev), 96044d9e529SMustafa Ismail "ERR: cqp create failed - status %d maj_err %d min_err %d\n", 96144d9e529SMustafa Ismail status, maj_err, min_err); 96244d9e529SMustafa Ismail goto exit; 96344d9e529SMustafa Ismail } 96444d9e529SMustafa Ismail 96544d9e529SMustafa Ismail INIT_LIST_HEAD(&cqp->cqp_avail_reqs); 96644d9e529SMustafa Ismail INIT_LIST_HEAD(&cqp->cqp_pending_reqs); 96744d9e529SMustafa Ismail 96844d9e529SMustafa Ismail /* init the waitqueue of the cqp_requests and add them to the list */ 96944d9e529SMustafa Ismail for (i = 0; i < sqsize; i++) { 97044d9e529SMustafa Ismail init_waitqueue_head(&cqp->cqp_requests[i].waitq); 97144d9e529SMustafa Ismail list_add_tail(&cqp->cqp_requests[i].list, &cqp->cqp_avail_reqs); 97244d9e529SMustafa Ismail } 97344d9e529SMustafa Ismail init_waitqueue_head(&cqp->remove_wq); 97444d9e529SMustafa Ismail return 0; 97544d9e529SMustafa Ismail 97644d9e529SMustafa Ismail exit: 97744d9e529SMustafa Ismail irdma_destroy_cqp(rf, false); 97844d9e529SMustafa Ismail 97944d9e529SMustafa Ismail return status; 98044d9e529SMustafa Ismail } 98144d9e529SMustafa Ismail 98244d9e529SMustafa Ismail /** 98344d9e529SMustafa Ismail * irdma_create_ccq - create control cq 98444d9e529SMustafa Ismail * @rf: RDMA PCI function 98544d9e529SMustafa Ismail * 98644d9e529SMustafa Ismail * Return 0, if the ccq and the resources associated with it 98744d9e529SMustafa Ismail * are successfully created, otherwise return error 98844d9e529SMustafa Ismail */ 98944d9e529SMustafa Ismail static enum irdma_status_code irdma_create_ccq(struct irdma_pci_f *rf) 99044d9e529SMustafa Ismail { 99144d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 99244d9e529SMustafa Ismail enum irdma_status_code status; 99344d9e529SMustafa Ismail struct irdma_ccq_init_info info = {}; 99444d9e529SMustafa Ismail struct irdma_ccq *ccq = &rf->ccq; 99544d9e529SMustafa Ismail 99644d9e529SMustafa Ismail dev->ccq = &ccq->sc_cq; 99744d9e529SMustafa Ismail dev->ccq->dev = dev; 99844d9e529SMustafa Ismail info.dev = dev; 99944d9e529SMustafa Ismail ccq->shadow_area.size = sizeof(struct irdma_cq_shadow_area); 100044d9e529SMustafa Ismail ccq->mem_cq.size = ALIGN(sizeof(struct irdma_cqe) * IW_CCQ_SIZE, 100144d9e529SMustafa Ismail IRDMA_CQ0_ALIGNMENT); 100244d9e529SMustafa Ismail ccq->mem_cq.va = dma_alloc_coherent(dev->hw->device, ccq->mem_cq.size, 100344d9e529SMustafa Ismail &ccq->mem_cq.pa, GFP_KERNEL); 100444d9e529SMustafa Ismail if (!ccq->mem_cq.va) 100544d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 100644d9e529SMustafa Ismail 100744d9e529SMustafa Ismail status = irdma_obj_aligned_mem(rf, &ccq->shadow_area, 100844d9e529SMustafa Ismail ccq->shadow_area.size, 100944d9e529SMustafa Ismail IRDMA_SHADOWAREA_M); 101044d9e529SMustafa Ismail if (status) 101144d9e529SMustafa Ismail goto exit; 101244d9e529SMustafa Ismail 101344d9e529SMustafa Ismail ccq->sc_cq.back_cq = ccq; 101444d9e529SMustafa Ismail /* populate the ccq init info */ 101544d9e529SMustafa Ismail info.cq_base = ccq->mem_cq.va; 101644d9e529SMustafa Ismail info.cq_pa = ccq->mem_cq.pa; 101744d9e529SMustafa Ismail info.num_elem = IW_CCQ_SIZE; 101844d9e529SMustafa Ismail info.shadow_area = ccq->shadow_area.va; 101944d9e529SMustafa Ismail info.shadow_area_pa = ccq->shadow_area.pa; 102044d9e529SMustafa Ismail info.ceqe_mask = false; 102144d9e529SMustafa Ismail info.ceq_id_valid = true; 102244d9e529SMustafa Ismail info.shadow_read_threshold = 16; 102344d9e529SMustafa Ismail info.vsi = &rf->default_vsi; 102444d9e529SMustafa Ismail status = irdma_sc_ccq_init(dev->ccq, &info); 102544d9e529SMustafa Ismail if (!status) 102644d9e529SMustafa Ismail status = irdma_sc_ccq_create(dev->ccq, 0, true, true); 102744d9e529SMustafa Ismail exit: 102844d9e529SMustafa Ismail if (status) { 102944d9e529SMustafa Ismail dma_free_coherent(dev->hw->device, ccq->mem_cq.size, 103044d9e529SMustafa Ismail ccq->mem_cq.va, ccq->mem_cq.pa); 103144d9e529SMustafa Ismail ccq->mem_cq.va = NULL; 103244d9e529SMustafa Ismail } 103344d9e529SMustafa Ismail 103444d9e529SMustafa Ismail return status; 103544d9e529SMustafa Ismail } 103644d9e529SMustafa Ismail 103744d9e529SMustafa Ismail /** 103844d9e529SMustafa Ismail * irdma_alloc_set_mac - set up a mac address table entry 103944d9e529SMustafa Ismail * @iwdev: irdma device 104044d9e529SMustafa Ismail * 104144d9e529SMustafa Ismail * Allocate a mac ip entry and add it to the hw table Return 0 104244d9e529SMustafa Ismail * if successful, otherwise return error 104344d9e529SMustafa Ismail */ 104444d9e529SMustafa Ismail static enum irdma_status_code irdma_alloc_set_mac(struct irdma_device *iwdev) 104544d9e529SMustafa Ismail { 104644d9e529SMustafa Ismail enum irdma_status_code status; 104744d9e529SMustafa Ismail 104844d9e529SMustafa Ismail status = irdma_alloc_local_mac_entry(iwdev->rf, 104944d9e529SMustafa Ismail &iwdev->mac_ip_table_idx); 105044d9e529SMustafa Ismail if (!status) { 105144d9e529SMustafa Ismail status = irdma_add_local_mac_entry(iwdev->rf, 105244d9e529SMustafa Ismail (u8 *)iwdev->netdev->dev_addr, 105344d9e529SMustafa Ismail (u8)iwdev->mac_ip_table_idx); 105444d9e529SMustafa Ismail if (status) 105544d9e529SMustafa Ismail irdma_del_local_mac_entry(iwdev->rf, 105644d9e529SMustafa Ismail (u8)iwdev->mac_ip_table_idx); 105744d9e529SMustafa Ismail } 105844d9e529SMustafa Ismail return status; 105944d9e529SMustafa Ismail } 106044d9e529SMustafa Ismail 106144d9e529SMustafa Ismail /** 106244d9e529SMustafa Ismail * irdma_cfg_ceq_vector - set up the msix interrupt vector for 106344d9e529SMustafa Ismail * ceq 106444d9e529SMustafa Ismail * @rf: RDMA PCI function 106544d9e529SMustafa Ismail * @iwceq: ceq associated with the vector 106644d9e529SMustafa Ismail * @ceq_id: the id number of the iwceq 106744d9e529SMustafa Ismail * @msix_vec: interrupt vector information 106844d9e529SMustafa Ismail * 106944d9e529SMustafa Ismail * Allocate interrupt resources and enable irq handling 107044d9e529SMustafa Ismail * Return 0 if successful, otherwise return error 107144d9e529SMustafa Ismail */ 107244d9e529SMustafa Ismail static enum irdma_status_code 107344d9e529SMustafa Ismail irdma_cfg_ceq_vector(struct irdma_pci_f *rf, struct irdma_ceq *iwceq, 107444d9e529SMustafa Ismail u32 ceq_id, struct irdma_msix_vector *msix_vec) 107544d9e529SMustafa Ismail { 107644d9e529SMustafa Ismail int status; 107744d9e529SMustafa Ismail 107844d9e529SMustafa Ismail if (rf->msix_shared && !ceq_id) { 107944d9e529SMustafa Ismail tasklet_setup(&rf->dpc_tasklet, irdma_dpc); 108044d9e529SMustafa Ismail status = request_irq(msix_vec->irq, irdma_irq_handler, 0, 108144d9e529SMustafa Ismail "AEQCEQ", rf); 108244d9e529SMustafa Ismail } else { 108344d9e529SMustafa Ismail tasklet_setup(&iwceq->dpc_tasklet, irdma_ceq_dpc); 108444d9e529SMustafa Ismail 108544d9e529SMustafa Ismail status = request_irq(msix_vec->irq, irdma_ceq_handler, 0, 108644d9e529SMustafa Ismail "CEQ", iwceq); 108744d9e529SMustafa Ismail } 108844d9e529SMustafa Ismail cpumask_clear(&msix_vec->mask); 108944d9e529SMustafa Ismail cpumask_set_cpu(msix_vec->cpu_affinity, &msix_vec->mask); 109044d9e529SMustafa Ismail irq_set_affinity_hint(msix_vec->irq, &msix_vec->mask); 109144d9e529SMustafa Ismail if (status) { 109244d9e529SMustafa Ismail ibdev_dbg(&rf->iwdev->ibdev, "ERR: ceq irq config fail\n"); 109344d9e529SMustafa Ismail return IRDMA_ERR_CFG; 109444d9e529SMustafa Ismail } 109544d9e529SMustafa Ismail 109644d9e529SMustafa Ismail msix_vec->ceq_id = ceq_id; 109744d9e529SMustafa Ismail rf->sc_dev.irq_ops->irdma_cfg_ceq(&rf->sc_dev, ceq_id, msix_vec->idx, true); 109844d9e529SMustafa Ismail 109944d9e529SMustafa Ismail return 0; 110044d9e529SMustafa Ismail } 110144d9e529SMustafa Ismail 110244d9e529SMustafa Ismail /** 110344d9e529SMustafa Ismail * irdma_cfg_aeq_vector - set up the msix vector for aeq 110444d9e529SMustafa Ismail * @rf: RDMA PCI function 110544d9e529SMustafa Ismail * 110644d9e529SMustafa Ismail * Allocate interrupt resources and enable irq handling 110744d9e529SMustafa Ismail * Return 0 if successful, otherwise return error 110844d9e529SMustafa Ismail */ 110944d9e529SMustafa Ismail static enum irdma_status_code irdma_cfg_aeq_vector(struct irdma_pci_f *rf) 111044d9e529SMustafa Ismail { 111144d9e529SMustafa Ismail struct irdma_msix_vector *msix_vec = rf->iw_msixtbl; 111244d9e529SMustafa Ismail u32 ret = 0; 111344d9e529SMustafa Ismail 111444d9e529SMustafa Ismail if (!rf->msix_shared) { 111544d9e529SMustafa Ismail tasklet_setup(&rf->dpc_tasklet, irdma_dpc); 111644d9e529SMustafa Ismail ret = request_irq(msix_vec->irq, irdma_irq_handler, 0, 111744d9e529SMustafa Ismail "irdma", rf); 111844d9e529SMustafa Ismail } 111944d9e529SMustafa Ismail if (ret) { 112044d9e529SMustafa Ismail ibdev_dbg(&rf->iwdev->ibdev, "ERR: aeq irq config fail\n"); 112144d9e529SMustafa Ismail return IRDMA_ERR_CFG; 112244d9e529SMustafa Ismail } 112344d9e529SMustafa Ismail 112444d9e529SMustafa Ismail rf->sc_dev.irq_ops->irdma_cfg_aeq(&rf->sc_dev, msix_vec->idx, true); 112544d9e529SMustafa Ismail 112644d9e529SMustafa Ismail return 0; 112744d9e529SMustafa Ismail } 112844d9e529SMustafa Ismail 112944d9e529SMustafa Ismail /** 113044d9e529SMustafa Ismail * irdma_create_ceq - create completion event queue 113144d9e529SMustafa Ismail * @rf: RDMA PCI function 113244d9e529SMustafa Ismail * @iwceq: pointer to the ceq resources to be created 113344d9e529SMustafa Ismail * @ceq_id: the id number of the iwceq 113444d9e529SMustafa Ismail * @vsi: SC vsi struct 113544d9e529SMustafa Ismail * 113644d9e529SMustafa Ismail * Return 0, if the ceq and the resources associated with it 113744d9e529SMustafa Ismail * are successfully created, otherwise return error 113844d9e529SMustafa Ismail */ 113944d9e529SMustafa Ismail static enum irdma_status_code irdma_create_ceq(struct irdma_pci_f *rf, 114044d9e529SMustafa Ismail struct irdma_ceq *iwceq, 114144d9e529SMustafa Ismail u32 ceq_id, 114244d9e529SMustafa Ismail struct irdma_sc_vsi *vsi) 114344d9e529SMustafa Ismail { 114444d9e529SMustafa Ismail enum irdma_status_code status; 114544d9e529SMustafa Ismail struct irdma_ceq_init_info info = {}; 114644d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 114744d9e529SMustafa Ismail u64 scratch; 114844d9e529SMustafa Ismail u32 ceq_size; 114944d9e529SMustafa Ismail 115044d9e529SMustafa Ismail info.ceq_id = ceq_id; 115144d9e529SMustafa Ismail iwceq->rf = rf; 115244d9e529SMustafa Ismail ceq_size = min(rf->sc_dev.hmc_info->hmc_obj[IRDMA_HMC_IW_CQ].cnt, 115344d9e529SMustafa Ismail dev->hw_attrs.max_hw_ceq_size); 115444d9e529SMustafa Ismail iwceq->mem.size = ALIGN(sizeof(struct irdma_ceqe) * ceq_size, 115544d9e529SMustafa Ismail IRDMA_CEQ_ALIGNMENT); 115644d9e529SMustafa Ismail iwceq->mem.va = dma_alloc_coherent(dev->hw->device, iwceq->mem.size, 115744d9e529SMustafa Ismail &iwceq->mem.pa, GFP_KERNEL); 115844d9e529SMustafa Ismail if (!iwceq->mem.va) 115944d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 116044d9e529SMustafa Ismail 116144d9e529SMustafa Ismail info.ceq_id = ceq_id; 116244d9e529SMustafa Ismail info.ceqe_base = iwceq->mem.va; 116344d9e529SMustafa Ismail info.ceqe_pa = iwceq->mem.pa; 116444d9e529SMustafa Ismail info.elem_cnt = ceq_size; 116544d9e529SMustafa Ismail iwceq->sc_ceq.ceq_id = ceq_id; 116644d9e529SMustafa Ismail info.dev = dev; 116744d9e529SMustafa Ismail info.vsi = vsi; 116844d9e529SMustafa Ismail scratch = (uintptr_t)&rf->cqp.sc_cqp; 116944d9e529SMustafa Ismail status = irdma_sc_ceq_init(&iwceq->sc_ceq, &info); 117044d9e529SMustafa Ismail if (!status) { 117144d9e529SMustafa Ismail if (dev->ceq_valid) 117244d9e529SMustafa Ismail status = irdma_cqp_ceq_cmd(&rf->sc_dev, &iwceq->sc_ceq, 117344d9e529SMustafa Ismail IRDMA_OP_CEQ_CREATE); 117444d9e529SMustafa Ismail else 117544d9e529SMustafa Ismail status = irdma_sc_cceq_create(&iwceq->sc_ceq, scratch); 117644d9e529SMustafa Ismail } 117744d9e529SMustafa Ismail 117844d9e529SMustafa Ismail if (status) { 117944d9e529SMustafa Ismail dma_free_coherent(dev->hw->device, iwceq->mem.size, 118044d9e529SMustafa Ismail iwceq->mem.va, iwceq->mem.pa); 118144d9e529SMustafa Ismail iwceq->mem.va = NULL; 118244d9e529SMustafa Ismail } 118344d9e529SMustafa Ismail 118444d9e529SMustafa Ismail return status; 118544d9e529SMustafa Ismail } 118644d9e529SMustafa Ismail 118744d9e529SMustafa Ismail /** 118844d9e529SMustafa Ismail * irdma_setup_ceq_0 - create CEQ 0 and it's interrupt resource 118944d9e529SMustafa Ismail * @rf: RDMA PCI function 119044d9e529SMustafa Ismail * 119144d9e529SMustafa Ismail * Allocate a list for all device completion event queues 119244d9e529SMustafa Ismail * Create the ceq 0 and configure it's msix interrupt vector 119344d9e529SMustafa Ismail * Return 0, if successfully set up, otherwise return error 119444d9e529SMustafa Ismail */ 119544d9e529SMustafa Ismail static enum irdma_status_code irdma_setup_ceq_0(struct irdma_pci_f *rf) 119644d9e529SMustafa Ismail { 119744d9e529SMustafa Ismail struct irdma_ceq *iwceq; 119844d9e529SMustafa Ismail struct irdma_msix_vector *msix_vec; 119944d9e529SMustafa Ismail u32 i; 120044d9e529SMustafa Ismail enum irdma_status_code status = 0; 120144d9e529SMustafa Ismail u32 num_ceqs; 120244d9e529SMustafa Ismail 120344d9e529SMustafa Ismail num_ceqs = min(rf->msix_count, rf->sc_dev.hmc_fpm_misc.max_ceqs); 120444d9e529SMustafa Ismail rf->ceqlist = kcalloc(num_ceqs, sizeof(*rf->ceqlist), GFP_KERNEL); 120544d9e529SMustafa Ismail if (!rf->ceqlist) { 120644d9e529SMustafa Ismail status = IRDMA_ERR_NO_MEMORY; 120744d9e529SMustafa Ismail goto exit; 120844d9e529SMustafa Ismail } 120944d9e529SMustafa Ismail 121044d9e529SMustafa Ismail iwceq = &rf->ceqlist[0]; 121144d9e529SMustafa Ismail status = irdma_create_ceq(rf, iwceq, 0, &rf->default_vsi); 121244d9e529SMustafa Ismail if (status) { 121344d9e529SMustafa Ismail ibdev_dbg(&rf->iwdev->ibdev, "ERR: create ceq status = %d\n", 121444d9e529SMustafa Ismail status); 121544d9e529SMustafa Ismail goto exit; 121644d9e529SMustafa Ismail } 121744d9e529SMustafa Ismail 121844d9e529SMustafa Ismail spin_lock_init(&iwceq->ce_lock); 121944d9e529SMustafa Ismail i = rf->msix_shared ? 0 : 1; 122044d9e529SMustafa Ismail msix_vec = &rf->iw_msixtbl[i]; 122144d9e529SMustafa Ismail iwceq->irq = msix_vec->irq; 122244d9e529SMustafa Ismail iwceq->msix_idx = msix_vec->idx; 122344d9e529SMustafa Ismail status = irdma_cfg_ceq_vector(rf, iwceq, 0, msix_vec); 122444d9e529SMustafa Ismail if (status) { 122544d9e529SMustafa Ismail irdma_destroy_ceq(rf, iwceq); 122644d9e529SMustafa Ismail goto exit; 122744d9e529SMustafa Ismail } 122844d9e529SMustafa Ismail 122944d9e529SMustafa Ismail irdma_ena_intr(&rf->sc_dev, msix_vec->idx); 123044d9e529SMustafa Ismail rf->ceqs_count++; 123144d9e529SMustafa Ismail 123244d9e529SMustafa Ismail exit: 123344d9e529SMustafa Ismail if (status && !rf->ceqs_count) { 123444d9e529SMustafa Ismail kfree(rf->ceqlist); 123544d9e529SMustafa Ismail rf->ceqlist = NULL; 123644d9e529SMustafa Ismail return status; 123744d9e529SMustafa Ismail } 123844d9e529SMustafa Ismail rf->sc_dev.ceq_valid = true; 123944d9e529SMustafa Ismail 124044d9e529SMustafa Ismail return 0; 124144d9e529SMustafa Ismail } 124244d9e529SMustafa Ismail 124344d9e529SMustafa Ismail /** 124444d9e529SMustafa Ismail * irdma_setup_ceqs - manage the device ceq's and their interrupt resources 124544d9e529SMustafa Ismail * @rf: RDMA PCI function 124644d9e529SMustafa Ismail * @vsi: VSI structure for this CEQ 124744d9e529SMustafa Ismail * 124844d9e529SMustafa Ismail * Allocate a list for all device completion event queues 124944d9e529SMustafa Ismail * Create the ceq's and configure their msix interrupt vectors 125044d9e529SMustafa Ismail * Return 0, if ceqs are successfully set up, otherwise return error 125144d9e529SMustafa Ismail */ 125244d9e529SMustafa Ismail static enum irdma_status_code irdma_setup_ceqs(struct irdma_pci_f *rf, 125344d9e529SMustafa Ismail struct irdma_sc_vsi *vsi) 125444d9e529SMustafa Ismail { 125544d9e529SMustafa Ismail u32 i; 125644d9e529SMustafa Ismail u32 ceq_id; 125744d9e529SMustafa Ismail struct irdma_ceq *iwceq; 125844d9e529SMustafa Ismail struct irdma_msix_vector *msix_vec; 125944d9e529SMustafa Ismail enum irdma_status_code status; 126044d9e529SMustafa Ismail u32 num_ceqs; 126144d9e529SMustafa Ismail 126244d9e529SMustafa Ismail num_ceqs = min(rf->msix_count, rf->sc_dev.hmc_fpm_misc.max_ceqs); 126344d9e529SMustafa Ismail i = (rf->msix_shared) ? 1 : 2; 126444d9e529SMustafa Ismail for (ceq_id = 1; i < num_ceqs; i++, ceq_id++) { 126544d9e529SMustafa Ismail iwceq = &rf->ceqlist[ceq_id]; 126644d9e529SMustafa Ismail status = irdma_create_ceq(rf, iwceq, ceq_id, vsi); 126744d9e529SMustafa Ismail if (status) { 126844d9e529SMustafa Ismail ibdev_dbg(&rf->iwdev->ibdev, 126944d9e529SMustafa Ismail "ERR: create ceq status = %d\n", status); 127044d9e529SMustafa Ismail goto del_ceqs; 127144d9e529SMustafa Ismail } 127244d9e529SMustafa Ismail spin_lock_init(&iwceq->ce_lock); 127344d9e529SMustafa Ismail msix_vec = &rf->iw_msixtbl[i]; 127444d9e529SMustafa Ismail iwceq->irq = msix_vec->irq; 127544d9e529SMustafa Ismail iwceq->msix_idx = msix_vec->idx; 127644d9e529SMustafa Ismail status = irdma_cfg_ceq_vector(rf, iwceq, ceq_id, msix_vec); 127744d9e529SMustafa Ismail if (status) { 127844d9e529SMustafa Ismail irdma_destroy_ceq(rf, iwceq); 127944d9e529SMustafa Ismail goto del_ceqs; 128044d9e529SMustafa Ismail } 128144d9e529SMustafa Ismail irdma_ena_intr(&rf->sc_dev, msix_vec->idx); 128244d9e529SMustafa Ismail rf->ceqs_count++; 128344d9e529SMustafa Ismail } 128444d9e529SMustafa Ismail 128544d9e529SMustafa Ismail return 0; 128644d9e529SMustafa Ismail 128744d9e529SMustafa Ismail del_ceqs: 128844d9e529SMustafa Ismail irdma_del_ceqs(rf); 128944d9e529SMustafa Ismail 129044d9e529SMustafa Ismail return status; 129144d9e529SMustafa Ismail } 129244d9e529SMustafa Ismail 129344d9e529SMustafa Ismail static enum irdma_status_code irdma_create_virt_aeq(struct irdma_pci_f *rf, 129444d9e529SMustafa Ismail u32 size) 129544d9e529SMustafa Ismail { 129644d9e529SMustafa Ismail enum irdma_status_code status = IRDMA_ERR_NO_MEMORY; 129744d9e529SMustafa Ismail struct irdma_aeq *aeq = &rf->aeq; 129844d9e529SMustafa Ismail dma_addr_t *pg_arr; 129944d9e529SMustafa Ismail u32 pg_cnt; 130044d9e529SMustafa Ismail 130144d9e529SMustafa Ismail if (rf->rdma_ver < IRDMA_GEN_2) 130244d9e529SMustafa Ismail return IRDMA_NOT_SUPPORTED; 130344d9e529SMustafa Ismail 130444d9e529SMustafa Ismail aeq->mem.size = sizeof(struct irdma_sc_aeqe) * size; 130544d9e529SMustafa Ismail aeq->mem.va = vzalloc(aeq->mem.size); 130644d9e529SMustafa Ismail 130744d9e529SMustafa Ismail if (!aeq->mem.va) 130844d9e529SMustafa Ismail return status; 130944d9e529SMustafa Ismail 131044d9e529SMustafa Ismail pg_cnt = DIV_ROUND_UP(aeq->mem.size, PAGE_SIZE); 131144d9e529SMustafa Ismail status = irdma_get_pble(rf->pble_rsrc, &aeq->palloc, pg_cnt, true); 131244d9e529SMustafa Ismail if (status) { 131344d9e529SMustafa Ismail vfree(aeq->mem.va); 131444d9e529SMustafa Ismail return status; 131544d9e529SMustafa Ismail } 131644d9e529SMustafa Ismail 13172db7b2eaSShiraz Saleem pg_arr = (dma_addr_t *)aeq->palloc.level1.addr; 131844d9e529SMustafa Ismail status = irdma_map_vm_page_list(&rf->hw, aeq->mem.va, pg_arr, pg_cnt); 131944d9e529SMustafa Ismail if (status) { 132044d9e529SMustafa Ismail irdma_free_pble(rf->pble_rsrc, &aeq->palloc); 132144d9e529SMustafa Ismail vfree(aeq->mem.va); 132244d9e529SMustafa Ismail return status; 132344d9e529SMustafa Ismail } 132444d9e529SMustafa Ismail 132544d9e529SMustafa Ismail return 0; 132644d9e529SMustafa Ismail } 132744d9e529SMustafa Ismail 132844d9e529SMustafa Ismail /** 132944d9e529SMustafa Ismail * irdma_create_aeq - create async event queue 133044d9e529SMustafa Ismail * @rf: RDMA PCI function 133144d9e529SMustafa Ismail * 133244d9e529SMustafa Ismail * Return 0, if the aeq and the resources associated with it 133344d9e529SMustafa Ismail * are successfully created, otherwise return error 133444d9e529SMustafa Ismail */ 133544d9e529SMustafa Ismail static enum irdma_status_code irdma_create_aeq(struct irdma_pci_f *rf) 133644d9e529SMustafa Ismail { 133744d9e529SMustafa Ismail enum irdma_status_code status; 133844d9e529SMustafa Ismail struct irdma_aeq_init_info info = {}; 133944d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 134044d9e529SMustafa Ismail struct irdma_aeq *aeq = &rf->aeq; 134144d9e529SMustafa Ismail struct irdma_hmc_info *hmc_info = rf->sc_dev.hmc_info; 134244d9e529SMustafa Ismail u32 aeq_size; 134344d9e529SMustafa Ismail u8 multiplier = (rf->protocol_used == IRDMA_IWARP_PROTOCOL_ONLY) ? 2 : 1; 134444d9e529SMustafa Ismail 134544d9e529SMustafa Ismail aeq_size = multiplier * hmc_info->hmc_obj[IRDMA_HMC_IW_QP].cnt + 134644d9e529SMustafa Ismail hmc_info->hmc_obj[IRDMA_HMC_IW_CQ].cnt; 134744d9e529SMustafa Ismail aeq_size = min(aeq_size, dev->hw_attrs.max_hw_aeq_size); 134844d9e529SMustafa Ismail 134944d9e529SMustafa Ismail aeq->mem.size = ALIGN(sizeof(struct irdma_sc_aeqe) * aeq_size, 135044d9e529SMustafa Ismail IRDMA_AEQ_ALIGNMENT); 135144d9e529SMustafa Ismail aeq->mem.va = dma_alloc_coherent(dev->hw->device, aeq->mem.size, 135244d9e529SMustafa Ismail &aeq->mem.pa, 135344d9e529SMustafa Ismail GFP_KERNEL | __GFP_NOWARN); 135444d9e529SMustafa Ismail if (aeq->mem.va) 135544d9e529SMustafa Ismail goto skip_virt_aeq; 135644d9e529SMustafa Ismail 135744d9e529SMustafa Ismail /* physically mapped aeq failed. setup virtual aeq */ 135844d9e529SMustafa Ismail status = irdma_create_virt_aeq(rf, aeq_size); 135944d9e529SMustafa Ismail if (status) 136044d9e529SMustafa Ismail return status; 136144d9e529SMustafa Ismail 136244d9e529SMustafa Ismail info.virtual_map = true; 136344d9e529SMustafa Ismail aeq->virtual_map = info.virtual_map; 136444d9e529SMustafa Ismail info.pbl_chunk_size = 1; 136544d9e529SMustafa Ismail info.first_pm_pbl_idx = aeq->palloc.level1.idx; 136644d9e529SMustafa Ismail 136744d9e529SMustafa Ismail skip_virt_aeq: 136844d9e529SMustafa Ismail info.aeqe_base = aeq->mem.va; 136944d9e529SMustafa Ismail info.aeq_elem_pa = aeq->mem.pa; 137044d9e529SMustafa Ismail info.elem_cnt = aeq_size; 137144d9e529SMustafa Ismail info.dev = dev; 137244d9e529SMustafa Ismail info.msix_idx = rf->iw_msixtbl->idx; 137344d9e529SMustafa Ismail status = irdma_sc_aeq_init(&aeq->sc_aeq, &info); 137444d9e529SMustafa Ismail if (status) 137544d9e529SMustafa Ismail goto err; 137644d9e529SMustafa Ismail 137744d9e529SMustafa Ismail status = irdma_cqp_aeq_cmd(dev, &aeq->sc_aeq, IRDMA_OP_AEQ_CREATE); 137844d9e529SMustafa Ismail if (status) 137944d9e529SMustafa Ismail goto err; 138044d9e529SMustafa Ismail 138144d9e529SMustafa Ismail return 0; 138244d9e529SMustafa Ismail 138344d9e529SMustafa Ismail err: 138444d9e529SMustafa Ismail if (aeq->virtual_map) { 138544d9e529SMustafa Ismail irdma_destroy_virt_aeq(rf); 138644d9e529SMustafa Ismail } else { 138744d9e529SMustafa Ismail dma_free_coherent(dev->hw->device, aeq->mem.size, aeq->mem.va, 138844d9e529SMustafa Ismail aeq->mem.pa); 138944d9e529SMustafa Ismail aeq->mem.va = NULL; 139044d9e529SMustafa Ismail } 139144d9e529SMustafa Ismail 139244d9e529SMustafa Ismail return status; 139344d9e529SMustafa Ismail } 139444d9e529SMustafa Ismail 139544d9e529SMustafa Ismail /** 139644d9e529SMustafa Ismail * irdma_setup_aeq - set up the device aeq 139744d9e529SMustafa Ismail * @rf: RDMA PCI function 139844d9e529SMustafa Ismail * 139944d9e529SMustafa Ismail * Create the aeq and configure its msix interrupt vector 140044d9e529SMustafa Ismail * Return 0 if successful, otherwise return error 140144d9e529SMustafa Ismail */ 140244d9e529SMustafa Ismail static enum irdma_status_code irdma_setup_aeq(struct irdma_pci_f *rf) 140344d9e529SMustafa Ismail { 140444d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 140544d9e529SMustafa Ismail enum irdma_status_code status; 140644d9e529SMustafa Ismail 140744d9e529SMustafa Ismail status = irdma_create_aeq(rf); 140844d9e529SMustafa Ismail if (status) 140944d9e529SMustafa Ismail return status; 141044d9e529SMustafa Ismail 141144d9e529SMustafa Ismail status = irdma_cfg_aeq_vector(rf); 141244d9e529SMustafa Ismail if (status) { 141344d9e529SMustafa Ismail irdma_destroy_aeq(rf); 141444d9e529SMustafa Ismail return status; 141544d9e529SMustafa Ismail } 141644d9e529SMustafa Ismail 141744d9e529SMustafa Ismail if (!rf->msix_shared) 141844d9e529SMustafa Ismail irdma_ena_intr(dev, rf->iw_msixtbl[0].idx); 141944d9e529SMustafa Ismail 142044d9e529SMustafa Ismail return 0; 142144d9e529SMustafa Ismail } 142244d9e529SMustafa Ismail 142344d9e529SMustafa Ismail /** 142444d9e529SMustafa Ismail * irdma_initialize_ilq - create iwarp local queue for cm 142544d9e529SMustafa Ismail * @iwdev: irdma device 142644d9e529SMustafa Ismail * 142744d9e529SMustafa Ismail * Return 0 if successful, otherwise return error 142844d9e529SMustafa Ismail */ 142944d9e529SMustafa Ismail static enum irdma_status_code irdma_initialize_ilq(struct irdma_device *iwdev) 143044d9e529SMustafa Ismail { 143144d9e529SMustafa Ismail struct irdma_puda_rsrc_info info = {}; 143244d9e529SMustafa Ismail enum irdma_status_code status; 143344d9e529SMustafa Ismail 143444d9e529SMustafa Ismail info.type = IRDMA_PUDA_RSRC_TYPE_ILQ; 143544d9e529SMustafa Ismail info.cq_id = 1; 143644d9e529SMustafa Ismail info.qp_id = 1; 143744d9e529SMustafa Ismail info.count = 1; 143844d9e529SMustafa Ismail info.pd_id = 1; 143944d9e529SMustafa Ismail info.abi_ver = IRDMA_ABI_VER; 144044d9e529SMustafa Ismail info.sq_size = min(iwdev->rf->max_qp / 2, (u32)32768); 144144d9e529SMustafa Ismail info.rq_size = info.sq_size; 144244d9e529SMustafa Ismail info.buf_size = 1024; 144344d9e529SMustafa Ismail info.tx_buf_cnt = 2 * info.sq_size; 144444d9e529SMustafa Ismail info.receive = irdma_receive_ilq; 144544d9e529SMustafa Ismail info.xmit_complete = irdma_free_sqbuf; 144644d9e529SMustafa Ismail status = irdma_puda_create_rsrc(&iwdev->vsi, &info); 144744d9e529SMustafa Ismail if (status) 144844d9e529SMustafa Ismail ibdev_dbg(&iwdev->ibdev, "ERR: ilq create fail\n"); 144944d9e529SMustafa Ismail 145044d9e529SMustafa Ismail return status; 145144d9e529SMustafa Ismail } 145244d9e529SMustafa Ismail 145344d9e529SMustafa Ismail /** 145444d9e529SMustafa Ismail * irdma_initialize_ieq - create iwarp exception queue 145544d9e529SMustafa Ismail * @iwdev: irdma device 145644d9e529SMustafa Ismail * 145744d9e529SMustafa Ismail * Return 0 if successful, otherwise return error 145844d9e529SMustafa Ismail */ 145944d9e529SMustafa Ismail static enum irdma_status_code irdma_initialize_ieq(struct irdma_device *iwdev) 146044d9e529SMustafa Ismail { 146144d9e529SMustafa Ismail struct irdma_puda_rsrc_info info = {}; 146244d9e529SMustafa Ismail enum irdma_status_code status; 146344d9e529SMustafa Ismail 146444d9e529SMustafa Ismail info.type = IRDMA_PUDA_RSRC_TYPE_IEQ; 146544d9e529SMustafa Ismail info.cq_id = 2; 146644d9e529SMustafa Ismail info.qp_id = iwdev->vsi.exception_lan_q; 146744d9e529SMustafa Ismail info.count = 1; 146844d9e529SMustafa Ismail info.pd_id = 2; 146944d9e529SMustafa Ismail info.abi_ver = IRDMA_ABI_VER; 147044d9e529SMustafa Ismail info.sq_size = min(iwdev->rf->max_qp / 2, (u32)32768); 147144d9e529SMustafa Ismail info.rq_size = info.sq_size; 147244d9e529SMustafa Ismail info.buf_size = iwdev->vsi.mtu + IRDMA_IPV4_PAD; 147344d9e529SMustafa Ismail info.tx_buf_cnt = 4096; 147444d9e529SMustafa Ismail status = irdma_puda_create_rsrc(&iwdev->vsi, &info); 147544d9e529SMustafa Ismail if (status) 147644d9e529SMustafa Ismail ibdev_dbg(&iwdev->ibdev, "ERR: ieq create fail\n"); 147744d9e529SMustafa Ismail 147844d9e529SMustafa Ismail return status; 147944d9e529SMustafa Ismail } 148044d9e529SMustafa Ismail 148144d9e529SMustafa Ismail /** 148244d9e529SMustafa Ismail * irdma_reinitialize_ieq - destroy and re-create ieq 148344d9e529SMustafa Ismail * @vsi: VSI structure 148444d9e529SMustafa Ismail */ 148544d9e529SMustafa Ismail void irdma_reinitialize_ieq(struct irdma_sc_vsi *vsi) 148644d9e529SMustafa Ismail { 148744d9e529SMustafa Ismail struct irdma_device *iwdev = vsi->back_vsi; 148844d9e529SMustafa Ismail struct irdma_pci_f *rf = iwdev->rf; 148944d9e529SMustafa Ismail 149044d9e529SMustafa Ismail irdma_puda_dele_rsrc(vsi, IRDMA_PUDA_RSRC_TYPE_IEQ, false); 149144d9e529SMustafa Ismail if (irdma_initialize_ieq(iwdev)) { 149244d9e529SMustafa Ismail iwdev->reset = true; 149344d9e529SMustafa Ismail rf->gen_ops.request_reset(rf); 149444d9e529SMustafa Ismail } 149544d9e529SMustafa Ismail } 149644d9e529SMustafa Ismail 149744d9e529SMustafa Ismail /** 149844d9e529SMustafa Ismail * irdma_hmc_setup - create hmc objects for the device 149944d9e529SMustafa Ismail * @rf: RDMA PCI function 150044d9e529SMustafa Ismail * 150144d9e529SMustafa Ismail * Set up the device private memory space for the number and size of 150244d9e529SMustafa Ismail * the hmc objects and create the objects 150344d9e529SMustafa Ismail * Return 0 if successful, otherwise return error 150444d9e529SMustafa Ismail */ 150544d9e529SMustafa Ismail static enum irdma_status_code irdma_hmc_setup(struct irdma_pci_f *rf) 150644d9e529SMustafa Ismail { 150744d9e529SMustafa Ismail enum irdma_status_code status; 150844d9e529SMustafa Ismail u32 qpcnt; 150944d9e529SMustafa Ismail 151044d9e529SMustafa Ismail if (rf->rdma_ver == IRDMA_GEN_1) 151144d9e529SMustafa Ismail qpcnt = rsrc_limits_table[rf->limits_sel].qplimit * 2; 151244d9e529SMustafa Ismail else 151344d9e529SMustafa Ismail qpcnt = rsrc_limits_table[rf->limits_sel].qplimit; 151444d9e529SMustafa Ismail 151544d9e529SMustafa Ismail rf->sd_type = IRDMA_SD_TYPE_DIRECT; 151644d9e529SMustafa Ismail status = irdma_cfg_fpm_val(&rf->sc_dev, qpcnt); 151744d9e529SMustafa Ismail if (status) 151844d9e529SMustafa Ismail return status; 151944d9e529SMustafa Ismail 152044d9e529SMustafa Ismail status = irdma_create_hmc_objs(rf, true, rf->rdma_ver); 152144d9e529SMustafa Ismail 152244d9e529SMustafa Ismail return status; 152344d9e529SMustafa Ismail } 152444d9e529SMustafa Ismail 152544d9e529SMustafa Ismail /** 152644d9e529SMustafa Ismail * irdma_del_init_mem - deallocate memory resources 152744d9e529SMustafa Ismail * @rf: RDMA PCI function 152844d9e529SMustafa Ismail */ 152944d9e529SMustafa Ismail static void irdma_del_init_mem(struct irdma_pci_f *rf) 153044d9e529SMustafa Ismail { 153144d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 153244d9e529SMustafa Ismail 153344d9e529SMustafa Ismail kfree(dev->hmc_info->sd_table.sd_entry); 153444d9e529SMustafa Ismail dev->hmc_info->sd_table.sd_entry = NULL; 153544d9e529SMustafa Ismail kfree(rf->mem_rsrc); 153644d9e529SMustafa Ismail rf->mem_rsrc = NULL; 153744d9e529SMustafa Ismail dma_free_coherent(rf->hw.device, rf->obj_mem.size, rf->obj_mem.va, 153844d9e529SMustafa Ismail rf->obj_mem.pa); 153944d9e529SMustafa Ismail rf->obj_mem.va = NULL; 154044d9e529SMustafa Ismail if (rf->rdma_ver != IRDMA_GEN_1) { 154144d9e529SMustafa Ismail kfree(rf->allocated_ws_nodes); 154244d9e529SMustafa Ismail rf->allocated_ws_nodes = NULL; 154344d9e529SMustafa Ismail } 154444d9e529SMustafa Ismail kfree(rf->ceqlist); 154544d9e529SMustafa Ismail rf->ceqlist = NULL; 154644d9e529SMustafa Ismail kfree(rf->iw_msixtbl); 154744d9e529SMustafa Ismail rf->iw_msixtbl = NULL; 154844d9e529SMustafa Ismail kfree(rf->hmc_info_mem); 154944d9e529SMustafa Ismail rf->hmc_info_mem = NULL; 155044d9e529SMustafa Ismail } 155144d9e529SMustafa Ismail 155244d9e529SMustafa Ismail /** 155344d9e529SMustafa Ismail * irdma_initialize_dev - initialize device 155444d9e529SMustafa Ismail * @rf: RDMA PCI function 155544d9e529SMustafa Ismail * 155644d9e529SMustafa Ismail * Allocate memory for the hmc objects and initialize iwdev 155744d9e529SMustafa Ismail * Return 0 if successful, otherwise clean up the resources 155844d9e529SMustafa Ismail * and return error 155944d9e529SMustafa Ismail */ 156044d9e529SMustafa Ismail static enum irdma_status_code irdma_initialize_dev(struct irdma_pci_f *rf) 156144d9e529SMustafa Ismail { 156244d9e529SMustafa Ismail enum irdma_status_code status; 156344d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 156444d9e529SMustafa Ismail struct irdma_device_init_info info = {}; 156544d9e529SMustafa Ismail struct irdma_dma_mem mem; 156644d9e529SMustafa Ismail u32 size; 156744d9e529SMustafa Ismail 156844d9e529SMustafa Ismail size = sizeof(struct irdma_hmc_pble_rsrc) + 156944d9e529SMustafa Ismail sizeof(struct irdma_hmc_info) + 157044d9e529SMustafa Ismail (sizeof(struct irdma_hmc_obj_info) * IRDMA_HMC_IW_MAX); 157144d9e529SMustafa Ismail 157244d9e529SMustafa Ismail rf->hmc_info_mem = kzalloc(size, GFP_KERNEL); 157344d9e529SMustafa Ismail if (!rf->hmc_info_mem) 157444d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 157544d9e529SMustafa Ismail 157644d9e529SMustafa Ismail rf->pble_rsrc = (struct irdma_hmc_pble_rsrc *)rf->hmc_info_mem; 157744d9e529SMustafa Ismail dev->hmc_info = &rf->hw.hmc; 157844d9e529SMustafa Ismail dev->hmc_info->hmc_obj = (struct irdma_hmc_obj_info *) 157944d9e529SMustafa Ismail (rf->pble_rsrc + 1); 158044d9e529SMustafa Ismail 158144d9e529SMustafa Ismail status = irdma_obj_aligned_mem(rf, &mem, IRDMA_QUERY_FPM_BUF_SIZE, 158244d9e529SMustafa Ismail IRDMA_FPM_QUERY_BUF_ALIGNMENT_M); 158344d9e529SMustafa Ismail if (status) 158444d9e529SMustafa Ismail goto error; 158544d9e529SMustafa Ismail 158644d9e529SMustafa Ismail info.fpm_query_buf_pa = mem.pa; 158744d9e529SMustafa Ismail info.fpm_query_buf = mem.va; 158844d9e529SMustafa Ismail 158944d9e529SMustafa Ismail status = irdma_obj_aligned_mem(rf, &mem, IRDMA_COMMIT_FPM_BUF_SIZE, 159044d9e529SMustafa Ismail IRDMA_FPM_COMMIT_BUF_ALIGNMENT_M); 159144d9e529SMustafa Ismail if (status) 159244d9e529SMustafa Ismail goto error; 159344d9e529SMustafa Ismail 159444d9e529SMustafa Ismail info.fpm_commit_buf_pa = mem.pa; 159544d9e529SMustafa Ismail info.fpm_commit_buf = mem.va; 159644d9e529SMustafa Ismail 159744d9e529SMustafa Ismail info.bar0 = rf->hw.hw_addr; 159844d9e529SMustafa Ismail info.hmc_fn_id = PCI_FUNC(rf->pcidev->devfn); 159944d9e529SMustafa Ismail info.hw = &rf->hw; 160044d9e529SMustafa Ismail status = irdma_sc_dev_init(rf->rdma_ver, &rf->sc_dev, &info); 160144d9e529SMustafa Ismail if (status) 160244d9e529SMustafa Ismail goto error; 160344d9e529SMustafa Ismail 160444d9e529SMustafa Ismail return status; 160544d9e529SMustafa Ismail error: 160644d9e529SMustafa Ismail kfree(rf->hmc_info_mem); 160744d9e529SMustafa Ismail rf->hmc_info_mem = NULL; 160844d9e529SMustafa Ismail 160944d9e529SMustafa Ismail return status; 161044d9e529SMustafa Ismail } 161144d9e529SMustafa Ismail 161244d9e529SMustafa Ismail /** 161344d9e529SMustafa Ismail * irdma_rt_deinit_hw - clean up the irdma device resources 161444d9e529SMustafa Ismail * @iwdev: irdma device 161544d9e529SMustafa Ismail * 161644d9e529SMustafa Ismail * remove the mac ip entry and ipv4/ipv6 addresses, destroy the 161744d9e529SMustafa Ismail * device queues and free the pble and the hmc objects 161844d9e529SMustafa Ismail */ 161944d9e529SMustafa Ismail void irdma_rt_deinit_hw(struct irdma_device *iwdev) 162044d9e529SMustafa Ismail { 162144d9e529SMustafa Ismail ibdev_dbg(&iwdev->ibdev, "INIT: state = %d\n", iwdev->init_state); 162244d9e529SMustafa Ismail 162344d9e529SMustafa Ismail switch (iwdev->init_state) { 162444d9e529SMustafa Ismail case IP_ADDR_REGISTERED: 162544d9e529SMustafa Ismail if (iwdev->rf->sc_dev.hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_1) 162644d9e529SMustafa Ismail irdma_del_local_mac_entry(iwdev->rf, 162744d9e529SMustafa Ismail (u8)iwdev->mac_ip_table_idx); 162844d9e529SMustafa Ismail fallthrough; 162944d9e529SMustafa Ismail case AEQ_CREATED: 163044d9e529SMustafa Ismail case PBLE_CHUNK_MEM: 163144d9e529SMustafa Ismail case CEQS_CREATED: 163244d9e529SMustafa Ismail case IEQ_CREATED: 163344d9e529SMustafa Ismail if (!iwdev->roce_mode) 163444d9e529SMustafa Ismail irdma_puda_dele_rsrc(&iwdev->vsi, IRDMA_PUDA_RSRC_TYPE_IEQ, 163544d9e529SMustafa Ismail iwdev->reset); 163644d9e529SMustafa Ismail fallthrough; 163744d9e529SMustafa Ismail case ILQ_CREATED: 163844d9e529SMustafa Ismail if (!iwdev->roce_mode) 163944d9e529SMustafa Ismail irdma_puda_dele_rsrc(&iwdev->vsi, 164044d9e529SMustafa Ismail IRDMA_PUDA_RSRC_TYPE_ILQ, 164144d9e529SMustafa Ismail iwdev->reset); 164244d9e529SMustafa Ismail break; 164344d9e529SMustafa Ismail default: 164444d9e529SMustafa Ismail ibdev_warn(&iwdev->ibdev, "bad init_state = %d\n", iwdev->init_state); 164544d9e529SMustafa Ismail break; 164644d9e529SMustafa Ismail } 164744d9e529SMustafa Ismail 164844d9e529SMustafa Ismail irdma_cleanup_cm_core(&iwdev->cm_core); 164944d9e529SMustafa Ismail if (iwdev->vsi.pestat) { 165044d9e529SMustafa Ismail irdma_vsi_stats_free(&iwdev->vsi); 165144d9e529SMustafa Ismail kfree(iwdev->vsi.pestat); 165244d9e529SMustafa Ismail } 165344d9e529SMustafa Ismail if (iwdev->cleanup_wq) 165444d9e529SMustafa Ismail destroy_workqueue(iwdev->cleanup_wq); 165544d9e529SMustafa Ismail } 165644d9e529SMustafa Ismail 165744d9e529SMustafa Ismail static enum irdma_status_code irdma_setup_init_state(struct irdma_pci_f *rf) 165844d9e529SMustafa Ismail { 165944d9e529SMustafa Ismail enum irdma_status_code status; 166044d9e529SMustafa Ismail 166144d9e529SMustafa Ismail status = irdma_save_msix_info(rf); 166244d9e529SMustafa Ismail if (status) 166344d9e529SMustafa Ismail return status; 166444d9e529SMustafa Ismail 166544d9e529SMustafa Ismail rf->hw.device = &rf->pcidev->dev; 166644d9e529SMustafa Ismail rf->obj_mem.size = ALIGN(8192, IRDMA_HW_PAGE_SIZE); 166744d9e529SMustafa Ismail rf->obj_mem.va = dma_alloc_coherent(rf->hw.device, rf->obj_mem.size, 166844d9e529SMustafa Ismail &rf->obj_mem.pa, GFP_KERNEL); 166944d9e529SMustafa Ismail if (!rf->obj_mem.va) { 167044d9e529SMustafa Ismail status = IRDMA_ERR_NO_MEMORY; 167144d9e529SMustafa Ismail goto clean_msixtbl; 167244d9e529SMustafa Ismail } 167344d9e529SMustafa Ismail 167444d9e529SMustafa Ismail rf->obj_next = rf->obj_mem; 167544d9e529SMustafa Ismail status = irdma_initialize_dev(rf); 167644d9e529SMustafa Ismail if (status) 167744d9e529SMustafa Ismail goto clean_obj_mem; 167844d9e529SMustafa Ismail 167944d9e529SMustafa Ismail return 0; 168044d9e529SMustafa Ismail 168144d9e529SMustafa Ismail clean_obj_mem: 168244d9e529SMustafa Ismail dma_free_coherent(rf->hw.device, rf->obj_mem.size, rf->obj_mem.va, 168344d9e529SMustafa Ismail rf->obj_mem.pa); 168444d9e529SMustafa Ismail rf->obj_mem.va = NULL; 168544d9e529SMustafa Ismail clean_msixtbl: 168644d9e529SMustafa Ismail kfree(rf->iw_msixtbl); 168744d9e529SMustafa Ismail rf->iw_msixtbl = NULL; 168844d9e529SMustafa Ismail return status; 168944d9e529SMustafa Ismail } 169044d9e529SMustafa Ismail 169144d9e529SMustafa Ismail /** 169244d9e529SMustafa Ismail * irdma_get_used_rsrc - determine resources used internally 169344d9e529SMustafa Ismail * @iwdev: irdma device 169444d9e529SMustafa Ismail * 169544d9e529SMustafa Ismail * Called at the end of open to get all internal allocations 169644d9e529SMustafa Ismail */ 169744d9e529SMustafa Ismail static void irdma_get_used_rsrc(struct irdma_device *iwdev) 169844d9e529SMustafa Ismail { 169944d9e529SMustafa Ismail iwdev->rf->used_pds = find_next_zero_bit(iwdev->rf->allocated_pds, 170044d9e529SMustafa Ismail iwdev->rf->max_pd, 0); 170144d9e529SMustafa Ismail iwdev->rf->used_qps = find_next_zero_bit(iwdev->rf->allocated_qps, 170244d9e529SMustafa Ismail iwdev->rf->max_qp, 0); 170344d9e529SMustafa Ismail iwdev->rf->used_cqs = find_next_zero_bit(iwdev->rf->allocated_cqs, 170444d9e529SMustafa Ismail iwdev->rf->max_cq, 0); 170544d9e529SMustafa Ismail iwdev->rf->used_mrs = find_next_zero_bit(iwdev->rf->allocated_mrs, 170644d9e529SMustafa Ismail iwdev->rf->max_mr, 0); 170744d9e529SMustafa Ismail } 170844d9e529SMustafa Ismail 170944d9e529SMustafa Ismail void irdma_ctrl_deinit_hw(struct irdma_pci_f *rf) 171044d9e529SMustafa Ismail { 171144d9e529SMustafa Ismail enum init_completion_state state = rf->init_state; 171244d9e529SMustafa Ismail 171344d9e529SMustafa Ismail rf->init_state = INVALID_STATE; 171444d9e529SMustafa Ismail if (rf->rsrc_created) { 171544d9e529SMustafa Ismail irdma_destroy_aeq(rf); 171644d9e529SMustafa Ismail irdma_destroy_pble_prm(rf->pble_rsrc); 171744d9e529SMustafa Ismail irdma_del_ceqs(rf); 171844d9e529SMustafa Ismail rf->rsrc_created = false; 171944d9e529SMustafa Ismail } 172044d9e529SMustafa Ismail switch (state) { 172144d9e529SMustafa Ismail case CEQ0_CREATED: 172244d9e529SMustafa Ismail irdma_del_ceq_0(rf); 172344d9e529SMustafa Ismail fallthrough; 172444d9e529SMustafa Ismail case CCQ_CREATED: 172544d9e529SMustafa Ismail irdma_destroy_ccq(rf); 172644d9e529SMustafa Ismail fallthrough; 172744d9e529SMustafa Ismail case HW_RSRC_INITIALIZED: 172844d9e529SMustafa Ismail case HMC_OBJS_CREATED: 172944d9e529SMustafa Ismail irdma_del_hmc_objects(&rf->sc_dev, rf->sc_dev.hmc_info, true, 173044d9e529SMustafa Ismail rf->reset, rf->rdma_ver); 173144d9e529SMustafa Ismail fallthrough; 173244d9e529SMustafa Ismail case CQP_CREATED: 173344d9e529SMustafa Ismail irdma_destroy_cqp(rf, true); 173444d9e529SMustafa Ismail fallthrough; 173544d9e529SMustafa Ismail case INITIAL_STATE: 173644d9e529SMustafa Ismail irdma_del_init_mem(rf); 173744d9e529SMustafa Ismail break; 173844d9e529SMustafa Ismail case INVALID_STATE: 173944d9e529SMustafa Ismail default: 174044d9e529SMustafa Ismail ibdev_warn(&rf->iwdev->ibdev, "bad init_state = %d\n", rf->init_state); 174144d9e529SMustafa Ismail break; 174244d9e529SMustafa Ismail } 174344d9e529SMustafa Ismail } 174444d9e529SMustafa Ismail 174544d9e529SMustafa Ismail /** 174644d9e529SMustafa Ismail * irdma_rt_init_hw - Initializes runtime portion of HW 174744d9e529SMustafa Ismail * @iwdev: irdma device 174844d9e529SMustafa Ismail * @l2params: qos, tc, mtu info from netdev driver 174944d9e529SMustafa Ismail * 175044d9e529SMustafa Ismail * Create device queues ILQ, IEQ, CEQs and PBLEs. Setup irdma 175144d9e529SMustafa Ismail * device resource objects. 175244d9e529SMustafa Ismail */ 175344d9e529SMustafa Ismail enum irdma_status_code irdma_rt_init_hw(struct irdma_device *iwdev, 175444d9e529SMustafa Ismail struct irdma_l2params *l2params) 175544d9e529SMustafa Ismail { 175644d9e529SMustafa Ismail struct irdma_pci_f *rf = iwdev->rf; 175744d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 175844d9e529SMustafa Ismail enum irdma_status_code status; 175944d9e529SMustafa Ismail struct irdma_vsi_init_info vsi_info = {}; 176044d9e529SMustafa Ismail struct irdma_vsi_stats_info stats_info = {}; 176144d9e529SMustafa Ismail 176244d9e529SMustafa Ismail vsi_info.dev = dev; 176344d9e529SMustafa Ismail vsi_info.back_vsi = iwdev; 176444d9e529SMustafa Ismail vsi_info.params = l2params; 176544d9e529SMustafa Ismail vsi_info.pf_data_vsi_num = iwdev->vsi_num; 176644d9e529SMustafa Ismail vsi_info.register_qset = rf->gen_ops.register_qset; 176744d9e529SMustafa Ismail vsi_info.unregister_qset = rf->gen_ops.unregister_qset; 176844d9e529SMustafa Ismail vsi_info.exception_lan_q = 2; 176944d9e529SMustafa Ismail irdma_sc_vsi_init(&iwdev->vsi, &vsi_info); 177044d9e529SMustafa Ismail 177144d9e529SMustafa Ismail status = irdma_setup_cm_core(iwdev, rf->rdma_ver); 177244d9e529SMustafa Ismail if (status) 177344d9e529SMustafa Ismail return status; 177444d9e529SMustafa Ismail 177544d9e529SMustafa Ismail stats_info.pestat = kzalloc(sizeof(*stats_info.pestat), GFP_KERNEL); 177644d9e529SMustafa Ismail if (!stats_info.pestat) { 177744d9e529SMustafa Ismail irdma_cleanup_cm_core(&iwdev->cm_core); 177844d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 177944d9e529SMustafa Ismail } 178044d9e529SMustafa Ismail stats_info.fcn_id = dev->hmc_fn_id; 178144d9e529SMustafa Ismail status = irdma_vsi_stats_init(&iwdev->vsi, &stats_info); 178244d9e529SMustafa Ismail if (status) { 178344d9e529SMustafa Ismail irdma_cleanup_cm_core(&iwdev->cm_core); 178444d9e529SMustafa Ismail kfree(stats_info.pestat); 178544d9e529SMustafa Ismail return status; 178644d9e529SMustafa Ismail } 178744d9e529SMustafa Ismail 178844d9e529SMustafa Ismail do { 178944d9e529SMustafa Ismail if (!iwdev->roce_mode) { 179044d9e529SMustafa Ismail status = irdma_initialize_ilq(iwdev); 179144d9e529SMustafa Ismail if (status) 179244d9e529SMustafa Ismail break; 179344d9e529SMustafa Ismail iwdev->init_state = ILQ_CREATED; 179444d9e529SMustafa Ismail status = irdma_initialize_ieq(iwdev); 179544d9e529SMustafa Ismail if (status) 179644d9e529SMustafa Ismail break; 179744d9e529SMustafa Ismail iwdev->init_state = IEQ_CREATED; 179844d9e529SMustafa Ismail } 179944d9e529SMustafa Ismail if (!rf->rsrc_created) { 180044d9e529SMustafa Ismail status = irdma_setup_ceqs(rf, &iwdev->vsi); 180144d9e529SMustafa Ismail if (status) 180244d9e529SMustafa Ismail break; 180344d9e529SMustafa Ismail 180444d9e529SMustafa Ismail iwdev->init_state = CEQS_CREATED; 180544d9e529SMustafa Ismail 180644d9e529SMustafa Ismail status = irdma_hmc_init_pble(&rf->sc_dev, 180744d9e529SMustafa Ismail rf->pble_rsrc); 180844d9e529SMustafa Ismail if (status) { 180944d9e529SMustafa Ismail irdma_del_ceqs(rf); 181044d9e529SMustafa Ismail break; 181144d9e529SMustafa Ismail } 181244d9e529SMustafa Ismail 181344d9e529SMustafa Ismail iwdev->init_state = PBLE_CHUNK_MEM; 181444d9e529SMustafa Ismail 181544d9e529SMustafa Ismail status = irdma_setup_aeq(rf); 181644d9e529SMustafa Ismail if (status) { 181744d9e529SMustafa Ismail irdma_destroy_pble_prm(rf->pble_rsrc); 181844d9e529SMustafa Ismail irdma_del_ceqs(rf); 181944d9e529SMustafa Ismail break; 182044d9e529SMustafa Ismail } 182144d9e529SMustafa Ismail iwdev->init_state = AEQ_CREATED; 182244d9e529SMustafa Ismail rf->rsrc_created = true; 182344d9e529SMustafa Ismail } 182444d9e529SMustafa Ismail 182544d9e529SMustafa Ismail iwdev->device_cap_flags = IB_DEVICE_LOCAL_DMA_LKEY | 182644d9e529SMustafa Ismail IB_DEVICE_MEM_WINDOW | 182744d9e529SMustafa Ismail IB_DEVICE_MEM_MGT_EXTENSIONS; 182844d9e529SMustafa Ismail 182944d9e529SMustafa Ismail if (iwdev->rf->sc_dev.hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_1) 183044d9e529SMustafa Ismail irdma_alloc_set_mac(iwdev); 183144d9e529SMustafa Ismail irdma_add_ip(iwdev); 183244d9e529SMustafa Ismail iwdev->init_state = IP_ADDR_REGISTERED; 183344d9e529SMustafa Ismail 183444d9e529SMustafa Ismail /* handles asynch cleanup tasks - disconnect CM , free qp, 183544d9e529SMustafa Ismail * free cq bufs 183644d9e529SMustafa Ismail */ 183744d9e529SMustafa Ismail iwdev->cleanup_wq = alloc_workqueue("irdma-cleanup-wq", 183844d9e529SMustafa Ismail WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE); 183944d9e529SMustafa Ismail if (!iwdev->cleanup_wq) 184044d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 184144d9e529SMustafa Ismail irdma_get_used_rsrc(iwdev); 184244d9e529SMustafa Ismail init_waitqueue_head(&iwdev->suspend_wq); 184344d9e529SMustafa Ismail 184444d9e529SMustafa Ismail return 0; 184544d9e529SMustafa Ismail } while (0); 184644d9e529SMustafa Ismail 184744d9e529SMustafa Ismail dev_err(&rf->pcidev->dev, "HW runtime init FAIL status = %d last cmpl = %d\n", 184844d9e529SMustafa Ismail status, iwdev->init_state); 184944d9e529SMustafa Ismail irdma_rt_deinit_hw(iwdev); 185044d9e529SMustafa Ismail 185144d9e529SMustafa Ismail return status; 185244d9e529SMustafa Ismail } 185344d9e529SMustafa Ismail 185444d9e529SMustafa Ismail /** 185544d9e529SMustafa Ismail * irdma_ctrl_init_hw - Initializes control portion of HW 185644d9e529SMustafa Ismail * @rf: RDMA PCI function 185744d9e529SMustafa Ismail * 185844d9e529SMustafa Ismail * Create admin queues, HMC obejcts and RF resource objects 185944d9e529SMustafa Ismail */ 186044d9e529SMustafa Ismail enum irdma_status_code irdma_ctrl_init_hw(struct irdma_pci_f *rf) 186144d9e529SMustafa Ismail { 186244d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 186344d9e529SMustafa Ismail enum irdma_status_code status; 186444d9e529SMustafa Ismail do { 186544d9e529SMustafa Ismail status = irdma_setup_init_state(rf); 186644d9e529SMustafa Ismail if (status) 186744d9e529SMustafa Ismail break; 186844d9e529SMustafa Ismail rf->init_state = INITIAL_STATE; 186944d9e529SMustafa Ismail 187044d9e529SMustafa Ismail status = irdma_create_cqp(rf); 187144d9e529SMustafa Ismail if (status) 187244d9e529SMustafa Ismail break; 187344d9e529SMustafa Ismail rf->init_state = CQP_CREATED; 187444d9e529SMustafa Ismail 187544d9e529SMustafa Ismail status = irdma_hmc_setup(rf); 187644d9e529SMustafa Ismail if (status) 187744d9e529SMustafa Ismail break; 187844d9e529SMustafa Ismail rf->init_state = HMC_OBJS_CREATED; 187944d9e529SMustafa Ismail 188044d9e529SMustafa Ismail status = irdma_initialize_hw_rsrc(rf); 188144d9e529SMustafa Ismail if (status) 188244d9e529SMustafa Ismail break; 188344d9e529SMustafa Ismail rf->init_state = HW_RSRC_INITIALIZED; 188444d9e529SMustafa Ismail 188544d9e529SMustafa Ismail status = irdma_create_ccq(rf); 188644d9e529SMustafa Ismail if (status) 188744d9e529SMustafa Ismail break; 188844d9e529SMustafa Ismail rf->init_state = CCQ_CREATED; 188944d9e529SMustafa Ismail 189044d9e529SMustafa Ismail dev->feature_info[IRDMA_FEATURE_FW_INFO] = IRDMA_FW_VER_DEFAULT; 189144d9e529SMustafa Ismail if (rf->rdma_ver != IRDMA_GEN_1) { 189244d9e529SMustafa Ismail status = irdma_get_rdma_features(dev); 189344d9e529SMustafa Ismail if (status) 189444d9e529SMustafa Ismail break; 189544d9e529SMustafa Ismail } 189644d9e529SMustafa Ismail 189744d9e529SMustafa Ismail status = irdma_setup_ceq_0(rf); 189844d9e529SMustafa Ismail if (status) 189944d9e529SMustafa Ismail break; 190044d9e529SMustafa Ismail rf->init_state = CEQ0_CREATED; 190144d9e529SMustafa Ismail /* Handles processing of CQP completions */ 190244d9e529SMustafa Ismail rf->cqp_cmpl_wq = alloc_ordered_workqueue("cqp_cmpl_wq", 190344d9e529SMustafa Ismail WQ_HIGHPRI | WQ_UNBOUND); 190444d9e529SMustafa Ismail if (!rf->cqp_cmpl_wq) { 190544d9e529SMustafa Ismail status = IRDMA_ERR_NO_MEMORY; 190644d9e529SMustafa Ismail break; 190744d9e529SMustafa Ismail } 190844d9e529SMustafa Ismail INIT_WORK(&rf->cqp_cmpl_work, cqp_compl_worker); 190944d9e529SMustafa Ismail irdma_sc_ccq_arm(dev->ccq); 191044d9e529SMustafa Ismail return 0; 191144d9e529SMustafa Ismail } while (0); 191244d9e529SMustafa Ismail 191344d9e529SMustafa Ismail dev_err(&rf->pcidev->dev, "IRDMA hardware initialization FAILED init_state=%d status=%d\n", 191444d9e529SMustafa Ismail rf->init_state, status); 191544d9e529SMustafa Ismail irdma_ctrl_deinit_hw(rf); 191644d9e529SMustafa Ismail return status; 191744d9e529SMustafa Ismail } 191844d9e529SMustafa Ismail 191944d9e529SMustafa Ismail /** 192044d9e529SMustafa Ismail * irdma_set_hw_rsrc - set hw memory resources. 192144d9e529SMustafa Ismail * @rf: RDMA PCI function 192244d9e529SMustafa Ismail */ 192341f5fa9fSZhu Yanjun static void irdma_set_hw_rsrc(struct irdma_pci_f *rf) 192444d9e529SMustafa Ismail { 192544d9e529SMustafa Ismail rf->allocated_qps = (void *)(rf->mem_rsrc + 192644d9e529SMustafa Ismail (sizeof(struct irdma_arp_entry) * rf->arp_table_size)); 192744d9e529SMustafa Ismail rf->allocated_cqs = &rf->allocated_qps[BITS_TO_LONGS(rf->max_qp)]; 192844d9e529SMustafa Ismail rf->allocated_mrs = &rf->allocated_cqs[BITS_TO_LONGS(rf->max_cq)]; 192944d9e529SMustafa Ismail rf->allocated_pds = &rf->allocated_mrs[BITS_TO_LONGS(rf->max_mr)]; 193044d9e529SMustafa Ismail rf->allocated_ahs = &rf->allocated_pds[BITS_TO_LONGS(rf->max_pd)]; 193144d9e529SMustafa Ismail rf->allocated_mcgs = &rf->allocated_ahs[BITS_TO_LONGS(rf->max_ah)]; 193244d9e529SMustafa Ismail rf->allocated_arps = &rf->allocated_mcgs[BITS_TO_LONGS(rf->max_mcg)]; 193344d9e529SMustafa Ismail rf->qp_table = (struct irdma_qp **) 193444d9e529SMustafa Ismail (&rf->allocated_arps[BITS_TO_LONGS(rf->arp_table_size)]); 193544d9e529SMustafa Ismail 193644d9e529SMustafa Ismail spin_lock_init(&rf->rsrc_lock); 193744d9e529SMustafa Ismail spin_lock_init(&rf->arp_lock); 193844d9e529SMustafa Ismail spin_lock_init(&rf->qptable_lock); 193944d9e529SMustafa Ismail spin_lock_init(&rf->qh_list_lock); 194044d9e529SMustafa Ismail } 194144d9e529SMustafa Ismail 194244d9e529SMustafa Ismail /** 194344d9e529SMustafa Ismail * irdma_calc_mem_rsrc_size - calculate memory resources size. 194444d9e529SMustafa Ismail * @rf: RDMA PCI function 194544d9e529SMustafa Ismail */ 194644d9e529SMustafa Ismail static u32 irdma_calc_mem_rsrc_size(struct irdma_pci_f *rf) 194744d9e529SMustafa Ismail { 194844d9e529SMustafa Ismail u32 rsrc_size; 194944d9e529SMustafa Ismail 195044d9e529SMustafa Ismail rsrc_size = sizeof(struct irdma_arp_entry) * rf->arp_table_size; 195144d9e529SMustafa Ismail rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_qp); 195244d9e529SMustafa Ismail rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_mr); 195344d9e529SMustafa Ismail rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_cq); 195444d9e529SMustafa Ismail rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_pd); 195544d9e529SMustafa Ismail rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->arp_table_size); 195644d9e529SMustafa Ismail rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_ah); 195744d9e529SMustafa Ismail rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_mcg); 195844d9e529SMustafa Ismail rsrc_size += sizeof(struct irdma_qp **) * rf->max_qp; 195944d9e529SMustafa Ismail 196044d9e529SMustafa Ismail return rsrc_size; 196144d9e529SMustafa Ismail } 196244d9e529SMustafa Ismail 196344d9e529SMustafa Ismail /** 196444d9e529SMustafa Ismail * irdma_initialize_hw_rsrc - initialize hw resource tracking array 196544d9e529SMustafa Ismail * @rf: RDMA PCI function 196644d9e529SMustafa Ismail */ 196744d9e529SMustafa Ismail u32 irdma_initialize_hw_rsrc(struct irdma_pci_f *rf) 196844d9e529SMustafa Ismail { 196944d9e529SMustafa Ismail u32 rsrc_size; 197044d9e529SMustafa Ismail u32 mrdrvbits; 197144d9e529SMustafa Ismail u32 ret; 197244d9e529SMustafa Ismail 197344d9e529SMustafa Ismail if (rf->rdma_ver != IRDMA_GEN_1) { 197444d9e529SMustafa Ismail rf->allocated_ws_nodes = 197544d9e529SMustafa Ismail kcalloc(BITS_TO_LONGS(IRDMA_MAX_WS_NODES), 197644d9e529SMustafa Ismail sizeof(unsigned long), GFP_KERNEL); 197744d9e529SMustafa Ismail if (!rf->allocated_ws_nodes) 197844d9e529SMustafa Ismail return -ENOMEM; 197944d9e529SMustafa Ismail 198044d9e529SMustafa Ismail set_bit(0, rf->allocated_ws_nodes); 198144d9e529SMustafa Ismail rf->max_ws_node_id = IRDMA_MAX_WS_NODES; 198244d9e529SMustafa Ismail } 198344d9e529SMustafa Ismail rf->max_cqe = rf->sc_dev.hw_attrs.uk_attrs.max_hw_cq_size; 198444d9e529SMustafa Ismail rf->max_qp = rf->sc_dev.hmc_info->hmc_obj[IRDMA_HMC_IW_QP].cnt; 198544d9e529SMustafa Ismail rf->max_mr = rf->sc_dev.hmc_info->hmc_obj[IRDMA_HMC_IW_MR].cnt; 198644d9e529SMustafa Ismail rf->max_cq = rf->sc_dev.hmc_info->hmc_obj[IRDMA_HMC_IW_CQ].cnt; 198744d9e529SMustafa Ismail rf->max_pd = rf->sc_dev.hw_attrs.max_hw_pds; 198844d9e529SMustafa Ismail rf->arp_table_size = rf->sc_dev.hmc_info->hmc_obj[IRDMA_HMC_IW_ARP].cnt; 198944d9e529SMustafa Ismail rf->max_ah = rf->sc_dev.hmc_info->hmc_obj[IRDMA_HMC_IW_FSIAV].cnt; 199044d9e529SMustafa Ismail rf->max_mcg = rf->max_qp; 199144d9e529SMustafa Ismail 199244d9e529SMustafa Ismail rsrc_size = irdma_calc_mem_rsrc_size(rf); 199344d9e529SMustafa Ismail rf->mem_rsrc = kzalloc(rsrc_size, GFP_KERNEL); 199444d9e529SMustafa Ismail if (!rf->mem_rsrc) { 199544d9e529SMustafa Ismail ret = -ENOMEM; 199644d9e529SMustafa Ismail goto mem_rsrc_kzalloc_fail; 199744d9e529SMustafa Ismail } 199844d9e529SMustafa Ismail 199944d9e529SMustafa Ismail rf->arp_table = (struct irdma_arp_entry *)rf->mem_rsrc; 200044d9e529SMustafa Ismail 200141f5fa9fSZhu Yanjun irdma_set_hw_rsrc(rf); 200244d9e529SMustafa Ismail 200344d9e529SMustafa Ismail set_bit(0, rf->allocated_mrs); 200444d9e529SMustafa Ismail set_bit(0, rf->allocated_qps); 200544d9e529SMustafa Ismail set_bit(0, rf->allocated_cqs); 200644d9e529SMustafa Ismail set_bit(0, rf->allocated_pds); 200744d9e529SMustafa Ismail set_bit(0, rf->allocated_arps); 200844d9e529SMustafa Ismail set_bit(0, rf->allocated_ahs); 200944d9e529SMustafa Ismail set_bit(0, rf->allocated_mcgs); 201044d9e529SMustafa Ismail set_bit(2, rf->allocated_qps); /* qp 2 IEQ */ 201144d9e529SMustafa Ismail set_bit(1, rf->allocated_qps); /* qp 1 ILQ */ 201244d9e529SMustafa Ismail set_bit(1, rf->allocated_cqs); 201344d9e529SMustafa Ismail set_bit(1, rf->allocated_pds); 201444d9e529SMustafa Ismail set_bit(2, rf->allocated_cqs); 201544d9e529SMustafa Ismail set_bit(2, rf->allocated_pds); 201644d9e529SMustafa Ismail 201744d9e529SMustafa Ismail INIT_LIST_HEAD(&rf->mc_qht_list.list); 201844d9e529SMustafa Ismail /* stag index mask has a minimum of 14 bits */ 201944d9e529SMustafa Ismail mrdrvbits = 24 - max(get_count_order(rf->max_mr), 14); 202044d9e529SMustafa Ismail rf->mr_stagmask = ~(((1 << mrdrvbits) - 1) << (32 - mrdrvbits)); 202144d9e529SMustafa Ismail 202244d9e529SMustafa Ismail return 0; 202344d9e529SMustafa Ismail 202444d9e529SMustafa Ismail mem_rsrc_kzalloc_fail: 202544d9e529SMustafa Ismail kfree(rf->allocated_ws_nodes); 202644d9e529SMustafa Ismail rf->allocated_ws_nodes = NULL; 202744d9e529SMustafa Ismail 202844d9e529SMustafa Ismail return ret; 202944d9e529SMustafa Ismail } 203044d9e529SMustafa Ismail 203144d9e529SMustafa Ismail /** 203244d9e529SMustafa Ismail * irdma_cqp_ce_handler - handle cqp completions 203344d9e529SMustafa Ismail * @rf: RDMA PCI function 203444d9e529SMustafa Ismail * @cq: cq for cqp completions 203544d9e529SMustafa Ismail */ 203644d9e529SMustafa Ismail void irdma_cqp_ce_handler(struct irdma_pci_f *rf, struct irdma_sc_cq *cq) 203744d9e529SMustafa Ismail { 203844d9e529SMustafa Ismail struct irdma_cqp_request *cqp_request; 203944d9e529SMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 204044d9e529SMustafa Ismail u32 cqe_count = 0; 204144d9e529SMustafa Ismail struct irdma_ccq_cqe_info info; 204244d9e529SMustafa Ismail unsigned long flags; 204344d9e529SMustafa Ismail int ret; 204444d9e529SMustafa Ismail 204544d9e529SMustafa Ismail do { 204644d9e529SMustafa Ismail memset(&info, 0, sizeof(info)); 204744d9e529SMustafa Ismail spin_lock_irqsave(&rf->cqp.compl_lock, flags); 204844d9e529SMustafa Ismail ret = irdma_sc_ccq_get_cqe_info(cq, &info); 204944d9e529SMustafa Ismail spin_unlock_irqrestore(&rf->cqp.compl_lock, flags); 205044d9e529SMustafa Ismail if (ret) 205144d9e529SMustafa Ismail break; 205244d9e529SMustafa Ismail 205344d9e529SMustafa Ismail cqp_request = (struct irdma_cqp_request *) 205444d9e529SMustafa Ismail (unsigned long)info.scratch; 205544d9e529SMustafa Ismail if (info.error && irdma_cqp_crit_err(dev, cqp_request->info.cqp_cmd, 205644d9e529SMustafa Ismail info.maj_err_code, 205744d9e529SMustafa Ismail info.min_err_code)) 205844d9e529SMustafa Ismail ibdev_err(&rf->iwdev->ibdev, "cqp opcode = 0x%x maj_err_code = 0x%x min_err_code = 0x%x\n", 205944d9e529SMustafa Ismail info.op_code, info.maj_err_code, info.min_err_code); 206044d9e529SMustafa Ismail if (cqp_request) { 206144d9e529SMustafa Ismail cqp_request->compl_info.maj_err_code = info.maj_err_code; 206244d9e529SMustafa Ismail cqp_request->compl_info.min_err_code = info.min_err_code; 206344d9e529SMustafa Ismail cqp_request->compl_info.op_ret_val = info.op_ret_val; 206444d9e529SMustafa Ismail cqp_request->compl_info.error = info.error; 206544d9e529SMustafa Ismail 206644d9e529SMustafa Ismail if (cqp_request->waiting) { 206744d9e529SMustafa Ismail cqp_request->request_done = true; 206844d9e529SMustafa Ismail wake_up(&cqp_request->waitq); 206944d9e529SMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 207044d9e529SMustafa Ismail } else { 207144d9e529SMustafa Ismail if (cqp_request->callback_fcn) 207244d9e529SMustafa Ismail cqp_request->callback_fcn(cqp_request); 207344d9e529SMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 207444d9e529SMustafa Ismail } 207544d9e529SMustafa Ismail } 207644d9e529SMustafa Ismail 207744d9e529SMustafa Ismail cqe_count++; 207844d9e529SMustafa Ismail } while (1); 207944d9e529SMustafa Ismail 208044d9e529SMustafa Ismail if (cqe_count) { 208144d9e529SMustafa Ismail irdma_process_bh(dev); 208244d9e529SMustafa Ismail irdma_sc_ccq_arm(cq); 208344d9e529SMustafa Ismail } 208444d9e529SMustafa Ismail } 208544d9e529SMustafa Ismail 208644d9e529SMustafa Ismail /** 208744d9e529SMustafa Ismail * cqp_compl_worker - Handle cqp completions 208844d9e529SMustafa Ismail * @work: Pointer to work structure 208944d9e529SMustafa Ismail */ 209044d9e529SMustafa Ismail void cqp_compl_worker(struct work_struct *work) 209144d9e529SMustafa Ismail { 209244d9e529SMustafa Ismail struct irdma_pci_f *rf = container_of(work, struct irdma_pci_f, 209344d9e529SMustafa Ismail cqp_cmpl_work); 209444d9e529SMustafa Ismail struct irdma_sc_cq *cq = &rf->ccq.sc_cq; 209544d9e529SMustafa Ismail 209644d9e529SMustafa Ismail irdma_cqp_ce_handler(rf, cq); 209744d9e529SMustafa Ismail } 209844d9e529SMustafa Ismail 209944d9e529SMustafa Ismail /** 210044d9e529SMustafa Ismail * irdma_lookup_apbvt_entry - lookup hash table for an existing apbvt entry corresponding to port 210144d9e529SMustafa Ismail * @cm_core: cm's core 210244d9e529SMustafa Ismail * @port: port to identify apbvt entry 210344d9e529SMustafa Ismail */ 210444d9e529SMustafa Ismail static struct irdma_apbvt_entry *irdma_lookup_apbvt_entry(struct irdma_cm_core *cm_core, 210544d9e529SMustafa Ismail u16 port) 210644d9e529SMustafa Ismail { 210744d9e529SMustafa Ismail struct irdma_apbvt_entry *entry; 210844d9e529SMustafa Ismail 210944d9e529SMustafa Ismail hash_for_each_possible(cm_core->apbvt_hash_tbl, entry, hlist, port) { 211044d9e529SMustafa Ismail if (entry->port == port) { 211144d9e529SMustafa Ismail entry->use_cnt++; 211244d9e529SMustafa Ismail return entry; 211344d9e529SMustafa Ismail } 211444d9e529SMustafa Ismail } 211544d9e529SMustafa Ismail 211644d9e529SMustafa Ismail return NULL; 211744d9e529SMustafa Ismail } 211844d9e529SMustafa Ismail 211944d9e529SMustafa Ismail /** 212044d9e529SMustafa Ismail * irdma_next_iw_state - modify qp state 212144d9e529SMustafa Ismail * @iwqp: iwarp qp to modify 212244d9e529SMustafa Ismail * @state: next state for qp 212344d9e529SMustafa Ismail * @del_hash: del hash 212444d9e529SMustafa Ismail * @term: term message 212544d9e529SMustafa Ismail * @termlen: length of term message 212644d9e529SMustafa Ismail */ 212744d9e529SMustafa Ismail void irdma_next_iw_state(struct irdma_qp *iwqp, u8 state, u8 del_hash, u8 term, 212844d9e529SMustafa Ismail u8 termlen) 212944d9e529SMustafa Ismail { 213044d9e529SMustafa Ismail struct irdma_modify_qp_info info = {}; 213144d9e529SMustafa Ismail 213244d9e529SMustafa Ismail info.next_iwarp_state = state; 213344d9e529SMustafa Ismail info.remove_hash_idx = del_hash; 213444d9e529SMustafa Ismail info.cq_num_valid = true; 213544d9e529SMustafa Ismail info.arp_cache_idx_valid = true; 213644d9e529SMustafa Ismail info.dont_send_term = true; 213744d9e529SMustafa Ismail info.dont_send_fin = true; 213844d9e529SMustafa Ismail info.termlen = termlen; 213944d9e529SMustafa Ismail 214044d9e529SMustafa Ismail if (term & IRDMAQP_TERM_SEND_TERM_ONLY) 214144d9e529SMustafa Ismail info.dont_send_term = false; 214244d9e529SMustafa Ismail if (term & IRDMAQP_TERM_SEND_FIN_ONLY) 214344d9e529SMustafa Ismail info.dont_send_fin = false; 214444d9e529SMustafa Ismail if (iwqp->sc_qp.term_flags && state == IRDMA_QP_STATE_ERROR) 214544d9e529SMustafa Ismail info.reset_tcp_conn = true; 214644d9e529SMustafa Ismail iwqp->hw_iwarp_state = state; 214744d9e529SMustafa Ismail irdma_hw_modify_qp(iwqp->iwdev, iwqp, &info, 0); 214844d9e529SMustafa Ismail iwqp->iwarp_state = info.next_iwarp_state; 214944d9e529SMustafa Ismail } 215044d9e529SMustafa Ismail 215144d9e529SMustafa Ismail /** 215244d9e529SMustafa Ismail * irdma_del_local_mac_entry - remove a mac entry from the hw 215344d9e529SMustafa Ismail * table 215444d9e529SMustafa Ismail * @rf: RDMA PCI function 215544d9e529SMustafa Ismail * @idx: the index of the mac ip address to delete 215644d9e529SMustafa Ismail */ 215744d9e529SMustafa Ismail void irdma_del_local_mac_entry(struct irdma_pci_f *rf, u16 idx) 215844d9e529SMustafa Ismail { 215944d9e529SMustafa Ismail struct irdma_cqp *iwcqp = &rf->cqp; 216044d9e529SMustafa Ismail struct irdma_cqp_request *cqp_request; 216144d9e529SMustafa Ismail struct cqp_cmds_info *cqp_info; 216244d9e529SMustafa Ismail 216344d9e529SMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, true); 216444d9e529SMustafa Ismail if (!cqp_request) 216544d9e529SMustafa Ismail return; 216644d9e529SMustafa Ismail 216744d9e529SMustafa Ismail cqp_info = &cqp_request->info; 216844d9e529SMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_DELETE_LOCAL_MAC_ENTRY; 216944d9e529SMustafa Ismail cqp_info->post_sq = 1; 217044d9e529SMustafa Ismail cqp_info->in.u.del_local_mac_entry.cqp = &iwcqp->sc_cqp; 217144d9e529SMustafa Ismail cqp_info->in.u.del_local_mac_entry.scratch = (uintptr_t)cqp_request; 217244d9e529SMustafa Ismail cqp_info->in.u.del_local_mac_entry.entry_idx = idx; 217344d9e529SMustafa Ismail cqp_info->in.u.del_local_mac_entry.ignore_ref_count = 0; 217444d9e529SMustafa Ismail 217544d9e529SMustafa Ismail irdma_handle_cqp_op(rf, cqp_request); 217644d9e529SMustafa Ismail irdma_put_cqp_request(iwcqp, cqp_request); 217744d9e529SMustafa Ismail } 217844d9e529SMustafa Ismail 217944d9e529SMustafa Ismail /** 218044d9e529SMustafa Ismail * irdma_add_local_mac_entry - add a mac ip address entry to the 218144d9e529SMustafa Ismail * hw table 218244d9e529SMustafa Ismail * @rf: RDMA PCI function 218344d9e529SMustafa Ismail * @mac_addr: pointer to mac address 218444d9e529SMustafa Ismail * @idx: the index of the mac ip address to add 218544d9e529SMustafa Ismail */ 218644d9e529SMustafa Ismail int irdma_add_local_mac_entry(struct irdma_pci_f *rf, u8 *mac_addr, u16 idx) 218744d9e529SMustafa Ismail { 218844d9e529SMustafa Ismail struct irdma_local_mac_entry_info *info; 218944d9e529SMustafa Ismail struct irdma_cqp *iwcqp = &rf->cqp; 219044d9e529SMustafa Ismail struct irdma_cqp_request *cqp_request; 219144d9e529SMustafa Ismail struct cqp_cmds_info *cqp_info; 219244d9e529SMustafa Ismail enum irdma_status_code status; 219344d9e529SMustafa Ismail 219444d9e529SMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, true); 219544d9e529SMustafa Ismail if (!cqp_request) 219644d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 219744d9e529SMustafa Ismail 219844d9e529SMustafa Ismail cqp_info = &cqp_request->info; 219944d9e529SMustafa Ismail cqp_info->post_sq = 1; 220044d9e529SMustafa Ismail info = &cqp_info->in.u.add_local_mac_entry.info; 220144d9e529SMustafa Ismail ether_addr_copy(info->mac_addr, mac_addr); 220244d9e529SMustafa Ismail info->entry_idx = idx; 220344d9e529SMustafa Ismail cqp_info->in.u.add_local_mac_entry.scratch = (uintptr_t)cqp_request; 220444d9e529SMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_ADD_LOCAL_MAC_ENTRY; 220544d9e529SMustafa Ismail cqp_info->in.u.add_local_mac_entry.cqp = &iwcqp->sc_cqp; 220644d9e529SMustafa Ismail cqp_info->in.u.add_local_mac_entry.scratch = (uintptr_t)cqp_request; 220744d9e529SMustafa Ismail 220844d9e529SMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 220944d9e529SMustafa Ismail irdma_put_cqp_request(iwcqp, cqp_request); 221044d9e529SMustafa Ismail 221144d9e529SMustafa Ismail return status; 221244d9e529SMustafa Ismail } 221344d9e529SMustafa Ismail 221444d9e529SMustafa Ismail /** 221544d9e529SMustafa Ismail * irdma_alloc_local_mac_entry - allocate a mac entry 221644d9e529SMustafa Ismail * @rf: RDMA PCI function 221744d9e529SMustafa Ismail * @mac_tbl_idx: the index of the new mac address 221844d9e529SMustafa Ismail * 221944d9e529SMustafa Ismail * Allocate a mac address entry and update the mac_tbl_idx 222044d9e529SMustafa Ismail * to hold the index of the newly created mac address 222144d9e529SMustafa Ismail * Return 0 if successful, otherwise return error 222244d9e529SMustafa Ismail */ 222344d9e529SMustafa Ismail int irdma_alloc_local_mac_entry(struct irdma_pci_f *rf, u16 *mac_tbl_idx) 222444d9e529SMustafa Ismail { 222544d9e529SMustafa Ismail struct irdma_cqp *iwcqp = &rf->cqp; 222644d9e529SMustafa Ismail struct irdma_cqp_request *cqp_request; 222744d9e529SMustafa Ismail struct cqp_cmds_info *cqp_info; 222844d9e529SMustafa Ismail enum irdma_status_code status = 0; 222944d9e529SMustafa Ismail 223044d9e529SMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, true); 223144d9e529SMustafa Ismail if (!cqp_request) 223244d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 223344d9e529SMustafa Ismail 223444d9e529SMustafa Ismail cqp_info = &cqp_request->info; 223544d9e529SMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_ALLOC_LOCAL_MAC_ENTRY; 223644d9e529SMustafa Ismail cqp_info->post_sq = 1; 223744d9e529SMustafa Ismail cqp_info->in.u.alloc_local_mac_entry.cqp = &iwcqp->sc_cqp; 223844d9e529SMustafa Ismail cqp_info->in.u.alloc_local_mac_entry.scratch = (uintptr_t)cqp_request; 223944d9e529SMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 224044d9e529SMustafa Ismail if (!status) 224144d9e529SMustafa Ismail *mac_tbl_idx = (u16)cqp_request->compl_info.op_ret_val; 224244d9e529SMustafa Ismail 224344d9e529SMustafa Ismail irdma_put_cqp_request(iwcqp, cqp_request); 224444d9e529SMustafa Ismail 224544d9e529SMustafa Ismail return status; 224644d9e529SMustafa Ismail } 224744d9e529SMustafa Ismail 224844d9e529SMustafa Ismail /** 224944d9e529SMustafa Ismail * irdma_cqp_manage_apbvt_cmd - send cqp command manage apbvt 225044d9e529SMustafa Ismail * @iwdev: irdma device 225144d9e529SMustafa Ismail * @accel_local_port: port for apbvt 225244d9e529SMustafa Ismail * @add_port: add ordelete port 225344d9e529SMustafa Ismail */ 225444d9e529SMustafa Ismail static enum irdma_status_code 225544d9e529SMustafa Ismail irdma_cqp_manage_apbvt_cmd(struct irdma_device *iwdev, u16 accel_local_port, 225644d9e529SMustafa Ismail bool add_port) 225744d9e529SMustafa Ismail { 225844d9e529SMustafa Ismail struct irdma_apbvt_info *info; 225944d9e529SMustafa Ismail struct irdma_cqp_request *cqp_request; 226044d9e529SMustafa Ismail struct cqp_cmds_info *cqp_info; 226144d9e529SMustafa Ismail enum irdma_status_code status; 226244d9e529SMustafa Ismail 226344d9e529SMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&iwdev->rf->cqp, add_port); 226444d9e529SMustafa Ismail if (!cqp_request) 226544d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 226644d9e529SMustafa Ismail 226744d9e529SMustafa Ismail cqp_info = &cqp_request->info; 226844d9e529SMustafa Ismail info = &cqp_info->in.u.manage_apbvt_entry.info; 226944d9e529SMustafa Ismail memset(info, 0, sizeof(*info)); 227044d9e529SMustafa Ismail info->add = add_port; 227144d9e529SMustafa Ismail info->port = accel_local_port; 227244d9e529SMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_MANAGE_APBVT_ENTRY; 227344d9e529SMustafa Ismail cqp_info->post_sq = 1; 227444d9e529SMustafa Ismail cqp_info->in.u.manage_apbvt_entry.cqp = &iwdev->rf->cqp.sc_cqp; 227544d9e529SMustafa Ismail cqp_info->in.u.manage_apbvt_entry.scratch = (uintptr_t)cqp_request; 227644d9e529SMustafa Ismail ibdev_dbg(&iwdev->ibdev, "DEV: %s: port=0x%04x\n", 227744d9e529SMustafa Ismail (!add_port) ? "DELETE" : "ADD", accel_local_port); 227844d9e529SMustafa Ismail 227944d9e529SMustafa Ismail status = irdma_handle_cqp_op(iwdev->rf, cqp_request); 228044d9e529SMustafa Ismail irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request); 228144d9e529SMustafa Ismail 228244d9e529SMustafa Ismail return status; 228344d9e529SMustafa Ismail } 228444d9e529SMustafa Ismail 228544d9e529SMustafa Ismail /** 228644d9e529SMustafa Ismail * irdma_add_apbvt - add tcp port to HW apbvt table 228744d9e529SMustafa Ismail * @iwdev: irdma device 228844d9e529SMustafa Ismail * @port: port for apbvt 228944d9e529SMustafa Ismail */ 229044d9e529SMustafa Ismail struct irdma_apbvt_entry *irdma_add_apbvt(struct irdma_device *iwdev, u16 port) 229144d9e529SMustafa Ismail { 229244d9e529SMustafa Ismail struct irdma_cm_core *cm_core = &iwdev->cm_core; 229344d9e529SMustafa Ismail struct irdma_apbvt_entry *entry; 229444d9e529SMustafa Ismail unsigned long flags; 229544d9e529SMustafa Ismail 229644d9e529SMustafa Ismail spin_lock_irqsave(&cm_core->apbvt_lock, flags); 229744d9e529SMustafa Ismail entry = irdma_lookup_apbvt_entry(cm_core, port); 229844d9e529SMustafa Ismail if (entry) { 229944d9e529SMustafa Ismail spin_unlock_irqrestore(&cm_core->apbvt_lock, flags); 230044d9e529SMustafa Ismail return entry; 230144d9e529SMustafa Ismail } 230244d9e529SMustafa Ismail 230344d9e529SMustafa Ismail entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 230444d9e529SMustafa Ismail if (!entry) { 230544d9e529SMustafa Ismail spin_unlock_irqrestore(&cm_core->apbvt_lock, flags); 230644d9e529SMustafa Ismail return NULL; 230744d9e529SMustafa Ismail } 230844d9e529SMustafa Ismail 230944d9e529SMustafa Ismail entry->port = port; 231044d9e529SMustafa Ismail entry->use_cnt = 1; 231144d9e529SMustafa Ismail hash_add(cm_core->apbvt_hash_tbl, &entry->hlist, entry->port); 231244d9e529SMustafa Ismail spin_unlock_irqrestore(&cm_core->apbvt_lock, flags); 231344d9e529SMustafa Ismail 231444d9e529SMustafa Ismail if (irdma_cqp_manage_apbvt_cmd(iwdev, port, true)) { 231544d9e529SMustafa Ismail kfree(entry); 231644d9e529SMustafa Ismail return NULL; 231744d9e529SMustafa Ismail } 231844d9e529SMustafa Ismail 231944d9e529SMustafa Ismail return entry; 232044d9e529SMustafa Ismail } 232144d9e529SMustafa Ismail 232244d9e529SMustafa Ismail /** 232344d9e529SMustafa Ismail * irdma_del_apbvt - delete tcp port from HW apbvt table 232444d9e529SMustafa Ismail * @iwdev: irdma device 232544d9e529SMustafa Ismail * @entry: apbvt entry object 232644d9e529SMustafa Ismail */ 232744d9e529SMustafa Ismail void irdma_del_apbvt(struct irdma_device *iwdev, 232844d9e529SMustafa Ismail struct irdma_apbvt_entry *entry) 232944d9e529SMustafa Ismail { 233044d9e529SMustafa Ismail struct irdma_cm_core *cm_core = &iwdev->cm_core; 233144d9e529SMustafa Ismail unsigned long flags; 233244d9e529SMustafa Ismail 233344d9e529SMustafa Ismail spin_lock_irqsave(&cm_core->apbvt_lock, flags); 233444d9e529SMustafa Ismail if (--entry->use_cnt) { 233544d9e529SMustafa Ismail spin_unlock_irqrestore(&cm_core->apbvt_lock, flags); 233644d9e529SMustafa Ismail return; 233744d9e529SMustafa Ismail } 233844d9e529SMustafa Ismail 233944d9e529SMustafa Ismail hash_del(&entry->hlist); 234044d9e529SMustafa Ismail /* apbvt_lock is held across CQP delete APBVT OP (non-waiting) to 234144d9e529SMustafa Ismail * protect against race where add APBVT CQP can race ahead of the delete 234244d9e529SMustafa Ismail * APBVT for same port. 234344d9e529SMustafa Ismail */ 234444d9e529SMustafa Ismail irdma_cqp_manage_apbvt_cmd(iwdev, entry->port, false); 234544d9e529SMustafa Ismail kfree(entry); 234644d9e529SMustafa Ismail spin_unlock_irqrestore(&cm_core->apbvt_lock, flags); 234744d9e529SMustafa Ismail } 234844d9e529SMustafa Ismail 234944d9e529SMustafa Ismail /** 235044d9e529SMustafa Ismail * irdma_manage_arp_cache - manage hw arp cache 235144d9e529SMustafa Ismail * @rf: RDMA PCI function 235244d9e529SMustafa Ismail * @mac_addr: mac address ptr 235344d9e529SMustafa Ismail * @ip_addr: ip addr for arp cache 235444d9e529SMustafa Ismail * @ipv4: flag inicating IPv4 235544d9e529SMustafa Ismail * @action: add, delete or modify 235644d9e529SMustafa Ismail */ 235744d9e529SMustafa Ismail void irdma_manage_arp_cache(struct irdma_pci_f *rf, unsigned char *mac_addr, 235844d9e529SMustafa Ismail u32 *ip_addr, bool ipv4, u32 action) 235944d9e529SMustafa Ismail { 236044d9e529SMustafa Ismail struct irdma_add_arp_cache_entry_info *info; 236144d9e529SMustafa Ismail struct irdma_cqp_request *cqp_request; 236244d9e529SMustafa Ismail struct cqp_cmds_info *cqp_info; 236344d9e529SMustafa Ismail int arp_index; 236444d9e529SMustafa Ismail 236544d9e529SMustafa Ismail arp_index = irdma_arp_table(rf, ip_addr, ipv4, mac_addr, action); 236644d9e529SMustafa Ismail if (arp_index == -1) 236744d9e529SMustafa Ismail return; 236844d9e529SMustafa Ismail 236944d9e529SMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, false); 237044d9e529SMustafa Ismail if (!cqp_request) 237144d9e529SMustafa Ismail return; 237244d9e529SMustafa Ismail 237344d9e529SMustafa Ismail cqp_info = &cqp_request->info; 237444d9e529SMustafa Ismail if (action == IRDMA_ARP_ADD) { 237544d9e529SMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_ADD_ARP_CACHE_ENTRY; 237644d9e529SMustafa Ismail info = &cqp_info->in.u.add_arp_cache_entry.info; 237744d9e529SMustafa Ismail memset(info, 0, sizeof(*info)); 237844d9e529SMustafa Ismail info->arp_index = (u16)arp_index; 237944d9e529SMustafa Ismail info->permanent = true; 238044d9e529SMustafa Ismail ether_addr_copy(info->mac_addr, mac_addr); 238144d9e529SMustafa Ismail cqp_info->in.u.add_arp_cache_entry.scratch = 238244d9e529SMustafa Ismail (uintptr_t)cqp_request; 238344d9e529SMustafa Ismail cqp_info->in.u.add_arp_cache_entry.cqp = &rf->cqp.sc_cqp; 238444d9e529SMustafa Ismail } else { 238544d9e529SMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_DELETE_ARP_CACHE_ENTRY; 238644d9e529SMustafa Ismail cqp_info->in.u.del_arp_cache_entry.scratch = 238744d9e529SMustafa Ismail (uintptr_t)cqp_request; 238844d9e529SMustafa Ismail cqp_info->in.u.del_arp_cache_entry.cqp = &rf->cqp.sc_cqp; 238944d9e529SMustafa Ismail cqp_info->in.u.del_arp_cache_entry.arp_index = arp_index; 239044d9e529SMustafa Ismail } 239144d9e529SMustafa Ismail 239244d9e529SMustafa Ismail cqp_info->post_sq = 1; 239344d9e529SMustafa Ismail irdma_handle_cqp_op(rf, cqp_request); 239444d9e529SMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 239544d9e529SMustafa Ismail } 239644d9e529SMustafa Ismail 239744d9e529SMustafa Ismail /** 239844d9e529SMustafa Ismail * irdma_send_syn_cqp_callback - do syn/ack after qhash 239944d9e529SMustafa Ismail * @cqp_request: qhash cqp completion 240044d9e529SMustafa Ismail */ 240144d9e529SMustafa Ismail static void irdma_send_syn_cqp_callback(struct irdma_cqp_request *cqp_request) 240244d9e529SMustafa Ismail { 240344d9e529SMustafa Ismail struct irdma_cm_node *cm_node = cqp_request->param; 240444d9e529SMustafa Ismail 240544d9e529SMustafa Ismail irdma_send_syn(cm_node, 1); 240644d9e529SMustafa Ismail irdma_rem_ref_cm_node(cm_node); 240744d9e529SMustafa Ismail } 240844d9e529SMustafa Ismail 240944d9e529SMustafa Ismail /** 241044d9e529SMustafa Ismail * irdma_manage_qhash - add or modify qhash 241144d9e529SMustafa Ismail * @iwdev: irdma device 241244d9e529SMustafa Ismail * @cminfo: cm info for qhash 241344d9e529SMustafa Ismail * @etype: type (syn or quad) 241444d9e529SMustafa Ismail * @mtype: type of qhash 241544d9e529SMustafa Ismail * @cmnode: cmnode associated with connection 241644d9e529SMustafa Ismail * @wait: wait for completion 241744d9e529SMustafa Ismail */ 241844d9e529SMustafa Ismail enum irdma_status_code 241944d9e529SMustafa Ismail irdma_manage_qhash(struct irdma_device *iwdev, struct irdma_cm_info *cminfo, 242044d9e529SMustafa Ismail enum irdma_quad_entry_type etype, 242144d9e529SMustafa Ismail enum irdma_quad_hash_manage_type mtype, void *cmnode, 242244d9e529SMustafa Ismail bool wait) 242344d9e529SMustafa Ismail { 242444d9e529SMustafa Ismail struct irdma_qhash_table_info *info; 242544d9e529SMustafa Ismail enum irdma_status_code status; 242644d9e529SMustafa Ismail struct irdma_cqp *iwcqp = &iwdev->rf->cqp; 242744d9e529SMustafa Ismail struct irdma_cqp_request *cqp_request; 242844d9e529SMustafa Ismail struct cqp_cmds_info *cqp_info; 242944d9e529SMustafa Ismail struct irdma_cm_node *cm_node = cmnode; 243044d9e529SMustafa Ismail 243144d9e529SMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, wait); 243244d9e529SMustafa Ismail if (!cqp_request) 243344d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 243444d9e529SMustafa Ismail 243544d9e529SMustafa Ismail cqp_info = &cqp_request->info; 243644d9e529SMustafa Ismail info = &cqp_info->in.u.manage_qhash_table_entry.info; 243744d9e529SMustafa Ismail memset(info, 0, sizeof(*info)); 243844d9e529SMustafa Ismail info->vsi = &iwdev->vsi; 243944d9e529SMustafa Ismail info->manage = mtype; 244044d9e529SMustafa Ismail info->entry_type = etype; 244144d9e529SMustafa Ismail if (cminfo->vlan_id < VLAN_N_VID) { 244244d9e529SMustafa Ismail info->vlan_valid = true; 244344d9e529SMustafa Ismail info->vlan_id = cminfo->vlan_id; 244444d9e529SMustafa Ismail } else { 244544d9e529SMustafa Ismail info->vlan_valid = false; 244644d9e529SMustafa Ismail } 244744d9e529SMustafa Ismail info->ipv4_valid = cminfo->ipv4; 244844d9e529SMustafa Ismail info->user_pri = cminfo->user_pri; 244944d9e529SMustafa Ismail ether_addr_copy(info->mac_addr, iwdev->netdev->dev_addr); 245044d9e529SMustafa Ismail info->qp_num = cminfo->qh_qpid; 245144d9e529SMustafa Ismail info->dest_port = cminfo->loc_port; 245244d9e529SMustafa Ismail info->dest_ip[0] = cminfo->loc_addr[0]; 245344d9e529SMustafa Ismail info->dest_ip[1] = cminfo->loc_addr[1]; 245444d9e529SMustafa Ismail info->dest_ip[2] = cminfo->loc_addr[2]; 245544d9e529SMustafa Ismail info->dest_ip[3] = cminfo->loc_addr[3]; 245644d9e529SMustafa Ismail if (etype == IRDMA_QHASH_TYPE_TCP_ESTABLISHED || 245744d9e529SMustafa Ismail etype == IRDMA_QHASH_TYPE_UDP_UNICAST || 245844d9e529SMustafa Ismail etype == IRDMA_QHASH_TYPE_UDP_MCAST || 245944d9e529SMustafa Ismail etype == IRDMA_QHASH_TYPE_ROCE_MCAST || 246044d9e529SMustafa Ismail etype == IRDMA_QHASH_TYPE_ROCEV2_HW) { 246144d9e529SMustafa Ismail info->src_port = cminfo->rem_port; 246244d9e529SMustafa Ismail info->src_ip[0] = cminfo->rem_addr[0]; 246344d9e529SMustafa Ismail info->src_ip[1] = cminfo->rem_addr[1]; 246444d9e529SMustafa Ismail info->src_ip[2] = cminfo->rem_addr[2]; 246544d9e529SMustafa Ismail info->src_ip[3] = cminfo->rem_addr[3]; 246644d9e529SMustafa Ismail } 246744d9e529SMustafa Ismail if (cmnode) { 246844d9e529SMustafa Ismail cqp_request->callback_fcn = irdma_send_syn_cqp_callback; 246944d9e529SMustafa Ismail cqp_request->param = cmnode; 247044d9e529SMustafa Ismail if (!wait) 247144d9e529SMustafa Ismail refcount_inc(&cm_node->refcnt); 247244d9e529SMustafa Ismail } 247344d9e529SMustafa Ismail if (info->ipv4_valid) 247444d9e529SMustafa Ismail ibdev_dbg(&iwdev->ibdev, 247544d9e529SMustafa Ismail "CM: %s caller: %pS loc_port=0x%04x rem_port=0x%04x loc_addr=%pI4 rem_addr=%pI4 mac=%pM, vlan_id=%d cm_node=%p\n", 247644d9e529SMustafa Ismail (!mtype) ? "DELETE" : "ADD", 247744d9e529SMustafa Ismail __builtin_return_address(0), info->dest_port, 247844d9e529SMustafa Ismail info->src_port, info->dest_ip, info->src_ip, 247944d9e529SMustafa Ismail info->mac_addr, cminfo->vlan_id, 248044d9e529SMustafa Ismail cmnode ? cmnode : NULL); 248144d9e529SMustafa Ismail else 248244d9e529SMustafa Ismail ibdev_dbg(&iwdev->ibdev, 248344d9e529SMustafa Ismail "CM: %s caller: %pS loc_port=0x%04x rem_port=0x%04x loc_addr=%pI6 rem_addr=%pI6 mac=%pM, vlan_id=%d cm_node=%p\n", 248444d9e529SMustafa Ismail (!mtype) ? "DELETE" : "ADD", 248544d9e529SMustafa Ismail __builtin_return_address(0), info->dest_port, 248644d9e529SMustafa Ismail info->src_port, info->dest_ip, info->src_ip, 248744d9e529SMustafa Ismail info->mac_addr, cminfo->vlan_id, 248844d9e529SMustafa Ismail cmnode ? cmnode : NULL); 248944d9e529SMustafa Ismail 249044d9e529SMustafa Ismail cqp_info->in.u.manage_qhash_table_entry.cqp = &iwdev->rf->cqp.sc_cqp; 249144d9e529SMustafa Ismail cqp_info->in.u.manage_qhash_table_entry.scratch = (uintptr_t)cqp_request; 249244d9e529SMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_MANAGE_QHASH_TABLE_ENTRY; 249344d9e529SMustafa Ismail cqp_info->post_sq = 1; 249444d9e529SMustafa Ismail status = irdma_handle_cqp_op(iwdev->rf, cqp_request); 249544d9e529SMustafa Ismail if (status && cm_node && !wait) 249644d9e529SMustafa Ismail irdma_rem_ref_cm_node(cm_node); 249744d9e529SMustafa Ismail 249844d9e529SMustafa Ismail irdma_put_cqp_request(iwcqp, cqp_request); 249944d9e529SMustafa Ismail 250044d9e529SMustafa Ismail return status; 250144d9e529SMustafa Ismail } 250244d9e529SMustafa Ismail 250344d9e529SMustafa Ismail /** 250444d9e529SMustafa Ismail * irdma_hw_flush_wqes_callback - Check return code after flush 250544d9e529SMustafa Ismail * @cqp_request: qhash cqp completion 250644d9e529SMustafa Ismail */ 250744d9e529SMustafa Ismail static void irdma_hw_flush_wqes_callback(struct irdma_cqp_request *cqp_request) 250844d9e529SMustafa Ismail { 250944d9e529SMustafa Ismail struct irdma_qp_flush_info *hw_info; 251044d9e529SMustafa Ismail struct irdma_sc_qp *qp; 251144d9e529SMustafa Ismail struct irdma_qp *iwqp; 251244d9e529SMustafa Ismail struct cqp_cmds_info *cqp_info; 251344d9e529SMustafa Ismail 251444d9e529SMustafa Ismail cqp_info = &cqp_request->info; 251544d9e529SMustafa Ismail hw_info = &cqp_info->in.u.qp_flush_wqes.info; 251644d9e529SMustafa Ismail qp = cqp_info->in.u.qp_flush_wqes.qp; 251744d9e529SMustafa Ismail iwqp = qp->qp_uk.back_qp; 251844d9e529SMustafa Ismail 251944d9e529SMustafa Ismail if (cqp_request->compl_info.maj_err_code) 252044d9e529SMustafa Ismail return; 252144d9e529SMustafa Ismail 252244d9e529SMustafa Ismail if (hw_info->rq && 252344d9e529SMustafa Ismail (cqp_request->compl_info.min_err_code == IRDMA_CQP_COMPL_SQ_WQE_FLUSHED || 252444d9e529SMustafa Ismail cqp_request->compl_info.min_err_code == 0)) { 252544d9e529SMustafa Ismail /* RQ WQE flush was requested but did not happen */ 252644d9e529SMustafa Ismail qp->qp_uk.rq_flush_complete = true; 252744d9e529SMustafa Ismail } 252844d9e529SMustafa Ismail if (hw_info->sq && 252944d9e529SMustafa Ismail (cqp_request->compl_info.min_err_code == IRDMA_CQP_COMPL_RQ_WQE_FLUSHED || 253044d9e529SMustafa Ismail cqp_request->compl_info.min_err_code == 0)) { 253144d9e529SMustafa Ismail if (IRDMA_RING_MORE_WORK(qp->qp_uk.sq_ring)) { 253244d9e529SMustafa Ismail ibdev_err(&iwqp->iwdev->ibdev, "Flush QP[%d] failed, SQ has more work", 253344d9e529SMustafa Ismail qp->qp_uk.qp_id); 253444d9e529SMustafa Ismail irdma_ib_qp_event(iwqp, IRDMA_QP_EVENT_CATASTROPHIC); 253544d9e529SMustafa Ismail } 253644d9e529SMustafa Ismail qp->qp_uk.sq_flush_complete = true; 253744d9e529SMustafa Ismail } 253844d9e529SMustafa Ismail } 253944d9e529SMustafa Ismail 254044d9e529SMustafa Ismail /** 254144d9e529SMustafa Ismail * irdma_hw_flush_wqes - flush qp's wqe 254244d9e529SMustafa Ismail * @rf: RDMA PCI function 254344d9e529SMustafa Ismail * @qp: hardware control qp 254444d9e529SMustafa Ismail * @info: info for flush 254544d9e529SMustafa Ismail * @wait: flag wait for completion 254644d9e529SMustafa Ismail */ 254744d9e529SMustafa Ismail enum irdma_status_code irdma_hw_flush_wqes(struct irdma_pci_f *rf, 254844d9e529SMustafa Ismail struct irdma_sc_qp *qp, 254944d9e529SMustafa Ismail struct irdma_qp_flush_info *info, 255044d9e529SMustafa Ismail bool wait) 255144d9e529SMustafa Ismail { 255244d9e529SMustafa Ismail enum irdma_status_code status; 255344d9e529SMustafa Ismail struct irdma_qp_flush_info *hw_info; 255444d9e529SMustafa Ismail struct irdma_cqp_request *cqp_request; 255544d9e529SMustafa Ismail struct cqp_cmds_info *cqp_info; 255644d9e529SMustafa Ismail struct irdma_qp *iwqp = qp->qp_uk.back_qp; 255744d9e529SMustafa Ismail 255844d9e529SMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, wait); 255944d9e529SMustafa Ismail if (!cqp_request) 256044d9e529SMustafa Ismail return IRDMA_ERR_NO_MEMORY; 256144d9e529SMustafa Ismail 256244d9e529SMustafa Ismail cqp_info = &cqp_request->info; 256344d9e529SMustafa Ismail if (!wait) 256444d9e529SMustafa Ismail cqp_request->callback_fcn = irdma_hw_flush_wqes_callback; 256544d9e529SMustafa Ismail hw_info = &cqp_request->info.in.u.qp_flush_wqes.info; 256644d9e529SMustafa Ismail memcpy(hw_info, info, sizeof(*hw_info)); 256744d9e529SMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_QP_FLUSH_WQES; 256844d9e529SMustafa Ismail cqp_info->post_sq = 1; 256944d9e529SMustafa Ismail cqp_info->in.u.qp_flush_wqes.qp = qp; 257044d9e529SMustafa Ismail cqp_info->in.u.qp_flush_wqes.scratch = (uintptr_t)cqp_request; 257144d9e529SMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 257244d9e529SMustafa Ismail if (status) { 257344d9e529SMustafa Ismail qp->qp_uk.sq_flush_complete = true; 257444d9e529SMustafa Ismail qp->qp_uk.rq_flush_complete = true; 257544d9e529SMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 257644d9e529SMustafa Ismail return status; 257744d9e529SMustafa Ismail } 257844d9e529SMustafa Ismail 257944d9e529SMustafa Ismail if (!wait || cqp_request->compl_info.maj_err_code) 258044d9e529SMustafa Ismail goto put_cqp; 258144d9e529SMustafa Ismail 258244d9e529SMustafa Ismail if (info->rq) { 258344d9e529SMustafa Ismail if (cqp_request->compl_info.min_err_code == IRDMA_CQP_COMPL_SQ_WQE_FLUSHED || 258444d9e529SMustafa Ismail cqp_request->compl_info.min_err_code == 0) { 258544d9e529SMustafa Ismail /* RQ WQE flush was requested but did not happen */ 258644d9e529SMustafa Ismail qp->qp_uk.rq_flush_complete = true; 258744d9e529SMustafa Ismail } 258844d9e529SMustafa Ismail } 258944d9e529SMustafa Ismail if (info->sq) { 259044d9e529SMustafa Ismail if (cqp_request->compl_info.min_err_code == IRDMA_CQP_COMPL_RQ_WQE_FLUSHED || 259144d9e529SMustafa Ismail cqp_request->compl_info.min_err_code == 0) { 259244d9e529SMustafa Ismail /* 259344d9e529SMustafa Ismail * Handling case where WQE is posted to empty SQ when 259444d9e529SMustafa Ismail * flush has not completed 259544d9e529SMustafa Ismail */ 259644d9e529SMustafa Ismail if (IRDMA_RING_MORE_WORK(qp->qp_uk.sq_ring)) { 259744d9e529SMustafa Ismail struct irdma_cqp_request *new_req; 259844d9e529SMustafa Ismail 259944d9e529SMustafa Ismail if (!qp->qp_uk.sq_flush_complete) 260044d9e529SMustafa Ismail goto put_cqp; 260144d9e529SMustafa Ismail qp->qp_uk.sq_flush_complete = false; 260244d9e529SMustafa Ismail qp->flush_sq = false; 260344d9e529SMustafa Ismail 260444d9e529SMustafa Ismail info->rq = false; 260544d9e529SMustafa Ismail info->sq = true; 260644d9e529SMustafa Ismail new_req = irdma_alloc_and_get_cqp_request(&rf->cqp, true); 260744d9e529SMustafa Ismail if (!new_req) { 260844d9e529SMustafa Ismail status = IRDMA_ERR_NO_MEMORY; 260944d9e529SMustafa Ismail goto put_cqp; 261044d9e529SMustafa Ismail } 261144d9e529SMustafa Ismail cqp_info = &new_req->info; 261244d9e529SMustafa Ismail hw_info = &new_req->info.in.u.qp_flush_wqes.info; 261344d9e529SMustafa Ismail memcpy(hw_info, info, sizeof(*hw_info)); 261444d9e529SMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_QP_FLUSH_WQES; 261544d9e529SMustafa Ismail cqp_info->post_sq = 1; 261644d9e529SMustafa Ismail cqp_info->in.u.qp_flush_wqes.qp = qp; 261744d9e529SMustafa Ismail cqp_info->in.u.qp_flush_wqes.scratch = (uintptr_t)new_req; 261844d9e529SMustafa Ismail 261944d9e529SMustafa Ismail status = irdma_handle_cqp_op(rf, new_req); 262044d9e529SMustafa Ismail if (new_req->compl_info.maj_err_code || 262144d9e529SMustafa Ismail new_req->compl_info.min_err_code != IRDMA_CQP_COMPL_SQ_WQE_FLUSHED || 262244d9e529SMustafa Ismail status) { 262344d9e529SMustafa Ismail ibdev_err(&iwqp->iwdev->ibdev, "fatal QP event: SQ in error but not flushed, qp: %d", 262444d9e529SMustafa Ismail iwqp->ibqp.qp_num); 262544d9e529SMustafa Ismail qp->qp_uk.sq_flush_complete = false; 262644d9e529SMustafa Ismail irdma_ib_qp_event(iwqp, IRDMA_QP_EVENT_CATASTROPHIC); 262744d9e529SMustafa Ismail } 262844d9e529SMustafa Ismail irdma_put_cqp_request(&rf->cqp, new_req); 262944d9e529SMustafa Ismail } else { 263044d9e529SMustafa Ismail /* SQ WQE flush was requested but did not happen */ 263144d9e529SMustafa Ismail qp->qp_uk.sq_flush_complete = true; 263244d9e529SMustafa Ismail } 263344d9e529SMustafa Ismail } else { 263444d9e529SMustafa Ismail if (!IRDMA_RING_MORE_WORK(qp->qp_uk.sq_ring)) 263544d9e529SMustafa Ismail qp->qp_uk.sq_flush_complete = true; 263644d9e529SMustafa Ismail } 263744d9e529SMustafa Ismail } 263844d9e529SMustafa Ismail 263944d9e529SMustafa Ismail ibdev_dbg(&rf->iwdev->ibdev, 264044d9e529SMustafa Ismail "VERBS: qp_id=%d qp_type=%d qpstate=%d ibqpstate=%d last_aeq=%d hw_iw_state=%d maj_err_code=%d min_err_code=%d\n", 264144d9e529SMustafa Ismail iwqp->ibqp.qp_num, rf->protocol_used, iwqp->iwarp_state, 264244d9e529SMustafa Ismail iwqp->ibqp_state, iwqp->last_aeq, iwqp->hw_iwarp_state, 264344d9e529SMustafa Ismail cqp_request->compl_info.maj_err_code, 264444d9e529SMustafa Ismail cqp_request->compl_info.min_err_code); 264544d9e529SMustafa Ismail put_cqp: 264644d9e529SMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 264744d9e529SMustafa Ismail 264844d9e529SMustafa Ismail return status; 264944d9e529SMustafa Ismail } 265044d9e529SMustafa Ismail 265144d9e529SMustafa Ismail /** 265244d9e529SMustafa Ismail * irdma_gen_ae - generate AE 265344d9e529SMustafa Ismail * @rf: RDMA PCI function 265444d9e529SMustafa Ismail * @qp: qp associated with AE 265544d9e529SMustafa Ismail * @info: info for ae 265644d9e529SMustafa Ismail * @wait: wait for completion 265744d9e529SMustafa Ismail */ 265844d9e529SMustafa Ismail void irdma_gen_ae(struct irdma_pci_f *rf, struct irdma_sc_qp *qp, 265944d9e529SMustafa Ismail struct irdma_gen_ae_info *info, bool wait) 266044d9e529SMustafa Ismail { 266144d9e529SMustafa Ismail struct irdma_gen_ae_info *ae_info; 266244d9e529SMustafa Ismail struct irdma_cqp_request *cqp_request; 266344d9e529SMustafa Ismail struct cqp_cmds_info *cqp_info; 266444d9e529SMustafa Ismail 266544d9e529SMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, wait); 266644d9e529SMustafa Ismail if (!cqp_request) 266744d9e529SMustafa Ismail return; 266844d9e529SMustafa Ismail 266944d9e529SMustafa Ismail cqp_info = &cqp_request->info; 267044d9e529SMustafa Ismail ae_info = &cqp_request->info.in.u.gen_ae.info; 267144d9e529SMustafa Ismail memcpy(ae_info, info, sizeof(*ae_info)); 267244d9e529SMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_GEN_AE; 267344d9e529SMustafa Ismail cqp_info->post_sq = 1; 267444d9e529SMustafa Ismail cqp_info->in.u.gen_ae.qp = qp; 267544d9e529SMustafa Ismail cqp_info->in.u.gen_ae.scratch = (uintptr_t)cqp_request; 267644d9e529SMustafa Ismail 267744d9e529SMustafa Ismail irdma_handle_cqp_op(rf, cqp_request); 267844d9e529SMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 267944d9e529SMustafa Ismail } 268044d9e529SMustafa Ismail 268144d9e529SMustafa Ismail void irdma_flush_wqes(struct irdma_qp *iwqp, u32 flush_mask) 268244d9e529SMustafa Ismail { 268344d9e529SMustafa Ismail struct irdma_qp_flush_info info = {}; 268444d9e529SMustafa Ismail struct irdma_pci_f *rf = iwqp->iwdev->rf; 268544d9e529SMustafa Ismail u8 flush_code = iwqp->sc_qp.flush_code; 268644d9e529SMustafa Ismail 268744d9e529SMustafa Ismail if (!(flush_mask & IRDMA_FLUSH_SQ) && !(flush_mask & IRDMA_FLUSH_RQ)) 268844d9e529SMustafa Ismail return; 268944d9e529SMustafa Ismail 269044d9e529SMustafa Ismail /* Set flush info fields*/ 269144d9e529SMustafa Ismail info.sq = flush_mask & IRDMA_FLUSH_SQ; 269244d9e529SMustafa Ismail info.rq = flush_mask & IRDMA_FLUSH_RQ; 269344d9e529SMustafa Ismail 269444d9e529SMustafa Ismail if (flush_mask & IRDMA_REFLUSH) { 269544d9e529SMustafa Ismail if (info.sq) 269644d9e529SMustafa Ismail iwqp->sc_qp.flush_sq = false; 269744d9e529SMustafa Ismail if (info.rq) 269844d9e529SMustafa Ismail iwqp->sc_qp.flush_rq = false; 269944d9e529SMustafa Ismail } 270044d9e529SMustafa Ismail 270144d9e529SMustafa Ismail /* Generate userflush errors in CQE */ 270244d9e529SMustafa Ismail info.sq_major_code = IRDMA_FLUSH_MAJOR_ERR; 270344d9e529SMustafa Ismail info.sq_minor_code = FLUSH_GENERAL_ERR; 270444d9e529SMustafa Ismail info.rq_major_code = IRDMA_FLUSH_MAJOR_ERR; 270544d9e529SMustafa Ismail info.rq_minor_code = FLUSH_GENERAL_ERR; 270644d9e529SMustafa Ismail info.userflushcode = true; 270744d9e529SMustafa Ismail if (flush_code) { 270844d9e529SMustafa Ismail if (info.sq && iwqp->sc_qp.sq_flush_code) 270944d9e529SMustafa Ismail info.sq_minor_code = flush_code; 271044d9e529SMustafa Ismail if (info.rq && iwqp->sc_qp.rq_flush_code) 271144d9e529SMustafa Ismail info.rq_minor_code = flush_code; 271244d9e529SMustafa Ismail } 271344d9e529SMustafa Ismail 271444d9e529SMustafa Ismail /* Issue flush */ 271544d9e529SMustafa Ismail (void)irdma_hw_flush_wqes(rf, &iwqp->sc_qp, &info, 271644d9e529SMustafa Ismail flush_mask & IRDMA_FLUSH_WAIT); 271744d9e529SMustafa Ismail iwqp->flush_issued = true; 271844d9e529SMustafa Ismail } 2719