Path: blob/master/drivers/infiniband/hw/ehca/hcp_if.c
15112 views
/*1* IBM eServer eHCA Infiniband device driver for Linux on POWER2*3* Firmware Infiniband Interface code for POWER4*5* Authors: Christoph Raisch <[email protected]>6* Hoang-Nam Nguyen <[email protected]>7* Joachim Fenkes <[email protected]>8* Gerd Bayer <[email protected]>9* Waleri Fomin <[email protected]>10*11* Copyright (c) 2005 IBM Corporation12*13* All rights reserved.14*15* This source code is distributed under a dual license of GPL v2.0 and OpenIB16* BSD.17*18* OpenIB BSD License19*20* Redistribution and use in source and binary forms, with or without21* modification, are permitted provided that the following conditions are met:22*23* Redistributions of source code must retain the above copyright notice, this24* list of conditions and the following disclaimer.25*26* Redistributions in binary form must reproduce the above copyright notice,27* this list of conditions and the following disclaimer in the documentation28* and/or other materials29* provided with the distribution.30*31* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"32* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE33* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE34* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE35* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR36* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF37* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR38* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER39* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)40* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE41* POSSIBILITY OF SUCH DAMAGE.42*/4344#include <asm/hvcall.h>45#include "ehca_tools.h"46#include "hcp_if.h"47#include "hcp_phyp.h"48#include "hipz_fns.h"49#include "ipz_pt_fn.h"5051#define H_ALL_RES_QP_ENHANCED_OPS EHCA_BMASK_IBM(9, 11)52#define H_ALL_RES_QP_PTE_PIN EHCA_BMASK_IBM(12, 12)53#define H_ALL_RES_QP_SERVICE_TYPE EHCA_BMASK_IBM(13, 15)54#define H_ALL_RES_QP_STORAGE EHCA_BMASK_IBM(16, 17)55#define H_ALL_RES_QP_LL_RQ_CQE_POSTING EHCA_BMASK_IBM(18, 18)56#define H_ALL_RES_QP_LL_SQ_CQE_POSTING EHCA_BMASK_IBM(19, 21)57#define H_ALL_RES_QP_SIGNALING_TYPE EHCA_BMASK_IBM(22, 23)58#define H_ALL_RES_QP_UD_AV_LKEY_CTRL EHCA_BMASK_IBM(31, 31)59#define H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE EHCA_BMASK_IBM(32, 35)60#define H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE EHCA_BMASK_IBM(36, 39)61#define H_ALL_RES_QP_RESOURCE_TYPE EHCA_BMASK_IBM(56, 63)6263#define H_ALL_RES_QP_MAX_OUTST_SEND_WR EHCA_BMASK_IBM(0, 15)64#define H_ALL_RES_QP_MAX_OUTST_RECV_WR EHCA_BMASK_IBM(16, 31)65#define H_ALL_RES_QP_MAX_SEND_SGE EHCA_BMASK_IBM(32, 39)66#define H_ALL_RES_QP_MAX_RECV_SGE EHCA_BMASK_IBM(40, 47)6768#define H_ALL_RES_QP_UD_AV_LKEY EHCA_BMASK_IBM(32, 63)69#define H_ALL_RES_QP_SRQ_QP_TOKEN EHCA_BMASK_IBM(0, 31)70#define H_ALL_RES_QP_SRQ_QP_HANDLE EHCA_BMASK_IBM(0, 64)71#define H_ALL_RES_QP_SRQ_LIMIT EHCA_BMASK_IBM(48, 63)72#define H_ALL_RES_QP_SRQ_QPN EHCA_BMASK_IBM(40, 63)7374#define H_ALL_RES_QP_ACT_OUTST_SEND_WR EHCA_BMASK_IBM(16, 31)75#define H_ALL_RES_QP_ACT_OUTST_RECV_WR EHCA_BMASK_IBM(48, 63)76#define H_ALL_RES_QP_ACT_SEND_SGE EHCA_BMASK_IBM(8, 15)77#define H_ALL_RES_QP_ACT_RECV_SGE EHCA_BMASK_IBM(24, 31)7879#define H_ALL_RES_QP_SQUEUE_SIZE_PAGES EHCA_BMASK_IBM(0, 31)80#define H_ALL_RES_QP_RQUEUE_SIZE_PAGES EHCA_BMASK_IBM(32, 63)8182#define H_MP_INIT_TYPE EHCA_BMASK_IBM(44, 47)83#define H_MP_SHUTDOWN EHCA_BMASK_IBM(48, 48)84#define H_MP_RESET_QKEY_CTR EHCA_BMASK_IBM(49, 49)8586#define HCALL4_REGS_FORMAT "r4=%lx r5=%lx r6=%lx r7=%lx"87#define HCALL7_REGS_FORMAT HCALL4_REGS_FORMAT " r8=%lx r9=%lx r10=%lx"88#define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"8990static DEFINE_SPINLOCK(hcall_lock);9192static u32 get_longbusy_msecs(int longbusy_rc)93{94switch (longbusy_rc) {95case H_LONG_BUSY_ORDER_1_MSEC:96return 1;97case H_LONG_BUSY_ORDER_10_MSEC:98return 10;99case H_LONG_BUSY_ORDER_100_MSEC:100return 100;101case H_LONG_BUSY_ORDER_1_SEC:102return 1000;103case H_LONG_BUSY_ORDER_10_SEC:104return 10000;105case H_LONG_BUSY_ORDER_100_SEC:106return 100000;107default:108return 1;109}110}111112static long ehca_plpar_hcall_norets(unsigned long opcode,113unsigned long arg1,114unsigned long arg2,115unsigned long arg3,116unsigned long arg4,117unsigned long arg5,118unsigned long arg6,119unsigned long arg7)120{121long ret;122int i, sleep_msecs;123unsigned long flags = 0;124125if (unlikely(ehca_debug_level >= 2))126ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,127opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);128129for (i = 0; i < 5; i++) {130/* serialize hCalls to work around firmware issue */131if (ehca_lock_hcalls)132spin_lock_irqsave(&hcall_lock, flags);133134ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,135arg5, arg6, arg7);136137if (ehca_lock_hcalls)138spin_unlock_irqrestore(&hcall_lock, flags);139140if (H_IS_LONG_BUSY(ret)) {141sleep_msecs = get_longbusy_msecs(ret);142msleep_interruptible(sleep_msecs);143continue;144}145146if (ret < H_SUCCESS)147ehca_gen_err("opcode=%lx ret=%li " HCALL7_REGS_FORMAT,148opcode, ret, arg1, arg2, arg3,149arg4, arg5, arg6, arg7);150else151if (unlikely(ehca_debug_level >= 2))152ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);153154return ret;155}156157return H_BUSY;158}159160static long ehca_plpar_hcall9(unsigned long opcode,161unsigned long *outs, /* array of 9 outputs */162unsigned long arg1,163unsigned long arg2,164unsigned long arg3,165unsigned long arg4,166unsigned long arg5,167unsigned long arg6,168unsigned long arg7,169unsigned long arg8,170unsigned long arg9)171{172long ret;173int i, sleep_msecs;174unsigned long flags = 0;175176if (unlikely(ehca_debug_level >= 2))177ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,178arg1, arg2, arg3, arg4, arg5,179arg6, arg7, arg8, arg9);180181for (i = 0; i < 5; i++) {182/* serialize hCalls to work around firmware issue */183if (ehca_lock_hcalls)184spin_lock_irqsave(&hcall_lock, flags);185186ret = plpar_hcall9(opcode, outs,187arg1, arg2, arg3, arg4, arg5,188arg6, arg7, arg8, arg9);189190if (ehca_lock_hcalls)191spin_unlock_irqrestore(&hcall_lock, flags);192193if (H_IS_LONG_BUSY(ret)) {194sleep_msecs = get_longbusy_msecs(ret);195msleep_interruptible(sleep_msecs);196continue;197}198199if (ret < H_SUCCESS) {200ehca_gen_err("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT,201opcode, arg1, arg2, arg3, arg4, arg5,202arg6, arg7, arg8, arg9);203ehca_gen_err("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,204ret, outs[0], outs[1], outs[2], outs[3],205outs[4], outs[5], outs[6], outs[7],206outs[8]);207} else if (unlikely(ehca_debug_level >= 2))208ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,209ret, outs[0], outs[1], outs[2], outs[3],210outs[4], outs[5], outs[6], outs[7],211outs[8]);212return ret;213}214215return H_BUSY;216}217218u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,219struct ehca_pfeq *pfeq,220const u32 neq_control,221const u32 number_of_entries,222struct ipz_eq_handle *eq_handle,223u32 *act_nr_of_entries,224u32 *act_pages,225u32 *eq_ist)226{227u64 ret;228unsigned long outs[PLPAR_HCALL9_BUFSIZE];229u64 allocate_controls;230231/* resource type */232allocate_controls = 3ULL;233234/* ISN is associated */235if (neq_control != 1)236allocate_controls = (1ULL << (63 - 7)) | allocate_controls;237else /* notification event queue */238allocate_controls = (1ULL << 63) | allocate_controls;239240ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,241adapter_handle.handle, /* r4 */242allocate_controls, /* r5 */243number_of_entries, /* r6 */2440, 0, 0, 0, 0, 0);245eq_handle->handle = outs[0];246*act_nr_of_entries = (u32)outs[3];247*act_pages = (u32)outs[4];248*eq_ist = (u32)outs[5];249250if (ret == H_NOT_ENOUGH_RESOURCES)251ehca_gen_err("Not enough resource - ret=%lli ", ret);252253return ret;254}255256u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,257struct ipz_eq_handle eq_handle,258const u64 event_mask)259{260return ehca_plpar_hcall_norets(H_RESET_EVENTS,261adapter_handle.handle, /* r4 */262eq_handle.handle, /* r5 */263event_mask, /* r6 */2640, 0, 0, 0);265}266267u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,268struct ehca_cq *cq,269struct ehca_alloc_cq_parms *param)270{271int rc;272u64 ret;273unsigned long outs[PLPAR_HCALL9_BUFSIZE];274275ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,276adapter_handle.handle, /* r4 */2772, /* r5 */278param->eq_handle.handle, /* r6 */279cq->token, /* r7 */280param->nr_cqe, /* r8 */2810, 0, 0, 0);282cq->ipz_cq_handle.handle = outs[0];283param->act_nr_of_entries = (u32)outs[3];284param->act_pages = (u32)outs[4];285286if (ret == H_SUCCESS) {287rc = hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]);288if (rc) {289ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx",290rc, outs[5]);291292ehca_plpar_hcall_norets(H_FREE_RESOURCE,293adapter_handle.handle, /* r4 */294cq->ipz_cq_handle.handle, /* r5 */2950, 0, 0, 0, 0);296ret = H_NO_MEM;297}298}299300if (ret == H_NOT_ENOUGH_RESOURCES)301ehca_gen_err("Not enough resources. ret=%lli", ret);302303return ret;304}305306u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,307struct ehca_alloc_qp_parms *parms, int is_user)308{309int rc;310u64 ret;311u64 allocate_controls, max_r10_reg, r11, r12;312unsigned long outs[PLPAR_HCALL9_BUFSIZE];313314allocate_controls =315EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)316| EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)317| EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)318| EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)319| EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage)320| EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE,321parms->squeue.page_size)322| EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE,323parms->rqueue.page_size)324| EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,325!!(parms->ll_comp_flags & LLQP_RECV_COMP))326| EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,327!!(parms->ll_comp_flags & LLQP_SEND_COMP))328| EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,329parms->ud_av_l_key_ctl)330| EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);331332max_r10_reg =333EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,334parms->squeue.max_wr + 1)335| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,336parms->rqueue.max_wr + 1)337| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,338parms->squeue.max_sge)339| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,340parms->rqueue.max_sge);341342r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);343344if (parms->ext_type == EQPT_SRQ)345r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);346else347r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);348349ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,350adapter_handle.handle, /* r4 */351allocate_controls, /* r5 */352parms->send_cq_handle.handle,353parms->recv_cq_handle.handle,354parms->eq_handle.handle,355((u64)parms->token << 32) | parms->pd.value,356max_r10_reg, r11, r12);357358parms->qp_handle.handle = outs[0];359parms->real_qp_num = (u32)outs[1];360parms->squeue.act_nr_wqes =361(u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);362parms->rqueue.act_nr_wqes =363(u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);364parms->squeue.act_nr_sges =365(u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);366parms->rqueue.act_nr_sges =367(u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);368parms->squeue.queue_size =369(u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);370parms->rqueue.queue_size =371(u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);372373if (ret == H_SUCCESS) {374rc = hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]);375if (rc) {376ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx",377rc, outs[6]);378379ehca_plpar_hcall_norets(H_FREE_RESOURCE,380adapter_handle.handle, /* r4 */381parms->qp_handle.handle, /* r5 */3820, 0, 0, 0, 0);383ret = H_NO_MEM;384}385}386387if (ret == H_NOT_ENOUGH_RESOURCES)388ehca_gen_err("Not enough resources. ret=%lli", ret);389390return ret;391}392393u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,394const u8 port_id,395struct hipz_query_port *query_port_response_block)396{397u64 ret;398u64 r_cb = virt_to_abs(query_port_response_block);399400if (r_cb & (EHCA_PAGESIZE-1)) {401ehca_gen_err("response block not page aligned");402return H_PARAMETER;403}404405ret = ehca_plpar_hcall_norets(H_QUERY_PORT,406adapter_handle.handle, /* r4 */407port_id, /* r5 */408r_cb, /* r6 */4090, 0, 0, 0);410411if (ehca_debug_level >= 2)412ehca_dmp(query_port_response_block, 64, "response_block");413414return ret;415}416417u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,418const u8 port_id, const u32 port_cap,419const u8 init_type, const int modify_mask)420{421u64 port_attributes = port_cap;422423if (modify_mask & IB_PORT_SHUTDOWN)424port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);425if (modify_mask & IB_PORT_INIT_TYPE)426port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);427if (modify_mask & IB_PORT_RESET_QKEY_CNTR)428port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);429430return ehca_plpar_hcall_norets(H_MODIFY_PORT,431adapter_handle.handle, /* r4 */432port_id, /* r5 */433port_attributes, /* r6 */4340, 0, 0, 0);435}436437u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,438struct hipz_query_hca *query_hca_rblock)439{440u64 r_cb = virt_to_abs(query_hca_rblock);441442if (r_cb & (EHCA_PAGESIZE-1)) {443ehca_gen_err("response_block=%p not page aligned",444query_hca_rblock);445return H_PARAMETER;446}447448return ehca_plpar_hcall_norets(H_QUERY_HCA,449adapter_handle.handle, /* r4 */450r_cb, /* r5 */4510, 0, 0, 0, 0);452}453454u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,455const u8 pagesize,456const u8 queue_type,457const u64 resource_handle,458const u64 logical_address_of_page,459u64 count)460{461return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,462adapter_handle.handle, /* r4 */463(u64)queue_type | ((u64)pagesize) << 8,464/* r5 */465resource_handle, /* r6 */466logical_address_of_page, /* r7 */467count, /* r8 */4680, 0);469}470471u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,472const struct ipz_eq_handle eq_handle,473struct ehca_pfeq *pfeq,474const u8 pagesize,475const u8 queue_type,476const u64 logical_address_of_page,477const u64 count)478{479if (count != 1) {480ehca_gen_err("Ppage counter=%llx", count);481return H_PARAMETER;482}483return hipz_h_register_rpage(adapter_handle,484pagesize,485queue_type,486eq_handle.handle,487logical_address_of_page, count);488}489490u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,491u32 ist)492{493u64 ret;494ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,495adapter_handle.handle, /* r4 */496ist, /* r5 */4970, 0, 0, 0, 0);498499if (ret != H_SUCCESS && ret != H_BUSY)500ehca_gen_err("Could not query interrupt state.");501502return ret;503}504505u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,506const struct ipz_cq_handle cq_handle,507struct ehca_pfcq *pfcq,508const u8 pagesize,509const u8 queue_type,510const u64 logical_address_of_page,511const u64 count,512const struct h_galpa gal)513{514if (count != 1) {515ehca_gen_err("Page counter=%llx", count);516return H_PARAMETER;517}518519return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,520cq_handle.handle, logical_address_of_page,521count);522}523524u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,525const struct ipz_qp_handle qp_handle,526struct ehca_pfqp *pfqp,527const u8 pagesize,528const u8 queue_type,529const u64 logical_address_of_page,530const u64 count,531const struct h_galpa galpa)532{533if (count > 1) {534ehca_gen_err("Page counter=%llx", count);535return H_PARAMETER;536}537538return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,539qp_handle.handle, logical_address_of_page,540count);541}542543u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,544const struct ipz_qp_handle qp_handle,545struct ehca_pfqp *pfqp,546void **log_addr_next_sq_wqe2processed,547void **log_addr_next_rq_wqe2processed,548int dis_and_get_function_code)549{550u64 ret;551unsigned long outs[PLPAR_HCALL9_BUFSIZE];552553ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,554adapter_handle.handle, /* r4 */555dis_and_get_function_code, /* r5 */556qp_handle.handle, /* r6 */5570, 0, 0, 0, 0, 0);558if (log_addr_next_sq_wqe2processed)559*log_addr_next_sq_wqe2processed = (void *)outs[0];560if (log_addr_next_rq_wqe2processed)561*log_addr_next_rq_wqe2processed = (void *)outs[1];562563return ret;564}565566u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,567const struct ipz_qp_handle qp_handle,568struct ehca_pfqp *pfqp,569const u64 update_mask,570struct hcp_modify_qp_control_block *mqpcb,571struct h_galpa gal)572{573u64 ret;574unsigned long outs[PLPAR_HCALL9_BUFSIZE];575ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,576adapter_handle.handle, /* r4 */577qp_handle.handle, /* r5 */578update_mask, /* r6 */579virt_to_abs(mqpcb), /* r7 */5800, 0, 0, 0, 0);581582if (ret == H_NOT_ENOUGH_RESOURCES)583ehca_gen_err("Insufficient resources ret=%lli", ret);584585return ret;586}587588u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,589const struct ipz_qp_handle qp_handle,590struct ehca_pfqp *pfqp,591struct hcp_modify_qp_control_block *qqpcb,592struct h_galpa gal)593{594return ehca_plpar_hcall_norets(H_QUERY_QP,595adapter_handle.handle, /* r4 */596qp_handle.handle, /* r5 */597virt_to_abs(qqpcb), /* r6 */5980, 0, 0, 0);599}600601u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,602struct ehca_qp *qp)603{604u64 ret;605unsigned long outs[PLPAR_HCALL9_BUFSIZE];606607ret = hcp_galpas_dtor(&qp->galpas);608if (ret) {609ehca_gen_err("Could not destruct qp->galpas");610return H_RESOURCE;611}612ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,613adapter_handle.handle, /* r4 */614/* function code */6151, /* r5 */616qp->ipz_qp_handle.handle, /* r6 */6170, 0, 0, 0, 0, 0);618if (ret == H_HARDWARE)619ehca_gen_err("HCA not operational. ret=%lli", ret);620621ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,622adapter_handle.handle, /* r4 */623qp->ipz_qp_handle.handle, /* r5 */6240, 0, 0, 0, 0);625626if (ret == H_RESOURCE)627ehca_gen_err("Resource still in use. ret=%lli", ret);628629return ret;630}631632u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,633const struct ipz_qp_handle qp_handle,634struct h_galpa gal,635u32 port)636{637return ehca_plpar_hcall_norets(H_DEFINE_AQP0,638adapter_handle.handle, /* r4 */639qp_handle.handle, /* r5 */640port, /* r6 */6410, 0, 0, 0);642}643644u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,645const struct ipz_qp_handle qp_handle,646struct h_galpa gal,647u32 port, u32 * pma_qp_nr,648u32 * bma_qp_nr)649{650u64 ret;651unsigned long outs[PLPAR_HCALL9_BUFSIZE];652653ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,654adapter_handle.handle, /* r4 */655qp_handle.handle, /* r5 */656port, /* r6 */6570, 0, 0, 0, 0, 0);658*pma_qp_nr = (u32)outs[0];659*bma_qp_nr = (u32)outs[1];660661if (ret == H_ALIAS_EXIST)662ehca_gen_err("AQP1 already exists. ret=%lli", ret);663664return ret;665}666667u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,668const struct ipz_qp_handle qp_handle,669struct h_galpa gal,670u16 mcg_dlid,671u64 subnet_prefix, u64 interface_id)672{673u64 ret;674675ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,676adapter_handle.handle, /* r4 */677qp_handle.handle, /* r5 */678mcg_dlid, /* r6 */679interface_id, /* r7 */680subnet_prefix, /* r8 */6810, 0);682683if (ret == H_NOT_ENOUGH_RESOURCES)684ehca_gen_err("Not enough resources. ret=%lli", ret);685686return ret;687}688689u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,690const struct ipz_qp_handle qp_handle,691struct h_galpa gal,692u16 mcg_dlid,693u64 subnet_prefix, u64 interface_id)694{695return ehca_plpar_hcall_norets(H_DETACH_MCQP,696adapter_handle.handle, /* r4 */697qp_handle.handle, /* r5 */698mcg_dlid, /* r6 */699interface_id, /* r7 */700subnet_prefix, /* r8 */7010, 0);702}703704u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,705struct ehca_cq *cq,706u8 force_flag)707{708u64 ret;709710ret = hcp_galpas_dtor(&cq->galpas);711if (ret) {712ehca_gen_err("Could not destruct cp->galpas");713return H_RESOURCE;714}715716ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,717adapter_handle.handle, /* r4 */718cq->ipz_cq_handle.handle, /* r5 */719force_flag != 0 ? 1L : 0L, /* r6 */7200, 0, 0, 0);721722if (ret == H_RESOURCE)723ehca_gen_err("H_FREE_RESOURCE failed ret=%lli ", ret);724725return ret;726}727728u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,729struct ehca_eq *eq)730{731u64 ret;732733ret = hcp_galpas_dtor(&eq->galpas);734if (ret) {735ehca_gen_err("Could not destruct eq->galpas");736return H_RESOURCE;737}738739ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,740adapter_handle.handle, /* r4 */741eq->ipz_eq_handle.handle, /* r5 */7420, 0, 0, 0, 0);743744if (ret == H_RESOURCE)745ehca_gen_err("Resource in use. ret=%lli ", ret);746747return ret;748}749750u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,751const struct ehca_mr *mr,752const u64 vaddr,753const u64 length,754const u32 access_ctrl,755const struct ipz_pd pd,756struct ehca_mr_hipzout_parms *outparms)757{758u64 ret;759unsigned long outs[PLPAR_HCALL9_BUFSIZE];760761ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,762adapter_handle.handle, /* r4 */7635, /* r5 */764vaddr, /* r6 */765length, /* r7 */766(((u64)access_ctrl) << 32ULL), /* r8 */767pd.value, /* r9 */7680, 0, 0);769outparms->handle.handle = outs[0];770outparms->lkey = (u32)outs[2];771outparms->rkey = (u32)outs[3];772773return ret;774}775776u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,777const struct ehca_mr *mr,778const u8 pagesize,779const u8 queue_type,780const u64 logical_address_of_page,781const u64 count)782{783u64 ret;784785if (unlikely(ehca_debug_level >= 3)) {786if (count > 1) {787u64 *kpage;788int i;789kpage = (u64 *)abs_to_virt(logical_address_of_page);790for (i = 0; i < count; i++)791ehca_gen_dbg("kpage[%d]=%p",792i, (void *)kpage[i]);793} else794ehca_gen_dbg("kpage=%p",795(void *)logical_address_of_page);796}797798if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {799ehca_gen_err("logical_address_of_page not on a 4k boundary "800"adapter_handle=%llx mr=%p mr_handle=%llx "801"pagesize=%x queue_type=%x "802"logical_address_of_page=%llx count=%llx",803adapter_handle.handle, mr,804mr->ipz_mr_handle.handle, pagesize, queue_type,805logical_address_of_page, count);806ret = H_PARAMETER;807} else808ret = hipz_h_register_rpage(adapter_handle, pagesize,809queue_type,810mr->ipz_mr_handle.handle,811logical_address_of_page, count);812return ret;813}814815u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,816const struct ehca_mr *mr,817struct ehca_mr_hipzout_parms *outparms)818{819u64 ret;820unsigned long outs[PLPAR_HCALL9_BUFSIZE];821822ret = ehca_plpar_hcall9(H_QUERY_MR, outs,823adapter_handle.handle, /* r4 */824mr->ipz_mr_handle.handle, /* r5 */8250, 0, 0, 0, 0, 0, 0);826outparms->len = outs[0];827outparms->vaddr = outs[1];828outparms->acl = outs[4] >> 32;829outparms->lkey = (u32)(outs[5] >> 32);830outparms->rkey = (u32)(outs[5] & (0xffffffff));831832return ret;833}834835u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,836const struct ehca_mr *mr)837{838return ehca_plpar_hcall_norets(H_FREE_RESOURCE,839adapter_handle.handle, /* r4 */840mr->ipz_mr_handle.handle, /* r5 */8410, 0, 0, 0, 0);842}843844u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,845const struct ehca_mr *mr,846const u64 vaddr_in,847const u64 length,848const u32 access_ctrl,849const struct ipz_pd pd,850const u64 mr_addr_cb,851struct ehca_mr_hipzout_parms *outparms)852{853u64 ret;854unsigned long outs[PLPAR_HCALL9_BUFSIZE];855856ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,857adapter_handle.handle, /* r4 */858mr->ipz_mr_handle.handle, /* r5 */859vaddr_in, /* r6 */860length, /* r7 */861/* r8 */862((((u64)access_ctrl) << 32ULL) | pd.value),863mr_addr_cb, /* r9 */8640, 0, 0);865outparms->vaddr = outs[1];866outparms->lkey = (u32)outs[2];867outparms->rkey = (u32)outs[3];868869return ret;870}871872u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,873const struct ehca_mr *mr,874const struct ehca_mr *orig_mr,875const u64 vaddr_in,876const u32 access_ctrl,877const struct ipz_pd pd,878struct ehca_mr_hipzout_parms *outparms)879{880u64 ret;881unsigned long outs[PLPAR_HCALL9_BUFSIZE];882883ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,884adapter_handle.handle, /* r4 */885orig_mr->ipz_mr_handle.handle, /* r5 */886vaddr_in, /* r6 */887(((u64)access_ctrl) << 32ULL), /* r7 */888pd.value, /* r8 */8890, 0, 0, 0);890outparms->handle.handle = outs[0];891outparms->lkey = (u32)outs[2];892outparms->rkey = (u32)outs[3];893894return ret;895}896897u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,898const struct ehca_mw *mw,899const struct ipz_pd pd,900struct ehca_mw_hipzout_parms *outparms)901{902u64 ret;903unsigned long outs[PLPAR_HCALL9_BUFSIZE];904905ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,906adapter_handle.handle, /* r4 */9076, /* r5 */908pd.value, /* r6 */9090, 0, 0, 0, 0, 0);910outparms->handle.handle = outs[0];911outparms->rkey = (u32)outs[3];912913return ret;914}915916u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,917const struct ehca_mw *mw,918struct ehca_mw_hipzout_parms *outparms)919{920u64 ret;921unsigned long outs[PLPAR_HCALL9_BUFSIZE];922923ret = ehca_plpar_hcall9(H_QUERY_MW, outs,924adapter_handle.handle, /* r4 */925mw->ipz_mw_handle.handle, /* r5 */9260, 0, 0, 0, 0, 0, 0);927outparms->rkey = (u32)outs[3];928929return ret;930}931932u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,933const struct ehca_mw *mw)934{935return ehca_plpar_hcall_norets(H_FREE_RESOURCE,936adapter_handle.handle, /* r4 */937mw->ipz_mw_handle.handle, /* r5 */9380, 0, 0, 0, 0);939}940941u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,942const u64 ressource_handle,943void *rblock,944unsigned long *byte_count)945{946u64 r_cb = virt_to_abs(rblock);947948if (r_cb & (EHCA_PAGESIZE-1)) {949ehca_gen_err("rblock not page aligned.");950return H_PARAMETER;951}952953return ehca_plpar_hcall_norets(H_ERROR_DATA,954adapter_handle.handle,955ressource_handle,956r_cb,9570, 0, 0, 0);958}959960u64 hipz_h_eoi(int irq)961{962unsigned long xirr;963964iosync();965xirr = (0xffULL << 24) | irq;966967return plpar_hcall_norets(H_EOI, xirr);968}969970971