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