IB/ehca: Implement modify_port
[linux-2.6/mini2440.git] / drivers / infiniband / hw / ehca / hcp_if.c
blobb564fcd3b282a2924b9b9a40242e36f83c7b830f
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;
159 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
160 "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
161 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
162 arg8, arg9);
164 for (i = 0; i < 5; i++) {
165 ret = plpar_hcall9(opcode, outs,
166 arg1, arg2, arg3, arg4, arg5,
167 arg6, arg7, arg8, arg9);
169 if (H_IS_LONG_BUSY(ret)) {
170 sleep_msecs = get_longbusy_msecs(ret);
171 msleep_interruptible(sleep_msecs);
172 continue;
175 if (ret < H_SUCCESS)
176 ehca_gen_err("opcode=%lx ret=%lx"
177 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
178 " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
179 " arg9=%lx"
180 " out1=%lx out2=%lx out3=%lx out4=%lx"
181 " out5=%lx out6=%lx out7=%lx out8=%lx"
182 " out9=%lx",
183 opcode, ret,
184 arg1, arg2, arg3, arg4, arg5,
185 arg6, arg7, arg8, arg9,
186 outs[0], outs[1], outs[2], outs[3],
187 outs[4], outs[5], outs[6], outs[7],
188 outs[8]);
190 ehca_gen_dbg("opcode=%lx ret=%lx out1=%lx out2=%lx out3=%lx "
191 "out4=%lx out5=%lx out6=%lx out7=%lx out8=%lx "
192 "out9=%lx",
193 opcode, ret, outs[0], outs[1], outs[2], outs[3],
194 outs[4], outs[5], outs[6], outs[7], outs[8]);
195 return ret;
199 return H_BUSY;
201 u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
202 struct ehca_pfeq *pfeq,
203 const u32 neq_control,
204 const u32 number_of_entries,
205 struct ipz_eq_handle *eq_handle,
206 u32 *act_nr_of_entries,
207 u32 *act_pages,
208 u32 *eq_ist)
210 u64 ret;
211 u64 outs[PLPAR_HCALL9_BUFSIZE];
212 u64 allocate_controls;
214 /* resource type */
215 allocate_controls = 3ULL;
217 /* ISN is associated */
218 if (neq_control != 1)
219 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
220 else /* notification event queue */
221 allocate_controls = (1ULL << 63) | allocate_controls;
223 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
224 adapter_handle.handle, /* r4 */
225 allocate_controls, /* r5 */
226 number_of_entries, /* r6 */
227 0, 0, 0, 0, 0, 0);
228 eq_handle->handle = outs[0];
229 *act_nr_of_entries = (u32)outs[3];
230 *act_pages = (u32)outs[4];
231 *eq_ist = (u32)outs[5];
233 if (ret == H_NOT_ENOUGH_RESOURCES)
234 ehca_gen_err("Not enough resource - ret=%lx ", ret);
236 return ret;
239 u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
240 struct ipz_eq_handle eq_handle,
241 const u64 event_mask)
243 return ehca_plpar_hcall_norets(H_RESET_EVENTS,
244 adapter_handle.handle, /* r4 */
245 eq_handle.handle, /* r5 */
246 event_mask, /* r6 */
247 0, 0, 0, 0);
250 u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
251 struct ehca_cq *cq,
252 struct ehca_alloc_cq_parms *param)
254 u64 ret;
255 u64 outs[PLPAR_HCALL9_BUFSIZE];
257 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
258 adapter_handle.handle, /* r4 */
259 2, /* r5 */
260 param->eq_handle.handle, /* r6 */
261 cq->token, /* r7 */
262 param->nr_cqe, /* r8 */
263 0, 0, 0, 0);
264 cq->ipz_cq_handle.handle = outs[0];
265 param->act_nr_of_entries = (u32)outs[3];
266 param->act_pages = (u32)outs[4];
268 if (ret == H_SUCCESS)
269 hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
271 if (ret == H_NOT_ENOUGH_RESOURCES)
272 ehca_gen_err("Not enough resources. ret=%lx", ret);
274 return ret;
277 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
278 struct ehca_qp *qp,
279 struct ehca_alloc_qp_parms *parms)
281 u64 ret;
282 u64 allocate_controls;
283 u64 max_r10_reg;
284 u64 outs[PLPAR_HCALL9_BUFSIZE];
285 u16 max_nr_receive_wqes = qp->init_attr.cap.max_recv_wr + 1;
286 u16 max_nr_send_wqes = qp->init_attr.cap.max_send_wr + 1;
287 int daqp_ctrl = parms->daqp_ctrl;
289 allocate_controls =
290 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS,
291 (daqp_ctrl & DAQP_CTRL_ENABLE) ? 1 : 0)
292 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
293 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
294 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
295 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
296 (daqp_ctrl & DAQP_CTRL_RECV_COMP) ? 1 : 0)
297 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
298 (daqp_ctrl & DAQP_CTRL_SEND_COMP) ? 1 : 0)
299 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
300 parms->ud_av_l_key_ctl)
301 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
303 max_r10_reg =
304 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
305 max_nr_send_wqes)
306 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
307 max_nr_receive_wqes)
308 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
309 parms->max_send_sge)
310 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
311 parms->max_recv_sge);
313 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
314 adapter_handle.handle, /* r4 */
315 allocate_controls, /* r5 */
316 qp->send_cq->ipz_cq_handle.handle,
317 qp->recv_cq->ipz_cq_handle.handle,
318 parms->ipz_eq_handle.handle,
319 ((u64)qp->token << 32) | parms->pd.value,
320 max_r10_reg, /* r10 */
321 parms->ud_av_l_key_ctl, /* r11 */
323 qp->ipz_qp_handle.handle = outs[0];
324 qp->real_qp_num = (u32)outs[1];
325 parms->act_nr_send_sges =
326 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
327 parms->act_nr_recv_wqes =
328 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
329 parms->act_nr_send_sges =
330 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
331 parms->act_nr_recv_sges =
332 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
333 parms->nr_sq_pages =
334 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
335 parms->nr_rq_pages =
336 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
338 if (ret == H_SUCCESS)
339 hcp_galpas_ctor(&qp->galpas, outs[6], outs[6]);
341 if (ret == H_NOT_ENOUGH_RESOURCES)
342 ehca_gen_err("Not enough resources. ret=%lx", ret);
344 return ret;
347 u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
348 const u8 port_id,
349 struct hipz_query_port *query_port_response_block)
351 u64 ret;
352 u64 r_cb = virt_to_abs(query_port_response_block);
354 if (r_cb & (EHCA_PAGESIZE-1)) {
355 ehca_gen_err("response block not page aligned");
356 return H_PARAMETER;
359 ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
360 adapter_handle.handle, /* r4 */
361 port_id, /* r5 */
362 r_cb, /* r6 */
363 0, 0, 0, 0);
365 if (ehca_debug_level)
366 ehca_dmp(query_port_response_block, 64, "response_block");
368 return ret;
371 u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
372 const u8 port_id, const u32 port_cap,
373 const u8 init_type, const int modify_mask)
375 u64 port_attributes = port_cap;
377 if (modify_mask & IB_PORT_SHUTDOWN)
378 port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
379 if (modify_mask & IB_PORT_INIT_TYPE)
380 port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
381 if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
382 port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
384 return ehca_plpar_hcall_norets(H_MODIFY_PORT,
385 adapter_handle.handle, /* r4 */
386 port_id, /* r5 */
387 port_attributes, /* r6 */
388 0, 0, 0, 0);
391 u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
392 struct hipz_query_hca *query_hca_rblock)
394 u64 r_cb = virt_to_abs(query_hca_rblock);
396 if (r_cb & (EHCA_PAGESIZE-1)) {
397 ehca_gen_err("response_block=%p not page aligned",
398 query_hca_rblock);
399 return H_PARAMETER;
402 return ehca_plpar_hcall_norets(H_QUERY_HCA,
403 adapter_handle.handle, /* r4 */
404 r_cb, /* r5 */
405 0, 0, 0, 0, 0);
408 u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
409 const u8 pagesize,
410 const u8 queue_type,
411 const u64 resource_handle,
412 const u64 logical_address_of_page,
413 u64 count)
415 return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
416 adapter_handle.handle, /* r4 */
417 queue_type | pagesize << 8, /* r5 */
418 resource_handle, /* r6 */
419 logical_address_of_page, /* r7 */
420 count, /* r8 */
421 0, 0);
424 u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
425 const struct ipz_eq_handle eq_handle,
426 struct ehca_pfeq *pfeq,
427 const u8 pagesize,
428 const u8 queue_type,
429 const u64 logical_address_of_page,
430 const u64 count)
432 if (count != 1) {
433 ehca_gen_err("Ppage counter=%lx", count);
434 return H_PARAMETER;
436 return hipz_h_register_rpage(adapter_handle,
437 pagesize,
438 queue_type,
439 eq_handle.handle,
440 logical_address_of_page, count);
443 u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
444 u32 ist)
446 u64 ret;
447 ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
448 adapter_handle.handle, /* r4 */
449 ist, /* r5 */
450 0, 0, 0, 0, 0);
452 if (ret != H_SUCCESS && ret != H_BUSY)
453 ehca_gen_err("Could not query interrupt state.");
455 return ret;
458 u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
459 const struct ipz_cq_handle cq_handle,
460 struct ehca_pfcq *pfcq,
461 const u8 pagesize,
462 const u8 queue_type,
463 const u64 logical_address_of_page,
464 const u64 count,
465 const struct h_galpa gal)
467 if (count != 1) {
468 ehca_gen_err("Page counter=%lx", count);
469 return H_PARAMETER;
472 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
473 cq_handle.handle, logical_address_of_page,
474 count);
477 u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
478 const struct ipz_qp_handle qp_handle,
479 struct ehca_pfqp *pfqp,
480 const u8 pagesize,
481 const u8 queue_type,
482 const u64 logical_address_of_page,
483 const u64 count,
484 const struct h_galpa galpa)
486 if (count != 1) {
487 ehca_gen_err("Page counter=%lx", count);
488 return H_PARAMETER;
491 return hipz_h_register_rpage(adapter_handle,pagesize,queue_type,
492 qp_handle.handle,logical_address_of_page,
493 count);
496 u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
497 const struct ipz_qp_handle qp_handle,
498 struct ehca_pfqp *pfqp,
499 void **log_addr_next_sq_wqe2processed,
500 void **log_addr_next_rq_wqe2processed,
501 int dis_and_get_function_code)
503 u64 ret;
504 u64 outs[PLPAR_HCALL9_BUFSIZE];
506 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
507 adapter_handle.handle, /* r4 */
508 dis_and_get_function_code, /* r5 */
509 qp_handle.handle, /* r6 */
510 0, 0, 0, 0, 0, 0);
511 if (log_addr_next_sq_wqe2processed)
512 *log_addr_next_sq_wqe2processed = (void*)outs[0];
513 if (log_addr_next_rq_wqe2processed)
514 *log_addr_next_rq_wqe2processed = (void*)outs[1];
516 return ret;
519 u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
520 const struct ipz_qp_handle qp_handle,
521 struct ehca_pfqp *pfqp,
522 const u64 update_mask,
523 struct hcp_modify_qp_control_block *mqpcb,
524 struct h_galpa gal)
526 u64 ret;
527 u64 outs[PLPAR_HCALL9_BUFSIZE];
528 ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
529 adapter_handle.handle, /* r4 */
530 qp_handle.handle, /* r5 */
531 update_mask, /* r6 */
532 virt_to_abs(mqpcb), /* r7 */
533 0, 0, 0, 0, 0);
535 if (ret == H_NOT_ENOUGH_RESOURCES)
536 ehca_gen_err("Insufficient resources ret=%lx", ret);
538 return ret;
541 u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
542 const struct ipz_qp_handle qp_handle,
543 struct ehca_pfqp *pfqp,
544 struct hcp_modify_qp_control_block *qqpcb,
545 struct h_galpa gal)
547 return ehca_plpar_hcall_norets(H_QUERY_QP,
548 adapter_handle.handle, /* r4 */
549 qp_handle.handle, /* r5 */
550 virt_to_abs(qqpcb), /* r6 */
551 0, 0, 0, 0);
554 u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
555 struct ehca_qp *qp)
557 u64 ret;
558 u64 outs[PLPAR_HCALL9_BUFSIZE];
560 ret = hcp_galpas_dtor(&qp->galpas);
561 if (ret) {
562 ehca_gen_err("Could not destruct qp->galpas");
563 return H_RESOURCE;
565 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
566 adapter_handle.handle, /* r4 */
567 /* function code */
568 1, /* r5 */
569 qp->ipz_qp_handle.handle, /* r6 */
570 0, 0, 0, 0, 0, 0);
571 if (ret == H_HARDWARE)
572 ehca_gen_err("HCA not operational. ret=%lx", ret);
574 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
575 adapter_handle.handle, /* r4 */
576 qp->ipz_qp_handle.handle, /* r5 */
577 0, 0, 0, 0, 0);
579 if (ret == H_RESOURCE)
580 ehca_gen_err("Resource still in use. ret=%lx", ret);
582 return ret;
585 u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
586 const struct ipz_qp_handle qp_handle,
587 struct h_galpa gal,
588 u32 port)
590 return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
591 adapter_handle.handle, /* r4 */
592 qp_handle.handle, /* r5 */
593 port, /* r6 */
594 0, 0, 0, 0);
597 u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
598 const struct ipz_qp_handle qp_handle,
599 struct h_galpa gal,
600 u32 port, u32 * pma_qp_nr,
601 u32 * bma_qp_nr)
603 u64 ret;
604 u64 outs[PLPAR_HCALL9_BUFSIZE];
606 ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
607 adapter_handle.handle, /* r4 */
608 qp_handle.handle, /* r5 */
609 port, /* r6 */
610 0, 0, 0, 0, 0, 0);
611 *pma_qp_nr = (u32)outs[0];
612 *bma_qp_nr = (u32)outs[1];
614 if (ret == H_ALIAS_EXIST)
615 ehca_gen_err("AQP1 already exists. ret=%lx", ret);
617 return ret;
620 u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
621 const struct ipz_qp_handle qp_handle,
622 struct h_galpa gal,
623 u16 mcg_dlid,
624 u64 subnet_prefix, u64 interface_id)
626 u64 ret;
628 ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
629 adapter_handle.handle, /* r4 */
630 qp_handle.handle, /* r5 */
631 mcg_dlid, /* r6 */
632 interface_id, /* r7 */
633 subnet_prefix, /* r8 */
634 0, 0);
636 if (ret == H_NOT_ENOUGH_RESOURCES)
637 ehca_gen_err("Not enough resources. ret=%lx", ret);
639 return ret;
642 u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
643 const struct ipz_qp_handle qp_handle,
644 struct h_galpa gal,
645 u16 mcg_dlid,
646 u64 subnet_prefix, u64 interface_id)
648 return ehca_plpar_hcall_norets(H_DETACH_MCQP,
649 adapter_handle.handle, /* r4 */
650 qp_handle.handle, /* r5 */
651 mcg_dlid, /* r6 */
652 interface_id, /* r7 */
653 subnet_prefix, /* r8 */
654 0, 0);
657 u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
658 struct ehca_cq *cq,
659 u8 force_flag)
661 u64 ret;
663 ret = hcp_galpas_dtor(&cq->galpas);
664 if (ret) {
665 ehca_gen_err("Could not destruct cp->galpas");
666 return H_RESOURCE;
669 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
670 adapter_handle.handle, /* r4 */
671 cq->ipz_cq_handle.handle, /* r5 */
672 force_flag != 0 ? 1L : 0L, /* r6 */
673 0, 0, 0, 0);
675 if (ret == H_RESOURCE)
676 ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret);
678 return ret;
681 u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
682 struct ehca_eq *eq)
684 u64 ret;
686 ret = hcp_galpas_dtor(&eq->galpas);
687 if (ret) {
688 ehca_gen_err("Could not destruct eq->galpas");
689 return H_RESOURCE;
692 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
693 adapter_handle.handle, /* r4 */
694 eq->ipz_eq_handle.handle, /* r5 */
695 0, 0, 0, 0, 0);
697 if (ret == H_RESOURCE)
698 ehca_gen_err("Resource in use. ret=%lx ", ret);
700 return ret;
703 u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
704 const struct ehca_mr *mr,
705 const u64 vaddr,
706 const u64 length,
707 const u32 access_ctrl,
708 const struct ipz_pd pd,
709 struct ehca_mr_hipzout_parms *outparms)
711 u64 ret;
712 u64 outs[PLPAR_HCALL9_BUFSIZE];
714 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
715 adapter_handle.handle, /* r4 */
716 5, /* r5 */
717 vaddr, /* r6 */
718 length, /* r7 */
719 (((u64)access_ctrl) << 32ULL), /* r8 */
720 pd.value, /* r9 */
721 0, 0, 0);
722 outparms->handle.handle = outs[0];
723 outparms->lkey = (u32)outs[2];
724 outparms->rkey = (u32)outs[3];
726 return ret;
729 u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
730 const struct ehca_mr *mr,
731 const u8 pagesize,
732 const u8 queue_type,
733 const u64 logical_address_of_page,
734 const u64 count)
736 u64 ret;
738 if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
739 ehca_gen_err("logical_address_of_page not on a 4k boundary "
740 "adapter_handle=%lx mr=%p mr_handle=%lx "
741 "pagesize=%x queue_type=%x "
742 "logical_address_of_page=%lx count=%lx",
743 adapter_handle.handle, mr,
744 mr->ipz_mr_handle.handle, pagesize, queue_type,
745 logical_address_of_page, count);
746 ret = H_PARAMETER;
747 } else
748 ret = hipz_h_register_rpage(adapter_handle, pagesize,
749 queue_type,
750 mr->ipz_mr_handle.handle,
751 logical_address_of_page, count);
752 return ret;
755 u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
756 const struct ehca_mr *mr,
757 struct ehca_mr_hipzout_parms *outparms)
759 u64 ret;
760 u64 outs[PLPAR_HCALL9_BUFSIZE];
762 ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
763 adapter_handle.handle, /* r4 */
764 mr->ipz_mr_handle.handle, /* r5 */
765 0, 0, 0, 0, 0, 0, 0);
766 outparms->len = outs[0];
767 outparms->vaddr = outs[1];
768 outparms->acl = outs[4] >> 32;
769 outparms->lkey = (u32)(outs[5] >> 32);
770 outparms->rkey = (u32)(outs[5] & (0xffffffff));
772 return ret;
775 u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
776 const struct ehca_mr *mr)
778 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
779 adapter_handle.handle, /* r4 */
780 mr->ipz_mr_handle.handle, /* r5 */
781 0, 0, 0, 0, 0);
784 u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
785 const struct ehca_mr *mr,
786 const u64 vaddr_in,
787 const u64 length,
788 const u32 access_ctrl,
789 const struct ipz_pd pd,
790 const u64 mr_addr_cb,
791 struct ehca_mr_hipzout_parms *outparms)
793 u64 ret;
794 u64 outs[PLPAR_HCALL9_BUFSIZE];
796 ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
797 adapter_handle.handle, /* r4 */
798 mr->ipz_mr_handle.handle, /* r5 */
799 vaddr_in, /* r6 */
800 length, /* r7 */
801 /* r8 */
802 ((((u64)access_ctrl) << 32ULL) | pd.value),
803 mr_addr_cb, /* r9 */
804 0, 0, 0);
805 outparms->vaddr = outs[1];
806 outparms->lkey = (u32)outs[2];
807 outparms->rkey = (u32)outs[3];
809 return ret;
812 u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
813 const struct ehca_mr *mr,
814 const struct ehca_mr *orig_mr,
815 const u64 vaddr_in,
816 const u32 access_ctrl,
817 const struct ipz_pd pd,
818 struct ehca_mr_hipzout_parms *outparms)
820 u64 ret;
821 u64 outs[PLPAR_HCALL9_BUFSIZE];
823 ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
824 adapter_handle.handle, /* r4 */
825 orig_mr->ipz_mr_handle.handle, /* r5 */
826 vaddr_in, /* r6 */
827 (((u64)access_ctrl) << 32ULL), /* r7 */
828 pd.value, /* r8 */
829 0, 0, 0, 0);
830 outparms->handle.handle = outs[0];
831 outparms->lkey = (u32)outs[2];
832 outparms->rkey = (u32)outs[3];
834 return ret;
837 u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
838 const struct ehca_mw *mw,
839 const struct ipz_pd pd,
840 struct ehca_mw_hipzout_parms *outparms)
842 u64 ret;
843 u64 outs[PLPAR_HCALL9_BUFSIZE];
845 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
846 adapter_handle.handle, /* r4 */
847 6, /* r5 */
848 pd.value, /* r6 */
849 0, 0, 0, 0, 0, 0);
850 outparms->handle.handle = outs[0];
851 outparms->rkey = (u32)outs[3];
853 return ret;
856 u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
857 const struct ehca_mw *mw,
858 struct ehca_mw_hipzout_parms *outparms)
860 u64 ret;
861 u64 outs[PLPAR_HCALL9_BUFSIZE];
863 ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
864 adapter_handle.handle, /* r4 */
865 mw->ipz_mw_handle.handle, /* r5 */
866 0, 0, 0, 0, 0, 0, 0);
867 outparms->rkey = (u32)outs[3];
869 return ret;
872 u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
873 const struct ehca_mw *mw)
875 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
876 adapter_handle.handle, /* r4 */
877 mw->ipz_mw_handle.handle, /* r5 */
878 0, 0, 0, 0, 0);
881 u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
882 const u64 ressource_handle,
883 void *rblock,
884 unsigned long *byte_count)
886 u64 r_cb = virt_to_abs(rblock);
888 if (r_cb & (EHCA_PAGESIZE-1)) {
889 ehca_gen_err("rblock not page aligned.");
890 return H_PARAMETER;
893 return ehca_plpar_hcall_norets(H_ERROR_DATA,
894 adapter_handle.handle,
895 ressource_handle,
896 r_cb,
897 0, 0, 0, 0);