__in uint32_t add_privileges_mask,
__in uint32_t remove_privileges_mask);
+ __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);
+
+ __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);
+
+ __checkReturn efx_rc_t
+ef10_proxy_auth_exec_cmd(
+ __in efx_nic_t *enp,
+ __inout efx_proxy_cmd_params_t *paramsp);
+
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
#if EFSYS_OPT_RX_PACKED_STREAM
return (efx_mcdi_privilege_modify(enp, fn_group, pf_index, vf_index,
add_privileges_mask, remove_privileges_mask));
}
+
+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)
+{
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PRIVILEGE_MASK_IN_LEN,
+ MC_CMD_PRIVILEGE_MASK_OUT_LEN);
+ efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+ efx_mcdi_req_t req;
+ efx_rc_t rc;
+ uint32_t old_mask = 0;
+ uint32_t new_mask = 0;
+
+ EFSYS_ASSERT((value & ~mask) == 0);
+
+ req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
+
+ /* Get privilege mask */
+ MCDI_IN_POPULATE_DWORD_2(req, PRIVILEGE_MASK_IN_FUNCTION,
+ PRIVILEGE_MASK_IN_FUNCTION_PF, encp->enc_pf,
+ PRIVILEGE_MASK_IN_FUNCTION_VF, vf_index);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used != MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
+ rc = EMSGSIZE;
+ goto fail2;
+ }
+
+ old_mask = *MCDI_OUT2(req, uint32_t, PRIVILEGE_MASK_OUT_OLD_MASK);
+ new_mask = old_mask & ~mask;
+ new_mask |= (value & mask);
+
+ if (new_mask == old_mask)
+ return (0);
+
+ new_mask |= MC_CMD_PRIVILEGE_MASK_IN_DO_CHANGE;
+ memset(payload, 0, sizeof (payload));
+
+ req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
+
+ /* Set privilege mask */
+ MCDI_IN_SET_DWORD(req, PRIVILEGE_MASK_IN_NEW_MASK, new_mask);
+
+ efx_mcdi_execute(enp, &req);
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail3;
+ }
+
+ if (req.emr_out_length_used != MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
+ rc = EMSGSIZE;
+ goto fail4;
+ }
+
+ return (0);
+
+fail4:
+ EFSYS_PROBE(fail4);
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+ __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)
+{
+ return (efx_mcdi_privilege_mask_set(enp, vf_index,
+ mask, value));
+}
+
+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)
+{
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PROXY_COMPLETE_IN_LEN,
+ MC_CMD_PROXY_COMPLETE_OUT_LEN);
+ efx_mcdi_req_t req;
+ efx_rc_t rc;
+
+ req.emr_cmd = MC_CMD_PROXY_COMPLETE;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_PROXY_COMPLETE_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_PROXY_COMPLETE_OUT_LEN;
+
+ MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_BLOCK_INDEX, fn_index);
+ MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_STATUS, proxy_result);
+ MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_HANDLE, handle);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+ __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)
+{
+ return (efx_mcdi_proxy_complete(enp, fn_index,
+ proxy_result, handle));
+}
+
+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)
+{
+ efx_dword_t *inbufp;
+ efx_mcdi_req_t req;
+ efx_rc_t rc;
+
+ if (request_size % sizeof (*inbufp) != 0) {
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ EFSYS_KMEM_ALLOC(enp, (MC_CMD_PROXY_CMD_IN_LEN + request_size), inbufp);
+
+ req.emr_cmd = MC_CMD_PROXY_CMD;
+ req.emr_in_buf = (uint8_t *) inbufp;
+ req.emr_in_length = MC_CMD_PROXY_CMD_IN_LEN + request_size;
+ req.emr_out_buf = response_bufferp;
+ req.emr_out_length = response_size;
+
+ MCDI_IN_POPULATE_DWORD_2(req, PROXY_CMD_IN_TARGET,
+ PROXY_CMD_IN_TARGET_PF, pf_index,
+ PROXY_CMD_IN_TARGET_VF, vf_index);
+
+ /* Proxied command should be located just after PROXY_CMD */
+ memcpy(&inbufp[MC_CMD_PROXY_CMD_IN_LEN / sizeof (*inbufp)],
+ request_bufferp, request_size);
+
+ efx_mcdi_execute(enp, &req);
+
+ EFSYS_KMEM_FREE(enp, (MC_CMD_PROXY_CMD_IN_LEN + request_size), inbufp);
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail2;
+ }
+
+ if (response_size_actualp != NULL)
+ *response_size_actualp = req.emr_out_length_used;
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+ef10_proxy_auth_exec_cmd(
+ __in efx_nic_t *enp,
+ __inout efx_proxy_cmd_params_t *paramsp)
+{
+ return (efx_mcdi_proxy_cmd(enp, paramsp->pf_index, paramsp->vf_index,
+ paramsp->request_bufferp, paramsp->request_size,
+ paramsp->response_bufferp, paramsp->response_size,
+ paramsp->response_size_actualp));
+}
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
uint32_t handled_privileges;
} efx_proxy_auth_config_t;
+typedef struct efx_proxy_cmd_params_s {
+ uint32_t pf_index;
+ uint32_t vf_index;
+ uint8_t *request_bufferp;
+ size_t request_size;
+ uint8_t *response_bufferp;
+ size_t response_size;
+ size_t *response_size_actualp;
+} efx_proxy_cmd_params_t;
+
extern __checkReturn efx_rc_t
efx_proxy_auth_init(
__in efx_nic_t *enp);
__in efx_nic_t *enp,
__in uint32_t handled_privileges);
+ __checkReturn efx_rc_t
+efx_proxy_auth_complete_request(
+ __in efx_nic_t *enp,
+ __in uint32_t fn_index,
+ __in uint32_t proxy_result,
+ __in uint32_t handle);
+
+ __checkReturn efx_rc_t
+efx_proxy_auth_exec_cmd(
+ __in efx_nic_t *enp,
+ __inout efx_proxy_cmd_params_t *paramsp);
+
+ __checkReturn efx_rc_t
+efx_proxy_auth_set_privilege_mask(
+ __in efx_nic_t *enp,
+ __in uint32_t vf_index,
+ __in uint32_t mask,
+ __in uint32_t value);
+
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
#ifdef __cplusplus
efx_rc_t (*epo_disable)(efx_nic_t *);
efx_rc_t (*epo_privilege_modify)(efx_nic_t *, uint32_t, uint32_t,
uint32_t, uint32_t, uint32_t);
+ efx_rc_t (*epo_set_privilege_mask)(efx_nic_t *, uint32_t,
+ uint32_t, uint32_t);
+ efx_rc_t (*epo_complete_request)(efx_nic_t *, uint32_t,
+ uint32_t, uint32_t);
+ efx_rc_t (*epo_exec_cmd)(efx_nic_t *, efx_proxy_cmd_params_t *);
} efx_proxy_ops_t;
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
rc = EIO;
goto fail1;
}
+#if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER
+ if (((cmd != emrp->emr_cmd) && (emrp->emr_cmd != MC_CMD_PROXY_CMD)) ||
+#else
if ((cmd != emrp->emr_cmd) ||
+#endif
(seq != ((emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ)))) {
/* Response is for a different request */
rc = EIO;
efx_dword_t hdr[2];
unsigned int hdr_len;
size_t bytes;
+ unsigned int resp_off;
+#if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER
+ unsigned int resp_cmd;
+ boolean_t proxied_cmd_resp = B_FALSE;
+#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
if (emrp->emr_out_buf == NULL)
return;
*/
efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1]));
hdr_len += sizeof (hdr[1]);
+ resp_off = hdr_len;
emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1],
- MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
+ MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
+#if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER
+ /*
+ * A proxy MCDI command is executed by PF on behalf of
+ * one of its VFs. The command to be proxied follows
+ * immediately afterward in the host buffer.
+ * PROXY_CMD inner call complete response should be copied to
+ * output buffer so that it can be returned to the requesting
+ * function in MC_CMD_PROXY_COMPLETE payload.
+ */
+ resp_cmd =
+ EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_EXTENDED_CMD);
+ proxied_cmd_resp = ((emrp->emr_cmd == MC_CMD_PROXY_CMD) &&
+ (resp_cmd != MC_CMD_PROXY_CMD));
+ if (proxied_cmd_resp) {
+ resp_off = 0;
+ emrp->emr_out_length_used += hdr_len;
+ }
+#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
+ } else {
+ resp_off = hdr_len;
}
/* Copy payload out into caller supplied buffer */
bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length);
- efx_mcdi_read_response(enp, emrp->emr_out_buf, hdr_len, bytes);
+ efx_mcdi_read_response(enp, emrp->emr_out_buf, resp_off, bytes);
#if EFSYS_OPT_MCDI_LOGGING
if (emtp->emt_logger != NULL) {
unsigned int emr_cmd;
uint8_t *emr_in_buf;
size_t emr_in_length;
- /* Outputs: retcode, buffer, length, and length used */
+ /* Outputs: retcode, buffer, length and length used */
efx_rc_t emr_rc;
uint8_t *emr_out_buf;
size_t emr_out_length;
NULL, /* epo_mc_config */
NULL, /* epo_disable */
NULL, /* epo_privilege_modify */
+ NULL, /* epo_set_privilege_mask */
+ NULL, /* epo_complete_request */
+ NULL, /* epo_exec_cmd */
};
#endif /* EFSYS_OPT_SIENA */
ef10_proxy_auth_mc_config, /* epo_mc_config */
ef10_proxy_auth_disable, /* epo_disable */
ef10_proxy_auth_privilege_modify, /* epo_privilege_modify */
+ ef10_proxy_auth_set_privilege_mask, /* epo_set_privilege_mask */
+ ef10_proxy_auth_complete_request, /* epo_complete_request */
+ ef10_proxy_auth_exec_cmd, /* epo_exec_cmd */
};
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
return (rc);
}
+ __checkReturn efx_rc_t
+efx_proxy_auth_complete_request(
+ __in efx_nic_t *enp,
+ __in uint32_t fn_index,
+ __in uint32_t proxy_result,
+ __in uint32_t handle)
+{
+ const efx_proxy_ops_t *epop = enp->en_epop;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROXY);
+
+ if (epop->epo_complete_request == NULL) {
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ rc = epop->epo_complete_request(enp, fn_index, proxy_result, handle);
+ if (rc != 0)
+ goto fail2;
+
+ return (0);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_proxy_auth_exec_cmd(
+ __in efx_nic_t *enp,
+ __inout efx_proxy_cmd_params_t *paramsp)
+{
+ const efx_proxy_ops_t *epop = enp->en_epop;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROXY);
+
+ if (paramsp == NULL) {
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ if (epop->epo_exec_cmd == NULL) {
+ rc = ENOTSUP;
+ goto fail2;
+ }
+
+ rc = epop->epo_exec_cmd(enp, paramsp);
+ if (rc != 0)
+ goto fail3;
+
+ return (0);
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_proxy_auth_set_privilege_mask(
+ __in efx_nic_t *enp,
+ __in uint32_t vf_index,
+ __in uint32_t mask,
+ __in uint32_t value)
+{
+ const efx_proxy_ops_t *epop = enp->en_epop;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROXY);
+
+ if (epop->epo_set_privilege_mask == NULL) {
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ rc = epop->epo_set_privilege_mask(enp, vf_index, mask, value);
+ if (rc != 0)
+ goto fail2;
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */