From 4720bc6cfe70b606cf62a244c7a5391e59923e45 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 4 Mar 2009 10:01:15 +0000 Subject: sfc: Fix search for flush completion events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When flushing queues we disable normal interrupt and event handling and poll event queue 0 looking for flush completions. Unfortunately the flush event polling loop fails to move past any other type of event. This problem has not been observed in production hardware but appears to be a possibility. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index efd121c42a2..82c10f4de1b 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1187,31 +1187,29 @@ static void falcon_poll_flush_events(struct efx_nic *efx) struct efx_channel *channel = &efx->channel[0]; struct efx_tx_queue *tx_queue; struct efx_rx_queue *rx_queue; - unsigned int read_ptr, i; + unsigned int read_ptr = channel->eventq_read_ptr; + unsigned int end_ptr = (read_ptr - 1) & FALCON_EVQ_MASK; - read_ptr = channel->eventq_read_ptr; - for (i = 0; i < FALCON_EVQ_SIZE; ++i) { + do { efx_qword_t *event = falcon_event(channel, read_ptr); int ev_code, ev_sub_code, ev_queue; bool ev_failed; + if (!falcon_event_present(event)) break; ev_code = EFX_QWORD_FIELD(*event, EV_CODE); - if (ev_code != DRIVER_EV_DECODE) - continue; - ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE); - switch (ev_sub_code) { - case TX_DESCQ_FLS_DONE_EV_DECODE: + if (ev_code == DRIVER_EV_DECODE && + ev_sub_code == TX_DESCQ_FLS_DONE_EV_DECODE) { ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_TX_DESCQ_ID); if (ev_queue < EFX_TX_QUEUE_COUNT) { tx_queue = efx->tx_queue + ev_queue; tx_queue->flushed = true; } - break; - case RX_DESCQ_FLS_DONE_EV_DECODE: + } else if (ev_code == DRIVER_EV_DECODE && + ev_sub_code == RX_DESCQ_FLS_DONE_EV_DECODE) { ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_DESCQ_ID); ev_failed = EFX_QWORD_FIELD(*event, @@ -1225,11 +1223,10 @@ static void falcon_poll_flush_events(struct efx_nic *efx) else rx_queue->flushed = true; } - break; } read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK; - } + } while (read_ptr != end_ptr); } /* Handle tx and rx flushes at the same time, since they run in -- cgit v1.2.3