blob: 7efc4a2ad2b9a7775a9357d976603dbac209b182 [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
Joachim Fenkesc4ed7902007-04-24 17:44:31 +020073#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)
76
Heiko J Schickfab97222006-09-22 15:22:22 -070077static u32 get_longbusy_msecs(int longbusy_rc)
78{
79 switch (longbusy_rc) {
80 case H_LONG_BUSY_ORDER_1_MSEC:
81 return 1;
82 case H_LONG_BUSY_ORDER_10_MSEC:
83 return 10;
84 case H_LONG_BUSY_ORDER_100_MSEC:
85 return 100;
86 case H_LONG_BUSY_ORDER_1_SEC:
87 return 1000;
88 case H_LONG_BUSY_ORDER_10_SEC:
89 return 10000;
90 case H_LONG_BUSY_ORDER_100_SEC:
91 return 100000;
92 default:
93 return 1;
94 }
95}
96
97static long ehca_plpar_hcall_norets(unsigned long opcode,
98 unsigned long arg1,
99 unsigned long arg2,
100 unsigned long arg3,
101 unsigned long arg4,
102 unsigned long arg5,
103 unsigned long arg6,
104 unsigned long arg7)
105{
106 long ret;
107 int i, sleep_msecs;
108
109 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
110 "arg5=%lx arg6=%lx arg7=%lx",
111 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
112
113 for (i = 0; i < 5; i++) {
114 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
115 arg5, arg6, arg7);
116
117 if (H_IS_LONG_BUSY(ret)) {
118 sleep_msecs = get_longbusy_msecs(ret);
119 msleep_interruptible(sleep_msecs);
120 continue;
121 }
122
123 if (ret < H_SUCCESS)
124 ehca_gen_err("opcode=%lx ret=%lx"
125 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
126 " arg5=%lx arg6=%lx arg7=%lx ",
127 opcode, ret,
128 arg1, arg2, arg3, arg4, arg5,
129 arg6, arg7);
130
131 ehca_gen_dbg("opcode=%lx ret=%lx", opcode, ret);
132 return ret;
133
134 }
135
136 return H_BUSY;
137}
138
139static long ehca_plpar_hcall9(unsigned long opcode,
140 unsigned long *outs, /* array of 9 outputs */
141 unsigned long arg1,
142 unsigned long arg2,
143 unsigned long arg3,
144 unsigned long arg4,
145 unsigned long arg5,
146 unsigned long arg6,
147 unsigned long arg7,
148 unsigned long arg8,
149 unsigned long arg9)
150{
151 long ret;
Stefan Roscher5d882782007-05-09 13:47:56 +0200152 int i, sleep_msecs, lock_is_set = 0;
153 unsigned long flags;
Heiko J Schickfab97222006-09-22 15:22:22 -0700154
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++) {
Stefan Roscher5d882782007-05-09 13:47:56 +0200161 if ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)) {
162 spin_lock_irqsave(&hcall_lock, flags);
163 lock_is_set = 1;
164 }
165
Heiko J Schickfab97222006-09-22 15:22:22 -0700166 ret = plpar_hcall9(opcode, outs,
167 arg1, arg2, arg3, arg4, arg5,
168 arg6, arg7, arg8, arg9);
169
Stefan Roscher5d882782007-05-09 13:47:56 +0200170 if (lock_is_set)
171 spin_unlock_irqrestore(&hcall_lock, flags);
172
Heiko J Schickfab97222006-09-22 15:22:22 -0700173 if (H_IS_LONG_BUSY(ret)) {
174 sleep_msecs = get_longbusy_msecs(ret);
175 msleep_interruptible(sleep_msecs);
176 continue;
177 }
178
179 if (ret < H_SUCCESS)
180 ehca_gen_err("opcode=%lx ret=%lx"
181 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
182 " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
183 " arg9=%lx"
184 " out1=%lx out2=%lx out3=%lx out4=%lx"
185 " out5=%lx out6=%lx out7=%lx out8=%lx"
186 " out9=%lx",
187 opcode, ret,
188 arg1, arg2, arg3, arg4, arg5,
189 arg6, arg7, arg8, arg9,
190 outs[0], outs[1], outs[2], outs[3],
191 outs[4], outs[5], outs[6], outs[7],
192 outs[8]);
193
194 ehca_gen_dbg("opcode=%lx ret=%lx out1=%lx out2=%lx out3=%lx "
195 "out4=%lx out5=%lx out6=%lx out7=%lx out8=%lx "
196 "out9=%lx",
197 opcode, ret, outs[0], outs[1], outs[2], outs[3],
198 outs[4], outs[5], outs[6], outs[7], outs[8]);
199 return ret;
Heiko J Schickfab97222006-09-22 15:22:22 -0700200 }
201
202 return H_BUSY;
203}
Stefan Roscher5d882782007-05-09 13:47:56 +0200204
Heiko J Schickfab97222006-09-22 15:22:22 -0700205u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
206 struct ehca_pfeq *pfeq,
207 const u32 neq_control,
208 const u32 number_of_entries,
209 struct ipz_eq_handle *eq_handle,
210 u32 *act_nr_of_entries,
211 u32 *act_pages,
212 u32 *eq_ist)
213{
214 u64 ret;
215 u64 outs[PLPAR_HCALL9_BUFSIZE];
216 u64 allocate_controls;
217
218 /* resource type */
219 allocate_controls = 3ULL;
220
221 /* ISN is associated */
222 if (neq_control != 1)
223 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
224 else /* notification event queue */
225 allocate_controls = (1ULL << 63) | allocate_controls;
226
227 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
228 adapter_handle.handle, /* r4 */
229 allocate_controls, /* r5 */
230 number_of_entries, /* r6 */
231 0, 0, 0, 0, 0, 0);
232 eq_handle->handle = outs[0];
233 *act_nr_of_entries = (u32)outs[3];
234 *act_pages = (u32)outs[4];
235 *eq_ist = (u32)outs[5];
236
237 if (ret == H_NOT_ENOUGH_RESOURCES)
238 ehca_gen_err("Not enough resource - ret=%lx ", ret);
239
240 return ret;
241}
242
243u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
244 struct ipz_eq_handle eq_handle,
245 const u64 event_mask)
246{
247 return ehca_plpar_hcall_norets(H_RESET_EVENTS,
248 adapter_handle.handle, /* r4 */
249 eq_handle.handle, /* r5 */
250 event_mask, /* r6 */
251 0, 0, 0, 0);
252}
253
254u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
255 struct ehca_cq *cq,
256 struct ehca_alloc_cq_parms *param)
257{
258 u64 ret;
259 u64 outs[PLPAR_HCALL9_BUFSIZE];
260
261 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
262 adapter_handle.handle, /* r4 */
263 2, /* r5 */
264 param->eq_handle.handle, /* r6 */
265 cq->token, /* r7 */
266 param->nr_cqe, /* r8 */
267 0, 0, 0, 0);
268 cq->ipz_cq_handle.handle = outs[0];
269 param->act_nr_of_entries = (u32)outs[3];
270 param->act_pages = (u32)outs[4];
271
272 if (ret == H_SUCCESS)
273 hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
274
275 if (ret == H_NOT_ENOUGH_RESOURCES)
276 ehca_gen_err("Not enough resources. ret=%lx", ret);
277
278 return ret;
279}
280
281u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
Heiko J Schickfab97222006-09-22 15:22:22 -0700282 struct ehca_alloc_qp_parms *parms)
283{
284 u64 ret;
285 u64 allocate_controls;
286 u64 max_r10_reg;
287 u64 outs[PLPAR_HCALL9_BUFSIZE];
Heiko J Schickfab97222006-09-22 15:22:22 -0700288
289 allocate_controls =
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200290 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
Heiko J Schickfab97222006-09-22 15:22:22 -0700291 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
292 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
293 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
294 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200295 !!(parms->ll_comp_flags & LLQP_RECV_COMP))
Heiko J Schickfab97222006-09-22 15:22:22 -0700296 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200297 !!(parms->ll_comp_flags & LLQP_SEND_COMP))
Heiko J Schickfab97222006-09-22 15:22:22 -0700298 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
299 parms->ud_av_l_key_ctl)
300 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
301
302 max_r10_reg =
303 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200304 parms->max_send_wr + 1)
Heiko J Schickfab97222006-09-22 15:22:22 -0700305 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200306 parms->max_recv_wr + 1)
Heiko J Schickfab97222006-09-22 15:22:22 -0700307 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
308 parms->max_send_sge)
309 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
310 parms->max_recv_sge);
311
312 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
313 adapter_handle.handle, /* r4 */
314 allocate_controls, /* r5 */
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200315 parms->send_cq_handle.handle,
316 parms->recv_cq_handle.handle,
317 parms->eq_handle.handle,
318 ((u64)parms->token << 32) | parms->pd.value,
Heiko J Schickfab97222006-09-22 15:22:22 -0700319 max_r10_reg, /* r10 */
320 parms->ud_av_l_key_ctl, /* r11 */
321 0);
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200322
323 parms->qp_handle.handle = outs[0];
324 parms->real_qp_num = (u32)outs[1];
Stefan Roscher65a2c842007-05-24 16:51:08 +0200325 parms->act_nr_send_wqes =
Heiko J Schickfab97222006-09-22 15:22:22 -0700326 (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]);
337
338 if (ret == H_SUCCESS)
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200339 hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
Heiko J Schickfab97222006-09-22 15:22:22 -0700340
341 if (ret == H_NOT_ENOUGH_RESOURCES)
342 ehca_gen_err("Not enough resources. ret=%lx", ret);
343
344 return ret;
345}
346
347u64 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)
350{
351 u64 ret;
352 u64 r_cb = virt_to_abs(query_port_response_block);
353
354 if (r_cb & (EHCA_PAGESIZE-1)) {
355 ehca_gen_err("response block not page aligned");
356 return H_PARAMETER;
357 }
358
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);
364
365 if (ehca_debug_level)
366 ehca_dmp(query_port_response_block, 64, "response_block");
367
368 return ret;
369}
370
Joachim Fenkesc4ed7902007-04-24 17:44:31 +0200371u64 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)
374{
375 u64 port_attributes = port_cap;
376
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);
383
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);
389}
390
Heiko J Schickfab97222006-09-22 15:22:22 -0700391u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
392 struct hipz_query_hca *query_hca_rblock)
393{
394 u64 r_cb = virt_to_abs(query_hca_rblock);
395
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;
400 }
401
402 return ehca_plpar_hcall_norets(H_QUERY_HCA,
403 adapter_handle.handle, /* r4 */
404 r_cb, /* r5 */
405 0, 0, 0, 0, 0);
406}
407
408u64 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)
414{
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);
422}
423
424u64 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)
431{
432 if (count != 1) {
433 ehca_gen_err("Ppage counter=%lx", count);
434 return H_PARAMETER;
435 }
436 return hipz_h_register_rpage(adapter_handle,
437 pagesize,
438 queue_type,
439 eq_handle.handle,
440 logical_address_of_page, count);
441}
442
443u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
444 u32 ist)
445{
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);
451
452 if (ret != H_SUCCESS && ret != H_BUSY)
453 ehca_gen_err("Could not query interrupt state.");
454
455 return ret;
456}
457
458u64 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)
466{
467 if (count != 1) {
468 ehca_gen_err("Page counter=%lx", count);
469 return H_PARAMETER;
470 }
471
472 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
473 cq_handle.handle, logical_address_of_page,
474 count);
475}
476
477u64 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)
485{
486 if (count != 1) {
487 ehca_gen_err("Page counter=%lx", count);
488 return H_PARAMETER;
489 }
490
491 return hipz_h_register_rpage(adapter_handle,pagesize,queue_type,
492 qp_handle.handle,logical_address_of_page,
493 count);
494}
495
496u64 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)
502{
503 u64 ret;
504 u64 outs[PLPAR_HCALL9_BUFSIZE];
505
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];
515
516 return ret;
517}
518
519u64 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)
525{
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);
534
535 if (ret == H_NOT_ENOUGH_RESOURCES)
536 ehca_gen_err("Insufficient resources ret=%lx", ret);
537
538 return ret;
539}
540
541u64 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)
546{
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);
552}
553
554u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
555 struct ehca_qp *qp)
556{
557 u64 ret;
558 u64 outs[PLPAR_HCALL9_BUFSIZE];
559
560 ret = hcp_galpas_dtor(&qp->galpas);
561 if (ret) {
562 ehca_gen_err("Could not destruct qp->galpas");
563 return H_RESOURCE;
564 }
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);
573
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);
578
579 if (ret == H_RESOURCE)
580 ehca_gen_err("Resource still in use. ret=%lx", ret);
581
582 return ret;
583}
584
585u64 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)
589{
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);
595}
596
597u64 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)
602{
603 u64 ret;
604 u64 outs[PLPAR_HCALL9_BUFSIZE];
605
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];
613
614 if (ret == H_ALIAS_EXIST)
615 ehca_gen_err("AQP1 already exists. ret=%lx", ret);
616
617 return ret;
618}
619
620u64 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)
625{
626 u64 ret;
627
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);
635
636 if (ret == H_NOT_ENOUGH_RESOURCES)
637 ehca_gen_err("Not enough resources. ret=%lx", ret);
638
639 return ret;
640}
641
642u64 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)
647{
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);
655}
656
657u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
658 struct ehca_cq *cq,
659 u8 force_flag)
660{
661 u64 ret;
662
663 ret = hcp_galpas_dtor(&cq->galpas);
664 if (ret) {
665 ehca_gen_err("Could not destruct cp->galpas");
666 return H_RESOURCE;
667 }
668
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);
674
675 if (ret == H_RESOURCE)
676 ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret);
677
678 return ret;
679}
680
681u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
682 struct ehca_eq *eq)
683{
684 u64 ret;
685
686 ret = hcp_galpas_dtor(&eq->galpas);
687 if (ret) {
688 ehca_gen_err("Could not destruct eq->galpas");
689 return H_RESOURCE;
690 }
691
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);
696
697 if (ret == H_RESOURCE)
698 ehca_gen_err("Resource in use. ret=%lx ", ret);
699
700 return ret;
701}
702
703u64 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)
710{
711 u64 ret;
712 u64 outs[PLPAR_HCALL9_BUFSIZE];
713
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];
725
726 return ret;
727}
728
729u64 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)
735{
736 u64 ret;
737
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;
753}
754
755u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
756 const struct ehca_mr *mr,
757 struct ehca_mr_hipzout_parms *outparms)
758{
759 u64 ret;
760 u64 outs[PLPAR_HCALL9_BUFSIZE];
761
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));
771
772 return ret;
773}
774
775u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
776 const struct ehca_mr *mr)
777{
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);
782}
783
784u64 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)
792{
793 u64 ret;
794 u64 outs[PLPAR_HCALL9_BUFSIZE];
795
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];
808
809 return ret;
810}
811
812u64 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)
819{
820 u64 ret;
821 u64 outs[PLPAR_HCALL9_BUFSIZE];
822
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];
833
834 return ret;
835}
836
837u64 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)
841{
842 u64 ret;
843 u64 outs[PLPAR_HCALL9_BUFSIZE];
844
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];
852
853 return ret;
854}
855
856u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
857 const struct ehca_mw *mw,
858 struct ehca_mw_hipzout_parms *outparms)
859{
860 u64 ret;
861 u64 outs[PLPAR_HCALL9_BUFSIZE];
862
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];
868
869 return ret;
870}
871
872u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
873 const struct ehca_mw *mw)
874{
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);
879}
880
881u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
882 const u64 ressource_handle,
883 void *rblock,
884 unsigned long *byte_count)
885{
886 u64 r_cb = virt_to_abs(rblock);
887
888 if (r_cb & (EHCA_PAGESIZE-1)) {
889 ehca_gen_err("rblock not page aligned.");
890 return H_PARAMETER;
891 }
892
893 return ehca_plpar_hcall_norets(H_ERROR_DATA,
894 adapter_handle.handle,
895 ressource_handle,
896 r_cb,
897 0, 0, 0, 0);
898}