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