Skip to content

Commit

Permalink
sfc: Fix search for flush completion events
Browse files Browse the repository at this point in the history
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 <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ben Hutchings authored and David S. Miller committed Mar 5, 2009
1 parent 32d7600 commit 4720bc6
Showing 1 changed file with 9 additions and 12 deletions.
21 changes: 9 additions & 12 deletions drivers/net/sfc/falcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down

0 comments on commit 4720bc6

Please sign in to comment.