⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ehca_qp.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	ehca_dbg(&shca->ib_device, "qp_num=%x bad_send_wqe_p=%p",		 qp_num, bad_send_wqe_p);	/* convert wqe pointer to vadr */	bad_send_wqe_v = abs_to_virt((u64)bad_send_wqe_p);	if (ehca_debug_level)		ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num);	squeue = &my_qp->ipz_squeue;	if (ipz_queue_abs_to_offset(squeue, (u64)bad_send_wqe_p, &q_ofs)) {		ehca_err(&shca->ib_device, "failed to get wqe offset qp_num=%x"			 " bad_send_wqe_p=%p", qp_num, bad_send_wqe_p);		return -EFAULT;	}	/* loop sets wqe's purge bit */	wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs);	*bad_wqe_cnt = 0;	while (wqe->optype != 0xff && wqe->wqef != 0xff) {		if (ehca_debug_level)			ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num);		wqe->nr_of_data_seg = 0; /* suppress data access */		wqe->wqef = WQEF_PURGE; /* WQE to be purged */		q_ofs = ipz_queue_advance_offset(squeue, q_ofs);		wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs);		*bad_wqe_cnt = (*bad_wqe_cnt)+1;	}	/*	 * bad wqe will be reprocessed and ignored when pol_cq() is called,	 *  i.e. nr of wqes with flush error status is one less	 */	ehca_dbg(&shca->ib_device, "qp_num=%x flusherr_wqe_cnt=%x",		 qp_num, (*bad_wqe_cnt)-1);	wqe->wqef = 0;	return 0;}/* * internal_modify_qp with circumvention to handle aqp0 properly * smi_reset2init indicates if this is an internal reset-to-init-call for * smi. This flag must always be zero if called from ehca_modify_qp()! * This internal func was intorduced to avoid recursion of ehca_modify_qp()! */static int internal_modify_qp(struct ib_qp *ibqp,			      struct ib_qp_attr *attr,			      int attr_mask, int smi_reset2init){	enum ib_qp_state qp_cur_state, qp_new_state;	int cnt, qp_attr_idx, ret = 0;	enum ib_qp_statetrans statetrans;	struct hcp_modify_qp_control_block *mqpcb;	struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);	struct ehca_shca *shca =		container_of(ibqp->pd->device, struct ehca_shca, ib_device);	u64 update_mask;	u64 h_ret;	int bad_wqe_cnt = 0;	int squeue_locked = 0;	unsigned long flags = 0;	/* do query_qp to obtain current attr values */	mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);	if (!mqpcb) {		ehca_err(ibqp->device, "Could not get zeroed page for mqpcb "			 "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num);		return -ENOMEM;	}	h_ret = hipz_h_query_qp(shca->ipz_hca_handle,				my_qp->ipz_qp_handle,				&my_qp->pf,				mqpcb, my_qp->galpas.kernel);	if (h_ret != H_SUCCESS) {		ehca_err(ibqp->device, "hipz_h_query_qp() failed "			 "ehca_qp=%p qp_num=%x h_ret=%li",			 my_qp, ibqp->qp_num, h_ret);		ret = ehca2ib_return_code(h_ret);		goto modify_qp_exit1;	}	qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state);	if (qp_cur_state == -EINVAL) {	/* invalid qp state */		ret = -EINVAL;		ehca_err(ibqp->device, "Invalid current ehca_qp_state=%x "			 "ehca_qp=%p qp_num=%x",			 mqpcb->qp_state, my_qp, ibqp->qp_num);		goto modify_qp_exit1;	}	/*	 * circumvention to set aqp0 initial state to init	 * as expected by IB spec	 */	if (smi_reset2init == 0 &&	    ibqp->qp_type == IB_QPT_SMI &&	    qp_cur_state == IB_QPS_RESET &&	    (attr_mask & IB_QP_STATE) &&	    attr->qp_state == IB_QPS_INIT) { /* RESET -> INIT */		struct ib_qp_attr smiqp_attr = {			.qp_state = IB_QPS_INIT,			.port_num = my_qp->init_attr.port_num,			.pkey_index = 0,			.qkey = 0		};		int smiqp_attr_mask = IB_QP_STATE | IB_QP_PORT |			IB_QP_PKEY_INDEX | IB_QP_QKEY;		int smirc = internal_modify_qp(			ibqp, &smiqp_attr, smiqp_attr_mask, 1);		if (smirc) {			ehca_err(ibqp->device, "SMI RESET -> INIT failed. "				 "ehca_modify_qp() rc=%i", smirc);			ret = H_PARAMETER;			goto modify_qp_exit1;		}		qp_cur_state = IB_QPS_INIT;		ehca_dbg(ibqp->device, "SMI RESET -> INIT succeeded");	}	/* is transmitted current state  equal to "real" current state */	if ((attr_mask & IB_QP_CUR_STATE) &&	    qp_cur_state != attr->cur_qp_state) {		ret = -EINVAL;		ehca_err(ibqp->device,			 "Invalid IB_QP_CUR_STATE attr->curr_qp_state=%x <>"			 " actual cur_qp_state=%x. ehca_qp=%p qp_num=%x",			 attr->cur_qp_state, qp_cur_state, my_qp, ibqp->qp_num);		goto modify_qp_exit1;	}	ehca_dbg(ibqp->device, "ehca_qp=%p qp_num=%x current qp_state=%x "		 "new qp_state=%x attribute_mask=%x",		 my_qp, ibqp->qp_num, qp_cur_state, attr->qp_state, attr_mask);	qp_new_state = attr_mask & IB_QP_STATE ? attr->qp_state : qp_cur_state;	if (!smi_reset2init &&	    !ib_modify_qp_is_ok(qp_cur_state, qp_new_state, ibqp->qp_type,				attr_mask)) {		ret = -EINVAL;		ehca_err(ibqp->device,			 "Invalid qp transition new_state=%x cur_state=%x "			 "ehca_qp=%p qp_num=%x attr_mask=%x", qp_new_state,			 qp_cur_state, my_qp, ibqp->qp_num, attr_mask);		goto modify_qp_exit1;	}	mqpcb->qp_state = ib2ehca_qp_state(qp_new_state);	if (mqpcb->qp_state)		update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);	else {		ret = -EINVAL;		ehca_err(ibqp->device, "Invalid new qp state=%x "			 "ehca_qp=%p qp_num=%x",			 qp_new_state, my_qp, ibqp->qp_num);		goto modify_qp_exit1;	}	/* retrieve state transition struct to get req and opt attrs */	statetrans = get_modqp_statetrans(qp_cur_state, qp_new_state);	if (statetrans < 0) {		ret = -EINVAL;		ehca_err(ibqp->device, "<INVALID STATE CHANGE> qp_cur_state=%x "			 "new_qp_state=%x State_xsition=%x ehca_qp=%p "			 "qp_num=%x", qp_cur_state, qp_new_state,			 statetrans, my_qp, ibqp->qp_num);		goto modify_qp_exit1;	}	qp_attr_idx = ib2ehcaqptype(ibqp->qp_type);	if (qp_attr_idx < 0) {		ret = qp_attr_idx;		ehca_err(ibqp->device,			 "Invalid QP type=%x ehca_qp=%p qp_num=%x",			 ibqp->qp_type, my_qp, ibqp->qp_num);		goto modify_qp_exit1;	}	ehca_dbg(ibqp->device,		 "ehca_qp=%p qp_num=%x <VALID STATE CHANGE> qp_state_xsit=%x",		 my_qp, ibqp->qp_num, statetrans);	/* eHCA2 rev2 and higher require the SEND_GRH_FLAG to be set	 * in non-LL UD QPs.	 */	if ((my_qp->qp_type == IB_QPT_UD) &&	    (my_qp->ext_type != EQPT_LLQP) &&	    (statetrans == IB_QPST_INIT2RTR) &&	    (shca->hw_level >= 0x22)) {		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);		mqpcb->send_grh_flag = 1;	}	/* sqe -> rts: set purge bit of bad wqe before actual trans */	if ((my_qp->qp_type == IB_QPT_UD ||	     my_qp->qp_type == IB_QPT_GSI ||	     my_qp->qp_type == IB_QPT_SMI) &&	    statetrans == IB_QPST_SQE2RTS) {		/* mark next free wqe if kernel */		if (!ibqp->uobject) {			struct ehca_wqe *wqe;			/* lock send queue */			spin_lock_irqsave(&my_qp->spinlock_s, flags);			squeue_locked = 1;			/* mark next free wqe */			wqe = (struct ehca_wqe *)				ipz_qeit_get(&my_qp->ipz_squeue);			wqe->optype = wqe->wqef = 0xff;			ehca_dbg(ibqp->device, "qp_num=%x next_free_wqe=%p",				 ibqp->qp_num, wqe);		}		ret = prepare_sqe_rts(my_qp, shca, &bad_wqe_cnt);		if (ret) {			ehca_err(ibqp->device, "prepare_sqe_rts() failed "				 "ehca_qp=%p qp_num=%x ret=%i",				 my_qp, ibqp->qp_num, ret);			goto modify_qp_exit2;		}	}	/*	 * enable RDMA_Atomic_Control if reset->init und reliable con	 * this is necessary since gen2 does not provide that flag,	 * but pHyp requires it	 */	if (statetrans == IB_QPST_RESET2INIT &&	    (ibqp->qp_type == IB_QPT_RC || ibqp->qp_type == IB_QPT_UC)) {		mqpcb->rdma_atomic_ctrl = 3;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RDMA_ATOMIC_CTRL, 1);	}	/* circ. pHyp requires #RDMA/Atomic Resp Res for UC INIT -> RTR */	if (statetrans == IB_QPST_INIT2RTR &&	    (ibqp->qp_type == IB_QPT_UC) &&	    !(attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)) {		mqpcb->rdma_nr_atomic_resp_res = 1; /* default to 1 */		update_mask |=			EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1);	}	if (attr_mask & IB_QP_PKEY_INDEX) {		if (attr->pkey_index >= 16) {			ret = -EINVAL;			ehca_err(ibqp->device, "Invalid pkey_index=%x. "				 "ehca_qp=%p qp_num=%x max_pkey_index=f",				 attr->pkey_index, my_qp, ibqp->qp_num);			goto modify_qp_exit2;		}		mqpcb->prim_p_key_idx = attr->pkey_index;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1);	}	if (attr_mask & IB_QP_PORT) {		if (attr->port_num < 1 || attr->port_num > shca->num_ports) {			ret = -EINVAL;			ehca_err(ibqp->device, "Invalid port=%x. "				 "ehca_qp=%p qp_num=%x num_ports=%x",				 attr->port_num, my_qp, ibqp->qp_num,				 shca->num_ports);			goto modify_qp_exit2;		}		mqpcb->prim_phys_port = attr->port_num;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1);	}	if (attr_mask & IB_QP_QKEY) {		mqpcb->qkey = attr->qkey;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1);	}	if (attr_mask & IB_QP_AV) {		mqpcb->dlid = attr->ah_attr.dlid;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1);		mqpcb->source_path_bits = attr->ah_attr.src_path_bits;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS, 1);		mqpcb->service_level = attr->ah_attr.sl;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1);		if (ehca_calc_ipd(shca, mqpcb->prim_phys_port,				  attr->ah_attr.static_rate,				  &mqpcb->max_static_rate)) {			ret = -EINVAL;			goto modify_qp_exit2;		}		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1);		/*		 * Always supply the GRH flag, even if it's zero, to give the		 * hypervisor a clear "yes" or "no" instead of a "perhaps"		 */		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);		/*		 * only if GRH is TRUE we might consider SOURCE_GID_IDX		 * and DEST_GID otherwise phype will return H_ATTR_PARM!!!		 */		if (attr->ah_attr.ah_flags == IB_AH_GRH) {			mqpcb->send_grh_flag = 1;			mqpcb->source_gid_idx = attr->ah_attr.grh.sgid_index;			update_mask |=				EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX, 1);			for (cnt = 0; cnt < 16; cnt++)				mqpcb->dest_gid.byte[cnt] =					attr->ah_attr.grh.dgid.raw[cnt];			update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_GID, 1);			mqpcb->flow_label = attr->ah_attr.grh.flow_label;			update_mask |= EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL, 1);			mqpcb->hop_limit = attr->ah_attr.grh.hop_limit;			update_mask |= EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT, 1);			mqpcb->traffic_class = attr->ah_attr.grh.traffic_class;			update_mask |=				EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS, 1);		}	}	if (attr_mask & IB_QP_PATH_MTU) {		mqpcb->path_mtu = attr->path_mtu;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1);	}	if (attr_mask & IB_QP_TIMEOUT) {		mqpcb->timeout = attr->timeout;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT, 1);	}	if (attr_mask & IB_QP_RETRY_CNT) {		mqpcb->retry_count = attr->retry_cnt;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT, 1);	}	if (attr_mask & IB_QP_RNR_RETRY) {		mqpcb->rnr_retry_count = attr->rnr_retry;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT, 1);	}	if (attr_mask & IB_QP_RQ_PSN) {		mqpcb->receive_psn = attr->rq_psn;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RECEIVE_PSN, 1);	}	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {		mqpcb->rdma_nr_atomic_resp_res = attr->max_dest_rd_atomic < 3 ?			attr->max_dest_rd_atomic : 2;		update_mask |=			EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1);	}	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {		mqpcb->rdma_atomic_outst_dest_qp = attr->max_rd_atomic < 3 ?			attr->max_rd_atomic : 2;		update_mask |=			EHCA_BMASK_SET			(MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1);	}	if (attr_mask & IB_QP_ALT_PATH) {		if (attr->alt_port_num < 1		    || attr->alt_port_num > shca->num_ports) {			ret = -EINVAL;			ehca_err(ibqp->device, "Invalid alt_port=%x. "				 "ehca_qp=%p qp_num=%x num_ports=%x",				 attr->alt_port_num, my_qp, ibqp->qp_num,				 shca->num_ports);			goto modify_qp_exit2;		}		mqpcb->alt_phys_port = attr->alt_port_num;		if (attr->alt_pkey_index >= 16) {			ret = -EINVAL;			ehca_err(ibqp->device, "Invalid alt_pkey_index=%x. "				 "ehca_qp=%p qp_num=%x max_pkey_index=f",				 attr->pkey_index, my_qp, ibqp->qp_num);			goto modify_qp_exit2;		}		mqpcb->alt_p_key_idx = attr->alt_pkey_index;		mqpcb->timeout_al = attr->alt_timeout;		mqpcb->dlid_al = attr->alt_ah_attr.dlid;		mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits;		mqpcb->service_level_al = attr->alt_ah_attr.sl;		if (ehca_calc_ipd(shca, mqpcb->alt_phys_port,				  attr->alt_ah_attr.static_rate,				  &mqpcb->max_static_rate_al)) {			ret = -EINVAL;			goto modify_qp_exit2;		}		/* OpenIB doesn't support alternate retry counts - copy them */		mqpcb->retry_count_al = mqpcb->retry_count;		mqpcb->rnr_retry_count_al = mqpcb->rnr_retry_count;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_ALT_PHYS_PORT, 1)			| EHCA_BMASK_SET(MQPCB_MASK_ALT_P_KEY_IDX, 1)			| EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT_AL, 1)			| EHCA_BMASK_SET(MQPCB_MASK_DLID_AL, 1)			| EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS_AL, 1)			| EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL_AL, 1)			| EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE_AL, 1)			| EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT_AL, 1)			| EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT_AL, 1);		/*		 * Always supply the GRH flag, even if it's zero, to give the		 * hypervisor a clear "yes" or "no" instead of a "perhaps"		 */		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG_AL, 1);		/*		 * only if GRH is TRUE we might consider SOURCE_GID_IDX		 * and DEST_GID otherwise phype will return H_ATTR_PARM!!!		 */		if (attr->alt_ah_attr.ah_flags == IB_AH_GRH) {			mqpcb->send_grh_flag_al = 1;			for (cnt = 0; cnt < 16; cnt++)				mqpcb->dest_gid_al.byte[cnt] =					attr->alt_ah_attr.grh.dgid.raw[cnt];			mqpcb->source_gid_idx_al =				attr->alt_ah_attr.grh.sgid_index;			mqpcb->flow_label_al = attr->alt_ah_attr.grh.flow_label;			mqpcb->hop_limit_al = attr->alt_ah_attr.grh.hop_limit;			mqpcb->traffic_class_al =				attr->alt_ah_attr.grh.traffic_class;			update_mask |=				EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX_AL, 1)				| EHCA_BMASK_SET(MQPCB_MASK_DEST_GID_AL, 1)				| EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL_AL, 1)				| EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT_AL, 1) |				EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS_AL, 1);		}	}	if (attr_mask & IB_QP_MIN_RNR_TIMER) {		mqpcb->min_rnr_nak_timer_field = attr->min_rnr_timer;		update_mask |=			EHCA_BMASK_SET(MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD, 1);	}	if (attr_mask & IB_QP_SQ_PSN) {		mqpcb->send_psn = attr->sq_psn;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_PSN, 1);	}	if (attr_mask & IB_QP_DEST_QPN) {		mqpcb->dest_qp_nr = attr->dest_qp_num;		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_QP_NR, 1);	}	if (attr_mask & IB_QP_PATH_MIG_STATE) {		if (attr->path_mig_state != IB_MIG_REARM		    && attr->path_mig_state != IB_MIG_MIGRATED) {			ret = -EINVAL;			ehca_err(ibqp->device, "Invalid mig_state=%x",				 attr->path_mig_state);			goto modify_qp_exit2;		}		mqpcb->path_migration_state = attr->path_mig_state + 1;		update_mask |=			EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1);	}	if (attr_mask & IB_QP_CAP) {		mqpcb->max_nr_outst_send_wr = attr->cap.max_send_wr+1;		update_mask |=			EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_SEND_WR, 1);		mqpcb->max_nr_outst_recv_wr = attr->cap.max_recv_wr+1;		update_mask |=			EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_RECV_WR, 1);		/* no support for max_send/recv_sge yet */	}	if (ehca_debug_level)		ehca_dmp(mqpcb, 4*70, "qp_num=%x", ibqp->qp_num);	h_ret = hipz_h_modify_qp(shca->ipz_hca_handle,				 my_qp->ipz_qp_handle,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -