xref: /dpdk/drivers/common/sfc_efx/base/ef10_proxy.c (revision 672386c1e9e1f64f7aa3b1360ad22dc737ea8d72)
15e111ed8SAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
25e111ed8SAndrew Rybchenko  *
3*672386c1SAndrew Rybchenko  * Copyright(c) 2019-2021 Xilinx, Inc.
45e111ed8SAndrew Rybchenko  * Copyright(c) 2018-2019 Solarflare Communications Inc.
55e111ed8SAndrew Rybchenko  */
65e111ed8SAndrew Rybchenko 
75e111ed8SAndrew Rybchenko #include "efx.h"
85e111ed8SAndrew Rybchenko #include "efx_impl.h"
95e111ed8SAndrew Rybchenko 
105e111ed8SAndrew Rybchenko #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER
115e111ed8SAndrew Rybchenko 
125e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_proxy_auth_init(__in efx_nic_t * enp)135e111ed8SAndrew Rybchenko ef10_proxy_auth_init(
145e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
155e111ed8SAndrew Rybchenko {
165e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
175e111ed8SAndrew Rybchenko 
185e111ed8SAndrew Rybchenko 	return (0);
195e111ed8SAndrew Rybchenko }
205e111ed8SAndrew Rybchenko 
215e111ed8SAndrew Rybchenko 			void
ef10_proxy_auth_fini(__in efx_nic_t * enp)225e111ed8SAndrew Rybchenko ef10_proxy_auth_fini(
235e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
245e111ed8SAndrew Rybchenko {
255e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
265e111ed8SAndrew Rybchenko }
275e111ed8SAndrew Rybchenko 
285e111ed8SAndrew Rybchenko 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)295e111ed8SAndrew Rybchenko efx_mcdi_proxy_configure(
305e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
315e111ed8SAndrew Rybchenko 	__in		boolean_t disable_proxy,
325e111ed8SAndrew Rybchenko 	__in		uint64_t req_buffer_addr,
335e111ed8SAndrew Rybchenko 	__in		uint64_t resp_buffer_addr,
345e111ed8SAndrew Rybchenko 	__in		uint64_t stat_buffer_addr,
355e111ed8SAndrew Rybchenko 	__in		size_t req_size,
365e111ed8SAndrew Rybchenko 	__in		size_t resp_size,
375e111ed8SAndrew Rybchenko 	__in		uint32_t block_cnt,
385e111ed8SAndrew Rybchenko 	__in		uint8_t *op_maskp,
395e111ed8SAndrew Rybchenko 	__in		size_t op_mask_size)
405e111ed8SAndrew Rybchenko {
415e111ed8SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PROXY_CONFIGURE_EXT_IN_LEN,
425e111ed8SAndrew Rybchenko 		MC_CMD_PROXY_CONFIGURE_OUT_LEN);
435e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
445e111ed8SAndrew Rybchenko 	efx_rc_t rc;
455e111ed8SAndrew Rybchenko 
465e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_PROXY_CONFIGURE;
475e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
485e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_PROXY_CONFIGURE_EXT_IN_LEN;
495e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
505e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_PROXY_CONFIGURE_OUT_LEN;
515e111ed8SAndrew Rybchenko 
525e111ed8SAndrew Rybchenko 	if (!disable_proxy) {
535e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_FLAGS, 1);
545e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BUFF_ADDR_LO,
555e111ed8SAndrew Rybchenko 			req_buffer_addr & 0xffffffff);
565e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BUFF_ADDR_HI,
575e111ed8SAndrew Rybchenko 			req_buffer_addr >> 32);
585e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BUFF_ADDR_LO,
595e111ed8SAndrew Rybchenko 			resp_buffer_addr & 0xffffffff);
605e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BUFF_ADDR_HI,
615e111ed8SAndrew Rybchenko 			resp_buffer_addr >> 32);
625e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BUFF_ADDR_LO,
635e111ed8SAndrew Rybchenko 			stat_buffer_addr & 0xffffffff);
645e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BUFF_ADDR_HI,
655e111ed8SAndrew Rybchenko 			stat_buffer_addr >> 32);
665e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BLOCK_SIZE,
675e111ed8SAndrew Rybchenko 			req_size);
685e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BLOCK_SIZE,
695e111ed8SAndrew Rybchenko 			resp_size);
705e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BLOCK_SIZE,
715e111ed8SAndrew Rybchenko 			MC_PROXY_STATUS_BUFFER_LEN);
725e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_NUM_BLOCKS,
735e111ed8SAndrew Rybchenko 			block_cnt);
745e111ed8SAndrew Rybchenko 		memcpy(MCDI_IN2(req, efx_byte_t,
755e111ed8SAndrew Rybchenko 				PROXY_CONFIGURE_IN_ALLOWED_MCDI_MASK),
765e111ed8SAndrew Rybchenko 			op_maskp, op_mask_size);
775e111ed8SAndrew Rybchenko 		MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_EXT_IN_RESERVED,
785e111ed8SAndrew Rybchenko 			EFX_PROXY_CONFIGURE_MAGIC);
795e111ed8SAndrew Rybchenko 	}
805e111ed8SAndrew Rybchenko 
815e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
825e111ed8SAndrew Rybchenko 
835e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
845e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
855e111ed8SAndrew Rybchenko 		goto fail1;
865e111ed8SAndrew Rybchenko 	}
875e111ed8SAndrew Rybchenko 
885e111ed8SAndrew Rybchenko 	return (0);
895e111ed8SAndrew Rybchenko 
905e111ed8SAndrew Rybchenko fail1:
915e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
925e111ed8SAndrew Rybchenko 	return (rc);
935e111ed8SAndrew Rybchenko }
945e111ed8SAndrew Rybchenko 
955e111ed8SAndrew Rybchenko 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)965e111ed8SAndrew Rybchenko efx_mcdi_privilege_modify(
975e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
985e111ed8SAndrew Rybchenko 	__in		uint32_t fn_group,
995e111ed8SAndrew Rybchenko 	__in		uint32_t pf_index,
1005e111ed8SAndrew Rybchenko 	__in		uint32_t vf_index,
1015e111ed8SAndrew Rybchenko 	__in		uint32_t add_privileges_mask,
1025e111ed8SAndrew Rybchenko 	__in		uint32_t remove_privileges_mask)
1035e111ed8SAndrew Rybchenko {
1045e111ed8SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PRIVILEGE_MODIFY_IN_LEN,
1055e111ed8SAndrew Rybchenko 		MC_CMD_PRIVILEGE_MODIFY_OUT_LEN);
1065e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
1075e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1085e111ed8SAndrew Rybchenko 
1095e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_PRIVILEGE_MODIFY;
1105e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
1115e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_PRIVILEGE_MODIFY_IN_LEN;
1125e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
1135e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_PRIVILEGE_MODIFY_OUT_LEN;
1145e111ed8SAndrew Rybchenko 
1155e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(fn_group <= MC_CMD_PRIVILEGE_MODIFY_IN_ONE);
1165e111ed8SAndrew Rybchenko 
1175e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_FN_GROUP, fn_group);
1185e111ed8SAndrew Rybchenko 
1195e111ed8SAndrew Rybchenko 	if ((fn_group == MC_CMD_PRIVILEGE_MODIFY_IN_ONE) ||
1205e111ed8SAndrew Rybchenko 	    (fn_group == MC_CMD_PRIVILEGE_MODIFY_IN_VFS_OF_PF)) {
1215e111ed8SAndrew Rybchenko 		MCDI_IN_POPULATE_DWORD_2(req,
1225e111ed8SAndrew Rybchenko 		    PRIVILEGE_MODIFY_IN_FUNCTION,
1235e111ed8SAndrew Rybchenko 		    PRIVILEGE_MODIFY_IN_FUNCTION_PF, pf_index,
1245e111ed8SAndrew Rybchenko 		    PRIVILEGE_MODIFY_IN_FUNCTION_VF, vf_index);
1255e111ed8SAndrew Rybchenko 	}
1265e111ed8SAndrew Rybchenko 
1275e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_ADD_MASK,
1285e111ed8SAndrew Rybchenko 		add_privileges_mask);
1295e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_REMOVE_MASK,
1305e111ed8SAndrew Rybchenko 		remove_privileges_mask);
1315e111ed8SAndrew Rybchenko 
1325e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
1335e111ed8SAndrew Rybchenko 
1345e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
1355e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
1365e111ed8SAndrew Rybchenko 		goto fail1;
1375e111ed8SAndrew Rybchenko 	}
1385e111ed8SAndrew Rybchenko 
1395e111ed8SAndrew Rybchenko 	return (0);
1405e111ed8SAndrew Rybchenko 
1415e111ed8SAndrew Rybchenko fail1:
1425e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1435e111ed8SAndrew Rybchenko 	return (rc);
1445e111ed8SAndrew Rybchenko }
1455e111ed8SAndrew Rybchenko 
1465e111ed8SAndrew Rybchenko 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)1475e111ed8SAndrew Rybchenko efx_proxy_auth_fill_op_mask(
1485e111ed8SAndrew Rybchenko 	__in_ecount(op_count)		uint32_t *op_listp,
1495e111ed8SAndrew Rybchenko 	__in				size_t op_count,
1505e111ed8SAndrew Rybchenko 	__out_ecount(op_mask_size)	uint32_t *op_maskp,
1515e111ed8SAndrew Rybchenko 	__in				size_t op_mask_size)
1525e111ed8SAndrew Rybchenko {
1535e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1545e111ed8SAndrew Rybchenko 	uint32_t op;
1555e111ed8SAndrew Rybchenko 
1565e111ed8SAndrew Rybchenko 	if ((op_listp == NULL) || (op_maskp == NULL)) {
1575e111ed8SAndrew Rybchenko 		rc = EINVAL;
1585e111ed8SAndrew Rybchenko 		goto fail1;
1595e111ed8SAndrew Rybchenko 	}
1605e111ed8SAndrew Rybchenko 
1615e111ed8SAndrew Rybchenko 	while (op_count--) {
1625e111ed8SAndrew Rybchenko 		op = *op_listp++;
1635e111ed8SAndrew Rybchenko 		if (op > op_mask_size * 32) {
1645e111ed8SAndrew Rybchenko 			rc = EINVAL;
1655e111ed8SAndrew Rybchenko 			goto fail2;
1665e111ed8SAndrew Rybchenko 		}
1675e111ed8SAndrew Rybchenko 		op_maskp[op / 32] |= 1u << (op & 31);
1685e111ed8SAndrew Rybchenko 	}
1695e111ed8SAndrew Rybchenko 
1705e111ed8SAndrew Rybchenko 	return (0);
1715e111ed8SAndrew Rybchenko 
1725e111ed8SAndrew Rybchenko fail2:
1735e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
1745e111ed8SAndrew Rybchenko fail1:
1755e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1765e111ed8SAndrew Rybchenko 	return (rc);
1775e111ed8SAndrew Rybchenko }
1785e111ed8SAndrew Rybchenko 
1795e111ed8SAndrew Rybchenko 	__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)1805e111ed8SAndrew Rybchenko ef10_proxy_auth_mc_config(
1815e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
1825e111ed8SAndrew Rybchenko 	__in_ecount(block_cnt)	efsys_mem_t *request_bufferp,
1835e111ed8SAndrew Rybchenko 	__in_ecount(block_cnt)	efsys_mem_t *response_bufferp,
1845e111ed8SAndrew Rybchenko 	__in_ecount(block_cnt)	efsys_mem_t *status_bufferp,
1855e111ed8SAndrew Rybchenko 	__in			uint32_t block_cnt,
1865e111ed8SAndrew Rybchenko 	__in_ecount(op_count)	uint32_t *op_listp,
1875e111ed8SAndrew Rybchenko 	__in			size_t op_count)
1885e111ed8SAndrew Rybchenko {
1895e111ed8SAndrew Rybchenko #define	PROXY_OPS_MASK_SIZE						\
1905e111ed8SAndrew Rybchenko 	(EFX_DIV_ROUND_UP(						\
1915e111ed8SAndrew Rybchenko 	    MC_CMD_PROXY_CONFIGURE_IN_ALLOWED_MCDI_MASK_LEN,		\
1925e111ed8SAndrew Rybchenko 	    sizeof (uint32_t)))
1935e111ed8SAndrew Rybchenko 
1945e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1955e111ed8SAndrew Rybchenko 	uint32_t op_mask[PROXY_OPS_MASK_SIZE] = {0};
1965e111ed8SAndrew Rybchenko 
1975e111ed8SAndrew Rybchenko 	/* Prepare the operation mask from operation list array */
1985e111ed8SAndrew Rybchenko 	if ((rc = efx_proxy_auth_fill_op_mask(op_listp, op_count,
1995e111ed8SAndrew Rybchenko 			op_mask, PROXY_OPS_MASK_SIZE) != 0))
2005e111ed8SAndrew Rybchenko 		goto fail1;
2015e111ed8SAndrew Rybchenko 
2025e111ed8SAndrew Rybchenko 	if ((rc = efx_mcdi_proxy_configure(enp, B_FALSE,
2035e111ed8SAndrew Rybchenko 			EFSYS_MEM_ADDR(request_bufferp),
2045e111ed8SAndrew Rybchenko 			EFSYS_MEM_ADDR(response_bufferp),
2055e111ed8SAndrew Rybchenko 			EFSYS_MEM_ADDR(status_bufferp),
2065e111ed8SAndrew Rybchenko 			EFSYS_MEM_SIZE(request_bufferp) / block_cnt,
2075e111ed8SAndrew Rybchenko 			EFSYS_MEM_SIZE(response_bufferp) / block_cnt,
2085e111ed8SAndrew Rybchenko 			block_cnt, (uint8_t *)&op_mask,
2095e111ed8SAndrew Rybchenko 			sizeof (op_mask))) != 0)
2105e111ed8SAndrew Rybchenko 		goto fail2;
2115e111ed8SAndrew Rybchenko 
2125e111ed8SAndrew Rybchenko 	return (0);
2135e111ed8SAndrew Rybchenko 
2145e111ed8SAndrew Rybchenko fail2:
2155e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
2165e111ed8SAndrew Rybchenko 
2175e111ed8SAndrew Rybchenko fail1:
2185e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2195e111ed8SAndrew Rybchenko 	return (rc);
2205e111ed8SAndrew Rybchenko }
2215e111ed8SAndrew Rybchenko 
2225e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_proxy_auth_disable(__in efx_nic_t * enp)2235e111ed8SAndrew Rybchenko ef10_proxy_auth_disable(
2245e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
2255e111ed8SAndrew Rybchenko {
2265e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2275e111ed8SAndrew Rybchenko 
2285e111ed8SAndrew Rybchenko 	if ((rc = efx_mcdi_proxy_configure(enp, B_TRUE,
2295e111ed8SAndrew Rybchenko 			0, 0, 0, 0, 0, 0, NULL, 0) != 0))
2305e111ed8SAndrew Rybchenko 		goto fail1;
2315e111ed8SAndrew Rybchenko 
2325e111ed8SAndrew Rybchenko 	return (0);
2335e111ed8SAndrew Rybchenko 
2345e111ed8SAndrew Rybchenko fail1:
2355e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2365e111ed8SAndrew Rybchenko 	return (rc);
2375e111ed8SAndrew Rybchenko }
2385e111ed8SAndrew Rybchenko 
2395e111ed8SAndrew Rybchenko 	__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)2405e111ed8SAndrew Rybchenko ef10_proxy_auth_privilege_modify(
2415e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
2425e111ed8SAndrew Rybchenko 	__in		uint32_t fn_group,
2435e111ed8SAndrew Rybchenko 	__in		uint32_t pf_index,
2445e111ed8SAndrew Rybchenko 	__in		uint32_t vf_index,
2455e111ed8SAndrew Rybchenko 	__in		uint32_t add_privileges_mask,
2465e111ed8SAndrew Rybchenko 	__in		uint32_t remove_privileges_mask)
2475e111ed8SAndrew Rybchenko {
2485e111ed8SAndrew Rybchenko 	return (efx_mcdi_privilege_modify(enp, fn_group, pf_index, vf_index,
2495e111ed8SAndrew Rybchenko 			add_privileges_mask, remove_privileges_mask));
2505e111ed8SAndrew Rybchenko }
2515e111ed8SAndrew Rybchenko 
2525e111ed8SAndrew Rybchenko 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)2535e111ed8SAndrew Rybchenko efx_mcdi_privilege_mask_set(
2545e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
2555e111ed8SAndrew Rybchenko 	__in		uint32_t vf_index,
2565e111ed8SAndrew Rybchenko 	__in		uint32_t mask,
2575e111ed8SAndrew Rybchenko 	__in		uint32_t value)
2585e111ed8SAndrew Rybchenko {
2595e111ed8SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PRIVILEGE_MASK_IN_LEN,
2605e111ed8SAndrew Rybchenko 		MC_CMD_PRIVILEGE_MASK_OUT_LEN);
2615e111ed8SAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
2625e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
2635e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2645e111ed8SAndrew Rybchenko 	uint32_t old_mask = 0;
2655e111ed8SAndrew Rybchenko 	uint32_t new_mask = 0;
2665e111ed8SAndrew Rybchenko 
2675e111ed8SAndrew Rybchenko 	EFSYS_ASSERT((value & ~mask) == 0);
2685e111ed8SAndrew Rybchenko 
2695e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
2705e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
2715e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
2725e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
2735e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
2745e111ed8SAndrew Rybchenko 
2755e111ed8SAndrew Rybchenko 	/* Get privilege mask */
2765e111ed8SAndrew Rybchenko 	MCDI_IN_POPULATE_DWORD_2(req, PRIVILEGE_MASK_IN_FUNCTION,
2775e111ed8SAndrew Rybchenko 		PRIVILEGE_MASK_IN_FUNCTION_PF, encp->enc_pf,
2785e111ed8SAndrew Rybchenko 		PRIVILEGE_MASK_IN_FUNCTION_VF, vf_index);
2795e111ed8SAndrew Rybchenko 
2805e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
2815e111ed8SAndrew Rybchenko 
2825e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
2835e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
2845e111ed8SAndrew Rybchenko 		goto fail1;
2855e111ed8SAndrew Rybchenko 	}
2865e111ed8SAndrew Rybchenko 
2875e111ed8SAndrew Rybchenko 	if (req.emr_out_length_used != MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
2885e111ed8SAndrew Rybchenko 		rc = EMSGSIZE;
2895e111ed8SAndrew Rybchenko 		goto fail2;
2905e111ed8SAndrew Rybchenko 	}
2915e111ed8SAndrew Rybchenko 
2925e111ed8SAndrew Rybchenko 	old_mask = *MCDI_OUT2(req, uint32_t, PRIVILEGE_MASK_OUT_OLD_MASK);
2935e111ed8SAndrew Rybchenko 	new_mask = old_mask & ~mask;
2945e111ed8SAndrew Rybchenko 	new_mask |= (value & mask);
2955e111ed8SAndrew Rybchenko 
2965e111ed8SAndrew Rybchenko 	if (new_mask == old_mask)
2975e111ed8SAndrew Rybchenko 		return (0);
2985e111ed8SAndrew Rybchenko 
2995e111ed8SAndrew Rybchenko 	new_mask |= MC_CMD_PRIVILEGE_MASK_IN_DO_CHANGE;
3005e111ed8SAndrew Rybchenko 	memset(payload, 0, sizeof (payload));
3015e111ed8SAndrew Rybchenko 
3025e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
3035e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
3045e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
3055e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
3065e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
3075e111ed8SAndrew Rybchenko 
3085e111ed8SAndrew Rybchenko 	/* Set privilege mask */
3095e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, PRIVILEGE_MASK_IN_NEW_MASK, new_mask);
3105e111ed8SAndrew Rybchenko 
3115e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
3125e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
3135e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
3145e111ed8SAndrew Rybchenko 		goto fail3;
3155e111ed8SAndrew Rybchenko 	}
3165e111ed8SAndrew Rybchenko 
3175e111ed8SAndrew Rybchenko 	if (req.emr_out_length_used != MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
3185e111ed8SAndrew Rybchenko 		rc = EMSGSIZE;
3195e111ed8SAndrew Rybchenko 		goto fail4;
3205e111ed8SAndrew Rybchenko 	}
3215e111ed8SAndrew Rybchenko 
3225e111ed8SAndrew Rybchenko 	return (0);
3235e111ed8SAndrew Rybchenko 
3245e111ed8SAndrew Rybchenko fail4:
3255e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail4);
3265e111ed8SAndrew Rybchenko fail3:
3275e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
3285e111ed8SAndrew Rybchenko fail2:
3295e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
3305e111ed8SAndrew Rybchenko fail1:
3315e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3325e111ed8SAndrew Rybchenko 	return (rc);
3335e111ed8SAndrew Rybchenko }
3345e111ed8SAndrew Rybchenko 
3355e111ed8SAndrew Rybchenko 	__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)3365e111ed8SAndrew Rybchenko ef10_proxy_auth_set_privilege_mask(
3375e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
3385e111ed8SAndrew Rybchenko 	__in		uint32_t vf_index,
3395e111ed8SAndrew Rybchenko 	__in		uint32_t mask,
3405e111ed8SAndrew Rybchenko 	__in		uint32_t value)
3415e111ed8SAndrew Rybchenko {
3425e111ed8SAndrew Rybchenko 	return (efx_mcdi_privilege_mask_set(enp, vf_index,
3435e111ed8SAndrew Rybchenko 			mask, value));
3445e111ed8SAndrew Rybchenko }
3455e111ed8SAndrew Rybchenko 
3465e111ed8SAndrew Rybchenko 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)3475e111ed8SAndrew Rybchenko efx_mcdi_proxy_complete(
3485e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
3495e111ed8SAndrew Rybchenko 	__in		uint32_t fn_index,
3505e111ed8SAndrew Rybchenko 	__in		uint32_t proxy_result,
3515e111ed8SAndrew Rybchenko 	__in		uint32_t handle)
3525e111ed8SAndrew Rybchenko {
3535e111ed8SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PROXY_COMPLETE_IN_LEN,
3545e111ed8SAndrew Rybchenko 		MC_CMD_PROXY_COMPLETE_OUT_LEN);
3555e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
3565e111ed8SAndrew Rybchenko 	efx_rc_t rc;
3575e111ed8SAndrew Rybchenko 
3585e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_PROXY_COMPLETE;
3595e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
3605e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_PROXY_COMPLETE_IN_LEN;
3615e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
3625e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_PROXY_COMPLETE_OUT_LEN;
3635e111ed8SAndrew Rybchenko 
3645e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_BLOCK_INDEX, fn_index);
3655e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_STATUS, proxy_result);
3665e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_HANDLE, handle);
3675e111ed8SAndrew Rybchenko 
3685e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
3695e111ed8SAndrew Rybchenko 
3705e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
3715e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
3725e111ed8SAndrew Rybchenko 		goto fail1;
3735e111ed8SAndrew Rybchenko 	}
3745e111ed8SAndrew Rybchenko 
3755e111ed8SAndrew Rybchenko 	return (0);
3765e111ed8SAndrew Rybchenko 
3775e111ed8SAndrew Rybchenko fail1:
3785e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3795e111ed8SAndrew Rybchenko 	return (rc);
3805e111ed8SAndrew Rybchenko }
3815e111ed8SAndrew Rybchenko 
3825e111ed8SAndrew Rybchenko 	__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)3835e111ed8SAndrew Rybchenko ef10_proxy_auth_complete_request(
3845e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
3855e111ed8SAndrew Rybchenko 	__in		uint32_t fn_index,
3865e111ed8SAndrew Rybchenko 	__in		uint32_t proxy_result,
3875e111ed8SAndrew Rybchenko 	__in		uint32_t handle)
3885e111ed8SAndrew Rybchenko {
3895e111ed8SAndrew Rybchenko 	return (efx_mcdi_proxy_complete(enp, fn_index,
3905e111ed8SAndrew Rybchenko 			proxy_result, handle));
3915e111ed8SAndrew Rybchenko }
3925e111ed8SAndrew Rybchenko 
3935e111ed8SAndrew Rybchenko 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)3945e111ed8SAndrew Rybchenko efx_mcdi_proxy_cmd(
3955e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
3965e111ed8SAndrew Rybchenko 	__in				uint32_t pf_index,
3975e111ed8SAndrew Rybchenko 	__in				uint32_t vf_index,
3985e111ed8SAndrew Rybchenko 	__in_bcount(request_size)	uint8_t *request_bufferp,
3995e111ed8SAndrew Rybchenko 	__in				size_t request_size,
4005e111ed8SAndrew Rybchenko 	__out_bcount(response_size)	uint8_t *response_bufferp,
4015e111ed8SAndrew Rybchenko 	__in				size_t response_size,
4025e111ed8SAndrew Rybchenko 	__out_opt			size_t *response_size_actualp)
4035e111ed8SAndrew Rybchenko {
4045e111ed8SAndrew Rybchenko 	efx_dword_t *inbufp;
4055e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
4065e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4075e111ed8SAndrew Rybchenko 
4085e111ed8SAndrew Rybchenko 	if (request_size % sizeof (*inbufp) != 0) {
4095e111ed8SAndrew Rybchenko 		rc = EINVAL;
4105e111ed8SAndrew Rybchenko 		goto fail1;
4115e111ed8SAndrew Rybchenko 	}
4125e111ed8SAndrew Rybchenko 
4135e111ed8SAndrew Rybchenko 	EFSYS_KMEM_ALLOC(enp, (MC_CMD_PROXY_CMD_IN_LEN + request_size), inbufp);
4145e111ed8SAndrew Rybchenko 
4155e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_PROXY_CMD;
4165e111ed8SAndrew Rybchenko 	req.emr_in_buf = (uint8_t *) inbufp;
4175e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_PROXY_CMD_IN_LEN + request_size;
4185e111ed8SAndrew Rybchenko 	req.emr_out_buf = response_bufferp;
4195e111ed8SAndrew Rybchenko 	req.emr_out_length = response_size;
4205e111ed8SAndrew Rybchenko 
4215e111ed8SAndrew Rybchenko 	MCDI_IN_POPULATE_DWORD_2(req, PROXY_CMD_IN_TARGET,
4225e111ed8SAndrew Rybchenko 		 PROXY_CMD_IN_TARGET_PF, pf_index,
4235e111ed8SAndrew Rybchenko 		 PROXY_CMD_IN_TARGET_VF, vf_index);
4245e111ed8SAndrew Rybchenko 
4255e111ed8SAndrew Rybchenko 	/* Proxied command should be located just after PROXY_CMD */
4265e111ed8SAndrew Rybchenko 	memcpy(&inbufp[MC_CMD_PROXY_CMD_IN_LEN / sizeof (*inbufp)],
4275e111ed8SAndrew Rybchenko 		request_bufferp, request_size);
4285e111ed8SAndrew Rybchenko 
4295e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
4305e111ed8SAndrew Rybchenko 
4315e111ed8SAndrew Rybchenko 	EFSYS_KMEM_FREE(enp, (MC_CMD_PROXY_CMD_IN_LEN + request_size), inbufp);
4325e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
4335e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
4345e111ed8SAndrew Rybchenko 		goto fail2;
4355e111ed8SAndrew Rybchenko 	}
4365e111ed8SAndrew Rybchenko 
4375e111ed8SAndrew Rybchenko 	if (response_size_actualp != NULL)
4385e111ed8SAndrew Rybchenko 		*response_size_actualp = req.emr_out_length_used;
4395e111ed8SAndrew Rybchenko 
4405e111ed8SAndrew Rybchenko 	return (0);
4415e111ed8SAndrew Rybchenko 
4425e111ed8SAndrew Rybchenko fail2:
4435e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
4445e111ed8SAndrew Rybchenko fail1:
4455e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4465e111ed8SAndrew Rybchenko 	return (rc);
4475e111ed8SAndrew Rybchenko }
4485e111ed8SAndrew Rybchenko 
4495e111ed8SAndrew Rybchenko 	__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)4505e111ed8SAndrew Rybchenko ef10_proxy_auth_get_privilege_mask(
4515e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
4525e111ed8SAndrew Rybchenko 	__in		uint32_t pf_index,
4535e111ed8SAndrew Rybchenko 	__in		uint32_t vf_index,
4545e111ed8SAndrew Rybchenko 	__out		uint32_t *maskp)
4555e111ed8SAndrew Rybchenko {
4565e111ed8SAndrew Rybchenko 	return (efx_mcdi_privilege_mask(enp, pf_index, vf_index, maskp));
4575e111ed8SAndrew Rybchenko }
4585e111ed8SAndrew Rybchenko 
4595e111ed8SAndrew Rybchenko 
4605e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_proxy_auth_exec_cmd(__in efx_nic_t * enp,__inout efx_proxy_cmd_params_t * paramsp)4615e111ed8SAndrew Rybchenko ef10_proxy_auth_exec_cmd(
4625e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
4635e111ed8SAndrew Rybchenko 	__inout		efx_proxy_cmd_params_t *paramsp)
4645e111ed8SAndrew Rybchenko {
4655e111ed8SAndrew Rybchenko 	return (efx_mcdi_proxy_cmd(enp, paramsp->pf_index, paramsp->vf_index,
4665e111ed8SAndrew Rybchenko 			paramsp->request_bufferp, paramsp->request_size,
4675e111ed8SAndrew Rybchenko 			paramsp->response_bufferp, paramsp->response_size,
4685e111ed8SAndrew Rybchenko 			paramsp->response_size_actualp));
4695e111ed8SAndrew Rybchenko }
4705e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
471