blob: 24f454162f2479029255a3b4097a6ad7b0a61c0b [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)
Stefan Roschere2f81da2007-07-20 16:04:17 +020055#define H_ALL_RES_QP_STORAGE EHCA_BMASK_IBM(16, 17)
Heiko J Schickfab97222006-09-22 15:22:22 -070056#define H_ALL_RES_QP_LL_RQ_CQE_POSTING EHCA_BMASK_IBM(18, 18)
57#define H_ALL_RES_QP_LL_SQ_CQE_POSTING EHCA_BMASK_IBM(19, 21)
58#define H_ALL_RES_QP_SIGNALING_TYPE EHCA_BMASK_IBM(22, 23)
59#define H_ALL_RES_QP_UD_AV_LKEY_CTRL EHCA_BMASK_IBM(31, 31)
Stefan Roschere2f81da2007-07-20 16:04:17 +020060#define H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE EHCA_BMASK_IBM(32, 35)
61#define H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE EHCA_BMASK_IBM(36, 39)
Heiko J Schickfab97222006-09-22 15:22:22 -070062#define H_ALL_RES_QP_RESOURCE_TYPE EHCA_BMASK_IBM(56, 63)
63
64#define H_ALL_RES_QP_MAX_OUTST_SEND_WR EHCA_BMASK_IBM(0, 15)
65#define H_ALL_RES_QP_MAX_OUTST_RECV_WR EHCA_BMASK_IBM(16, 31)
66#define H_ALL_RES_QP_MAX_SEND_SGE EHCA_BMASK_IBM(32, 39)
67#define H_ALL_RES_QP_MAX_RECV_SGE EHCA_BMASK_IBM(40, 47)
68
Joachim Fenkesa6a12942007-07-09 15:25:10 +020069#define H_ALL_RES_QP_UD_AV_LKEY EHCA_BMASK_IBM(32, 63)
70#define H_ALL_RES_QP_SRQ_QP_TOKEN EHCA_BMASK_IBM(0, 31)
71#define H_ALL_RES_QP_SRQ_QP_HANDLE EHCA_BMASK_IBM(0, 64)
72#define H_ALL_RES_QP_SRQ_LIMIT EHCA_BMASK_IBM(48, 63)
73#define H_ALL_RES_QP_SRQ_QPN EHCA_BMASK_IBM(40, 63)
74
Heiko J Schickfab97222006-09-22 15:22:22 -070075#define H_ALL_RES_QP_ACT_OUTST_SEND_WR EHCA_BMASK_IBM(16, 31)
76#define H_ALL_RES_QP_ACT_OUTST_RECV_WR EHCA_BMASK_IBM(48, 63)
77#define H_ALL_RES_QP_ACT_SEND_SGE EHCA_BMASK_IBM(8, 15)
78#define H_ALL_RES_QP_ACT_RECV_SGE EHCA_BMASK_IBM(24, 31)
79
80#define H_ALL_RES_QP_SQUEUE_SIZE_PAGES EHCA_BMASK_IBM(0, 31)
81#define H_ALL_RES_QP_RQUEUE_SIZE_PAGES EHCA_BMASK_IBM(32, 63)
82
Joachim Fenkesc4ed7902007-04-24 17:44:31 +020083#define H_MP_INIT_TYPE EHCA_BMASK_IBM(44, 47)
84#define H_MP_SHUTDOWN EHCA_BMASK_IBM(48, 48)
85#define H_MP_RESET_QKEY_CTR EHCA_BMASK_IBM(49, 49)
86
Joachim Fenkes9844b712007-07-09 15:29:03 +020087static DEFINE_SPINLOCK(hcall_lock);
88
Heiko J Schickfab97222006-09-22 15:22:22 -070089static u32 get_longbusy_msecs(int longbusy_rc)
90{
91 switch (longbusy_rc) {
92 case H_LONG_BUSY_ORDER_1_MSEC:
93 return 1;
94 case H_LONG_BUSY_ORDER_10_MSEC:
95 return 10;
96 case H_LONG_BUSY_ORDER_100_MSEC:
97 return 100;
98 case H_LONG_BUSY_ORDER_1_SEC:
99 return 1000;
100 case H_LONG_BUSY_ORDER_10_SEC:
101 return 10000;
102 case H_LONG_BUSY_ORDER_100_SEC:
103 return 100000;
104 default:
105 return 1;
106 }
107}
108
109static long ehca_plpar_hcall_norets(unsigned long opcode,
110 unsigned long arg1,
111 unsigned long arg2,
112 unsigned long arg3,
113 unsigned long arg4,
114 unsigned long arg5,
115 unsigned long arg6,
116 unsigned long arg7)
117{
118 long ret;
119 int i, sleep_msecs;
120
121 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
122 "arg5=%lx arg6=%lx arg7=%lx",
123 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
124
125 for (i = 0; i < 5; i++) {
126 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
127 arg5, arg6, arg7);
128
129 if (H_IS_LONG_BUSY(ret)) {
130 sleep_msecs = get_longbusy_msecs(ret);
131 msleep_interruptible(sleep_msecs);
132 continue;
133 }
134
135 if (ret < H_SUCCESS)
136 ehca_gen_err("opcode=%lx ret=%lx"
137 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
138 " arg5=%lx arg6=%lx arg7=%lx ",
139 opcode, ret,
140 arg1, arg2, arg3, arg4, arg5,
141 arg6, arg7);
142
143 ehca_gen_dbg("opcode=%lx ret=%lx", opcode, ret);
144 return ret;
145
146 }
147
148 return H_BUSY;
149}
150
151static long ehca_plpar_hcall9(unsigned long opcode,
152 unsigned long *outs, /* array of 9 outputs */
153 unsigned long arg1,
154 unsigned long arg2,
155 unsigned long arg3,
156 unsigned long arg4,
157 unsigned long arg5,
158 unsigned long arg6,
159 unsigned long arg7,
160 unsigned long arg8,
161 unsigned long arg9)
162{
163 long ret;
Stefan Roscher5d882782007-05-09 13:47:56 +0200164 int i, sleep_msecs, lock_is_set = 0;
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200165 unsigned long flags = 0;
Heiko J Schickfab97222006-09-22 15:22:22 -0700166
167 ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
168 "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
169 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
170 arg8, arg9);
171
172 for (i = 0; i < 5; i++) {
Stefan Roscher5d882782007-05-09 13:47:56 +0200173 if ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)) {
174 spin_lock_irqsave(&hcall_lock, flags);
175 lock_is_set = 1;
176 }
177
Heiko J Schickfab97222006-09-22 15:22:22 -0700178 ret = plpar_hcall9(opcode, outs,
179 arg1, arg2, arg3, arg4, arg5,
180 arg6, arg7, arg8, arg9);
181
Stefan Roscher5d882782007-05-09 13:47:56 +0200182 if (lock_is_set)
183 spin_unlock_irqrestore(&hcall_lock, flags);
184
Heiko J Schickfab97222006-09-22 15:22:22 -0700185 if (H_IS_LONG_BUSY(ret)) {
186 sleep_msecs = get_longbusy_msecs(ret);
187 msleep_interruptible(sleep_msecs);
188 continue;
189 }
190
191 if (ret < H_SUCCESS)
192 ehca_gen_err("opcode=%lx ret=%lx"
193 " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
194 " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
195 " arg9=%lx"
196 " out1=%lx out2=%lx out3=%lx out4=%lx"
197 " out5=%lx out6=%lx out7=%lx out8=%lx"
198 " out9=%lx",
199 opcode, ret,
200 arg1, arg2, arg3, arg4, arg5,
201 arg6, arg7, arg8, arg9,
202 outs[0], outs[1], outs[2], outs[3],
203 outs[4], outs[5], outs[6], outs[7],
204 outs[8]);
205
206 ehca_gen_dbg("opcode=%lx ret=%lx out1=%lx out2=%lx out3=%lx "
207 "out4=%lx out5=%lx out6=%lx out7=%lx out8=%lx "
208 "out9=%lx",
209 opcode, ret, outs[0], outs[1], outs[2], outs[3],
210 outs[4], outs[5], outs[6], outs[7], outs[8]);
211 return ret;
Heiko J Schickfab97222006-09-22 15:22:22 -0700212 }
213
214 return H_BUSY;
215}
Stefan Roscher5d882782007-05-09 13:47:56 +0200216
Heiko J Schickfab97222006-09-22 15:22:22 -0700217u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
218 struct ehca_pfeq *pfeq,
219 const u32 neq_control,
220 const u32 number_of_entries,
221 struct ipz_eq_handle *eq_handle,
222 u32 *act_nr_of_entries,
223 u32 *act_pages,
224 u32 *eq_ist)
225{
226 u64 ret;
227 u64 outs[PLPAR_HCALL9_BUFSIZE];
228 u64 allocate_controls;
229
230 /* resource type */
231 allocate_controls = 3ULL;
232
233 /* ISN is associated */
234 if (neq_control != 1)
235 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
236 else /* notification event queue */
237 allocate_controls = (1ULL << 63) | allocate_controls;
238
239 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
240 adapter_handle.handle, /* r4 */
241 allocate_controls, /* r5 */
242 number_of_entries, /* r6 */
243 0, 0, 0, 0, 0, 0);
244 eq_handle->handle = outs[0];
245 *act_nr_of_entries = (u32)outs[3];
246 *act_pages = (u32)outs[4];
247 *eq_ist = (u32)outs[5];
248
249 if (ret == H_NOT_ENOUGH_RESOURCES)
250 ehca_gen_err("Not enough resource - ret=%lx ", ret);
251
252 return ret;
253}
254
255u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
256 struct ipz_eq_handle eq_handle,
257 const u64 event_mask)
258{
259 return ehca_plpar_hcall_norets(H_RESET_EVENTS,
260 adapter_handle.handle, /* r4 */
261 eq_handle.handle, /* r5 */
262 event_mask, /* r6 */
263 0, 0, 0, 0);
264}
265
266u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
267 struct ehca_cq *cq,
268 struct ehca_alloc_cq_parms *param)
269{
270 u64 ret;
271 u64 outs[PLPAR_HCALL9_BUFSIZE];
272
273 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
274 adapter_handle.handle, /* r4 */
275 2, /* r5 */
276 param->eq_handle.handle, /* r6 */
277 cq->token, /* r7 */
278 param->nr_cqe, /* r8 */
279 0, 0, 0, 0);
280 cq->ipz_cq_handle.handle = outs[0];
281 param->act_nr_of_entries = (u32)outs[3];
282 param->act_pages = (u32)outs[4];
283
284 if (ret == H_SUCCESS)
285 hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
286
287 if (ret == H_NOT_ENOUGH_RESOURCES)
288 ehca_gen_err("Not enough resources. ret=%lx", ret);
289
290 return ret;
291}
292
293u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
Heiko J Schickfab97222006-09-22 15:22:22 -0700294 struct ehca_alloc_qp_parms *parms)
295{
296 u64 ret;
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200297 u64 allocate_controls, max_r10_reg, r11, r12;
Heiko J Schickfab97222006-09-22 15:22:22 -0700298 u64 outs[PLPAR_HCALL9_BUFSIZE];
Heiko J Schickfab97222006-09-22 15:22:22 -0700299
300 allocate_controls =
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200301 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
Heiko J Schickfab97222006-09-22 15:22:22 -0700302 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
303 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
304 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
Stefan Roschere2f81da2007-07-20 16:04:17 +0200305 | EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage)
306 | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE,
307 parms->squeue.page_size)
308 | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE,
309 parms->rqueue.page_size)
Heiko J Schickfab97222006-09-22 15:22:22 -0700310 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200311 !!(parms->ll_comp_flags & LLQP_RECV_COMP))
Heiko J Schickfab97222006-09-22 15:22:22 -0700312 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200313 !!(parms->ll_comp_flags & LLQP_SEND_COMP))
Heiko J Schickfab97222006-09-22 15:22:22 -0700314 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
315 parms->ud_av_l_key_ctl)
316 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
317
318 max_r10_reg =
319 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
Stefan Roschere2f81da2007-07-20 16:04:17 +0200320 parms->squeue.max_wr + 1)
Heiko J Schickfab97222006-09-22 15:22:22 -0700321 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
Stefan Roschere2f81da2007-07-20 16:04:17 +0200322 parms->rqueue.max_wr + 1)
Heiko J Schickfab97222006-09-22 15:22:22 -0700323 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
Stefan Roschere2f81da2007-07-20 16:04:17 +0200324 parms->squeue.max_sge)
Heiko J Schickfab97222006-09-22 15:22:22 -0700325 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
Stefan Roschere2f81da2007-07-20 16:04:17 +0200326 parms->rqueue.max_sge);
Heiko J Schickfab97222006-09-22 15:22:22 -0700327
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200328 r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
329
330 if (parms->ext_type == EQPT_SRQ)
331 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
332 else
333 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
334
Heiko J Schickfab97222006-09-22 15:22:22 -0700335 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
336 adapter_handle.handle, /* r4 */
337 allocate_controls, /* r5 */
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200338 parms->send_cq_handle.handle,
339 parms->recv_cq_handle.handle,
340 parms->eq_handle.handle,
341 ((u64)parms->token << 32) | parms->pd.value,
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200342 max_r10_reg, r11, r12);
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200343
344 parms->qp_handle.handle = outs[0];
345 parms->real_qp_num = (u32)outs[1];
Stefan Roschere2f81da2007-07-20 16:04:17 +0200346 parms->squeue.act_nr_wqes =
Heiko J Schickfab97222006-09-22 15:22:22 -0700347 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
Stefan Roschere2f81da2007-07-20 16:04:17 +0200348 parms->rqueue.act_nr_wqes =
Heiko J Schickfab97222006-09-22 15:22:22 -0700349 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
Stefan Roschere2f81da2007-07-20 16:04:17 +0200350 parms->squeue.act_nr_sges =
Heiko J Schickfab97222006-09-22 15:22:22 -0700351 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
Stefan Roschere2f81da2007-07-20 16:04:17 +0200352 parms->rqueue.act_nr_sges =
Heiko J Schickfab97222006-09-22 15:22:22 -0700353 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
Stefan Roschere2f81da2007-07-20 16:04:17 +0200354 parms->squeue.queue_size =
Heiko J Schickfab97222006-09-22 15:22:22 -0700355 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
Stefan Roschere2f81da2007-07-20 16:04:17 +0200356 parms->rqueue.queue_size =
Heiko J Schickfab97222006-09-22 15:22:22 -0700357 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
358
359 if (ret == H_SUCCESS)
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200360 hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
Heiko J Schickfab97222006-09-22 15:22:22 -0700361
362 if (ret == H_NOT_ENOUGH_RESOURCES)
363 ehca_gen_err("Not enough resources. ret=%lx", ret);
364
365 return ret;
366}
367
368u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
369 const u8 port_id,
370 struct hipz_query_port *query_port_response_block)
371{
372 u64 ret;
373 u64 r_cb = virt_to_abs(query_port_response_block);
374
375 if (r_cb & (EHCA_PAGESIZE-1)) {
376 ehca_gen_err("response block not page aligned");
377 return H_PARAMETER;
378 }
379
380 ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
381 adapter_handle.handle, /* r4 */
382 port_id, /* r5 */
383 r_cb, /* r6 */
384 0, 0, 0, 0);
385
386 if (ehca_debug_level)
387 ehca_dmp(query_port_response_block, 64, "response_block");
388
389 return ret;
390}
391
Joachim Fenkesc4ed7902007-04-24 17:44:31 +0200392u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
393 const u8 port_id, const u32 port_cap,
394 const u8 init_type, const int modify_mask)
395{
396 u64 port_attributes = port_cap;
397
398 if (modify_mask & IB_PORT_SHUTDOWN)
399 port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
400 if (modify_mask & IB_PORT_INIT_TYPE)
401 port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
402 if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
403 port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
404
405 return ehca_plpar_hcall_norets(H_MODIFY_PORT,
406 adapter_handle.handle, /* r4 */
407 port_id, /* r5 */
408 port_attributes, /* r6 */
409 0, 0, 0, 0);
410}
411
Heiko J Schickfab97222006-09-22 15:22:22 -0700412u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
413 struct hipz_query_hca *query_hca_rblock)
414{
415 u64 r_cb = virt_to_abs(query_hca_rblock);
416
417 if (r_cb & (EHCA_PAGESIZE-1)) {
418 ehca_gen_err("response_block=%p not page aligned",
419 query_hca_rblock);
420 return H_PARAMETER;
421 }
422
423 return ehca_plpar_hcall_norets(H_QUERY_HCA,
424 adapter_handle.handle, /* r4 */
425 r_cb, /* r5 */
426 0, 0, 0, 0, 0);
427}
428
429u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
430 const u8 pagesize,
431 const u8 queue_type,
432 const u64 resource_handle,
433 const u64 logical_address_of_page,
434 u64 count)
435{
436 return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
437 adapter_handle.handle, /* r4 */
Hoang-Nam Nguyen5bb7d922007-07-20 16:01:51 +0200438 (u64)queue_type | ((u64)pagesize) << 8,
439 /* r5 */
Heiko J Schickfab97222006-09-22 15:22:22 -0700440 resource_handle, /* r6 */
441 logical_address_of_page, /* r7 */
442 count, /* r8 */
443 0, 0);
444}
445
446u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
447 const struct ipz_eq_handle eq_handle,
448 struct ehca_pfeq *pfeq,
449 const u8 pagesize,
450 const u8 queue_type,
451 const u64 logical_address_of_page,
452 const u64 count)
453{
454 if (count != 1) {
455 ehca_gen_err("Ppage counter=%lx", count);
456 return H_PARAMETER;
457 }
458 return hipz_h_register_rpage(adapter_handle,
459 pagesize,
460 queue_type,
461 eq_handle.handle,
462 logical_address_of_page, count);
463}
464
465u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
466 u32 ist)
467{
468 u64 ret;
469 ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
470 adapter_handle.handle, /* r4 */
471 ist, /* r5 */
472 0, 0, 0, 0, 0);
473
474 if (ret != H_SUCCESS && ret != H_BUSY)
475 ehca_gen_err("Could not query interrupt state.");
476
477 return ret;
478}
479
480u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
481 const struct ipz_cq_handle cq_handle,
482 struct ehca_pfcq *pfcq,
483 const u8 pagesize,
484 const u8 queue_type,
485 const u64 logical_address_of_page,
486 const u64 count,
487 const struct h_galpa gal)
488{
489 if (count != 1) {
490 ehca_gen_err("Page counter=%lx", count);
491 return H_PARAMETER;
492 }
493
494 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
495 cq_handle.handle, logical_address_of_page,
496 count);
497}
498
499u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
500 const struct ipz_qp_handle qp_handle,
501 struct ehca_pfqp *pfqp,
502 const u8 pagesize,
503 const u8 queue_type,
504 const u64 logical_address_of_page,
505 const u64 count,
506 const struct h_galpa galpa)
507{
Stefan Roschere2f81da2007-07-20 16:04:17 +0200508 if (count > 1) {
Heiko J Schickfab97222006-09-22 15:22:22 -0700509 ehca_gen_err("Page counter=%lx", count);
510 return H_PARAMETER;
511 }
512
Hoang-Nam Nguyen2b943972007-07-12 17:53:47 +0200513 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
514 qp_handle.handle, logical_address_of_page,
Heiko J Schickfab97222006-09-22 15:22:22 -0700515 count);
516}
517
518u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
519 const struct ipz_qp_handle qp_handle,
520 struct ehca_pfqp *pfqp,
521 void **log_addr_next_sq_wqe2processed,
522 void **log_addr_next_rq_wqe2processed,
523 int dis_and_get_function_code)
524{
525 u64 ret;
526 u64 outs[PLPAR_HCALL9_BUFSIZE];
527
528 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
529 adapter_handle.handle, /* r4 */
530 dis_and_get_function_code, /* r5 */
531 qp_handle.handle, /* r6 */
532 0, 0, 0, 0, 0, 0);
533 if (log_addr_next_sq_wqe2processed)
Hoang-Nam Nguyen2b943972007-07-12 17:53:47 +0200534 *log_addr_next_sq_wqe2processed = (void *)outs[0];
Heiko J Schickfab97222006-09-22 15:22:22 -0700535 if (log_addr_next_rq_wqe2processed)
Hoang-Nam Nguyen2b943972007-07-12 17:53:47 +0200536 *log_addr_next_rq_wqe2processed = (void *)outs[1];
Heiko J Schickfab97222006-09-22 15:22:22 -0700537
538 return ret;
539}
540
541u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
542 const struct ipz_qp_handle qp_handle,
543 struct ehca_pfqp *pfqp,
544 const u64 update_mask,
545 struct hcp_modify_qp_control_block *mqpcb,
546 struct h_galpa gal)
547{
548 u64 ret;
549 u64 outs[PLPAR_HCALL9_BUFSIZE];
550 ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
551 adapter_handle.handle, /* r4 */
552 qp_handle.handle, /* r5 */
553 update_mask, /* r6 */
554 virt_to_abs(mqpcb), /* r7 */
555 0, 0, 0, 0, 0);
556
557 if (ret == H_NOT_ENOUGH_RESOURCES)
558 ehca_gen_err("Insufficient resources ret=%lx", ret);
559
560 return ret;
561}
562
563u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
564 const struct ipz_qp_handle qp_handle,
565 struct ehca_pfqp *pfqp,
566 struct hcp_modify_qp_control_block *qqpcb,
567 struct h_galpa gal)
568{
569 return ehca_plpar_hcall_norets(H_QUERY_QP,
570 adapter_handle.handle, /* r4 */
571 qp_handle.handle, /* r5 */
572 virt_to_abs(qqpcb), /* r6 */
573 0, 0, 0, 0);
574}
575
576u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
577 struct ehca_qp *qp)
578{
579 u64 ret;
580 u64 outs[PLPAR_HCALL9_BUFSIZE];
581
582 ret = hcp_galpas_dtor(&qp->galpas);
583 if (ret) {
584 ehca_gen_err("Could not destruct qp->galpas");
585 return H_RESOURCE;
586 }
587 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
588 adapter_handle.handle, /* r4 */
589 /* function code */
590 1, /* r5 */
591 qp->ipz_qp_handle.handle, /* r6 */
592 0, 0, 0, 0, 0, 0);
593 if (ret == H_HARDWARE)
594 ehca_gen_err("HCA not operational. ret=%lx", ret);
595
596 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
597 adapter_handle.handle, /* r4 */
598 qp->ipz_qp_handle.handle, /* r5 */
599 0, 0, 0, 0, 0);
600
601 if (ret == H_RESOURCE)
602 ehca_gen_err("Resource still in use. ret=%lx", ret);
603
604 return ret;
605}
606
607u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
608 const struct ipz_qp_handle qp_handle,
609 struct h_galpa gal,
610 u32 port)
611{
612 return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
613 adapter_handle.handle, /* r4 */
614 qp_handle.handle, /* r5 */
615 port, /* r6 */
616 0, 0, 0, 0);
617}
618
619u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
620 const struct ipz_qp_handle qp_handle,
621 struct h_galpa gal,
622 u32 port, u32 * pma_qp_nr,
623 u32 * bma_qp_nr)
624{
625 u64 ret;
626 u64 outs[PLPAR_HCALL9_BUFSIZE];
627
628 ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
629 adapter_handle.handle, /* r4 */
630 qp_handle.handle, /* r5 */
631 port, /* r6 */
632 0, 0, 0, 0, 0, 0);
633 *pma_qp_nr = (u32)outs[0];
634 *bma_qp_nr = (u32)outs[1];
635
636 if (ret == H_ALIAS_EXIST)
637 ehca_gen_err("AQP1 already exists. ret=%lx", ret);
638
639 return ret;
640}
641
642u64 hipz_h_attach_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 u64 ret;
649
650 ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
651 adapter_handle.handle, /* r4 */
652 qp_handle.handle, /* r5 */
653 mcg_dlid, /* r6 */
654 interface_id, /* r7 */
655 subnet_prefix, /* r8 */
656 0, 0);
657
658 if (ret == H_NOT_ENOUGH_RESOURCES)
659 ehca_gen_err("Not enough resources. ret=%lx", ret);
660
661 return ret;
662}
663
664u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
665 const struct ipz_qp_handle qp_handle,
666 struct h_galpa gal,
667 u16 mcg_dlid,
668 u64 subnet_prefix, u64 interface_id)
669{
670 return ehca_plpar_hcall_norets(H_DETACH_MCQP,
671 adapter_handle.handle, /* r4 */
672 qp_handle.handle, /* r5 */
673 mcg_dlid, /* r6 */
674 interface_id, /* r7 */
675 subnet_prefix, /* r8 */
676 0, 0);
677}
678
679u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
680 struct ehca_cq *cq,
681 u8 force_flag)
682{
683 u64 ret;
684
685 ret = hcp_galpas_dtor(&cq->galpas);
686 if (ret) {
687 ehca_gen_err("Could not destruct cp->galpas");
688 return H_RESOURCE;
689 }
690
691 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
692 adapter_handle.handle, /* r4 */
693 cq->ipz_cq_handle.handle, /* r5 */
694 force_flag != 0 ? 1L : 0L, /* r6 */
695 0, 0, 0, 0);
696
697 if (ret == H_RESOURCE)
698 ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret);
699
700 return ret;
701}
702
703u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
704 struct ehca_eq *eq)
705{
706 u64 ret;
707
708 ret = hcp_galpas_dtor(&eq->galpas);
709 if (ret) {
710 ehca_gen_err("Could not destruct eq->galpas");
711 return H_RESOURCE;
712 }
713
714 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
715 adapter_handle.handle, /* r4 */
716 eq->ipz_eq_handle.handle, /* r5 */
717 0, 0, 0, 0, 0);
718
719 if (ret == H_RESOURCE)
720 ehca_gen_err("Resource in use. ret=%lx ", ret);
721
722 return ret;
723}
724
725u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
726 const struct ehca_mr *mr,
727 const u64 vaddr,
728 const u64 length,
729 const u32 access_ctrl,
730 const struct ipz_pd pd,
731 struct ehca_mr_hipzout_parms *outparms)
732{
733 u64 ret;
734 u64 outs[PLPAR_HCALL9_BUFSIZE];
735
Hoang-Nam Nguyen5bb7d922007-07-20 16:01:51 +0200736 ehca_gen_dbg("kernel PAGE_SIZE=%x access_ctrl=%016x "
737 "vaddr=%lx length=%lx",
738 (u32)PAGE_SIZE, access_ctrl, vaddr, length);
Heiko J Schickfab97222006-09-22 15:22:22 -0700739 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
740 adapter_handle.handle, /* r4 */
741 5, /* r5 */
742 vaddr, /* r6 */
743 length, /* r7 */
744 (((u64)access_ctrl) << 32ULL), /* r8 */
745 pd.value, /* r9 */
746 0, 0, 0);
747 outparms->handle.handle = outs[0];
748 outparms->lkey = (u32)outs[2];
749 outparms->rkey = (u32)outs[3];
750
751 return ret;
752}
753
754u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
755 const struct ehca_mr *mr,
756 const u8 pagesize,
757 const u8 queue_type,
758 const u64 logical_address_of_page,
759 const u64 count)
760{
761 u64 ret;
762
Hoang-Nam Nguyen5bb7d922007-07-20 16:01:51 +0200763 if (unlikely(ehca_debug_level >= 2)) {
764 if (count > 1) {
765 u64 *kpage;
766 int i;
767 kpage = (u64 *)abs_to_virt(logical_address_of_page);
768 for (i = 0; i < count; i++)
769 ehca_gen_dbg("kpage[%d]=%p",
770 i, (void *)kpage[i]);
771 } else
772 ehca_gen_dbg("kpage=%p",
773 (void *)logical_address_of_page);
774 }
775
Heiko J Schickfab97222006-09-22 15:22:22 -0700776 if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
777 ehca_gen_err("logical_address_of_page not on a 4k boundary "
778 "adapter_handle=%lx mr=%p mr_handle=%lx "
779 "pagesize=%x queue_type=%x "
780 "logical_address_of_page=%lx count=%lx",
781 adapter_handle.handle, mr,
782 mr->ipz_mr_handle.handle, pagesize, queue_type,
783 logical_address_of_page, count);
784 ret = H_PARAMETER;
785 } else
786 ret = hipz_h_register_rpage(adapter_handle, pagesize,
787 queue_type,
788 mr->ipz_mr_handle.handle,
789 logical_address_of_page, count);
790 return ret;
791}
792
793u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
794 const struct ehca_mr *mr,
795 struct ehca_mr_hipzout_parms *outparms)
796{
797 u64 ret;
798 u64 outs[PLPAR_HCALL9_BUFSIZE];
799
800 ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
801 adapter_handle.handle, /* r4 */
802 mr->ipz_mr_handle.handle, /* r5 */
803 0, 0, 0, 0, 0, 0, 0);
804 outparms->len = outs[0];
805 outparms->vaddr = outs[1];
806 outparms->acl = outs[4] >> 32;
807 outparms->lkey = (u32)(outs[5] >> 32);
808 outparms->rkey = (u32)(outs[5] & (0xffffffff));
809
810 return ret;
811}
812
813u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
814 const struct ehca_mr *mr)
815{
816 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
817 adapter_handle.handle, /* r4 */
818 mr->ipz_mr_handle.handle, /* r5 */
819 0, 0, 0, 0, 0);
820}
821
822u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
823 const struct ehca_mr *mr,
824 const u64 vaddr_in,
825 const u64 length,
826 const u32 access_ctrl,
827 const struct ipz_pd pd,
828 const u64 mr_addr_cb,
829 struct ehca_mr_hipzout_parms *outparms)
830{
831 u64 ret;
832 u64 outs[PLPAR_HCALL9_BUFSIZE];
833
834 ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
835 adapter_handle.handle, /* r4 */
836 mr->ipz_mr_handle.handle, /* r5 */
837 vaddr_in, /* r6 */
838 length, /* r7 */
839 /* r8 */
840 ((((u64)access_ctrl) << 32ULL) | pd.value),
841 mr_addr_cb, /* r9 */
842 0, 0, 0);
843 outparms->vaddr = outs[1];
844 outparms->lkey = (u32)outs[2];
845 outparms->rkey = (u32)outs[3];
846
847 return ret;
848}
849
850u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
851 const struct ehca_mr *mr,
852 const struct ehca_mr *orig_mr,
853 const u64 vaddr_in,
854 const u32 access_ctrl,
855 const struct ipz_pd pd,
856 struct ehca_mr_hipzout_parms *outparms)
857{
858 u64 ret;
859 u64 outs[PLPAR_HCALL9_BUFSIZE];
860
861 ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
862 adapter_handle.handle, /* r4 */
863 orig_mr->ipz_mr_handle.handle, /* r5 */
864 vaddr_in, /* r6 */
865 (((u64)access_ctrl) << 32ULL), /* r7 */
866 pd.value, /* r8 */
867 0, 0, 0, 0);
868 outparms->handle.handle = outs[0];
869 outparms->lkey = (u32)outs[2];
870 outparms->rkey = (u32)outs[3];
871
872 return ret;
873}
874
875u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
876 const struct ehca_mw *mw,
877 const struct ipz_pd pd,
878 struct ehca_mw_hipzout_parms *outparms)
879{
880 u64 ret;
881 u64 outs[PLPAR_HCALL9_BUFSIZE];
882
883 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
884 adapter_handle.handle, /* r4 */
885 6, /* r5 */
886 pd.value, /* r6 */
887 0, 0, 0, 0, 0, 0);
888 outparms->handle.handle = outs[0];
889 outparms->rkey = (u32)outs[3];
890
891 return ret;
892}
893
894u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
895 const struct ehca_mw *mw,
896 struct ehca_mw_hipzout_parms *outparms)
897{
898 u64 ret;
899 u64 outs[PLPAR_HCALL9_BUFSIZE];
900
901 ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
902 adapter_handle.handle, /* r4 */
903 mw->ipz_mw_handle.handle, /* r5 */
904 0, 0, 0, 0, 0, 0, 0);
905 outparms->rkey = (u32)outs[3];
906
907 return ret;
908}
909
910u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
911 const struct ehca_mw *mw)
912{
913 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
914 adapter_handle.handle, /* r4 */
915 mw->ipz_mw_handle.handle, /* r5 */
916 0, 0, 0, 0, 0);
917}
918
919u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
920 const u64 ressource_handle,
921 void *rblock,
922 unsigned long *byte_count)
923{
924 u64 r_cb = virt_to_abs(rblock);
925
926 if (r_cb & (EHCA_PAGESIZE-1)) {
927 ehca_gen_err("rblock not page aligned.");
928 return H_PARAMETER;
929 }
930
931 return ehca_plpar_hcall_norets(H_ERROR_DATA,
932 adapter_handle.handle,
933 ressource_handle,
934 r_cb,
935 0, 0, 0, 0);
936}