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