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