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

📄 ehca_qp.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
				 pd, init_attr->cap.max_recv_sge);			return ERR_PTR(-EINVAL);		}	}	/* check QP type */	if (qp_type != IB_QPT_UD &&	    qp_type != IB_QPT_UC &&	    qp_type != IB_QPT_RC &&	    qp_type != IB_QPT_SMI &&	    qp_type != IB_QPT_GSI) {		ehca_err(pd->device, "wrong QP Type=%x", qp_type);		return ERR_PTR(-EINVAL);	}	if (is_llqp) {		switch (qp_type) {		case IB_QPT_RC:			if ((init_attr->cap.max_send_wr > 255) ||			    (init_attr->cap.max_recv_wr > 255)) {				ehca_err(pd->device,					 "Invalid Number of max_sq_wr=%x "					 "or max_rq_wr=%x for RC LLQP",					 init_attr->cap.max_send_wr,					 init_attr->cap.max_recv_wr);				return ERR_PTR(-EINVAL);			}			break;		case IB_QPT_UD:			if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) {				ehca_err(pd->device, "UD LLQP not supported "					 "by this adapter");				return ERR_PTR(-ENOSYS);			}			if (!(init_attr->cap.max_send_sge <= 5			    && init_attr->cap.max_send_sge >= 1			    && init_attr->cap.max_recv_sge <= 5			    && init_attr->cap.max_recv_sge >= 1)) {				ehca_err(pd->device,					 "Invalid Number of max_send_sge=%x "					 "or max_recv_sge=%x for UD LLQP",					 init_attr->cap.max_send_sge,					 init_attr->cap.max_recv_sge);				return ERR_PTR(-EINVAL);			} else if (init_attr->cap.max_send_wr > 255) {				ehca_err(pd->device,					 "Invalid Number of "					 "max_send_wr=%x for UD QP_TYPE=%x",					 init_attr->cap.max_send_wr, qp_type);				return ERR_PTR(-EINVAL);			}			break;		default:			ehca_err(pd->device, "unsupported LL QP Type=%x",				 qp_type);			return ERR_PTR(-EINVAL);			break;		}	} else {		int max_sge = (qp_type == IB_QPT_UD || qp_type == IB_QPT_SMI			       || qp_type == IB_QPT_GSI) ? 250 : 252;		if (init_attr->cap.max_send_sge > max_sge		    || init_attr->cap.max_recv_sge > max_sge) {			ehca_err(pd->device, "Invalid number of SGEs requested "				 "send_sge=%x recv_sge=%x max_sge=%x",				 init_attr->cap.max_send_sge,				 init_attr->cap.max_recv_sge, max_sge);			return ERR_PTR(-EINVAL);		}	}	if (pd->uobject && udata)		context = pd->uobject->context;	my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);	if (!my_qp) {		ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);		return ERR_PTR(-ENOMEM);	}	spin_lock_init(&my_qp->spinlock_s);	spin_lock_init(&my_qp->spinlock_r);	my_qp->qp_type = qp_type;	my_qp->ext_type = parms.ext_type;	if (init_attr->recv_cq)		my_qp->recv_cq =			container_of(init_attr->recv_cq, struct ehca_cq, ib_cq);	if (init_attr->send_cq)		my_qp->send_cq =			container_of(init_attr->send_cq, struct ehca_cq, ib_cq);	do {		if (!idr_pre_get(&ehca_qp_idr, GFP_KERNEL)) {			ret = -ENOMEM;			ehca_err(pd->device, "Can't reserve idr resources.");			goto create_qp_exit0;		}		write_lock_irqsave(&ehca_qp_idr_lock, flags);		ret = idr_get_new(&ehca_qp_idr, my_qp, &my_qp->token);		write_unlock_irqrestore(&ehca_qp_idr_lock, flags);	} while (ret == -EAGAIN);	if (ret) {		ret = -ENOMEM;		ehca_err(pd->device, "Can't allocate new idr entry.");		goto create_qp_exit0;	}	if (my_qp->token > 0x1FFFFFF) {		ret = -EINVAL;		ehca_err(pd->device, "Invalid number of qp");		goto create_qp_exit1;	}	if (has_srq)		parms.srq_token = my_qp->token;	parms.servicetype = ibqptype2servicetype(qp_type);	if (parms.servicetype < 0) {		ret = -EINVAL;		ehca_err(pd->device, "Invalid qp_type=%x", qp_type);		goto create_qp_exit1;	}	if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)		parms.sigtype = HCALL_SIGT_EVERY;	else		parms.sigtype = HCALL_SIGT_BY_WQE;	/* UD_AV CIRCUMVENTION */	max_send_sge = init_attr->cap.max_send_sge;	max_recv_sge = init_attr->cap.max_recv_sge;	if (parms.servicetype == ST_UD && !is_llqp) {		max_send_sge += 2;		max_recv_sge += 2;	}	parms.token = my_qp->token;	parms.eq_handle = shca->eq.ipz_eq_handle;	parms.pd = my_pd->fw_pd;	if (my_qp->send_cq)		parms.send_cq_handle = my_qp->send_cq->ipz_cq_handle;	if (my_qp->recv_cq)		parms.recv_cq_handle = my_qp->recv_cq->ipz_cq_handle;	parms.squeue.max_wr = init_attr->cap.max_send_wr;	parms.rqueue.max_wr = init_attr->cap.max_recv_wr;	parms.squeue.max_sge = max_send_sge;	parms.rqueue.max_sge = max_recv_sge;	if (EHCA_BMASK_GET(HCA_CAP_MINI_QP, shca->hca_cap)) {		if (HAS_SQ(my_qp))			ehca_determine_small_queue(				&parms.squeue, max_send_sge, is_llqp);		if (HAS_RQ(my_qp))			ehca_determine_small_queue(				&parms.rqueue, max_recv_sge, is_llqp);		parms.qp_storage =			(parms.squeue.is_small || parms.rqueue.is_small);	}	h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms);	if (h_ret != H_SUCCESS) {		ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%li",			 h_ret);		ret = ehca2ib_return_code(h_ret);		goto create_qp_exit1;	}	ib_qp_num = my_qp->real_qp_num = parms.real_qp_num;	my_qp->ipz_qp_handle = parms.qp_handle;	my_qp->galpas = parms.galpas;	swqe_size = ehca_calc_wqe_size(parms.squeue.act_nr_sges, is_llqp);	rwqe_size = ehca_calc_wqe_size(parms.rqueue.act_nr_sges, is_llqp);	switch (qp_type) {	case IB_QPT_RC:		if (is_llqp) {			parms.squeue.act_nr_sges = 1;			parms.rqueue.act_nr_sges = 1;		}		break;	case IB_QPT_UD:	case IB_QPT_GSI:	case IB_QPT_SMI:		/* UD circumvention */		if (is_llqp) {			parms.squeue.act_nr_sges = 1;			parms.rqueue.act_nr_sges = 1;		} else {			parms.squeue.act_nr_sges -= 2;			parms.rqueue.act_nr_sges -= 2;		}		if (IB_QPT_GSI == qp_type || IB_QPT_SMI == qp_type) {			parms.squeue.act_nr_wqes = init_attr->cap.max_send_wr;			parms.rqueue.act_nr_wqes = init_attr->cap.max_recv_wr;			parms.squeue.act_nr_sges = init_attr->cap.max_send_sge;			parms.rqueue.act_nr_sges = init_attr->cap.max_recv_sge;			ib_qp_num = (qp_type == IB_QPT_SMI) ? 0 : 1;		}		break;	default:		break;	}	/* initialize r/squeue and register queue pages */	if (HAS_SQ(my_qp)) {		ret = init_qp_queue(			shca, my_pd, my_qp, &my_qp->ipz_squeue, 0,			HAS_RQ(my_qp) ? H_PAGE_REGISTERED : H_SUCCESS,			&parms.squeue, swqe_size);		if (ret) {			ehca_err(pd->device, "Couldn't initialize squeue "				 "and pages ret=%i", ret);			goto create_qp_exit2;		}	}	if (HAS_RQ(my_qp)) {		ret = init_qp_queue(			shca, my_pd, my_qp, &my_qp->ipz_rqueue, 1,			H_SUCCESS, &parms.rqueue, rwqe_size);		if (ret) {			ehca_err(pd->device, "Couldn't initialize rqueue "				 "and pages ret=%i", ret);			goto create_qp_exit3;		}	}	if (is_srq) {		my_qp->ib_srq.pd = &my_pd->ib_pd;		my_qp->ib_srq.device = my_pd->ib_pd.device;		my_qp->ib_srq.srq_context = init_attr->qp_context;		my_qp->ib_srq.event_handler = init_attr->event_handler;	} else {		my_qp->ib_qp.qp_num = ib_qp_num;		my_qp->ib_qp.pd = &my_pd->ib_pd;		my_qp->ib_qp.device = my_pd->ib_pd.device;		my_qp->ib_qp.recv_cq = init_attr->recv_cq;		my_qp->ib_qp.send_cq = init_attr->send_cq;		my_qp->ib_qp.qp_type = qp_type;		my_qp->ib_qp.srq = init_attr->srq;		my_qp->ib_qp.qp_context = init_attr->qp_context;		my_qp->ib_qp.event_handler = init_attr->event_handler;	}	init_attr->cap.max_inline_data = 0; /* not supported yet */	init_attr->cap.max_recv_sge = parms.rqueue.act_nr_sges;	init_attr->cap.max_recv_wr = parms.rqueue.act_nr_wqes;	init_attr->cap.max_send_sge = parms.squeue.act_nr_sges;	init_attr->cap.max_send_wr = parms.squeue.act_nr_wqes;	my_qp->init_attr = *init_attr;	/* NOTE: define_apq0() not supported yet */	if (qp_type == IB_QPT_GSI) {		h_ret = ehca_define_sqp(shca, my_qp, init_attr);		if (h_ret != H_SUCCESS) {			ret = ehca2ib_return_code(h_ret);			goto create_qp_exit4;		}	}	if (my_qp->send_cq) {		ret = ehca_cq_assign_qp(my_qp->send_cq, my_qp);		if (ret) {			ehca_err(pd->device,				 "Couldn't assign qp to send_cq ret=%i", ret);			goto create_qp_exit4;		}	}	/* copy queues, galpa data to user space */	if (context && udata) {		struct ehca_create_qp_resp resp;		memset(&resp, 0, sizeof(resp));		resp.qp_num = my_qp->real_qp_num;		resp.token = my_qp->token;		resp.qp_type = my_qp->qp_type;		resp.ext_type = my_qp->ext_type;		resp.qkey = my_qp->qkey;		resp.real_qp_num = my_qp->real_qp_num;		if (HAS_SQ(my_qp))			queue2resp(&resp.ipz_squeue, &my_qp->ipz_squeue);		if (HAS_RQ(my_qp))			queue2resp(&resp.ipz_rqueue, &my_qp->ipz_rqueue);		resp.fw_handle_ofs = (u32)			(my_qp->galpas.user.fw_handle & (PAGE_SIZE - 1));		if (ib_copy_to_udata(udata, &resp, sizeof resp)) {			ehca_err(pd->device, "Copy to udata failed");			ret = -EINVAL;			goto create_qp_exit4;		}	}	return my_qp;create_qp_exit4:	if (HAS_RQ(my_qp))		ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);create_qp_exit3:	if (HAS_SQ(my_qp))		ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);create_qp_exit2:	hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);create_qp_exit1:	write_lock_irqsave(&ehca_qp_idr_lock, flags);	idr_remove(&ehca_qp_idr, my_qp->token);	write_unlock_irqrestore(&ehca_qp_idr_lock, flags);create_qp_exit0:	kmem_cache_free(qp_cache, my_qp);	return ERR_PTR(ret);}struct ib_qp *ehca_create_qp(struct ib_pd *pd,			     struct ib_qp_init_attr *qp_init_attr,			     struct ib_udata *udata){	struct ehca_qp *ret;	ret = internal_create_qp(pd, qp_init_attr, NULL, udata, 0);	return IS_ERR(ret) ? (struct ib_qp *)ret : &ret->ib_qp;}static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,			       struct ib_uobject *uobject);struct ib_srq *ehca_create_srq(struct ib_pd *pd,			       struct ib_srq_init_attr *srq_init_attr,			       struct ib_udata *udata){	struct ib_qp_init_attr qp_init_attr;	struct ehca_qp *my_qp;	struct ib_srq *ret;	struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,					      ib_device);	struct hcp_modify_qp_control_block *mqpcb;	u64 hret, update_mask;	/* For common attributes, internal_create_qp() takes its info	 * out of qp_init_attr, so copy all common attrs there.	 */	memset(&qp_init_attr, 0, sizeof(qp_init_attr));	qp_init_attr.event_handler = srq_init_attr->event_handler;	qp_init_attr.qp_context = srq_init_attr->srq_context;	qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;	qp_init_attr.qp_type = IB_QPT_RC;	qp_init_attr.cap.max_recv_wr = srq_init_attr->attr.max_wr;	qp_init_attr.cap.max_recv_sge = srq_init_attr->attr.max_sge;	my_qp = internal_create_qp(pd, &qp_init_attr, srq_init_attr, udata, 1);	if (IS_ERR(my_qp))		return (struct ib_srq *)my_qp;	/* copy back return values */	srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr;	srq_init_attr->attr.max_sge = 3;	/* drive SRQ into RTR state */	mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);	if (!mqpcb) {		ehca_err(pd->device, "Could not get zeroed page for mqpcb "			 "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);		ret = ERR_PTR(-ENOMEM);		goto create_srq1;	}	mqpcb->qp_state = EHCA_QPS_INIT;	mqpcb->prim_phys_port = 1;	update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);	hret = hipz_h_modify_qp(shca->ipz_hca_handle,				my_qp->ipz_qp_handle,				&my_qp->pf,				update_mask,				mqpcb, my_qp->galpas.kernel);	if (hret != H_SUCCESS) {		ehca_err(pd->device, "Could not modify SRQ to INIT"			 "ehca_qp=%p qp_num=%x h_ret=%li",			 my_qp, my_qp->real_qp_num, hret);		goto create_srq2;	}	mqpcb->qp_enable = 1;	update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1);	hret = hipz_h_modify_qp(shca->ipz_hca_handle,				my_qp->ipz_qp_handle,				&my_qp->pf,				update_mask,				mqpcb, my_qp->galpas.kernel);	if (hret != H_SUCCESS) {		ehca_err(pd->device, "Could not enable SRQ"			 "ehca_qp=%p qp_num=%x h_ret=%li",			 my_qp, my_qp->real_qp_num, hret);		goto create_srq2;	}	mqpcb->qp_state  = EHCA_QPS_RTR;	update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);	hret = hipz_h_modify_qp(shca->ipz_hca_handle,				my_qp->ipz_qp_handle,				&my_qp->pf,				update_mask,				mqpcb, my_qp->galpas.kernel);	if (hret != H_SUCCESS) {		ehca_err(pd->device, "Could not modify SRQ to RTR"			 "ehca_qp=%p qp_num=%x h_ret=%li",			 my_qp, my_qp->real_qp_num, hret);		goto create_srq2;	}	ehca_free_fw_ctrlblock(mqpcb);	return &my_qp->ib_srq;create_srq2:	ret = ERR_PTR(ehca2ib_return_code(hret));	ehca_free_fw_ctrlblock(mqpcb);create_srq1:	internal_destroy_qp(pd->device, my_qp, my_qp->ib_srq.uobject);	return ret;}/* * prepare_sqe_rts called by internal_modify_qp() at trans sqe -> rts * set purge bit of bad wqe and subsequent wqes to avoid reentering sqe * returns total number of bad wqes in bad_wqe_cnt */static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,			   int *bad_wqe_cnt){	u64 h_ret;	struct ipz_queue *squeue;	void *bad_send_wqe_p, *bad_send_wqe_v;	u64 q_ofs;	struct ehca_wqe *wqe;	int qp_num = my_qp->ib_qp.qp_num;	/* get send wqe pointer */	h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle,					   my_qp->ipz_qp_handle, &my_qp->pf,					   &bad_send_wqe_p, NULL, 2);	if (h_ret != H_SUCCESS) {		ehca_err(&shca->ib_device, "hipz_h_disable_and_get_wqe() failed"			 " ehca_qp=%p qp_num=%x h_ret=%li",			 my_qp, qp_num, h_ret);		return ehca2ib_return_code(h_ret);	}	bad_send_wqe_p = (void *)((u64)bad_send_wqe_p & (~(1L << 63)));

⌨️ 快捷键说明

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