fs: use kmem_cache_zalloc instead
[pv_ops_mirror.git] / drivers / infiniband / hw / ehca / hcp_if.c
blobc16a21374bb5a3c222a73147c28584cb871ab619
1 /*
2 * IBM eServer eHCA Infiniband device driver for Linux on POWER
4 * Firmware Infiniband Interface code for POWER
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>
12 * Copyright (c) 2005 IBM Corporation
14 * All rights reserved.
16 * This source code is distributed under a dual license of GPL v2.0 and OpenIB
17 * BSD.
19 * OpenIB BSD License
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
24 * Redistributions of source code must retain the above copyright notice, this
25 * list of conditions and the following disclaimer.
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.
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.
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"
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)
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)
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)
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)
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)
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)
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"
91 static DEFINE_SPINLOCK(hcall_lock);
93 static u32 get_longbusy_msecs(int longbusy_rc)
95 switch (longbusy_rc) {
96 case H_LONG_BUSY_ORDER_1_MSEC:
97 return 1;
98 case H_LONG_BUSY_ORDER_10_MSEC:
99 return 10;
100 case H_LONG_BUSY_ORDER_100_MSEC:
101 return 100;
102 case H_LONG_BUSY_ORDER_1_SEC:
103 return 1000;
104 case H_LONG_BUSY_ORDER_10_SEC:
105 return 10000;
106 case H_LONG_BUSY_ORDER_100_SEC:
107 return 100000;
108 default:
109 return 1;
113 static long ehca_plpar_hcall_norets(unsigned long opcode,
114 unsigned long arg1,
115 unsigned long arg2,
116 unsigned long arg3,
117 unsigned long arg4,
118 unsigned long arg5,
119 unsigned long arg6,
120 unsigned long arg7)
122 long ret;
123 int i, sleep_msecs, do_lock;
124 unsigned long flags;
126 ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
127 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
129 /* lock H_FREE_RESOURCE(MR) against itself and H_ALLOC_RESOURCE(MR) */
130 if ((opcode == H_FREE_RESOURCE) && (arg7 == 5)) {
131 arg7 = 0; /* better not upset firmware */
132 do_lock = 1;
135 for (i = 0; i < 5; i++) {
136 if (do_lock)
137 spin_lock_irqsave(&hcall_lock, flags);
139 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
140 arg5, arg6, arg7);
142 if (do_lock)
143 spin_unlock_irqrestore(&hcall_lock, flags);
145 if (H_IS_LONG_BUSY(ret)) {
146 sleep_msecs = get_longbusy_msecs(ret);
147 msleep_interruptible(sleep_msecs);
148 continue;
151 if (ret < H_SUCCESS)
152 ehca_gen_err("opcode=%lx ret=%li " HCALL7_REGS_FORMAT,
153 opcode, ret, arg1, arg2, arg3,
154 arg4, arg5, arg6, arg7);
155 else
156 ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
158 return ret;
161 return H_BUSY;
164 static long ehca_plpar_hcall9(unsigned long opcode,
165 unsigned long *outs, /* array of 9 outputs */
166 unsigned long arg1,
167 unsigned long arg2,
168 unsigned long arg3,
169 unsigned long arg4,
170 unsigned long arg5,
171 unsigned long arg6,
172 unsigned long arg7,
173 unsigned long arg8,
174 unsigned long arg9)
176 long ret;
177 int i, sleep_msecs, do_lock;
178 unsigned long flags = 0;
180 ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
181 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
183 /* lock H_ALLOC_RESOURCE(MR) against itself and H_FREE_RESOURCE(MR) */
184 do_lock = ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5));
186 for (i = 0; i < 5; i++) {
187 if (do_lock)
188 spin_lock_irqsave(&hcall_lock, flags);
190 ret = plpar_hcall9(opcode, outs,
191 arg1, arg2, arg3, arg4, arg5,
192 arg6, arg7, arg8, arg9);
194 if (do_lock)
195 spin_unlock_irqrestore(&hcall_lock, flags);
197 if (H_IS_LONG_BUSY(ret)) {
198 sleep_msecs = get_longbusy_msecs(ret);
199 msleep_interruptible(sleep_msecs);
200 continue;
203 if (ret < H_SUCCESS) {
204 ehca_gen_err("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT,
205 opcode, arg1, arg2, arg3, arg4, arg5,
206 arg6, arg7, arg8, arg9);
207 ehca_gen_err("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
208 ret, outs[0], outs[1], outs[2], outs[3],
209 outs[4], outs[5], outs[6], outs[7],
210 outs[8]);
211 } else
212 ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
213 ret, outs[0], outs[1], outs[2], outs[3],
214 outs[4], outs[5], outs[6], outs[7],
215 outs[8]);
216 return ret;
219 return H_BUSY;
222 u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
223 struct ehca_pfeq *pfeq,
224 const u32 neq_control,
225 const u32 number_of_entries,
226 struct ipz_eq_handle *eq_handle,
227 u32 *act_nr_of_entries,
228 u32 *act_pages,
229 u32 *eq_ist)
231 u64 ret;
232 u64 outs[PLPAR_HCALL9_BUFSIZE];
233 u64 allocate_controls;
235 /* resource type */
236 allocate_controls = 3ULL;
238 /* ISN is associated */
239 if (neq_control != 1)
240 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
241 else /* notification event queue */
242 allocate_controls = (1ULL << 63) | allocate_controls;
244 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
245 adapter_handle.handle, /* r4 */
246 allocate_controls, /* r5 */
247 number_of_entries, /* r6 */
248 0, 0, 0, 0, 0, 0);
249 eq_handle->handle = outs[0];
250 *act_nr_of_entries = (u32)outs[3];
251 *act_pages = (u32)outs[4];
252 *eq_ist = (u32)outs[5];
254 if (ret == H_NOT_ENOUGH_RESOURCES)
255 ehca_gen_err("Not enough resource - ret=%li ", ret);
257 return ret;
260 u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
261 struct ipz_eq_handle eq_handle,
262 const u64 event_mask)
264 return ehca_plpar_hcall_norets(H_RESET_EVENTS,
265 adapter_handle.handle, /* r4 */
266 eq_handle.handle, /* r5 */
267 event_mask, /* r6 */
268 0, 0, 0, 0);
271 u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
272 struct ehca_cq *cq,
273 struct ehca_alloc_cq_parms *param)
275 u64 ret;
276 u64 outs[PLPAR_HCALL9_BUFSIZE];
278 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
279 adapter_handle.handle, /* r4 */
280 2, /* r5 */
281 param->eq_handle.handle, /* r6 */
282 cq->token, /* r7 */
283 param->nr_cqe, /* r8 */
284 0, 0, 0, 0);
285 cq->ipz_cq_handle.handle = outs[0];
286 param->act_nr_of_entries = (u32)outs[3];
287 param->act_pages = (u32)outs[4];
289 if (ret == H_SUCCESS)
290 hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
292 if (ret == H_NOT_ENOUGH_RESOURCES)
293 ehca_gen_err("Not enough resources. ret=%li", ret);
295 return ret;
298 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
299 struct ehca_alloc_qp_parms *parms)
301 u64 ret;
302 u64 allocate_controls, max_r10_reg, r11, r12;
303 u64 outs[PLPAR_HCALL9_BUFSIZE];
305 allocate_controls =
306 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
307 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
308 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
309 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
310 | EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage)
311 | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE,
312 parms->squeue.page_size)
313 | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE,
314 parms->rqueue.page_size)
315 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
316 !!(parms->ll_comp_flags & LLQP_RECV_COMP))
317 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
318 !!(parms->ll_comp_flags & LLQP_SEND_COMP))
319 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
320 parms->ud_av_l_key_ctl)
321 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
323 max_r10_reg =
324 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
325 parms->squeue.max_wr + 1)
326 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
327 parms->rqueue.max_wr + 1)
328 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
329 parms->squeue.max_sge)
330 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
331 parms->rqueue.max_sge);
333 r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
335 if (parms->ext_type == EQPT_SRQ)
336 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
337 else
338 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
340 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
341 adapter_handle.handle, /* r4 */
342 allocate_controls, /* r5 */
343 parms->send_cq_handle.handle,
344 parms->recv_cq_handle.handle,
345 parms->eq_handle.handle,
346 ((u64)parms->token << 32) | parms->pd.value,
347 max_r10_reg, r11, r12);
349 parms->qp_handle.handle = outs[0];
350 parms->real_qp_num = (u32)outs[1];
351 parms->squeue.act_nr_wqes =
352 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
353 parms->rqueue.act_nr_wqes =
354 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
355 parms->squeue.act_nr_sges =
356 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
357 parms->rqueue.act_nr_sges =
358 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
359 parms->squeue.queue_size =
360 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
361 parms->rqueue.queue_size =
362 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
364 if (ret == H_SUCCESS)
365 hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
367 if (ret == H_NOT_ENOUGH_RESOURCES)
368 ehca_gen_err("Not enough resources. ret=%li", ret);
370 return ret;
373 u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
374 const u8 port_id,
375 struct hipz_query_port *query_port_response_block)
377 u64 ret;
378 u64 r_cb = virt_to_abs(query_port_response_block);
380 if (r_cb & (EHCA_PAGESIZE-1)) {
381 ehca_gen_err("response block not page aligned");
382 return H_PARAMETER;
385 ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
386 adapter_handle.handle, /* r4 */
387 port_id, /* r5 */
388 r_cb, /* r6 */
389 0, 0, 0, 0);
391 if (ehca_debug_level)
392 ehca_dmp(query_port_response_block, 64, "response_block");
394 return ret;
397 u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
398 const u8 port_id, const u32 port_cap,
399 const u8 init_type, const int modify_mask)
401 u64 port_attributes = port_cap;
403 if (modify_mask & IB_PORT_SHUTDOWN)
404 port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
405 if (modify_mask & IB_PORT_INIT_TYPE)
406 port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
407 if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
408 port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
410 return ehca_plpar_hcall_norets(H_MODIFY_PORT,
411 adapter_handle.handle, /* r4 */
412 port_id, /* r5 */
413 port_attributes, /* r6 */
414 0, 0, 0, 0);
417 u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
418 struct hipz_query_hca *query_hca_rblock)
420 u64 r_cb = virt_to_abs(query_hca_rblock);
422 if (r_cb & (EHCA_PAGESIZE-1)) {
423 ehca_gen_err("response_block=%p not page aligned",
424 query_hca_rblock);
425 return H_PARAMETER;
428 return ehca_plpar_hcall_norets(H_QUERY_HCA,
429 adapter_handle.handle, /* r4 */
430 r_cb, /* r5 */
431 0, 0, 0, 0, 0);
434 u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
435 const u8 pagesize,
436 const u8 queue_type,
437 const u64 resource_handle,
438 const u64 logical_address_of_page,
439 u64 count)
441 return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
442 adapter_handle.handle, /* r4 */
443 (u64)queue_type | ((u64)pagesize) << 8,
444 /* r5 */
445 resource_handle, /* r6 */
446 logical_address_of_page, /* r7 */
447 count, /* r8 */
448 0, 0);
451 u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
452 const struct ipz_eq_handle eq_handle,
453 struct ehca_pfeq *pfeq,
454 const u8 pagesize,
455 const u8 queue_type,
456 const u64 logical_address_of_page,
457 const u64 count)
459 if (count != 1) {
460 ehca_gen_err("Ppage counter=%lx", count);
461 return H_PARAMETER;
463 return hipz_h_register_rpage(adapter_handle,
464 pagesize,
465 queue_type,
466 eq_handle.handle,
467 logical_address_of_page, count);
470 u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
471 u32 ist)
473 u64 ret;
474 ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
475 adapter_handle.handle, /* r4 */
476 ist, /* r5 */
477 0, 0, 0, 0, 0);
479 if (ret != H_SUCCESS && ret != H_BUSY)
480 ehca_gen_err("Could not query interrupt state.");
482 return ret;
485 u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
486 const struct ipz_cq_handle cq_handle,
487 struct ehca_pfcq *pfcq,
488 const u8 pagesize,
489 const u8 queue_type,
490 const u64 logical_address_of_page,
491 const u64 count,
492 const struct h_galpa gal)
494 if (count != 1) {
495 ehca_gen_err("Page counter=%lx", count);
496 return H_PARAMETER;
499 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
500 cq_handle.handle, logical_address_of_page,
501 count);
504 u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
505 const struct ipz_qp_handle qp_handle,
506 struct ehca_pfqp *pfqp,
507 const u8 pagesize,
508 const u8 queue_type,
509 const u64 logical_address_of_page,
510 const u64 count,
511 const struct h_galpa galpa)
513 if (count > 1) {
514 ehca_gen_err("Page counter=%lx", count);
515 return H_PARAMETER;
518 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
519 qp_handle.handle, logical_address_of_page,
520 count);
523 u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
524 const struct ipz_qp_handle qp_handle,
525 struct ehca_pfqp *pfqp,
526 void **log_addr_next_sq_wqe2processed,
527 void **log_addr_next_rq_wqe2processed,
528 int dis_and_get_function_code)
530 u64 ret;
531 u64 outs[PLPAR_HCALL9_BUFSIZE];
533 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
534 adapter_handle.handle, /* r4 */
535 dis_and_get_function_code, /* r5 */
536 qp_handle.handle, /* r6 */
537 0, 0, 0, 0, 0, 0);
538 if (log_addr_next_sq_wqe2processed)
539 *log_addr_next_sq_wqe2processed = (void *)outs[0];
540 if (log_addr_next_rq_wqe2processed)
541 *log_addr_next_rq_wqe2processed = (void *)outs[1];
543 return ret;
546 u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
547 const struct ipz_qp_handle qp_handle,
548 struct ehca_pfqp *pfqp,
549 const u64 update_mask,
550 struct hcp_modify_qp_control_block *mqpcb,
551 struct h_galpa gal)
553 u64 ret;
554 u64 outs[PLPAR_HCALL9_BUFSIZE];
555 ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
556 adapter_handle.handle, /* r4 */
557 qp_handle.handle, /* r5 */
558 update_mask, /* r6 */
559 virt_to_abs(mqpcb), /* r7 */
560 0, 0, 0, 0, 0);
562 if (ret == H_NOT_ENOUGH_RESOURCES)
563 ehca_gen_err("Insufficient resources ret=%li", ret);
565 return ret;
568 u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
569 const struct ipz_qp_handle qp_handle,
570 struct ehca_pfqp *pfqp,
571 struct hcp_modify_qp_control_block *qqpcb,
572 struct h_galpa gal)
574 return ehca_plpar_hcall_norets(H_QUERY_QP,
575 adapter_handle.handle, /* r4 */
576 qp_handle.handle, /* r5 */
577 virt_to_abs(qqpcb), /* r6 */
578 0, 0, 0, 0);
581 u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
582 struct ehca_qp *qp)
584 u64 ret;
585 u64 outs[PLPAR_HCALL9_BUFSIZE];
587 ret = hcp_galpas_dtor(&qp->galpas);
588 if (ret) {
589 ehca_gen_err("Could not destruct qp->galpas");
590 return H_RESOURCE;
592 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
593 adapter_handle.handle, /* r4 */
594 /* function code */
595 1, /* r5 */
596 qp->ipz_qp_handle.handle, /* r6 */
597 0, 0, 0, 0, 0, 0);
598 if (ret == H_HARDWARE)
599 ehca_gen_err("HCA not operational. ret=%li", ret);
601 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
602 adapter_handle.handle, /* r4 */
603 qp->ipz_qp_handle.handle, /* r5 */
604 0, 0, 0, 0, 0);
606 if (ret == H_RESOURCE)
607 ehca_gen_err("Resource still in use. ret=%li", ret);
609 return ret;
612 u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
613 const struct ipz_qp_handle qp_handle,
614 struct h_galpa gal,
615 u32 port)
617 return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
618 adapter_handle.handle, /* r4 */
619 qp_handle.handle, /* r5 */
620 port, /* r6 */
621 0, 0, 0, 0);
624 u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
625 const struct ipz_qp_handle qp_handle,
626 struct h_galpa gal,
627 u32 port, u32 * pma_qp_nr,
628 u32 * bma_qp_nr)
630 u64 ret;
631 u64 outs[PLPAR_HCALL9_BUFSIZE];
633 ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
634 adapter_handle.handle, /* r4 */
635 qp_handle.handle, /* r5 */
636 port, /* r6 */
637 0, 0, 0, 0, 0, 0);
638 *pma_qp_nr = (u32)outs[0];
639 *bma_qp_nr = (u32)outs[1];
641 if (ret == H_ALIAS_EXIST)
642 ehca_gen_err("AQP1 already exists. ret=%li", ret);
644 return ret;
647 u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
648 const struct ipz_qp_handle qp_handle,
649 struct h_galpa gal,
650 u16 mcg_dlid,
651 u64 subnet_prefix, u64 interface_id)
653 u64 ret;
655 ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
656 adapter_handle.handle, /* r4 */
657 qp_handle.handle, /* r5 */
658 mcg_dlid, /* r6 */
659 interface_id, /* r7 */
660 subnet_prefix, /* r8 */
661 0, 0);
663 if (ret == H_NOT_ENOUGH_RESOURCES)
664 ehca_gen_err("Not enough resources. ret=%li", ret);
666 return ret;
669 u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
670 const struct ipz_qp_handle qp_handle,
671 struct h_galpa gal,
672 u16 mcg_dlid,
673 u64 subnet_prefix, u64 interface_id)
675 return ehca_plpar_hcall_norets(H_DETACH_MCQP,
676 adapter_handle.handle, /* r4 */
677 qp_handle.handle, /* r5 */
678 mcg_dlid, /* r6 */
679 interface_id, /* r7 */
680 subnet_prefix, /* r8 */
681 0, 0);
684 u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
685 struct ehca_cq *cq,
686 u8 force_flag)
688 u64 ret;
690 ret = hcp_galpas_dtor(&cq->galpas);
691 if (ret) {
692 ehca_gen_err("Could not destruct cp->galpas");
693 return H_RESOURCE;
696 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
697 adapter_handle.handle, /* r4 */
698 cq->ipz_cq_handle.handle, /* r5 */
699 force_flag != 0 ? 1L : 0L, /* r6 */
700 0, 0, 0, 0);
702 if (ret == H_RESOURCE)
703 ehca_gen_err("H_FREE_RESOURCE failed ret=%li ", ret);
705 return ret;
708 u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
709 struct ehca_eq *eq)
711 u64 ret;
713 ret = hcp_galpas_dtor(&eq->galpas);
714 if (ret) {
715 ehca_gen_err("Could not destruct eq->galpas");
716 return H_RESOURCE;
719 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
720 adapter_handle.handle, /* r4 */
721 eq->ipz_eq_handle.handle, /* r5 */
722 0, 0, 0, 0, 0);
724 if (ret == H_RESOURCE)
725 ehca_gen_err("Resource in use. ret=%li ", ret);
727 return ret;
730 u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
731 const struct ehca_mr *mr,
732 const u64 vaddr,
733 const u64 length,
734 const u32 access_ctrl,
735 const struct ipz_pd pd,
736 struct ehca_mr_hipzout_parms *outparms)
738 u64 ret;
739 u64 outs[PLPAR_HCALL9_BUFSIZE];
741 ehca_gen_dbg("kernel PAGE_SIZE=%x access_ctrl=%016x "
742 "vaddr=%lx length=%lx",
743 (u32)PAGE_SIZE, access_ctrl, vaddr, length);
744 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
745 adapter_handle.handle, /* r4 */
746 5, /* r5 */
747 vaddr, /* r6 */
748 length, /* r7 */
749 (((u64)access_ctrl) << 32ULL), /* r8 */
750 pd.value, /* r9 */
751 0, 0, 0);
752 outparms->handle.handle = outs[0];
753 outparms->lkey = (u32)outs[2];
754 outparms->rkey = (u32)outs[3];
756 return ret;
759 u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
760 const struct ehca_mr *mr,
761 const u8 pagesize,
762 const u8 queue_type,
763 const u64 logical_address_of_page,
764 const u64 count)
766 u64 ret;
768 if (unlikely(ehca_debug_level >= 2)) {
769 if (count > 1) {
770 u64 *kpage;
771 int i;
772 kpage = (u64 *)abs_to_virt(logical_address_of_page);
773 for (i = 0; i < count; i++)
774 ehca_gen_dbg("kpage[%d]=%p",
775 i, (void *)kpage[i]);
776 } else
777 ehca_gen_dbg("kpage=%p",
778 (void *)logical_address_of_page);
781 if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
782 ehca_gen_err("logical_address_of_page not on a 4k boundary "
783 "adapter_handle=%lx mr=%p mr_handle=%lx "
784 "pagesize=%x queue_type=%x "
785 "logical_address_of_page=%lx count=%lx",
786 adapter_handle.handle, mr,
787 mr->ipz_mr_handle.handle, pagesize, queue_type,
788 logical_address_of_page, count);
789 ret = H_PARAMETER;
790 } else
791 ret = hipz_h_register_rpage(adapter_handle, pagesize,
792 queue_type,
793 mr->ipz_mr_handle.handle,
794 logical_address_of_page, count);
795 return ret;
798 u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
799 const struct ehca_mr *mr,
800 struct ehca_mr_hipzout_parms *outparms)
802 u64 ret;
803 u64 outs[PLPAR_HCALL9_BUFSIZE];
805 ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
806 adapter_handle.handle, /* r4 */
807 mr->ipz_mr_handle.handle, /* r5 */
808 0, 0, 0, 0, 0, 0, 0);
809 outparms->len = outs[0];
810 outparms->vaddr = outs[1];
811 outparms->acl = outs[4] >> 32;
812 outparms->lkey = (u32)(outs[5] >> 32);
813 outparms->rkey = (u32)(outs[5] & (0xffffffff));
815 return ret;
818 u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
819 const struct ehca_mr *mr)
821 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
822 adapter_handle.handle, /* r4 */
823 mr->ipz_mr_handle.handle, /* r5 */
824 0, 0, 0, 0, 5);
827 u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
828 const struct ehca_mr *mr,
829 const u64 vaddr_in,
830 const u64 length,
831 const u32 access_ctrl,
832 const struct ipz_pd pd,
833 const u64 mr_addr_cb,
834 struct ehca_mr_hipzout_parms *outparms)
836 u64 ret;
837 u64 outs[PLPAR_HCALL9_BUFSIZE];
839 ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
840 adapter_handle.handle, /* r4 */
841 mr->ipz_mr_handle.handle, /* r5 */
842 vaddr_in, /* r6 */
843 length, /* r7 */
844 /* r8 */
845 ((((u64)access_ctrl) << 32ULL) | pd.value),
846 mr_addr_cb, /* r9 */
847 0, 0, 0);
848 outparms->vaddr = outs[1];
849 outparms->lkey = (u32)outs[2];
850 outparms->rkey = (u32)outs[3];
852 return ret;
855 u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
856 const struct ehca_mr *mr,
857 const struct ehca_mr *orig_mr,
858 const u64 vaddr_in,
859 const u32 access_ctrl,
860 const struct ipz_pd pd,
861 struct ehca_mr_hipzout_parms *outparms)
863 u64 ret;
864 u64 outs[PLPAR_HCALL9_BUFSIZE];
866 ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
867 adapter_handle.handle, /* r4 */
868 orig_mr->ipz_mr_handle.handle, /* r5 */
869 vaddr_in, /* r6 */
870 (((u64)access_ctrl) << 32ULL), /* r7 */
871 pd.value, /* r8 */
872 0, 0, 0, 0);
873 outparms->handle.handle = outs[0];
874 outparms->lkey = (u32)outs[2];
875 outparms->rkey = (u32)outs[3];
877 return ret;
880 u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
881 const struct ehca_mw *mw,
882 const struct ipz_pd pd,
883 struct ehca_mw_hipzout_parms *outparms)
885 u64 ret;
886 u64 outs[PLPAR_HCALL9_BUFSIZE];
888 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
889 adapter_handle.handle, /* r4 */
890 6, /* r5 */
891 pd.value, /* r6 */
892 0, 0, 0, 0, 0, 0);
893 outparms->handle.handle = outs[0];
894 outparms->rkey = (u32)outs[3];
896 return ret;
899 u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
900 const struct ehca_mw *mw,
901 struct ehca_mw_hipzout_parms *outparms)
903 u64 ret;
904 u64 outs[PLPAR_HCALL9_BUFSIZE];
906 ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
907 adapter_handle.handle, /* r4 */
908 mw->ipz_mw_handle.handle, /* r5 */
909 0, 0, 0, 0, 0, 0, 0);
910 outparms->rkey = (u32)outs[3];
912 return ret;
915 u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
916 const struct ehca_mw *mw)
918 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
919 adapter_handle.handle, /* r4 */
920 mw->ipz_mw_handle.handle, /* r5 */
921 0, 0, 0, 0, 0);
924 u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
925 const u64 ressource_handle,
926 void *rblock,
927 unsigned long *byte_count)
929 u64 r_cb = virt_to_abs(rblock);
931 if (r_cb & (EHCA_PAGESIZE-1)) {
932 ehca_gen_err("rblock not page aligned.");
933 return H_PARAMETER;
936 return ehca_plpar_hcall_norets(H_ERROR_DATA,
937 adapter_handle.handle,
938 ressource_handle,
939 r_cb,
940 0, 0, 0, 0);