blob: 3fb46e67df87fe378683315770f61c50ff97a9ba [file] [log] [blame]
Heiko J Schickfab97222006-09-22 15:22:22 -07001/*
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 * Gerd Bayer <gerd.bayer@de.ibm.com>
9 * Waleri Fomin <fomin@de.ibm.com>
10 *
11 * Copyright (c) 2005 IBM Corporation
12 *
13 * All rights reserved.
14 *
15 * This source code is distributed under a dual license of GPL v2.0 and OpenIB
16 * BSD.
17 *
18 * OpenIB BSD License
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are met:
22 *
23 * Redistributions of source code must retain the above copyright notice, this
24 * list of conditions and the following disclaimer.
25 *
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.
30 *
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.
42 */
43
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"
50
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)
59
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)
64
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)
69
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)
72
73/* direct access qp controls */
74#define DAQP_CTRL_ENABLE 0x01
75#define DAQP_CTRL_SEND_COMP 0x20
76#define DAQP_CTRL_RECV_COMP 0x40
77
78static u32 get_longbusy_msecs(int longbusy_rc)
79{
80 switch (longbusy_rc) {
81 case H_LONG_BUSY_ORDER_1_MSEC:
82 return 1;
83 case H_LONG_BUSY_ORDER_10_MSEC:
84 return 10;
85 case H_LONG_BUSY_ORDER_100_MSEC:
86 return 100;
87 case H_LONG_BUSY_ORDER_1_SEC:
88 return 1000;
89 case H_LONG_BUSY_ORDER_10_SEC:
90 return 10000;
91 case H_LONG_BUSY_ORDER_100_SEC:
92 return 100000;
93 default:
94 return 1;
95 }
96}
97
98static long ehca_plpar_hcall_norets(unsigned long opcode,
99 unsigned long arg1,
100 unsigned long arg2,
101 unsigned long arg3,
102 unsigned long arg4,
103 unsigned long arg5,
104 unsigned long arg6,
105 unsigned long arg7)
106{
107 long ret;
108 int i, sleep_msecs;
109
110 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
111 "arg5=%lx arg6=%lx arg7=%lx",
112 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
113
114 for (i = 0; i < 5; i++) {
115 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
116 arg5, arg6, arg7);
117
118 if (H_IS_LONG_BUSY(ret)) {
119 sleep_msecs = get_longbusy_msecs(ret);
120 msleep_interruptible(sleep_msecs);
121 continue;
122 }
123
124 if (ret < H_SUCCESS)
125 ehca_gen_err("opcode=%lx ret=%lx"
126 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
127 " arg5=%lx arg6=%lx arg7=%lx ",
128 opcode, ret,
129 arg1, arg2, arg3, arg4, arg5,
130 arg6, arg7);
131
132 ehca_gen_dbg("opcode=%lx ret=%lx", opcode, ret);
133 return ret;
134
135 }
136
137 return H_BUSY;
138}
139
140static long ehca_plpar_hcall9(unsigned long opcode,
141 unsigned long *outs, /* array of 9 outputs */
142 unsigned long arg1,
143 unsigned long arg2,
144 unsigned long arg3,
145 unsigned long arg4,
146 unsigned long arg5,
147 unsigned long arg6,
148 unsigned long arg7,
149 unsigned long arg8,
150 unsigned long arg9)
151{
152 long ret;
153 int i, sleep_msecs;
154
155 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
156 "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
157 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
158 arg8, arg9);
159
160 for (i = 0; i < 5; i++) {
161 ret = plpar_hcall9(opcode, outs,
162 arg1, arg2, arg3, arg4, arg5,
163 arg6, arg7, arg8, arg9);
164
165 if (H_IS_LONG_BUSY(ret)) {
166 sleep_msecs = get_longbusy_msecs(ret);
167 msleep_interruptible(sleep_msecs);
168 continue;
169 }
170
171 if (ret < H_SUCCESS)
172 ehca_gen_err("opcode=%lx ret=%lx"
173 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
174 " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
175 " arg9=%lx"
176 " out1=%lx out2=%lx out3=%lx out4=%lx"
177 " out5=%lx out6=%lx out7=%lx out8=%lx"
178 " out9=%lx",
179 opcode, ret,
180 arg1, arg2, arg3, arg4, arg5,
181 arg6, arg7, arg8, arg9,
182 outs[0], outs[1], outs[2], outs[3],
183 outs[4], outs[5], outs[6], outs[7],
184 outs[8]);
185
186 ehca_gen_dbg("opcode=%lx ret=%lx out1=%lx out2=%lx out3=%lx "
187 "out4=%lx out5=%lx out6=%lx out7=%lx out8=%lx "
188 "out9=%lx",
189 opcode, ret, outs[0], outs[1], outs[2], outs[3],
190 outs[4], outs[5], outs[6], outs[7], outs[8]);
191 return ret;
192
193 }
194
195 return H_BUSY;
196}
197u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
198 struct ehca_pfeq *pfeq,
199 const u32 neq_control,
200 const u32 number_of_entries,
201 struct ipz_eq_handle *eq_handle,
202 u32 *act_nr_of_entries,
203 u32 *act_pages,
204 u32 *eq_ist)
205{
206 u64 ret;
207 u64 outs[PLPAR_HCALL9_BUFSIZE];
208 u64 allocate_controls;
209
210 /* resource type */
211 allocate_controls = 3ULL;
212
213 /* ISN is associated */
214 if (neq_control != 1)
215 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
216 else /* notification event queue */
217 allocate_controls = (1ULL << 63) | allocate_controls;
218
219 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
220 adapter_handle.handle, /* r4 */
221 allocate_controls, /* r5 */
222 number_of_entries, /* r6 */
223 0, 0, 0, 0, 0, 0);
224 eq_handle->handle = outs[0];
225 *act_nr_of_entries = (u32)outs[3];
226 *act_pages = (u32)outs[4];
227 *eq_ist = (u32)outs[5];
228
229 if (ret == H_NOT_ENOUGH_RESOURCES)
230 ehca_gen_err("Not enough resource - ret=%lx ", ret);
231
232 return ret;
233}
234
235u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
236 struct ipz_eq_handle eq_handle,
237 const u64 event_mask)
238{
239 return ehca_plpar_hcall_norets(H_RESET_EVENTS,
240 adapter_handle.handle, /* r4 */
241 eq_handle.handle, /* r5 */
242 event_mask, /* r6 */
243 0, 0, 0, 0);
244}
245
246u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
247 struct ehca_cq *cq,
248 struct ehca_alloc_cq_parms *param)
249{
250 u64 ret;
251 u64 outs[PLPAR_HCALL9_BUFSIZE];
252
253 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
254 adapter_handle.handle, /* r4 */
255 2, /* r5 */
256 param->eq_handle.handle, /* r6 */
257 cq->token, /* r7 */
258 param->nr_cqe, /* r8 */
259 0, 0, 0, 0);
260 cq->ipz_cq_handle.handle = outs[0];
261 param->act_nr_of_entries = (u32)outs[3];
262 param->act_pages = (u32)outs[4];
263
264 if (ret == H_SUCCESS)
265 hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
266
267 if (ret == H_NOT_ENOUGH_RESOURCES)
268 ehca_gen_err("Not enough resources. ret=%lx", ret);
269
270 return ret;
271}
272
273u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
274 struct ehca_qp *qp,
275 struct ehca_alloc_qp_parms *parms)
276{
277 u64 ret;
278 u64 allocate_controls;
279 u64 max_r10_reg;
280 u64 outs[PLPAR_HCALL9_BUFSIZE];
281 u16 max_nr_receive_wqes = qp->init_attr.cap.max_recv_wr + 1;
282 u16 max_nr_send_wqes = qp->init_attr.cap.max_send_wr + 1;
283 int daqp_ctrl = parms->daqp_ctrl;
284
285 allocate_controls =
286 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS,
287 (daqp_ctrl & DAQP_CTRL_ENABLE) ? 1 : 0)
288 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
289 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
290 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
291 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
292 (daqp_ctrl & DAQP_CTRL_RECV_COMP) ? 1 : 0)
293 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
294 (daqp_ctrl & DAQP_CTRL_SEND_COMP) ? 1 : 0)
295 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
296 parms->ud_av_l_key_ctl)
297 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
298
299 max_r10_reg =
300 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
301 max_nr_send_wqes)
302 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
303 max_nr_receive_wqes)
304 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
305 parms->max_send_sge)
306 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
307 parms->max_recv_sge);
308
309 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
310 adapter_handle.handle, /* r4 */
311 allocate_controls, /* r5 */
312 qp->send_cq->ipz_cq_handle.handle,
313 qp->recv_cq->ipz_cq_handle.handle,
314 parms->ipz_eq_handle.handle,
315 ((u64)qp->token << 32) | parms->pd.value,
316 max_r10_reg, /* r10 */
317 parms->ud_av_l_key_ctl, /* r11 */
318 0);
319 qp->ipz_qp_handle.handle = outs[0];
320 qp->real_qp_num = (u32)outs[1];
321 parms->act_nr_send_sges =
322 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
323 parms->act_nr_recv_wqes =
324 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
325 parms->act_nr_send_sges =
326 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
327 parms->act_nr_recv_sges =
328 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
329 parms->nr_sq_pages =
330 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
331 parms->nr_rq_pages =
332 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
333
334 if (ret == H_SUCCESS)
335 hcp_galpas_ctor(&qp->galpas, outs[6], outs[6]);
336
337 if (ret == H_NOT_ENOUGH_RESOURCES)
338 ehca_gen_err("Not enough resources. ret=%lx", ret);
339
340 return ret;
341}
342
343u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
344 const u8 port_id,
345 struct hipz_query_port *query_port_response_block)
346{
347 u64 ret;
348 u64 r_cb = virt_to_abs(query_port_response_block);
349
350 if (r_cb & (EHCA_PAGESIZE-1)) {
351 ehca_gen_err("response block not page aligned");
352 return H_PARAMETER;
353 }
354
355 ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
356 adapter_handle.handle, /* r4 */
357 port_id, /* r5 */
358 r_cb, /* r6 */
359 0, 0, 0, 0);
360
361 if (ehca_debug_level)
362 ehca_dmp(query_port_response_block, 64, "response_block");
363
364 return ret;
365}
366
367u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
368 struct hipz_query_hca *query_hca_rblock)
369{
370 u64 r_cb = virt_to_abs(query_hca_rblock);
371
372 if (r_cb & (EHCA_PAGESIZE-1)) {
373 ehca_gen_err("response_block=%p not page aligned",
374 query_hca_rblock);
375 return H_PARAMETER;
376 }
377
378 return ehca_plpar_hcall_norets(H_QUERY_HCA,
379 adapter_handle.handle, /* r4 */
380 r_cb, /* r5 */
381 0, 0, 0, 0, 0);
382}
383
384u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
385 const u8 pagesize,
386 const u8 queue_type,
387 const u64 resource_handle,
388 const u64 logical_address_of_page,
389 u64 count)
390{
391 return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
392 adapter_handle.handle, /* r4 */
393 queue_type | pagesize << 8, /* r5 */
394 resource_handle, /* r6 */
395 logical_address_of_page, /* r7 */
396 count, /* r8 */
397 0, 0);
398}
399
400u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
401 const struct ipz_eq_handle eq_handle,
402 struct ehca_pfeq *pfeq,
403 const u8 pagesize,
404 const u8 queue_type,
405 const u64 logical_address_of_page,
406 const u64 count)
407{
408 if (count != 1) {
409 ehca_gen_err("Ppage counter=%lx", count);
410 return H_PARAMETER;
411 }
412 return hipz_h_register_rpage(adapter_handle,
413 pagesize,
414 queue_type,
415 eq_handle.handle,
416 logical_address_of_page, count);
417}
418
419u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
420 u32 ist)
421{
422 u64 ret;
423 ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
424 adapter_handle.handle, /* r4 */
425 ist, /* r5 */
426 0, 0, 0, 0, 0);
427
428 if (ret != H_SUCCESS && ret != H_BUSY)
429 ehca_gen_err("Could not query interrupt state.");
430
431 return ret;
432}
433
434u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
435 const struct ipz_cq_handle cq_handle,
436 struct ehca_pfcq *pfcq,
437 const u8 pagesize,
438 const u8 queue_type,
439 const u64 logical_address_of_page,
440 const u64 count,
441 const struct h_galpa gal)
442{
443 if (count != 1) {
444 ehca_gen_err("Page counter=%lx", count);
445 return H_PARAMETER;
446 }
447
448 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
449 cq_handle.handle, logical_address_of_page,
450 count);
451}
452
453u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
454 const struct ipz_qp_handle qp_handle,
455 struct ehca_pfqp *pfqp,
456 const u8 pagesize,
457 const u8 queue_type,
458 const u64 logical_address_of_page,
459 const u64 count,
460 const struct h_galpa galpa)
461{
462 if (count != 1) {
463 ehca_gen_err("Page counter=%lx", count);
464 return H_PARAMETER;
465 }
466
467 return hipz_h_register_rpage(adapter_handle,pagesize,queue_type,
468 qp_handle.handle,logical_address_of_page,
469 count);
470}
471
472u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
473 const struct ipz_qp_handle qp_handle,
474 struct ehca_pfqp *pfqp,
475 void **log_addr_next_sq_wqe2processed,
476 void **log_addr_next_rq_wqe2processed,
477 int dis_and_get_function_code)
478{
479 u64 ret;
480 u64 outs[PLPAR_HCALL9_BUFSIZE];
481
482 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
483 adapter_handle.handle, /* r4 */
484 dis_and_get_function_code, /* r5 */
485 qp_handle.handle, /* r6 */
486 0, 0, 0, 0, 0, 0);
487 if (log_addr_next_sq_wqe2processed)
488 *log_addr_next_sq_wqe2processed = (void*)outs[0];
489 if (log_addr_next_rq_wqe2processed)
490 *log_addr_next_rq_wqe2processed = (void*)outs[1];
491
492 return ret;
493}
494
495u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
496 const struct ipz_qp_handle qp_handle,
497 struct ehca_pfqp *pfqp,
498 const u64 update_mask,
499 struct hcp_modify_qp_control_block *mqpcb,
500 struct h_galpa gal)
501{
502 u64 ret;
503 u64 outs[PLPAR_HCALL9_BUFSIZE];
504 ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
505 adapter_handle.handle, /* r4 */
506 qp_handle.handle, /* r5 */
507 update_mask, /* r6 */
508 virt_to_abs(mqpcb), /* r7 */
509 0, 0, 0, 0, 0);
510
511 if (ret == H_NOT_ENOUGH_RESOURCES)
512 ehca_gen_err("Insufficient resources ret=%lx", ret);
513
514 return ret;
515}
516
517u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
518 const struct ipz_qp_handle qp_handle,
519 struct ehca_pfqp *pfqp,
520 struct hcp_modify_qp_control_block *qqpcb,
521 struct h_galpa gal)
522{
523 return ehca_plpar_hcall_norets(H_QUERY_QP,
524 adapter_handle.handle, /* r4 */
525 qp_handle.handle, /* r5 */
526 virt_to_abs(qqpcb), /* r6 */
527 0, 0, 0, 0);
528}
529
530u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
531 struct ehca_qp *qp)
532{
533 u64 ret;
534 u64 outs[PLPAR_HCALL9_BUFSIZE];
535
536 ret = hcp_galpas_dtor(&qp->galpas);
537 if (ret) {
538 ehca_gen_err("Could not destruct qp->galpas");
539 return H_RESOURCE;
540 }
541 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
542 adapter_handle.handle, /* r4 */
543 /* function code */
544 1, /* r5 */
545 qp->ipz_qp_handle.handle, /* r6 */
546 0, 0, 0, 0, 0, 0);
547 if (ret == H_HARDWARE)
548 ehca_gen_err("HCA not operational. ret=%lx", ret);
549
550 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
551 adapter_handle.handle, /* r4 */
552 qp->ipz_qp_handle.handle, /* r5 */
553 0, 0, 0, 0, 0);
554
555 if (ret == H_RESOURCE)
556 ehca_gen_err("Resource still in use. ret=%lx", ret);
557
558 return ret;
559}
560
561u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
562 const struct ipz_qp_handle qp_handle,
563 struct h_galpa gal,
564 u32 port)
565{
566 return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
567 adapter_handle.handle, /* r4 */
568 qp_handle.handle, /* r5 */
569 port, /* r6 */
570 0, 0, 0, 0);
571}
572
573u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
574 const struct ipz_qp_handle qp_handle,
575 struct h_galpa gal,
576 u32 port, u32 * pma_qp_nr,
577 u32 * bma_qp_nr)
578{
579 u64 ret;
580 u64 outs[PLPAR_HCALL9_BUFSIZE];
581
582 ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
583 adapter_handle.handle, /* r4 */
584 qp_handle.handle, /* r5 */
585 port, /* r6 */
586 0, 0, 0, 0, 0, 0);
587 *pma_qp_nr = (u32)outs[0];
588 *bma_qp_nr = (u32)outs[1];
589
590 if (ret == H_ALIAS_EXIST)
591 ehca_gen_err("AQP1 already exists. ret=%lx", ret);
592
593 return ret;
594}
595
596u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
597 const struct ipz_qp_handle qp_handle,
598 struct h_galpa gal,
599 u16 mcg_dlid,
600 u64 subnet_prefix, u64 interface_id)
601{
602 u64 ret;
603
604 ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
605 adapter_handle.handle, /* r4 */
606 qp_handle.handle, /* r5 */
607 mcg_dlid, /* r6 */
608 interface_id, /* r7 */
609 subnet_prefix, /* r8 */
610 0, 0);
611
612 if (ret == H_NOT_ENOUGH_RESOURCES)
613 ehca_gen_err("Not enough resources. ret=%lx", ret);
614
615 return ret;
616}
617
618u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
619 const struct ipz_qp_handle qp_handle,
620 struct h_galpa gal,
621 u16 mcg_dlid,
622 u64 subnet_prefix, u64 interface_id)
623{
624 return ehca_plpar_hcall_norets(H_DETACH_MCQP,
625 adapter_handle.handle, /* r4 */
626 qp_handle.handle, /* r5 */
627 mcg_dlid, /* r6 */
628 interface_id, /* r7 */
629 subnet_prefix, /* r8 */
630 0, 0);
631}
632
633u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
634 struct ehca_cq *cq,
635 u8 force_flag)
636{
637 u64 ret;
638
639 ret = hcp_galpas_dtor(&cq->galpas);
640 if (ret) {
641 ehca_gen_err("Could not destruct cp->galpas");
642 return H_RESOURCE;
643 }
644
645 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
646 adapter_handle.handle, /* r4 */
647 cq->ipz_cq_handle.handle, /* r5 */
648 force_flag != 0 ? 1L : 0L, /* r6 */
649 0, 0, 0, 0);
650
651 if (ret == H_RESOURCE)
652 ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret);
653
654 return ret;
655}
656
657u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
658 struct ehca_eq *eq)
659{
660 u64 ret;
661
662 ret = hcp_galpas_dtor(&eq->galpas);
663 if (ret) {
664 ehca_gen_err("Could not destruct eq->galpas");
665 return H_RESOURCE;
666 }
667
668 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
669 adapter_handle.handle, /* r4 */
670 eq->ipz_eq_handle.handle, /* r5 */
671 0, 0, 0, 0, 0);
672
673 if (ret == H_RESOURCE)
674 ehca_gen_err("Resource in use. ret=%lx ", ret);
675
676 return ret;
677}
678
679u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
680 const struct ehca_mr *mr,
681 const u64 vaddr,
682 const u64 length,
683 const u32 access_ctrl,
684 const struct ipz_pd pd,
685 struct ehca_mr_hipzout_parms *outparms)
686{
687 u64 ret;
688 u64 outs[PLPAR_HCALL9_BUFSIZE];
689
690 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
691 adapter_handle.handle, /* r4 */
692 5, /* r5 */
693 vaddr, /* r6 */
694 length, /* r7 */
695 (((u64)access_ctrl) << 32ULL), /* r8 */
696 pd.value, /* r9 */
697 0, 0, 0);
698 outparms->handle.handle = outs[0];
699 outparms->lkey = (u32)outs[2];
700 outparms->rkey = (u32)outs[3];
701
702 return ret;
703}
704
705u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
706 const struct ehca_mr *mr,
707 const u8 pagesize,
708 const u8 queue_type,
709 const u64 logical_address_of_page,
710 const u64 count)
711{
712 u64 ret;
713
714 if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
715 ehca_gen_err("logical_address_of_page not on a 4k boundary "
716 "adapter_handle=%lx mr=%p mr_handle=%lx "
717 "pagesize=%x queue_type=%x "
718 "logical_address_of_page=%lx count=%lx",
719 adapter_handle.handle, mr,
720 mr->ipz_mr_handle.handle, pagesize, queue_type,
721 logical_address_of_page, count);
722 ret = H_PARAMETER;
723 } else
724 ret = hipz_h_register_rpage(adapter_handle, pagesize,
725 queue_type,
726 mr->ipz_mr_handle.handle,
727 logical_address_of_page, count);
728 return ret;
729}
730
731u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
732 const struct ehca_mr *mr,
733 struct ehca_mr_hipzout_parms *outparms)
734{
735 u64 ret;
736 u64 outs[PLPAR_HCALL9_BUFSIZE];
737
738 ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
739 adapter_handle.handle, /* r4 */
740 mr->ipz_mr_handle.handle, /* r5 */
741 0, 0, 0, 0, 0, 0, 0);
742 outparms->len = outs[0];
743 outparms->vaddr = outs[1];
744 outparms->acl = outs[4] >> 32;
745 outparms->lkey = (u32)(outs[5] >> 32);
746 outparms->rkey = (u32)(outs[5] & (0xffffffff));
747
748 return ret;
749}
750
751u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
752 const struct ehca_mr *mr)
753{
754 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
755 adapter_handle.handle, /* r4 */
756 mr->ipz_mr_handle.handle, /* r5 */
757 0, 0, 0, 0, 0);
758}
759
760u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
761 const struct ehca_mr *mr,
762 const u64 vaddr_in,
763 const u64 length,
764 const u32 access_ctrl,
765 const struct ipz_pd pd,
766 const u64 mr_addr_cb,
767 struct ehca_mr_hipzout_parms *outparms)
768{
769 u64 ret;
770 u64 outs[PLPAR_HCALL9_BUFSIZE];
771
772 ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
773 adapter_handle.handle, /* r4 */
774 mr->ipz_mr_handle.handle, /* r5 */
775 vaddr_in, /* r6 */
776 length, /* r7 */
777 /* r8 */
778 ((((u64)access_ctrl) << 32ULL) | pd.value),
779 mr_addr_cb, /* r9 */
780 0, 0, 0);
781 outparms->vaddr = outs[1];
782 outparms->lkey = (u32)outs[2];
783 outparms->rkey = (u32)outs[3];
784
785 return ret;
786}
787
788u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
789 const struct ehca_mr *mr,
790 const struct ehca_mr *orig_mr,
791 const u64 vaddr_in,
792 const u32 access_ctrl,
793 const struct ipz_pd pd,
794 struct ehca_mr_hipzout_parms *outparms)
795{
796 u64 ret;
797 u64 outs[PLPAR_HCALL9_BUFSIZE];
798
799 ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
800 adapter_handle.handle, /* r4 */
801 orig_mr->ipz_mr_handle.handle, /* r5 */
802 vaddr_in, /* r6 */
803 (((u64)access_ctrl) << 32ULL), /* r7 */
804 pd.value, /* r8 */
805 0, 0, 0, 0);
806 outparms->handle.handle = outs[0];
807 outparms->lkey = (u32)outs[2];
808 outparms->rkey = (u32)outs[3];
809
810 return ret;
811}
812
813u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
814 const struct ehca_mw *mw,
815 const struct ipz_pd pd,
816 struct ehca_mw_hipzout_parms *outparms)
817{
818 u64 ret;
819 u64 outs[PLPAR_HCALL9_BUFSIZE];
820
821 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
822 adapter_handle.handle, /* r4 */
823 6, /* r5 */
824 pd.value, /* r6 */
825 0, 0, 0, 0, 0, 0);
826 outparms->handle.handle = outs[0];
827 outparms->rkey = (u32)outs[3];
828
829 return ret;
830}
831
832u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
833 const struct ehca_mw *mw,
834 struct ehca_mw_hipzout_parms *outparms)
835{
836 u64 ret;
837 u64 outs[PLPAR_HCALL9_BUFSIZE];
838
839 ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
840 adapter_handle.handle, /* r4 */
841 mw->ipz_mw_handle.handle, /* r5 */
842 0, 0, 0, 0, 0, 0, 0);
843 outparms->rkey = (u32)outs[3];
844
845 return ret;
846}
847
848u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
849 const struct ehca_mw *mw)
850{
851 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
852 adapter_handle.handle, /* r4 */
853 mw->ipz_mw_handle.handle, /* r5 */
854 0, 0, 0, 0, 0);
855}
856
857u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
858 const u64 ressource_handle,
859 void *rblock,
860 unsigned long *byte_count)
861{
862 u64 r_cb = virt_to_abs(rblock);
863
864 if (r_cb & (EHCA_PAGESIZE-1)) {
865 ehca_gen_err("rblock not page aligned.");
866 return H_PARAMETER;
867 }
868
869 return ehca_plpar_hcall_norets(H_ERROR_DATA,
870 adapter_handle.handle,
871 ressource_handle,
872 r_cb,
873 0, 0, 0, 0);
874}