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