📄 ehca_qp.c
字号:
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 + -