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
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"
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 static DEFINE_SPINLOCK(hcall_lock);
89 static u32 get_longbusy_msecs(int longbusy_rc)
91 switch (longbusy_rc) {
92 case H_LONG_BUSY_ORDER_1_MSEC:
94 case H_LONG_BUSY_ORDER_10_MSEC:
96 case H_LONG_BUSY_ORDER_100_MSEC:
98 case H_LONG_BUSY_ORDER_1_SEC:
100 case H_LONG_BUSY_ORDER_10_SEC:
102 case H_LONG_BUSY_ORDER_100_SEC:
109 static long ehca_plpar_hcall_norets(unsigned long opcode,
121 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
122 "arg5=%lx arg6=%lx arg7=%lx",
123 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
125 for (i = 0; i < 5; i++) {
126 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
129 if (H_IS_LONG_BUSY(ret)) {
130 sleep_msecs = get_longbusy_msecs(ret);
131 msleep_interruptible(sleep_msecs);
136 ehca_gen_err("opcode=%lx ret=%lx"
137 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
138 " arg5=%lx arg6=%lx arg7=%lx ",
140 arg1, arg2, arg3, arg4, arg5,
143 ehca_gen_dbg("opcode=%lx ret=%lx", opcode, ret);
151 static long ehca_plpar_hcall9(unsigned long opcode,
152 unsigned long *outs, /* array of 9 outputs */
164 int i, sleep_msecs, lock_is_set = 0;
165 unsigned long flags = 0;
167 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
168 "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
169 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
172 for (i = 0; i < 5; i++) {
173 if ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)) {
174 spin_lock_irqsave(&hcall_lock, flags);
178 ret = plpar_hcall9(opcode, outs,
179 arg1, arg2, arg3, arg4, arg5,
180 arg6, arg7, arg8, arg9);
183 spin_unlock_irqrestore(&hcall_lock, flags);
185 if (H_IS_LONG_BUSY(ret)) {
186 sleep_msecs = get_longbusy_msecs(ret);
187 msleep_interruptible(sleep_msecs);
192 ehca_gen_err("opcode=%lx ret=%lx"
193 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
194 " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
196 " out1=%lx out2=%lx out3=%lx out4=%lx"
197 " out5=%lx out6=%lx out7=%lx out8=%lx"
200 arg1, arg2, arg3, arg4, arg5,
201 arg6, arg7, arg8, arg9,
202 outs[0], outs[1], outs[2], outs[3],
203 outs[4], outs[5], outs[6], outs[7],
206 ehca_gen_dbg("opcode=%lx ret=%lx out1=%lx out2=%lx out3=%lx "
207 "out4=%lx out5=%lx out6=%lx out7=%lx out8=%lx "
209 opcode, ret, outs[0], outs[1], outs[2], outs[3],
210 outs[4], outs[5], outs[6], outs[7], outs[8]);
217 u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
218 struct ehca_pfeq *pfeq,
219 const u32 neq_control,
220 const u32 number_of_entries,
221 struct ipz_eq_handle *eq_handle,
222 u32 *act_nr_of_entries,
227 u64 outs[PLPAR_HCALL9_BUFSIZE];
228 u64 allocate_controls;
231 allocate_controls = 3ULL;
233 /* ISN is associated */
234 if (neq_control != 1)
235 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
236 else /* notification event queue */
237 allocate_controls = (1ULL << 63) | allocate_controls;
239 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
240 adapter_handle.handle, /* r4 */
241 allocate_controls, /* r5 */
242 number_of_entries, /* r6 */
244 eq_handle->handle = outs[0];
245 *act_nr_of_entries = (u32)outs[3];
246 *act_pages = (u32)outs[4];
247 *eq_ist = (u32)outs[5];
249 if (ret == H_NOT_ENOUGH_RESOURCES)
250 ehca_gen_err("Not enough resource - ret=%lx ", ret);
255 u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
256 struct ipz_eq_handle eq_handle,
257 const u64 event_mask)
259 return ehca_plpar_hcall_norets(H_RESET_EVENTS,
260 adapter_handle.handle, /* r4 */
261 eq_handle.handle, /* r5 */
266 u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
268 struct ehca_alloc_cq_parms *param)
271 u64 outs[PLPAR_HCALL9_BUFSIZE];
273 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
274 adapter_handle.handle, /* r4 */
276 param->eq_handle.handle, /* r6 */
278 param->nr_cqe, /* r8 */
280 cq->ipz_cq_handle.handle = outs[0];
281 param->act_nr_of_entries = (u32)outs[3];
282 param->act_pages = (u32)outs[4];
284 if (ret == H_SUCCESS)
285 hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
287 if (ret == H_NOT_ENOUGH_RESOURCES)
288 ehca_gen_err("Not enough resources. ret=%lx", ret);
293 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
294 struct ehca_alloc_qp_parms *parms)
297 u64 allocate_controls, max_r10_reg, r11, r12;
298 u64 outs[PLPAR_HCALL9_BUFSIZE];
301 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
302 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
303 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
304 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
305 | EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage)
306 | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE,
307 parms->squeue.page_size)
308 | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE,
309 parms->rqueue.page_size)
310 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
311 !!(parms->ll_comp_flags & LLQP_RECV_COMP))
312 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
313 !!(parms->ll_comp_flags & LLQP_SEND_COMP))
314 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
315 parms->ud_av_l_key_ctl)
316 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
319 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
320 parms->squeue.max_wr + 1)
321 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
322 parms->rqueue.max_wr + 1)
323 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
324 parms->squeue.max_sge)
325 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
326 parms->rqueue.max_sge);
328 r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
330 if (parms->ext_type == EQPT_SRQ)
331 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
333 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
335 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
336 adapter_handle.handle, /* r4 */
337 allocate_controls, /* r5 */
338 parms->send_cq_handle.handle,
339 parms->recv_cq_handle.handle,
340 parms->eq_handle.handle,
341 ((u64)parms->token << 32) | parms->pd.value,
342 max_r10_reg, r11, r12);
344 parms->qp_handle.handle = outs[0];
345 parms->real_qp_num = (u32)outs[1];
346 parms->squeue.act_nr_wqes =
347 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
348 parms->rqueue.act_nr_wqes =
349 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
350 parms->squeue.act_nr_sges =
351 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
352 parms->rqueue.act_nr_sges =
353 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
354 parms->squeue.queue_size =
355 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
356 parms->rqueue.queue_size =
357 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
359 if (ret == H_SUCCESS)
360 hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
362 if (ret == H_NOT_ENOUGH_RESOURCES)
363 ehca_gen_err("Not enough resources. ret=%lx", ret);
368 u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
370 struct hipz_query_port *query_port_response_block)
373 u64 r_cb = virt_to_abs(query_port_response_block);
375 if (r_cb & (EHCA_PAGESIZE-1)) {
376 ehca_gen_err("response block not page aligned");
380 ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
381 adapter_handle.handle, /* r4 */
386 if (ehca_debug_level)
387 ehca_dmp(query_port_response_block, 64, "response_block");
392 u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
393 const u8 port_id, const u32 port_cap,
394 const u8 init_type, const int modify_mask)
396 u64 port_attributes = port_cap;
398 if (modify_mask & IB_PORT_SHUTDOWN)
399 port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
400 if (modify_mask & IB_PORT_INIT_TYPE)
401 port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
402 if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
403 port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
405 return ehca_plpar_hcall_norets(H_MODIFY_PORT,
406 adapter_handle.handle, /* r4 */
408 port_attributes, /* r6 */
412 u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
413 struct hipz_query_hca *query_hca_rblock)
415 u64 r_cb = virt_to_abs(query_hca_rblock);
417 if (r_cb & (EHCA_PAGESIZE-1)) {
418 ehca_gen_err("response_block=%p not page aligned",
423 return ehca_plpar_hcall_norets(H_QUERY_HCA,
424 adapter_handle.handle, /* r4 */
429 u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
432 const u64 resource_handle,
433 const u64 logical_address_of_page,
436 return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
437 adapter_handle.handle, /* r4 */
438 (u64)queue_type | ((u64)pagesize) << 8,
440 resource_handle, /* r6 */
441 logical_address_of_page, /* r7 */
446 u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
447 const struct ipz_eq_handle eq_handle,
448 struct ehca_pfeq *pfeq,
451 const u64 logical_address_of_page,
455 ehca_gen_err("Ppage counter=%lx", count);
458 return hipz_h_register_rpage(adapter_handle,
462 logical_address_of_page, count);
465 u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
469 ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
470 adapter_handle.handle, /* r4 */
474 if (ret != H_SUCCESS && ret != H_BUSY)
475 ehca_gen_err("Could not query interrupt state.");
480 u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
481 const struct ipz_cq_handle cq_handle,
482 struct ehca_pfcq *pfcq,
485 const u64 logical_address_of_page,
487 const struct h_galpa gal)
490 ehca_gen_err("Page counter=%lx", count);
494 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
495 cq_handle.handle, logical_address_of_page,
499 u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
500 const struct ipz_qp_handle qp_handle,
501 struct ehca_pfqp *pfqp,
504 const u64 logical_address_of_page,
506 const struct h_galpa galpa)
509 ehca_gen_err("Page counter=%lx", count);
513 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
514 qp_handle.handle, logical_address_of_page,
518 u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
519 const struct ipz_qp_handle qp_handle,
520 struct ehca_pfqp *pfqp,
521 void **log_addr_next_sq_wqe2processed,
522 void **log_addr_next_rq_wqe2processed,
523 int dis_and_get_function_code)
526 u64 outs[PLPAR_HCALL9_BUFSIZE];
528 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
529 adapter_handle.handle, /* r4 */
530 dis_and_get_function_code, /* r5 */
531 qp_handle.handle, /* r6 */
533 if (log_addr_next_sq_wqe2processed)
534 *log_addr_next_sq_wqe2processed = (void *)outs[0];
535 if (log_addr_next_rq_wqe2processed)
536 *log_addr_next_rq_wqe2processed = (void *)outs[1];
541 u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
542 const struct ipz_qp_handle qp_handle,
543 struct ehca_pfqp *pfqp,
544 const u64 update_mask,
545 struct hcp_modify_qp_control_block *mqpcb,
549 u64 outs[PLPAR_HCALL9_BUFSIZE];
550 ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
551 adapter_handle.handle, /* r4 */
552 qp_handle.handle, /* r5 */
553 update_mask, /* r6 */
554 virt_to_abs(mqpcb), /* r7 */
557 if (ret == H_NOT_ENOUGH_RESOURCES)
558 ehca_gen_err("Insufficient resources ret=%lx", ret);
563 u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
564 const struct ipz_qp_handle qp_handle,
565 struct ehca_pfqp *pfqp,
566 struct hcp_modify_qp_control_block *qqpcb,
569 return ehca_plpar_hcall_norets(H_QUERY_QP,
570 adapter_handle.handle, /* r4 */
571 qp_handle.handle, /* r5 */
572 virt_to_abs(qqpcb), /* r6 */
576 u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
580 u64 outs[PLPAR_HCALL9_BUFSIZE];
582 ret = hcp_galpas_dtor(&qp->galpas);
584 ehca_gen_err("Could not destruct qp->galpas");
587 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
588 adapter_handle.handle, /* r4 */
591 qp->ipz_qp_handle.handle, /* r6 */
593 if (ret == H_HARDWARE)
594 ehca_gen_err("HCA not operational. ret=%lx", ret);
596 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
597 adapter_handle.handle, /* r4 */
598 qp->ipz_qp_handle.handle, /* r5 */
601 if (ret == H_RESOURCE)
602 ehca_gen_err("Resource still in use. ret=%lx", ret);
607 u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
608 const struct ipz_qp_handle qp_handle,
612 return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
613 adapter_handle.handle, /* r4 */
614 qp_handle.handle, /* r5 */
619 u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
620 const struct ipz_qp_handle qp_handle,
622 u32 port, u32 * pma_qp_nr,
626 u64 outs[PLPAR_HCALL9_BUFSIZE];
628 ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
629 adapter_handle.handle, /* r4 */
630 qp_handle.handle, /* r5 */
633 *pma_qp_nr = (u32)outs[0];
634 *bma_qp_nr = (u32)outs[1];
636 if (ret == H_ALIAS_EXIST)
637 ehca_gen_err("AQP1 already exists. ret=%lx", ret);
642 u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
643 const struct ipz_qp_handle qp_handle,
646 u64 subnet_prefix, u64 interface_id)
650 ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
651 adapter_handle.handle, /* r4 */
652 qp_handle.handle, /* r5 */
654 interface_id, /* r7 */
655 subnet_prefix, /* r8 */
658 if (ret == H_NOT_ENOUGH_RESOURCES)
659 ehca_gen_err("Not enough resources. ret=%lx", ret);
664 u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
665 const struct ipz_qp_handle qp_handle,
668 u64 subnet_prefix, u64 interface_id)
670 return ehca_plpar_hcall_norets(H_DETACH_MCQP,
671 adapter_handle.handle, /* r4 */
672 qp_handle.handle, /* r5 */
674 interface_id, /* r7 */
675 subnet_prefix, /* r8 */
679 u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
685 ret = hcp_galpas_dtor(&cq->galpas);
687 ehca_gen_err("Could not destruct cp->galpas");
691 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
692 adapter_handle.handle, /* r4 */
693 cq->ipz_cq_handle.handle, /* r5 */
694 force_flag != 0 ? 1L : 0L, /* r6 */
697 if (ret == H_RESOURCE)
698 ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret);
703 u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
708 ret = hcp_galpas_dtor(&eq->galpas);
710 ehca_gen_err("Could not destruct eq->galpas");
714 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
715 adapter_handle.handle, /* r4 */
716 eq->ipz_eq_handle.handle, /* r5 */
719 if (ret == H_RESOURCE)
720 ehca_gen_err("Resource in use. ret=%lx ", ret);
725 u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
726 const struct ehca_mr *mr,
729 const u32 access_ctrl,
730 const struct ipz_pd pd,
731 struct ehca_mr_hipzout_parms *outparms)
734 u64 outs[PLPAR_HCALL9_BUFSIZE];
736 ehca_gen_dbg("kernel PAGE_SIZE=%x access_ctrl=%016x "
737 "vaddr=%lx length=%lx",
738 (u32)PAGE_SIZE, access_ctrl, vaddr, length);
739 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
740 adapter_handle.handle, /* r4 */
744 (((u64)access_ctrl) << 32ULL), /* r8 */
747 outparms->handle.handle = outs[0];
748 outparms->lkey = (u32)outs[2];
749 outparms->rkey = (u32)outs[3];
754 u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
755 const struct ehca_mr *mr,
758 const u64 logical_address_of_page,
763 if (unlikely(ehca_debug_level >= 2)) {
767 kpage = (u64 *)abs_to_virt(logical_address_of_page);
768 for (i = 0; i < count; i++)
769 ehca_gen_dbg("kpage[%d]=%p",
770 i, (void *)kpage[i]);
772 ehca_gen_dbg("kpage=%p",
773 (void *)logical_address_of_page);
776 if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
777 ehca_gen_err("logical_address_of_page not on a 4k boundary "
778 "adapter_handle=%lx mr=%p mr_handle=%lx "
779 "pagesize=%x queue_type=%x "
780 "logical_address_of_page=%lx count=%lx",
781 adapter_handle.handle, mr,
782 mr->ipz_mr_handle.handle, pagesize, queue_type,
783 logical_address_of_page, count);
786 ret = hipz_h_register_rpage(adapter_handle, pagesize,
788 mr->ipz_mr_handle.handle,
789 logical_address_of_page, count);
793 u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
794 const struct ehca_mr *mr,
795 struct ehca_mr_hipzout_parms *outparms)
798 u64 outs[PLPAR_HCALL9_BUFSIZE];
800 ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
801 adapter_handle.handle, /* r4 */
802 mr->ipz_mr_handle.handle, /* r5 */
803 0, 0, 0, 0, 0, 0, 0);
804 outparms->len = outs[0];
805 outparms->vaddr = outs[1];
806 outparms->acl = outs[4] >> 32;
807 outparms->lkey = (u32)(outs[5] >> 32);
808 outparms->rkey = (u32)(outs[5] & (0xffffffff));
813 u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
814 const struct ehca_mr *mr)
816 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
817 adapter_handle.handle, /* r4 */
818 mr->ipz_mr_handle.handle, /* r5 */
822 u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
823 const struct ehca_mr *mr,
826 const u32 access_ctrl,
827 const struct ipz_pd pd,
828 const u64 mr_addr_cb,
829 struct ehca_mr_hipzout_parms *outparms)
832 u64 outs[PLPAR_HCALL9_BUFSIZE];
834 ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
835 adapter_handle.handle, /* r4 */
836 mr->ipz_mr_handle.handle, /* r5 */
840 ((((u64)access_ctrl) << 32ULL) | pd.value),
843 outparms->vaddr = outs[1];
844 outparms->lkey = (u32)outs[2];
845 outparms->rkey = (u32)outs[3];
850 u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
851 const struct ehca_mr *mr,
852 const struct ehca_mr *orig_mr,
854 const u32 access_ctrl,
855 const struct ipz_pd pd,
856 struct ehca_mr_hipzout_parms *outparms)
859 u64 outs[PLPAR_HCALL9_BUFSIZE];
861 ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
862 adapter_handle.handle, /* r4 */
863 orig_mr->ipz_mr_handle.handle, /* r5 */
865 (((u64)access_ctrl) << 32ULL), /* r7 */
868 outparms->handle.handle = outs[0];
869 outparms->lkey = (u32)outs[2];
870 outparms->rkey = (u32)outs[3];
875 u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
876 const struct ehca_mw *mw,
877 const struct ipz_pd pd,
878 struct ehca_mw_hipzout_parms *outparms)
881 u64 outs[PLPAR_HCALL9_BUFSIZE];
883 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
884 adapter_handle.handle, /* r4 */
888 outparms->handle.handle = outs[0];
889 outparms->rkey = (u32)outs[3];
894 u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
895 const struct ehca_mw *mw,
896 struct ehca_mw_hipzout_parms *outparms)
899 u64 outs[PLPAR_HCALL9_BUFSIZE];
901 ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
902 adapter_handle.handle, /* r4 */
903 mw->ipz_mw_handle.handle, /* r5 */
904 0, 0, 0, 0, 0, 0, 0);
905 outparms->rkey = (u32)outs[3];
910 u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
911 const struct ehca_mw *mw)
913 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
914 adapter_handle.handle, /* r4 */
915 mw->ipz_mw_handle.handle, /* r5 */
919 u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
920 const u64 ressource_handle,
922 unsigned long *byte_count)
924 u64 r_cb = virt_to_abs(rblock);
926 if (r_cb & (EHCA_PAGESIZE-1)) {
927 ehca_gen_err("rblock not page aligned.");
931 return ehca_plpar_hcall_norets(H_ERROR_DATA,
932 adapter_handle.handle,