aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc/mcdi.h
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2013-08-27 23:12:31 +0100
committerBen Hutchings <bhutchings@solarflare.com>2013-08-29 18:12:06 +0100
commitcade715ff18440dda53e59c10c606586c92be33e (patch)
tree5c88d245245ccf9f67f6d19b076bd280686e5346 /drivers/net/ethernet/sfc/mcdi.h
parentsfc: Remove unnecessary use of atomic_t (diff)
downloadlinux-dev-cade715ff18440dda53e59c10c606586c92be33e.tar.xz
linux-dev-cade715ff18440dda53e59c10c606586c92be33e.zip
sfc: Implement asynchronous MCDI requests
This will allow use of MCDI from the data path, in particular for accelerated RFS. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc/mcdi.h')
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h29
1 files changed, 25 insertions, 4 deletions
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index 6c0363a2abdf..e37cf1d6ed46 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -14,15 +14,17 @@
* enum efx_mcdi_state - MCDI request handling state
* @MCDI_STATE_QUIESCENT: No pending MCDI requests. If the caller holds the
* mcdi @iface_lock then they are able to move to %MCDI_STATE_RUNNING
- * @MCDI_STATE_RUNNING: There is an MCDI request pending. Only the thread that
- * moved into this state is allowed to move out of it.
+ * @MCDI_STATE_RUNNING_SYNC: There is a synchronous MCDI request pending.
+ * Only the thread that moved into this state is allowed to move out of it.
+ * @MCDI_STATE_RUNNING_ASYNC: There is an asynchronous MCDI request pending.
* @MCDI_STATE_COMPLETED: An MCDI request has completed, but the owning thread
* has not yet consumed the result. For all other threads, equivalent to
* %MCDI_STATE_RUNNING.
*/
enum efx_mcdi_state {
MCDI_STATE_QUIESCENT,
- MCDI_STATE_RUNNING,
+ MCDI_STATE_RUNNING_SYNC,
+ MCDI_STATE_RUNNING_ASYNC,
MCDI_STATE_COMPLETED,
};
@@ -33,19 +35,25 @@ enum efx_mcdi_mode {
/**
* struct efx_mcdi_iface - MCDI protocol context
+ * @efx: The associated NIC.
* @state: Request handling state. Waited for by @wq.
* @mode: Poll for mcdi completion, or wait for an mcdi_event.
* @wq: Wait queue for threads waiting for @state != %MCDI_STATE_RUNNING
* @new_epoch: Indicates start of day or start of MC reboot recovery
- * @iface_lock: Serialises access to all the following fields
+ * @iface_lock: Serialises access to @seqno, @credits and response metadata
* @seqno: The next sequence number to use for mcdi requests.
* @credits: Number of spurious MCDI completion events allowed before we
* trigger a fatal error
* @resprc: Response error/success code (Linux numbering)
* @resp_hdr_len: Response header length
* @resp_data_len: Response data (SDU or error) length
+ * @async_lock: Serialises access to @async_list while event processing is
+ * enabled
+ * @async_list: Queue of asynchronous requests
+ * @async_timer: Timer for asynchronous request timeout
*/
struct efx_mcdi_iface {
+ struct efx_nic *efx;
enum efx_mcdi_state state;
enum efx_mcdi_mode mode;
wait_queue_head_t wq;
@@ -56,6 +64,9 @@ struct efx_mcdi_iface {
int resprc;
size_t resp_hdr_len;
size_t resp_data_len;
+ spinlock_t async_lock;
+ struct list_head async_list;
+ struct timer_list async_timer;
};
struct efx_mcdi_mon {
@@ -111,10 +122,20 @@ extern int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
efx_dword_t *outbuf, size_t outlen,
size_t *outlen_actual);
+typedef void efx_mcdi_async_completer(struct efx_nic *efx,
+ unsigned long cookie, int rc,
+ efx_dword_t *outbuf,
+ size_t outlen_actual);
+extern int efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd,
+ const efx_dword_t *inbuf, size_t inlen,
+ size_t outlen,
+ efx_mcdi_async_completer *complete,
+ unsigned long cookie);
extern int efx_mcdi_poll_reboot(struct efx_nic *efx);
extern void efx_mcdi_mode_poll(struct efx_nic *efx);
extern void efx_mcdi_mode_event(struct efx_nic *efx);
+extern void efx_mcdi_flush_async(struct efx_nic *efx);
extern void efx_mcdi_process_event(struct efx_channel *channel,
efx_qword_t *event);