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