u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, struct ehca_cq *cq, struct ehca_alloc_cq_parms *param) { u64 ret; u64 outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, adapter_handle.handle, /* r4 */ 2, /* r5 */ param->eq_handle.handle, /* r6 */ cq->token, /* r7 */ param->nr_cqe, /* r8 */ 0, 0, 0, 0); cq->ipz_cq_handle.handle = outs[0]; param->act_nr_of_entries = (u32)outs[3]; param->act_pages = (u32)outs[4]; if (ret == H_SUCCESS) hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]); if (ret == H_NOT_ENOUGH_RESOURCES) ehca_gen_err("Not enough resources. ret=%lx", ret); return ret; }
u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, const struct ehca_mr *mr, const u64 vaddr_in, const u64 length, const u32 access_ctrl, const struct ipz_pd pd, const u64 mr_addr_cb, struct ehca_mr_hipzout_parms *outparms) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs, adapter_handle.handle, mr->ipz_mr_handle.handle, vaddr_in, length, ((((u64)access_ctrl) << 32ULL) | pd.value), mr_addr_cb, 0, 0, 0); outparms->vaddr = outs[1]; outparms->lkey = (u32)outs[2]; outparms->rkey = (u32)outs[3]; return ret; }
u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle, const struct ehca_mr *mr, const u64 vaddr, const u64 length, const u32 access_ctrl, const struct ipz_pd pd, struct ehca_mr_hipzout_parms *outparms) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, adapter_handle.handle, 5, vaddr, length, (((u64)access_ctrl) << 32ULL), pd.value, 0, 0, 0); outparms->handle.handle = outs[0]; outparms->lkey = (u32)outs[2]; outparms->rkey = (u32)outs[3]; return ret; }
u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle, struct ehca_qp *qp) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = hcp_galpas_dtor(&qp->galpas); if (ret) { ehca_gen_err("Could not destruct qp->galpas"); return H_RESOURCE; } ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs, adapter_handle.handle, 1, qp->ipz_qp_handle.handle, 0, 0, 0, 0, 0, 0); if (ret == H_HARDWARE) ehca_gen_err("HCA not operational. ret=%lli", ret); ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE, adapter_handle.handle, qp->ipz_qp_handle.handle, 0, 0, 0, 0, 0); if (ret == H_RESOURCE) ehca_gen_err("Resource still in use. ret=%lli", ret); return ret; }
u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle, const struct ehca_mw *mw, struct ehca_mw_hipzout_parms *outparms) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_QUERY_MW, outs, adapter_handle.handle, mw->ipz_mw_handle.handle, 0, 0, 0, 0, 0, 0, 0); outparms->rkey = (u32)outs[3]; return ret; }
u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle, const struct ehca_mw *mw, const struct ipz_pd pd, struct ehca_mw_hipzout_parms *outparms) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, adapter_handle.handle, 6, pd.value, 0, 0, 0, 0, 0, 0); outparms->handle.handle = outs[0]; outparms->rkey = (u32)outs[3]; return ret; }
u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle, const struct ehca_mr *mr, struct ehca_mr_hipzout_parms *outparms) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_QUERY_MR, outs, adapter_handle.handle, mr->ipz_mr_handle.handle, 0, 0, 0, 0, 0, 0, 0); outparms->len = outs[0]; outparms->vaddr = outs[1]; outparms->acl = outs[4] >> 32; outparms->lkey = (u32)(outs[5] >> 32); outparms->rkey = (u32)(outs[5] & (0xffffffff)); return ret; }
u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle, const struct ipz_qp_handle qp_handle, struct ehca_pfqp *pfqp, const u64 update_mask, struct hcp_modify_qp_control_block *mqpcb, struct h_galpa gal) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_MODIFY_QP, outs, adapter_handle.handle, qp_handle.handle, update_mask, virt_to_abs(mqpcb), 0, 0, 0, 0, 0); if (ret == H_NOT_ENOUGH_RESOURCES) ehca_gen_err("Insufficient resources ret=%lli", ret); return ret; }
u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle, const struct ipz_qp_handle qp_handle, struct h_galpa gal, u32 port, u32 * pma_qp_nr, u32 * bma_qp_nr) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs, adapter_handle.handle, qp_handle.handle, port, 0, 0, 0, 0, 0, 0); *pma_qp_nr = (u32)outs[0]; *bma_qp_nr = (u32)outs[1]; if (ret == H_ALIAS_EXIST) ehca_gen_err("AQP1 already exists. ret=%lli", ret); return ret; }
u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle, const struct ipz_qp_handle qp_handle, struct ehca_pfqp *pfqp, void **log_addr_next_sq_wqe2processed, void **log_addr_next_rq_wqe2processed, int dis_and_get_function_code) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs, adapter_handle.handle, dis_and_get_function_code, qp_handle.handle, 0, 0, 0, 0, 0, 0); if (log_addr_next_sq_wqe2processed) *log_addr_next_sq_wqe2processed = (void *)outs[0]; if (log_addr_next_rq_wqe2processed) *log_addr_next_rq_wqe2processed = (void *)outs[1]; return ret; }
u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, struct ehca_cq *cq, struct ehca_alloc_cq_parms *param) { int rc; u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, adapter_handle.handle, 2, param->eq_handle.handle, cq->token, param->nr_cqe, 0, 0, 0, 0); cq->ipz_cq_handle.handle = outs[0]; param->act_nr_of_entries = (u32)outs[3]; param->act_pages = (u32)outs[4]; if (ret == H_SUCCESS) { rc = hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]); if (rc) { ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx", rc, outs[5]); ehca_plpar_hcall_norets(H_FREE_RESOURCE, adapter_handle.handle, cq->ipz_cq_handle.handle, 0, 0, 0, 0, 0); ret = H_NO_MEM; } } if (ret == H_NOT_ENOUGH_RESOURCES) ehca_gen_err("Not enough resources. ret=%lli", ret); return ret; }
u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle, struct ehca_pfeq *pfeq, const u32 neq_control, const u32 number_of_entries, struct ipz_eq_handle *eq_handle, u32 *act_nr_of_entries, u32 *act_pages, u32 *eq_ist) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; u64 allocate_controls; allocate_controls = 3ULL; if (neq_control != 1) allocate_controls = (1ULL << (63 - 7)) | allocate_controls; else allocate_controls = (1ULL << 63) | allocate_controls; ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, adapter_handle.handle, allocate_controls, number_of_entries, 0, 0, 0, 0, 0, 0); eq_handle->handle = outs[0]; *act_nr_of_entries = (u32)outs[3]; *act_pages = (u32)outs[4]; *eq_ist = (u32)outs[5]; if (ret == H_NOT_ENOUGH_RESOURCES) ehca_gen_err("Not enough resource - ret=%lli ", ret); return ret; }
u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle, struct ehca_pfeq *pfeq, const u32 neq_control, const u32 number_of_entries, struct ipz_eq_handle *eq_handle, u32 *act_nr_of_entries, u32 *act_pages, u32 *eq_ist) { u64 ret; u64 outs[PLPAR_HCALL9_BUFSIZE]; u64 allocate_controls; /* resource type */ allocate_controls = 3ULL; /* ISN is associated */ if (neq_control != 1) allocate_controls = (1ULL << (63 - 7)) | allocate_controls; else /* notification event queue */ allocate_controls = (1ULL << 63) | allocate_controls; ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, adapter_handle.handle, /* r4 */ allocate_controls, /* r5 */ number_of_entries, /* r6 */ 0, 0, 0, 0, 0, 0); eq_handle->handle = outs[0]; *act_nr_of_entries = (u32)outs[3]; *act_pages = (u32)outs[4]; *eq_ist = (u32)outs[5]; if (ret == H_NOT_ENOUGH_RESOURCES) ehca_gen_err("Not enough resource - ret=%lx ", ret); return ret; }
u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle, const struct ehca_mr *mr, const struct ehca_mr *orig_mr, const u64 vaddr_in, const u32 access_ctrl, const struct ipz_pd pd, struct ehca_mr_hipzout_parms *outparms) { u64 ret; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs, adapter_handle.handle, orig_mr->ipz_mr_handle.handle, vaddr_in, (((u64)access_ctrl) << 32ULL), pd.value, 0, 0, 0, 0); outparms->handle.handle = outs[0]; outparms->lkey = (u32)outs[2]; outparms->rkey = (u32)outs[3]; return ret; }
u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, struct ehca_alloc_qp_parms *parms, int is_user) { int rc; u64 ret; u64 allocate_controls, max_r10_reg, r11, r12; unsigned long outs[PLPAR_HCALL9_BUFSIZE]; allocate_controls = EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type) | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0) | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype) | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype) | EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage) | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE, parms->squeue.page_size) | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE, parms->rqueue.page_size) | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING, !!(parms->ll_comp_flags & LLQP_RECV_COMP)) | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING, !!(parms->ll_comp_flags & LLQP_SEND_COMP)) | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL, parms->ud_av_l_key_ctl) | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1); max_r10_reg = EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR, parms->squeue.max_wr + 1) | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR, parms->rqueue.max_wr + 1) | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE, parms->squeue.max_sge) | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE, parms->rqueue.max_sge); r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token); if (parms->ext_type == EQPT_SRQ) r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit); else r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn); ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, adapter_handle.handle, allocate_controls, parms->send_cq_handle.handle, parms->recv_cq_handle.handle, parms->eq_handle.handle, ((u64)parms->token << 32) | parms->pd.value, max_r10_reg, r11, r12); parms->qp_handle.handle = outs[0]; parms->real_qp_num = (u32)outs[1]; parms->squeue.act_nr_wqes = (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]); parms->rqueue.act_nr_wqes = (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]); parms->squeue.act_nr_sges = (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]); parms->rqueue.act_nr_sges = (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]); parms->squeue.queue_size = (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]); parms->rqueue.queue_size = (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]); if (ret == H_SUCCESS) { rc = hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]); if (rc) { ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx", rc, outs[6]); ehca_plpar_hcall_norets(H_FREE_RESOURCE, adapter_handle.handle, parms->qp_handle.handle, 0, 0, 0, 0, 0); ret = H_NO_MEM; } } if (ret == H_NOT_ENOUGH_RESOURCES) ehca_gen_err("Not enough resources. ret=%lli", ret); return ret; }
u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, struct ehca_qp *qp, struct ehca_alloc_qp_parms *parms) { u64 ret; u64 allocate_controls; u64 max_r10_reg; u64 outs[PLPAR_HCALL9_BUFSIZE]; u16 max_nr_receive_wqes = qp->init_attr.cap.max_recv_wr + 1; u16 max_nr_send_wqes = qp->init_attr.cap.max_send_wr + 1; int daqp_ctrl = parms->daqp_ctrl; allocate_controls = EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, (daqp_ctrl & DAQP_CTRL_ENABLE) ? 1 : 0) | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0) | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype) | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype) | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING, (daqp_ctrl & DAQP_CTRL_RECV_COMP) ? 1 : 0) | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING, (daqp_ctrl & DAQP_CTRL_SEND_COMP) ? 1 : 0) | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL, parms->ud_av_l_key_ctl) | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1); max_r10_reg = EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR, max_nr_send_wqes) | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR, max_nr_receive_wqes) | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE, parms->max_send_sge) | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE, parms->max_recv_sge); ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, adapter_handle.handle, /* r4 */ allocate_controls, /* r5 */ qp->send_cq->ipz_cq_handle.handle, qp->recv_cq->ipz_cq_handle.handle, parms->ipz_eq_handle.handle, ((u64)qp->token << 32) | parms->pd.value, max_r10_reg, /* r10 */ parms->ud_av_l_key_ctl, /* r11 */ 0); qp->ipz_qp_handle.handle = outs[0]; qp->real_qp_num = (u32)outs[1]; parms->act_nr_send_wqes = (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]); parms->act_nr_recv_wqes = (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]); parms->act_nr_send_sges = (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]); parms->act_nr_recv_sges = (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]); parms->nr_sq_pages = (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]); parms->nr_rq_pages = (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]); if (ret == H_SUCCESS) hcp_galpas_ctor(&qp->galpas, outs[6], outs[6]); if (ret == H_NOT_ENOUGH_RESOURCES) ehca_gen_err("Not enough resources. ret=%lx", ret); return ret; }