MFC r292051

sfxge: [6/6] support for MCDI proxy authorization in common code

Submitted by:   Andy Moreton <amoreton at solarflare.com>
Sponsored by:   Solarflare Communications, Inc.
This commit is contained in:
arybchik 2016-01-14 15:27:49 +00:00
parent aec7138125
commit c98bc0b5ee
4 changed files with 115 additions and 1 deletions

View File

@ -218,6 +218,9 @@ typedef struct efx_mcdi_transport_s {
void (*emt_logger)(void *, efx_log_msg_t,
void *, size_t, void *, size_t);
#endif /* EFSYS_OPT_MCDI_LOGGING */
#if EFSYS_OPT_MCDI_PROXY_AUTH
void (*emt_ev_proxy_response)(void *, uint32_t, efx_rc_t);
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */
} efx_mcdi_transport_t;
extern __checkReturn efx_rc_t

View File

@ -299,6 +299,21 @@ efx_mcdi_read_response_header(
emrp->emr_err_code = err_code;
emrp->emr_err_arg = err_arg;
#if EFSYS_OPT_MCDI_PROXY_AUTH
if ((err_code == MC_CMD_ERR_PROXY_PENDING) &&
(err_len == sizeof (err))) {
/*
* The MCDI request would normally fail with EPERM, but
* firmware has forwarded it to an authorization agent
* attached to a privileged PF.
*
* Save the authorization request handle. The client
* must wait for a PROXY_RESPONSE event, or timeout.
*/
emrp->emr_proxy_handle = err_arg;
}
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */
#if EFSYS_OPT_MCDI_LOGGING
if (emtp->emt_logger != NULL) {
emtp->emt_logger(emtp->emt_context,
@ -319,6 +334,9 @@ efx_mcdi_read_response_header(
emrp->emr_rc = 0;
emrp->emr_out_length_used = data_len;
#if EFSYS_OPT_MCDI_PROXY_AUTH
emrp->emr_proxy_handle = 0;
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */
return;
fail3:
@ -460,6 +478,9 @@ efx_mcdi_request_errcode(
case MC_CMD_ERR_MAC_EXIST:
return (EEXIST);
case MC_CMD_ERR_PROXY_PENDING:
return (EAGAIN);
default:
EFSYS_PROBE1(mc_pcol_error, int, err);
return (EIO);
@ -581,11 +602,70 @@ efx_mcdi_ev_cpl(
emrp->emr_rc = 0;
}
}
emcop->emco_request_copyout(enp, emrp);
if (errcode == 0) {
emcop->emco_request_copyout(enp, emrp);
}
emtp->emt_ev_cpl(emtp->emt_context);
}
#if EFSYS_OPT_MCDI_PROXY_AUTH
__checkReturn efx_rc_t
efx_mcdi_get_proxy_handle(
__in efx_nic_t *enp,
__in efx_mcdi_req_t *emrp,
__out uint32_t *handlep)
{
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
efx_rc_t rc;
/*
* Return proxy handle from MCDI request that returned with error
* MC_MCD_ERR_PROXY_PENDING. This handle is used to wait for a matching
* PROXY_RESPONSE event.
*/
if ((emrp == NULL) || (handlep == NULL)) {
rc = EINVAL;
goto fail1;
}
if ((emrp->emr_rc != 0) &&
(emrp->emr_err_code == MC_CMD_ERR_PROXY_PENDING)) {
*handlep = emrp->emr_proxy_handle;
rc = 0;
} else {
*handlep = 0;
rc = ENOENT;
}
return (rc);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
void
efx_mcdi_ev_proxy_response(
__in efx_nic_t *enp,
__in unsigned int handle,
__in unsigned int status)
{
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
efx_rc_t rc;
/*
* Handle results of an authorization request for a privileged MCDI
* command. If authorization was granted then we must re-issue the
* original MCDI request. If authorization failed or timed out,
* then the original MCDI request should be completed with the
* result code from this event.
*/
rc = (status == 0) ? 0 : efx_mcdi_request_errcode(status);
emtp->emt_ev_proxy_response(emtp->emt_context, handle, rc);
}
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */
void
efx_mcdi_ev_death(
__in efx_nic_t *enp,

View File

@ -62,6 +62,9 @@ struct efx_mcdi_req_s {
/* Internals: low level transport details */
unsigned int emr_err_code;
unsigned int emr_err_arg;
#if EFSYS_OPT_MCDI_PROXY_AUTH
uint32_t emr_proxy_handle;
#endif
};
typedef struct efx_mcdi_iface_s {
@ -97,6 +100,20 @@ efx_mcdi_ev_cpl(
__in unsigned int outlen,
__in int errcode);
#if EFSYS_OPT_MCDI_PROXY_AUTH
__checkReturn efx_rc_t
efx_mcdi_get_proxy_handle(
__in efx_nic_t *enp,
__in efx_mcdi_req_t *emrp,
__out uint32_t *handlep);
extern void
efx_mcdi_ev_proxy_response(
__in efx_nic_t *enp,
__in unsigned int handle,
__in unsigned int status);
#endif
extern void
efx_mcdi_ev_death(
__in efx_nic_t *enp,

View File

@ -829,6 +829,20 @@ hunt_ev_mcdi(
MCDI_EV_FIELD(eqp, CMDDONE_ERRNO));
break;
#if EFSYS_OPT_MCDI_PROXY_AUTH
case MCDI_EVENT_CODE_PROXY_RESPONSE:
/*
* This event notifies a function that an authorization request
* has been processed. If the request was authorized then the
* function can now re-send the original MCDI request.
* See SF-113652-SW "SR-IOV Proxied Network Access Control".
*/
efx_mcdi_ev_proxy_response(enp,
MCDI_EV_FIELD(eqp, PROXY_RESPONSE_HANDLE),
MCDI_EV_FIELD(eqp, PROXY_RESPONSE_RC));
break;
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */
case MCDI_EVENT_CODE_LINKCHANGE: {
efx_link_mode_t link_mode;