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