1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (c) 2018-2019 Solarflare Communications Inc.
10 #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER
12 __checkReturn efx_rc_t
16 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
17 enp->en_family == EFX_FAMILY_MEDFORD ||
18 enp->en_family == EFX_FAMILY_MEDFORD2);
27 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
28 enp->en_family == EFX_FAMILY_MEDFORD ||
29 enp->en_family == EFX_FAMILY_MEDFORD2);
32 static __checkReturn efx_rc_t
33 efx_mcdi_proxy_configure(
35 __in boolean_t disable_proxy,
36 __in uint64_t req_buffer_addr,
37 __in uint64_t resp_buffer_addr,
38 __in uint64_t stat_buffer_addr,
40 __in size_t resp_size,
41 __in uint32_t block_cnt,
42 __in uint8_t *op_maskp,
43 __in size_t op_mask_size)
45 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PROXY_CONFIGURE_EXT_IN_LEN,
46 MC_CMD_PROXY_CONFIGURE_OUT_LEN);
50 req.emr_cmd = MC_CMD_PROXY_CONFIGURE;
51 req.emr_in_buf = payload;
52 req.emr_in_length = MC_CMD_PROXY_CONFIGURE_EXT_IN_LEN;
53 req.emr_out_buf = payload;
54 req.emr_out_length = MC_CMD_PROXY_CONFIGURE_OUT_LEN;
57 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_FLAGS, 1);
58 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BUFF_ADDR_LO,
59 req_buffer_addr & 0xffffffff);
60 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BUFF_ADDR_HI,
61 req_buffer_addr >> 32);
62 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BUFF_ADDR_LO,
63 resp_buffer_addr & 0xffffffff);
64 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BUFF_ADDR_HI,
65 resp_buffer_addr >> 32);
66 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BUFF_ADDR_LO,
67 stat_buffer_addr & 0xffffffff);
68 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BUFF_ADDR_HI,
69 stat_buffer_addr >> 32);
70 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BLOCK_SIZE,
72 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BLOCK_SIZE,
74 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BLOCK_SIZE,
75 MC_PROXY_STATUS_BUFFER_LEN);
76 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_NUM_BLOCKS,
78 memcpy(MCDI_IN2(req, efx_byte_t,
79 PROXY_CONFIGURE_IN_ALLOWED_MCDI_MASK),
80 op_maskp, op_mask_size);
81 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_EXT_IN_RESERVED,
82 EFX_PROXY_CONFIGURE_MAGIC);
85 efx_mcdi_execute(enp, &req);
87 if (req.emr_rc != 0) {
95 EFSYS_PROBE1(fail1, efx_rc_t, rc);
99 static __checkReturn efx_rc_t
100 efx_mcdi_privilege_modify(
102 __in uint32_t fn_group,
103 __in uint32_t pf_index,
104 __in uint32_t vf_index,
105 __in uint32_t add_privileges_mask,
106 __in uint32_t remove_privileges_mask)
108 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PRIVILEGE_MODIFY_IN_LEN,
109 MC_CMD_PRIVILEGE_MODIFY_OUT_LEN);
113 req.emr_cmd = MC_CMD_PRIVILEGE_MODIFY;
114 req.emr_in_buf = payload;
115 req.emr_in_length = MC_CMD_PRIVILEGE_MODIFY_IN_LEN;
116 req.emr_out_buf = payload;
117 req.emr_out_length = MC_CMD_PRIVILEGE_MODIFY_OUT_LEN;
119 EFSYS_ASSERT(fn_group <= MC_CMD_PRIVILEGE_MODIFY_IN_ONE);
121 MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_FN_GROUP, fn_group);
123 if ((fn_group == MC_CMD_PRIVILEGE_MODIFY_IN_ONE) ||
124 (fn_group == MC_CMD_PRIVILEGE_MODIFY_IN_VFS_OF_PF)) {
125 MCDI_IN_POPULATE_DWORD_2(req,
126 PRIVILEGE_MODIFY_IN_FUNCTION,
127 PRIVILEGE_MODIFY_IN_FUNCTION_PF, pf_index,
128 PRIVILEGE_MODIFY_IN_FUNCTION_VF, vf_index);
131 MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_ADD_MASK,
132 add_privileges_mask);
133 MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_REMOVE_MASK,
134 remove_privileges_mask);
136 efx_mcdi_execute(enp, &req);
138 if (req.emr_rc != 0) {
146 EFSYS_PROBE1(fail1, efx_rc_t, rc);
150 static __checkReturn efx_rc_t
151 efx_proxy_auth_fill_op_mask(
152 __in_ecount(op_count) uint32_t *op_listp,
153 __in size_t op_count,
154 __out_ecount(op_mask_size) uint32_t *op_maskp,
155 __in size_t op_mask_size)
160 if ((op_listp == NULL) || (op_maskp == NULL)) {
167 if (op > op_mask_size * 32) {
171 op_maskp[op / 32] |= 1u << (op & 31);
179 EFSYS_PROBE1(fail1, efx_rc_t, rc);
183 __checkReturn efx_rc_t
184 ef10_proxy_auth_mc_config(
186 __in_ecount(block_cnt) efsys_mem_t *request_bufferp,
187 __in_ecount(block_cnt) efsys_mem_t *response_bufferp,
188 __in_ecount(block_cnt) efsys_mem_t *status_bufferp,
189 __in uint32_t block_cnt,
190 __in_ecount(op_count) uint32_t *op_listp,
191 __in size_t op_count)
193 #define PROXY_OPS_MASK_SIZE \
195 MC_CMD_PROXY_CONFIGURE_IN_ALLOWED_MCDI_MASK_LEN, \
199 uint32_t op_mask[PROXY_OPS_MASK_SIZE] = {0};
201 /* Prepare the operation mask from operation list array */
202 if ((rc = efx_proxy_auth_fill_op_mask(op_listp, op_count,
203 op_mask, PROXY_OPS_MASK_SIZE) != 0))
206 if ((rc = efx_mcdi_proxy_configure(enp, B_FALSE,
207 EFSYS_MEM_ADDR(request_bufferp),
208 EFSYS_MEM_ADDR(response_bufferp),
209 EFSYS_MEM_ADDR(status_bufferp),
210 EFSYS_MEM_SIZE(request_bufferp) / block_cnt,
211 EFSYS_MEM_SIZE(response_bufferp) / block_cnt,
212 block_cnt, (uint8_t *)&op_mask,
213 sizeof (op_mask))) != 0)
222 EFSYS_PROBE1(fail1, efx_rc_t, rc);
226 __checkReturn efx_rc_t
227 ef10_proxy_auth_disable(
232 if ((rc = efx_mcdi_proxy_configure(enp, B_TRUE,
233 0, 0, 0, 0, 0, 0, NULL, 0) != 0))
239 EFSYS_PROBE1(fail1, efx_rc_t, rc);
243 __checkReturn efx_rc_t
244 ef10_proxy_auth_privilege_modify(
246 __in uint32_t fn_group,
247 __in uint32_t pf_index,
248 __in uint32_t vf_index,
249 __in uint32_t add_privileges_mask,
250 __in uint32_t remove_privileges_mask)
252 return (efx_mcdi_privilege_modify(enp, fn_group, pf_index, vf_index,
253 add_privileges_mask, remove_privileges_mask));
256 static __checkReturn efx_rc_t
257 efx_mcdi_privilege_mask_set(
259 __in uint32_t vf_index,
263 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PRIVILEGE_MASK_IN_LEN,
264 MC_CMD_PRIVILEGE_MASK_OUT_LEN);
265 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
268 uint32_t old_mask = 0;
269 uint32_t new_mask = 0;
271 EFSYS_ASSERT((value & ~mask) == 0);
273 req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
274 req.emr_in_buf = payload;
275 req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
276 req.emr_out_buf = payload;
277 req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
279 /* Get privilege mask */
280 MCDI_IN_POPULATE_DWORD_2(req, PRIVILEGE_MASK_IN_FUNCTION,
281 PRIVILEGE_MASK_IN_FUNCTION_PF, encp->enc_pf,
282 PRIVILEGE_MASK_IN_FUNCTION_VF, vf_index);
284 efx_mcdi_execute(enp, &req);
286 if (req.emr_rc != 0) {
291 if (req.emr_out_length_used != MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
296 old_mask = *MCDI_OUT2(req, uint32_t, PRIVILEGE_MASK_OUT_OLD_MASK);
297 new_mask = old_mask & ~mask;
298 new_mask |= (value & mask);
300 if (new_mask == old_mask)
303 new_mask |= MC_CMD_PRIVILEGE_MASK_IN_DO_CHANGE;
304 memset(payload, 0, sizeof (payload));
306 req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
307 req.emr_in_buf = payload;
308 req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
309 req.emr_out_buf = payload;
310 req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
312 /* Set privilege mask */
313 MCDI_IN_SET_DWORD(req, PRIVILEGE_MASK_IN_NEW_MASK, new_mask);
315 efx_mcdi_execute(enp, &req);
316 if (req.emr_rc != 0) {
321 if (req.emr_out_length_used != MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
335 EFSYS_PROBE1(fail1, efx_rc_t, rc);
339 __checkReturn efx_rc_t
340 ef10_proxy_auth_set_privilege_mask(
342 __in uint32_t vf_index,
346 return (efx_mcdi_privilege_mask_set(enp, vf_index,
350 static __checkReturn efx_rc_t
351 efx_mcdi_proxy_complete(
353 __in uint32_t fn_index,
354 __in uint32_t proxy_result,
355 __in uint32_t handle)
357 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PROXY_COMPLETE_IN_LEN,
358 MC_CMD_PROXY_COMPLETE_OUT_LEN);
362 req.emr_cmd = MC_CMD_PROXY_COMPLETE;
363 req.emr_in_buf = payload;
364 req.emr_in_length = MC_CMD_PROXY_COMPLETE_IN_LEN;
365 req.emr_out_buf = payload;
366 req.emr_out_length = MC_CMD_PROXY_COMPLETE_OUT_LEN;
368 MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_BLOCK_INDEX, fn_index);
369 MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_STATUS, proxy_result);
370 MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_HANDLE, handle);
372 efx_mcdi_execute(enp, &req);
374 if (req.emr_rc != 0) {
382 EFSYS_PROBE1(fail1, efx_rc_t, rc);
386 __checkReturn efx_rc_t
387 ef10_proxy_auth_complete_request(
389 __in uint32_t fn_index,
390 __in uint32_t proxy_result,
391 __in uint32_t handle)
393 return (efx_mcdi_proxy_complete(enp, fn_index,
394 proxy_result, handle));
397 static __checkReturn efx_rc_t
400 __in uint32_t pf_index,
401 __in uint32_t vf_index,
402 __in_bcount(request_size) uint8_t *request_bufferp,
403 __in size_t request_size,
404 __out_bcount(response_size) uint8_t *response_bufferp,
405 __in size_t response_size,
406 __out_opt size_t *response_size_actualp)
412 if (request_size % sizeof (*inbufp) != 0) {
417 EFSYS_KMEM_ALLOC(enp, (MC_CMD_PROXY_CMD_IN_LEN + request_size), inbufp);
419 req.emr_cmd = MC_CMD_PROXY_CMD;
420 req.emr_in_buf = (uint8_t *) inbufp;
421 req.emr_in_length = MC_CMD_PROXY_CMD_IN_LEN + request_size;
422 req.emr_out_buf = response_bufferp;
423 req.emr_out_length = response_size;
425 MCDI_IN_POPULATE_DWORD_2(req, PROXY_CMD_IN_TARGET,
426 PROXY_CMD_IN_TARGET_PF, pf_index,
427 PROXY_CMD_IN_TARGET_VF, vf_index);
429 /* Proxied command should be located just after PROXY_CMD */
430 memcpy(&inbufp[MC_CMD_PROXY_CMD_IN_LEN / sizeof (*inbufp)],
431 request_bufferp, request_size);
433 efx_mcdi_execute(enp, &req);
435 EFSYS_KMEM_FREE(enp, (MC_CMD_PROXY_CMD_IN_LEN + request_size), inbufp);
436 if (req.emr_rc != 0) {
441 if (response_size_actualp != NULL)
442 *response_size_actualp = req.emr_out_length_used;
449 EFSYS_PROBE1(fail1, efx_rc_t, rc);
453 __checkReturn efx_rc_t
454 ef10_proxy_auth_exec_cmd(
456 __inout efx_proxy_cmd_params_t *paramsp)
458 return (efx_mcdi_proxy_cmd(enp, paramsp->pf_index, paramsp->vf_index,
459 paramsp->request_bufferp, paramsp->request_size,
460 paramsp->response_bufferp, paramsp->response_size,
461 paramsp->response_size_actualp));
463 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */