aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc
diff options
context:
space:
mode:
authorDaniel Pieczko <dpieczko@solarflare.com>2012-10-02 08:36:18 -0400
committerBen Hutchings <bhutchings@solarflare.com>2012-11-30 21:37:27 -0500
commit525d9e824018cd7cc8d8d44832ddcd363abfe6e1 (patch)
treecedb42187455981ebd1cb05a9bba0a836b5a94eb /drivers/net/ethernet/sfc
parent876be083b669c43203c0ee8709d749896e1d8d60 (diff)
sfc: Work-around flush timeout when flushes have completed
We sometimes hit a "failed to flush" timeout on some TX queues, but the flushes have completed and the flush completion events seem to go missing. In this case, we can check the TX_DESC_PTR_TBL register and drain the queues if the flushes had finished. [bwh: Minor fixes to coding style] Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h1
-rw-r--r--drivers/net/ethernet/sfc/nic.c56
2 files changed, 53 insertions, 4 deletions
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 1014556df0e7..2d756c1d7142 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -200,6 +200,7 @@ struct efx_tx_queue {
200 /* Members shared between paths and sometimes updated */ 200 /* Members shared between paths and sometimes updated */
201 unsigned int empty_read_count ____cacheline_aligned_in_smp; 201 unsigned int empty_read_count ____cacheline_aligned_in_smp;
202#define EFX_EMPTY_COUNT_VALID 0x80000000 202#define EFX_EMPTY_COUNT_VALID 0x80000000
203 atomic_t flush_outstanding;
203}; 204};
204 205
205/** 206/**
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 1327f29d086f..0ad790cc473c 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -73,6 +73,8 @@
73 _EFX_CHANNEL_MAGIC(_EFX_CHANNEL_MAGIC_TX_DRAIN, \ 73 _EFX_CHANNEL_MAGIC(_EFX_CHANNEL_MAGIC_TX_DRAIN, \
74 (_tx_queue)->queue) 74 (_tx_queue)->queue)
75 75
76static void efx_magic_event(struct efx_channel *channel, u32 magic);
77
76/************************************************************************** 78/**************************************************************************
77 * 79 *
78 * Solarstorm hardware access 80 * Solarstorm hardware access
@@ -491,6 +493,9 @@ static void efx_flush_tx_queue(struct efx_tx_queue *tx_queue)
491 struct efx_nic *efx = tx_queue->efx; 493 struct efx_nic *efx = tx_queue->efx;
492 efx_oword_t tx_flush_descq; 494 efx_oword_t tx_flush_descq;
493 495
496 WARN_ON(atomic_read(&tx_queue->flush_outstanding));
497 atomic_set(&tx_queue->flush_outstanding, 1);
498
494 EFX_POPULATE_OWORD_2(tx_flush_descq, 499 EFX_POPULATE_OWORD_2(tx_flush_descq,
495 FRF_AZ_TX_FLUSH_DESCQ_CMD, 1, 500 FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
496 FRF_AZ_TX_FLUSH_DESCQ, tx_queue->queue); 501 FRF_AZ_TX_FLUSH_DESCQ, tx_queue->queue);
@@ -666,6 +671,47 @@ static bool efx_flush_wake(struct efx_nic *efx)
666 && atomic_read(&efx->rxq_flush_pending) > 0)); 671 && atomic_read(&efx->rxq_flush_pending) > 0));
667} 672}
668 673
674static bool efx_check_tx_flush_complete(struct efx_nic *efx)
675{
676 bool i = true;
677 efx_oword_t txd_ptr_tbl;
678 struct efx_channel *channel;
679 struct efx_tx_queue *tx_queue;
680
681 efx_for_each_channel(channel, efx) {
682 efx_for_each_channel_tx_queue(tx_queue, channel) {
683 efx_reado_table(efx, &txd_ptr_tbl,
684 FR_BZ_TX_DESC_PTR_TBL, tx_queue->queue);
685 if (EFX_OWORD_FIELD(txd_ptr_tbl,
686 FRF_AZ_TX_DESCQ_FLUSH) ||
687 EFX_OWORD_FIELD(txd_ptr_tbl,
688 FRF_AZ_TX_DESCQ_EN)) {
689 netif_dbg(efx, hw, efx->net_dev,
690 "flush did not complete on TXQ %d\n",
691 tx_queue->queue);
692 i = false;
693 } else if (atomic_cmpxchg(&tx_queue->flush_outstanding,
694 1, 0)) {
695 /* The flush is complete, but we didn't
696 * receive a flush completion event
697 */
698 netif_dbg(efx, hw, efx->net_dev,
699 "flush complete on TXQ %d, so drain "
700 "the queue\n", tx_queue->queue);
701 /* Don't need to increment drain_pending as it
702 * has already been incremented for the queues
703 * which did not drain
704 */
705 efx_magic_event(channel,
706 EFX_CHANNEL_MAGIC_TX_DRAIN(
707 tx_queue));
708 }
709 }
710 }
711
712 return i;
713}
714
669/* Flush all the transmit queues, and continue flushing receive queues until 715/* Flush all the transmit queues, and continue flushing receive queues until
670 * they're all flushed. Wait for the DRAIN events to be recieved so that there 716 * they're all flushed. Wait for the DRAIN events to be recieved so that there
671 * are no more RX and TX events left on any channel. */ 717 * are no more RX and TX events left on any channel. */
@@ -726,7 +772,8 @@ int efx_nic_flush_queues(struct efx_nic *efx)
726 timeout); 772 timeout);
727 } 773 }
728 774
729 if (atomic_read(&efx->drain_pending)) { 775 if (atomic_read(&efx->drain_pending) &&
776 !efx_check_tx_flush_complete(efx)) {
730 netif_err(efx, hw, efx->net_dev, "failed to flush %d queues " 777 netif_err(efx, hw, efx->net_dev, "failed to flush %d queues "
731 "(rx %d+%d)\n", atomic_read(&efx->drain_pending), 778 "(rx %d+%d)\n", atomic_read(&efx->drain_pending),
732 atomic_read(&efx->rxq_flush_outstanding), 779 atomic_read(&efx->rxq_flush_outstanding),
@@ -1018,9 +1065,10 @@ efx_handle_tx_flush_done(struct efx_nic *efx, efx_qword_t *event)
1018 if (qid < EFX_TXQ_TYPES * efx->n_tx_channels) { 1065 if (qid < EFX_TXQ_TYPES * efx->n_tx_channels) {
1019 tx_queue = efx_get_tx_queue(efx, qid / EFX_TXQ_TYPES, 1066 tx_queue = efx_get_tx_queue(efx, qid / EFX_TXQ_TYPES,
1020 qid % EFX_TXQ_TYPES); 1067 qid % EFX_TXQ_TYPES);
1021 1068 if (atomic_cmpxchg(&tx_queue->flush_outstanding, 1, 0)) {
1022 efx_magic_event(tx_queue->channel, 1069 efx_magic_event(tx_queue->channel,
1023 EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue)); 1070 EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue));
1071 }
1024 } 1072 }
1025} 1073}
1026 1074