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