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