Pull percpu-dtc into release branch
[sfrench/cifs-2.6.git] / 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  *           Gerd Bayer <gerd.bayer@de.ibm.com>
9  *           Waleri Fomin <fomin@de.ibm.com>
10  *
11  *  Copyright (c) 2005 IBM Corporation
12  *
13  *  All rights reserved.
14  *
15  *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
16  *  BSD.
17  *
18  * OpenIB BSD License
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions are met:
22  *
23  * Redistributions of source code must retain the above copyright notice, this
24  * list of conditions and the following disclaimer.
25  *
26  * Redistributions in binary form must reproduce the above copyright notice,
27  * this list of conditions and the following disclaimer in the documentation
28  * and/or other materials
29  * provided with the distribution.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
35  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
38  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
39  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGE.
42  */
43
44 #include <asm/hvcall.h>
45 #include "ehca_tools.h"
46 #include "hcp_if.h"
47 #include "hcp_phyp.h"
48 #include "hipz_fns.h"
49 #include "ipz_pt_fn.h"
50
51 #define H_ALL_RES_QP_ENHANCED_OPS       EHCA_BMASK_IBM(9, 11)
52 #define H_ALL_RES_QP_PTE_PIN            EHCA_BMASK_IBM(12, 12)
53 #define H_ALL_RES_QP_SERVICE_TYPE       EHCA_BMASK_IBM(13, 15)
54 #define H_ALL_RES_QP_LL_RQ_CQE_POSTING  EHCA_BMASK_IBM(18, 18)
55 #define H_ALL_RES_QP_LL_SQ_CQE_POSTING  EHCA_BMASK_IBM(19, 21)
56 #define H_ALL_RES_QP_SIGNALING_TYPE     EHCA_BMASK_IBM(22, 23)
57 #define H_ALL_RES_QP_UD_AV_LKEY_CTRL    EHCA_BMASK_IBM(31, 31)
58 #define H_ALL_RES_QP_RESOURCE_TYPE      EHCA_BMASK_IBM(56, 63)
59
60 #define H_ALL_RES_QP_MAX_OUTST_SEND_WR  EHCA_BMASK_IBM(0, 15)
61 #define H_ALL_RES_QP_MAX_OUTST_RECV_WR  EHCA_BMASK_IBM(16, 31)
62 #define H_ALL_RES_QP_MAX_SEND_SGE       EHCA_BMASK_IBM(32, 39)
63 #define H_ALL_RES_QP_MAX_RECV_SGE       EHCA_BMASK_IBM(40, 47)
64
65 #define H_ALL_RES_QP_ACT_OUTST_SEND_WR  EHCA_BMASK_IBM(16, 31)
66 #define H_ALL_RES_QP_ACT_OUTST_RECV_WR  EHCA_BMASK_IBM(48, 63)
67 #define H_ALL_RES_QP_ACT_SEND_SGE       EHCA_BMASK_IBM(8, 15)
68 #define H_ALL_RES_QP_ACT_RECV_SGE       EHCA_BMASK_IBM(24, 31)
69
70 #define H_ALL_RES_QP_SQUEUE_SIZE_PAGES  EHCA_BMASK_IBM(0, 31)
71 #define H_ALL_RES_QP_RQUEUE_SIZE_PAGES  EHCA_BMASK_IBM(32, 63)
72
73 #define H_MP_INIT_TYPE                  EHCA_BMASK_IBM(44, 47)
74 #define H_MP_SHUTDOWN                   EHCA_BMASK_IBM(48, 48)
75 #define H_MP_RESET_QKEY_CTR             EHCA_BMASK_IBM(49, 49)
76
77 /* direct access qp controls */
78 #define DAQP_CTRL_ENABLE    0x01
79 #define DAQP_CTRL_SEND_COMP 0x20
80 #define DAQP_CTRL_RECV_COMP 0x40
81
82 static u32 get_longbusy_msecs(int longbusy_rc)
83 {
84         switch (longbusy_rc) {
85         case H_LONG_BUSY_ORDER_1_MSEC:
86                 return 1;
87         case H_LONG_BUSY_ORDER_10_MSEC:
88                 return 10;
89         case H_LONG_BUSY_ORDER_100_MSEC:
90                 return 100;
91         case H_LONG_BUSY_ORDER_1_SEC:
92                 return 1000;
93         case H_LONG_BUSY_ORDER_10_SEC:
94                 return 10000;
95         case H_LONG_BUSY_ORDER_100_SEC:
96                 return 100000;
97         default:
98                 return 1;
99         }
100 }
101
102 static long ehca_plpar_hcall_norets(unsigned long opcode,
103                                     unsigned long arg1,
104                                     unsigned long arg2,
105                                     unsigned long arg3,
106                                     unsigned long arg4,
107                                     unsigned long arg5,
108                                     unsigned long arg6,
109                                     unsigned long arg7)
110 {
111         long ret;
112         int i, sleep_msecs;
113
114         ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
115                      "arg5=%lx arg6=%lx arg7=%lx",
116                      opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
117
118         for (i = 0; i < 5; i++) {
119                 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
120                                          arg5, arg6, arg7);
121
122                 if (H_IS_LONG_BUSY(ret)) {
123                         sleep_msecs = get_longbusy_msecs(ret);
124                         msleep_interruptible(sleep_msecs);
125                         continue;
126                 }
127
128                 if (ret < H_SUCCESS)
129                         ehca_gen_err("opcode=%lx ret=%lx"
130                                      " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
131                                      " arg5=%lx arg6=%lx arg7=%lx ",
132                                      opcode, ret,
133                                      arg1, arg2, arg3, arg4, arg5,
134                                      arg6, arg7);
135
136                 ehca_gen_dbg("opcode=%lx ret=%lx", opcode, ret);
137                 return ret;
138
139         }
140
141         return H_BUSY;
142 }
143
144 static long ehca_plpar_hcall9(unsigned long opcode,
145                               unsigned long *outs, /* array of 9 outputs */
146                               unsigned long arg1,
147                               unsigned long arg2,
148                               unsigned long arg3,
149                               unsigned long arg4,
150                               unsigned long arg5,
151                               unsigned long arg6,
152                               unsigned long arg7,
153                               unsigned long arg8,
154                               unsigned long arg9)
155 {
156         long ret;
157         int i, sleep_msecs;
158
159         ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
160                      "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
161                      opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
162                      arg8, arg9);
163
164         for (i = 0; i < 5; i++) {
165                 ret = plpar_hcall9(opcode, outs,
166                                    arg1, arg2, arg3, arg4, arg5,
167                                    arg6, arg7, arg8, arg9);
168
169                 if (H_IS_LONG_BUSY(ret)) {
170                         sleep_msecs = get_longbusy_msecs(ret);
171                         msleep_interruptible(sleep_msecs);
172                         continue;
173                 }
174
175                 if (ret < H_SUCCESS)
176                         ehca_gen_err("opcode=%lx ret=%lx"
177                                      " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
178                                      " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
179                                      " arg9=%lx"
180                                      " out1=%lx out2=%lx out3=%lx out4=%lx"
181                                      " out5=%lx out6=%lx out7=%lx out8=%lx"
182                                      " out9=%lx",
183                                      opcode, ret,
184                                      arg1, arg2, arg3, arg4, arg5,
185                                      arg6, arg7, arg8, arg9,
186                                      outs[0], outs[1], outs[2], outs[3],
187                                      outs[4], outs[5], outs[6], outs[7],
188                                      outs[8]);
189
190                 ehca_gen_dbg("opcode=%lx ret=%lx out1=%lx out2=%lx out3=%lx "
191                              "out4=%lx out5=%lx out6=%lx out7=%lx out8=%lx "
192                              "out9=%lx",
193                              opcode, ret, outs[0], outs[1], outs[2], outs[3],
194                              outs[4], outs[5], outs[6], outs[7], outs[8]);
195                 return ret;
196
197         }
198
199         return H_BUSY;
200 }
201 u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
202                              struct ehca_pfeq *pfeq,
203                              const u32 neq_control,
204                              const u32 number_of_entries,
205                              struct ipz_eq_handle *eq_handle,
206                              u32 *act_nr_of_entries,
207                              u32 *act_pages,
208                              u32 *eq_ist)
209 {
210         u64 ret;
211         u64 outs[PLPAR_HCALL9_BUFSIZE];
212         u64 allocate_controls;
213
214         /* resource type */
215         allocate_controls = 3ULL;
216
217         /* ISN is associated */
218         if (neq_control != 1)
219                 allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
220         else /* notification event queue */
221                 allocate_controls = (1ULL << 63) | allocate_controls;
222
223         ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
224                                 adapter_handle.handle,  /* r4 */
225                                 allocate_controls,      /* r5 */
226                                 number_of_entries,      /* r6 */
227                                 0, 0, 0, 0, 0, 0);
228         eq_handle->handle = outs[0];
229         *act_nr_of_entries = (u32)outs[3];
230         *act_pages = (u32)outs[4];
231         *eq_ist = (u32)outs[5];
232
233         if (ret == H_NOT_ENOUGH_RESOURCES)
234                 ehca_gen_err("Not enough resource - ret=%lx ", ret);
235
236         return ret;
237 }
238
239 u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
240                        struct ipz_eq_handle eq_handle,
241                        const u64 event_mask)
242 {
243         return ehca_plpar_hcall_norets(H_RESET_EVENTS,
244                                        adapter_handle.handle, /* r4 */
245                                        eq_handle.handle,      /* r5 */
246                                        event_mask,            /* r6 */
247                                        0, 0, 0, 0);
248 }
249
250 u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
251                              struct ehca_cq *cq,
252                              struct ehca_alloc_cq_parms *param)
253 {
254         u64 ret;
255         u64 outs[PLPAR_HCALL9_BUFSIZE];
256
257         ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
258                                 adapter_handle.handle,   /* r4  */
259                                 2,                       /* r5  */
260                                 param->eq_handle.handle, /* r6  */
261                                 cq->token,               /* r7  */
262                                 param->nr_cqe,           /* r8  */
263                                 0, 0, 0, 0);
264         cq->ipz_cq_handle.handle = outs[0];
265         param->act_nr_of_entries = (u32)outs[3];
266         param->act_pages = (u32)outs[4];
267
268         if (ret == H_SUCCESS)
269                 hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
270
271         if (ret == H_NOT_ENOUGH_RESOURCES)
272                 ehca_gen_err("Not enough resources. ret=%lx", ret);
273
274         return ret;
275 }
276
277 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
278                              struct ehca_qp *qp,
279                              struct ehca_alloc_qp_parms *parms)
280 {
281         u64 ret;
282         u64 allocate_controls;
283         u64 max_r10_reg;
284         u64 outs[PLPAR_HCALL9_BUFSIZE];
285         u16 max_nr_receive_wqes = qp->init_attr.cap.max_recv_wr + 1;
286         u16 max_nr_send_wqes = qp->init_attr.cap.max_send_wr + 1;
287         int daqp_ctrl = parms->daqp_ctrl;
288
289         allocate_controls =
290                 EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS,
291                                (daqp_ctrl & DAQP_CTRL_ENABLE) ? 1 : 0)
292                 | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
293                 | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
294                 | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
295                 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
296                                  (daqp_ctrl & DAQP_CTRL_RECV_COMP) ? 1 : 0)
297                 | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
298                                  (daqp_ctrl & DAQP_CTRL_SEND_COMP) ? 1 : 0)
299                 | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
300                                  parms->ud_av_l_key_ctl)
301                 | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
302
303         max_r10_reg =
304                 EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
305                                max_nr_send_wqes)
306                 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
307                                  max_nr_receive_wqes)
308                 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
309                                  parms->max_send_sge)
310                 | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
311                                  parms->max_recv_sge);
312
313         ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
314                                 adapter_handle.handle,             /* r4  */
315                                 allocate_controls,                 /* r5  */
316                                 qp->send_cq->ipz_cq_handle.handle,
317                                 qp->recv_cq->ipz_cq_handle.handle,
318                                 parms->ipz_eq_handle.handle,
319                                 ((u64)qp->token << 32) | parms->pd.value,
320                                 max_r10_reg,                       /* r10 */
321                                 parms->ud_av_l_key_ctl,            /* r11 */
322                                 0);
323         qp->ipz_qp_handle.handle = outs[0];
324         qp->real_qp_num = (u32)outs[1];
325         parms->act_nr_send_sges =
326                 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
327         parms->act_nr_recv_wqes =
328                 (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
329         parms->act_nr_send_sges =
330                 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
331         parms->act_nr_recv_sges =
332                 (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
333         parms->nr_sq_pages =
334                 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
335         parms->nr_rq_pages =
336                 (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
337
338         if (ret == H_SUCCESS)
339                 hcp_galpas_ctor(&qp->galpas, outs[6], outs[6]);
340
341         if (ret == H_NOT_ENOUGH_RESOURCES)
342                 ehca_gen_err("Not enough resources. ret=%lx", ret);
343
344         return ret;
345 }
346
347 u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
348                       const u8 port_id,
349                       struct hipz_query_port *query_port_response_block)
350 {
351         u64 ret;
352         u64 r_cb = virt_to_abs(query_port_response_block);
353
354         if (r_cb & (EHCA_PAGESIZE-1)) {
355                 ehca_gen_err("response block not page aligned");
356                 return H_PARAMETER;
357         }
358
359         ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
360                                       adapter_handle.handle, /* r4 */
361                                       port_id,               /* r5 */
362                                       r_cb,                  /* r6 */
363                                       0, 0, 0, 0);
364
365         if (ehca_debug_level)
366                 ehca_dmp(query_port_response_block, 64, "response_block");
367
368         return ret;
369 }
370
371 u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
372                        const u8 port_id, const u32 port_cap,
373                        const u8 init_type, const int modify_mask)
374 {
375         u64 port_attributes = port_cap;
376
377         if (modify_mask & IB_PORT_SHUTDOWN)
378                 port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
379         if (modify_mask & IB_PORT_INIT_TYPE)
380                 port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
381         if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
382                 port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
383
384         return ehca_plpar_hcall_norets(H_MODIFY_PORT,
385                                        adapter_handle.handle, /* r4 */
386                                        port_id,               /* r5 */
387                                        port_attributes,       /* r6 */
388                                        0, 0, 0, 0);
389 }
390
391 u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
392                      struct hipz_query_hca *query_hca_rblock)
393 {
394         u64 r_cb = virt_to_abs(query_hca_rblock);
395
396         if (r_cb & (EHCA_PAGESIZE-1)) {
397                 ehca_gen_err("response_block=%p not page aligned",
398                              query_hca_rblock);
399                 return H_PARAMETER;
400         }
401
402         return ehca_plpar_hcall_norets(H_QUERY_HCA,
403                                        adapter_handle.handle, /* r4 */
404                                        r_cb,                  /* r5 */
405                                        0, 0, 0, 0, 0);
406 }
407
408 u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
409                           const u8 pagesize,
410                           const u8 queue_type,
411                           const u64 resource_handle,
412                           const u64 logical_address_of_page,
413                           u64 count)
414 {
415         return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
416                                        adapter_handle.handle,      /* r4  */
417                                        queue_type | pagesize << 8, /* r5  */
418                                        resource_handle,            /* r6  */
419                                        logical_address_of_page,    /* r7  */
420                                        count,                      /* r8  */
421                                        0, 0);
422 }
423
424 u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
425                              const struct ipz_eq_handle eq_handle,
426                              struct ehca_pfeq *pfeq,
427                              const u8 pagesize,
428                              const u8 queue_type,
429                              const u64 logical_address_of_page,
430                              const u64 count)
431 {
432         if (count != 1) {
433                 ehca_gen_err("Ppage counter=%lx", count);
434                 return H_PARAMETER;
435         }
436         return hipz_h_register_rpage(adapter_handle,
437                                      pagesize,
438                                      queue_type,
439                                      eq_handle.handle,
440                                      logical_address_of_page, count);
441 }
442
443 u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
444                            u32 ist)
445 {
446         u64 ret;
447         ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
448                                       adapter_handle.handle, /* r4 */
449                                       ist,                   /* r5 */
450                                       0, 0, 0, 0, 0);
451
452         if (ret != H_SUCCESS && ret != H_BUSY)
453                 ehca_gen_err("Could not query interrupt state.");
454
455         return ret;
456 }
457
458 u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
459                              const struct ipz_cq_handle cq_handle,
460                              struct ehca_pfcq *pfcq,
461                              const u8 pagesize,
462                              const u8 queue_type,
463                              const u64 logical_address_of_page,
464                              const u64 count,
465                              const struct h_galpa gal)
466 {
467         if (count != 1) {
468                 ehca_gen_err("Page counter=%lx", count);
469                 return H_PARAMETER;
470         }
471
472         return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
473                                      cq_handle.handle, logical_address_of_page,
474                                      count);
475 }
476
477 u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
478                              const struct ipz_qp_handle qp_handle,
479                              struct ehca_pfqp *pfqp,
480                              const u8 pagesize,
481                              const u8 queue_type,
482                              const u64 logical_address_of_page,
483                              const u64 count,
484                              const struct h_galpa galpa)
485 {
486         if (count != 1) {
487                 ehca_gen_err("Page counter=%lx", count);
488                 return H_PARAMETER;
489         }
490
491         return hipz_h_register_rpage(adapter_handle,pagesize,queue_type,
492                                      qp_handle.handle,logical_address_of_page,
493                                      count);
494 }
495
496 u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
497                                const struct ipz_qp_handle qp_handle,
498                                struct ehca_pfqp *pfqp,
499                                void **log_addr_next_sq_wqe2processed,
500                                void **log_addr_next_rq_wqe2processed,
501                                int dis_and_get_function_code)
502 {
503         u64 ret;
504         u64 outs[PLPAR_HCALL9_BUFSIZE];
505
506         ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
507                                 adapter_handle.handle,     /* r4 */
508                                 dis_and_get_function_code, /* r5 */
509                                 qp_handle.handle,          /* r6 */
510                                 0, 0, 0, 0, 0, 0);
511         if (log_addr_next_sq_wqe2processed)
512                 *log_addr_next_sq_wqe2processed = (void*)outs[0];
513         if (log_addr_next_rq_wqe2processed)
514                 *log_addr_next_rq_wqe2processed = (void*)outs[1];
515
516         return ret;
517 }
518
519 u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
520                      const struct ipz_qp_handle qp_handle,
521                      struct ehca_pfqp *pfqp,
522                      const u64 update_mask,
523                      struct hcp_modify_qp_control_block *mqpcb,
524                      struct h_galpa gal)
525 {
526         u64 ret;
527         u64 outs[PLPAR_HCALL9_BUFSIZE];
528         ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
529                                 adapter_handle.handle, /* r4 */
530                                 qp_handle.handle,      /* r5 */
531                                 update_mask,           /* r6 */
532                                 virt_to_abs(mqpcb),    /* r7 */
533                                 0, 0, 0, 0, 0);
534
535         if (ret == H_NOT_ENOUGH_RESOURCES)
536                 ehca_gen_err("Insufficient resources ret=%lx", ret);
537
538         return ret;
539 }
540
541 u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
542                     const struct ipz_qp_handle qp_handle,
543                     struct ehca_pfqp *pfqp,
544                     struct hcp_modify_qp_control_block *qqpcb,
545                     struct h_galpa gal)
546 {
547         return ehca_plpar_hcall_norets(H_QUERY_QP,
548                                        adapter_handle.handle, /* r4 */
549                                        qp_handle.handle,      /* r5 */
550                                        virt_to_abs(qqpcb),    /* r6 */
551                                        0, 0, 0, 0);
552 }
553
554 u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
555                       struct ehca_qp *qp)
556 {
557         u64 ret;
558         u64 outs[PLPAR_HCALL9_BUFSIZE];
559
560         ret = hcp_galpas_dtor(&qp->galpas);
561         if (ret) {
562                 ehca_gen_err("Could not destruct qp->galpas");
563                 return H_RESOURCE;
564         }
565         ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
566                                 adapter_handle.handle,     /* r4 */
567                                 /* function code */
568                                 1,                         /* r5 */
569                                 qp->ipz_qp_handle.handle,  /* r6 */
570                                 0, 0, 0, 0, 0, 0);
571         if (ret == H_HARDWARE)
572                 ehca_gen_err("HCA not operational. ret=%lx", ret);
573
574         ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
575                                       adapter_handle.handle,     /* r4 */
576                                       qp->ipz_qp_handle.handle,  /* r5 */
577                                       0, 0, 0, 0, 0);
578
579         if (ret == H_RESOURCE)
580                 ehca_gen_err("Resource still in use. ret=%lx", ret);
581
582         return ret;
583 }
584
585 u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
586                        const struct ipz_qp_handle qp_handle,
587                        struct h_galpa gal,
588                        u32 port)
589 {
590         return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
591                                        adapter_handle.handle, /* r4 */
592                                        qp_handle.handle,      /* r5 */
593                                        port,                  /* r6 */
594                                        0, 0, 0, 0);
595 }
596
597 u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
598                        const struct ipz_qp_handle qp_handle,
599                        struct h_galpa gal,
600                        u32 port, u32 * pma_qp_nr,
601                        u32 * bma_qp_nr)
602 {
603         u64 ret;
604         u64 outs[PLPAR_HCALL9_BUFSIZE];
605
606         ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
607                                 adapter_handle.handle, /* r4 */
608                                 qp_handle.handle,      /* r5 */
609                                 port,                  /* r6 */
610                                 0, 0, 0, 0, 0, 0);
611         *pma_qp_nr = (u32)outs[0];
612         *bma_qp_nr = (u32)outs[1];
613
614         if (ret == H_ALIAS_EXIST)
615                 ehca_gen_err("AQP1 already exists. ret=%lx", ret);
616
617         return ret;
618 }
619
620 u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
621                        const struct ipz_qp_handle qp_handle,
622                        struct h_galpa gal,
623                        u16 mcg_dlid,
624                        u64 subnet_prefix, u64 interface_id)
625 {
626         u64 ret;
627
628         ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
629                                       adapter_handle.handle,  /* r4 */
630                                       qp_handle.handle,       /* r5 */
631                                       mcg_dlid,               /* r6 */
632                                       interface_id,           /* r7 */
633                                       subnet_prefix,          /* r8 */
634                                       0, 0);
635
636         if (ret == H_NOT_ENOUGH_RESOURCES)
637                 ehca_gen_err("Not enough resources. ret=%lx", ret);
638
639         return ret;
640 }
641
642 u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
643                        const struct ipz_qp_handle qp_handle,
644                        struct h_galpa gal,
645                        u16 mcg_dlid,
646                        u64 subnet_prefix, u64 interface_id)
647 {
648         return ehca_plpar_hcall_norets(H_DETACH_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
657 u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
658                       struct ehca_cq *cq,
659                       u8 force_flag)
660 {
661         u64 ret;
662
663         ret = hcp_galpas_dtor(&cq->galpas);
664         if (ret) {
665                 ehca_gen_err("Could not destruct cp->galpas");
666                 return H_RESOURCE;
667         }
668
669         ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
670                                       adapter_handle.handle,     /* r4 */
671                                       cq->ipz_cq_handle.handle,  /* r5 */
672                                       force_flag != 0 ? 1L : 0L, /* r6 */
673                                       0, 0, 0, 0);
674
675         if (ret == H_RESOURCE)
676                 ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret);
677
678         return ret;
679 }
680
681 u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
682                       struct ehca_eq *eq)
683 {
684         u64 ret;
685
686         ret = hcp_galpas_dtor(&eq->galpas);
687         if (ret) {
688                 ehca_gen_err("Could not destruct eq->galpas");
689                 return H_RESOURCE;
690         }
691
692         ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
693                                       adapter_handle.handle,     /* r4 */
694                                       eq->ipz_eq_handle.handle,  /* r5 */
695                                       0, 0, 0, 0, 0);
696
697         if (ret == H_RESOURCE)
698                 ehca_gen_err("Resource in use. ret=%lx ", ret);
699
700         return ret;
701 }
702
703 u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
704                              const struct ehca_mr *mr,
705                              const u64 vaddr,
706                              const u64 length,
707                              const u32 access_ctrl,
708                              const struct ipz_pd pd,
709                              struct ehca_mr_hipzout_parms *outparms)
710 {
711         u64 ret;
712         u64 outs[PLPAR_HCALL9_BUFSIZE];
713
714         ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
715                                 adapter_handle.handle,            /* r4 */
716                                 5,                                /* r5 */
717                                 vaddr,                            /* r6 */
718                                 length,                           /* r7 */
719                                 (((u64)access_ctrl) << 32ULL),    /* r8 */
720                                 pd.value,                         /* r9 */
721                                 0, 0, 0);
722         outparms->handle.handle = outs[0];
723         outparms->lkey = (u32)outs[2];
724         outparms->rkey = (u32)outs[3];
725
726         return ret;
727 }
728
729 u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
730                              const struct ehca_mr *mr,
731                              const u8 pagesize,
732                              const u8 queue_type,
733                              const u64 logical_address_of_page,
734                              const u64 count)
735 {
736         u64 ret;
737
738         if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
739                 ehca_gen_err("logical_address_of_page not on a 4k boundary "
740                              "adapter_handle=%lx mr=%p mr_handle=%lx "
741                              "pagesize=%x queue_type=%x "
742                              "logical_address_of_page=%lx count=%lx",
743                              adapter_handle.handle, mr,
744                              mr->ipz_mr_handle.handle, pagesize, queue_type,
745                              logical_address_of_page, count);
746                 ret = H_PARAMETER;
747         } else
748                 ret = hipz_h_register_rpage(adapter_handle, pagesize,
749                                             queue_type,
750                                             mr->ipz_mr_handle.handle,
751                                             logical_address_of_page, count);
752         return ret;
753 }
754
755 u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
756                     const struct ehca_mr *mr,
757                     struct ehca_mr_hipzout_parms *outparms)
758 {
759         u64 ret;
760         u64 outs[PLPAR_HCALL9_BUFSIZE];
761
762         ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
763                                 adapter_handle.handle,     /* r4 */
764                                 mr->ipz_mr_handle.handle,  /* r5 */
765                                 0, 0, 0, 0, 0, 0, 0);
766         outparms->len = outs[0];
767         outparms->vaddr = outs[1];
768         outparms->acl  = outs[4] >> 32;
769         outparms->lkey = (u32)(outs[5] >> 32);
770         outparms->rkey = (u32)(outs[5] & (0xffffffff));
771
772         return ret;
773 }
774
775 u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
776                             const struct ehca_mr *mr)
777 {
778         return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
779                                        adapter_handle.handle,    /* r4 */
780                                        mr->ipz_mr_handle.handle, /* r5 */
781                                        0, 0, 0, 0, 0);
782 }
783
784 u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
785                           const struct ehca_mr *mr,
786                           const u64 vaddr_in,
787                           const u64 length,
788                           const u32 access_ctrl,
789                           const struct ipz_pd pd,
790                           const u64 mr_addr_cb,
791                           struct ehca_mr_hipzout_parms *outparms)
792 {
793         u64 ret;
794         u64 outs[PLPAR_HCALL9_BUFSIZE];
795
796         ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
797                                 adapter_handle.handle,    /* r4 */
798                                 mr->ipz_mr_handle.handle, /* r5 */
799                                 vaddr_in,                 /* r6 */
800                                 length,                   /* r7 */
801                                 /* r8 */
802                                 ((((u64)access_ctrl) << 32ULL) | pd.value),
803                                 mr_addr_cb,               /* r9 */
804                                 0, 0, 0);
805         outparms->vaddr = outs[1];
806         outparms->lkey = (u32)outs[2];
807         outparms->rkey = (u32)outs[3];
808
809         return ret;
810 }
811
812 u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
813                         const struct ehca_mr *mr,
814                         const struct ehca_mr *orig_mr,
815                         const u64 vaddr_in,
816                         const u32 access_ctrl,
817                         const struct ipz_pd pd,
818                         struct ehca_mr_hipzout_parms *outparms)
819 {
820         u64 ret;
821         u64 outs[PLPAR_HCALL9_BUFSIZE];
822
823         ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
824                                 adapter_handle.handle,            /* r4 */
825                                 orig_mr->ipz_mr_handle.handle,    /* r5 */
826                                 vaddr_in,                         /* r6 */
827                                 (((u64)access_ctrl) << 32ULL),    /* r7 */
828                                 pd.value,                         /* r8 */
829                                 0, 0, 0, 0);
830         outparms->handle.handle = outs[0];
831         outparms->lkey = (u32)outs[2];
832         outparms->rkey = (u32)outs[3];
833
834         return ret;
835 }
836
837 u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
838                              const struct ehca_mw *mw,
839                              const struct ipz_pd pd,
840                              struct ehca_mw_hipzout_parms *outparms)
841 {
842         u64 ret;
843         u64 outs[PLPAR_HCALL9_BUFSIZE];
844
845         ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
846                                 adapter_handle.handle,      /* r4 */
847                                 6,                          /* r5 */
848                                 pd.value,                   /* r6 */
849                                 0, 0, 0, 0, 0, 0);
850         outparms->handle.handle = outs[0];
851         outparms->rkey = (u32)outs[3];
852
853         return ret;
854 }
855
856 u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
857                     const struct ehca_mw *mw,
858                     struct ehca_mw_hipzout_parms *outparms)
859 {
860         u64 ret;
861         u64 outs[PLPAR_HCALL9_BUFSIZE];
862
863         ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
864                                 adapter_handle.handle,    /* r4 */
865                                 mw->ipz_mw_handle.handle, /* r5 */
866                                 0, 0, 0, 0, 0, 0, 0);
867         outparms->rkey = (u32)outs[3];
868
869         return ret;
870 }
871
872 u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
873                             const struct ehca_mw *mw)
874 {
875         return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
876                                        adapter_handle.handle,    /* r4 */
877                                        mw->ipz_mw_handle.handle, /* r5 */
878                                        0, 0, 0, 0, 0);
879 }
880
881 u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
882                       const u64 ressource_handle,
883                       void *rblock,
884                       unsigned long *byte_count)
885 {
886         u64 r_cb = virt_to_abs(rblock);
887
888         if (r_cb & (EHCA_PAGESIZE-1)) {
889                 ehca_gen_err("rblock not page aligned.");
890                 return H_PARAMETER;
891         }
892
893         return ehca_plpar_hcall_norets(H_ERROR_DATA,
894                                        adapter_handle.handle,
895                                        ressource_handle,
896                                        r_cb,
897                                        0, 0, 0, 0);
898 }