⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hcp_if.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  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> *           Joachim Fenkes <fenkes@de.ibm.com> *           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)#define H_ALL_RES_QP_STORAGE            EHCA_BMASK_IBM(16, 17)#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)#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)#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)#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)#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)#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)#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"static DEFINE_SPINLOCK(hcall_lock);static u32 get_longbusy_msecs(int longbusy_rc){	switch (longbusy_rc) {	case H_LONG_BUSY_ORDER_1_MSEC:		return 1;	case H_LONG_BUSY_ORDER_10_MSEC:		return 10;	case H_LONG_BUSY_ORDER_100_MSEC:		return 100;	case H_LONG_BUSY_ORDER_1_SEC:		return 1000;	case H_LONG_BUSY_ORDER_10_SEC:		return 10000;	case H_LONG_BUSY_ORDER_100_SEC:		return 100000;	default:		return 1;	}}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;	int i, sleep_msecs;	unsigned long flags = 0;	ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,		     opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);	for (i = 0; i < 5; i++) {		/* serialize hCalls to work around firmware issue */		if (ehca_lock_hcalls)			spin_lock_irqsave(&hcall_lock, flags);		ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,					 arg5, arg6, arg7);		if (ehca_lock_hcalls)			spin_unlock_irqrestore(&hcall_lock, flags);		if (H_IS_LONG_BUSY(ret)) {			sleep_msecs = get_longbusy_msecs(ret);			msleep_interruptible(sleep_msecs);			continue;		}		if (ret < H_SUCCESS)			ehca_gen_err("opcode=%lx ret=%li " HCALL7_REGS_FORMAT,				     opcode, ret, arg1, arg2, arg3,				     arg4, arg5, arg6, arg7);		else			ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);		return ret;	}	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;	int i, sleep_msecs;	unsigned long flags = 0;	ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,		     arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);	for (i = 0; i < 5; i++) {		/* serialize hCalls to work around firmware issue */		if (ehca_lock_hcalls)			spin_lock_irqsave(&hcall_lock, flags);		ret = plpar_hcall9(opcode, outs,				   arg1, arg2, arg3, arg4, arg5,				   arg6, arg7, arg8, arg9);		if (ehca_lock_hcalls)			spin_unlock_irqrestore(&hcall_lock, flags);		if (H_IS_LONG_BUSY(ret)) {			sleep_msecs = get_longbusy_msecs(ret);			msleep_interruptible(sleep_msecs);			continue;		}		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]);		} else			ehca_gen_dbg("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]);		return ret;	}	return H_BUSY;}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=%li ", ret);	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){	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=%li", ret);	return ret;}u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,			     struct ehca_alloc_qp_parms *parms){	u64 ret;	u64 allocate_controls, max_r10_reg, r11, r12;	u64 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,	           /* r4  */				allocate_controls,	           /* r5  */				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)		hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);	if (ret == H_NOT_ENOUGH_RESOURCES)		ehca_gen_err("Not enough resources. ret=%li", ret);	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;	u64 r_cb = virt_to_abs(query_port_response_block);	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);	if (ehca_debug_level)		ehca_dmp(query_port_response_block, 64, "response_block");	return ret;}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);}u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,		     struct hipz_query_hca *query_hca_rblock){	u64 r_cb = virt_to_abs(query_hca_rblock);	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  */				       (u64)queue_type | ((u64)pagesize) << 8,				       /* r5  */				       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) {		ehca_gen_err("Ppage counter=%lx", count);		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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -