Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-2.6] / drivers / infiniband / hw / ehca / hcp_if.c
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
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
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         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                 /* serialize hCalls to work around firmware issue */
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
159 static long ehca_plpar_hcall9(unsigned long opcode,
160                               unsigned long *outs, /* array of 9 outputs */
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                 /* serialize hCalls to work around firmware issue */
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
215 u64 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         /* resource type */
229         allocate_controls = 3ULL;
230
231         /* ISN is associated */
232         if (neq_control != 1)
233                 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
234         else /* notification event queue */
235                 allocate_controls = (1ULL << 63) | allocate_controls;
236
237         ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
238                                 adapter_handle.handle,  /* r4 */
239                                 allocate_controls,      /* r5 */
240                                 number_of_entries,      /* r6 */
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
253 u64 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, /* r4 */
259                                        eq_handle.handle,      /* r5 */
260                                        event_mask,            /* r6 */
261                                        0, 0, 0, 0);
262 }
263
264 u64 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,   /* r4  */
273                                 2,                       /* r5  */
274                                 param->eq_handle.handle, /* r6  */
275                                 cq->token,               /* r7  */
276                                 param->nr_cqe,           /* r8  */
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
291 u64 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,             /* r4  */
335                                 allocate_controls,                 /* r5  */
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
366 u64 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, /* r4 */
380                                       port_id,               /* r5 */
381                                       r_cb,                  /* r6 */
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
390 u64 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, /* r4 */
405                                        port_id,               /* r5 */
406                                        port_attributes,       /* r6 */
407                                        0, 0, 0, 0);
408 }
409
410 u64 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, /* r4 */
423                                        r_cb,                  /* r5 */
424                                        0, 0, 0, 0, 0);
425 }
426
427 u64 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,      /* r4  */
436                                        (u64)queue_type | ((u64)pagesize) << 8,
437                                        /* r5  */
438                                        resource_handle,            /* r6  */
439                                        logical_address_of_page,    /* r7  */
440                                        count,                      /* r8  */
441                                        0, 0);
442 }
443
444 u64 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
463 u64 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, /* r4 */
469                                       ist,                   /* r5 */
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
478 u64 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
497 u64 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
516 u64 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,     /* r4 */
528                                 dis_and_get_function_code, /* r5 */
529                                 qp_handle.handle,          /* r6 */
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
539 u64 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, /* r4 */
550                                 qp_handle.handle,      /* r5 */
551                                 update_mask,           /* r6 */
552                                 virt_to_abs(mqpcb),    /* r7 */
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
561 u64 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, /* r4 */
569                                        qp_handle.handle,      /* r5 */
570                                        virt_to_abs(qqpcb),    /* r6 */
571                                        0, 0, 0, 0);
572 }
573
574 u64 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,     /* r4 */
587                                 /* function code */
588                                 1,                         /* r5 */
589                                 qp->ipz_qp_handle.handle,  /* r6 */
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,     /* r4 */
596                                       qp->ipz_qp_handle.handle,  /* r5 */
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
605 u64 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, /* r4 */
612                                        qp_handle.handle,      /* r5 */
613                                        port,                  /* r6 */
614                                        0, 0, 0, 0);
615 }
616
617 u64 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, /* r4 */
628                                 qp_handle.handle,      /* r5 */
629                                 port,                  /* r6 */
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
640 u64 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,  /* r4 */
650                                       qp_handle.handle,       /* r5 */
651                                       mcg_dlid,               /* r6 */
652                                       interface_id,           /* r7 */
653                                       subnet_prefix,          /* r8 */
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
662 u64 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, /* r4 */
670                                        qp_handle.handle,      /* r5 */
671                                        mcg_dlid,              /* r6 */
672                                        interface_id,          /* r7 */
673                                        subnet_prefix,         /* r8 */
674                                        0, 0);
675 }
676
677 u64 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,     /* r4 */
691                                       cq->ipz_cq_handle.handle,  /* r5 */
692                                       force_flag != 0 ? 1L : 0L, /* r6 */
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
701 u64 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,     /* r4 */
714                                       eq->ipz_eq_handle.handle,  /* r5 */
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
723 u64 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,            /* r4 */
739                                 5,                                /* r5 */
740                                 vaddr,                            /* r6 */
741                                 length,                           /* r7 */
742                                 (((u64)access_ctrl) << 32ULL),    /* r8 */
743                                 pd.value,                         /* r9 */
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
752 u64 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
791 u64 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,     /* r4 */
800                                 mr->ipz_mr_handle.handle,  /* r5 */
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
811 u64 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,    /* r4 */
816                                        mr->ipz_mr_handle.handle, /* r5 */
817                                        0, 0, 0, 0, 0);
818 }
819
820 u64 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,    /* r4 */
834                                 mr->ipz_mr_handle.handle, /* r5 */
835                                 vaddr_in,                 /* r6 */
836                                 length,                   /* r7 */
837                                 /* r8 */
838                                 ((((u64)access_ctrl) << 32ULL) | pd.value),
839                                 mr_addr_cb,               /* r9 */
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
848 u64 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,            /* r4 */
861                                 orig_mr->ipz_mr_handle.handle,    /* r5 */
862                                 vaddr_in,                         /* r6 */
863                                 (((u64)access_ctrl) << 32ULL),    /* r7 */
864                                 pd.value,                         /* r8 */
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
873 u64 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,      /* r4 */
883                                 6,                          /* r5 */
884                                 pd.value,                   /* r6 */
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
892 u64 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,    /* r4 */
901                                 mw->ipz_mw_handle.handle, /* r5 */
902                                 0, 0, 0, 0, 0, 0, 0);
903         outparms->rkey = (u32)outs[3];
904
905         return ret;
906 }
907
908 u64 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,    /* r4 */
913                                        mw->ipz_mw_handle.handle, /* r5 */
914                                        0, 0, 0, 0, 0);
915 }
916
917 u64 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 }