1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  linux/drivers/net/ethernet/ibm/ehea/ehea_phyp.c
4  *
5  *  eHEA ethernet device driver for IBM eServer System p
6  *
7  *  (C) Copyright IBM Corp. 2006
8  *
9  *  Authors:
10  *	 Christoph Raisch <raisch@de.ibm.com>
11  *	 Jan-Bernd Themann <themann@de.ibm.com>
12  *	 Thomas Klein <tklein@de.ibm.com>
13  */
14 
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 
17 #include "ehea_phyp.h"
18 
19 
get_order_of_qentries(u16 queue_entries)20 static inline u16 get_order_of_qentries(u16 queue_entries)
21 {
22 	u8 ld = 1;		/*  logarithmus dualis */
23 	while (((1U << ld) - 1) < queue_entries)
24 		ld++;
25 	return ld - 1;
26 }
27 
28 /* Defines for H_CALL H_ALLOC_RESOURCE */
29 #define H_ALL_RES_TYPE_QP	 1
30 #define H_ALL_RES_TYPE_CQ	 2
31 #define H_ALL_RES_TYPE_EQ	 3
32 #define H_ALL_RES_TYPE_MR	 5
33 #define H_ALL_RES_TYPE_MW	 6
34 
ehea_plpar_hcall_norets(unsigned long opcode,unsigned long arg1,unsigned long arg2,unsigned long arg3,unsigned long arg4,unsigned long arg5,unsigned long arg6,unsigned long arg7)35 static long ehea_plpar_hcall_norets(unsigned long opcode,
36 				    unsigned long arg1,
37 				    unsigned long arg2,
38 				    unsigned long arg3,
39 				    unsigned long arg4,
40 				    unsigned long arg5,
41 				    unsigned long arg6,
42 				    unsigned long arg7)
43 {
44 	long ret;
45 	int i, sleep_msecs;
46 
47 	for (i = 0; i < 5; i++) {
48 		ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
49 					 arg5, arg6, arg7);
50 
51 		if (H_IS_LONG_BUSY(ret)) {
52 			sleep_msecs = get_longbusy_msecs(ret);
53 			msleep_interruptible(sleep_msecs);
54 			continue;
55 		}
56 
57 		if (ret < H_SUCCESS)
58 			pr_err("opcode=%lx ret=%lx"
59 			       " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
60 			       " arg5=%lx arg6=%lx arg7=%lx\n",
61 			       opcode, ret,
62 			       arg1, arg2, arg3, arg4, arg5, arg6, arg7);
63 
64 		return ret;
65 	}
66 
67 	return H_BUSY;
68 }
69 
ehea_plpar_hcall9(unsigned long opcode,unsigned long * outs,unsigned long arg1,unsigned long arg2,unsigned long arg3,unsigned long arg4,unsigned long arg5,unsigned long arg6,unsigned long arg7,unsigned long arg8,unsigned long arg9)70 static long ehea_plpar_hcall9(unsigned long opcode,
71 			      unsigned long *outs, /* array of 9 outputs */
72 			      unsigned long arg1,
73 			      unsigned long arg2,
74 			      unsigned long arg3,
75 			      unsigned long arg4,
76 			      unsigned long arg5,
77 			      unsigned long arg6,
78 			      unsigned long arg7,
79 			      unsigned long arg8,
80 			      unsigned long arg9)
81 {
82 	long ret;
83 	int i, sleep_msecs;
84 	u8 cb_cat;
85 
86 	for (i = 0; i < 5; i++) {
87 		ret = plpar_hcall9(opcode, outs,
88 				   arg1, arg2, arg3, arg4, arg5,
89 				   arg6, arg7, arg8, arg9);
90 
91 		if (H_IS_LONG_BUSY(ret)) {
92 			sleep_msecs = get_longbusy_msecs(ret);
93 			msleep_interruptible(sleep_msecs);
94 			continue;
95 		}
96 
97 		cb_cat = EHEA_BMASK_GET(H_MEHEAPORT_CAT, arg2);
98 
99 		if ((ret < H_SUCCESS) && !(((ret == H_AUTHORITY)
100 		    && (opcode == H_MODIFY_HEA_PORT))
101 		    && (((cb_cat == H_PORT_CB4) && ((arg3 == H_PORT_CB4_JUMBO)
102 		    || (arg3 == H_PORT_CB4_SPEED))) || ((cb_cat == H_PORT_CB7)
103 		    && (arg3 == H_PORT_CB7_DUCQPN)))))
104 			pr_err("opcode=%lx ret=%lx"
105 			       " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
106 			       " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
107 			       " arg9=%lx"
108 			       " out1=%lx out2=%lx out3=%lx out4=%lx"
109 			       " out5=%lx out6=%lx out7=%lx out8=%lx"
110 			       " out9=%lx\n",
111 			       opcode, ret,
112 			       arg1, arg2, arg3, arg4, arg5,
113 			       arg6, arg7, arg8, arg9,
114 			       outs[0], outs[1], outs[2], outs[3], outs[4],
115 			       outs[5], outs[6], outs[7], outs[8]);
116 		return ret;
117 	}
118 
119 	return H_BUSY;
120 }
121 
ehea_h_query_ehea_qp(const u64 adapter_handle,const u8 qp_category,const u64 qp_handle,const u64 sel_mask,void * cb_addr)122 u64 ehea_h_query_ehea_qp(const u64 adapter_handle, const u8 qp_category,
123 			 const u64 qp_handle, const u64 sel_mask, void *cb_addr)
124 {
125 	return ehea_plpar_hcall_norets(H_QUERY_HEA_QP,
126 				       adapter_handle,		/* R4 */
127 				       qp_category,		/* R5 */
128 				       qp_handle,		/* R6 */
129 				       sel_mask,		/* R7 */
130 				       __pa(cb_addr),		/* R8 */
131 				       0, 0);
132 }
133 
134 /* input param R5 */
135 #define H_ALL_RES_QP_EQPO	  EHEA_BMASK_IBM(9, 11)
136 #define H_ALL_RES_QP_QPP	  EHEA_BMASK_IBM(12, 12)
137 #define H_ALL_RES_QP_RQR	  EHEA_BMASK_IBM(13, 15)
138 #define H_ALL_RES_QP_EQEG	  EHEA_BMASK_IBM(16, 16)
139 #define H_ALL_RES_QP_LL_QP	  EHEA_BMASK_IBM(17, 17)
140 #define H_ALL_RES_QP_DMA128	  EHEA_BMASK_IBM(19, 19)
141 #define H_ALL_RES_QP_HSM	  EHEA_BMASK_IBM(20, 21)
142 #define H_ALL_RES_QP_SIGT	  EHEA_BMASK_IBM(22, 23)
143 #define H_ALL_RES_QP_TENURE	  EHEA_BMASK_IBM(48, 55)
144 #define H_ALL_RES_QP_RES_TYP	  EHEA_BMASK_IBM(56, 63)
145 
146 /* input param R9  */
147 #define H_ALL_RES_QP_TOKEN	  EHEA_BMASK_IBM(0, 31)
148 #define H_ALL_RES_QP_PD		  EHEA_BMASK_IBM(32, 63)
149 
150 /* input param R10 */
151 #define H_ALL_RES_QP_MAX_SWQE	  EHEA_BMASK_IBM(4, 7)
152 #define H_ALL_RES_QP_MAX_R1WQE	  EHEA_BMASK_IBM(12, 15)
153 #define H_ALL_RES_QP_MAX_R2WQE	  EHEA_BMASK_IBM(20, 23)
154 #define H_ALL_RES_QP_MAX_R3WQE	  EHEA_BMASK_IBM(28, 31)
155 /* Max Send Scatter Gather Elements */
156 #define H_ALL_RES_QP_MAX_SSGE	  EHEA_BMASK_IBM(37, 39)
157 #define H_ALL_RES_QP_MAX_R1SGE	  EHEA_BMASK_IBM(45, 47)
158 /* Max Receive SG Elements RQ1 */
159 #define H_ALL_RES_QP_MAX_R2SGE	  EHEA_BMASK_IBM(53, 55)
160 #define H_ALL_RES_QP_MAX_R3SGE	  EHEA_BMASK_IBM(61, 63)
161 
162 /* input param R11 */
163 #define H_ALL_RES_QP_SWQE_IDL	  EHEA_BMASK_IBM(0, 7)
164 /* max swqe immediate data length */
165 #define H_ALL_RES_QP_PORT_NUM	  EHEA_BMASK_IBM(48, 63)
166 
167 /* input param R12 */
168 #define H_ALL_RES_QP_TH_RQ2	  EHEA_BMASK_IBM(0, 15)
169 /* Threshold RQ2 */
170 #define H_ALL_RES_QP_TH_RQ3	  EHEA_BMASK_IBM(16, 31)
171 /* Threshold RQ3 */
172 
173 /* output param R6 */
174 #define H_ALL_RES_QP_ACT_SWQE	  EHEA_BMASK_IBM(0, 15)
175 #define H_ALL_RES_QP_ACT_R1WQE	  EHEA_BMASK_IBM(16, 31)
176 #define H_ALL_RES_QP_ACT_R2WQE	  EHEA_BMASK_IBM(32, 47)
177 #define H_ALL_RES_QP_ACT_R3WQE	  EHEA_BMASK_IBM(48, 63)
178 
179 /* output param, R7 */
180 #define H_ALL_RES_QP_ACT_SSGE	  EHEA_BMASK_IBM(0, 7)
181 #define H_ALL_RES_QP_ACT_R1SGE	  EHEA_BMASK_IBM(8, 15)
182 #define H_ALL_RES_QP_ACT_R2SGE	  EHEA_BMASK_IBM(16, 23)
183 #define H_ALL_RES_QP_ACT_R3SGE	  EHEA_BMASK_IBM(24, 31)
184 #define H_ALL_RES_QP_ACT_SWQE_IDL EHEA_BMASK_IBM(32, 39)
185 
186 /* output param R8,R9 */
187 #define H_ALL_RES_QP_SIZE_SQ	  EHEA_BMASK_IBM(0, 31)
188 #define H_ALL_RES_QP_SIZE_RQ1	  EHEA_BMASK_IBM(32, 63)
189 #define H_ALL_RES_QP_SIZE_RQ2	  EHEA_BMASK_IBM(0, 31)
190 #define H_ALL_RES_QP_SIZE_RQ3	  EHEA_BMASK_IBM(32, 63)
191 
192 /* output param R11,R12 */
193 #define H_ALL_RES_QP_LIOBN_SQ	  EHEA_BMASK_IBM(0, 31)
194 #define H_ALL_RES_QP_LIOBN_RQ1	  EHEA_BMASK_IBM(32, 63)
195 #define H_ALL_RES_QP_LIOBN_RQ2	  EHEA_BMASK_IBM(0, 31)
196 #define H_ALL_RES_QP_LIOBN_RQ3	  EHEA_BMASK_IBM(32, 63)
197 
ehea_h_alloc_resource_qp(const u64 adapter_handle,struct ehea_qp_init_attr * init_attr,const u32 pd,u64 * qp_handle,struct h_epas * h_epas)198 u64 ehea_h_alloc_resource_qp(const u64 adapter_handle,
199 			     struct ehea_qp_init_attr *init_attr, const u32 pd,
200 			     u64 *qp_handle, struct h_epas *h_epas)
201 {
202 	u64 hret;
203 	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
204 
205 	u64 allocate_controls =
206 	    EHEA_BMASK_SET(H_ALL_RES_QP_EQPO, init_attr->low_lat_rq1 ? 1 : 0)
207 	    | EHEA_BMASK_SET(H_ALL_RES_QP_QPP, 0)
208 	    | EHEA_BMASK_SET(H_ALL_RES_QP_RQR, 6)	/* rq1 & rq2 & rq3 */
209 	    | EHEA_BMASK_SET(H_ALL_RES_QP_EQEG, 0)	/* EQE gen. disabled */
210 	    | EHEA_BMASK_SET(H_ALL_RES_QP_LL_QP, init_attr->low_lat_rq1)
211 	    | EHEA_BMASK_SET(H_ALL_RES_QP_DMA128, 0)
212 	    | EHEA_BMASK_SET(H_ALL_RES_QP_HSM, 0)
213 	    | EHEA_BMASK_SET(H_ALL_RES_QP_SIGT, init_attr->signalingtype)
214 	    | EHEA_BMASK_SET(H_ALL_RES_QP_RES_TYP, H_ALL_RES_TYPE_QP);
215 
216 	u64 r9_reg = EHEA_BMASK_SET(H_ALL_RES_QP_PD, pd)
217 	    | EHEA_BMASK_SET(H_ALL_RES_QP_TOKEN, init_attr->qp_token);
218 
219 	u64 max_r10_reg =
220 	    EHEA_BMASK_SET(H_ALL_RES_QP_MAX_SWQE,
221 			   get_order_of_qentries(init_attr->max_nr_send_wqes))
222 	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R1WQE,
223 			     get_order_of_qentries(init_attr->max_nr_rwqes_rq1))
224 	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R2WQE,
225 			     get_order_of_qentries(init_attr->max_nr_rwqes_rq2))
226 	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R3WQE,
227 			     get_order_of_qentries(init_attr->max_nr_rwqes_rq3))
228 	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_SSGE, init_attr->wqe_size_enc_sq)
229 	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R1SGE,
230 			     init_attr->wqe_size_enc_rq1)
231 	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R2SGE,
232 			     init_attr->wqe_size_enc_rq2)
233 	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R3SGE,
234 			     init_attr->wqe_size_enc_rq3);
235 
236 	u64 r11_in =
237 	    EHEA_BMASK_SET(H_ALL_RES_QP_SWQE_IDL, init_attr->swqe_imm_data_len)
238 	    | EHEA_BMASK_SET(H_ALL_RES_QP_PORT_NUM, init_attr->port_nr);
239 	u64 threshold =
240 	    EHEA_BMASK_SET(H_ALL_RES_QP_TH_RQ2, init_attr->rq2_threshold)
241 	    | EHEA_BMASK_SET(H_ALL_RES_QP_TH_RQ3, init_attr->rq3_threshold);
242 
243 	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
244 				 outs,
245 				 adapter_handle,		/* R4 */
246 				 allocate_controls,		/* R5 */
247 				 init_attr->send_cq_handle,	/* R6 */
248 				 init_attr->recv_cq_handle,	/* R7 */
249 				 init_attr->aff_eq_handle,	/* R8 */
250 				 r9_reg,			/* R9 */
251 				 max_r10_reg,			/* R10 */
252 				 r11_in,			/* R11 */
253 				 threshold);			/* R12 */
254 
255 	*qp_handle = outs[0];
256 	init_attr->qp_nr = (u32)outs[1];
257 
258 	init_attr->act_nr_send_wqes =
259 	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_SWQE, outs[2]);
260 	init_attr->act_nr_rwqes_rq1 =
261 	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R1WQE, outs[2]);
262 	init_attr->act_nr_rwqes_rq2 =
263 	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R2WQE, outs[2]);
264 	init_attr->act_nr_rwqes_rq3 =
265 	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R3WQE, outs[2]);
266 
267 	init_attr->act_wqe_size_enc_sq = init_attr->wqe_size_enc_sq;
268 	init_attr->act_wqe_size_enc_rq1 = init_attr->wqe_size_enc_rq1;
269 	init_attr->act_wqe_size_enc_rq2 = init_attr->wqe_size_enc_rq2;
270 	init_attr->act_wqe_size_enc_rq3 = init_attr->wqe_size_enc_rq3;
271 
272 	init_attr->nr_sq_pages =
273 	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_SQ, outs[4]);
274 	init_attr->nr_rq1_pages =
275 	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ1, outs[4]);
276 	init_attr->nr_rq2_pages =
277 	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ2, outs[5]);
278 	init_attr->nr_rq3_pages =
279 	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ3, outs[5]);
280 
281 	init_attr->liobn_sq =
282 	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_SQ, outs[7]);
283 	init_attr->liobn_rq1 =
284 	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ1, outs[7]);
285 	init_attr->liobn_rq2 =
286 	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ2, outs[8]);
287 	init_attr->liobn_rq3 =
288 	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ3, outs[8]);
289 
290 	if (!hret)
291 		hcp_epas_ctor(h_epas, outs[6], outs[6]);
292 
293 	return hret;
294 }
295 
ehea_h_alloc_resource_cq(const u64 adapter_handle,struct ehea_cq_attr * cq_attr,u64 * cq_handle,struct h_epas * epas)296 u64 ehea_h_alloc_resource_cq(const u64 adapter_handle,
297 			     struct ehea_cq_attr *cq_attr,
298 			     u64 *cq_handle, struct h_epas *epas)
299 {
300 	u64 hret;
301 	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
302 
303 	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
304 				 outs,
305 				 adapter_handle,		/* R4 */
306 				 H_ALL_RES_TYPE_CQ,		/* R5 */
307 				 cq_attr->eq_handle,		/* R6 */
308 				 cq_attr->cq_token,		/* R7 */
309 				 cq_attr->max_nr_of_cqes,	/* R8 */
310 				 0, 0, 0, 0);			/* R9-R12 */
311 
312 	*cq_handle = outs[0];
313 	cq_attr->act_nr_of_cqes = outs[3];
314 	cq_attr->nr_pages = outs[4];
315 
316 	if (!hret)
317 		hcp_epas_ctor(epas, outs[5], outs[6]);
318 
319 	return hret;
320 }
321 
322 /* Defines for H_CALL H_ALLOC_RESOURCE */
323 #define H_ALL_RES_TYPE_QP	 1
324 #define H_ALL_RES_TYPE_CQ	 2
325 #define H_ALL_RES_TYPE_EQ	 3
326 #define H_ALL_RES_TYPE_MR	 5
327 #define H_ALL_RES_TYPE_MW	 6
328 
329 /*  input param R5 */
330 #define H_ALL_RES_EQ_NEQ	     EHEA_BMASK_IBM(0, 0)
331 #define H_ALL_RES_EQ_NON_NEQ_ISN     EHEA_BMASK_IBM(6, 7)
332 #define H_ALL_RES_EQ_INH_EQE_GEN     EHEA_BMASK_IBM(16, 16)
333 #define H_ALL_RES_EQ_RES_TYPE	     EHEA_BMASK_IBM(56, 63)
334 /*  input param R6 */
335 #define H_ALL_RES_EQ_MAX_EQE	     EHEA_BMASK_IBM(32, 63)
336 
337 /*  output param R6 */
338 #define H_ALL_RES_EQ_LIOBN	     EHEA_BMASK_IBM(32, 63)
339 
340 /*  output param R7 */
341 #define H_ALL_RES_EQ_ACT_EQE	     EHEA_BMASK_IBM(32, 63)
342 
343 /*  output param R8 */
344 #define H_ALL_RES_EQ_ACT_PS	     EHEA_BMASK_IBM(32, 63)
345 
346 /*  output param R9 */
347 #define H_ALL_RES_EQ_ACT_EQ_IST_C    EHEA_BMASK_IBM(30, 31)
348 #define H_ALL_RES_EQ_ACT_EQ_IST_1    EHEA_BMASK_IBM(40, 63)
349 
350 /*  output param R10 */
351 #define H_ALL_RES_EQ_ACT_EQ_IST_2    EHEA_BMASK_IBM(40, 63)
352 
353 /*  output param R11 */
354 #define H_ALL_RES_EQ_ACT_EQ_IST_3    EHEA_BMASK_IBM(40, 63)
355 
356 /*  output param R12 */
357 #define H_ALL_RES_EQ_ACT_EQ_IST_4    EHEA_BMASK_IBM(40, 63)
358 
ehea_h_alloc_resource_eq(const u64 adapter_handle,struct ehea_eq_attr * eq_attr,u64 * eq_handle)359 u64 ehea_h_alloc_resource_eq(const u64 adapter_handle,
360 			     struct ehea_eq_attr *eq_attr, u64 *eq_handle)
361 {
362 	u64 hret, allocate_controls;
363 	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
364 
365 	/* resource type */
366 	allocate_controls =
367 	    EHEA_BMASK_SET(H_ALL_RES_EQ_RES_TYPE, H_ALL_RES_TYPE_EQ)
368 	    | EHEA_BMASK_SET(H_ALL_RES_EQ_NEQ, eq_attr->type ? 1 : 0)
369 	    | EHEA_BMASK_SET(H_ALL_RES_EQ_INH_EQE_GEN, !eq_attr->eqe_gen)
370 	    | EHEA_BMASK_SET(H_ALL_RES_EQ_NON_NEQ_ISN, 1);
371 
372 	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
373 				 outs,
374 				 adapter_handle,		/* R4 */
375 				 allocate_controls,		/* R5 */
376 				 eq_attr->max_nr_of_eqes,	/* R6 */
377 				 0, 0, 0, 0, 0, 0);		/* R7-R10 */
378 
379 	*eq_handle = outs[0];
380 	eq_attr->act_nr_of_eqes = outs[3];
381 	eq_attr->nr_pages = outs[4];
382 	eq_attr->ist1 = outs[5];
383 	eq_attr->ist2 = outs[6];
384 	eq_attr->ist3 = outs[7];
385 	eq_attr->ist4 = outs[8];
386 
387 	return hret;
388 }
389 
ehea_h_modify_ehea_qp(const u64 adapter_handle,const u8 cat,const u64 qp_handle,const u64 sel_mask,void * cb_addr,u64 * inv_attr_id,u64 * proc_mask,u16 * out_swr,u16 * out_rwr)390 u64 ehea_h_modify_ehea_qp(const u64 adapter_handle, const u8 cat,
391 			  const u64 qp_handle, const u64 sel_mask,
392 			  void *cb_addr, u64 *inv_attr_id, u64 *proc_mask,
393 			  u16 *out_swr, u16 *out_rwr)
394 {
395 	u64 hret;
396 	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
397 
398 	hret = ehea_plpar_hcall9(H_MODIFY_HEA_QP,
399 				 outs,
400 				 adapter_handle,		/* R4 */
401 				 (u64) cat,			/* R5 */
402 				 qp_handle,			/* R6 */
403 				 sel_mask,			/* R7 */
404 				 __pa(cb_addr),			/* R8 */
405 				 0, 0, 0, 0);			/* R9-R12 */
406 
407 	*inv_attr_id = outs[0];
408 	*out_swr = outs[3];
409 	*out_rwr = outs[4];
410 	*proc_mask = outs[5];
411 
412 	return hret;
413 }
414 
ehea_h_register_rpage(const u64 adapter_handle,const u8 pagesize,const u8 queue_type,const u64 resource_handle,const u64 log_pageaddr,u64 count)415 u64 ehea_h_register_rpage(const u64 adapter_handle, const u8 pagesize,
416 			  const u8 queue_type, const u64 resource_handle,
417 			  const u64 log_pageaddr, u64 count)
418 {
419 	u64  reg_control;
420 
421 	reg_control = EHEA_BMASK_SET(H_REG_RPAGE_PAGE_SIZE, pagesize)
422 		    | EHEA_BMASK_SET(H_REG_RPAGE_QT, queue_type);
423 
424 	return ehea_plpar_hcall_norets(H_REGISTER_HEA_RPAGES,
425 				       adapter_handle,		/* R4 */
426 				       reg_control,		/* R5 */
427 				       resource_handle,		/* R6 */
428 				       log_pageaddr,		/* R7 */
429 				       count,			/* R8 */
430 				       0, 0);			/* R9-R10 */
431 }
432 
ehea_h_register_smr(const u64 adapter_handle,const u64 orig_mr_handle,const u64 vaddr_in,const u32 access_ctrl,const u32 pd,struct ehea_mr * mr)433 u64 ehea_h_register_smr(const u64 adapter_handle, const u64 orig_mr_handle,
434 			const u64 vaddr_in, const u32 access_ctrl, const u32 pd,
435 			struct ehea_mr *mr)
436 {
437 	u64 hret;
438 	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
439 
440 	hret = ehea_plpar_hcall9(H_REGISTER_SMR,
441 				 outs,
442 				 adapter_handle	      ,		 /* R4 */
443 				 orig_mr_handle,		 /* R5 */
444 				 vaddr_in,			 /* R6 */
445 				 (((u64)access_ctrl) << 32ULL),	 /* R7 */
446 				 pd,				 /* R8 */
447 				 0, 0, 0, 0);			 /* R9-R12 */
448 
449 	mr->handle = outs[0];
450 	mr->lkey = (u32)outs[2];
451 
452 	return hret;
453 }
454 
ehea_h_disable_and_get_hea(const u64 adapter_handle,const u64 qp_handle)455 u64 ehea_h_disable_and_get_hea(const u64 adapter_handle, const u64 qp_handle)
456 {
457 	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
458 
459 	return ehea_plpar_hcall9(H_DISABLE_AND_GET_HEA,
460 				 outs,
461 				 adapter_handle,		/* R4 */
462 				 H_DISABLE_GET_EHEA_WQE_P,	/* R5 */
463 				 qp_handle,			/* R6 */
464 				 0, 0, 0, 0, 0, 0);		/* R7-R12 */
465 }
466 
ehea_h_free_resource(const u64 adapter_handle,const u64 res_handle,u64 force_bit)467 u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle,
468 			 u64 force_bit)
469 {
470 	return ehea_plpar_hcall_norets(H_FREE_RESOURCE,
471 				       adapter_handle,	   /* R4 */
472 				       res_handle,	   /* R5 */
473 				       force_bit,
474 				       0, 0, 0, 0);	   /* R7-R10 */
475 }
476 
ehea_h_alloc_resource_mr(const u64 adapter_handle,const u64 vaddr,const u64 length,const u32 access_ctrl,const u32 pd,u64 * mr_handle,u32 * lkey)477 u64 ehea_h_alloc_resource_mr(const u64 adapter_handle, const u64 vaddr,
478 			     const u64 length, const u32 access_ctrl,
479 			     const u32 pd, u64 *mr_handle, u32 *lkey)
480 {
481 	u64 hret;
482 	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
483 
484 	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
485 				 outs,
486 				 adapter_handle,		   /* R4 */
487 				 5,				   /* R5 */
488 				 vaddr,				   /* R6 */
489 				 length,			   /* R7 */
490 				 (((u64) access_ctrl) << 32ULL),   /* R8 */
491 				 pd,				   /* R9 */
492 				 0, 0, 0);			   /* R10-R12 */
493 
494 	*mr_handle = outs[0];
495 	*lkey = (u32)outs[2];
496 	return hret;
497 }
498 
ehea_h_register_rpage_mr(const u64 adapter_handle,const u64 mr_handle,const u8 pagesize,const u8 queue_type,const u64 log_pageaddr,const u64 count)499 u64 ehea_h_register_rpage_mr(const u64 adapter_handle, const u64 mr_handle,
500 			     const u8 pagesize, const u8 queue_type,
501 			     const u64 log_pageaddr, const u64 count)
502 {
503 	if ((count > 1) && (log_pageaddr & ~PAGE_MASK)) {
504 		pr_err("not on pageboundary\n");
505 		return H_PARAMETER;
506 	}
507 
508 	return ehea_h_register_rpage(adapter_handle, pagesize,
509 				     queue_type, mr_handle,
510 				     log_pageaddr, count);
511 }
512 
ehea_h_query_ehea(const u64 adapter_handle,void * cb_addr)513 u64 ehea_h_query_ehea(const u64 adapter_handle, void *cb_addr)
514 {
515 	u64 hret, cb_logaddr;
516 
517 	cb_logaddr = __pa(cb_addr);
518 
519 	hret = ehea_plpar_hcall_norets(H_QUERY_HEA,
520 				       adapter_handle,		/* R4 */
521 				       cb_logaddr,		/* R5 */
522 				       0, 0, 0, 0, 0);		/* R6-R10 */
523 #ifdef DEBUG
524 	ehea_dump(cb_addr, sizeof(struct hcp_query_ehea), "hcp_query_ehea");
525 #endif
526 	return hret;
527 }
528 
ehea_h_query_ehea_port(const u64 adapter_handle,const u16 port_num,const u8 cb_cat,const u64 select_mask,void * cb_addr)529 u64 ehea_h_query_ehea_port(const u64 adapter_handle, const u16 port_num,
530 			   const u8 cb_cat, const u64 select_mask,
531 			   void *cb_addr)
532 {
533 	u64 port_info;
534 	u64 cb_logaddr = __pa(cb_addr);
535 	u64 arr_index = 0;
536 
537 	port_info = EHEA_BMASK_SET(H_MEHEAPORT_CAT, cb_cat)
538 		  | EHEA_BMASK_SET(H_MEHEAPORT_PN, port_num);
539 
540 	return ehea_plpar_hcall_norets(H_QUERY_HEA_PORT,
541 				       adapter_handle,		/* R4 */
542 				       port_info,		/* R5 */
543 				       select_mask,		/* R6 */
544 				       arr_index,		/* R7 */
545 				       cb_logaddr,		/* R8 */
546 				       0, 0);			/* R9-R10 */
547 }
548 
ehea_h_modify_ehea_port(const u64 adapter_handle,const u16 port_num,const u8 cb_cat,const u64 select_mask,void * cb_addr)549 u64 ehea_h_modify_ehea_port(const u64 adapter_handle, const u16 port_num,
550 			    const u8 cb_cat, const u64 select_mask,
551 			    void *cb_addr)
552 {
553 	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
554 	u64 port_info;
555 	u64 arr_index = 0;
556 	u64 cb_logaddr = __pa(cb_addr);
557 
558 	port_info = EHEA_BMASK_SET(H_MEHEAPORT_CAT, cb_cat)
559 		  | EHEA_BMASK_SET(H_MEHEAPORT_PN, port_num);
560 #ifdef DEBUG
561 	ehea_dump(cb_addr, sizeof(struct hcp_ehea_port_cb0), "Before HCALL");
562 #endif
563 	return ehea_plpar_hcall9(H_MODIFY_HEA_PORT,
564 				 outs,
565 				 adapter_handle,		/* R4 */
566 				 port_info,			/* R5 */
567 				 select_mask,			/* R6 */
568 				 arr_index,			/* R7 */
569 				 cb_logaddr,			/* R8 */
570 				 0, 0, 0, 0);			/* R9-R12 */
571 }
572 
ehea_h_reg_dereg_bcmc(const u64 adapter_handle,const u16 port_num,const u8 reg_type,const u64 mc_mac_addr,const u16 vlan_id,const u32 hcall_id)573 u64 ehea_h_reg_dereg_bcmc(const u64 adapter_handle, const u16 port_num,
574 			  const u8 reg_type, const u64 mc_mac_addr,
575 			  const u16 vlan_id, const u32 hcall_id)
576 {
577 	u64 r5_port_num, r6_reg_type, r7_mc_mac_addr, r8_vlan_id;
578 	u64 mac_addr = mc_mac_addr >> 16;
579 
580 	r5_port_num = EHEA_BMASK_SET(H_REGBCMC_PN, port_num);
581 	r6_reg_type = EHEA_BMASK_SET(H_REGBCMC_REGTYPE, reg_type);
582 	r7_mc_mac_addr = EHEA_BMASK_SET(H_REGBCMC_MACADDR, mac_addr);
583 	r8_vlan_id = EHEA_BMASK_SET(H_REGBCMC_VLANID, vlan_id);
584 
585 	return ehea_plpar_hcall_norets(hcall_id,
586 				       adapter_handle,		/* R4 */
587 				       r5_port_num,		/* R5 */
588 				       r6_reg_type,		/* R6 */
589 				       r7_mc_mac_addr,		/* R7 */
590 				       r8_vlan_id,		/* R8 */
591 				       0, 0);			/* R9-R12 */
592 }
593 
ehea_h_reset_events(const u64 adapter_handle,const u64 neq_handle,const u64 event_mask)594 u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
595 			const u64 event_mask)
596 {
597 	return ehea_plpar_hcall_norets(H_RESET_EVENTS,
598 				       adapter_handle,		/* R4 */
599 				       neq_handle,		/* R5 */
600 				       event_mask,		/* R6 */
601 				       0, 0, 0, 0);		/* R7-R12 */
602 }
603 
ehea_h_error_data(const u64 adapter_handle,const u64 ressource_handle,void * rblock)604 u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
605 		      void *rblock)
606 {
607 	return ehea_plpar_hcall_norets(H_ERROR_DATA,
608 				       adapter_handle,		/* R4 */
609 				       ressource_handle,	/* R5 */
610 				       __pa(rblock),		/* R6 */
611 				       0, 0, 0, 0);		/* R7-R12 */
612 }
613