blob: c16a21374bb5a3c222a73147c28584cb871ab619 [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 Fenkes2863ad42007-09-11 15:31:49 +020087#define HCALL4_REGS_FORMAT "r4=%lx r5=%lx r6=%lx r7=%lx"
88#define HCALL7_REGS_FORMAT HCALL4_REGS_FORMAT " r8=%lx r9=%lx r10=%lx"
89#define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"
90
Joachim Fenkes9844b712007-07-09 15:29:03 +020091static DEFINE_SPINLOCK(hcall_lock);
92
Heiko J Schickfab97222006-09-22 15:22:22 -070093static u32 get_longbusy_msecs(int longbusy_rc)
94{
95 switch (longbusy_rc) {
96 case H_LONG_BUSY_ORDER_1_MSEC:
97 return 1;
98 case H_LONG_BUSY_ORDER_10_MSEC:
99 return 10;
100 case H_LONG_BUSY_ORDER_100_MSEC:
101 return 100;
102 case H_LONG_BUSY_ORDER_1_SEC:
103 return 1000;
104 case H_LONG_BUSY_ORDER_10_SEC:
105 return 10000;
106 case H_LONG_BUSY_ORDER_100_SEC:
107 return 100000;
108 default:
109 return 1;
110 }
111}
112
113static long ehca_plpar_hcall_norets(unsigned long opcode,
114 unsigned long arg1,
115 unsigned long arg2,
116 unsigned long arg3,
117 unsigned long arg4,
118 unsigned long arg5,
119 unsigned long arg6,
120 unsigned long arg7)
121{
122 long ret;
Joachim Fenkes0b5de962007-09-11 15:34:35 +0200123 int i, sleep_msecs, do_lock;
124 unsigned long flags;
Heiko J Schickfab97222006-09-22 15:22:22 -0700125
Joachim Fenkes2863ad42007-09-11 15:31:49 +0200126 ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
Heiko J Schickfab97222006-09-22 15:22:22 -0700127 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
128
Joachim Fenkes0b5de962007-09-11 15:34:35 +0200129 /* lock H_FREE_RESOURCE(MR) against itself and H_ALLOC_RESOURCE(MR) */
130 if ((opcode == H_FREE_RESOURCE) && (arg7 == 5)) {
131 arg7 = 0; /* better not upset firmware */
132 do_lock = 1;
133 }
134
Heiko J Schickfab97222006-09-22 15:22:22 -0700135 for (i = 0; i < 5; i++) {
Joachim Fenkes0b5de962007-09-11 15:34:35 +0200136 if (do_lock)
137 spin_lock_irqsave(&hcall_lock, flags);
138
Heiko J Schickfab97222006-09-22 15:22:22 -0700139 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
140 arg5, arg6, arg7);
141
Joachim Fenkes0b5de962007-09-11 15:34:35 +0200142 if (do_lock)
143 spin_unlock_irqrestore(&hcall_lock, flags);
144
Heiko J Schickfab97222006-09-22 15:22:22 -0700145 if (H_IS_LONG_BUSY(ret)) {
146 sleep_msecs = get_longbusy_msecs(ret);
147 msleep_interruptible(sleep_msecs);
148 continue;
149 }
150
151 if (ret < H_SUCCESS)
Joachim Fenkes2863ad42007-09-11 15:31:49 +0200152 ehca_gen_err("opcode=%lx ret=%li " HCALL7_REGS_FORMAT,
153 opcode, ret, arg1, arg2, arg3,
154 arg4, arg5, arg6, arg7);
155 else
156 ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700157
Heiko J Schickfab97222006-09-22 15:22:22 -0700158 return ret;
Heiko J Schickfab97222006-09-22 15:22:22 -0700159 }
160
161 return H_BUSY;
162}
163
164static long ehca_plpar_hcall9(unsigned long opcode,
165 unsigned long *outs, /* array of 9 outputs */
166 unsigned long arg1,
167 unsigned long arg2,
168 unsigned long arg3,
169 unsigned long arg4,
170 unsigned long arg5,
171 unsigned long arg6,
172 unsigned long arg7,
173 unsigned long arg8,
174 unsigned long arg9)
175{
176 long ret;
Joachim Fenkes0b5de962007-09-11 15:34:35 +0200177 int i, sleep_msecs, do_lock;
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200178 unsigned long flags = 0;
Heiko J Schickfab97222006-09-22 15:22:22 -0700179
Joachim Fenkes2863ad42007-09-11 15:31:49 +0200180 ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
181 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
Heiko J Schickfab97222006-09-22 15:22:22 -0700182
Joachim Fenkes0b5de962007-09-11 15:34:35 +0200183 /* lock H_ALLOC_RESOURCE(MR) against itself and H_FREE_RESOURCE(MR) */
184 do_lock = ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5));
185
Heiko J Schickfab97222006-09-22 15:22:22 -0700186 for (i = 0; i < 5; i++) {
Joachim Fenkes0b5de962007-09-11 15:34:35 +0200187 if (do_lock)
Stefan Roscher5d882782007-05-09 13:47:56 +0200188 spin_lock_irqsave(&hcall_lock, flags);
Stefan Roscher5d882782007-05-09 13:47:56 +0200189
Heiko J Schickfab97222006-09-22 15:22:22 -0700190 ret = plpar_hcall9(opcode, outs,
191 arg1, arg2, arg3, arg4, arg5,
192 arg6, arg7, arg8, arg9);
193
Joachim Fenkes0b5de962007-09-11 15:34:35 +0200194 if (do_lock)
Stefan Roscher5d882782007-05-09 13:47:56 +0200195 spin_unlock_irqrestore(&hcall_lock, flags);
196
Heiko J Schickfab97222006-09-22 15:22:22 -0700197 if (H_IS_LONG_BUSY(ret)) {
198 sleep_msecs = get_longbusy_msecs(ret);
199 msleep_interruptible(sleep_msecs);
200 continue;
201 }
202
Joachim Fenkes2863ad42007-09-11 15:31:49 +0200203 if (ret < H_SUCCESS) {
204 ehca_gen_err("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT,
205 opcode, arg1, arg2, arg3, arg4, arg5,
206 arg6, arg7, arg8, arg9);
207 ehca_gen_err("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
208 ret, outs[0], outs[1], outs[2], outs[3],
Heiko J Schickfab97222006-09-22 15:22:22 -0700209 outs[4], outs[5], outs[6], outs[7],
210 outs[8]);
Joachim Fenkes2863ad42007-09-11 15:31:49 +0200211 } else
212 ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
213 ret, outs[0], outs[1], outs[2], outs[3],
214 outs[4], outs[5], outs[6], outs[7],
215 outs[8]);
Heiko J Schickfab97222006-09-22 15:22:22 -0700216 return ret;
Heiko J Schickfab97222006-09-22 15:22:22 -0700217 }
218
219 return H_BUSY;
220}
Stefan Roscher5d882782007-05-09 13:47:56 +0200221
Heiko J Schickfab97222006-09-22 15:22:22 -0700222u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
223 struct ehca_pfeq *pfeq,
224 const u32 neq_control,
225 const u32 number_of_entries,
226 struct ipz_eq_handle *eq_handle,
227 u32 *act_nr_of_entries,
228 u32 *act_pages,
229 u32 *eq_ist)
230{
231 u64 ret;
232 u64 outs[PLPAR_HCALL9_BUFSIZE];
233 u64 allocate_controls;
234
235 /* resource type */
236 allocate_controls = 3ULL;
237
238 /* ISN is associated */
239 if (neq_control != 1)
240 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
241 else /* notification event queue */
242 allocate_controls = (1ULL << 63) | allocate_controls;
243
244 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
245 adapter_handle.handle, /* r4 */
246 allocate_controls, /* r5 */
247 number_of_entries, /* r6 */
248 0, 0, 0, 0, 0, 0);
249 eq_handle->handle = outs[0];
250 *act_nr_of_entries = (u32)outs[3];
251 *act_pages = (u32)outs[4];
252 *eq_ist = (u32)outs[5];
253
254 if (ret == H_NOT_ENOUGH_RESOURCES)
Joachim Fenkese3722192007-09-11 15:32:22 +0200255 ehca_gen_err("Not enough resource - ret=%li ", ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700256
257 return ret;
258}
259
260u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
261 struct ipz_eq_handle eq_handle,
262 const u64 event_mask)
263{
264 return ehca_plpar_hcall_norets(H_RESET_EVENTS,
265 adapter_handle.handle, /* r4 */
266 eq_handle.handle, /* r5 */
267 event_mask, /* r6 */
268 0, 0, 0, 0);
269}
270
271u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
272 struct ehca_cq *cq,
273 struct ehca_alloc_cq_parms *param)
274{
275 u64 ret;
276 u64 outs[PLPAR_HCALL9_BUFSIZE];
277
278 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
279 adapter_handle.handle, /* r4 */
280 2, /* r5 */
281 param->eq_handle.handle, /* r6 */
282 cq->token, /* r7 */
283 param->nr_cqe, /* r8 */
284 0, 0, 0, 0);
285 cq->ipz_cq_handle.handle = outs[0];
286 param->act_nr_of_entries = (u32)outs[3];
287 param->act_pages = (u32)outs[4];
288
289 if (ret == H_SUCCESS)
290 hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
291
292 if (ret == H_NOT_ENOUGH_RESOURCES)
Joachim Fenkese3722192007-09-11 15:32:22 +0200293 ehca_gen_err("Not enough resources. ret=%li", ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700294
295 return ret;
296}
297
298u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
Heiko J Schickfab97222006-09-22 15:22:22 -0700299 struct ehca_alloc_qp_parms *parms)
300{
301 u64 ret;
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200302 u64 allocate_controls, max_r10_reg, r11, r12;
Heiko J Schickfab97222006-09-22 15:22:22 -0700303 u64 outs[PLPAR_HCALL9_BUFSIZE];
Heiko J Schickfab97222006-09-22 15:22:22 -0700304
305 allocate_controls =
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200306 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
Heiko J Schickfab97222006-09-22 15:22:22 -0700307 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
308 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
309 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
Stefan Roschere2f81da2007-07-20 16:04:17 +0200310 | EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage)
311 | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE,
312 parms->squeue.page_size)
313 | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE,
314 parms->rqueue.page_size)
Heiko J Schickfab97222006-09-22 15:22:22 -0700315 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200316 !!(parms->ll_comp_flags & LLQP_RECV_COMP))
Heiko J Schickfab97222006-09-22 15:22:22 -0700317 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200318 !!(parms->ll_comp_flags & LLQP_SEND_COMP))
Heiko J Schickfab97222006-09-22 15:22:22 -0700319 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
320 parms->ud_av_l_key_ctl)
321 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
322
323 max_r10_reg =
324 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
Stefan Roschere2f81da2007-07-20 16:04:17 +0200325 parms->squeue.max_wr + 1)
Heiko J Schickfab97222006-09-22 15:22:22 -0700326 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
Stefan Roschere2f81da2007-07-20 16:04:17 +0200327 parms->rqueue.max_wr + 1)
Heiko J Schickfab97222006-09-22 15:22:22 -0700328 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
Stefan Roschere2f81da2007-07-20 16:04:17 +0200329 parms->squeue.max_sge)
Heiko J Schickfab97222006-09-22 15:22:22 -0700330 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
Stefan Roschere2f81da2007-07-20 16:04:17 +0200331 parms->rqueue.max_sge);
Heiko J Schickfab97222006-09-22 15:22:22 -0700332
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200333 r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
334
335 if (parms->ext_type == EQPT_SRQ)
336 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
337 else
338 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
339
Heiko J Schickfab97222006-09-22 15:22:22 -0700340 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
341 adapter_handle.handle, /* r4 */
342 allocate_controls, /* r5 */
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200343 parms->send_cq_handle.handle,
344 parms->recv_cq_handle.handle,
345 parms->eq_handle.handle,
346 ((u64)parms->token << 32) | parms->pd.value,
Joachim Fenkesa6a12942007-07-09 15:25:10 +0200347 max_r10_reg, r11, r12);
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200348
349 parms->qp_handle.handle = outs[0];
350 parms->real_qp_num = (u32)outs[1];
Stefan Roschere2f81da2007-07-20 16:04:17 +0200351 parms->squeue.act_nr_wqes =
Heiko J Schickfab97222006-09-22 15:22:22 -0700352 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
Stefan Roschere2f81da2007-07-20 16:04:17 +0200353 parms->rqueue.act_nr_wqes =
Heiko J Schickfab97222006-09-22 15:22:22 -0700354 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
Stefan Roschere2f81da2007-07-20 16:04:17 +0200355 parms->squeue.act_nr_sges =
Heiko J Schickfab97222006-09-22 15:22:22 -0700356 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
Stefan Roschere2f81da2007-07-20 16:04:17 +0200357 parms->rqueue.act_nr_sges =
Heiko J Schickfab97222006-09-22 15:22:22 -0700358 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
Stefan Roschere2f81da2007-07-20 16:04:17 +0200359 parms->squeue.queue_size =
Heiko J Schickfab97222006-09-22 15:22:22 -0700360 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
Stefan Roschere2f81da2007-07-20 16:04:17 +0200361 parms->rqueue.queue_size =
Heiko J Schickfab97222006-09-22 15:22:22 -0700362 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
363
364 if (ret == H_SUCCESS)
Joachim Fenkes9a79fc02007-07-09 15:23:15 +0200365 hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
Heiko J Schickfab97222006-09-22 15:22:22 -0700366
367 if (ret == H_NOT_ENOUGH_RESOURCES)
Joachim Fenkese3722192007-09-11 15:32:22 +0200368 ehca_gen_err("Not enough resources. ret=%li", ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700369
370 return ret;
371}
372
373u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
374 const u8 port_id,
375 struct hipz_query_port *query_port_response_block)
376{
377 u64 ret;
378 u64 r_cb = virt_to_abs(query_port_response_block);
379
380 if (r_cb & (EHCA_PAGESIZE-1)) {
381 ehca_gen_err("response block not page aligned");
382 return H_PARAMETER;
383 }
384
385 ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
386 adapter_handle.handle, /* r4 */
387 port_id, /* r5 */
388 r_cb, /* r6 */
389 0, 0, 0, 0);
390
391 if (ehca_debug_level)
392 ehca_dmp(query_port_response_block, 64, "response_block");
393
394 return ret;
395}
396
Joachim Fenkesc4ed7902007-04-24 17:44:31 +0200397u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
398 const u8 port_id, const u32 port_cap,
399 const u8 init_type, const int modify_mask)
400{
401 u64 port_attributes = port_cap;
402
403 if (modify_mask & IB_PORT_SHUTDOWN)
404 port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
405 if (modify_mask & IB_PORT_INIT_TYPE)
406 port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
407 if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
408 port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
409
410 return ehca_plpar_hcall_norets(H_MODIFY_PORT,
411 adapter_handle.handle, /* r4 */
412 port_id, /* r5 */
413 port_attributes, /* r6 */
414 0, 0, 0, 0);
415}
416
Heiko J Schickfab97222006-09-22 15:22:22 -0700417u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
418 struct hipz_query_hca *query_hca_rblock)
419{
420 u64 r_cb = virt_to_abs(query_hca_rblock);
421
422 if (r_cb & (EHCA_PAGESIZE-1)) {
423 ehca_gen_err("response_block=%p not page aligned",
424 query_hca_rblock);
425 return H_PARAMETER;
426 }
427
428 return ehca_plpar_hcall_norets(H_QUERY_HCA,
429 adapter_handle.handle, /* r4 */
430 r_cb, /* r5 */
431 0, 0, 0, 0, 0);
432}
433
434u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
435 const u8 pagesize,
436 const u8 queue_type,
437 const u64 resource_handle,
438 const u64 logical_address_of_page,
439 u64 count)
440{
441 return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
442 adapter_handle.handle, /* r4 */
Hoang-Nam Nguyen5bb7d922007-07-20 16:01:51 +0200443 (u64)queue_type | ((u64)pagesize) << 8,
444 /* r5 */
Heiko J Schickfab97222006-09-22 15:22:22 -0700445 resource_handle, /* r6 */
446 logical_address_of_page, /* r7 */
447 count, /* r8 */
448 0, 0);
449}
450
451u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
452 const struct ipz_eq_handle eq_handle,
453 struct ehca_pfeq *pfeq,
454 const u8 pagesize,
455 const u8 queue_type,
456 const u64 logical_address_of_page,
457 const u64 count)
458{
459 if (count != 1) {
460 ehca_gen_err("Ppage counter=%lx", count);
461 return H_PARAMETER;
462 }
463 return hipz_h_register_rpage(adapter_handle,
464 pagesize,
465 queue_type,
466 eq_handle.handle,
467 logical_address_of_page, count);
468}
469
470u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
471 u32 ist)
472{
473 u64 ret;
474 ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
475 adapter_handle.handle, /* r4 */
476 ist, /* r5 */
477 0, 0, 0, 0, 0);
478
479 if (ret != H_SUCCESS && ret != H_BUSY)
480 ehca_gen_err("Could not query interrupt state.");
481
482 return ret;
483}
484
485u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
486 const struct ipz_cq_handle cq_handle,
487 struct ehca_pfcq *pfcq,
488 const u8 pagesize,
489 const u8 queue_type,
490 const u64 logical_address_of_page,
491 const u64 count,
492 const struct h_galpa gal)
493{
494 if (count != 1) {
495 ehca_gen_err("Page counter=%lx", count);
496 return H_PARAMETER;
497 }
498
499 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
500 cq_handle.handle, logical_address_of_page,
501 count);
502}
503
504u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
505 const struct ipz_qp_handle qp_handle,
506 struct ehca_pfqp *pfqp,
507 const u8 pagesize,
508 const u8 queue_type,
509 const u64 logical_address_of_page,
510 const u64 count,
511 const struct h_galpa galpa)
512{
Stefan Roschere2f81da2007-07-20 16:04:17 +0200513 if (count > 1) {
Heiko J Schickfab97222006-09-22 15:22:22 -0700514 ehca_gen_err("Page counter=%lx", count);
515 return H_PARAMETER;
516 }
517
Hoang-Nam Nguyen2b943972007-07-12 17:53:47 +0200518 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
519 qp_handle.handle, logical_address_of_page,
Heiko J Schickfab97222006-09-22 15:22:22 -0700520 count);
521}
522
523u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
524 const struct ipz_qp_handle qp_handle,
525 struct ehca_pfqp *pfqp,
526 void **log_addr_next_sq_wqe2processed,
527 void **log_addr_next_rq_wqe2processed,
528 int dis_and_get_function_code)
529{
530 u64 ret;
531 u64 outs[PLPAR_HCALL9_BUFSIZE];
532
533 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
534 adapter_handle.handle, /* r4 */
535 dis_and_get_function_code, /* r5 */
536 qp_handle.handle, /* r6 */
537 0, 0, 0, 0, 0, 0);
538 if (log_addr_next_sq_wqe2processed)
Hoang-Nam Nguyen2b943972007-07-12 17:53:47 +0200539 *log_addr_next_sq_wqe2processed = (void *)outs[0];
Heiko J Schickfab97222006-09-22 15:22:22 -0700540 if (log_addr_next_rq_wqe2processed)
Hoang-Nam Nguyen2b943972007-07-12 17:53:47 +0200541 *log_addr_next_rq_wqe2processed = (void *)outs[1];
Heiko J Schickfab97222006-09-22 15:22:22 -0700542
543 return ret;
544}
545
546u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
547 const struct ipz_qp_handle qp_handle,
548 struct ehca_pfqp *pfqp,
549 const u64 update_mask,
550 struct hcp_modify_qp_control_block *mqpcb,
551 struct h_galpa gal)
552{
553 u64 ret;
554 u64 outs[PLPAR_HCALL9_BUFSIZE];
555 ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
556 adapter_handle.handle, /* r4 */
557 qp_handle.handle, /* r5 */
558 update_mask, /* r6 */
559 virt_to_abs(mqpcb), /* r7 */
560 0, 0, 0, 0, 0);
561
562 if (ret == H_NOT_ENOUGH_RESOURCES)
Joachim Fenkese3722192007-09-11 15:32:22 +0200563 ehca_gen_err("Insufficient resources ret=%li", ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700564
565 return ret;
566}
567
568u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
569 const struct ipz_qp_handle qp_handle,
570 struct ehca_pfqp *pfqp,
571 struct hcp_modify_qp_control_block *qqpcb,
572 struct h_galpa gal)
573{
574 return ehca_plpar_hcall_norets(H_QUERY_QP,
575 adapter_handle.handle, /* r4 */
576 qp_handle.handle, /* r5 */
577 virt_to_abs(qqpcb), /* r6 */
578 0, 0, 0, 0);
579}
580
581u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
582 struct ehca_qp *qp)
583{
584 u64 ret;
585 u64 outs[PLPAR_HCALL9_BUFSIZE];
586
587 ret = hcp_galpas_dtor(&qp->galpas);
588 if (ret) {
589 ehca_gen_err("Could not destruct qp->galpas");
590 return H_RESOURCE;
591 }
592 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
593 adapter_handle.handle, /* r4 */
594 /* function code */
595 1, /* r5 */
596 qp->ipz_qp_handle.handle, /* r6 */
597 0, 0, 0, 0, 0, 0);
598 if (ret == H_HARDWARE)
Joachim Fenkese3722192007-09-11 15:32:22 +0200599 ehca_gen_err("HCA not operational. ret=%li", ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700600
601 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
602 adapter_handle.handle, /* r4 */
603 qp->ipz_qp_handle.handle, /* r5 */
604 0, 0, 0, 0, 0);
605
606 if (ret == H_RESOURCE)
Joachim Fenkese3722192007-09-11 15:32:22 +0200607 ehca_gen_err("Resource still in use. ret=%li", ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700608
609 return ret;
610}
611
612u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
613 const struct ipz_qp_handle qp_handle,
614 struct h_galpa gal,
615 u32 port)
616{
617 return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
618 adapter_handle.handle, /* r4 */
619 qp_handle.handle, /* r5 */
620 port, /* r6 */
621 0, 0, 0, 0);
622}
623
624u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
625 const struct ipz_qp_handle qp_handle,
626 struct h_galpa gal,
627 u32 port, u32 * pma_qp_nr,
628 u32 * bma_qp_nr)
629{
630 u64 ret;
631 u64 outs[PLPAR_HCALL9_BUFSIZE];
632
633 ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
634 adapter_handle.handle, /* r4 */
635 qp_handle.handle, /* r5 */
636 port, /* r6 */
637 0, 0, 0, 0, 0, 0);
638 *pma_qp_nr = (u32)outs[0];
639 *bma_qp_nr = (u32)outs[1];
640
641 if (ret == H_ALIAS_EXIST)
Joachim Fenkese3722192007-09-11 15:32:22 +0200642 ehca_gen_err("AQP1 already exists. ret=%li", ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700643
644 return ret;
645}
646
647u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
648 const struct ipz_qp_handle qp_handle,
649 struct h_galpa gal,
650 u16 mcg_dlid,
651 u64 subnet_prefix, u64 interface_id)
652{
653 u64 ret;
654
655 ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
656 adapter_handle.handle, /* r4 */
657 qp_handle.handle, /* r5 */
658 mcg_dlid, /* r6 */
659 interface_id, /* r7 */
660 subnet_prefix, /* r8 */
661 0, 0);
662
663 if (ret == H_NOT_ENOUGH_RESOURCES)
Joachim Fenkese3722192007-09-11 15:32:22 +0200664 ehca_gen_err("Not enough resources. ret=%li", ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700665
666 return ret;
667}
668
669u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
670 const struct ipz_qp_handle qp_handle,
671 struct h_galpa gal,
672 u16 mcg_dlid,
673 u64 subnet_prefix, u64 interface_id)
674{
675 return ehca_plpar_hcall_norets(H_DETACH_MCQP,
676 adapter_handle.handle, /* r4 */
677 qp_handle.handle, /* r5 */
678 mcg_dlid, /* r6 */
679 interface_id, /* r7 */
680 subnet_prefix, /* r8 */
681 0, 0);
682}
683
684u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
685 struct ehca_cq *cq,
686 u8 force_flag)
687{
688 u64 ret;
689
690 ret = hcp_galpas_dtor(&cq->galpas);
691 if (ret) {
692 ehca_gen_err("Could not destruct cp->galpas");
693 return H_RESOURCE;
694 }
695
696 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
697 adapter_handle.handle, /* r4 */
698 cq->ipz_cq_handle.handle, /* r5 */
699 force_flag != 0 ? 1L : 0L, /* r6 */
700 0, 0, 0, 0);
701
702 if (ret == H_RESOURCE)
Joachim Fenkese3722192007-09-11 15:32:22 +0200703 ehca_gen_err("H_FREE_RESOURCE failed ret=%li ", ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700704
705 return ret;
706}
707
708u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
709 struct ehca_eq *eq)
710{
711 u64 ret;
712
713 ret = hcp_galpas_dtor(&eq->galpas);
714 if (ret) {
715 ehca_gen_err("Could not destruct eq->galpas");
716 return H_RESOURCE;
717 }
718
719 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
720 adapter_handle.handle, /* r4 */
721 eq->ipz_eq_handle.handle, /* r5 */
722 0, 0, 0, 0, 0);
723
724 if (ret == H_RESOURCE)
Joachim Fenkese3722192007-09-11 15:32:22 +0200725 ehca_gen_err("Resource in use. ret=%li ", ret);
Heiko J Schickfab97222006-09-22 15:22:22 -0700726
727 return ret;
728}
729
730u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
731 const struct ehca_mr *mr,
732 const u64 vaddr,
733 const u64 length,
734 const u32 access_ctrl,
735 const struct ipz_pd pd,
736 struct ehca_mr_hipzout_parms *outparms)
737{
738 u64 ret;
739 u64 outs[PLPAR_HCALL9_BUFSIZE];
740
Hoang-Nam Nguyen5bb7d922007-07-20 16:01:51 +0200741 ehca_gen_dbg("kernel PAGE_SIZE=%x access_ctrl=%016x "
742 "vaddr=%lx length=%lx",
743 (u32)PAGE_SIZE, access_ctrl, vaddr, length);
Heiko J Schickfab97222006-09-22 15:22:22 -0700744 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
745 adapter_handle.handle, /* r4 */
746 5, /* r5 */
747 vaddr, /* r6 */
748 length, /* r7 */
749 (((u64)access_ctrl) << 32ULL), /* r8 */
750 pd.value, /* r9 */
751 0, 0, 0);
752 outparms->handle.handle = outs[0];
753 outparms->lkey = (u32)outs[2];
754 outparms->rkey = (u32)outs[3];
755
756 return ret;
757}
758
759u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
760 const struct ehca_mr *mr,
761 const u8 pagesize,
762 const u8 queue_type,
763 const u64 logical_address_of_page,
764 const u64 count)
765{
766 u64 ret;
767
Hoang-Nam Nguyen5bb7d922007-07-20 16:01:51 +0200768 if (unlikely(ehca_debug_level >= 2)) {
769 if (count > 1) {
770 u64 *kpage;
771 int i;
772 kpage = (u64 *)abs_to_virt(logical_address_of_page);
773 for (i = 0; i < count; i++)
774 ehca_gen_dbg("kpage[%d]=%p",
775 i, (void *)kpage[i]);
776 } else
777 ehca_gen_dbg("kpage=%p",
778 (void *)logical_address_of_page);
779 }
780
Heiko J Schickfab97222006-09-22 15:22:22 -0700781 if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
782 ehca_gen_err("logical_address_of_page not on a 4k boundary "
783 "adapter_handle=%lx mr=%p mr_handle=%lx "
784 "pagesize=%x queue_type=%x "
785 "logical_address_of_page=%lx count=%lx",
786 adapter_handle.handle, mr,
787 mr->ipz_mr_handle.handle, pagesize, queue_type,
788 logical_address_of_page, count);
789 ret = H_PARAMETER;
790 } else
791 ret = hipz_h_register_rpage(adapter_handle, pagesize,
792 queue_type,
793 mr->ipz_mr_handle.handle,
794 logical_address_of_page, count);
795 return ret;
796}
797
798u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
799 const struct ehca_mr *mr,
800 struct ehca_mr_hipzout_parms *outparms)
801{
802 u64 ret;
803 u64 outs[PLPAR_HCALL9_BUFSIZE];
804
805 ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
806 adapter_handle.handle, /* r4 */
807 mr->ipz_mr_handle.handle, /* r5 */
808 0, 0, 0, 0, 0, 0, 0);
809 outparms->len = outs[0];
810 outparms->vaddr = outs[1];
811 outparms->acl = outs[4] >> 32;
812 outparms->lkey = (u32)(outs[5] >> 32);
813 outparms->rkey = (u32)(outs[5] & (0xffffffff));
814
815 return ret;
816}
817
818u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
819 const struct ehca_mr *mr)
820{
821 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
822 adapter_handle.handle, /* r4 */
823 mr->ipz_mr_handle.handle, /* r5 */
Joachim Fenkes0b5de962007-09-11 15:34:35 +0200824 0, 0, 0, 0, 5);
Heiko J Schickfab97222006-09-22 15:22:22 -0700825}
826
827u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
828 const struct ehca_mr *mr,
829 const u64 vaddr_in,
830 const u64 length,
831 const u32 access_ctrl,
832 const struct ipz_pd pd,
833 const u64 mr_addr_cb,
834 struct ehca_mr_hipzout_parms *outparms)
835{
836 u64 ret;
837 u64 outs[PLPAR_HCALL9_BUFSIZE];
838
839 ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
840 adapter_handle.handle, /* r4 */
841 mr->ipz_mr_handle.handle, /* r5 */
842 vaddr_in, /* r6 */
843 length, /* r7 */
844 /* r8 */
845 ((((u64)access_ctrl) << 32ULL) | pd.value),
846 mr_addr_cb, /* r9 */
847 0, 0, 0);
848 outparms->vaddr = outs[1];
849 outparms->lkey = (u32)outs[2];
850 outparms->rkey = (u32)outs[3];
851
852 return ret;
853}
854
855u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
856 const struct ehca_mr *mr,
857 const struct ehca_mr *orig_mr,
858 const u64 vaddr_in,
859 const u32 access_ctrl,
860 const struct ipz_pd pd,
861 struct ehca_mr_hipzout_parms *outparms)
862{
863 u64 ret;
864 u64 outs[PLPAR_HCALL9_BUFSIZE];
865
866 ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
867 adapter_handle.handle, /* r4 */
868 orig_mr->ipz_mr_handle.handle, /* r5 */
869 vaddr_in, /* r6 */
870 (((u64)access_ctrl) << 32ULL), /* r7 */
871 pd.value, /* r8 */
872 0, 0, 0, 0);
873 outparms->handle.handle = outs[0];
874 outparms->lkey = (u32)outs[2];
875 outparms->rkey = (u32)outs[3];
876
877 return ret;
878}
879
880u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
881 const struct ehca_mw *mw,
882 const struct ipz_pd pd,
883 struct ehca_mw_hipzout_parms *outparms)
884{
885 u64 ret;
886 u64 outs[PLPAR_HCALL9_BUFSIZE];
887
888 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
889 adapter_handle.handle, /* r4 */
890 6, /* r5 */
891 pd.value, /* r6 */
892 0, 0, 0, 0, 0, 0);
893 outparms->handle.handle = outs[0];
894 outparms->rkey = (u32)outs[3];
895
896 return ret;
897}
898
899u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
900 const struct ehca_mw *mw,
901 struct ehca_mw_hipzout_parms *outparms)
902{
903 u64 ret;
904 u64 outs[PLPAR_HCALL9_BUFSIZE];
905
906 ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
907 adapter_handle.handle, /* r4 */
908 mw->ipz_mw_handle.handle, /* r5 */
909 0, 0, 0, 0, 0, 0, 0);
910 outparms->rkey = (u32)outs[3];
911
912 return ret;
913}
914
915u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
916 const struct ehca_mw *mw)
917{
918 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
919 adapter_handle.handle, /* r4 */
920 mw->ipz_mw_handle.handle, /* r5 */
921 0, 0, 0, 0, 0);
922}
923
924u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
925 const u64 ressource_handle,
926 void *rblock,
927 unsigned long *byte_count)
928{
929 u64 r_cb = virt_to_abs(rblock);
930
931 if (r_cb & (EHCA_PAGESIZE-1)) {
932 ehca_gen_err("rblock not page aligned.");
933 return H_PARAMETER;
934 }
935
936 return ehca_plpar_hcall_norets(H_ERROR_DATA,
937 adapter_handle.handle,
938 ressource_handle,
939 r_cb,
940 0, 0, 0, 0);
941}