xref: /dpdk/drivers/common/sfc_efx/base/ef10_proxy.c (revision 672386c1e9e1f64f7aa3b1360ad22dc737ea8d72)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2021 Xilinx, Inc.
4  * Copyright(c) 2018-2019 Solarflare Communications Inc.
5  */
6 
7 #include "efx.h"
8 #include "efx_impl.h"
9 
10 #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER
11 
12 	__checkReturn	efx_rc_t
ef10_proxy_auth_init(__in efx_nic_t * enp)13 ef10_proxy_auth_init(
14 	__in		efx_nic_t *enp)
15 {
16 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
17 
18 	return (0);
19 }
20 
21 			void
ef10_proxy_auth_fini(__in efx_nic_t * enp)22 ef10_proxy_auth_fini(
23 	__in		efx_nic_t *enp)
24 {
25 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
26 }
27 
28 static	__checkReturn	efx_rc_t
efx_mcdi_proxy_configure(__in efx_nic_t * enp,__in boolean_t disable_proxy,__in uint64_t req_buffer_addr,__in uint64_t resp_buffer_addr,__in uint64_t stat_buffer_addr,__in size_t req_size,__in size_t resp_size,__in uint32_t block_cnt,__in uint8_t * op_maskp,__in size_t op_mask_size)29 efx_mcdi_proxy_configure(
30 	__in		efx_nic_t *enp,
31 	__in		boolean_t disable_proxy,
32 	__in		uint64_t req_buffer_addr,
33 	__in		uint64_t resp_buffer_addr,
34 	__in		uint64_t stat_buffer_addr,
35 	__in		size_t req_size,
36 	__in		size_t resp_size,
37 	__in		uint32_t block_cnt,
38 	__in		uint8_t *op_maskp,
39 	__in		size_t op_mask_size)
40 {
41 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PROXY_CONFIGURE_EXT_IN_LEN,
42 		MC_CMD_PROXY_CONFIGURE_OUT_LEN);
43 	efx_mcdi_req_t req;
44 	efx_rc_t rc;
45 
46 	req.emr_cmd = MC_CMD_PROXY_CONFIGURE;
47 	req.emr_in_buf = payload;
48 	req.emr_in_length = MC_CMD_PROXY_CONFIGURE_EXT_IN_LEN;
49 	req.emr_out_buf = payload;
50 	req.emr_out_length = MC_CMD_PROXY_CONFIGURE_OUT_LEN;
51 
52 	if (!disable_proxy) {
53 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_FLAGS, 1);
54 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BUFF_ADDR_LO,
55 			req_buffer_addr & 0xffffffff);
56 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BUFF_ADDR_HI,
57 			req_buffer_addr >> 32);
58 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BUFF_ADDR_LO,
59 			resp_buffer_addr & 0xffffffff);
60 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BUFF_ADDR_HI,
61 			resp_buffer_addr >> 32);
62 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BUFF_ADDR_LO,
63 			stat_buffer_addr & 0xffffffff);
64 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BUFF_ADDR_HI,
65 			stat_buffer_addr >> 32);
66 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BLOCK_SIZE,
67 			req_size);
68 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BLOCK_SIZE,
69 			resp_size);
70 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BLOCK_SIZE,
71 			MC_PROXY_STATUS_BUFFER_LEN);
72 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_NUM_BLOCKS,
73 			block_cnt);
74 		memcpy(MCDI_IN2(req, efx_byte_t,
75 				PROXY_CONFIGURE_IN_ALLOWED_MCDI_MASK),
76 			op_maskp, op_mask_size);
77 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_EXT_IN_RESERVED,
78 			EFX_PROXY_CONFIGURE_MAGIC);
79 	}
80 
81 	efx_mcdi_execute(enp, &req);
82 
83 	if (req.emr_rc != 0) {
84 		rc = req.emr_rc;
85 		goto fail1;
86 	}
87 
88 	return (0);
89 
90 fail1:
91 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
92 	return (rc);
93 }
94 
95 static	__checkReturn	efx_rc_t
efx_mcdi_privilege_modify(__in efx_nic_t * enp,__in uint32_t fn_group,__in uint32_t pf_index,__in uint32_t vf_index,__in uint32_t add_privileges_mask,__in uint32_t remove_privileges_mask)96 efx_mcdi_privilege_modify(
97 	__in		efx_nic_t *enp,
98 	__in		uint32_t fn_group,
99 	__in		uint32_t pf_index,
100 	__in		uint32_t vf_index,
101 	__in		uint32_t add_privileges_mask,
102 	__in		uint32_t remove_privileges_mask)
103 {
104 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PRIVILEGE_MODIFY_IN_LEN,
105 		MC_CMD_PRIVILEGE_MODIFY_OUT_LEN);
106 	efx_mcdi_req_t req;
107 	efx_rc_t rc;
108 
109 	req.emr_cmd = MC_CMD_PRIVILEGE_MODIFY;
110 	req.emr_in_buf = payload;
111 	req.emr_in_length = MC_CMD_PRIVILEGE_MODIFY_IN_LEN;
112 	req.emr_out_buf = payload;
113 	req.emr_out_length = MC_CMD_PRIVILEGE_MODIFY_OUT_LEN;
114 
115 	EFSYS_ASSERT(fn_group <= MC_CMD_PRIVILEGE_MODIFY_IN_ONE);
116 
117 	MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_FN_GROUP, fn_group);
118 
119 	if ((fn_group == MC_CMD_PRIVILEGE_MODIFY_IN_ONE) ||
120 	    (fn_group == MC_CMD_PRIVILEGE_MODIFY_IN_VFS_OF_PF)) {
121 		MCDI_IN_POPULATE_DWORD_2(req,
122 		    PRIVILEGE_MODIFY_IN_FUNCTION,
123 		    PRIVILEGE_MODIFY_IN_FUNCTION_PF, pf_index,
124 		    PRIVILEGE_MODIFY_IN_FUNCTION_VF, vf_index);
125 	}
126 
127 	MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_ADD_MASK,
128 		add_privileges_mask);
129 	MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_REMOVE_MASK,
130 		remove_privileges_mask);
131 
132 	efx_mcdi_execute(enp, &req);
133 
134 	if (req.emr_rc != 0) {
135 		rc = req.emr_rc;
136 		goto fail1;
137 	}
138 
139 	return (0);
140 
141 fail1:
142 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
143 	return (rc);
144 }
145 
146 static	__checkReturn			efx_rc_t
efx_proxy_auth_fill_op_mask(__in_ecount (op_count)uint32_t * op_listp,__in size_t op_count,__out_ecount (op_mask_size)uint32_t * op_maskp,__in size_t op_mask_size)147 efx_proxy_auth_fill_op_mask(
148 	__in_ecount(op_count)		uint32_t *op_listp,
149 	__in				size_t op_count,
150 	__out_ecount(op_mask_size)	uint32_t *op_maskp,
151 	__in				size_t op_mask_size)
152 {
153 	efx_rc_t rc;
154 	uint32_t op;
155 
156 	if ((op_listp == NULL) || (op_maskp == NULL)) {
157 		rc = EINVAL;
158 		goto fail1;
159 	}
160 
161 	while (op_count--) {
162 		op = *op_listp++;
163 		if (op > op_mask_size * 32) {
164 			rc = EINVAL;
165 			goto fail2;
166 		}
167 		op_maskp[op / 32] |= 1u << (op & 31);
168 	}
169 
170 	return (0);
171 
172 fail2:
173 	EFSYS_PROBE(fail2);
174 fail1:
175 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
176 	return (rc);
177 }
178 
179 	__checkReturn		efx_rc_t
ef10_proxy_auth_mc_config(__in efx_nic_t * enp,__in_ecount (block_cnt)efsys_mem_t * request_bufferp,__in_ecount (block_cnt)efsys_mem_t * response_bufferp,__in_ecount (block_cnt)efsys_mem_t * status_bufferp,__in uint32_t block_cnt,__in_ecount (op_count)uint32_t * op_listp,__in size_t op_count)180 ef10_proxy_auth_mc_config(
181 	__in			efx_nic_t *enp,
182 	__in_ecount(block_cnt)	efsys_mem_t *request_bufferp,
183 	__in_ecount(block_cnt)	efsys_mem_t *response_bufferp,
184 	__in_ecount(block_cnt)	efsys_mem_t *status_bufferp,
185 	__in			uint32_t block_cnt,
186 	__in_ecount(op_count)	uint32_t *op_listp,
187 	__in			size_t op_count)
188 {
189 #define	PROXY_OPS_MASK_SIZE						\
190 	(EFX_DIV_ROUND_UP(						\
191 	    MC_CMD_PROXY_CONFIGURE_IN_ALLOWED_MCDI_MASK_LEN,		\
192 	    sizeof (uint32_t)))
193 
194 	efx_rc_t rc;
195 	uint32_t op_mask[PROXY_OPS_MASK_SIZE] = {0};
196 
197 	/* Prepare the operation mask from operation list array */
198 	if ((rc = efx_proxy_auth_fill_op_mask(op_listp, op_count,
199 			op_mask, PROXY_OPS_MASK_SIZE) != 0))
200 		goto fail1;
201 
202 	if ((rc = efx_mcdi_proxy_configure(enp, B_FALSE,
203 			EFSYS_MEM_ADDR(request_bufferp),
204 			EFSYS_MEM_ADDR(response_bufferp),
205 			EFSYS_MEM_ADDR(status_bufferp),
206 			EFSYS_MEM_SIZE(request_bufferp) / block_cnt,
207 			EFSYS_MEM_SIZE(response_bufferp) / block_cnt,
208 			block_cnt, (uint8_t *)&op_mask,
209 			sizeof (op_mask))) != 0)
210 		goto fail2;
211 
212 	return (0);
213 
214 fail2:
215 	EFSYS_PROBE(fail2);
216 
217 fail1:
218 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
219 	return (rc);
220 }
221 
222 	__checkReturn	efx_rc_t
ef10_proxy_auth_disable(__in efx_nic_t * enp)223 ef10_proxy_auth_disable(
224 	__in		efx_nic_t *enp)
225 {
226 	efx_rc_t rc;
227 
228 	if ((rc = efx_mcdi_proxy_configure(enp, B_TRUE,
229 			0, 0, 0, 0, 0, 0, NULL, 0) != 0))
230 		goto fail1;
231 
232 	return (0);
233 
234 fail1:
235 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
236 	return (rc);
237 }
238 
239 	__checkReturn	efx_rc_t
ef10_proxy_auth_privilege_modify(__in efx_nic_t * enp,__in uint32_t fn_group,__in uint32_t pf_index,__in uint32_t vf_index,__in uint32_t add_privileges_mask,__in uint32_t remove_privileges_mask)240 ef10_proxy_auth_privilege_modify(
241 	__in		efx_nic_t *enp,
242 	__in		uint32_t fn_group,
243 	__in		uint32_t pf_index,
244 	__in		uint32_t vf_index,
245 	__in		uint32_t add_privileges_mask,
246 	__in		uint32_t remove_privileges_mask)
247 {
248 	return (efx_mcdi_privilege_modify(enp, fn_group, pf_index, vf_index,
249 			add_privileges_mask, remove_privileges_mask));
250 }
251 
252 static	__checkReturn	efx_rc_t
efx_mcdi_privilege_mask_set(__in efx_nic_t * enp,__in uint32_t vf_index,__in uint32_t mask,__in uint32_t value)253 efx_mcdi_privilege_mask_set(
254 	__in		efx_nic_t *enp,
255 	__in		uint32_t vf_index,
256 	__in		uint32_t mask,
257 	__in		uint32_t value)
258 {
259 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PRIVILEGE_MASK_IN_LEN,
260 		MC_CMD_PRIVILEGE_MASK_OUT_LEN);
261 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
262 	efx_mcdi_req_t req;
263 	efx_rc_t rc;
264 	uint32_t old_mask = 0;
265 	uint32_t new_mask = 0;
266 
267 	EFSYS_ASSERT((value & ~mask) == 0);
268 
269 	req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
270 	req.emr_in_buf = payload;
271 	req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
272 	req.emr_out_buf = payload;
273 	req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
274 
275 	/* Get privilege mask */
276 	MCDI_IN_POPULATE_DWORD_2(req, PRIVILEGE_MASK_IN_FUNCTION,
277 		PRIVILEGE_MASK_IN_FUNCTION_PF, encp->enc_pf,
278 		PRIVILEGE_MASK_IN_FUNCTION_VF, vf_index);
279 
280 	efx_mcdi_execute(enp, &req);
281 
282 	if (req.emr_rc != 0) {
283 		rc = req.emr_rc;
284 		goto fail1;
285 	}
286 
287 	if (req.emr_out_length_used != MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
288 		rc = EMSGSIZE;
289 		goto fail2;
290 	}
291 
292 	old_mask = *MCDI_OUT2(req, uint32_t, PRIVILEGE_MASK_OUT_OLD_MASK);
293 	new_mask = old_mask & ~mask;
294 	new_mask |= (value & mask);
295 
296 	if (new_mask == old_mask)
297 		return (0);
298 
299 	new_mask |= MC_CMD_PRIVILEGE_MASK_IN_DO_CHANGE;
300 	memset(payload, 0, sizeof (payload));
301 
302 	req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
303 	req.emr_in_buf = payload;
304 	req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
305 	req.emr_out_buf = payload;
306 	req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
307 
308 	/* Set privilege mask */
309 	MCDI_IN_SET_DWORD(req, PRIVILEGE_MASK_IN_NEW_MASK, new_mask);
310 
311 	efx_mcdi_execute(enp, &req);
312 	if (req.emr_rc != 0) {
313 		rc = req.emr_rc;
314 		goto fail3;
315 	}
316 
317 	if (req.emr_out_length_used != MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
318 		rc = EMSGSIZE;
319 		goto fail4;
320 	}
321 
322 	return (0);
323 
324 fail4:
325 	EFSYS_PROBE(fail4);
326 fail3:
327 	EFSYS_PROBE(fail3);
328 fail2:
329 	EFSYS_PROBE(fail2);
330 fail1:
331 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
332 	return (rc);
333 }
334 
335 	__checkReturn	efx_rc_t
ef10_proxy_auth_set_privilege_mask(__in efx_nic_t * enp,__in uint32_t vf_index,__in uint32_t mask,__in uint32_t value)336 ef10_proxy_auth_set_privilege_mask(
337 	__in		efx_nic_t *enp,
338 	__in		uint32_t vf_index,
339 	__in		uint32_t mask,
340 	__in		uint32_t value)
341 {
342 	return (efx_mcdi_privilege_mask_set(enp, vf_index,
343 			mask, value));
344 }
345 
346 static	__checkReturn	efx_rc_t
efx_mcdi_proxy_complete(__in efx_nic_t * enp,__in uint32_t fn_index,__in uint32_t proxy_result,__in uint32_t handle)347 efx_mcdi_proxy_complete(
348 	__in		efx_nic_t *enp,
349 	__in		uint32_t fn_index,
350 	__in		uint32_t proxy_result,
351 	__in		uint32_t handle)
352 {
353 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PROXY_COMPLETE_IN_LEN,
354 		MC_CMD_PROXY_COMPLETE_OUT_LEN);
355 	efx_mcdi_req_t req;
356 	efx_rc_t rc;
357 
358 	req.emr_cmd = MC_CMD_PROXY_COMPLETE;
359 	req.emr_in_buf = payload;
360 	req.emr_in_length = MC_CMD_PROXY_COMPLETE_IN_LEN;
361 	req.emr_out_buf = payload;
362 	req.emr_out_length = MC_CMD_PROXY_COMPLETE_OUT_LEN;
363 
364 	MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_BLOCK_INDEX, fn_index);
365 	MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_STATUS, proxy_result);
366 	MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_HANDLE, handle);
367 
368 	efx_mcdi_execute(enp, &req);
369 
370 	if (req.emr_rc != 0) {
371 		rc = req.emr_rc;
372 		goto fail1;
373 	}
374 
375 	return (0);
376 
377 fail1:
378 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
379 	return (rc);
380 }
381 
382 	__checkReturn	efx_rc_t
ef10_proxy_auth_complete_request(__in efx_nic_t * enp,__in uint32_t fn_index,__in uint32_t proxy_result,__in uint32_t handle)383 ef10_proxy_auth_complete_request(
384 	__in		efx_nic_t *enp,
385 	__in		uint32_t fn_index,
386 	__in		uint32_t proxy_result,
387 	__in		uint32_t handle)
388 {
389 	return (efx_mcdi_proxy_complete(enp, fn_index,
390 			proxy_result, handle));
391 }
392 
393 static	__checkReturn			efx_rc_t
efx_mcdi_proxy_cmd(__in efx_nic_t * enp,__in uint32_t pf_index,__in uint32_t vf_index,__in_bcount (request_size)uint8_t * request_bufferp,__in size_t request_size,__out_bcount (response_size)uint8_t * response_bufferp,__in size_t response_size,__out_opt size_t * response_size_actualp)394 efx_mcdi_proxy_cmd(
395 	__in				efx_nic_t *enp,
396 	__in				uint32_t pf_index,
397 	__in				uint32_t vf_index,
398 	__in_bcount(request_size)	uint8_t *request_bufferp,
399 	__in				size_t request_size,
400 	__out_bcount(response_size)	uint8_t *response_bufferp,
401 	__in				size_t response_size,
402 	__out_opt			size_t *response_size_actualp)
403 {
404 	efx_dword_t *inbufp;
405 	efx_mcdi_req_t req;
406 	efx_rc_t rc;
407 
408 	if (request_size % sizeof (*inbufp) != 0) {
409 		rc = EINVAL;
410 		goto fail1;
411 	}
412 
413 	EFSYS_KMEM_ALLOC(enp, (MC_CMD_PROXY_CMD_IN_LEN + request_size), inbufp);
414 
415 	req.emr_cmd = MC_CMD_PROXY_CMD;
416 	req.emr_in_buf = (uint8_t *) inbufp;
417 	req.emr_in_length = MC_CMD_PROXY_CMD_IN_LEN + request_size;
418 	req.emr_out_buf = response_bufferp;
419 	req.emr_out_length = response_size;
420 
421 	MCDI_IN_POPULATE_DWORD_2(req, PROXY_CMD_IN_TARGET,
422 		 PROXY_CMD_IN_TARGET_PF, pf_index,
423 		 PROXY_CMD_IN_TARGET_VF, vf_index);
424 
425 	/* Proxied command should be located just after PROXY_CMD */
426 	memcpy(&inbufp[MC_CMD_PROXY_CMD_IN_LEN / sizeof (*inbufp)],
427 		request_bufferp, request_size);
428 
429 	efx_mcdi_execute(enp, &req);
430 
431 	EFSYS_KMEM_FREE(enp, (MC_CMD_PROXY_CMD_IN_LEN + request_size), inbufp);
432 	if (req.emr_rc != 0) {
433 		rc = req.emr_rc;
434 		goto fail2;
435 	}
436 
437 	if (response_size_actualp != NULL)
438 		*response_size_actualp = req.emr_out_length_used;
439 
440 	return (0);
441 
442 fail2:
443 	EFSYS_PROBE(fail2);
444 fail1:
445 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
446 	return (rc);
447 }
448 
449 	__checkReturn	efx_rc_t
ef10_proxy_auth_get_privilege_mask(__in efx_nic_t * enp,__in uint32_t pf_index,__in uint32_t vf_index,__out uint32_t * maskp)450 ef10_proxy_auth_get_privilege_mask(
451 	__in		efx_nic_t *enp,
452 	__in		uint32_t pf_index,
453 	__in		uint32_t vf_index,
454 	__out		uint32_t *maskp)
455 {
456 	return (efx_mcdi_privilege_mask(enp, pf_index, vf_index, maskp));
457 }
458 
459 
460 	__checkReturn	efx_rc_t
ef10_proxy_auth_exec_cmd(__in efx_nic_t * enp,__inout efx_proxy_cmd_params_t * paramsp)461 ef10_proxy_auth_exec_cmd(
462 	__in		efx_nic_t *enp,
463 	__inout		efx_proxy_cmd_params_t *paramsp)
464 {
465 	return (efx_mcdi_proxy_cmd(enp, paramsp->pf_index, paramsp->vf_index,
466 			paramsp->request_bufferp, paramsp->request_size,
467 			paramsp->response_bufferp, paramsp->response_size,
468 			paramsp->response_size_actualp));
469 }
470 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
471