RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / drivers / infiniband / hw / ehca / hcp_if.c
blob5766ae3a202995bebb306f4aae1f4580a888109a
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 * Gerd Bayer <gerd.bayer@de.ibm.com>
9 * Waleri Fomin <fomin@de.ibm.com>
11 * Copyright (c) 2005 IBM Corporation
13 * All rights reserved.
15 * This source code is distributed under a dual license of GPL v2.0 and OpenIB
16 * BSD.
18 * OpenIB BSD License
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are met:
23 * Redistributions of source code must retain the above copyright notice, this
24 * list of conditions and the following disclaimer.
26 * Redistributions in binary form must reproduce the above copyright notice,
27 * this list of conditions and the following disclaimer in the documentation
28 * and/or other materials
29 * provided with the distribution.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
35 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
38 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
39 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGE.
44 #include <asm/hvcall.h>
45 #include "ehca_tools.h"
46 #include "hcp_if.h"
47 #include "hcp_phyp.h"
48 #include "hipz_fns.h"
49 #include "ipz_pt_fn.h"
51 #define H_ALL_RES_QP_ENHANCED_OPS EHCA_BMASK_IBM(9, 11)
52 #define H_ALL_RES_QP_PTE_PIN EHCA_BMASK_IBM(12, 12)
53 #define H_ALL_RES_QP_SERVICE_TYPE EHCA_BMASK_IBM(13, 15)
54 #define H_ALL_RES_QP_LL_RQ_CQE_POSTING EHCA_BMASK_IBM(18, 18)
55 #define H_ALL_RES_QP_LL_SQ_CQE_POSTING EHCA_BMASK_IBM(19, 21)
56 #define H_ALL_RES_QP_SIGNALING_TYPE EHCA_BMASK_IBM(22, 23)
57 #define H_ALL_RES_QP_UD_AV_LKEY_CTRL EHCA_BMASK_IBM(31, 31)
58 #define H_ALL_RES_QP_RESOURCE_TYPE EHCA_BMASK_IBM(56, 63)
60 #define H_ALL_RES_QP_MAX_OUTST_SEND_WR EHCA_BMASK_IBM(0, 15)
61 #define H_ALL_RES_QP_MAX_OUTST_RECV_WR EHCA_BMASK_IBM(16, 31)
62 #define H_ALL_RES_QP_MAX_SEND_SGE EHCA_BMASK_IBM(32, 39)
63 #define H_ALL_RES_QP_MAX_RECV_SGE EHCA_BMASK_IBM(40, 47)
65 #define H_ALL_RES_QP_ACT_OUTST_SEND_WR EHCA_BMASK_IBM(16, 31)
66 #define H_ALL_RES_QP_ACT_OUTST_RECV_WR EHCA_BMASK_IBM(48, 63)
67 #define H_ALL_RES_QP_ACT_SEND_SGE EHCA_BMASK_IBM(8, 15)
68 #define H_ALL_RES_QP_ACT_RECV_SGE EHCA_BMASK_IBM(24, 31)
70 #define H_ALL_RES_QP_SQUEUE_SIZE_PAGES EHCA_BMASK_IBM(0, 31)
71 #define H_ALL_RES_QP_RQUEUE_SIZE_PAGES EHCA_BMASK_IBM(32, 63)
73 #define H_MP_INIT_TYPE EHCA_BMASK_IBM(44, 47)
74 #define H_MP_SHUTDOWN EHCA_BMASK_IBM(48, 48)
75 #define H_MP_RESET_QKEY_CTR EHCA_BMASK_IBM(49, 49)
77 /* direct access qp controls */
78 #define DAQP_CTRL_ENABLE 0x01
79 #define DAQP_CTRL_SEND_COMP 0x20
80 #define DAQP_CTRL_RECV_COMP 0x40
82 static u32 get_longbusy_msecs(int longbusy_rc)
84 switch (longbusy_rc) {
85 case H_LONG_BUSY_ORDER_1_MSEC:
86 return 1;
87 case H_LONG_BUSY_ORDER_10_MSEC:
88 return 10;
89 case H_LONG_BUSY_ORDER_100_MSEC:
90 return 100;
91 case H_LONG_BUSY_ORDER_1_SEC:
92 return 1000;
93 case H_LONG_BUSY_ORDER_10_SEC:
94 return 10000;
95 case H_LONG_BUSY_ORDER_100_SEC:
96 return 100000;
97 default:
98 return 1;
102 static long ehca_plpar_hcall_norets(unsigned long opcode,
103 unsigned long arg1,
104 unsigned long arg2,
105 unsigned long arg3,
106 unsigned long arg4,
107 unsigned long arg5,
108 unsigned long arg6,
109 unsigned long arg7)
111 long ret;
112 int i, sleep_msecs;
114 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
115 "arg5=%lx arg6=%lx arg7=%lx",
116 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
118 for (i = 0; i < 5; i++) {
119 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
120 arg5, arg6, arg7);
122 if (H_IS_LONG_BUSY(ret)) {
123 sleep_msecs = get_longbusy_msecs(ret);
124 msleep_interruptible(sleep_msecs);
125 continue;
128 if (ret < H_SUCCESS)
129 ehca_gen_err("opcode=%lx ret=%lx"
130 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
131 " arg5=%lx arg6=%lx arg7=%lx ",
132 opcode, ret,
133 arg1, arg2, arg3, arg4, arg5,
134 arg6, arg7);
136 ehca_gen_dbg("opcode=%lx ret=%lx", opcode, ret);
137 return ret;
141 return H_BUSY;
144 static long ehca_plpar_hcall9(unsigned long opcode,
145 unsigned long *outs, /* array of 9 outputs */
146 unsigned long arg1,
147 unsigned long arg2,
148 unsigned long arg3,
149 unsigned long arg4,
150 unsigned long arg5,
151 unsigned long arg6,
152 unsigned long arg7,
153 unsigned long arg8,
154 unsigned long arg9)
156 long ret;
157 int i, sleep_msecs, lock_is_set = 0;
158 unsigned long flags;
160 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
161 "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
162 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
163 arg8, arg9);
165 for (i = 0; i < 5; i++) {
166 if ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)) {
167 spin_lock_irqsave(&hcall_lock, flags);
168 lock_is_set = 1;
171 ret = plpar_hcall9(opcode, outs,
172 arg1, arg2, arg3, arg4, arg5,
173 arg6, arg7, arg8, arg9);
175 if (lock_is_set)
176 spin_unlock_irqrestore(&hcall_lock, flags);
178 if (H_IS_LONG_BUSY(ret)) {
179 sleep_msecs = get_longbusy_msecs(ret);
180 msleep_interruptible(sleep_msecs);
181 continue;
184 if (ret < H_SUCCESS)
185 ehca_gen_err("opcode=%lx ret=%lx"
186 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
187 " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
188 " arg9=%lx"
189 " out1=%lx out2=%lx out3=%lx out4=%lx"
190 " out5=%lx out6=%lx out7=%lx out8=%lx"
191 " out9=%lx",
192 opcode, ret,
193 arg1, arg2, arg3, arg4, arg5,
194 arg6, arg7, arg8, arg9,
195 outs[0], outs[1], outs[2], outs[3],
196 outs[4], outs[5], outs[6], outs[7],
197 outs[8]);
199 ehca_gen_dbg("opcode=%lx ret=%lx out1=%lx out2=%lx out3=%lx "
200 "out4=%lx out5=%lx out6=%lx out7=%lx out8=%lx "
201 "out9=%lx",
202 opcode, ret, outs[0], outs[1], outs[2], outs[3],
203 outs[4], outs[5], outs[6], outs[7], outs[8]);
204 return ret;
207 return H_BUSY;
210 u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
211 struct ehca_pfeq *pfeq,
212 const u32 neq_control,
213 const u32 number_of_entries,
214 struct ipz_eq_handle *eq_handle,
215 u32 *act_nr_of_entries,
216 u32 *act_pages,
217 u32 *eq_ist)
219 u64 ret;
220 u64 outs[PLPAR_HCALL9_BUFSIZE];
221 u64 allocate_controls;
223 /* resource type */
224 allocate_controls = 3ULL;
226 /* ISN is associated */
227 if (neq_control != 1)
228 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
229 else /* notification event queue */
230 allocate_controls = (1ULL << 63) | allocate_controls;
232 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
233 adapter_handle.handle, /* r4 */
234 allocate_controls, /* r5 */
235 number_of_entries, /* r6 */
236 0, 0, 0, 0, 0, 0);
237 eq_handle->handle = outs[0];
238 *act_nr_of_entries = (u32)outs[3];
239 *act_pages = (u32)outs[4];
240 *eq_ist = (u32)outs[5];
242 if (ret == H_NOT_ENOUGH_RESOURCES)
243 ehca_gen_err("Not enough resource - ret=%lx ", ret);
245 return ret;
248 u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
249 struct ipz_eq_handle eq_handle,
250 const u64 event_mask)
252 return ehca_plpar_hcall_norets(H_RESET_EVENTS,
253 adapter_handle.handle, /* r4 */
254 eq_handle.handle, /* r5 */
255 event_mask, /* r6 */
256 0, 0, 0, 0);
259 u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
260 struct ehca_cq *cq,
261 struct ehca_alloc_cq_parms *param)
263 u64 ret;
264 u64 outs[PLPAR_HCALL9_BUFSIZE];
266 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
267 adapter_handle.handle, /* r4 */
268 2, /* r5 */
269 param->eq_handle.handle, /* r6 */
270 cq->token, /* r7 */
271 param->nr_cqe, /* r8 */
272 0, 0, 0, 0);
273 cq->ipz_cq_handle.handle = outs[0];
274 param->act_nr_of_entries = (u32)outs[3];
275 param->act_pages = (u32)outs[4];
277 if (ret == H_SUCCESS)
278 hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
280 if (ret == H_NOT_ENOUGH_RESOURCES)
281 ehca_gen_err("Not enough resources. ret=%lx", ret);
283 return ret;
286 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
287 struct ehca_qp *qp,
288 struct ehca_alloc_qp_parms *parms)
290 u64 ret;
291 u64 allocate_controls;
292 u64 max_r10_reg;
293 u64 outs[PLPAR_HCALL9_BUFSIZE];
294 u16 max_nr_receive_wqes = qp->init_attr.cap.max_recv_wr + 1;
295 u16 max_nr_send_wqes = qp->init_attr.cap.max_send_wr + 1;
296 int daqp_ctrl = parms->daqp_ctrl;
298 allocate_controls =
299 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS,
300 (daqp_ctrl & DAQP_CTRL_ENABLE) ? 1 : 0)
301 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
302 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
303 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
304 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
305 (daqp_ctrl & DAQP_CTRL_RECV_COMP) ? 1 : 0)
306 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
307 (daqp_ctrl & DAQP_CTRL_SEND_COMP) ? 1 : 0)
308 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
309 parms->ud_av_l_key_ctl)
310 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
312 max_r10_reg =
313 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
314 max_nr_send_wqes)
315 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
316 max_nr_receive_wqes)
317 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
318 parms->max_send_sge)
319 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
320 parms->max_recv_sge);
322 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
323 adapter_handle.handle, /* r4 */
324 allocate_controls, /* r5 */
325 qp->send_cq->ipz_cq_handle.handle,
326 qp->recv_cq->ipz_cq_handle.handle,
327 parms->ipz_eq_handle.handle,
328 ((u64)qp->token << 32) | parms->pd.value,
329 max_r10_reg, /* r10 */
330 parms->ud_av_l_key_ctl, /* r11 */
332 qp->ipz_qp_handle.handle = outs[0];
333 qp->real_qp_num = (u32)outs[1];
334 parms->act_nr_send_wqes =
335 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
336 parms->act_nr_recv_wqes =
337 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
338 parms->act_nr_send_sges =
339 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
340 parms->act_nr_recv_sges =
341 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
342 parms->nr_sq_pages =
343 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
344 parms->nr_rq_pages =
345 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
347 if (ret == H_SUCCESS)
348 hcp_galpas_ctor(&qp->galpas, outs[6], outs[6]);
350 if (ret == H_NOT_ENOUGH_RESOURCES)
351 ehca_gen_err("Not enough resources. ret=%lx", ret);
353 return ret;
356 u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
357 const u8 port_id,
358 struct hipz_query_port *query_port_response_block)
360 u64 ret;
361 u64 r_cb = virt_to_abs(query_port_response_block);
363 if (r_cb & (EHCA_PAGESIZE-1)) {
364 ehca_gen_err("response block not page aligned");
365 return H_PARAMETER;
368 ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
369 adapter_handle.handle, /* r4 */
370 port_id, /* r5 */
371 r_cb, /* r6 */
372 0, 0, 0, 0);
374 if (ehca_debug_level)
375 ehca_dmp(query_port_response_block, 64, "response_block");
377 return ret;
380 u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
381 const u8 port_id, const u32 port_cap,
382 const u8 init_type, const int modify_mask)
384 u64 port_attributes = port_cap;
386 if (modify_mask & IB_PORT_SHUTDOWN)
387 port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
388 if (modify_mask & IB_PORT_INIT_TYPE)
389 port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
390 if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
391 port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
393 return ehca_plpar_hcall_norets(H_MODIFY_PORT,
394 adapter_handle.handle, /* r4 */
395 port_id, /* r5 */
396 port_attributes, /* r6 */
397 0, 0, 0, 0);
400 u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
401 struct hipz_query_hca *query_hca_rblock)
403 u64 r_cb = virt_to_abs(query_hca_rblock);
405 if (r_cb & (EHCA_PAGESIZE-1)) {
406 ehca_gen_err("response_block=%p not page aligned",
407 query_hca_rblock);
408 return H_PARAMETER;
411 return ehca_plpar_hcall_norets(H_QUERY_HCA,
412 adapter_handle.handle, /* r4 */
413 r_cb, /* r5 */
414 0, 0, 0, 0, 0);
417 u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
418 const u8 pagesize,
419 const u8 queue_type,
420 const u64 resource_handle,
421 const u64 logical_address_of_page,
422 u64 count)
424 return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
425 adapter_handle.handle, /* r4 */
426 queue_type | pagesize << 8, /* r5 */
427 resource_handle, /* r6 */
428 logical_address_of_page, /* r7 */
429 count, /* r8 */
430 0, 0);
433 u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
434 const struct ipz_eq_handle eq_handle,
435 struct ehca_pfeq *pfeq,
436 const u8 pagesize,
437 const u8 queue_type,
438 const u64 logical_address_of_page,
439 const u64 count)
441 if (count != 1) {
442 ehca_gen_err("Ppage counter=%lx", count);
443 return H_PARAMETER;
445 return hipz_h_register_rpage(adapter_handle,
446 pagesize,
447 queue_type,
448 eq_handle.handle,
449 logical_address_of_page, count);
452 u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
453 u32 ist)
455 u64 ret;
456 ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
457 adapter_handle.handle, /* r4 */
458 ist, /* r5 */
459 0, 0, 0, 0, 0);
461 if (ret != H_SUCCESS && ret != H_BUSY)
462 ehca_gen_err("Could not query interrupt state.");
464 return ret;
467 u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
468 const struct ipz_cq_handle cq_handle,
469 struct ehca_pfcq *pfcq,
470 const u8 pagesize,
471 const u8 queue_type,
472 const u64 logical_address_of_page,
473 const u64 count,
474 const struct h_galpa gal)
476 if (count != 1) {
477 ehca_gen_err("Page counter=%lx", count);
478 return H_PARAMETER;
481 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
482 cq_handle.handle, logical_address_of_page,
483 count);
486 u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
487 const struct ipz_qp_handle qp_handle,
488 struct ehca_pfqp *pfqp,
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 galpa)
495 if (count != 1) {
496 ehca_gen_err("Page counter=%lx", count);
497 return H_PARAMETER;
500 return hipz_h_register_rpage(adapter_handle,pagesize,queue_type,
501 qp_handle.handle,logical_address_of_page,
502 count);
505 u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
506 const struct ipz_qp_handle qp_handle,
507 struct ehca_pfqp *pfqp,
508 void **log_addr_next_sq_wqe2processed,
509 void **log_addr_next_rq_wqe2processed,
510 int dis_and_get_function_code)
512 u64 ret;
513 u64 outs[PLPAR_HCALL9_BUFSIZE];
515 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
516 adapter_handle.handle, /* r4 */
517 dis_and_get_function_code, /* r5 */
518 qp_handle.handle, /* r6 */
519 0, 0, 0, 0, 0, 0);
520 if (log_addr_next_sq_wqe2processed)
521 *log_addr_next_sq_wqe2processed = (void*)outs[0];
522 if (log_addr_next_rq_wqe2processed)
523 *log_addr_next_rq_wqe2processed = (void*)outs[1];
525 return ret;
528 u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
529 const struct ipz_qp_handle qp_handle,
530 struct ehca_pfqp *pfqp,
531 const u64 update_mask,
532 struct hcp_modify_qp_control_block *mqpcb,
533 struct h_galpa gal)
535 u64 ret;
536 u64 outs[PLPAR_HCALL9_BUFSIZE];
537 ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
538 adapter_handle.handle, /* r4 */
539 qp_handle.handle, /* r5 */
540 update_mask, /* r6 */
541 virt_to_abs(mqpcb), /* r7 */
542 0, 0, 0, 0, 0);
544 if (ret == H_NOT_ENOUGH_RESOURCES)
545 ehca_gen_err("Insufficient resources ret=%lx", ret);
547 return ret;
550 u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
551 const struct ipz_qp_handle qp_handle,
552 struct ehca_pfqp *pfqp,
553 struct hcp_modify_qp_control_block *qqpcb,
554 struct h_galpa gal)
556 return ehca_plpar_hcall_norets(H_QUERY_QP,
557 adapter_handle.handle, /* r4 */
558 qp_handle.handle, /* r5 */
559 virt_to_abs(qqpcb), /* r6 */
560 0, 0, 0, 0);
563 u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
564 struct ehca_qp *qp)
566 u64 ret;
567 u64 outs[PLPAR_HCALL9_BUFSIZE];
569 ret = hcp_galpas_dtor(&qp->galpas);
570 if (ret) {
571 ehca_gen_err("Could not destruct qp->galpas");
572 return H_RESOURCE;
574 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
575 adapter_handle.handle, /* r4 */
576 /* function code */
577 1, /* r5 */
578 qp->ipz_qp_handle.handle, /* r6 */
579 0, 0, 0, 0, 0, 0);
580 if (ret == H_HARDWARE)
581 ehca_gen_err("HCA not operational. ret=%lx", ret);
583 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
584 adapter_handle.handle, /* r4 */
585 qp->ipz_qp_handle.handle, /* r5 */
586 0, 0, 0, 0, 0);
588 if (ret == H_RESOURCE)
589 ehca_gen_err("Resource still in use. ret=%lx", ret);
591 return ret;
594 u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
595 const struct ipz_qp_handle qp_handle,
596 struct h_galpa gal,
597 u32 port)
599 return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
600 adapter_handle.handle, /* r4 */
601 qp_handle.handle, /* r5 */
602 port, /* r6 */
603 0, 0, 0, 0);
606 u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
607 const struct ipz_qp_handle qp_handle,
608 struct h_galpa gal,
609 u32 port, u32 * pma_qp_nr,
610 u32 * bma_qp_nr)
612 u64 ret;
613 u64 outs[PLPAR_HCALL9_BUFSIZE];
615 ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
616 adapter_handle.handle, /* r4 */
617 qp_handle.handle, /* r5 */
618 port, /* r6 */
619 0, 0, 0, 0, 0, 0);
620 *pma_qp_nr = (u32)outs[0];
621 *bma_qp_nr = (u32)outs[1];
623 if (ret == H_ALIAS_EXIST)
624 ehca_gen_err("AQP1 already exists. ret=%lx", ret);
626 return ret;
629 u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
630 const struct ipz_qp_handle qp_handle,
631 struct h_galpa gal,
632 u16 mcg_dlid,
633 u64 subnet_prefix, u64 interface_id)
635 u64 ret;
637 ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
638 adapter_handle.handle, /* r4 */
639 qp_handle.handle, /* r5 */
640 mcg_dlid, /* r6 */
641 interface_id, /* r7 */
642 subnet_prefix, /* r8 */
643 0, 0);
645 if (ret == H_NOT_ENOUGH_RESOURCES)
646 ehca_gen_err("Not enough resources. ret=%lx", ret);
648 return ret;
651 u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
652 const struct ipz_qp_handle qp_handle,
653 struct h_galpa gal,
654 u16 mcg_dlid,
655 u64 subnet_prefix, u64 interface_id)
657 return ehca_plpar_hcall_norets(H_DETACH_MCQP,
658 adapter_handle.handle, /* r4 */
659 qp_handle.handle, /* r5 */
660 mcg_dlid, /* r6 */
661 interface_id, /* r7 */
662 subnet_prefix, /* r8 */
663 0, 0);
666 u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
667 struct ehca_cq *cq,
668 u8 force_flag)
670 u64 ret;
672 ret = hcp_galpas_dtor(&cq->galpas);
673 if (ret) {
674 ehca_gen_err("Could not destruct cp->galpas");
675 return H_RESOURCE;
678 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
679 adapter_handle.handle, /* r4 */
680 cq->ipz_cq_handle.handle, /* r5 */
681 force_flag != 0 ? 1L : 0L, /* r6 */
682 0, 0, 0, 0);
684 if (ret == H_RESOURCE)
685 ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret);
687 return ret;
690 u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
691 struct ehca_eq *eq)
693 u64 ret;
695 ret = hcp_galpas_dtor(&eq->galpas);
696 if (ret) {
697 ehca_gen_err("Could not destruct eq->galpas");
698 return H_RESOURCE;
701 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
702 adapter_handle.handle, /* r4 */
703 eq->ipz_eq_handle.handle, /* r5 */
704 0, 0, 0, 0, 0);
706 if (ret == H_RESOURCE)
707 ehca_gen_err("Resource in use. ret=%lx ", ret);
709 return ret;
712 u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
713 const struct ehca_mr *mr,
714 const u64 vaddr,
715 const u64 length,
716 const u32 access_ctrl,
717 const struct ipz_pd pd,
718 struct ehca_mr_hipzout_parms *outparms)
720 u64 ret;
721 u64 outs[PLPAR_HCALL9_BUFSIZE];
723 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
724 adapter_handle.handle, /* r4 */
725 5, /* r5 */
726 vaddr, /* r6 */
727 length, /* r7 */
728 (((u64)access_ctrl) << 32ULL), /* r8 */
729 pd.value, /* r9 */
730 0, 0, 0);
731 outparms->handle.handle = outs[0];
732 outparms->lkey = (u32)outs[2];
733 outparms->rkey = (u32)outs[3];
735 return ret;
738 u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
739 const struct ehca_mr *mr,
740 const u8 pagesize,
741 const u8 queue_type,
742 const u64 logical_address_of_page,
743 const u64 count)
745 u64 ret;
747 if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
748 ehca_gen_err("logical_address_of_page not on a 4k boundary "
749 "adapter_handle=%lx mr=%p mr_handle=%lx "
750 "pagesize=%x queue_type=%x "
751 "logical_address_of_page=%lx count=%lx",
752 adapter_handle.handle, mr,
753 mr->ipz_mr_handle.handle, pagesize, queue_type,
754 logical_address_of_page, count);
755 ret = H_PARAMETER;
756 } else
757 ret = hipz_h_register_rpage(adapter_handle, pagesize,
758 queue_type,
759 mr->ipz_mr_handle.handle,
760 logical_address_of_page, count);
761 return ret;
764 u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
765 const struct ehca_mr *mr,
766 struct ehca_mr_hipzout_parms *outparms)
768 u64 ret;
769 u64 outs[PLPAR_HCALL9_BUFSIZE];
771 ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
772 adapter_handle.handle, /* r4 */
773 mr->ipz_mr_handle.handle, /* r5 */
774 0, 0, 0, 0, 0, 0, 0);
775 outparms->len = outs[0];
776 outparms->vaddr = outs[1];
777 outparms->acl = outs[4] >> 32;
778 outparms->lkey = (u32)(outs[5] >> 32);
779 outparms->rkey = (u32)(outs[5] & (0xffffffff));
781 return ret;
784 u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
785 const struct ehca_mr *mr)
787 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
788 adapter_handle.handle, /* r4 */
789 mr->ipz_mr_handle.handle, /* r5 */
790 0, 0, 0, 0, 0);
793 u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
794 const struct ehca_mr *mr,
795 const u64 vaddr_in,
796 const u64 length,
797 const u32 access_ctrl,
798 const struct ipz_pd pd,
799 const u64 mr_addr_cb,
800 struct ehca_mr_hipzout_parms *outparms)
802 u64 ret;
803 u64 outs[PLPAR_HCALL9_BUFSIZE];
805 ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
806 adapter_handle.handle, /* r4 */
807 mr->ipz_mr_handle.handle, /* r5 */
808 vaddr_in, /* r6 */
809 length, /* r7 */
810 /* r8 */
811 ((((u64)access_ctrl) << 32ULL) | pd.value),
812 mr_addr_cb, /* r9 */
813 0, 0, 0);
814 outparms->vaddr = outs[1];
815 outparms->lkey = (u32)outs[2];
816 outparms->rkey = (u32)outs[3];
818 return ret;
821 u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
822 const struct ehca_mr *mr,
823 const struct ehca_mr *orig_mr,
824 const u64 vaddr_in,
825 const u32 access_ctrl,
826 const struct ipz_pd pd,
827 struct ehca_mr_hipzout_parms *outparms)
829 u64 ret;
830 u64 outs[PLPAR_HCALL9_BUFSIZE];
832 ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
833 adapter_handle.handle, /* r4 */
834 orig_mr->ipz_mr_handle.handle, /* r5 */
835 vaddr_in, /* r6 */
836 (((u64)access_ctrl) << 32ULL), /* r7 */
837 pd.value, /* r8 */
838 0, 0, 0, 0);
839 outparms->handle.handle = outs[0];
840 outparms->lkey = (u32)outs[2];
841 outparms->rkey = (u32)outs[3];
843 return ret;
846 u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
847 const struct ehca_mw *mw,
848 const struct ipz_pd pd,
849 struct ehca_mw_hipzout_parms *outparms)
851 u64 ret;
852 u64 outs[PLPAR_HCALL9_BUFSIZE];
854 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
855 adapter_handle.handle, /* r4 */
856 6, /* r5 */
857 pd.value, /* r6 */
858 0, 0, 0, 0, 0, 0);
859 outparms->handle.handle = outs[0];
860 outparms->rkey = (u32)outs[3];
862 return ret;
865 u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
866 const struct ehca_mw *mw,
867 struct ehca_mw_hipzout_parms *outparms)
869 u64 ret;
870 u64 outs[PLPAR_HCALL9_BUFSIZE];
872 ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
873 adapter_handle.handle, /* r4 */
874 mw->ipz_mw_handle.handle, /* r5 */
875 0, 0, 0, 0, 0, 0, 0);
876 outparms->rkey = (u32)outs[3];
878 return ret;
881 u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
882 const struct ehca_mw *mw)
884 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
885 adapter_handle.handle, /* r4 */
886 mw->ipz_mw_handle.handle, /* r5 */
887 0, 0, 0, 0, 0);
890 u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
891 const u64 ressource_handle,
892 void *rblock,
893 unsigned long *byte_count)
895 u64 r_cb = virt_to_abs(rblock);
897 if (r_cb & (EHCA_PAGESIZE-1)) {
898 ehca_gen_err("rblock not page aligned.");
899 return H_PARAMETER;
902 return ehca_plpar_hcall_norets(H_ERROR_DATA,
903 adapter_handle.handle,
904 ressource_handle,
905 r_cb,
906 0, 0, 0, 0);