summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorarybchik <arybchik@FreeBSD.org>2015-12-10 07:16:21 +0000
committerarybchik <arybchik@FreeBSD.org>2015-12-10 07:16:21 +0000
commit2d559ff67c460a8330e8f9b090121bf777ac59d7 (patch)
treecea2c30b57d1d3fbee5f2399df2660d5c7ddc5e3
parent3d29fd25507df8f28ae5668af416e2b89c541fc3 (diff)
downloadFreeBSD-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.h3
-rw-r--r--sys/dev/sfxge/common/efx_mcdi.c82
-rw-r--r--sys/dev/sfxge/common/efx_mcdi.h17
-rw-r--r--sys/dev/sfxge/common/hunt_ev.c14
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;
OpenPOWER on IntegriCloud