1/*
2 *  IBM eServer eHCA Infiniband device driver for Linux on POWER
3 *
4 *  Firmware Infiniband Interface code for POWER
5 *
6 *  Authors: Christoph Raisch <raisch@de.ibm.com>
7 *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
8 *           Joachim Fenkes <fenkes@de.ibm.com>
9 *           Gerd Bayer <gerd.bayer@de.ibm.com>
10 *           Waleri Fomin <fomin@de.ibm.com>
11 *
12 *  Copyright (c) 2005 IBM Corporation
13 *
14 *  All rights reserved.
15 *
16 *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
17 *  BSD.
18 *
19 * OpenIB BSD License
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 *
24 * Redistributions of source code must retain the above copyright notice, this
25 * list of conditions and the following disclaimer.
26 *
27 * Redistributions in binary form must reproduce the above copyright notice,
28 * this list of conditions and the following disclaimer in the documentation
29 * and/or other materials
30 * provided with the distribution.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
36 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
40 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGE.
43 */
44
45#include <asm/hvcall.h>
46#include "ehca_tools.h"
47#include "hcp_if.h"
48#include "hcp_phyp.h"
49#include "hipz_fns.h"
50#include "ipz_pt_fn.h"
51
52#define H_ALL_RES_QP_ENHANCED_OPS       EHCA_BMASK_IBM(9, 11)
53#define H_ALL_RES_QP_PTE_PIN            EHCA_BMASK_IBM(12, 12)
54#define H_ALL_RES_QP_SERVICE_TYPE       EHCA_BMASK_IBM(13, 15)
55#define H_ALL_RES_QP_STORAGE            EHCA_BMASK_IBM(16, 17)
56#define H_ALL_RES_QP_LL_RQ_CQE_POSTING  EHCA_BMASK_IBM(18, 18)
57#define H_ALL_RES_QP_LL_SQ_CQE_POSTING  EHCA_BMASK_IBM(19, 21)
58#define H_ALL_RES_QP_SIGNALING_TYPE     EHCA_BMASK_IBM(22, 23)
59#define H_ALL_RES_QP_UD_AV_LKEY_CTRL    EHCA_BMASK_IBM(31, 31)
60#define H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE EHCA_BMASK_IBM(32, 35)
61#define H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE EHCA_BMASK_IBM(36, 39)
62#define H_ALL_RES_QP_RESOURCE_TYPE      EHCA_BMASK_IBM(56, 63)
63
64#define H_ALL_RES_QP_MAX_OUTST_SEND_WR  EHCA_BMASK_IBM(0, 15)
65#define H_ALL_RES_QP_MAX_OUTST_RECV_WR  EHCA_BMASK_IBM(16, 31)
66#define H_ALL_RES_QP_MAX_SEND_SGE       EHCA_BMASK_IBM(32, 39)
67#define H_ALL_RES_QP_MAX_RECV_SGE       EHCA_BMASK_IBM(40, 47)
68
69#define H_ALL_RES_QP_UD_AV_LKEY         EHCA_BMASK_IBM(32, 63)
70#define H_ALL_RES_QP_SRQ_QP_TOKEN       EHCA_BMASK_IBM(0, 31)
71#define H_ALL_RES_QP_SRQ_QP_HANDLE      EHCA_BMASK_IBM(0, 64)
72#define H_ALL_RES_QP_SRQ_LIMIT          EHCA_BMASK_IBM(48, 63)
73#define H_ALL_RES_QP_SRQ_QPN            EHCA_BMASK_IBM(40, 63)
74
75#define H_ALL_RES_QP_ACT_OUTST_SEND_WR  EHCA_BMASK_IBM(16, 31)
76#define H_ALL_RES_QP_ACT_OUTST_RECV_WR  EHCA_BMASK_IBM(48, 63)
77#define H_ALL_RES_QP_ACT_SEND_SGE       EHCA_BMASK_IBM(8, 15)
78#define H_ALL_RES_QP_ACT_RECV_SGE       EHCA_BMASK_IBM(24, 31)
79
80#define H_ALL_RES_QP_SQUEUE_SIZE_PAGES  EHCA_BMASK_IBM(0, 31)
81#define H_ALL_RES_QP_RQUEUE_SIZE_PAGES  EHCA_BMASK_IBM(32, 63)
82
83#define H_MP_INIT_TYPE                  EHCA_BMASK_IBM(44, 47)
84#define H_MP_SHUTDOWN                   EHCA_BMASK_IBM(48, 48)
85#define H_MP_RESET_QKEY_CTR             EHCA_BMASK_IBM(49, 49)
86
87#define HCALL4_REGS_FORMAT "r4=%lx r5=%lx r6=%lx r7=%lx"
88#define HCALL7_REGS_FORMAT HCALL4_REGS_FORMAT " r8=%lx r9=%lx r10=%lx"
89#define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"
90
91static DEFINE_SPINLOCK(hcall_lock);
92
93static long ehca_plpar_hcall_norets(unsigned long opcode,
94				    unsigned long arg1,
95				    unsigned long arg2,
96				    unsigned long arg3,
97				    unsigned long arg4,
98				    unsigned long arg5,
99				    unsigned long arg6,
100				    unsigned long arg7)
101{
102	long ret;
103	int i, sleep_msecs;
104	unsigned long flags = 0;
105
106	if (unlikely(ehca_debug_level >= 2))
107		ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
108			     opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
109
110	for (i = 0; i < 5; i++) {
111		/* serialize hCalls to work around firmware issue */
112		if (ehca_lock_hcalls)
113			spin_lock_irqsave(&hcall_lock, flags);
114
115		ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
116					 arg5, arg6, arg7);
117
118		if (ehca_lock_hcalls)
119			spin_unlock_irqrestore(&hcall_lock, flags);
120
121		if (H_IS_LONG_BUSY(ret)) {
122			sleep_msecs = get_longbusy_msecs(ret);
123			msleep_interruptible(sleep_msecs);
124			continue;
125		}
126
127		if (ret < H_SUCCESS)
128			ehca_gen_err("opcode=%lx ret=%li " HCALL7_REGS_FORMAT,
129				     opcode, ret, arg1, arg2, arg3,
130				     arg4, arg5, arg6, arg7);
131		else
132			if (unlikely(ehca_debug_level >= 2))
133				ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
134
135		return ret;
136	}
137
138	return H_BUSY;
139}
140
141static long ehca_plpar_hcall9(unsigned long opcode,
142			      unsigned long *outs, /* array of 9 outputs */
143			      unsigned long arg1,
144			      unsigned long arg2,
145			      unsigned long arg3,
146			      unsigned long arg4,
147			      unsigned long arg5,
148			      unsigned long arg6,
149			      unsigned long arg7,
150			      unsigned long arg8,
151			      unsigned long arg9)
152{
153	long ret;
154	int i, sleep_msecs;
155	unsigned long flags = 0;
156
157	if (unlikely(ehca_debug_level >= 2))
158		ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
159			     arg1, arg2, arg3, arg4, arg5,
160			     arg6, arg7, arg8, arg9);
161
162	for (i = 0; i < 5; i++) {
163		/* serialize hCalls to work around firmware issue */
164		if (ehca_lock_hcalls)
165			spin_lock_irqsave(&hcall_lock, flags);
166
167		ret = plpar_hcall9(opcode, outs,
168				   arg1, arg2, arg3, arg4, arg5,
169				   arg6, arg7, arg8, arg9);
170
171		if (ehca_lock_hcalls)
172			spin_unlock_irqrestore(&hcall_lock, flags);
173
174		if (H_IS_LONG_BUSY(ret)) {
175			sleep_msecs = get_longbusy_msecs(ret);
176			msleep_interruptible(sleep_msecs);
177			continue;
178		}
179
180		if (ret < H_SUCCESS) {
181			ehca_gen_err("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT,
182				     opcode, arg1, arg2, arg3, arg4, arg5,
183				     arg6, arg7, arg8, arg9);
184			ehca_gen_err("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
185				     ret, outs[0], outs[1], outs[2], outs[3],
186				     outs[4], outs[5], outs[6], outs[7],
187				     outs[8]);
188		} else if (unlikely(ehca_debug_level >= 2))
189			ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
190				     ret, outs[0], outs[1], outs[2], outs[3],
191				     outs[4], outs[5], outs[6], outs[7],
192				     outs[8]);
193		return ret;
194	}
195
196	return H_BUSY;
197}
198
199u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
200			     struct ehca_pfeq *pfeq,
201			     const u32 neq_control,
202			     const u32 number_of_entries,
203			     struct ipz_eq_handle *eq_handle,
204			     u32 *act_nr_of_entries,
205			     u32 *act_pages,
206			     u32 *eq_ist)
207{
208	u64 ret;
209	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
210	u64 allocate_controls;
211
212	/* resource type */
213	allocate_controls = 3ULL;
214
215	/* ISN is associated */
216	if (neq_control != 1)
217		allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
218	else /* notification event queue */
219		allocate_controls = (1ULL << 63) | allocate_controls;
220
221	ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
222				adapter_handle.handle,  /* r4 */
223				allocate_controls,      /* r5 */
224				number_of_entries,      /* r6 */
225				0, 0, 0, 0, 0, 0);
226	eq_handle->handle = outs[0];
227	*act_nr_of_entries = (u32)outs[3];
228	*act_pages = (u32)outs[4];
229	*eq_ist = (u32)outs[5];
230
231	if (ret == H_NOT_ENOUGH_RESOURCES)
232		ehca_gen_err("Not enough resource - ret=%lli ", ret);
233
234	return ret;
235}
236
237u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
238		       struct ipz_eq_handle eq_handle,
239		       const u64 event_mask)
240{
241	return ehca_plpar_hcall_norets(H_RESET_EVENTS,
242				       adapter_handle.handle, /* r4 */
243				       eq_handle.handle,      /* r5 */
244				       event_mask,	      /* r6 */
245				       0, 0, 0, 0);
246}
247
248u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
249			     struct ehca_cq *cq,
250			     struct ehca_alloc_cq_parms *param)
251{
252	int rc;
253	u64 ret;
254	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
255
256	ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
257				adapter_handle.handle,   /* r4  */
258				2,	                 /* r5  */
259				param->eq_handle.handle, /* r6  */
260				cq->token,	         /* r7  */
261				param->nr_cqe,           /* r8  */
262				0, 0, 0, 0);
263	cq->ipz_cq_handle.handle = outs[0];
264	param->act_nr_of_entries = (u32)outs[3];
265	param->act_pages = (u32)outs[4];
266
267	if (ret == H_SUCCESS) {
268		rc = hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]);
269		if (rc) {
270			ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx",
271				     rc, outs[5]);
272
273			ehca_plpar_hcall_norets(H_FREE_RESOURCE,
274						adapter_handle.handle,     /* r4 */
275						cq->ipz_cq_handle.handle,  /* r5 */
276						0, 0, 0, 0, 0);
277			ret = H_NO_MEM;
278		}
279	}
280
281	if (ret == H_NOT_ENOUGH_RESOURCES)
282		ehca_gen_err("Not enough resources. ret=%lli", ret);
283
284	return ret;
285}
286
287u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
288			     struct ehca_alloc_qp_parms *parms, int is_user)
289{
290	int rc;
291	u64 ret;
292	u64 allocate_controls, max_r10_reg, r11, r12;
293	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
294
295	allocate_controls =
296		EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
297		| EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
298		| EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
299		| EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
300		| EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage)
301		| EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE,
302				 parms->squeue.page_size)
303		| EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE,
304				 parms->rqueue.page_size)
305		| EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
306				 !!(parms->ll_comp_flags & LLQP_RECV_COMP))
307		| EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
308				 !!(parms->ll_comp_flags & LLQP_SEND_COMP))
309		| EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
310				 parms->ud_av_l_key_ctl)
311		| EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
312
313	max_r10_reg =
314		EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
315			       parms->squeue.max_wr + 1)
316		| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
317				 parms->rqueue.max_wr + 1)
318		| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
319				 parms->squeue.max_sge)
320		| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
321				 parms->rqueue.max_sge);
322
323	r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
324
325	if (parms->ext_type == EQPT_SRQ)
326		r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
327	else
328		r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
329
330	ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
331				adapter_handle.handle,	           /* r4  */
332				allocate_controls,	           /* r5  */
333				parms->send_cq_handle.handle,
334				parms->recv_cq_handle.handle,
335				parms->eq_handle.handle,
336				((u64)parms->token << 32) | parms->pd.value,
337				max_r10_reg, r11, r12);
338
339	parms->qp_handle.handle = outs[0];
340	parms->real_qp_num = (u32)outs[1];
341	parms->squeue.act_nr_wqes =
342		(u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
343	parms->rqueue.act_nr_wqes =
344		(u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
345	parms->squeue.act_nr_sges =
346		(u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
347	parms->rqueue.act_nr_sges =
348		(u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
349	parms->squeue.queue_size =
350		(u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
351	parms->rqueue.queue_size =
352		(u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
353
354	if (ret == H_SUCCESS) {
355		rc = hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]);
356		if (rc) {
357			ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx",
358				     rc, outs[6]);
359
360			ehca_plpar_hcall_norets(H_FREE_RESOURCE,
361						adapter_handle.handle,     /* r4 */
362						parms->qp_handle.handle,  /* r5 */
363						0, 0, 0, 0, 0);
364			ret = H_NO_MEM;
365		}
366	}
367
368	if (ret == H_NOT_ENOUGH_RESOURCES)
369		ehca_gen_err("Not enough resources. ret=%lli", ret);
370
371	return ret;
372}
373
374u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
375		      const u8 port_id,
376		      struct hipz_query_port *query_port_response_block)
377{
378	u64 ret;
379	u64 r_cb = __pa(query_port_response_block);
380
381	if (r_cb & (EHCA_PAGESIZE-1)) {
382		ehca_gen_err("response block not page aligned");
383		return H_PARAMETER;
384	}
385
386	ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
387				      adapter_handle.handle, /* r4 */
388				      port_id,	             /* r5 */
389				      r_cb,	             /* r6 */
390				      0, 0, 0, 0);
391
392	if (ehca_debug_level >= 2)
393		ehca_dmp(query_port_response_block, 64, "response_block");
394
395	return ret;
396}
397
398u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
399		       const u8 port_id, const u32 port_cap,
400		       const u8 init_type, const int modify_mask)
401{
402	u64 port_attributes = port_cap;
403
404	if (modify_mask & IB_PORT_SHUTDOWN)
405		port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
406	if (modify_mask & IB_PORT_INIT_TYPE)
407		port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
408	if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
409		port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
410
411	return ehca_plpar_hcall_norets(H_MODIFY_PORT,
412				       adapter_handle.handle, /* r4 */
413				       port_id,               /* r5 */
414				       port_attributes,       /* r6 */
415				       0, 0, 0, 0);
416}
417
418u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
419		     struct hipz_query_hca *query_hca_rblock)
420{
421	u64 r_cb = __pa(query_hca_rblock);
422
423	if (r_cb & (EHCA_PAGESIZE-1)) {
424		ehca_gen_err("response_block=%p not page aligned",
425			     query_hca_rblock);
426		return H_PARAMETER;
427	}
428
429	return ehca_plpar_hcall_norets(H_QUERY_HCA,
430				       adapter_handle.handle, /* r4 */
431				       r_cb,                  /* r5 */
432				       0, 0, 0, 0, 0);
433}
434
435u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
436			  const u8 pagesize,
437			  const u8 queue_type,
438			  const u64 resource_handle,
439			  const u64 logical_address_of_page,
440			  u64 count)
441{
442	return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
443				       adapter_handle.handle,      /* r4  */
444				       (u64)queue_type | ((u64)pagesize) << 8,
445				       /* r5  */
446				       resource_handle,	           /* r6  */
447				       logical_address_of_page,    /* r7  */
448				       count,	                   /* r8  */
449				       0, 0);
450}
451
452u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
453			     const struct ipz_eq_handle eq_handle,
454			     struct ehca_pfeq *pfeq,
455			     const u8 pagesize,
456			     const u8 queue_type,
457			     const u64 logical_address_of_page,
458			     const u64 count)
459{
460	if (count != 1) {
461		ehca_gen_err("Ppage counter=%llx", count);
462		return H_PARAMETER;
463	}
464	return hipz_h_register_rpage(adapter_handle,
465				     pagesize,
466				     queue_type,
467				     eq_handle.handle,
468				     logical_address_of_page, count);
469}
470
471u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
472			   u32 ist)
473{
474	u64 ret;
475	ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
476				      adapter_handle.handle, /* r4 */
477				      ist,                   /* r5 */
478				      0, 0, 0, 0, 0);
479
480	if (ret != H_SUCCESS && ret != H_BUSY)
481		ehca_gen_err("Could not query interrupt state.");
482
483	return ret;
484}
485
486u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
487			     const struct ipz_cq_handle cq_handle,
488			     struct ehca_pfcq *pfcq,
489			     const u8 pagesize,
490			     const u8 queue_type,
491			     const u64 logical_address_of_page,
492			     const u64 count,
493			     const struct h_galpa gal)
494{
495	if (count != 1) {
496		ehca_gen_err("Page counter=%llx", count);
497		return H_PARAMETER;
498	}
499
500	return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
501				     cq_handle.handle, logical_address_of_page,
502				     count);
503}
504
505u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
506			     const struct ipz_qp_handle qp_handle,
507			     struct ehca_pfqp *pfqp,
508			     const u8 pagesize,
509			     const u8 queue_type,
510			     const u64 logical_address_of_page,
511			     const u64 count,
512			     const struct h_galpa galpa)
513{
514	if (count > 1) {
515		ehca_gen_err("Page counter=%llx", count);
516		return H_PARAMETER;
517	}
518
519	return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
520				     qp_handle.handle, logical_address_of_page,
521				     count);
522}
523
524u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
525			       const struct ipz_qp_handle qp_handle,
526			       struct ehca_pfqp *pfqp,
527			       void **log_addr_next_sq_wqe2processed,
528			       void **log_addr_next_rq_wqe2processed,
529			       int dis_and_get_function_code)
530{
531	u64 ret;
532	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
533
534	ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
535				adapter_handle.handle,     /* r4 */
536				dis_and_get_function_code, /* r5 */
537				qp_handle.handle,	   /* r6 */
538				0, 0, 0, 0, 0, 0);
539	if (log_addr_next_sq_wqe2processed)
540		*log_addr_next_sq_wqe2processed = (void *)outs[0];
541	if (log_addr_next_rq_wqe2processed)
542		*log_addr_next_rq_wqe2processed = (void *)outs[1];
543
544	return ret;
545}
546
547u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
548		     const struct ipz_qp_handle qp_handle,
549		     struct ehca_pfqp *pfqp,
550		     const u64 update_mask,
551		     struct hcp_modify_qp_control_block *mqpcb,
552		     struct h_galpa gal)
553{
554	u64 ret;
555	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
556	ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
557				adapter_handle.handle, /* r4 */
558				qp_handle.handle,      /* r5 */
559				update_mask,	       /* r6 */
560				__pa(mqpcb),	       /* r7 */
561				0, 0, 0, 0, 0);
562
563	if (ret == H_NOT_ENOUGH_RESOURCES)
564		ehca_gen_err("Insufficient resources ret=%lli", ret);
565
566	return ret;
567}
568
569u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
570		    const struct ipz_qp_handle qp_handle,
571		    struct ehca_pfqp *pfqp,
572		    struct hcp_modify_qp_control_block *qqpcb,
573		    struct h_galpa gal)
574{
575	return ehca_plpar_hcall_norets(H_QUERY_QP,
576				       adapter_handle.handle, /* r4 */
577				       qp_handle.handle,      /* r5 */
578				       __pa(qqpcb),	      /* r6 */
579				       0, 0, 0, 0);
580}
581
582u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
583		      struct ehca_qp *qp)
584{
585	u64 ret;
586	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
587
588	ret = hcp_galpas_dtor(&qp->galpas);
589	if (ret) {
590		ehca_gen_err("Could not destruct qp->galpas");
591		return H_RESOURCE;
592	}
593	ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
594				adapter_handle.handle,     /* r4 */
595				/* function code */
596				1,	                   /* r5 */
597				qp->ipz_qp_handle.handle,  /* r6 */
598				0, 0, 0, 0, 0, 0);
599	if (ret == H_HARDWARE)
600		ehca_gen_err("HCA not operational. ret=%lli", ret);
601
602	ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
603				      adapter_handle.handle,     /* r4 */
604				      qp->ipz_qp_handle.handle,  /* r5 */
605				      0, 0, 0, 0, 0);
606
607	if (ret == H_RESOURCE)
608		ehca_gen_err("Resource still in use. ret=%lli", ret);
609
610	return ret;
611}
612
613u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
614		       const struct ipz_qp_handle qp_handle,
615		       struct h_galpa gal,
616		       u32 port)
617{
618	return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
619				       adapter_handle.handle, /* r4 */
620				       qp_handle.handle,      /* r5 */
621				       port,                  /* r6 */
622				       0, 0, 0, 0);
623}
624
625u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
626		       const struct ipz_qp_handle qp_handle,
627		       struct h_galpa gal,
628		       u32 port, u32 * pma_qp_nr,
629		       u32 * bma_qp_nr)
630{
631	u64 ret;
632	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
633
634	ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
635				adapter_handle.handle, /* r4 */
636				qp_handle.handle,      /* r5 */
637				port,	               /* r6 */
638				0, 0, 0, 0, 0, 0);
639	*pma_qp_nr = (u32)outs[0];
640	*bma_qp_nr = (u32)outs[1];
641
642	if (ret == H_ALIAS_EXIST)
643		ehca_gen_err("AQP1 already exists. ret=%lli", ret);
644
645	return ret;
646}
647
648u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
649		       const struct ipz_qp_handle qp_handle,
650		       struct h_galpa gal,
651		       u16 mcg_dlid,
652		       u64 subnet_prefix, u64 interface_id)
653{
654	u64 ret;
655
656	ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
657				      adapter_handle.handle,  /* r4 */
658				      qp_handle.handle,       /* r5 */
659				      mcg_dlid,               /* r6 */
660				      interface_id,           /* r7 */
661				      subnet_prefix,          /* r8 */
662				      0, 0);
663
664	if (ret == H_NOT_ENOUGH_RESOURCES)
665		ehca_gen_err("Not enough resources. ret=%lli", ret);
666
667	return ret;
668}
669
670u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
671		       const struct ipz_qp_handle qp_handle,
672		       struct h_galpa gal,
673		       u16 mcg_dlid,
674		       u64 subnet_prefix, u64 interface_id)
675{
676	return ehca_plpar_hcall_norets(H_DETACH_MCQP,
677				       adapter_handle.handle, /* r4 */
678				       qp_handle.handle,      /* r5 */
679				       mcg_dlid,              /* r6 */
680				       interface_id,          /* r7 */
681				       subnet_prefix,         /* r8 */
682				       0, 0);
683}
684
685u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
686		      struct ehca_cq *cq,
687		      u8 force_flag)
688{
689	u64 ret;
690
691	ret = hcp_galpas_dtor(&cq->galpas);
692	if (ret) {
693		ehca_gen_err("Could not destruct cp->galpas");
694		return H_RESOURCE;
695	}
696
697	ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
698				      adapter_handle.handle,     /* r4 */
699				      cq->ipz_cq_handle.handle,  /* r5 */
700				      force_flag != 0 ? 1L : 0L, /* r6 */
701				      0, 0, 0, 0);
702
703	if (ret == H_RESOURCE)
704		ehca_gen_err("H_FREE_RESOURCE failed ret=%lli ", ret);
705
706	return ret;
707}
708
709u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
710		      struct ehca_eq *eq)
711{
712	u64 ret;
713
714	ret = hcp_galpas_dtor(&eq->galpas);
715	if (ret) {
716		ehca_gen_err("Could not destruct eq->galpas");
717		return H_RESOURCE;
718	}
719
720	ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
721				      adapter_handle.handle,     /* r4 */
722				      eq->ipz_eq_handle.handle,  /* r5 */
723				      0, 0, 0, 0, 0);
724
725	if (ret == H_RESOURCE)
726		ehca_gen_err("Resource in use. ret=%lli ", ret);
727
728	return ret;
729}
730
731u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
732			     const struct ehca_mr *mr,
733			     const u64 vaddr,
734			     const u64 length,
735			     const u32 access_ctrl,
736			     const struct ipz_pd pd,
737			     struct ehca_mr_hipzout_parms *outparms)
738{
739	u64 ret;
740	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
741
742	ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
743				adapter_handle.handle,            /* r4 */
744				5,                                /* r5 */
745				vaddr,                            /* r6 */
746				length,                           /* r7 */
747				(((u64)access_ctrl) << 32ULL),    /* r8 */
748				pd.value,                         /* r9 */
749				0, 0, 0);
750	outparms->handle.handle = outs[0];
751	outparms->lkey = (u32)outs[2];
752	outparms->rkey = (u32)outs[3];
753
754	return ret;
755}
756
757u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
758			     const struct ehca_mr *mr,
759			     const u8 pagesize,
760			     const u8 queue_type,
761			     const u64 logical_address_of_page,
762			     const u64 count)
763{
764	u64 ret;
765
766	if (unlikely(ehca_debug_level >= 3)) {
767		if (count > 1) {
768			u64 *kpage;
769			int i;
770			kpage = __va(logical_address_of_page);
771			for (i = 0; i < count; i++)
772				ehca_gen_dbg("kpage[%d]=%p",
773					     i, (void *)kpage[i]);
774		} else
775			ehca_gen_dbg("kpage=%p",
776				     (void *)logical_address_of_page);
777	}
778
779	if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
780		ehca_gen_err("logical_address_of_page not on a 4k boundary "
781			     "adapter_handle=%llx mr=%p mr_handle=%llx "
782			     "pagesize=%x queue_type=%x "
783			     "logical_address_of_page=%llx count=%llx",
784			     adapter_handle.handle, mr,
785			     mr->ipz_mr_handle.handle, pagesize, queue_type,
786			     logical_address_of_page, count);
787		ret = H_PARAMETER;
788	} else
789		ret = hipz_h_register_rpage(adapter_handle, pagesize,
790					    queue_type,
791					    mr->ipz_mr_handle.handle,
792					    logical_address_of_page, count);
793	return ret;
794}
795
796u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
797		    const struct ehca_mr *mr,
798		    struct ehca_mr_hipzout_parms *outparms)
799{
800	u64 ret;
801	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
802
803	ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
804				adapter_handle.handle,     /* r4 */
805				mr->ipz_mr_handle.handle,  /* r5 */
806				0, 0, 0, 0, 0, 0, 0);
807	outparms->len = outs[0];
808	outparms->vaddr = outs[1];
809	outparms->acl  = outs[4] >> 32;
810	outparms->lkey = (u32)(outs[5] >> 32);
811	outparms->rkey = (u32)(outs[5] & (0xffffffff));
812
813	return ret;
814}
815
816u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
817			    const struct ehca_mr *mr)
818{
819	return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
820				       adapter_handle.handle,    /* r4 */
821				       mr->ipz_mr_handle.handle, /* r5 */
822				       0, 0, 0, 0, 0);
823}
824
825u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
826			  const struct ehca_mr *mr,
827			  const u64 vaddr_in,
828			  const u64 length,
829			  const u32 access_ctrl,
830			  const struct ipz_pd pd,
831			  const u64 mr_addr_cb,
832			  struct ehca_mr_hipzout_parms *outparms)
833{
834	u64 ret;
835	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
836
837	ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
838				adapter_handle.handle,    /* r4 */
839				mr->ipz_mr_handle.handle, /* r5 */
840				vaddr_in,	          /* r6 */
841				length,                   /* r7 */
842				/* r8 */
843				((((u64)access_ctrl) << 32ULL) | pd.value),
844				mr_addr_cb,               /* r9 */
845				0, 0, 0);
846	outparms->vaddr = outs[1];
847	outparms->lkey = (u32)outs[2];
848	outparms->rkey = (u32)outs[3];
849
850	return ret;
851}
852
853u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
854			const struct ehca_mr *mr,
855			const struct ehca_mr *orig_mr,
856			const u64 vaddr_in,
857			const u32 access_ctrl,
858			const struct ipz_pd pd,
859			struct ehca_mr_hipzout_parms *outparms)
860{
861	u64 ret;
862	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
863
864	ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
865				adapter_handle.handle,            /* r4 */
866				orig_mr->ipz_mr_handle.handle,    /* r5 */
867				vaddr_in,                         /* r6 */
868				(((u64)access_ctrl) << 32ULL),    /* r7 */
869				pd.value,                         /* r8 */
870				0, 0, 0, 0);
871	outparms->handle.handle = outs[0];
872	outparms->lkey = (u32)outs[2];
873	outparms->rkey = (u32)outs[3];
874
875	return ret;
876}
877
878u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
879			     const struct ehca_mw *mw,
880			     const struct ipz_pd pd,
881			     struct ehca_mw_hipzout_parms *outparms)
882{
883	u64 ret;
884	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
885
886	ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
887				adapter_handle.handle,      /* r4 */
888				6,                          /* r5 */
889				pd.value,                   /* r6 */
890				0, 0, 0, 0, 0, 0);
891	outparms->handle.handle = outs[0];
892	outparms->rkey = (u32)outs[3];
893
894	return ret;
895}
896
897u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
898		    const struct ehca_mw *mw,
899		    struct ehca_mw_hipzout_parms *outparms)
900{
901	u64 ret;
902	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
903
904	ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
905				adapter_handle.handle,    /* r4 */
906				mw->ipz_mw_handle.handle, /* r5 */
907				0, 0, 0, 0, 0, 0, 0);
908	outparms->rkey = (u32)outs[3];
909
910	return ret;
911}
912
913u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
914			    const struct ehca_mw *mw)
915{
916	return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
917				       adapter_handle.handle,    /* r4 */
918				       mw->ipz_mw_handle.handle, /* r5 */
919				       0, 0, 0, 0, 0);
920}
921
922u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
923		      const u64 ressource_handle,
924		      void *rblock,
925		      unsigned long *byte_count)
926{
927	u64 r_cb = __pa(rblock);
928
929	if (r_cb & (EHCA_PAGESIZE-1)) {
930		ehca_gen_err("rblock not page aligned.");
931		return H_PARAMETER;
932	}
933
934	return ehca_plpar_hcall_norets(H_ERROR_DATA,
935				       adapter_handle.handle,
936				       ressource_handle,
937				       r_cb,
938				       0, 0, 0, 0);
939}
940
941u64 hipz_h_eoi(int irq)
942{
943	unsigned long xirr;
944
945	iosync();
946	xirr = (0xffULL << 24) | irq;
947
948	return plpar_hcall_norets(H_EOI, xirr);
949}
950