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