blob: 358796ccf00894607bc37e75f94cf2afe134372b [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 */
Hoang-Nam Nguyen5bb7d922007-07-20 16:01:51 +0200430 (u64)queue_type | ((u64)pagesize) << 8,
431 /* r5 */
Heiko J Schickfab97222006-09-22 15:22:22 -0700432 resource_handle, /* r6 */
433 logical_address_of_page, /* r7 */
434 count, /* r8 */
435 0, 0);
436}
437
438u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
439 const struct ipz_eq_handle eq_handle,
440 struct ehca_pfeq *pfeq,
441 const u8 pagesize,
442 const u8 queue_type,
443 const u64 logical_address_of_page,
444 const u64 count)
445{
446 if (count != 1) {
447 ehca_gen_err("Ppage counter=%lx", count);
448 return H_PARAMETER;
449 }
450 return hipz_h_register_rpage(adapter_handle,
451 pagesize,
452 queue_type,
453 eq_handle.handle,
454 logical_address_of_page, count);
455}
456
457u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
458 u32 ist)
459{
460 u64 ret;
461 ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
462 adapter_handle.handle, /* r4 */
463 ist, /* r5 */
464 0, 0, 0, 0, 0);
465
466 if (ret != H_SUCCESS && ret != H_BUSY)
467 ehca_gen_err("Could not query interrupt state.");
468
469 return ret;
470}
471
472u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
473 const struct ipz_cq_handle cq_handle,
474 struct ehca_pfcq *pfcq,
475 const u8 pagesize,
476 const u8 queue_type,
477 const u64 logical_address_of_page,
478 const u64 count,
479 const struct h_galpa gal)
480{
481 if (count != 1) {
482 ehca_gen_err("Page counter=%lx", count);
483 return H_PARAMETER;
484 }
485
486 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
487 cq_handle.handle, logical_address_of_page,
488 count);
489}
490
491u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
492 const struct ipz_qp_handle qp_handle,
493 struct ehca_pfqp *pfqp,
494 const u8 pagesize,
495 const u8 queue_type,
496 const u64 logical_address_of_page,
497 const u64 count,
498 const struct h_galpa galpa)
499{
500 if (count != 1) {
501 ehca_gen_err("Page counter=%lx", count);
502 return H_PARAMETER;
503 }
504
Hoang-Nam Nguyen2b943972007-07-12 17:53:47 +0200505 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
506 qp_handle.handle, logical_address_of_page,
Heiko J Schickfab97222006-09-22 15:22:22 -0700507 count);
508}
509
510u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
511 const struct ipz_qp_handle qp_handle,
512 struct ehca_pfqp *pfqp,
513 void **log_addr_next_sq_wqe2processed,
514 void **log_addr_next_rq_wqe2processed,
515 int dis_and_get_function_code)
516{
517 u64 ret;
518 u64 outs[PLPAR_HCALL9_BUFSIZE];
519
520 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
521 adapter_handle.handle, /* r4 */
522 dis_and_get_function_code, /* r5 */
523 qp_handle.handle, /* r6 */
524 0, 0, 0, 0, 0, 0);
525 if (log_addr_next_sq_wqe2processed)
Hoang-Nam Nguyen2b943972007-07-12 17:53:47 +0200526 *log_addr_next_sq_wqe2processed = (void *)outs[0];
Heiko J Schickfab97222006-09-22 15:22:22 -0700527 if (log_addr_next_rq_wqe2processed)
Hoang-Nam Nguyen2b943972007-07-12 17:53:47 +0200528 *log_addr_next_rq_wqe2processed = (void *)outs[1];
Heiko J Schickfab97222006-09-22 15:22:22 -0700529
530 return ret;
531}
532
533u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
534 const struct ipz_qp_handle qp_handle,
535 struct ehca_pfqp *pfqp,
536 const u64 update_mask,
537 struct hcp_modify_qp_control_block *mqpcb,
538 struct h_galpa gal)
539{
540 u64 ret;
541 u64 outs[PLPAR_HCALL9_BUFSIZE];
542 ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
543 adapter_handle.handle, /* r4 */
544 qp_handle.handle, /* r5 */
545 update_mask, /* r6 */
546 virt_to_abs(mqpcb), /* r7 */
547 0, 0, 0, 0, 0);
548
549 if (ret == H_NOT_ENOUGH_RESOURCES)
550 ehca_gen_err("Insufficient resources ret=%lx", ret);
551
552 return ret;
553}
554
555u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
556 const struct ipz_qp_handle qp_handle,
557 struct ehca_pfqp *pfqp,
558 struct hcp_modify_qp_control_block *qqpcb,
559 struct h_galpa gal)
560{
561 return ehca_plpar_hcall_norets(H_QUERY_QP,
562 adapter_handle.handle, /* r4 */
563 qp_handle.handle, /* r5 */
564 virt_to_abs(qqpcb), /* r6 */
565 0, 0, 0, 0);
566}
567
568u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
569 struct ehca_qp *qp)
570{
571 u64 ret;
572 u64 outs[PLPAR_HCALL9_BUFSIZE];
573
574 ret = hcp_galpas_dtor(&qp->galpas);
575 if (ret) {
576 ehca_gen_err("Could not destruct qp->galpas");
577 return H_RESOURCE;
578 }
579 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
580 adapter_handle.handle, /* r4 */
581 /* function code */
582 1, /* r5 */
583 qp->ipz_qp_handle.handle, /* r6 */
584 0, 0, 0, 0, 0, 0);
585 if (ret == H_HARDWARE)
586 ehca_gen_err("HCA not operational. ret=%lx", ret);
587
588 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
589 adapter_handle.handle, /* r4 */
590 qp->ipz_qp_handle.handle, /* r5 */
591 0, 0, 0, 0, 0);
592
593 if (ret == H_RESOURCE)
594 ehca_gen_err("Resource still in use. ret=%lx", ret);
595
596 return ret;
597}
598
599u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
600 const struct ipz_qp_handle qp_handle,
601 struct h_galpa gal,
602 u32 port)
603{
604 return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
605 adapter_handle.handle, /* r4 */
606 qp_handle.handle, /* r5 */
607 port, /* r6 */
608 0, 0, 0, 0);
609}
610
611u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
612 const struct ipz_qp_handle qp_handle,
613 struct h_galpa gal,
614 u32 port, u32 * pma_qp_nr,
615 u32 * bma_qp_nr)
616{
617 u64 ret;
618 u64 outs[PLPAR_HCALL9_BUFSIZE];
619
620 ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
621 adapter_handle.handle, /* r4 */
622 qp_handle.handle, /* r5 */
623 port, /* r6 */
624 0, 0, 0, 0, 0, 0);
625 *pma_qp_nr = (u32)outs[0];
626 *bma_qp_nr = (u32)outs[1];
627
628 if (ret == H_ALIAS_EXIST)
629 ehca_gen_err("AQP1 already exists. ret=%lx", ret);
630
631 return ret;
632}
633
634u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
635 const struct ipz_qp_handle qp_handle,
636 struct h_galpa gal,
637 u16 mcg_dlid,
638 u64 subnet_prefix, u64 interface_id)
639{
640 u64 ret;
641
642 ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
643 adapter_handle.handle, /* r4 */
644 qp_handle.handle, /* r5 */
645 mcg_dlid, /* r6 */
646 interface_id, /* r7 */
647 subnet_prefix, /* r8 */
648 0, 0);
649
650 if (ret == H_NOT_ENOUGH_RESOURCES)
651 ehca_gen_err("Not enough resources. ret=%lx", ret);
652
653 return ret;
654}
655
656u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
657 const struct ipz_qp_handle qp_handle,
658 struct h_galpa gal,
659 u16 mcg_dlid,
660 u64 subnet_prefix, u64 interface_id)
661{
662 return ehca_plpar_hcall_norets(H_DETACH_MCQP,
663 adapter_handle.handle, /* r4 */
664 qp_handle.handle, /* r5 */
665 mcg_dlid, /* r6 */
666 interface_id, /* r7 */
667 subnet_prefix, /* r8 */
668 0, 0);
669}
670
671u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
672 struct ehca_cq *cq,
673 u8 force_flag)
674{
675 u64 ret;
676
677 ret = hcp_galpas_dtor(&cq->galpas);
678 if (ret) {
679 ehca_gen_err("Could not destruct cp->galpas");
680 return H_RESOURCE;
681 }
682
683 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
684 adapter_handle.handle, /* r4 */
685 cq->ipz_cq_handle.handle, /* r5 */
686 force_flag != 0 ? 1L : 0L, /* r6 */
687 0, 0, 0, 0);
688
689 if (ret == H_RESOURCE)
690 ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret);
691
692 return ret;
693}
694
695u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
696 struct ehca_eq *eq)
697{
698 u64 ret;
699
700 ret = hcp_galpas_dtor(&eq->galpas);
701 if (ret) {
702 ehca_gen_err("Could not destruct eq->galpas");
703 return H_RESOURCE;
704 }
705
706 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
707 adapter_handle.handle, /* r4 */
708 eq->ipz_eq_handle.handle, /* r5 */
709 0, 0, 0, 0, 0);
710
711 if (ret == H_RESOURCE)
712 ehca_gen_err("Resource in use. ret=%lx ", ret);
713
714 return ret;
715}
716
717u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
718 const struct ehca_mr *mr,
719 const u64 vaddr,
720 const u64 length,
721 const u32 access_ctrl,
722 const struct ipz_pd pd,
723 struct ehca_mr_hipzout_parms *outparms)
724{
725 u64 ret;
726 u64 outs[PLPAR_HCALL9_BUFSIZE];
727
Hoang-Nam Nguyen5bb7d922007-07-20 16:01:51 +0200728 ehca_gen_dbg("kernel PAGE_SIZE=%x access_ctrl=%016x "
729 "vaddr=%lx length=%lx",
730 (u32)PAGE_SIZE, access_ctrl, vaddr, length);
Heiko J Schickfab97222006-09-22 15:22:22 -0700731 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
732 adapter_handle.handle, /* r4 */
733 5, /* r5 */
734 vaddr, /* r6 */
735 length, /* r7 */
736 (((u64)access_ctrl) << 32ULL), /* r8 */
737 pd.value, /* r9 */
738 0, 0, 0);
739 outparms->handle.handle = outs[0];
740 outparms->lkey = (u32)outs[2];
741 outparms->rkey = (u32)outs[3];
742
743 return ret;
744}
745
746u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
747 const struct ehca_mr *mr,
748 const u8 pagesize,
749 const u8 queue_type,
750 const u64 logical_address_of_page,
751 const u64 count)
752{
Hoang-Nam Nguyen5bb7d922007-07-20 16:01:51 +0200753 extern int ehca_debug_level;
Heiko J Schickfab97222006-09-22 15:22:22 -0700754 u64 ret;
755
Hoang-Nam Nguyen5bb7d922007-07-20 16:01:51 +0200756 if (unlikely(ehca_debug_level >= 2)) {
757 if (count > 1) {
758 u64 *kpage;
759 int i;
760 kpage = (u64 *)abs_to_virt(logical_address_of_page);
761 for (i = 0; i < count; i++)
762 ehca_gen_dbg("kpage[%d]=%p",
763 i, (void *)kpage[i]);
764 } else
765 ehca_gen_dbg("kpage=%p",
766 (void *)logical_address_of_page);
767 }
768
Heiko J Schickfab97222006-09-22 15:22:22 -0700769 if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
770 ehca_gen_err("logical_address_of_page not on a 4k boundary "
771 "adapter_handle=%lx mr=%p mr_handle=%lx "
772 "pagesize=%x queue_type=%x "
773 "logical_address_of_page=%lx count=%lx",
774 adapter_handle.handle, mr,
775 mr->ipz_mr_handle.handle, pagesize, queue_type,
776 logical_address_of_page, count);
777 ret = H_PARAMETER;
778 } else
779 ret = hipz_h_register_rpage(adapter_handle, pagesize,
780 queue_type,
781 mr->ipz_mr_handle.handle,
782 logical_address_of_page, count);
783 return ret;
784}
785
786u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
787 const struct ehca_mr *mr,
788 struct ehca_mr_hipzout_parms *outparms)
789{
790 u64 ret;
791 u64 outs[PLPAR_HCALL9_BUFSIZE];
792
793 ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
794 adapter_handle.handle, /* r4 */
795 mr->ipz_mr_handle.handle, /* r5 */
796 0, 0, 0, 0, 0, 0, 0);
797 outparms->len = outs[0];
798 outparms->vaddr = outs[1];
799 outparms->acl = outs[4] >> 32;
800 outparms->lkey = (u32)(outs[5] >> 32);
801 outparms->rkey = (u32)(outs[5] & (0xffffffff));
802
803 return ret;
804}
805
806u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
807 const struct ehca_mr *mr)
808{
809 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
810 adapter_handle.handle, /* r4 */
811 mr->ipz_mr_handle.handle, /* r5 */
812 0, 0, 0, 0, 0);
813}
814
815u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
816 const struct ehca_mr *mr,
817 const u64 vaddr_in,
818 const u64 length,
819 const u32 access_ctrl,
820 const struct ipz_pd pd,
821 const u64 mr_addr_cb,
822 struct ehca_mr_hipzout_parms *outparms)
823{
824 u64 ret;
825 u64 outs[PLPAR_HCALL9_BUFSIZE];
826
827 ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
828 adapter_handle.handle, /* r4 */
829 mr->ipz_mr_handle.handle, /* r5 */
830 vaddr_in, /* r6 */
831 length, /* r7 */
832 /* r8 */
833 ((((u64)access_ctrl) << 32ULL) | pd.value),
834 mr_addr_cb, /* r9 */
835 0, 0, 0);
836 outparms->vaddr = outs[1];
837 outparms->lkey = (u32)outs[2];
838 outparms->rkey = (u32)outs[3];
839
840 return ret;
841}
842
843u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
844 const struct ehca_mr *mr,
845 const struct ehca_mr *orig_mr,
846 const u64 vaddr_in,
847 const u32 access_ctrl,
848 const struct ipz_pd pd,
849 struct ehca_mr_hipzout_parms *outparms)
850{
851 u64 ret;
852 u64 outs[PLPAR_HCALL9_BUFSIZE];
853
854 ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
855 adapter_handle.handle, /* r4 */
856 orig_mr->ipz_mr_handle.handle, /* r5 */
857 vaddr_in, /* r6 */
858 (((u64)access_ctrl) << 32ULL), /* r7 */
859 pd.value, /* r8 */
860 0, 0, 0, 0);
861 outparms->handle.handle = outs[0];
862 outparms->lkey = (u32)outs[2];
863 outparms->rkey = (u32)outs[3];
864
865 return ret;
866}
867
868u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
869 const struct ehca_mw *mw,
870 const struct ipz_pd pd,
871 struct ehca_mw_hipzout_parms *outparms)
872{
873 u64 ret;
874 u64 outs[PLPAR_HCALL9_BUFSIZE];
875
876 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
877 adapter_handle.handle, /* r4 */
878 6, /* r5 */
879 pd.value, /* r6 */
880 0, 0, 0, 0, 0, 0);
881 outparms->handle.handle = outs[0];
882 outparms->rkey = (u32)outs[3];
883
884 return ret;
885}
886
887u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
888 const struct ehca_mw *mw,
889 struct ehca_mw_hipzout_parms *outparms)
890{
891 u64 ret;
892 u64 outs[PLPAR_HCALL9_BUFSIZE];
893
894 ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
895 adapter_handle.handle, /* r4 */
896 mw->ipz_mw_handle.handle, /* r5 */
897 0, 0, 0, 0, 0, 0, 0);
898 outparms->rkey = (u32)outs[3];
899
900 return ret;
901}
902
903u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
904 const struct ehca_mw *mw)
905{
906 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
907 adapter_handle.handle, /* r4 */
908 mw->ipz_mw_handle.handle, /* r5 */
909 0, 0, 0, 0, 0);
910}
911
912u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
913 const u64 ressource_handle,
914 void *rblock,
915 unsigned long *byte_count)
916{
917 u64 r_cb = virt_to_abs(rblock);
918
919 if (r_cb & (EHCA_PAGESIZE-1)) {
920 ehca_gen_err("rblock not page aligned.");
921 return H_PARAMETER;
922 }
923
924 return ehca_plpar_hcall_norets(H_ERROR_DATA,
925 adapter_handle.handle,
926 ressource_handle,
927 r_cb,
928 0, 0, 0, 0);
929}