2006-09-22 15:22:22 -07:00
/*
* IBM eServer eHCA Infiniband device driver for Linux on POWER
*
* Firmware Infiniband Interface code for POWER
*
* Authors : Christoph Raisch < raisch @ de . ibm . com >
* Hoang - Nam Nguyen < hnguyen @ de . ibm . com >
2007-07-09 15:25:10 +02:00
* Joachim Fenkes < fenkes @ de . ibm . com >
2006-09-22 15:22:22 -07:00
* Gerd Bayer < gerd . bayer @ de . ibm . com >
* Waleri Fomin < fomin @ de . ibm . com >
*
* Copyright ( c ) 2005 IBM Corporation
*
* All rights reserved .
*
* This source code is distributed under a dual license of GPL v2 .0 and OpenIB
* BSD .
*
* OpenIB BSD License
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
*
* Redistributions of source code must retain the above copyright notice , this
* list of conditions and the following disclaimer .
*
* Redistributions in binary form must reproduce the above copyright notice ,
* this list of conditions and the following disclaimer in the documentation
* and / or other materials
* provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
* AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR
* BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER
* IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
*/
# include <asm/hvcall.h>
# include "ehca_tools.h"
# include "hcp_if.h"
# include "hcp_phyp.h"
# include "hipz_fns.h"
# include "ipz_pt_fn.h"
# define H_ALL_RES_QP_ENHANCED_OPS EHCA_BMASK_IBM(9, 11)
# define H_ALL_RES_QP_PTE_PIN EHCA_BMASK_IBM(12, 12)
# define H_ALL_RES_QP_SERVICE_TYPE EHCA_BMASK_IBM(13, 15)
2007-07-20 16:04:17 +02:00
# define H_ALL_RES_QP_STORAGE EHCA_BMASK_IBM(16, 17)
2006-09-22 15:22:22 -07:00
# define H_ALL_RES_QP_LL_RQ_CQE_POSTING EHCA_BMASK_IBM(18, 18)
# define H_ALL_RES_QP_LL_SQ_CQE_POSTING EHCA_BMASK_IBM(19, 21)
# define H_ALL_RES_QP_SIGNALING_TYPE EHCA_BMASK_IBM(22, 23)
# define H_ALL_RES_QP_UD_AV_LKEY_CTRL EHCA_BMASK_IBM(31, 31)
2007-07-20 16:04:17 +02:00
# define H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE EHCA_BMASK_IBM(32, 35)
# define H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE EHCA_BMASK_IBM(36, 39)
2006-09-22 15:22:22 -07:00
# define H_ALL_RES_QP_RESOURCE_TYPE EHCA_BMASK_IBM(56, 63)
# define H_ALL_RES_QP_MAX_OUTST_SEND_WR EHCA_BMASK_IBM(0, 15)
# define H_ALL_RES_QP_MAX_OUTST_RECV_WR EHCA_BMASK_IBM(16, 31)
# define H_ALL_RES_QP_MAX_SEND_SGE EHCA_BMASK_IBM(32, 39)
# define H_ALL_RES_QP_MAX_RECV_SGE EHCA_BMASK_IBM(40, 47)
2007-07-09 15:25:10 +02:00
# define H_ALL_RES_QP_UD_AV_LKEY EHCA_BMASK_IBM(32, 63)
# define H_ALL_RES_QP_SRQ_QP_TOKEN EHCA_BMASK_IBM(0, 31)
# define H_ALL_RES_QP_SRQ_QP_HANDLE EHCA_BMASK_IBM(0, 64)
# define H_ALL_RES_QP_SRQ_LIMIT EHCA_BMASK_IBM(48, 63)
# define H_ALL_RES_QP_SRQ_QPN EHCA_BMASK_IBM(40, 63)
2006-09-22 15:22:22 -07:00
# define H_ALL_RES_QP_ACT_OUTST_SEND_WR EHCA_BMASK_IBM(16, 31)
# define H_ALL_RES_QP_ACT_OUTST_RECV_WR EHCA_BMASK_IBM(48, 63)
# define H_ALL_RES_QP_ACT_SEND_SGE EHCA_BMASK_IBM(8, 15)
# define H_ALL_RES_QP_ACT_RECV_SGE EHCA_BMASK_IBM(24, 31)
# define H_ALL_RES_QP_SQUEUE_SIZE_PAGES EHCA_BMASK_IBM(0, 31)
# define H_ALL_RES_QP_RQUEUE_SIZE_PAGES EHCA_BMASK_IBM(32, 63)
2007-04-24 17:44:31 +02:00
# define H_MP_INIT_TYPE EHCA_BMASK_IBM(44, 47)
# define H_MP_SHUTDOWN EHCA_BMASK_IBM(48, 48)
# define H_MP_RESET_QKEY_CTR EHCA_BMASK_IBM(49, 49)
2007-09-11 15:31:49 +02:00
# define HCALL4_REGS_FORMAT "r4=%lx r5=%lx r6=%lx r7=%lx"
# define HCALL7_REGS_FORMAT HCALL4_REGS_FORMAT " r8=%lx r9=%lx r10=%lx"
# define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"
2007-07-09 15:29:03 +02:00
static DEFINE_SPINLOCK ( hcall_lock ) ;
2006-09-22 15:22:22 -07:00
static long ehca_plpar_hcall_norets ( unsigned long opcode ,
unsigned long arg1 ,
unsigned long arg2 ,
unsigned long arg3 ,
unsigned long arg4 ,
unsigned long arg5 ,
unsigned long arg6 ,
unsigned long arg7 )
{
long ret ;
2007-12-10 18:59:10 +01:00
int i , sleep_msecs ;
unsigned long flags = 0 ;
2006-09-22 15:22:22 -07:00
2008-04-23 11:55:45 -07:00
if ( unlikely ( ehca_debug_level > = 2 ) )
ehca_gen_dbg ( " opcode=%lx " HCALL7_REGS_FORMAT ,
opcode , arg1 , arg2 , arg3 , arg4 , arg5 , arg6 , arg7 ) ;
2006-09-22 15:22:22 -07:00
for ( i = 0 ; i < 5 ; i + + ) {
2007-12-10 18:59:10 +01:00
/* serialize hCalls to work around firmware issue */
if ( ehca_lock_hcalls )
2007-09-11 15:34:35 +02:00
spin_lock_irqsave ( & hcall_lock , flags ) ;
2006-09-22 15:22:22 -07:00
ret = plpar_hcall_norets ( opcode , arg1 , arg2 , arg3 , arg4 ,
arg5 , arg6 , arg7 ) ;
2007-12-10 18:59:10 +01:00
if ( ehca_lock_hcalls )
2007-09-11 15:34:35 +02:00
spin_unlock_irqrestore ( & hcall_lock , flags ) ;
2006-09-22 15:22:22 -07:00
if ( H_IS_LONG_BUSY ( ret ) ) {
sleep_msecs = get_longbusy_msecs ( ret ) ;
msleep_interruptible ( sleep_msecs ) ;
continue ;
}
if ( ret < H_SUCCESS )
2007-09-11 15:31:49 +02:00
ehca_gen_err ( " opcode=%lx ret=%li " HCALL7_REGS_FORMAT ,
opcode , ret , arg1 , arg2 , arg3 ,
arg4 , arg5 , arg6 , arg7 ) ;
else
2008-04-23 11:55:45 -07:00
if ( unlikely ( ehca_debug_level > = 2 ) )
ehca_gen_dbg ( " opcode=%lx ret=%li " , opcode , ret ) ;
2006-09-22 15:22:22 -07:00
2007-09-11 15:31:49 +02:00
return ret ;
2006-09-22 15:22:22 -07:00
}
return H_BUSY ;
}
static long ehca_plpar_hcall9 ( unsigned long opcode ,
unsigned long * outs , /* array of 9 outputs */
unsigned long arg1 ,
unsigned long arg2 ,
unsigned long arg3 ,
unsigned long arg4 ,
unsigned long arg5 ,
unsigned long arg6 ,
unsigned long arg7 ,
unsigned long arg8 ,
unsigned long arg9 )
{
long ret ;
2007-12-10 18:59:10 +01:00
int i , sleep_msecs ;
2007-07-09 15:25:10 +02:00
unsigned long flags = 0 ;
2006-09-22 15:22:22 -07:00
2008-04-23 11:55:45 -07:00
if ( unlikely ( ehca_debug_level > = 2 ) )
ehca_gen_dbg ( " INPUT -- opcode=%lx " HCALL9_REGS_FORMAT , opcode ,
arg1 , arg2 , arg3 , arg4 , arg5 ,
arg6 , arg7 , arg8 , arg9 ) ;
2006-09-22 15:22:22 -07:00
for ( i = 0 ; i < 5 ; i + + ) {
2007-12-10 18:59:10 +01:00
/* serialize hCalls to work around firmware issue */
if ( ehca_lock_hcalls )
2007-05-09 13:47:56 +02:00
spin_lock_irqsave ( & hcall_lock , flags ) ;
2006-09-22 15:22:22 -07:00
ret = plpar_hcall9 ( opcode , outs ,
arg1 , arg2 , arg3 , arg4 , arg5 ,
arg6 , arg7 , arg8 , arg9 ) ;
2007-12-10 18:59:10 +01:00
if ( ehca_lock_hcalls )
2007-05-09 13:47:56 +02:00
spin_unlock_irqrestore ( & hcall_lock , flags ) ;
2006-09-22 15:22:22 -07:00
if ( H_IS_LONG_BUSY ( ret ) ) {
sleep_msecs = get_longbusy_msecs ( ret ) ;
msleep_interruptible ( sleep_msecs ) ;
continue ;
}
2007-09-11 15:31:49 +02:00
if ( ret < H_SUCCESS ) {
ehca_gen_err ( " INPUT -- opcode=%lx " HCALL9_REGS_FORMAT ,
opcode , arg1 , arg2 , arg3 , arg4 , arg5 ,
arg6 , arg7 , arg8 , arg9 ) ;
ehca_gen_err ( " OUTPUT -- ret=%li " HCALL9_REGS_FORMAT ,
ret , outs [ 0 ] , outs [ 1 ] , outs [ 2 ] , outs [ 3 ] ,
outs [ 4 ] , outs [ 5 ] , outs [ 6 ] , outs [ 7 ] ,
outs [ 8 ] ) ;
2008-04-23 11:55:45 -07:00
} else if ( unlikely ( ehca_debug_level > = 2 ) )
2007-09-11 15:31:49 +02:00
ehca_gen_dbg ( " OUTPUT -- ret=%li " HCALL9_REGS_FORMAT ,
ret , outs [ 0 ] , outs [ 1 ] , outs [ 2 ] , outs [ 3 ] ,
2006-09-22 15:22:22 -07:00
outs [ 4 ] , outs [ 5 ] , outs [ 6 ] , outs [ 7 ] ,
outs [ 8 ] ) ;
return ret ;
}
return H_BUSY ;
}
2007-05-09 13:47:56 +02:00
2006-09-22 15:22:22 -07:00
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 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
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 )
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " Not enough resource - ret=%lli " , ret ) ;
2006-09-22 15:22:22 -07:00
return ret ;
}
u64 hipz_h_reset_event ( const struct ipz_adapter_handle adapter_handle ,
struct ipz_eq_handle eq_handle ,
const u64 event_mask )
{
return ehca_plpar_hcall_norets ( H_RESET_EVENTS ,
adapter_handle . handle , /* r4 */
eq_handle . handle , /* r5 */
event_mask , /* r6 */
0 , 0 , 0 , 0 ) ;
}
u64 hipz_h_alloc_resource_cq ( const struct ipz_adapter_handle adapter_handle ,
struct ehca_cq * cq ,
struct ehca_alloc_cq_parms * param )
{
2010-07-05 16:19:25 +00:00
int rc ;
2006-09-22 15:22:22 -07:00
u64 ret ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
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 ] ;
2010-07-05 16:19:25 +00:00
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 , /* r4 */
cq - > ipz_cq_handle . handle , /* r5 */
0 , 0 , 0 , 0 , 0 ) ;
ret = H_NO_MEM ;
}
}
2006-09-22 15:22:22 -07:00
if ( ret = = H_NOT_ENOUGH_RESOURCES )
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " Not enough resources. ret=%lli " , ret ) ;
2006-09-22 15:22:22 -07:00
return ret ;
}
u64 hipz_h_alloc_resource_qp ( const struct ipz_adapter_handle adapter_handle ,
2009-05-13 16:52:43 -07:00
struct ehca_alloc_qp_parms * parms , int is_user )
2006-09-22 15:22:22 -07:00
{
2010-07-05 16:19:25 +00:00
int rc ;
2006-09-22 15:22:22 -07:00
u64 ret ;
2007-07-09 15:25:10 +02:00
u64 allocate_controls , max_r10_reg , r11 , r12 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
allocate_controls =
2007-07-09 15:23:15 +02:00
EHCA_BMASK_SET ( H_ALL_RES_QP_ENHANCED_OPS , parms - > ext_type )
2006-09-22 15:22:22 -07:00
| 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 )
2007-07-20 16:04:17 +02:00
| 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 )
2006-09-22 15:22:22 -07:00
| EHCA_BMASK_SET ( H_ALL_RES_QP_LL_RQ_CQE_POSTING ,
2007-07-09 15:23:15 +02:00
! ! ( parms - > ll_comp_flags & LLQP_RECV_COMP ) )
2006-09-22 15:22:22 -07:00
| EHCA_BMASK_SET ( H_ALL_RES_QP_LL_SQ_CQE_POSTING ,
2007-07-09 15:23:15 +02:00
! ! ( parms - > ll_comp_flags & LLQP_SEND_COMP ) )
2006-09-22 15:22:22 -07:00
| 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 ,
2007-07-20 16:04:17 +02:00
parms - > squeue . max_wr + 1 )
2006-09-22 15:22:22 -07:00
| EHCA_BMASK_SET ( H_ALL_RES_QP_MAX_OUTST_RECV_WR ,
2007-07-20 16:04:17 +02:00
parms - > rqueue . max_wr + 1 )
2006-09-22 15:22:22 -07:00
| EHCA_BMASK_SET ( H_ALL_RES_QP_MAX_SEND_SGE ,
2007-07-20 16:04:17 +02:00
parms - > squeue . max_sge )
2006-09-22 15:22:22 -07:00
| EHCA_BMASK_SET ( H_ALL_RES_QP_MAX_RECV_SGE ,
2007-07-20 16:04:17 +02:00
parms - > rqueue . max_sge ) ;
2006-09-22 15:22:22 -07:00
2007-07-09 15:25:10 +02:00
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 ) ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall9 ( H_ALLOC_RESOURCE , outs ,
adapter_handle . handle , /* r4 */
allocate_controls , /* r5 */
2007-07-09 15:23:15 +02:00
parms - > send_cq_handle . handle ,
parms - > recv_cq_handle . handle ,
parms - > eq_handle . handle ,
( ( u64 ) parms - > token < < 32 ) | parms - > pd . value ,
2007-07-09 15:25:10 +02:00
max_r10_reg , r11 , r12 ) ;
2007-07-09 15:23:15 +02:00
parms - > qp_handle . handle = outs [ 0 ] ;
parms - > real_qp_num = ( u32 ) outs [ 1 ] ;
2007-07-20 16:04:17 +02:00
parms - > squeue . act_nr_wqes =
2006-09-22 15:22:22 -07:00
( u16 ) EHCA_BMASK_GET ( H_ALL_RES_QP_ACT_OUTST_SEND_WR , outs [ 2 ] ) ;
2007-07-20 16:04:17 +02:00
parms - > rqueue . act_nr_wqes =
2006-09-22 15:22:22 -07:00
( u16 ) EHCA_BMASK_GET ( H_ALL_RES_QP_ACT_OUTST_RECV_WR , outs [ 2 ] ) ;
2007-07-20 16:04:17 +02:00
parms - > squeue . act_nr_sges =
2006-09-22 15:22:22 -07:00
( u8 ) EHCA_BMASK_GET ( H_ALL_RES_QP_ACT_SEND_SGE , outs [ 3 ] ) ;
2007-07-20 16:04:17 +02:00
parms - > rqueue . act_nr_sges =
2006-09-22 15:22:22 -07:00
( u8 ) EHCA_BMASK_GET ( H_ALL_RES_QP_ACT_RECV_SGE , outs [ 3 ] ) ;
2007-07-20 16:04:17 +02:00
parms - > squeue . queue_size =
2006-09-22 15:22:22 -07:00
( u32 ) EHCA_BMASK_GET ( H_ALL_RES_QP_SQUEUE_SIZE_PAGES , outs [ 4 ] ) ;
2007-07-20 16:04:17 +02:00
parms - > rqueue . queue_size =
2006-09-22 15:22:22 -07:00
( u32 ) EHCA_BMASK_GET ( H_ALL_RES_QP_RQUEUE_SIZE_PAGES , outs [ 4 ] ) ;
2010-07-05 16:19:25 +00:00
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 , /* r4 */
parms - > qp_handle . handle , /* r5 */
0 , 0 , 0 , 0 , 0 ) ;
ret = H_NO_MEM ;
}
}
2006-09-22 15:22:22 -07:00
if ( ret = = H_NOT_ENOUGH_RESOURCES )
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " Not enough resources. ret=%lli " , ret ) ;
2006-09-22 15:22:22 -07:00
return ret ;
}
u64 hipz_h_query_port ( const struct ipz_adapter_handle adapter_handle ,
const u8 port_id ,
struct hipz_query_port * query_port_response_block )
{
u64 ret ;
2012-07-25 21:19:53 +00:00
u64 r_cb = __pa ( query_port_response_block ) ;
2006-09-22 15:22:22 -07:00
if ( r_cb & ( EHCA_PAGESIZE - 1 ) ) {
ehca_gen_err ( " response block not page aligned " ) ;
return H_PARAMETER ;
}
ret = ehca_plpar_hcall_norets ( H_QUERY_PORT ,
adapter_handle . handle , /* r4 */
port_id , /* r5 */
r_cb , /* r6 */
0 , 0 , 0 , 0 ) ;
2008-04-23 11:55:45 -07:00
if ( ehca_debug_level > = 2 )
2006-09-22 15:22:22 -07:00
ehca_dmp ( query_port_response_block , 64 , " response_block " ) ;
return ret ;
}
2007-04-24 17:44:31 +02:00
u64 hipz_h_modify_port ( const struct ipz_adapter_handle adapter_handle ,
const u8 port_id , const u32 port_cap ,
const u8 init_type , const int modify_mask )
{
u64 port_attributes = port_cap ;
if ( modify_mask & IB_PORT_SHUTDOWN )
port_attributes | = EHCA_BMASK_SET ( H_MP_SHUTDOWN , 1 ) ;
if ( modify_mask & IB_PORT_INIT_TYPE )
port_attributes | = EHCA_BMASK_SET ( H_MP_INIT_TYPE , init_type ) ;
if ( modify_mask & IB_PORT_RESET_QKEY_CNTR )
port_attributes | = EHCA_BMASK_SET ( H_MP_RESET_QKEY_CTR , 1 ) ;
return ehca_plpar_hcall_norets ( H_MODIFY_PORT ,
adapter_handle . handle , /* r4 */
port_id , /* r5 */
port_attributes , /* r6 */
0 , 0 , 0 , 0 ) ;
}
2006-09-22 15:22:22 -07:00
u64 hipz_h_query_hca ( const struct ipz_adapter_handle adapter_handle ,
struct hipz_query_hca * query_hca_rblock )
{
2012-07-25 21:19:53 +00:00
u64 r_cb = __pa ( query_hca_rblock ) ;
2006-09-22 15:22:22 -07:00
if ( r_cb & ( EHCA_PAGESIZE - 1 ) ) {
ehca_gen_err ( " response_block=%p not page aligned " ,
query_hca_rblock ) ;
return H_PARAMETER ;
}
return ehca_plpar_hcall_norets ( H_QUERY_HCA ,
adapter_handle . handle , /* r4 */
r_cb , /* r5 */
0 , 0 , 0 , 0 , 0 ) ;
}
u64 hipz_h_register_rpage ( const struct ipz_adapter_handle adapter_handle ,
const u8 pagesize ,
const u8 queue_type ,
const u64 resource_handle ,
const u64 logical_address_of_page ,
u64 count )
{
return ehca_plpar_hcall_norets ( H_REGISTER_RPAGES ,
adapter_handle . handle , /* r4 */
2007-07-20 16:01:51 +02:00
( u64 ) queue_type | ( ( u64 ) pagesize ) < < 8 ,
/* r5 */
2006-09-22 15:22:22 -07:00
resource_handle , /* r6 */
logical_address_of_page , /* r7 */
count , /* r8 */
0 , 0 ) ;
}
u64 hipz_h_register_rpage_eq ( const struct ipz_adapter_handle adapter_handle ,
const struct ipz_eq_handle eq_handle ,
struct ehca_pfeq * pfeq ,
const u8 pagesize ,
const u8 queue_type ,
const u64 logical_address_of_page ,
const u64 count )
{
if ( count ! = 1 ) {
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " Ppage counter=%llx " , count ) ;
2006-09-22 15:22:22 -07:00
return H_PARAMETER ;
}
return hipz_h_register_rpage ( adapter_handle ,
pagesize ,
queue_type ,
eq_handle . handle ,
logical_address_of_page , count ) ;
}
u64 hipz_h_query_int_state ( const struct ipz_adapter_handle adapter_handle ,
u32 ist )
{
u64 ret ;
ret = ehca_plpar_hcall_norets ( H_QUERY_INT_STATE ,
adapter_handle . handle , /* r4 */
ist , /* r5 */
0 , 0 , 0 , 0 , 0 ) ;
if ( ret ! = H_SUCCESS & & ret ! = H_BUSY )
ehca_gen_err ( " Could not query interrupt state. " ) ;
return ret ;
}
u64 hipz_h_register_rpage_cq ( const struct ipz_adapter_handle adapter_handle ,
const struct ipz_cq_handle cq_handle ,
struct ehca_pfcq * pfcq ,
const u8 pagesize ,
const u8 queue_type ,
const u64 logical_address_of_page ,
const u64 count ,
const struct h_galpa gal )
{
if ( count ! = 1 ) {
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " Page counter=%llx " , count ) ;
2006-09-22 15:22:22 -07:00
return H_PARAMETER ;
}
return hipz_h_register_rpage ( adapter_handle , pagesize , queue_type ,
cq_handle . handle , logical_address_of_page ,
count ) ;
}
u64 hipz_h_register_rpage_qp ( const struct ipz_adapter_handle adapter_handle ,
const struct ipz_qp_handle qp_handle ,
struct ehca_pfqp * pfqp ,
const u8 pagesize ,
const u8 queue_type ,
const u64 logical_address_of_page ,
const u64 count ,
const struct h_galpa galpa )
{
2007-07-20 16:04:17 +02:00
if ( count > 1 ) {
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " Page counter=%llx " , count ) ;
2006-09-22 15:22:22 -07:00
return H_PARAMETER ;
}
2007-07-12 17:53:47 +02:00
return hipz_h_register_rpage ( adapter_handle , pagesize , queue_type ,
qp_handle . handle , logical_address_of_page ,
2006-09-22 15:22:22 -07:00
count ) ;
}
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 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall9 ( H_DISABLE_AND_GETC , outs ,
adapter_handle . handle , /* r4 */
dis_and_get_function_code , /* r5 */
qp_handle . handle , /* r6 */
0 , 0 , 0 , 0 , 0 , 0 ) ;
if ( log_addr_next_sq_wqe2processed )
2007-07-12 17:53:47 +02:00
* log_addr_next_sq_wqe2processed = ( void * ) outs [ 0 ] ;
2006-09-22 15:22:22 -07:00
if ( log_addr_next_rq_wqe2processed )
2007-07-12 17:53:47 +02:00
* log_addr_next_rq_wqe2processed = ( void * ) outs [ 1 ] ;
2006-09-22 15:22:22 -07:00
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 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall9 ( H_MODIFY_QP , outs ,
adapter_handle . handle , /* r4 */
qp_handle . handle , /* r5 */
update_mask , /* r6 */
2012-07-25 21:19:53 +00:00
__pa ( mqpcb ) , /* r7 */
2006-09-22 15:22:22 -07:00
0 , 0 , 0 , 0 , 0 ) ;
if ( ret = = H_NOT_ENOUGH_RESOURCES )
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " Insufficient resources ret=%lli " , ret ) ;
2006-09-22 15:22:22 -07:00
return ret ;
}
u64 hipz_h_query_qp ( const struct ipz_adapter_handle adapter_handle ,
const struct ipz_qp_handle qp_handle ,
struct ehca_pfqp * pfqp ,
struct hcp_modify_qp_control_block * qqpcb ,
struct h_galpa gal )
{
return ehca_plpar_hcall_norets ( H_QUERY_QP ,
adapter_handle . handle , /* r4 */
qp_handle . handle , /* r5 */
2012-07-25 21:19:53 +00:00
__pa ( qqpcb ) , /* r6 */
2006-09-22 15:22:22 -07:00
0 , 0 , 0 , 0 ) ;
}
u64 hipz_h_destroy_qp ( const struct ipz_adapter_handle adapter_handle ,
struct ehca_qp * qp )
{
u64 ret ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
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 , /* r4 */
/* function code */
1 , /* r5 */
qp - > ipz_qp_handle . handle , /* r6 */
0 , 0 , 0 , 0 , 0 , 0 ) ;
if ( ret = = H_HARDWARE )
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " HCA not operational. ret=%lli " , ret ) ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall_norets ( H_FREE_RESOURCE ,
adapter_handle . handle , /* r4 */
qp - > ipz_qp_handle . handle , /* r5 */
0 , 0 , 0 , 0 , 0 ) ;
if ( ret = = H_RESOURCE )
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " Resource still in use. ret=%lli " , ret ) ;
2006-09-22 15:22:22 -07:00
return ret ;
}
u64 hipz_h_define_aqp0 ( const struct ipz_adapter_handle adapter_handle ,
const struct ipz_qp_handle qp_handle ,
struct h_galpa gal ,
u32 port )
{
return ehca_plpar_hcall_norets ( H_DEFINE_AQP0 ,
adapter_handle . handle , /* r4 */
qp_handle . handle , /* r5 */
port , /* r6 */
0 , 0 , 0 , 0 ) ;
}
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 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall9 ( H_DEFINE_AQP1 , outs ,
adapter_handle . handle , /* r4 */
qp_handle . handle , /* r5 */
port , /* r6 */
0 , 0 , 0 , 0 , 0 , 0 ) ;
* pma_qp_nr = ( u32 ) outs [ 0 ] ;
* bma_qp_nr = ( u32 ) outs [ 1 ] ;
if ( ret = = H_ALIAS_EXIST )
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " AQP1 already exists. ret=%lli " , ret ) ;
2006-09-22 15:22:22 -07:00
return ret ;
}
u64 hipz_h_attach_mcqp ( const struct ipz_adapter_handle adapter_handle ,
const struct ipz_qp_handle qp_handle ,
struct h_galpa gal ,
u16 mcg_dlid ,
u64 subnet_prefix , u64 interface_id )
{
u64 ret ;
ret = ehca_plpar_hcall_norets ( H_ATTACH_MCQP ,
adapter_handle . handle , /* r4 */
qp_handle . handle , /* r5 */
mcg_dlid , /* r6 */
interface_id , /* r7 */
subnet_prefix , /* r8 */
0 , 0 ) ;
if ( ret = = H_NOT_ENOUGH_RESOURCES )
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " Not enough resources. ret=%lli " , ret ) ;
2006-09-22 15:22:22 -07:00
return ret ;
}
u64 hipz_h_detach_mcqp ( const struct ipz_adapter_handle adapter_handle ,
const struct ipz_qp_handle qp_handle ,
struct h_galpa gal ,
u16 mcg_dlid ,
u64 subnet_prefix , u64 interface_id )
{
return ehca_plpar_hcall_norets ( H_DETACH_MCQP ,
adapter_handle . handle , /* r4 */
qp_handle . handle , /* r5 */
mcg_dlid , /* r6 */
interface_id , /* r7 */
subnet_prefix , /* r8 */
0 , 0 ) ;
}
u64 hipz_h_destroy_cq ( const struct ipz_adapter_handle adapter_handle ,
struct ehca_cq * cq ,
u8 force_flag )
{
u64 ret ;
ret = hcp_galpas_dtor ( & cq - > galpas ) ;
if ( ret ) {
ehca_gen_err ( " Could not destruct cp->galpas " ) ;
return H_RESOURCE ;
}
ret = ehca_plpar_hcall_norets ( H_FREE_RESOURCE ,
adapter_handle . handle , /* r4 */
cq - > ipz_cq_handle . handle , /* r5 */
force_flag ! = 0 ? 1L : 0L , /* r6 */
0 , 0 , 0 , 0 ) ;
if ( ret = = H_RESOURCE )
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " H_FREE_RESOURCE failed ret=%lli " , ret ) ;
2006-09-22 15:22:22 -07:00
return ret ;
}
u64 hipz_h_destroy_eq ( const struct ipz_adapter_handle adapter_handle ,
struct ehca_eq * eq )
{
u64 ret ;
ret = hcp_galpas_dtor ( & eq - > galpas ) ;
if ( ret ) {
ehca_gen_err ( " Could not destruct eq->galpas " ) ;
return H_RESOURCE ;
}
ret = ehca_plpar_hcall_norets ( H_FREE_RESOURCE ,
adapter_handle . handle , /* r4 */
eq - > ipz_eq_handle . handle , /* r5 */
0 , 0 , 0 , 0 , 0 ) ;
if ( ret = = H_RESOURCE )
2009-01-16 14:55:28 -08:00
ehca_gen_err ( " Resource in use. ret=%lli " , ret ) ;
2006-09-22 15:22:22 -07:00
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 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall9 ( H_ALLOC_RESOURCE , outs ,
adapter_handle . handle , /* r4 */
5 , /* r5 */
vaddr , /* r6 */
length , /* r7 */
( ( ( u64 ) access_ctrl ) < < 32ULL ) , /* r8 */
pd . value , /* r9 */
0 , 0 , 0 ) ;
outparms - > handle . handle = outs [ 0 ] ;
outparms - > lkey = ( u32 ) outs [ 2 ] ;
outparms - > rkey = ( u32 ) outs [ 3 ] ;
return ret ;
}
u64 hipz_h_register_rpage_mr ( const struct ipz_adapter_handle adapter_handle ,
const struct ehca_mr * mr ,
const u8 pagesize ,
const u8 queue_type ,
const u64 logical_address_of_page ,
const u64 count )
{
u64 ret ;
2008-04-23 11:55:45 -07:00
if ( unlikely ( ehca_debug_level > = 3 ) ) {
2007-07-20 16:01:51 +02:00
if ( count > 1 ) {
u64 * kpage ;
int i ;
2012-07-25 21:19:53 +00:00
kpage = __va ( logical_address_of_page ) ;
2007-07-20 16:01:51 +02:00
for ( i = 0 ; i < count ; i + + )
ehca_gen_dbg ( " kpage[%d]=%p " ,
i , ( void * ) kpage [ i ] ) ;
} else
ehca_gen_dbg ( " kpage=%p " ,
( void * ) logical_address_of_page ) ;
}
2006-09-22 15:22:22 -07:00
if ( ( count > 1 ) & & ( logical_address_of_page & ( EHCA_PAGESIZE - 1 ) ) ) {
ehca_gen_err ( " logical_address_of_page not on a 4k boundary "
2009-01-16 14:55:28 -08:00
" adapter_handle=%llx mr=%p mr_handle=%llx "
2006-09-22 15:22:22 -07:00
" pagesize=%x queue_type=%x "
2009-01-16 14:55:28 -08:00
" logical_address_of_page=%llx count=%llx " ,
2006-09-22 15:22:22 -07:00
adapter_handle . handle , mr ,
mr - > ipz_mr_handle . handle , pagesize , queue_type ,
logical_address_of_page , count ) ;
ret = H_PARAMETER ;
} else
ret = hipz_h_register_rpage ( adapter_handle , pagesize ,
queue_type ,
mr - > ipz_mr_handle . handle ,
logical_address_of_page , count ) ;
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 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall9 ( H_QUERY_MR , outs ,
adapter_handle . handle , /* r4 */
mr - > ipz_mr_handle . handle , /* r5 */
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_free_resource_mr ( const struct ipz_adapter_handle adapter_handle ,
const struct ehca_mr * mr )
{
return ehca_plpar_hcall_norets ( H_FREE_RESOURCE ,
adapter_handle . handle , /* r4 */
mr - > ipz_mr_handle . handle , /* r5 */
2007-12-10 18:59:10 +01:00
0 , 0 , 0 , 0 , 0 ) ;
2006-09-22 15:22:22 -07:00
}
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 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall9 ( H_REREGISTER_PMR , outs ,
adapter_handle . handle , /* r4 */
mr - > ipz_mr_handle . handle , /* r5 */
vaddr_in , /* r6 */
length , /* r7 */
/* r8 */
( ( ( ( u64 ) access_ctrl ) < < 32ULL ) | pd . value ) ,
mr_addr_cb , /* r9 */
0 , 0 , 0 ) ;
outparms - > vaddr = outs [ 1 ] ;
outparms - > lkey = ( u32 ) outs [ 2 ] ;
outparms - > rkey = ( u32 ) outs [ 3 ] ;
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 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall9 ( H_REGISTER_SMR , outs ,
adapter_handle . handle , /* r4 */
orig_mr - > ipz_mr_handle . handle , /* r5 */
vaddr_in , /* r6 */
( ( ( u64 ) access_ctrl ) < < 32ULL ) , /* r7 */
pd . value , /* r8 */
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_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 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall9 ( H_ALLOC_RESOURCE , outs ,
adapter_handle . handle , /* r4 */
6 , /* r5 */
pd . value , /* r6 */
0 , 0 , 0 , 0 , 0 , 0 ) ;
outparms - > handle . handle = outs [ 0 ] ;
outparms - > rkey = ( u32 ) outs [ 3 ] ;
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 ;
2009-01-16 14:55:40 -08:00
unsigned long outs [ PLPAR_HCALL9_BUFSIZE ] ;
2006-09-22 15:22:22 -07:00
ret = ehca_plpar_hcall9 ( H_QUERY_MW , outs ,
adapter_handle . handle , /* r4 */
mw - > ipz_mw_handle . handle , /* r5 */
0 , 0 , 0 , 0 , 0 , 0 , 0 ) ;
outparms - > rkey = ( u32 ) outs [ 3 ] ;
return ret ;
}
u64 hipz_h_free_resource_mw ( const struct ipz_adapter_handle adapter_handle ,
const struct ehca_mw * mw )
{
return ehca_plpar_hcall_norets ( H_FREE_RESOURCE ,
adapter_handle . handle , /* r4 */
mw - > ipz_mw_handle . handle , /* r5 */
0 , 0 , 0 , 0 , 0 ) ;
}
u64 hipz_h_error_data ( const struct ipz_adapter_handle adapter_handle ,
const u64 ressource_handle ,
void * rblock ,
unsigned long * byte_count )
{
2012-07-25 21:19:53 +00:00
u64 r_cb = __pa ( rblock ) ;
2006-09-22 15:22:22 -07:00
if ( r_cb & ( EHCA_PAGESIZE - 1 ) ) {
ehca_gen_err ( " rblock not page aligned. " ) ;
return H_PARAMETER ;
}
return ehca_plpar_hcall_norets ( H_ERROR_DATA ,
adapter_handle . handle ,
ressource_handle ,
r_cb ,
0 , 0 , 0 , 0 ) ;
}
2008-07-14 23:48:47 -07:00
u64 hipz_h_eoi ( int irq )
{
unsigned long xirr ;
iosync ( ) ;
xirr = ( 0xffULL < < 24 ) | irq ;
return plpar_hcall_norets ( H_EOI , xirr ) ;
}