diff options
author | arybchik <arybchik@FreeBSD.org> | 2015-12-10 07:16:21 +0000 |
---|---|---|
committer | arybchik <arybchik@FreeBSD.org> | 2015-12-10 07:16:21 +0000 |
commit | 2d559ff67c460a8330e8f9b090121bf777ac59d7 (patch) | |
tree | cea2c30b57d1d3fbee5f2399df2660d5c7ddc5e3 | |
parent | 3d29fd25507df8f28ae5668af416e2b89c541fc3 (diff) | |
download | FreeBSD-src-2d559ff67c460a8330e8f9b090121bf777ac59d7.zip FreeBSD-src-2d559ff67c460a8330e8f9b090121bf777ac59d7.tar.gz |
sfxge: [6/6] support for MCDI proxy authorization in common code
Submitted by: Andy Moreton <amoreton at solarflare.com>
Sponsored by: Solarflare Communications, Inc.
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D4454
-rw-r--r-- | sys/dev/sfxge/common/efx.h | 3 | ||||
-rw-r--r-- | sys/dev/sfxge/common/efx_mcdi.c | 82 | ||||
-rw-r--r-- | sys/dev/sfxge/common/efx_mcdi.h | 17 | ||||
-rw-r--r-- | sys/dev/sfxge/common/hunt_ev.c | 14 |
4 files changed, 115 insertions, 1 deletions
diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h index 531b6c9..a84454d 100644 --- a/sys/dev/sfxge/common/efx.h +++ b/sys/dev/sfxge/common/efx.h @@ -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 diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c index 19c825b..e6ca1e8 100644 --- a/sys/dev/sfxge/common/efx_mcdi.c +++ b/sys/dev/sfxge/common/efx_mcdi.c @@ -302,6 +302,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, @@ -322,6 +337,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: @@ -463,6 +481,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); @@ -584,11 +605,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, diff --git a/sys/dev/sfxge/common/efx_mcdi.h b/sys/dev/sfxge/common/efx_mcdi.h index 925e574..960a508 100644 --- a/sys/dev/sfxge/common/efx_mcdi.h +++ b/sys/dev/sfxge/common/efx_mcdi.h @@ -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, diff --git a/sys/dev/sfxge/common/hunt_ev.c b/sys/dev/sfxge/common/hunt_ev.c index b5585bb..5e6ccab 100644 --- a/sys/dev/sfxge/common/hunt_ev.c +++ b/sys/dev/sfxge/common/hunt_ev.c @@ -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; |