blob: 4776a8b0feec4f02bbf6f90e8de04f79e0e9dbda [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>
Joachim Fenkesa6a12942007-07-09 15:25:10 +02008 * Joachim Fenkes <fenkes@de.ibm.com>
Heiko J Schickfab97222006-09-22 15:22:22 -07009 * Gerd Bayer <gerd.bayer@de.ibm.com>
10 * Waleri Fomin <fomin@de.ibm.com>
11 *
12 * Copyright (c) 2005 IBM Corporation
13 *
14 * All rights reserved.
15 *
16 * This source code is distributed under a dual license of GPL v2.0 and OpenIB
17 * BSD.
18 *
19 * OpenIB BSD License
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 *
24 * Redistributions of source code must retain the above copyright notice, this
25 * list of conditions and the following disclaimer.
26 *
27 * Redistributions in binary form must reproduce the above copyright notice,
28 * this list of conditions and the following disclaimer in the documentation
29 * and/or other materials
30 * provided with the distribution.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
36 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
40 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGE.
43 */
44
45#include <asm/hvcall.h>
46#include "ehca_tools.h"
47#include "hcp_if.h"
48#include "hcp_phyp.h"
49#include "hipz_fns.h"
50#include "ipz_pt_fn.h"
51
52#define H_ALL_RES_QP_ENHANCED_OPS EHCA_BMASK_IBM(9, 11)
53#define H_ALL_RES_QP_PTE_PIN EHCA_BMASK_IBM(12, 12)
54#define H_ALL_RES_QP_SERVICE_TYPE EHCA_BMASK_IBM(13, 15)
55#define H_ALL_RES_QP_LL_RQ_CQE_POSTING EHCA_BMASK_IBM(18, 18)
56#define H_ALL_RES_QP_LL_SQ_CQE_POSTING EHCA_BMASK_IBM(19, 21)
57#define H_ALL_RES_QP_SIGNALING_TYPE EHCA_BMASK_IBM(22, 23)
58#define H_ALL_RES_QP_UD_AV_LKEY_CTRL EHCA_BMASK_IBM(31, 31)
59#define H_ALL_RES_QP_RESOURCE_TYPE EHCA_BMASK_IBM(56, 63)
60
61#define H_ALL_RES_QP_MAX_OUTST_SEND_WR EHCA_BMASK_IBM(0, 15)
62#define H_ALL_RES_QP_MAX_OUTST_RECV_WR EHCA_BMASK_IBM(16, 31)
63#define H_ALL_RES_QP_MAX_SEND_SGE EHCA_BMASK_IBM(32, 39)
64#define H_ALL_RES_QP_MAX_RECV_SGE EHCA_BMASK_IBM(40, 47)
65
Joachim Fenkesa6a12942007-07-09 15:25:10 +020066#define H_ALL_RES_QP_UD_AV_LKEY EHCA_BMASK_IBM(32, 63)
67#define H_ALL_RES_QP_SRQ_QP_TOKEN EHCA_BMASK_IBM(0, 31)
68#define H_ALL_RES_QP_SRQ_QP_HANDLE EHCA_BMASK_IBM(0, 64)
69#define H_ALL_RES_QP_SRQ_LIMIT EHCA_BMASK_IBM(48, 63)
70#define H_ALL_RES_QP_SRQ_QPN EHCA_BMASK_IBM(40, 63)
71
Heiko J Schickfab97222006-09-22 15:22:22 -070072#define H_ALL_RES_QP_ACT_OUTST_SEND_WR EHCA_BMASK_IBM(16, 31)
73#define H_ALL_RES_QP_ACT_OUTST_RECV_WR EHCA_BMASK_IBM(48, 63)
74#define H_ALL_RES_QP_ACT_SEND_SGE EHCA_BMASK_IBM(8, 15)
75#define H_ALL_RES_QP_ACT_RECV_SGE EHCA_BMASK_IBM(24, 31)
76
77#define H_ALL_RES_QP_SQUEUE_SIZE_PAGES EHCA_BMASK_IBM(0, 31)
78#define H_ALL_RES_QP_RQUEUE_SIZE_PAGES EHCA_BMASK_IBM(32, 63)
79
Joachim Fenkesc4ed7902007-04-24 17:44:31 +020080#define H_MP_INIT_TYPE EHCA_BMASK_IBM(44, 47)
81#define H_MP_SHUTDOWN EHCA_BMASK_IBM(48, 48)
82#define H_MP_RESET_QKEY_CTR EHCA_BMASK_IBM(49, 49)
83
Joachim Fenkes9844b712007-07-09 15:29:03 +020084static DEFINE_SPINLOCK(hcall_lock);
85
Heiko J Schickfab97222006-09-22 15:22:22 -070086static u32 get_longbusy_msecs(int longbusy_rc)
87{
88 switch (longbusy_rc) {
89 case H_LONG_BUSY_ORDER_1_MSEC:
90 return 1;
91 case H_LONG_BUSY_ORDER_10_MSEC:
92 return 10;
93 case H_LONG_BUSY_ORDER_100_MSEC:
94 return 100;
95 case H_LONG_BUSY_ORDER_1_SEC:
96 return 1000;
97 case H_LONG_BUSY_ORDER_10_SEC:
98 return 10000;
99 case H_LONG_BUSY_ORDER_100_SEC:
100 return 100000;
101 default:
102 return 1;
103 }
104}
105
106static long ehca_plpar_hcall_norets(unsigned long opcode,
107 unsigned long arg1,
108 unsigned long arg2,
109 unsigned long arg3,
110 unsigned long arg4,
111 unsigned long arg5,
112 unsigned long arg6,
113 unsigned long arg7)
114{
115 long ret;
116 int i, sleep_msecs;
117
118 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
119 "arg5=%lx arg6=%lx arg7=%lx",
120 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
121
122 for (i = 0; i < 5; i++) {
123 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
124 arg5, arg6, arg7);
125
126 if (H_IS_LONG_BUSY(ret)) {
127 sleep_msecs = get_longbusy_msecs(ret);
128 msleep_interruptible(sleep_msecs);
129 continue;
130 }
131
132 if (ret < H_SUCCESS)
133 ehca_gen_err("opcode=%lx ret=%lx"
134 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
135 " arg5=%lx arg6=%lx arg7=%lx ",
136 opcode, ret,
137 arg1, arg2, arg3, arg4, arg5,
138 arg6, arg7);
139
140 ehca_gen_dbg("opcode=%lx ret=%lx", opcode, ret);
141 return ret;
142
143 }
144
145 return H_BUSY;
146}
147
148static long ehca_plpar_hcall9(unsigned long opcode,
149 unsigned long *outs, /* array of 9 outputs */
150 unsigned long arg1,
151 unsigned long arg2,
152 unsigned long arg3,
153 unsigned long arg4,
154 unsigned long arg5,
155 unsigned long arg6,
156 unsigned long arg7,
157 unsigned long arg8,
158 unsigned long arg9)
159{
160 long ret;
Stefan Roscher5d882782007-05-09 13:47:56 +0200161 int i, sleep_msecs, lock_is_set = 0;
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200162 unsigned long flags = 0;
Heiko J Schickfab97222006-09-22 15:22:22 -0700163
164 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
165 "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
166 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
167 arg8, arg9);
168
169 for (i = 0; i < 5; i++) {
Stefan Roscher5d882782007-05-09 13:47:56 +0200170 if ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)) {
171 spin_lock_irqsave(&hcall_lock, flags);
172 lock_is_set = 1;
173 }
174
Heiko J Schickfab97222006-09-22 15:22:22 -0700175 ret = plpar_hcall9(opcode, outs,
176 arg1, arg2, arg3, arg4, arg5,
177 arg6, arg7, arg8, arg9);
178
Stefan Roscher5d882782007-05-09 13:47:56 +0200179 if (lock_is_set)
180 spin_unlock_irqrestore(&hcall_lock, flags);
181
Heiko J Schickfab97222006-09-22 15:22:22 -0700182 if (H_IS_LONG_BUSY(ret)) {
183 sleep_msecs = get_longbusy_msecs(ret);
184 msleep_interruptible(sleep_msecs);
185 continue;
186 }
187
188 if (ret < H_SUCCESS)
189 ehca_gen_err("opcode=%lx ret=%lx"
190 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
191 " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
192 " arg9=%lx"
193 " out1=%lx out2=%lx out3=%lx out4=%lx"
194 " out5=%lx out6=%lx out7=%lx out8=%lx"
195 " out9=%lx",
196 opcode, ret,
197 arg1, arg2, arg3, arg4, arg5,
198 arg6, arg7, arg8, arg9,
199 outs[0], outs[1], outs[2], outs[3],
200 outs[4], outs[5], outs[6], outs[7],
201 outs[8]);
202
203 ehca_gen_dbg("opcode=%lx ret=%lx out1=%lx out2=%lx out3=%lx "
204 "out4=%lx out5=%lx out6=%lx out7=%lx out8=%lx "
205 "out9=%lx",
206 opcode, ret, outs[0], outs[1], outs[2], outs[3],
207 outs[4], outs[5], outs[6], outs[7], outs[8]);
208 return ret;
Heiko J Schickfab97222006-09-22 15:22:22 -0700209 }
210
211 return H_BUSY;
212}
Stefan Roscher5d882782007-05-09 13:47:56 +0200213
Heiko J Schickfab97222006-09-22 15:22:22 -0700214u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
215 struct ehca_pfeq *pfeq,
216 const u32 neq_control,
217 const u32 number_of_entries,
218 struct ipz_eq_handle *eq_handle,
219 u32 *act_nr_of_entries,
220 u32 *act_pages,
221 u32 *eq_ist)
222{
223 u64 ret;
224 u64 outs[PLPAR_HCALL9_BUFSIZE];
225 u64 allocate_controls;
226
227 /* resource type */
228 allocate_controls = 3ULL;
229
230 /* ISN is associated */
231 if (neq_control != 1)
232 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
233 else /* notification event queue */
234 allocate_controls = (1ULL << 63) | allocate_controls;
235
236 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
237 adapter_handle.handle, /* r4 */
238 allocate_controls, /* r5 */
239 number_of_entries, /* r6 */
240 0, 0, 0, 0, 0, 0);
241 eq_handle->handle = outs[0];
242 *act_nr_of_entries = (u32)outs[3];
243 *act_pages = (u32)outs[4];
244 *eq_ist = (u32)outs[5];
245
246 if (ret == H_NOT_ENOUGH_RESOURCES)
247 ehca_gen_err("Not enough resource - ret=%lx ", ret);
248
249 return ret;
250}
251
252u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
253 struct ipz_eq_handle eq_handle,
254 const u64 event_mask)
255{
256 return ehca_plpar_hcall_norets(H_RESET_EVENTS,
257 adapter_handle.handle, /* r4 */
258 eq_handle.handle, /* r5 */
259 event_mask, /* r6 */
260 0, 0, 0, 0);
261}
262
263u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
264 struct ehca_cq *cq,
265 struct ehca_alloc_cq_parms *param)
266{
267 u64 ret;
268 u64 outs[PLPAR_HCALL9_BUFSIZE];
269
270 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
271 adapter_handle.handle, /* r4 */
272 2, /* r5 */
273 param->eq_handle.handle, /* r6 */
274 cq->token, /* r7 */
275 param->nr_cqe, /* r8 */
276 0, 0, 0, 0);
277 cq->ipz_cq_handle.handle = outs[0];
278 param->act_nr_of_entries = (u32)outs[3];
279 param->act_pages = (u32)outs[4];
280
281 if (ret == H_SUCCESS)
282 hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
283
284 if (ret == H_NOT_ENOUGH_RESOURCES)
285 ehca_gen_err("Not enough resources. ret=%lx", ret);
286
287 return ret;
288}
289
290u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
Heiko J Schickfab97222006-09-22 15:22:22 -0700291 struct ehca_alloc_qp_parms *parms)
292{
293 u64 ret;
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200294 u64 allocate_controls, max_r10_reg, r11, r12;
Heiko J Schickfab97222006-09-22 15:22:22 -0700295 u64 outs[PLPAR_HCALL9_BUFSIZE];
Heiko J Schickfab97222006-09-22 15:22:22 -0700296
297 allocate_controls =
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200298 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
Heiko J Schickfab97222006-09-22 15:22:22 -0700299 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
300 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
301 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
302 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200303 !!(parms->ll_comp_flags & LLQP_RECV_COMP))
Heiko J Schickfab97222006-09-22 15:22:22 -0700304 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200305 !!(parms->ll_comp_flags & LLQP_SEND_COMP))
Heiko J Schickfab97222006-09-22 15:22:22 -0700306 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
307 parms->ud_av_l_key_ctl)
308 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
309
310 max_r10_reg =
311 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200312 parms->max_send_wr + 1)
Heiko J Schickfab97222006-09-22 15:22:22 -0700313 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200314 parms->max_recv_wr + 1)
Heiko J Schickfab97222006-09-22 15:22:22 -0700315 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
316 parms->max_send_sge)
317 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
318 parms->max_recv_sge);
319
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200320 r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
321
322 if (parms->ext_type == EQPT_SRQ)
323 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
324 else
325 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
326
Heiko J Schickfab97222006-09-22 15:22:22 -0700327 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
328 adapter_handle.handle, /* r4 */
329 allocate_controls, /* r5 */
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200330 parms->send_cq_handle.handle,
331 parms->recv_cq_handle.handle,
332 parms->eq_handle.handle,
333 ((u64)parms->token << 32) | parms->pd.value,
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200334 max_r10_reg, r11, r12);
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200335
336 parms->qp_handle.handle = outs[0];
337 parms->real_qp_num = (u32)outs[1];
Stefan Roscher65a2c842007-05-24 16:51:08 +0200338 parms->act_nr_send_wqes =
Heiko J Schickfab97222006-09-22 15:22:22 -0700339 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
340 parms->act_nr_recv_wqes =
341 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
342 parms->act_nr_send_sges =
343 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
344 parms->act_nr_recv_sges =
345 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
346 parms->nr_sq_pages =
347 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
348 parms->nr_rq_pages =
349 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
350
351 if (ret == H_SUCCESS)
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200352 hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
Heiko J Schickfab97222006-09-22 15:22:22 -0700353
354 if (ret == H_NOT_ENOUGH_RESOURCES)
355 ehca_gen_err("Not enough resources. ret=%lx", ret);
356
357 return ret;
358}
359
360u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
361 const u8 port_id,
362 struct hipz_query_port *query_port_response_block)
363{
364 u64 ret;
365 u64 r_cb = virt_to_abs(query_port_response_block);
366
367 if (r_cb & (EHCA_PAGESIZE-1)) {
368 ehca_gen_err("response block not page aligned");
369 return H_PARAMETER;
370 }
371
372 ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
373 adapter_handle.handle, /* r4 */
374 port_id, /* r5 */
375 r_cb, /* r6 */
376 0, 0, 0, 0);
377
378 if (ehca_debug_level)
379 ehca_dmp(query_port_response_block, 64, "response_block");
380
381 return ret;
382}
383
Joachim Fenkesc4ed7902007-04-24 17:44:31 +0200384u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
385 const u8 port_id, const u32 port_cap,
386 const u8 init_type, const int modify_mask)
387{
388 u64 port_attributes = port_cap;
389
390 if (modify_mask & IB_PORT_SHUTDOWN)
391 port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
392 if (modify_mask & IB_PORT_INIT_TYPE)
393 port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
394 if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
395 port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
396
397 return ehca_plpar_hcall_norets(H_MODIFY_PORT,
398 adapter_handle.handle, /* r4 */
399 port_id, /* r5 */
400 port_attributes, /* r6 */
401 0, 0, 0, 0);
402}
403
Heiko J Schickfab97222006-09-22 15:22:22 -0700404u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
405 struct hipz_query_hca *query_hca_rblock)
406{
407 u64 r_cb = virt_to_abs(query_hca_rblock);
408
409 if (r_cb & (EHCA_PAGESIZE-1)) {
410 ehca_gen_err("response_block=%p not page aligned",
411 query_hca_rblock);
412 return H_PARAMETER;
413 }
414
415 return ehca_plpar_hcall_norets(H_QUERY_HCA,
416 adapter_handle.handle, /* r4 */
417 r_cb, /* r5 */
418 0, 0, 0, 0, 0);
419}
420
421u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
422 const u8 pagesize,
423 const u8 queue_type,
424 const u64 resource_handle,
425 const u64 logical_address_of_page,
426 u64 count)
427{
428 return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
429 adapter_handle.handle, /* r4 */
430 queue_type | pagesize << 8, /* r5 */
431 resource_handle, /* r6 */
432 logical_address_of_page, /* r7 */
433 count, /* r8 */
434 0, 0);
435}
436
437u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
438 const struct ipz_eq_handle eq_handle,
439 struct ehca_pfeq *pfeq,
440 const u8 pagesize,
441 const u8 queue_type,
442 const u64 logical_address_of_page,
443 const u64 count)
444{
445 if (count != 1) {
446 ehca_gen_err("Ppage counter=%lx", count);
447 return H_PARAMETER;
448 }
449 return hipz_h_register_rpage(adapter_handle,
450 pagesize,
451 queue_type,
452 eq_handle.handle,
453 logical_address_of_page, count);
454}
455
456u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
457 u32 ist)
458{
459 u64 ret;
460 ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
461 adapter_handle.handle, /* r4 */
462 ist, /* r5 */
463 0, 0, 0, 0, 0);
464
465 if (ret != H_SUCCESS && ret != H_BUSY)
466 ehca_gen_err("Could not query interrupt state.");
467
468 return ret;
469}
470
471u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
472 const struct ipz_cq_handle cq_handle,
473 struct ehca_pfcq *pfcq,
474 const u8 pagesize,
475 const u8 queue_type,
476 const u64 logical_address_of_page,
477 const u64 count,
478 const struct h_galpa gal)
479{
480 if (count != 1) {
481 ehca_gen_err("Page counter=%lx", count);
482 return H_PARAMETER;
483 }
484
485 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
486 cq_handle.handle, logical_address_of_page,
487 count);
488}
489
490u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
491 const struct ipz_qp_handle qp_handle,
492 struct ehca_pfqp *pfqp,
493 const u8 pagesize,
494 const u8 queue_type,
495 const u64 logical_address_of_page,
496 const u64 count,
497 const struct h_galpa galpa)
498{
499 if (count != 1) {
500 ehca_gen_err("Page counter=%lx", count);
501 return H_PARAMETER;
502 }
503
504 return hipz_h_register_rpage(adapter_handle,pagesize,queue_type,
505 qp_handle.handle,logical_address_of_page,
506 count);
507}
508
509u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
510 const struct ipz_qp_handle qp_handle,
511 struct ehca_pfqp *pfqp,
512 void **log_addr_next_sq_wqe2processed,
513 void **log_addr_next_rq_wqe2processed,
514 int dis_and_get_function_code)
515{
516 u64 ret;
517 u64 outs[PLPAR_HCALL9_BUFSIZE];
518
519 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
520 adapter_handle.handle, /* r4 */
521 dis_and_get_function_code, /* r5 */
522 qp_handle.handle, /* r6 */
523 0, 0, 0, 0, 0, 0);
524 if (log_addr_next_sq_wqe2processed)
525 *log_addr_next_sq_wqe2processed = (void*)outs[0];
526 if (log_addr_next_rq_wqe2processed)
527 *log_addr_next_rq_wqe2processed = (void*)outs[1];
528
529 return ret;
530}
531
532u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
533 const struct ipz_qp_handle qp_handle,
534 struct ehca_pfqp *pfqp,
535 const u64 update_mask,
536 struct hcp_modify_qp_control_block *mqpcb,
537 struct h_galpa gal)
538{
539 u64 ret;
540 u64 outs[PLPAR_HCALL9_BUFSIZE];
541 ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
542 adapter_handle.handle, /* r4 */
543 qp_handle.handle, /* r5 */
544 update_mask, /* r6 */
545 virt_to_abs(mqpcb), /* r7 */
546 0, 0, 0, 0, 0);
547
548 if (ret == H_NOT_ENOUGH_RESOURCES)
549 ehca_gen_err("Insufficient resources ret=%lx", ret);
550
551 return ret;
552}
553
554u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
555 const struct ipz_qp_handle qp_handle,
556 struct ehca_pfqp *pfqp,
557 struct hcp_modify_qp_control_block *qqpcb,
558 struct h_galpa gal)
559{
560 return ehca_plpar_hcall_norets(H_QUERY_QP,
561 adapter_handle.handle, /* r4 */
562 qp_handle.handle, /* r5 */
563 virt_to_abs(qqpcb), /* r6 */
564 0, 0, 0, 0);
565}
566
567u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
568 struct ehca_qp *qp)
569{
570 u64 ret;
571 u64 outs[PLPAR_HCALL9_BUFSIZE];
572
573 ret = hcp_galpas_dtor(&qp->galpas);
574 if (ret) {
575 ehca_gen_err("Could not destruct qp->galpas");
576 return H_RESOURCE;
577 }
578 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
579 adapter_handle.handle, /* r4 */
580 /* function code */
581 1, /* r5 */
582 qp->ipz_qp_handle.handle, /* r6 */
583 0, 0, 0, 0, 0, 0);
584 if (ret == H_HARDWARE)
585 ehca_gen_err("HCA not operational. ret=%lx", ret);
586
587 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
588 adapter_handle.handle, /* r4 */
589 qp->ipz_qp_handle.handle, /* r5 */
590 0, 0, 0, 0, 0);
591
592 if (ret == H_RESOURCE)
593 ehca_gen_err("Resource still in use. ret=%lx", ret);
594
595 return ret;
596}
597
598u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
599 const struct ipz_qp_handle qp_handle,
600 struct h_galpa gal,
601 u32 port)
602{
603 return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
604 adapter_handle.handle, /* r4 */
605 qp_handle.handle, /* r5 */
606 port, /* r6 */
607 0, 0, 0, 0);
608}
609
610u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
611 const struct ipz_qp_handle qp_handle,
612 struct h_galpa gal,
613 u32 port, u32 * pma_qp_nr,
614 u32 * bma_qp_nr)
615{
616 u64 ret;
617 u64 outs[PLPAR_HCALL9_BUFSIZE];
618
619 ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
620 adapter_handle.handle, /* r4 */
621 qp_handle.handle, /* r5 */
622 port, /* r6 */
623 0, 0, 0, 0, 0, 0);
624 *pma_qp_nr = (u32)outs[0];
625 *bma_qp_nr = (u32)outs[1];
626
627 if (ret == H_ALIAS_EXIST)
628 ehca_gen_err("AQP1 already exists. ret=%lx", ret);
629
630 return ret;
631}
632
633u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
634 const struct ipz_qp_handle qp_handle,
635 struct h_galpa gal,
636 u16 mcg_dlid,
637 u64 subnet_prefix, u64 interface_id)
638{
639 u64 ret;
640
641 ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
642 adapter_handle.handle, /* r4 */
643 qp_handle.handle, /* r5 */
644 mcg_dlid, /* r6 */
645 interface_id, /* r7 */
646 subnet_prefix, /* r8 */
647 0, 0);
648
649 if (ret == H_NOT_ENOUGH_RESOURCES)
650 ehca_gen_err("Not enough resources. ret=%lx", ret);
651
652 return ret;
653}
654
655u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
656 const struct ipz_qp_handle qp_handle,
657 struct h_galpa gal,
658 u16 mcg_dlid,
659 u64 subnet_prefix, u64 interface_id)
660{
661 return ehca_plpar_hcall_norets(H_DETACH_MCQP,
662 adapter_handle.handle, /* r4 */
663 qp_handle.handle, /* r5 */
664 mcg_dlid, /* r6 */
665 interface_id, /* r7 */
666 subnet_prefix, /* r8 */
667 0, 0);
668}
669
670u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
671 struct ehca_cq *cq,
672 u8 force_flag)
673{
674 u64 ret;
675
676 ret = hcp_galpas_dtor(&cq->galpas);
677 if (ret) {
678 ehca_gen_err("Could not destruct cp->galpas");
679 return H_RESOURCE;
680 }
681
682 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
683 adapter_handle.handle, /* r4 */
684 cq->ipz_cq_handle.handle, /* r5 */
685 force_flag != 0 ? 1L : 0L, /* r6 */
686 0, 0, 0, 0);
687
688 if (ret == H_RESOURCE)
689 ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret);
690
691 return ret;
692}
693
694u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
695 struct ehca_eq *eq)
696{
697 u64 ret;
698
699 ret = hcp_galpas_dtor(&eq->galpas);
700 if (ret) {
701 ehca_gen_err("Could not destruct eq->galpas");
702 return H_RESOURCE;
703 }
704
705 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
706 adapter_handle.handle, /* r4 */
707 eq->ipz_eq_handle.handle, /* r5 */
708 0, 0, 0, 0, 0);
709
710 if (ret == H_RESOURCE)
711 ehca_gen_err("Resource in use. ret=%lx ", ret);
712
713 return ret;
714}
715
716u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
717 const struct ehca_mr *mr,
718 const u64 vaddr,
719 const u64 length,
720 const u32 access_ctrl,
721 const struct ipz_pd pd,
722 struct ehca_mr_hipzout_parms *outparms)
723{
724 u64 ret;
725 u64 outs[PLPAR_HCALL9_BUFSIZE];
726
727 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
728 adapter_handle.handle, /* r4 */
729 5, /* r5 */
730 vaddr, /* r6 */
731 length, /* r7 */
732 (((u64)access_ctrl) << 32ULL), /* r8 */
733 pd.value, /* r9 */
734 0, 0, 0);
735 outparms->handle.handle = outs[0];
736 outparms->lkey = (u32)outs[2];
737 outparms->rkey = (u32)outs[3];
738
739 return ret;
740}
741
742u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
743 const struct ehca_mr *mr,
744 const u8 pagesize,
745 const u8 queue_type,
746 const u64 logical_address_of_page,
747 const u64 count)
748{
749 u64 ret;
750
751 if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
752 ehca_gen_err("logical_address_of_page not on a 4k boundary "
753 "adapter_handle=%lx mr=%p mr_handle=%lx "
754 "pagesize=%x queue_type=%x "
755 "logical_address_of_page=%lx count=%lx",
756 adapter_handle.handle, mr,
757 mr->ipz_mr_handle.handle, pagesize, queue_type,
758 logical_address_of_page, count);
759 ret = H_PARAMETER;
760 } else
761 ret = hipz_h_register_rpage(adapter_handle, pagesize,
762 queue_type,
763 mr->ipz_mr_handle.handle,
764 logical_address_of_page, count);
765 return ret;
766}
767
768u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
769 const struct ehca_mr *mr,
770 struct ehca_mr_hipzout_parms *outparms)
771{
772 u64 ret;
773 u64 outs[PLPAR_HCALL9_BUFSIZE];
774
775 ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
776 adapter_handle.handle, /* r4 */
777 mr->ipz_mr_handle.handle, /* r5 */
778 0, 0, 0, 0, 0, 0, 0);
779 outparms->len = outs[0];
780 outparms->vaddr = outs[1];
781 outparms->acl = outs[4] >> 32;
782 outparms->lkey = (u32)(outs[5] >> 32);
783 outparms->rkey = (u32)(outs[5] & (0xffffffff));
784
785 return ret;
786}
787
788u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
789 const struct ehca_mr *mr)
790{
791 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
792 adapter_handle.handle, /* r4 */
793 mr->ipz_mr_handle.handle, /* r5 */
794 0, 0, 0, 0, 0);
795}
796
797u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
798 const struct ehca_mr *mr,
799 const u64 vaddr_in,
800 const u64 length,
801 const u32 access_ctrl,
802 const struct ipz_pd pd,
803 const u64 mr_addr_cb,
804 struct ehca_mr_hipzout_parms *outparms)
805{
806 u64 ret;
807 u64 outs[PLPAR_HCALL9_BUFSIZE];
808
809 ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
810 adapter_handle.handle, /* r4 */
811 mr->ipz_mr_handle.handle, /* r5 */
812 vaddr_in, /* r6 */
813 length, /* r7 */
814 /* r8 */
815 ((((u64)access_ctrl) << 32ULL) | pd.value),
816 mr_addr_cb, /* r9 */
817 0, 0, 0);
818 outparms->vaddr = outs[1];
819 outparms->lkey = (u32)outs[2];
820 outparms->rkey = (u32)outs[3];
821
822 return ret;
823}
824
825u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
826 const struct ehca_mr *mr,
827 const struct ehca_mr *orig_mr,
828 const u64 vaddr_in,
829 const u32 access_ctrl,
830 const struct ipz_pd pd,
831 struct ehca_mr_hipzout_parms *outparms)
832{
833 u64 ret;
834 u64 outs[PLPAR_HCALL9_BUFSIZE];
835
836 ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
837 adapter_handle.handle, /* r4 */
838 orig_mr->ipz_mr_handle.handle, /* r5 */
839 vaddr_in, /* r6 */
840 (((u64)access_ctrl) << 32ULL), /* r7 */
841 pd.value, /* r8 */
842 0, 0, 0, 0);
843 outparms->handle.handle = outs[0];
844 outparms->lkey = (u32)outs[2];
845 outparms->rkey = (u32)outs[3];
846
847 return ret;
848}
849
850u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
851 const struct ehca_mw *mw,
852 const struct ipz_pd pd,
853 struct ehca_mw_hipzout_parms *outparms)
854{
855 u64 ret;
856 u64 outs[PLPAR_HCALL9_BUFSIZE];
857
858 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
859 adapter_handle.handle, /* r4 */
860 6, /* r5 */
861 pd.value, /* r6 */
862 0, 0, 0, 0, 0, 0);
863 outparms->handle.handle = outs[0];
864 outparms->rkey = (u32)outs[3];
865
866 return ret;
867}
868
869u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
870 const struct ehca_mw *mw,
871 struct ehca_mw_hipzout_parms *outparms)
872{
873 u64 ret;
874 u64 outs[PLPAR_HCALL9_BUFSIZE];
875
876 ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
877 adapter_handle.handle, /* r4 */
878 mw->ipz_mw_handle.handle, /* r5 */
879 0, 0, 0, 0, 0, 0, 0);
880 outparms->rkey = (u32)outs[3];
881
882 return ret;
883}
884
885u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
886 const struct ehca_mw *mw)
887{
888 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
889 adapter_handle.handle, /* r4 */
890 mw->ipz_mw_handle.handle, /* r5 */
891 0, 0, 0, 0, 0);
892}
893
894u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
895 const u64 ressource_handle,
896 void *rblock,
897 unsigned long *byte_count)
898{
899 u64 r_cb = virt_to_abs(rblock);
900
901 if (r_cb & (EHCA_PAGESIZE-1)) {
902 ehca_gen_err("rblock not page aligned.");
903 return H_PARAMETER;
904 }
905
906 return ehca_plpar_hcall_norets(H_ERROR_DATA,
907 adapter_handle.handle,
908 ressource_handle,
909 r_cb,
910 0, 0, 0, 0);
911}