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