aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Maravic <igorm@etf.rs>2012-03-04 18:01:25 -0500
committerFrancois Romieu <romieu@fr.zoreil.com>2012-03-05 18:24:26 -0500
commit036dafa28da1e2565a8529de2ae663c37b7a0060 (patch)
tree97df33f26323d324964412939aa2b60dd15c7b88
parent8027aa245bbd125350f6a78c5a78771d143aba55 (diff)
r8169: add byte queue limit support.
Nothing fancy: - sent bytes count is notified in the start_xmit path right before updating the owner bit in the hardware Tx descriptor (E. Dumazet) - avoid useless tp->dev dereferencing in start_xmit (E. Dumazet) Use of netdev_reset_queue is favored over proper accounting in rtl8169_tx_clear_range since the latter would need more work for the same result (nb: said accounting degenerates to nothing in xmit_frags). Signed-off-by: Igor Maravic <igorm@etf.rs> Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
-rw-r--r--drivers/net/ethernet/realtek/r8169.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index a4d7674886a2..515a7edb605c 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -5399,6 +5399,7 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp)
5399{ 5399{
5400 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); 5400 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
5401 tp->cur_tx = tp->dirty_tx = 0; 5401 tp->cur_tx = tp->dirty_tx = 0;
5402 netdev_reset_queue(tp->dev);
5402} 5403}
5403 5404
5404static void rtl_reset_work(struct rtl8169_private *tp) 5405static void rtl_reset_work(struct rtl8169_private *tp)
@@ -5553,6 +5554,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5553 5554
5554 txd->opts2 = cpu_to_le32(opts[1]); 5555 txd->opts2 = cpu_to_le32(opts[1]);
5555 5556
5557 netdev_sent_queue(dev, skb->len);
5558
5556 wmb(); 5559 wmb();
5557 5560
5558 /* Anti gcc 2.95.3 bugware (sic) */ 5561 /* Anti gcc 2.95.3 bugware (sic) */
@@ -5647,9 +5650,16 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
5647 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); 5650 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
5648} 5651}
5649 5652
5653struct rtl_txc {
5654 int packets;
5655 int bytes;
5656};
5657
5650static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) 5658static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
5651{ 5659{
5660 struct rtl8169_stats *tx_stats = &tp->tx_stats;
5652 unsigned int dirty_tx, tx_left; 5661 unsigned int dirty_tx, tx_left;
5662 struct rtl_txc txc = { 0, 0 };
5653 5663
5654 dirty_tx = tp->dirty_tx; 5664 dirty_tx = tp->dirty_tx;
5655 smp_rmb(); 5665 smp_rmb();
@@ -5668,17 +5678,24 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
5668 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, 5678 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
5669 tp->TxDescArray + entry); 5679 tp->TxDescArray + entry);
5670 if (status & LastFrag) { 5680 if (status & LastFrag) {
5671 u64_stats_update_begin(&tp->tx_stats.syncp); 5681 struct sk_buff *skb = tx_skb->skb;
5672 tp->tx_stats.packets++; 5682
5673 tp->tx_stats.bytes += tx_skb->skb->len; 5683 txc.packets++;
5674 u64_stats_update_end(&tp->tx_stats.syncp); 5684 txc.bytes += skb->len;
5675 dev_kfree_skb(tx_skb->skb); 5685 dev_kfree_skb(skb);
5676 tx_skb->skb = NULL; 5686 tx_skb->skb = NULL;
5677 } 5687 }
5678 dirty_tx++; 5688 dirty_tx++;
5679 tx_left--; 5689 tx_left--;
5680 } 5690 }
5681 5691
5692 u64_stats_update_begin(&tx_stats->syncp);
5693 tx_stats->packets += txc.packets;
5694 tx_stats->bytes += txc.bytes;
5695 u64_stats_update_end(&tx_stats->syncp);
5696
5697 netdev_completed_queue(dev, txc.packets, txc.bytes);
5698
5682 if (tp->dirty_tx != dirty_tx) { 5699 if (tp->dirty_tx != dirty_tx) {
5683 tp->dirty_tx = dirty_tx; 5700 tp->dirty_tx = dirty_tx;
5684 /* Sync with rtl8169_start_xmit: 5701 /* Sync with rtl8169_start_xmit: