summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/sfc/tx.c
diff options
context:
space:
mode:
authorMartin Habets <mhabets@solarflare.com>2015-11-02 12:51:31 +0000
committerDavid S. Miller <davem@davemloft.net>2015-11-02 23:02:58 -0500
commitb2663a4f30e85ec606b806f5135413e6d5c78d1e (patch)
tree115a16d89b46e332254fe2cdf3b1087f95e97391 /drivers/net/ethernet/sfc/tx.c
parent4ece9009774596ee3df0acba65a324b7ea79387c (diff)
sfc: push partner queue for skb->xmit_more
When the IP stack passes SKBs the sfc driver puts them in 2 different TX queues (called partners), one for checksummed and one for not checksummed. If the SKB has xmit_more set the driver will delay pushing the work to the NIC. When later it does decide to push the buffers this patch ensures it also pushes the partner queue, if that also has any delayed work. Before this fix the work in the partner queue would be left for a long time and cause a netdev watchdog. Fixes: 70b33fb ("sfc: add support for skb->xmit_more") Reported-by: Jianlin Shi <jishi@redhat.com> Signed-off-by: Martin Habets <mhabets@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/sfc/tx.c')
-rw-r--r--drivers/net/ethernet/sfc/tx.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 1833a0146571..67f6afaa022f 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -431,8 +431,20 @@ finish_packet:
efx_tx_maybe_stop_queue(tx_queue);
/* Pass off to hardware */
- if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq))
+ if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
+ struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue);
+
+ /* There could be packets left on the partner queue if those
+ * SKBs had skb->xmit_more set. If we do not push those they
+ * could be left for a long time and cause a netdev watchdog.
+ */
+ if (txq2->xmit_more_available)
+ efx_nic_push_buffers(txq2);
+
efx_nic_push_buffers(tx_queue);
+ } else {
+ tx_queue->xmit_more_available = skb->xmit_more;
+ }
tx_queue->tx_packets++;
@@ -722,6 +734,7 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
tx_queue->read_count = 0;
tx_queue->old_read_count = 0;
tx_queue->empty_read_count = 0 | EFX_EMPTY_COUNT_VALID;
+ tx_queue->xmit_more_available = false;
/* Set up TX descriptor ring */
efx_nic_init_tx(tx_queue);
@@ -747,6 +760,7 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
++tx_queue->read_count;
}
+ tx_queue->xmit_more_available = false;
netdev_tx_reset_queue(tx_queue->core_txq);
}
@@ -1302,8 +1316,20 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
efx_tx_maybe_stop_queue(tx_queue);
/* Pass off to hardware */
- if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq))
+ if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
+ struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue);
+
+ /* There could be packets left on the partner queue if those
+ * SKBs had skb->xmit_more set. If we do not push those they
+ * could be left for a long time and cause a netdev watchdog.
+ */
+ if (txq2->xmit_more_available)
+ efx_nic_push_buffers(txq2);
+
efx_nic_push_buffers(tx_queue);
+ } else {
+ tx_queue->xmit_more_available = skb->xmit_more;
+ }
tx_queue->tso_bursts++;
return NETDEV_TX_OK;