/** * allocates memory for a queue and registers pages in phyp */ int ehea_qp_alloc_register(struct ehea_qp *qp, struct hw_queue *hw_queue, int nr_pages, int wqe_size, int act_nr_sges, struct ehea_adapter *adapter, int h_call_q_selector) { u64 hret, rpage; int ret, cnt; void *vpage; ret = hw_queue_ctor(hw_queue, nr_pages, EHEA_PAGESIZE, wqe_size); if (ret) return ret; for (cnt = 0; cnt < nr_pages; cnt++) { vpage = hw_qpageit_get_inc(hw_queue); if (!vpage) { ehea_error("hw_qpageit_get_inc failed"); goto out_kill_hwq; } rpage = virt_to_abs(vpage); hret = ehea_h_register_rpage(adapter->handle, 0, h_call_q_selector, qp->fw_handle, rpage, 1); if (hret < H_SUCCESS) { ehea_error("register_rpage_qp failed"); goto out_kill_hwq; } } hw_qeit_reset(hw_queue); return 0; out_kill_hwq: hw_queue_dtor(hw_queue); return -EIO; }
u64 ehea_h_register_rpage_mr(const u64 adapter_handle, const u64 mr_handle, const u8 pagesize, const u8 queue_type, const u64 log_pageaddr, const u64 count) { if ((count > 1) && (log_pageaddr & ~PAGE_MASK)) { pr_err("not on pageboundary\n"); return H_PARAMETER; } return ehea_h_register_rpage(adapter_handle, pagesize, queue_type, mr_handle, log_pageaddr, count); }
struct ehea_eq *ehea_create_eq(struct ehea_adapter *adapter, const enum ehea_eq_type type, const u32 max_nr_of_eqes, const u8 eqe_gen) { int ret, i; u64 hret, rpage; void *vpage; struct ehea_eq *eq; eq = kzalloc(sizeof(*eq), GFP_KERNEL); if (!eq) { ehea_error("no mem for eq"); return NULL; } eq->adapter = adapter; eq->attr.type = type; eq->attr.max_nr_of_eqes = max_nr_of_eqes; eq->attr.eqe_gen = eqe_gen; spin_lock_init(&eq->spinlock); hret = ehea_h_alloc_resource_eq(adapter->handle, &eq->attr, &eq->fw_handle); if (hret != H_SUCCESS) { ehea_error("alloc_resource_eq failed"); goto out_freemem; } ret = hw_queue_ctor(&eq->hw_queue, eq->attr.nr_pages, EHEA_PAGESIZE, sizeof(struct ehea_eqe)); if (ret) { ehea_error("can't allocate eq pages"); goto out_freeres; } for (i = 0; i < eq->attr.nr_pages; i++) { vpage = hw_qpageit_get_inc(&eq->hw_queue); if (!vpage) { ehea_error("hw_qpageit_get_inc failed"); hret = H_RESOURCE; goto out_kill_hwq; } rpage = virt_to_abs(vpage); hret = ehea_h_register_rpage(adapter->handle, 0, EHEA_EQ_REGISTER_ORIG, eq->fw_handle, rpage, 1); if (i == (eq->attr.nr_pages - 1)) { /* last page */ vpage = hw_qpageit_get_inc(&eq->hw_queue); if ((hret != H_SUCCESS) || (vpage)) { goto out_kill_hwq; } } else { if ((hret != H_PAGE_REGISTERED) || (!vpage)) { goto out_kill_hwq; } } } hw_qeit_reset(&eq->hw_queue); return eq; out_kill_hwq: hw_queue_dtor(&eq->hw_queue); out_freeres: ehea_h_free_resource(adapter->handle, eq->fw_handle, FORCE_FREE); out_freemem: kfree(eq); return NULL; }
struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter, int nr_of_cqe, u64 eq_handle, u32 cq_token) { struct ehea_cq *cq; struct h_epa epa; u64 *cq_handle_ref, hret, rpage; u32 act_nr_of_entries, act_pages, counter; int ret; void *vpage; cq = kzalloc(sizeof(*cq), GFP_KERNEL); if (!cq) { ehea_error("no mem for cq"); goto out_nomem; } cq->attr.max_nr_of_cqes = nr_of_cqe; cq->attr.cq_token = cq_token; cq->attr.eq_handle = eq_handle; cq->adapter = adapter; cq_handle_ref = &cq->fw_handle; act_nr_of_entries = 0; act_pages = 0; hret = ehea_h_alloc_resource_cq(adapter->handle, &cq->attr, &cq->fw_handle, &cq->epas); if (hret != H_SUCCESS) { ehea_error("alloc_resource_cq failed"); goto out_freemem; } ret = hw_queue_ctor(&cq->hw_queue, cq->attr.nr_pages, EHEA_PAGESIZE, sizeof(struct ehea_cqe)); if (ret) goto out_freeres; for (counter = 0; counter < cq->attr.nr_pages; counter++) { vpage = hw_qpageit_get_inc(&cq->hw_queue); if (!vpage) { ehea_error("hw_qpageit_get_inc failed"); goto out_kill_hwq; } rpage = virt_to_abs(vpage); hret = ehea_h_register_rpage(adapter->handle, 0, EHEA_CQ_REGISTER_ORIG, cq->fw_handle, rpage, 1); if (hret < H_SUCCESS) { ehea_error("register_rpage_cq failed ehea_cq=%p " "hret=%lx counter=%i act_pages=%i", cq, hret, counter, cq->attr.nr_pages); goto out_kill_hwq; } if (counter == (cq->attr.nr_pages - 1)) { vpage = hw_qpageit_get_inc(&cq->hw_queue); if ((hret != H_SUCCESS) || (vpage)) { ehea_error("registration of pages not " "complete hret=%lx\n", hret); goto out_kill_hwq; } } else { if ((hret != H_PAGE_REGISTERED) || (!vpage)) { ehea_error("CQ: registration of page failed " "hret=%lx\n", hret); goto out_kill_hwq; } } } hw_qeit_reset(&cq->hw_queue); epa = cq->epas.kernel; ehea_reset_cq_ep(cq); ehea_reset_cq_n1(cq); return cq; out_kill_hwq: hw_queue_dtor(&cq->hw_queue); out_freeres: ehea_h_free_resource(adapter->handle, cq->fw_handle, FORCE_FREE); out_freemem: kfree(cq); out_nomem: return NULL; }