Commit cade715f authored by Ben Hutchings's avatar Ben Hutchings

sfc: Implement asynchronous MCDI requests

This will allow use of MCDI from the data path, in particular for
accelerated RFS.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
parent 251111d9
...@@ -1368,6 +1368,9 @@ static void efx_soft_disable_interrupts(struct efx_nic *efx) ...@@ -1368,6 +1368,9 @@ static void efx_soft_disable_interrupts(struct efx_nic *efx)
if (!channel->type->keep_eventq) if (!channel->type->keep_eventq)
efx_fini_eventq(channel); efx_fini_eventq(channel);
} }
/* Flush the asynchronous MCDI request queue */
efx_mcdi_flush_async(efx);
} }
static void efx_enable_interrupts(struct efx_nic *efx) static void efx_enable_interrupts(struct efx_nic *efx)
......
This diff is collapsed.
...@@ -14,15 +14,17 @@ ...@@ -14,15 +14,17 @@
* enum efx_mcdi_state - MCDI request handling state * enum efx_mcdi_state - MCDI request handling state
* @MCDI_STATE_QUIESCENT: No pending MCDI requests. If the caller holds the * @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 @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 * @MCDI_STATE_RUNNING_SYNC: There is a synchronous MCDI request pending.
* moved into this state is allowed to move out of it. * 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 * @MCDI_STATE_COMPLETED: An MCDI request has completed, but the owning thread
* has not yet consumed the result. For all other threads, equivalent to * has not yet consumed the result. For all other threads, equivalent to
* %MCDI_STATE_RUNNING. * %MCDI_STATE_RUNNING.
*/ */
enum efx_mcdi_state { enum efx_mcdi_state {
MCDI_STATE_QUIESCENT, MCDI_STATE_QUIESCENT,
MCDI_STATE_RUNNING, MCDI_STATE_RUNNING_SYNC,
MCDI_STATE_RUNNING_ASYNC,
MCDI_STATE_COMPLETED, MCDI_STATE_COMPLETED,
}; };
...@@ -33,19 +35,25 @@ enum efx_mcdi_mode { ...@@ -33,19 +35,25 @@ enum efx_mcdi_mode {
/** /**
* struct efx_mcdi_iface - MCDI protocol context * struct efx_mcdi_iface - MCDI protocol context
* @efx: The associated NIC.
* @state: Request handling state. Waited for by @wq. * @state: Request handling state. Waited for by @wq.
* @mode: Poll for mcdi completion, or wait for an mcdi_event. * @mode: Poll for mcdi completion, or wait for an mcdi_event.
* @wq: Wait queue for threads waiting for @state != %MCDI_STATE_RUNNING * @wq: Wait queue for threads waiting for @state != %MCDI_STATE_RUNNING
* @new_epoch: Indicates start of day or start of MC reboot recovery * @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. * @seqno: The next sequence number to use for mcdi requests.
* @credits: Number of spurious MCDI completion events allowed before we * @credits: Number of spurious MCDI completion events allowed before we
* trigger a fatal error * trigger a fatal error
* @resprc: Response error/success code (Linux numbering) * @resprc: Response error/success code (Linux numbering)
* @resp_hdr_len: Response header length * @resp_hdr_len: Response header length
* @resp_data_len: Response data (SDU or error) 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_mcdi_iface {
struct efx_nic *efx;
enum efx_mcdi_state state; enum efx_mcdi_state state;
enum efx_mcdi_mode mode; enum efx_mcdi_mode mode;
wait_queue_head_t wq; wait_queue_head_t wq;
...@@ -56,6 +64,9 @@ struct efx_mcdi_iface { ...@@ -56,6 +64,9 @@ struct efx_mcdi_iface {
int resprc; int resprc;
size_t resp_hdr_len; size_t resp_hdr_len;
size_t resp_data_len; size_t resp_data_len;
spinlock_t async_lock;
struct list_head async_list;
struct timer_list async_timer;
}; };
struct efx_mcdi_mon { struct efx_mcdi_mon {
...@@ -111,10 +122,20 @@ extern int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, ...@@ -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, efx_dword_t *outbuf, size_t outlen,
size_t *outlen_actual); 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 int efx_mcdi_poll_reboot(struct efx_nic *efx);
extern void efx_mcdi_mode_poll(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_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, extern void efx_mcdi_process_event(struct efx_channel *channel,
efx_qword_t *event); efx_qword_t *event);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment