Commit 9f2cb71c authored by Ben Hutchings's avatar Ben Hutchings

sfc: Leave interrupts and event queues enabled whenever we can

When SR-IOV is enabled we may receive FLR (Function-Level Reset)
events, associated queue flush events and requests from VF drivers at
any time.  Therefore we need to keep event queues and interrupts
enabled whenever possible.

Currently we stop interrupt-driven event processing before flushing RX
and TX queues; efx_nic_flush_queues() then polls event queues for
flush events and discards any others it finds.  Change it to work with
the regular event handling functions.

Currently efx_start_channel() fills RX queues synchronously when a
device is brought up.  This could now race with NAPI, so change it to
send fill events.

This was almost entirely written by Steve Hodgson, formerly
shodgson@solarflare.com.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
parent 2ae75dac
This diff is collapsed.
...@@ -85,13 +85,6 @@ struct efx_special_buffer { ...@@ -85,13 +85,6 @@ struct efx_special_buffer {
int entries; int entries;
}; };
enum efx_flush_state {
FLUSH_NONE,
FLUSH_PENDING,
FLUSH_FAILED,
FLUSH_DONE,
};
/** /**
* struct efx_tx_buffer - An Efx TX buffer * struct efx_tx_buffer - An Efx TX buffer
* @skb: The associated socket buffer. * @skb: The associated socket buffer.
...@@ -138,7 +131,6 @@ struct efx_tx_buffer { ...@@ -138,7 +131,6 @@ struct efx_tx_buffer {
* @txd: The hardware descriptor ring * @txd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1. * @ptr_mask: The size of the ring minus 1.
* @initialised: Has hardware queue been initialised? * @initialised: Has hardware queue been initialised?
* @flushed: Used when handling queue flushing
* @read_count: Current read pointer. * @read_count: Current read pointer.
* This is the number of buffers that have been removed from both rings. * This is the number of buffers that have been removed from both rings.
* @old_write_count: The value of @write_count when last checked. * @old_write_count: The value of @write_count when last checked.
...@@ -181,7 +173,6 @@ struct efx_tx_queue { ...@@ -181,7 +173,6 @@ struct efx_tx_queue {
struct efx_special_buffer txd; struct efx_special_buffer txd;
unsigned int ptr_mask; unsigned int ptr_mask;
bool initialised; bool initialised;
enum efx_flush_state flushed;
/* Members used mainly on the completion path */ /* Members used mainly on the completion path */
unsigned int read_count ____cacheline_aligned_in_smp; unsigned int read_count ____cacheline_aligned_in_smp;
...@@ -249,6 +240,9 @@ struct efx_rx_page_state { ...@@ -249,6 +240,9 @@ struct efx_rx_page_state {
* @buffer: The software buffer ring * @buffer: The software buffer ring
* @rxd: The hardware descriptor ring * @rxd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1. * @ptr_mask: The size of the ring minus 1.
* @enabled: Receive queue enabled indicator.
* @flush_pending: Set when a RX flush is pending. Has the same lifetime as
* @rxq_flush_pending.
* @added_count: Number of buffers added to the receive queue. * @added_count: Number of buffers added to the receive queue.
* @notified_count: Number of buffers given to NIC (<= @added_count). * @notified_count: Number of buffers given to NIC (<= @added_count).
* @removed_count: Number of buffers removed from the receive queue. * @removed_count: Number of buffers removed from the receive queue.
...@@ -263,13 +257,14 @@ struct efx_rx_page_state { ...@@ -263,13 +257,14 @@ struct efx_rx_page_state {
* @alloc_page_count: RX allocation strategy counter. * @alloc_page_count: RX allocation strategy counter.
* @alloc_skb_count: RX allocation strategy counter. * @alloc_skb_count: RX allocation strategy counter.
* @slow_fill: Timer used to defer efx_nic_generate_fill_event(). * @slow_fill: Timer used to defer efx_nic_generate_fill_event().
* @flushed: Use when handling queue flushing
*/ */
struct efx_rx_queue { struct efx_rx_queue {
struct efx_nic *efx; struct efx_nic *efx;
struct efx_rx_buffer *buffer; struct efx_rx_buffer *buffer;
struct efx_special_buffer rxd; struct efx_special_buffer rxd;
unsigned int ptr_mask; unsigned int ptr_mask;
bool enabled;
bool flush_pending;
int added_count; int added_count;
int notified_count; int notified_count;
...@@ -283,8 +278,6 @@ struct efx_rx_queue { ...@@ -283,8 +278,6 @@ struct efx_rx_queue {
unsigned int alloc_skb_count; unsigned int alloc_skb_count;
struct timer_list slow_fill; struct timer_list slow_fill;
unsigned int slow_fill_count; unsigned int slow_fill_count;
enum efx_flush_state flushed;
}; };
/** /**
...@@ -681,6 +674,13 @@ struct efx_filter_state; ...@@ -681,6 +674,13 @@ struct efx_filter_state;
* @loopback_mode: Loopback status * @loopback_mode: Loopback status
* @loopback_modes: Supported loopback mode bitmask * @loopback_modes: Supported loopback mode bitmask
* @loopback_selftest: Offline self-test private state * @loopback_selftest: Offline self-test private state
* @drain_pending: Count of RX and TX queues that haven't been flushed and drained.
* @rxq_flush_pending: Count of number of receive queues that need to be flushed.
* Decremented when the efx_flush_rx_queue() is called.
* @rxq_flush_outstanding: Count of number of RX flushes started but not yet
* completed (either success or failure). Not used when MCDI is used to
* flush receive queues.
* @flush_wq: wait queue used by efx_nic_flush_queues() to wait for flush completions.
* @monitor_work: Hardware monitor workitem * @monitor_work: Hardware monitor workitem
* @biu_lock: BIU (bus interface unit) lock * @biu_lock: BIU (bus interface unit) lock
* @last_irq_cpu: Last CPU to handle a possible test interrupt. This * @last_irq_cpu: Last CPU to handle a possible test interrupt. This
...@@ -778,6 +778,11 @@ struct efx_nic { ...@@ -778,6 +778,11 @@ struct efx_nic {
struct efx_filter_state *filter_state; struct efx_filter_state *filter_state;
atomic_t drain_pending;
atomic_t rxq_flush_pending;
atomic_t rxq_flush_outstanding;
wait_queue_head_t flush_wq;
/* The following fields may be written more often */ /* The following fields may be written more often */
struct delayed_work monitor_work ____cacheline_aligned_in_smp; struct delayed_work monitor_work ____cacheline_aligned_in_smp;
...@@ -956,13 +961,6 @@ static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue) ...@@ -956,13 +961,6 @@ static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue)
_tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \ _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
_tx_queue++) _tx_queue++)
static inline struct efx_rx_queue *
efx_get_rx_queue(struct efx_nic *efx, unsigned index)
{
EFX_BUG_ON_PARANOID(index >= efx->n_rx_channels);
return &efx->channel[index]->rx_queue;
}
static inline bool efx_channel_has_rx_queue(struct efx_channel *channel) static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
{ {
return channel->channel < channel->efx->n_rx_channels; return channel->channel < channel->efx->n_rx_channels;
......
This diff is collapsed.
...@@ -705,6 +705,7 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue) ...@@ -705,6 +705,7 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
rx_queue->fast_fill_limit = limit; rx_queue->fast_fill_limit = limit;
/* Set up RX descriptor ring */ /* Set up RX descriptor ring */
rx_queue->enabled = true;
efx_nic_init_rx(rx_queue); efx_nic_init_rx(rx_queue);
} }
...@@ -716,6 +717,9 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue) ...@@ -716,6 +717,9 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev, netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
"shutting down RX queue %d\n", efx_rx_queue_index(rx_queue)); "shutting down RX queue %d\n", efx_rx_queue_index(rx_queue));
/* A flush failure might have left rx_queue->enabled */
rx_queue->enabled = false;
del_timer_sync(&rx_queue->slow_fill); del_timer_sync(&rx_queue->slow_fill);
efx_nic_fini_rx(rx_queue); efx_nic_fini_rx(rx_queue);
......
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