Merge tag 'drm-intel-next-2014-12-19' of git://anongit.freedesktop.org/drm-intel...
[deliverable/linux.git] / drivers / infiniband / hw / ehca / hcp_if.c
CommitLineData
fab97220
HS
1/*
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>
a6a12947 8 * Joachim Fenkes <fenkes@de.ibm.com>
fab97220
HS
9 * 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)
e2f81daf 55#define H_ALL_RES_QP_STORAGE EHCA_BMASK_IBM(16, 17)
fab97220
HS
56#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)
e2f81daf
SR
60#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)
fab97220
HS
62#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
a6a12947
JF
69#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
fab97220
HS
75#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
c4ed790d
JF
83#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
2863ad4b
JF
87#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
9844b71b
JF
91static DEFINE_SPINLOCK(hcall_lock);
92
fab97220
HS
93static long ehca_plpar_hcall_norets(unsigned long opcode,
94 unsigned long arg1,
95 unsigned long arg2,
96 unsigned long arg3,
97 unsigned long arg4,
98 unsigned long arg5,
99 unsigned long arg6,
100 unsigned long arg7)
101{
102 long ret;
4faf7757
JF
103 int i, sleep_msecs;
104 unsigned long flags = 0;
fab97220 105
4da27d6d
JF
106 if (unlikely(ehca_debug_level >= 2))
107 ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
108 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
fab97220
HS
109
110 for (i = 0; i < 5; i++) {
4faf7757
JF
111 /* serialize hCalls to work around firmware issue */
112 if (ehca_lock_hcalls)
0b5de968
JF
113 spin_lock_irqsave(&hcall_lock, flags);
114
fab97220
HS
115 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
116 arg5, arg6, arg7);
117
4faf7757 118 if (ehca_lock_hcalls)
0b5de968
JF
119 spin_unlock_irqrestore(&hcall_lock, flags);
120
fab97220
HS
121 if (H_IS_LONG_BUSY(ret)) {
122 sleep_msecs = get_longbusy_msecs(ret);
123 msleep_interruptible(sleep_msecs);
124 continue;
125 }
126
127 if (ret < H_SUCCESS)
2863ad4b
JF
128 ehca_gen_err("opcode=%lx ret=%li " HCALL7_REGS_FORMAT,
129 opcode, ret, arg1, arg2, arg3,
130 arg4, arg5, arg6, arg7);
131 else
4da27d6d
JF
132 if (unlikely(ehca_debug_level >= 2))
133 ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
fab97220 134
2863ad4b 135 return ret;
fab97220
HS
136 }
137
138 return H_BUSY;
139}
140
141static long ehca_plpar_hcall9(unsigned long opcode,
142 unsigned long *outs, /* array of 9 outputs */
143 unsigned long arg1,
144 unsigned long arg2,
145 unsigned long arg3,
146 unsigned long arg4,
147 unsigned long arg5,
148 unsigned long arg6,
149 unsigned long arg7,
150 unsigned long arg8,
151 unsigned long arg9)
152{
153 long ret;
4faf7757 154 int i, sleep_msecs;
a6a12947 155 unsigned long flags = 0;
fab97220 156
4da27d6d
JF
157 if (unlikely(ehca_debug_level >= 2))
158 ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
159 arg1, arg2, arg3, arg4, arg5,
160 arg6, arg7, arg8, arg9);
fab97220
HS
161
162 for (i = 0; i < 5; i++) {
4faf7757
JF
163 /* serialize hCalls to work around firmware issue */
164 if (ehca_lock_hcalls)
5d88278e 165 spin_lock_irqsave(&hcall_lock, flags);
5d88278e 166
fab97220
HS
167 ret = plpar_hcall9(opcode, outs,
168 arg1, arg2, arg3, arg4, arg5,
169 arg6, arg7, arg8, arg9);
170
4faf7757 171 if (ehca_lock_hcalls)
5d88278e
SR
172 spin_unlock_irqrestore(&hcall_lock, flags);
173
fab97220
HS
174 if (H_IS_LONG_BUSY(ret)) {
175 sleep_msecs = get_longbusy_msecs(ret);
176 msleep_interruptible(sleep_msecs);
177 continue;
178 }
179
2863ad4b
JF
180 if (ret < H_SUCCESS) {
181 ehca_gen_err("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT,
182 opcode, arg1, arg2, arg3, arg4, arg5,
183 arg6, arg7, arg8, arg9);
184 ehca_gen_err("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
185 ret, outs[0], outs[1], outs[2], outs[3],
186 outs[4], outs[5], outs[6], outs[7],
187 outs[8]);
4da27d6d 188 } else if (unlikely(ehca_debug_level >= 2))
2863ad4b
JF
189 ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
190 ret, outs[0], outs[1], outs[2], outs[3],
fab97220
HS
191 outs[4], outs[5], outs[6], outs[7],
192 outs[8]);
fab97220 193 return ret;
fab97220
HS
194 }
195
196 return H_BUSY;
197}
5d88278e 198
fab97220
HS
199u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
200 struct ehca_pfeq *pfeq,
201 const u32 neq_control,
202 const u32 number_of_entries,
203 struct ipz_eq_handle *eq_handle,
204 u32 *act_nr_of_entries,
205 u32 *act_pages,
206 u32 *eq_ist)
207{
208 u64 ret;
ee96aae5 209 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
210 u64 allocate_controls;
211
212 /* resource type */
213 allocate_controls = 3ULL;
214
215 /* ISN is associated */
216 if (neq_control != 1)
217 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
218 else /* notification event queue */
219 allocate_controls = (1ULL << 63) | allocate_controls;
220
221 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
222 adapter_handle.handle, /* r4 */
223 allocate_controls, /* r5 */
224 number_of_entries, /* r6 */
225 0, 0, 0, 0, 0, 0);
226 eq_handle->handle = outs[0];
227 *act_nr_of_entries = (u32)outs[3];
228 *act_pages = (u32)outs[4];
229 *eq_ist = (u32)outs[5];
230
231 if (ret == H_NOT_ENOUGH_RESOURCES)
3750f605 232 ehca_gen_err("Not enough resource - ret=%lli ", ret);
fab97220
HS
233
234 return ret;
235}
236
237u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
238 struct ipz_eq_handle eq_handle,
239 const u64 event_mask)
240{
241 return ehca_plpar_hcall_norets(H_RESET_EVENTS,
242 adapter_handle.handle, /* r4 */
243 eq_handle.handle, /* r5 */
244 event_mask, /* r6 */
245 0, 0, 0, 0);
246}
247
248u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
249 struct ehca_cq *cq,
250 struct ehca_alloc_cq_parms *param)
251{
e675b6db 252 int rc;
fab97220 253 u64 ret;
ee96aae5 254 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
255
256 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
257 adapter_handle.handle, /* r4 */
258 2, /* r5 */
259 param->eq_handle.handle, /* r6 */
260 cq->token, /* r7 */
261 param->nr_cqe, /* r8 */
262 0, 0, 0, 0);
263 cq->ipz_cq_handle.handle = outs[0];
264 param->act_nr_of_entries = (u32)outs[3];
265 param->act_pages = (u32)outs[4];
266
e675b6db
AS
267 if (ret == H_SUCCESS) {
268 rc = hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]);
269 if (rc) {
270 ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx",
271 rc, outs[5]);
272
273 ehca_plpar_hcall_norets(H_FREE_RESOURCE,
274 adapter_handle.handle, /* r4 */
275 cq->ipz_cq_handle.handle, /* r5 */
276 0, 0, 0, 0, 0);
277 ret = H_NO_MEM;
278 }
279 }
fab97220
HS
280
281 if (ret == H_NOT_ENOUGH_RESOURCES)
3750f605 282 ehca_gen_err("Not enough resources. ret=%lli", ret);
fab97220
HS
283
284 return ret;
285}
286
287u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
1988d1fa 288 struct ehca_alloc_qp_parms *parms, int is_user)
fab97220 289{
e675b6db 290 int rc;
fab97220 291 u64 ret;
a6a12947 292 u64 allocate_controls, max_r10_reg, r11, r12;
ee96aae5 293 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
294
295 allocate_controls =
9a79fc0a 296 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
fab97220
HS
297 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
298 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
299 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
e2f81daf
SR
300 | EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage)
301 | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE,
302 parms->squeue.page_size)
303 | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE,
304 parms->rqueue.page_size)
fab97220 305 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
9a79fc0a 306 !!(parms->ll_comp_flags & LLQP_RECV_COMP))
fab97220 307 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
9a79fc0a 308 !!(parms->ll_comp_flags & LLQP_SEND_COMP))
fab97220
HS
309 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
310 parms->ud_av_l_key_ctl)
311 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
312
313 max_r10_reg =
314 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
e2f81daf 315 parms->squeue.max_wr + 1)
fab97220 316 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
e2f81daf 317 parms->rqueue.max_wr + 1)
fab97220 318 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
e2f81daf 319 parms->squeue.max_sge)
fab97220 320 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
e2f81daf 321 parms->rqueue.max_sge);
fab97220 322
a6a12947
JF
323 r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
324
325 if (parms->ext_type == EQPT_SRQ)
326 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
327 else
328 r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
329
fab97220
HS
330 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
331 adapter_handle.handle, /* r4 */
332 allocate_controls, /* r5 */
9a79fc0a
JF
333 parms->send_cq_handle.handle,
334 parms->recv_cq_handle.handle,
335 parms->eq_handle.handle,
336 ((u64)parms->token << 32) | parms->pd.value,
a6a12947 337 max_r10_reg, r11, r12);
9a79fc0a
JF
338
339 parms->qp_handle.handle = outs[0];
340 parms->real_qp_num = (u32)outs[1];
e2f81daf 341 parms->squeue.act_nr_wqes =
fab97220 342 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
e2f81daf 343 parms->rqueue.act_nr_wqes =
fab97220 344 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
e2f81daf 345 parms->squeue.act_nr_sges =
fab97220 346 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
e2f81daf 347 parms->rqueue.act_nr_sges =
fab97220 348 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
e2f81daf 349 parms->squeue.queue_size =
fab97220 350 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
e2f81daf 351 parms->rqueue.queue_size =
fab97220
HS
352 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
353
e675b6db
AS
354 if (ret == H_SUCCESS) {
355 rc = hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]);
356 if (rc) {
357 ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx",
358 rc, outs[6]);
359
360 ehca_plpar_hcall_norets(H_FREE_RESOURCE,
361 adapter_handle.handle, /* r4 */
362 parms->qp_handle.handle, /* r5 */
363 0, 0, 0, 0, 0);
364 ret = H_NO_MEM;
365 }
366 }
fab97220
HS
367
368 if (ret == H_NOT_ENOUGH_RESOURCES)
3750f605 369 ehca_gen_err("Not enough resources. ret=%lli", ret);
fab97220
HS
370
371 return ret;
372}
373
374u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
375 const u8 port_id,
376 struct hipz_query_port *query_port_response_block)
377{
378 u64 ret;
b4b8d1e4 379 u64 r_cb = __pa(query_port_response_block);
fab97220
HS
380
381 if (r_cb & (EHCA_PAGESIZE-1)) {
382 ehca_gen_err("response block not page aligned");
383 return H_PARAMETER;
384 }
385
386 ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
387 adapter_handle.handle, /* r4 */
388 port_id, /* r5 */
389 r_cb, /* r6 */
390 0, 0, 0, 0);
391
4da27d6d 392 if (ehca_debug_level >= 2)
fab97220
HS
393 ehca_dmp(query_port_response_block, 64, "response_block");
394
395 return ret;
396}
397
c4ed790d
JF
398u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
399 const u8 port_id, const u32 port_cap,
400 const u8 init_type, const int modify_mask)
401{
402 u64 port_attributes = port_cap;
403
404 if (modify_mask & IB_PORT_SHUTDOWN)
405 port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
406 if (modify_mask & IB_PORT_INIT_TYPE)
407 port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
408 if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
409 port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
410
411 return ehca_plpar_hcall_norets(H_MODIFY_PORT,
412 adapter_handle.handle, /* r4 */
413 port_id, /* r5 */
414 port_attributes, /* r6 */
415 0, 0, 0, 0);
416}
417
fab97220
HS
418u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
419 struct hipz_query_hca *query_hca_rblock)
420{
b4b8d1e4 421 u64 r_cb = __pa(query_hca_rblock);
fab97220
HS
422
423 if (r_cb & (EHCA_PAGESIZE-1)) {
424 ehca_gen_err("response_block=%p not page aligned",
425 query_hca_rblock);
426 return H_PARAMETER;
427 }
428
429 return ehca_plpar_hcall_norets(H_QUERY_HCA,
430 adapter_handle.handle, /* r4 */
431 r_cb, /* r5 */
432 0, 0, 0, 0, 0);
433}
434
435u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
436 const u8 pagesize,
437 const u8 queue_type,
438 const u64 resource_handle,
439 const u64 logical_address_of_page,
440 u64 count)
441{
442 return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
443 adapter_handle.handle, /* r4 */
5bb7d929
HNN
444 (u64)queue_type | ((u64)pagesize) << 8,
445 /* r5 */
fab97220
HS
446 resource_handle, /* r6 */
447 logical_address_of_page, /* r7 */
448 count, /* r8 */
449 0, 0);
450}
451
452u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
453 const struct ipz_eq_handle eq_handle,
454 struct ehca_pfeq *pfeq,
455 const u8 pagesize,
456 const u8 queue_type,
457 const u64 logical_address_of_page,
458 const u64 count)
459{
460 if (count != 1) {
3750f605 461 ehca_gen_err("Ppage counter=%llx", count);
fab97220
HS
462 return H_PARAMETER;
463 }
464 return hipz_h_register_rpage(adapter_handle,
465 pagesize,
466 queue_type,
467 eq_handle.handle,
468 logical_address_of_page, count);
469}
470
471u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
472 u32 ist)
473{
474 u64 ret;
475 ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
476 adapter_handle.handle, /* r4 */
477 ist, /* r5 */
478 0, 0, 0, 0, 0);
479
480 if (ret != H_SUCCESS && ret != H_BUSY)
481 ehca_gen_err("Could not query interrupt state.");
482
483 return ret;
484}
485
486u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
487 const struct ipz_cq_handle cq_handle,
488 struct ehca_pfcq *pfcq,
489 const u8 pagesize,
490 const u8 queue_type,
491 const u64 logical_address_of_page,
492 const u64 count,
493 const struct h_galpa gal)
494{
495 if (count != 1) {
3750f605 496 ehca_gen_err("Page counter=%llx", count);
fab97220
HS
497 return H_PARAMETER;
498 }
499
500 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
501 cq_handle.handle, logical_address_of_page,
502 count);
503}
504
505u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
506 const struct ipz_qp_handle qp_handle,
507 struct ehca_pfqp *pfqp,
508 const u8 pagesize,
509 const u8 queue_type,
510 const u64 logical_address_of_page,
511 const u64 count,
512 const struct h_galpa galpa)
513{
e2f81daf 514 if (count > 1) {
3750f605 515 ehca_gen_err("Page counter=%llx", count);
fab97220
HS
516 return H_PARAMETER;
517 }
518
2b94397a
HNN
519 return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
520 qp_handle.handle, logical_address_of_page,
fab97220
HS
521 count);
522}
523
524u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
525 const struct ipz_qp_handle qp_handle,
526 struct ehca_pfqp *pfqp,
527 void **log_addr_next_sq_wqe2processed,
528 void **log_addr_next_rq_wqe2processed,
529 int dis_and_get_function_code)
530{
531 u64 ret;
ee96aae5 532 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
533
534 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
535 adapter_handle.handle, /* r4 */
536 dis_and_get_function_code, /* r5 */
537 qp_handle.handle, /* r6 */
538 0, 0, 0, 0, 0, 0);
539 if (log_addr_next_sq_wqe2processed)
2b94397a 540 *log_addr_next_sq_wqe2processed = (void *)outs[0];
fab97220 541 if (log_addr_next_rq_wqe2processed)
2b94397a 542 *log_addr_next_rq_wqe2processed = (void *)outs[1];
fab97220
HS
543
544 return ret;
545}
546
547u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
548 const struct ipz_qp_handle qp_handle,
549 struct ehca_pfqp *pfqp,
550 const u64 update_mask,
551 struct hcp_modify_qp_control_block *mqpcb,
552 struct h_galpa gal)
553{
554 u64 ret;
ee96aae5 555 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
556 ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
557 adapter_handle.handle, /* r4 */
558 qp_handle.handle, /* r5 */
559 update_mask, /* r6 */
b4b8d1e4 560 __pa(mqpcb), /* r7 */
fab97220
HS
561 0, 0, 0, 0, 0);
562
563 if (ret == H_NOT_ENOUGH_RESOURCES)
3750f605 564 ehca_gen_err("Insufficient resources ret=%lli", ret);
fab97220
HS
565
566 return ret;
567}
568
569u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
570 const struct ipz_qp_handle qp_handle,
571 struct ehca_pfqp *pfqp,
572 struct hcp_modify_qp_control_block *qqpcb,
573 struct h_galpa gal)
574{
575 return ehca_plpar_hcall_norets(H_QUERY_QP,
576 adapter_handle.handle, /* r4 */
577 qp_handle.handle, /* r5 */
b4b8d1e4 578 __pa(qqpcb), /* r6 */
fab97220
HS
579 0, 0, 0, 0);
580}
581
582u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
583 struct ehca_qp *qp)
584{
585 u64 ret;
ee96aae5 586 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
587
588 ret = hcp_galpas_dtor(&qp->galpas);
589 if (ret) {
590 ehca_gen_err("Could not destruct qp->galpas");
591 return H_RESOURCE;
592 }
593 ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
594 adapter_handle.handle, /* r4 */
595 /* function code */
596 1, /* r5 */
597 qp->ipz_qp_handle.handle, /* r6 */
598 0, 0, 0, 0, 0, 0);
599 if (ret == H_HARDWARE)
3750f605 600 ehca_gen_err("HCA not operational. ret=%lli", ret);
fab97220
HS
601
602 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
603 adapter_handle.handle, /* r4 */
604 qp->ipz_qp_handle.handle, /* r5 */
605 0, 0, 0, 0, 0);
606
607 if (ret == H_RESOURCE)
3750f605 608 ehca_gen_err("Resource still in use. ret=%lli", ret);
fab97220
HS
609
610 return ret;
611}
612
613u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
614 const struct ipz_qp_handle qp_handle,
615 struct h_galpa gal,
616 u32 port)
617{
618 return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
619 adapter_handle.handle, /* r4 */
620 qp_handle.handle, /* r5 */
621 port, /* r6 */
622 0, 0, 0, 0);
623}
624
625u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
626 const struct ipz_qp_handle qp_handle,
627 struct h_galpa gal,
628 u32 port, u32 * pma_qp_nr,
629 u32 * bma_qp_nr)
630{
631 u64 ret;
ee96aae5 632 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
633
634 ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
635 adapter_handle.handle, /* r4 */
636 qp_handle.handle, /* r5 */
637 port, /* r6 */
638 0, 0, 0, 0, 0, 0);
639 *pma_qp_nr = (u32)outs[0];
640 *bma_qp_nr = (u32)outs[1];
641
642 if (ret == H_ALIAS_EXIST)
3750f605 643 ehca_gen_err("AQP1 already exists. ret=%lli", ret);
fab97220
HS
644
645 return ret;
646}
647
648u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
649 const struct ipz_qp_handle qp_handle,
650 struct h_galpa gal,
651 u16 mcg_dlid,
652 u64 subnet_prefix, u64 interface_id)
653{
654 u64 ret;
655
656 ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
657 adapter_handle.handle, /* r4 */
658 qp_handle.handle, /* r5 */
659 mcg_dlid, /* r6 */
660 interface_id, /* r7 */
661 subnet_prefix, /* r8 */
662 0, 0);
663
664 if (ret == H_NOT_ENOUGH_RESOURCES)
3750f605 665 ehca_gen_err("Not enough resources. ret=%lli", ret);
fab97220
HS
666
667 return ret;
668}
669
670u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
671 const struct ipz_qp_handle qp_handle,
672 struct h_galpa gal,
673 u16 mcg_dlid,
674 u64 subnet_prefix, u64 interface_id)
675{
676 return ehca_plpar_hcall_norets(H_DETACH_MCQP,
677 adapter_handle.handle, /* r4 */
678 qp_handle.handle, /* r5 */
679 mcg_dlid, /* r6 */
680 interface_id, /* r7 */
681 subnet_prefix, /* r8 */
682 0, 0);
683}
684
685u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
686 struct ehca_cq *cq,
687 u8 force_flag)
688{
689 u64 ret;
690
691 ret = hcp_galpas_dtor(&cq->galpas);
692 if (ret) {
693 ehca_gen_err("Could not destruct cp->galpas");
694 return H_RESOURCE;
695 }
696
697 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
698 adapter_handle.handle, /* r4 */
699 cq->ipz_cq_handle.handle, /* r5 */
700 force_flag != 0 ? 1L : 0L, /* r6 */
701 0, 0, 0, 0);
702
703 if (ret == H_RESOURCE)
3750f605 704 ehca_gen_err("H_FREE_RESOURCE failed ret=%lli ", ret);
fab97220
HS
705
706 return ret;
707}
708
709u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
710 struct ehca_eq *eq)
711{
712 u64 ret;
713
714 ret = hcp_galpas_dtor(&eq->galpas);
715 if (ret) {
716 ehca_gen_err("Could not destruct eq->galpas");
717 return H_RESOURCE;
718 }
719
720 ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
721 adapter_handle.handle, /* r4 */
722 eq->ipz_eq_handle.handle, /* r5 */
723 0, 0, 0, 0, 0);
724
725 if (ret == H_RESOURCE)
3750f605 726 ehca_gen_err("Resource in use. ret=%lli ", ret);
fab97220
HS
727
728 return ret;
729}
730
731u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
732 const struct ehca_mr *mr,
733 const u64 vaddr,
734 const u64 length,
735 const u32 access_ctrl,
736 const struct ipz_pd pd,
737 struct ehca_mr_hipzout_parms *outparms)
738{
739 u64 ret;
ee96aae5 740 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
741
742 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
743 adapter_handle.handle, /* r4 */
744 5, /* r5 */
745 vaddr, /* r6 */
746 length, /* r7 */
747 (((u64)access_ctrl) << 32ULL), /* r8 */
748 pd.value, /* r9 */
749 0, 0, 0);
750 outparms->handle.handle = outs[0];
751 outparms->lkey = (u32)outs[2];
752 outparms->rkey = (u32)outs[3];
753
754 return ret;
755}
756
757u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
758 const struct ehca_mr *mr,
759 const u8 pagesize,
760 const u8 queue_type,
761 const u64 logical_address_of_page,
762 const u64 count)
763{
764 u64 ret;
765
4da27d6d 766 if (unlikely(ehca_debug_level >= 3)) {
5bb7d929
HNN
767 if (count > 1) {
768 u64 *kpage;
769 int i;
b4b8d1e4 770 kpage = __va(logical_address_of_page);
5bb7d929
HNN
771 for (i = 0; i < count; i++)
772 ehca_gen_dbg("kpage[%d]=%p",
773 i, (void *)kpage[i]);
774 } else
775 ehca_gen_dbg("kpage=%p",
776 (void *)logical_address_of_page);
777 }
778
fab97220
HS
779 if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
780 ehca_gen_err("logical_address_of_page not on a 4k boundary "
3750f605 781 "adapter_handle=%llx mr=%p mr_handle=%llx "
fab97220 782 "pagesize=%x queue_type=%x "
3750f605 783 "logical_address_of_page=%llx count=%llx",
fab97220
HS
784 adapter_handle.handle, mr,
785 mr->ipz_mr_handle.handle, pagesize, queue_type,
786 logical_address_of_page, count);
787 ret = H_PARAMETER;
788 } else
789 ret = hipz_h_register_rpage(adapter_handle, pagesize,
790 queue_type,
791 mr->ipz_mr_handle.handle,
792 logical_address_of_page, count);
793 return ret;
794}
795
796u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
797 const struct ehca_mr *mr,
798 struct ehca_mr_hipzout_parms *outparms)
799{
800 u64 ret;
ee96aae5 801 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
802
803 ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
804 adapter_handle.handle, /* r4 */
805 mr->ipz_mr_handle.handle, /* r5 */
806 0, 0, 0, 0, 0, 0, 0);
807 outparms->len = outs[0];
808 outparms->vaddr = outs[1];
809 outparms->acl = outs[4] >> 32;
810 outparms->lkey = (u32)(outs[5] >> 32);
811 outparms->rkey = (u32)(outs[5] & (0xffffffff));
812
813 return ret;
814}
815
816u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
817 const struct ehca_mr *mr)
818{
819 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
820 adapter_handle.handle, /* r4 */
821 mr->ipz_mr_handle.handle, /* r5 */
4faf7757 822 0, 0, 0, 0, 0);
fab97220
HS
823}
824
825u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
826 const struct ehca_mr *mr,
827 const u64 vaddr_in,
828 const u64 length,
829 const u32 access_ctrl,
830 const struct ipz_pd pd,
831 const u64 mr_addr_cb,
832 struct ehca_mr_hipzout_parms *outparms)
833{
834 u64 ret;
ee96aae5 835 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
836
837 ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
838 adapter_handle.handle, /* r4 */
839 mr->ipz_mr_handle.handle, /* r5 */
840 vaddr_in, /* r6 */
841 length, /* r7 */
842 /* r8 */
843 ((((u64)access_ctrl) << 32ULL) | pd.value),
844 mr_addr_cb, /* r9 */
845 0, 0, 0);
846 outparms->vaddr = outs[1];
847 outparms->lkey = (u32)outs[2];
848 outparms->rkey = (u32)outs[3];
849
850 return ret;
851}
852
853u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
854 const struct ehca_mr *mr,
855 const struct ehca_mr *orig_mr,
856 const u64 vaddr_in,
857 const u32 access_ctrl,
858 const struct ipz_pd pd,
859 struct ehca_mr_hipzout_parms *outparms)
860{
861 u64 ret;
ee96aae5 862 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
863
864 ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
865 adapter_handle.handle, /* r4 */
866 orig_mr->ipz_mr_handle.handle, /* r5 */
867 vaddr_in, /* r6 */
868 (((u64)access_ctrl) << 32ULL), /* r7 */
869 pd.value, /* r8 */
870 0, 0, 0, 0);
871 outparms->handle.handle = outs[0];
872 outparms->lkey = (u32)outs[2];
873 outparms->rkey = (u32)outs[3];
874
875 return ret;
876}
877
878u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
879 const struct ehca_mw *mw,
880 const struct ipz_pd pd,
881 struct ehca_mw_hipzout_parms *outparms)
882{
883 u64 ret;
ee96aae5 884 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
885
886 ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
887 adapter_handle.handle, /* r4 */
888 6, /* r5 */
889 pd.value, /* r6 */
890 0, 0, 0, 0, 0, 0);
891 outparms->handle.handle = outs[0];
892 outparms->rkey = (u32)outs[3];
893
894 return ret;
895}
896
897u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
898 const struct ehca_mw *mw,
899 struct ehca_mw_hipzout_parms *outparms)
900{
901 u64 ret;
ee96aae5 902 unsigned long outs[PLPAR_HCALL9_BUFSIZE];
fab97220
HS
903
904 ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
905 adapter_handle.handle, /* r4 */
906 mw->ipz_mw_handle.handle, /* r5 */
907 0, 0, 0, 0, 0, 0, 0);
908 outparms->rkey = (u32)outs[3];
909
910 return ret;
911}
912
913u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
914 const struct ehca_mw *mw)
915{
916 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
917 adapter_handle.handle, /* r4 */
918 mw->ipz_mw_handle.handle, /* r5 */
919 0, 0, 0, 0, 0);
920}
921
922u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
923 const u64 ressource_handle,
924 void *rblock,
925 unsigned long *byte_count)
926{
b4b8d1e4 927 u64 r_cb = __pa(rblock);
fab97220
HS
928
929 if (r_cb & (EHCA_PAGESIZE-1)) {
930 ehca_gen_err("rblock not page aligned.");
931 return H_PARAMETER;
932 }
933
934 return ehca_plpar_hcall_norets(H_ERROR_DATA,
935 adapter_handle.handle,
936 ressource_handle,
937 r_cb,
938 0, 0, 0, 0);
939}
6f7bc01a
SR
940
941u64 hipz_h_eoi(int irq)
942{
943 unsigned long xirr;
944
945 iosync();
946 xirr = (0xffULL << 24) | irq;
947
948 return plpar_hcall_norets(H_EOI, xirr);
949}
This page took 0.630411 seconds and 5 git commands to generate.