Netdev List
 help / color / mirror / Atom feed
* [PATCHSET net-next v2 00/07] Support for byte queue limits on various drivers
From: Tino Reichardt @ 2013-10-20 18:13 UTC (permalink / raw)
  To: netdev, David S. Miller

Hello,

this patchset is intended for net-next/linux-3.13.

It adds support for byte queue limits on various network drivers.

Since not all of them are fully tested by now, I added an bql_disable
module parameter, which can be used to disable the BQL code.


Any comments are welcome, thanks.
Tino Reichardt


This BQL patchset contains the following patches by now:
0001-8139too-Support-for-byte-queue-limits.patch
0002-r8169-Support-for-byte-queue-limits.patch
0003-tulip-Support-for-byte-queue-limits.patch
0004-via-rhine-Support-for-byte-queue-limits.patch
0005-via-velocity-Support-for-byte-queue-limits.patch
0006-3c59x-Support-for-byte-queue-limits.patch
0007-natsemi-Support-for-byte-queue-limits.patch

---
 drivers/net/ethernet/3com/3c59x.c           | 47 +++++++++++++++++++++++++----
 drivers/net/ethernet/dec/tulip/interrupt.c  |  4 +++
 drivers/net/ethernet/dec/tulip/tulip.h      |  1 +
 drivers/net/ethernet/dec/tulip/tulip_core.c |  9 +++++-
 drivers/net/ethernet/natsemi/natsemi.c      | 21 +++++++++++++
 drivers/net/ethernet/realtek/8139too.c      | 28 ++++++++++++++---
 drivers/net/ethernet/realtek/r8169.c        | 14 +++++++++
 drivers/net/ethernet/via/via-rhine.c        | 17 +++++++++++
 drivers/net/ethernet/via/via-velocity.c     | 18 +++++++++++
 9 files changed, 147 insertions(+), 12 deletions(-)

^ permalink raw reply

* [PATCH net-next v2 01/07] 8139too: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 18:13 UTC (permalink / raw)
  To: netdev, David S. Miller, Joe Perches, Jiri Pirko, Bill Pemberton,
	Greg Kroah-Hartman
In-Reply-To: <1382292803-18875-1-git-send-email-milky-kernel@mcmilk.de>

Changes to 8139too driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/realtek/8139too.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 3ccedeb..c17c12f 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -160,6 +160,8 @@ static int multicast_filter_limit = 32;
 /* bitmapped message enable number */
 static int debug = -1;
 
+static bool bql_disable;
+
 /*
  * Receive ring size
  * Warning: 64K ring has hardware issues and may lock up.
@@ -626,10 +628,12 @@ module_param(multicast_filter_limit, int, 0);
 module_param_array(media, int, NULL, 0);
 module_param_array(full_duplex, int, NULL, 0);
 module_param(debug, int, 0);
-MODULE_PARM_DESC (debug, "8139too bitmapped message enable number");
-MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
-MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
-MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)");
+module_param(bql_disable, bool, 0);
+MODULE_PARM_DESC(debug, "8139too bitmapped message enable number");
+MODULE_PARM_DESC(multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
+MODULE_PARM_DESC(media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
+MODULE_PARM_DESC(full_duplex, "8139too: Force full duplex for board(s) (1)");
+MODULE_PARM_DESC(bql_disable, "8139too: Disable Byte Queue Limits functionality (default: false)");
 
 static int read_eeprom (void __iomem *ioaddr, int location, int addr_len);
 static int rtl8139_open (struct net_device *dev);
@@ -1409,6 +1413,8 @@ static void rtl8139_hw_start (struct net_device *dev)
 	}
 
 	netdev_dbg(dev, "init buffer addresses\n");
+	if (likely(bql_disable == false))
+		netdev_reset_queue(dev);
 
 	/* Lock Config[01234] and BMCR register writes */
 	RTL_W8 (Cfg9346, Cfg9346_Lock);
@@ -1639,6 +1645,9 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
 	tp->cur_tx = 0;
 	tp->dirty_tx = 0;
 
+	if (likely(bql_disable == false))
+		netdev_reset_queue(tp->dev);
+
 	/* XXX account for unsent Tx packets in tp->stats.tx_dropped */
 }
 
@@ -1729,10 +1738,13 @@ static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,
 	 * to make sure that the device sees the updated data.
 	 */
 	wmb();
+	len = max_t(unsigned int, len, (unsigned int)ETH_ZLEN);
 	RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
-		   tp->tx_flag | max(len, (unsigned int)ETH_ZLEN));
+		   tp->tx_flag | len);
 
 	tp->cur_tx++;
+	if (likely(bql_disable == false))
+		netdev_sent_queue(dev, len);
 
 	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
 		netif_stop_queue (dev);
@@ -1750,6 +1762,7 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
 				  void __iomem *ioaddr)
 {
 	unsigned long dirty_tx, tx_left;
+	unsigned bytes_compl = 0, pkts_compl = 0;
 
 	assert (dev != NULL);
 	assert (ioaddr != NULL);
@@ -1792,6 +1805,8 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
 			u64_stats_update_begin(&tp->tx_stats.syncp);
 			tp->tx_stats.packets++;
 			tp->tx_stats.bytes += txstatus & 0x7ff;
+			pkts_compl++;
+			bytes_compl += txstatus & 0x7ff;
 			u64_stats_update_end(&tp->tx_stats.syncp);
 		}
 
@@ -1807,6 +1822,9 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
 	}
 #endif /* RTL8139_NDEBUG */
 
+	if (likely(bql_disable == false))
+		netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
 	/* only wake the queue if we did work, and the queue is stopped */
 	if (tp->dirty_tx != dirty_tx) {
 		tp->dirty_tx = dirty_tx;
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v2 02/07] r8169: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 18:13 UTC (permalink / raw)
  To: netdev, Realtek linux nic maintainers, Igor Maravic,
	Francois Romieu
In-Reply-To: <1382292803-18875-1-git-send-email-milky-kernel@mcmilk.de>

Changes to r8169 driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/realtek/r8169.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 3397cee..8f12145 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -313,6 +313,7 @@ MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
 static int rx_buf_sz = 16383;
 static int use_dac;
+static bool bql_disable;
 static struct {
 	u32 msg_enable;
 } debug = { -1 };
@@ -818,6 +819,9 @@ MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
 module_param(use_dac, int, 0);
 MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
+module_param(bql_disable, bool, 0);
+MODULE_PARM_DESC(bql_disable,
+	"Disable Byte Queue Limits functionality (default: false)");
 module_param_named(debug, debug.msg_enable, int, 0);
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
 MODULE_LICENSE("GPL");
@@ -5841,6 +5845,8 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp)
 {
 	rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
 	tp->cur_tx = tp->dirty_tx = 0;
+	if (likely(bql_disable == false))
+		netdev_reset_queue(tp->dev);
 }
 
 static void rtl_reset_work(struct rtl8169_private *tp)
@@ -6017,6 +6023,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 	txd->opts2 = cpu_to_le32(opts[1]);
 
 	skb_tx_timestamp(skb);
+	if (likely(bql_disable == false))
+		netdev_sent_queue(dev, skb->len);
 
 	wmb();
 
@@ -6116,6 +6124,7 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
 static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
 {
 	unsigned int dirty_tx, tx_left;
+	unsigned int pkts_compl = 0, bytes_compl = 0;
 
 	dirty_tx = tp->dirty_tx;
 	smp_rmb();
@@ -6138,6 +6147,9 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
 			tp->tx_stats.packets++;
 			tp->tx_stats.bytes += tx_skb->skb->len;
 			u64_stats_update_end(&tp->tx_stats.syncp);
+
+			bytes_compl += tx_skb->skb->len;
+			pkts_compl++;
 			dev_kfree_skb(tx_skb->skb);
 			tx_skb->skb = NULL;
 		}
@@ -6155,6 +6167,8 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
 		 * ring status.
 		 */
 		smp_mb();
+		if (likely(bql_disable == false))
+			netdev_completed_queue(dev, pkts_compl, bytes_compl);
 		if (netif_queue_stopped(dev) &&
 		    TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
 			netif_wake_queue(dev);
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v2 03/07] tulip: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 18:13 UTC (permalink / raw)
  To: netdev, Grant Grundler
In-Reply-To: <1382292803-18875-1-git-send-email-milky-kernel@mcmilk.de>

Changes to tulip driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/dec/tulip/interrupt.c  | 4 ++++
 drivers/net/ethernet/dec/tulip/tulip.h      | 1 +
 drivers/net/ethernet/dec/tulip/tulip_core.c | 9 ++++++++-
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/dec/tulip/interrupt.c b/drivers/net/ethernet/dec/tulip/interrupt.c
index 92306b3..7084267 100644
--- a/drivers/net/ethernet/dec/tulip/interrupt.c
+++ b/drivers/net/ethernet/dec/tulip/interrupt.c
@@ -532,6 +532,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
 #endif
 	unsigned int work_count = tulip_max_interrupt_work;
 	unsigned int handled = 0;
+	unsigned int bytes_compl = 0;
 
 	/* Let's see whether the interrupt really is for us */
 	csr5 = ioread32(ioaddr + CSR5);
@@ -634,6 +635,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
 						 PCI_DMA_TODEVICE);
 
 				/* Free the original skb. */
+				bytes_compl += tp->tx_buffers[entry].skb->len;
 				dev_kfree_skb_irq(tp->tx_buffers[entry].skb);
 				tp->tx_buffers[entry].skb = NULL;
 				tp->tx_buffers[entry].mapping = 0;
@@ -802,6 +804,8 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
 	}
 #endif /* CONFIG_TULIP_NAPI */
 
+	if (likely(tulip_bql_disable == false))
+		netdev_completed_queue(dev, tx, bytes_compl);
 	if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) {
 		dev->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
 	}
diff --git a/drivers/net/ethernet/dec/tulip/tulip.h b/drivers/net/ethernet/dec/tulip/tulip.h
index 38431a1..3c62870 100644
--- a/drivers/net/ethernet/dec/tulip/tulip.h
+++ b/drivers/net/ethernet/dec/tulip/tulip.h
@@ -513,6 +513,7 @@ void comet_timer(unsigned long data);
 
 /* tulip_core.c */
 extern int tulip_debug;
+extern bool tulip_bql_disable;
 extern const char * const medianame[];
 extern const char tulip_media_cap[];
 extern struct tulip_chip_table tulip_tbl[];
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index 4e8cfa2..d02eaa1 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -106,11 +106,13 @@ static int csr0 = 0x00A00000 | 0x4800;
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (4*HZ)
 
-
 MODULE_AUTHOR("The Linux Kernel Team");
 MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
+module_param(tulip_bql_disable, bool, 0);
+MODULE_PARM_DESC(tulip_bql_disable,
+	"Disable Byte Queue Limits functionality (default: false)");
 module_param(tulip_debug, int, 0);
 module_param(max_interrupt_work, int, 0);
 module_param(rx_copybreak, int, 0);
@@ -123,6 +125,7 @@ int tulip_debug = TULIP_DEBUG;
 #else
 int tulip_debug = 1;
 #endif
+bool tulip_bql_disable;
 
 static void tulip_timer(unsigned long data)
 {
@@ -703,6 +706,8 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	wmb();
 
 	tp->cur_tx++;
+	if (likely(tulip_bql_disable == false))
+		netdev_sent_queue(dev, skb->len);
 
 	/* Trigger an immediate transmit demand. */
 	iowrite32(0, tp->base_addr + CSR1);
@@ -746,6 +751,8 @@ static void tulip_clean_tx_ring(struct tulip_private *tp)
 		tp->tx_buffers[entry].skb = NULL;
 		tp->tx_buffers[entry].mapping = 0;
 	}
+	if (likely(tulip_bql_disable == false))
+		netdev_reset_queue(tp->dev);
 }
 
 static void tulip_down (struct net_device *dev)
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v2 04/07] via-rhine: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 18:13 UTC (permalink / raw)
  To: netdev, Roger Luethi
In-Reply-To: <1382292803-18875-1-git-send-email-milky-kernel@mcmilk.de>

Changes to via-rhine driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/via/via-rhine.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index bdf697b..067b4ab 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -53,6 +53,8 @@ static int rx_copybreak = 1518;
 static int rx_copybreak;
 #endif
 
+static bool bql_disable;
+
 /* Work-around for broken BIOSes: they are unable to get the chip back out of
    power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */
 static bool avoid_D3;
@@ -128,9 +130,11 @@ MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
 MODULE_LICENSE("GPL");
 
 module_param(debug, int, 0);
+module_param(bql_disable, bool, 0);
 module_param(rx_copybreak, int, 0);
 module_param(avoid_D3, bool, 0);
 MODULE_PARM_DESC(debug, "VIA Rhine debug message flags");
+MODULE_PARM_DESC(bql_disable, "Disable Byte Queue Limits functionality (default: false)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
 
@@ -1220,6 +1224,8 @@ static void alloc_tbufs(struct net_device* dev)
 	}
 	rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma);
 
+	if (likely(bql_disable == false))
+		netdev_reset_queue(dev);
 }
 
 static void free_tbufs(struct net_device* dev)
@@ -1719,6 +1725,8 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
 	/* lock eth irq */
 	wmb();
 	rp->tx_ring[entry].tx_status |= cpu_to_le32(DescOwn);
+	if (likely(bql_disable == false))
+		netdev_sent_queue(dev, skb->len);
 	wmb();
 
 	rp->cur_tx++;
@@ -1783,6 +1791,7 @@ static void rhine_tx(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
 	int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE;
+	unsigned int pkts_compl = 0, bytes_compl = 0;
 
 	/* find and cleanup dirty tx descriptors */
 	while (rp->dirty_tx != rp->cur_tx) {
@@ -1830,10 +1839,18 @@ static void rhine_tx(struct net_device *dev)
 					 rp->tx_skbuff[entry]->len,
 					 PCI_DMA_TODEVICE);
 		}
+
+		bytes_compl += rp->tx_skbuff[entry]->len;
+		pkts_compl++;
 		dev_kfree_skb(rp->tx_skbuff[entry]);
+
 		rp->tx_skbuff[entry] = NULL;
 		entry = (++rp->dirty_tx) % TX_RING_SIZE;
 	}
+
+	if (likely(bql_disable == false))
+		netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
 	if ((rp->cur_tx - rp->dirty_tx) < TX_QUEUE_LEN - 4)
 		netif_wake_queue(dev);
 }
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v2 05/07] via-velocity: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 18:13 UTC (permalink / raw)
  To: netdev, Francois Romieu
In-Reply-To: <1382292803-18875-1-git-send-email-milky-kernel@mcmilk.de>

Changes to via-velocity driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/via/via-velocity.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index d022bf9..b084404 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -1,3 +1,4 @@
+
 /*
  * This code is derived from the VIA reference driver (copyright message
  * below) provided to Red Hat by VIA Networking Technologies, Inc. for
@@ -368,6 +369,11 @@ static int rx_copybreak = 200;
 module_param(rx_copybreak, int, 0644);
 MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
 
+static bool bql_disable;
+module_param(bql_disable, bool, 0);
+MODULE_PARM_DESC(bql_disable,
+	"Disable Byte Queue Limits functionality (default: false)");
+
 /*
  *	Internal board variants. At the moment we have only one
  */
@@ -1751,6 +1757,9 @@ static void velocity_free_tx_buf(struct velocity_info *vptr,
 					le16_to_cpu(pktlen), DMA_TO_DEVICE);
 		}
 	}
+
+	if (likely(bql_disable == false))
+		netdev_reset_queue(vptr->netdev);
 	dev_kfree_skb_irq(skb);
 	tdinfo->skb = NULL;
 }
@@ -1915,6 +1924,7 @@ static int velocity_tx_srv(struct velocity_info *vptr)
 	int works = 0;
 	struct velocity_td_info *tdinfo;
 	struct net_device_stats *stats = &vptr->netdev->stats;
+	unsigned int pkts_compl = 0, bytes_compl = 0;
 
 	for (qnum = 0; qnum < vptr->tx.numq; qnum++) {
 		for (idx = vptr->tx.tail[qnum]; vptr->tx.used[qnum] > 0;
@@ -1946,6 +1956,8 @@ static int velocity_tx_srv(struct velocity_info *vptr)
 			} else {
 				stats->tx_packets++;
 				stats->tx_bytes += tdinfo->skb->len;
+				pkts_compl++;
+				bytes_compl += tdinfo->skb->len;
 			}
 			velocity_free_tx_buf(vptr, tdinfo, td);
 			vptr->tx.used[qnum]--;
@@ -1955,6 +1967,10 @@ static int velocity_tx_srv(struct velocity_info *vptr)
 		if (AVAIL_TD(vptr, qnum) < 1)
 			full = 1;
 	}
+
+	if (likely(bql_disable == false))
+		netdev_completed_queue(vptr->netdev, pkts_compl, bytes_compl);
+
 	/*
 	 *	Look to see if we should kick the transmit network
 	 *	layer for more work.
@@ -2641,6 +2657,8 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
 	td_ptr->td_buf[0].size |= TD_QUEUE;
 	mac_tx_queue_wake(vptr->mac_regs, qnum);
 
+	if (likely(bql_disable == false))
+		netdev_sent_queue(vptr->netdev, skb->len);
 	spin_unlock_irqrestore(&vptr->lock, flags);
 out:
 	return NETDEV_TX_OK;
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v2 06/07] 3c59x: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 18:13 UTC (permalink / raw)
  To: netdev, Steffen Klassert
In-Reply-To: <1382292803-18875-1-git-send-email-milky-kernel@mcmilk.de>

Changes to 3c59x driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/3com/3c59x.c | 47 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 41 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index ad5272b..6a7b77d 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -795,6 +795,7 @@ static int global_options = -1;
 static int global_full_duplex = -1;
 static int global_enable_wol = -1;
 static int global_use_mmio = -1;
+static bool bql_disable;
 
 /* Variables to work-around the Compaq PCI BIOS32 problem. */
 static int compaq_ioaddr, compaq_irq, compaq_device_id = 0x5900;
@@ -819,6 +820,8 @@ module_param(compaq_device_id, int, 0);
 module_param(watchdog, int, 0);
 module_param(global_use_mmio, int, 0);
 module_param_array(use_mmio, int, NULL, 0);
+module_param(bql_disable, bool, 0);
+
 MODULE_PARM_DESC(debug, "3c59x debug level (0-6)");
 MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex");
 MODULE_PARM_DESC(global_options, "3c59x: same as options, but applies to all NICs if options is unset");
@@ -836,6 +839,7 @@ MODULE_PARM_DESC(compaq_device_id, "3c59x PCI device ID (Compaq BIOS problem wor
 MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds");
 MODULE_PARM_DESC(global_use_mmio, "3c59x: same as use_mmio, but applies to all NICs if options is unset");
 MODULE_PARM_DESC(use_mmio, "3c59x: use memory-mapped PCI I/O resource (0-1)");
+MODULE_PARM_DESC(bql_disable, "3c59x: Disable Byte Queue Limits functionality (default: false)");
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void poll_vortex(struct net_device *dev)
@@ -1726,6 +1730,9 @@ vortex_up(struct net_device *dev)
 	iowrite16(vp->intr_enable, ioaddr + EL3_CMD);
 	if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
 		iowrite32(0x8000, vp->cb_fn_base + 4);
+
+	if (likely(bql_disable == false))
+		netdev_reset_queue(dev);
 	netif_start_queue (dev);
 err_out:
 	return err;
@@ -2080,10 +2087,15 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		spin_unlock_irq(&vp->window_lock);
 		vp->tx_skb = skb;
 		iowrite16(StartDMADown, ioaddr + EL3_CMD);
+		if (likely(bql_disable == false))
+			netdev_sent_queue(dev, len);
 		/* netif_wake_queue() will be called at the DMADone interrupt. */
 	} else {
 		/* ... and the packet rounded to a doubleword. */
-		iowrite32_rep(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+		int len = (skb->len + 3) >> 2;
+		iowrite32_rep(ioaddr + TX_FIFO, skb->data, len);
+		if (likely(bql_disable == false))
+			netdev_sent_queue(dev, len);
 		dev_kfree_skb (skb);
 		if (ioread16(ioaddr + TxFree) > 1536) {
 			netif_start_queue (dev);	/* AKPM: redundant? */
@@ -2094,7 +2106,6 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		}
 	}
 
-
 	/* Clear the Tx status stack. */
 	{
 		int tx_status;
@@ -2164,12 +2175,14 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data,
 										skb->len, PCI_DMA_TODEVICE));
 		vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb->len | LAST_FRAG);
+		netdev_sent_queue(dev, skb->len);
 	} else {
-		int i;
+		int i, len;
 
 		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data,
 										skb_headlen(skb), PCI_DMA_TODEVICE));
 		vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb_headlen(skb));
+		len = skb_headlen(skb);
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -2180,16 +2193,21 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
 						(void *)skb_frag_address(frag),
 						skb_frag_size(frag), PCI_DMA_TODEVICE));
 
-			if (i == skb_shinfo(skb)->nr_frags-1)
+			if (i == skb_shinfo(skb)->nr_frags - 1) {
 					vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag)|LAST_FRAG);
-			else
+					len += skb_frag_size(frag) | LAST_FRAG;
+			} else {
 					vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag));
+					len += skb_frag_size(frag);
+			}
 		}
+		netdev_sent_queue(dev, len);
 	}
 #else
 	vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE));
 	vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
 	vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
+	netdev_sent_queue(dev, skb->len | LAST_FRAG);
 #endif
 
 	spin_lock_irqsave(&vp->lock, flags);
@@ -2234,6 +2252,7 @@ vortex_interrupt(int irq, void *dev_id)
 	int status;
 	int work_done = max_interrupt_work;
 	int handled = 0;
+	unsigned bytes_compl = 0, pkts_compl = 0;
 
 	ioaddr = vp->ioaddr;
 	spin_lock(&vp->lock);
@@ -2279,8 +2298,12 @@ vortex_interrupt(int irq, void *dev_id)
 
 		if (status & DMADone) {
 			if (ioread16(ioaddr + Wn7_MasterStatus) & 0x1000) {
+				int len;
 				iowrite16(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
-				pci_unmap_single(VORTEX_PCI(vp), vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE);
+				len = (vp->tx_skb->len + 3) & ~3;
+				pci_unmap_single(VORTEX_PCI(vp), vp->tx_skb_dma, len, PCI_DMA_TODEVICE);
+				bytes_compl += len;
+				pkts_compl++;
 				dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */
 				if (ioread16(ioaddr + TxFree) > 1536) {
 					/*
@@ -2327,6 +2350,9 @@ vortex_interrupt(int irq, void *dev_id)
 
 	spin_unlock(&vp->window_lock);
 
+	if (likely(bql_disable == false))
+		netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
 	if (vortex_debug > 4)
 		pr_debug("%s: exiting interrupt, status %4.4x.\n",
 			   dev->name, status);
@@ -2348,6 +2374,7 @@ boomerang_interrupt(int irq, void *dev_id)
 	void __iomem *ioaddr;
 	int status;
 	int work_done = max_interrupt_work;
+	unsigned bytes_compl = 0, pkts_compl = 0;
 
 	ioaddr = vp->ioaddr;
 
@@ -2420,6 +2447,8 @@ boomerang_interrupt(int irq, void *dev_id)
 					pci_unmap_single(VORTEX_PCI(vp),
 						le32_to_cpu(vp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE);
 #endif
+					bytes_compl += skb->len;
+					pkts_compl++;
 					dev_kfree_skb_irq(skb);
 					vp->tx_skbuff[entry] = NULL;
 				} else {
@@ -2467,6 +2496,10 @@ boomerang_interrupt(int irq, void *dev_id)
 handler_exit:
 	vp->handling_irq = 0;
 	spin_unlock(&vp->lock);
+
+	if (likely(bql_disable == false))
+		netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
 	return IRQ_HANDLED;
 }
 
@@ -2660,6 +2693,8 @@ vortex_down(struct net_device *dev, int final_down)
 	struct vortex_private *vp = netdev_priv(dev);
 	void __iomem *ioaddr = vp->ioaddr;
 
+	if (likely(bql_disable == false))
+		netdev_reset_queue(dev);
 	netif_stop_queue (dev);
 
 	del_timer_sync(&vp->rx_oom_timer);
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v2 07/07] natsemi: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 18:13 UTC (permalink / raw)
  To: netdev, Greg Kroah-Hartman, David S. Miller, Jiri Pirko,
	Bill Pemberton
In-Reply-To: <1382292803-18875-1-git-send-email-milky-kernel@mcmilk.de>

Changes to natsemi driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/natsemi/natsemi.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
index 7a5e295..1f6efbc 100644
--- a/drivers/net/ethernet/natsemi/natsemi.c
+++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -71,6 +71,8 @@
 				 NETIF_MSG_TX_ERR)
 static int debug = -1;
 
+static bool bql_disable;
+
 static int mtu;
 
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
@@ -139,12 +141,15 @@ MODULE_LICENSE("GPL");
 
 module_param(mtu, int, 0);
 module_param(debug, int, 0);
+module_param(bql_disable, bool, 0);
 module_param(rx_copybreak, int, 0);
 module_param(dspcfg_workaround, int, 0);
 module_param_array(options, int, NULL, 0);
 module_param_array(full_duplex, int, NULL, 0);
 MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)");
 MODULE_PARM_DESC(debug, "DP8381x default debug level");
+MODULE_PARM_DESC(bql_disable,
+	"Disable Byte Queue Limits functionality (default: false)");
 MODULE_PARM_DESC(rx_copybreak,
 	"DP8381x copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(dspcfg_workaround, "DP8381x: control DspCfg workaround");
@@ -1974,6 +1979,9 @@ static void init_ring(struct net_device *dev)
 		np->tx_ring[i].cmd_status = 0;
 	}
 
+	if (likely(bql_disable == false))
+		netdev_reset_queue(dev);
+
 	/* 2) RX ring */
 	np->dirty_rx = 0;
 	np->cur_rx = RX_RING_SIZE;
@@ -2012,6 +2020,9 @@ static void drain_tx(struct net_device *dev)
 		}
 		np->tx_skbuff[i] = NULL;
 	}
+
+	if (likely(bql_disable == false))
+		netdev_reset_queue(dev);
 }
 
 static void drain_rx(struct net_device *dev)
@@ -2116,6 +2127,9 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
 		dev_kfree_skb_irq(skb);
 		dev->stats.tx_dropped++;
 	}
+
+	if (likely(bql_disable == false))
+		netdev_sent_queue(dev, skb->len);
 	spin_unlock_irqrestore(&np->lock, flags);
 
 	if (netif_msg_tx_queued(np)) {
@@ -2128,6 +2142,7 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
 static void netdev_tx_done(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	unsigned bytes_compl = 0, pkts_compl = 0;
 
 	for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
 		int entry = np->dirty_tx % TX_RING_SIZE;
@@ -2158,9 +2173,15 @@ static void netdev_tx_done(struct net_device *dev)
 					np->tx_skbuff[entry]->len,
 					PCI_DMA_TODEVICE);
 		/* Free the original skb. */
+		bytes_compl += np->tx_skbuff[entry]->len;
+		pkts_compl++;
 		dev_kfree_skb_irq(np->tx_skbuff[entry]);
 		np->tx_skbuff[entry] = NULL;
 	}
+
+	if (likely(bql_disable == false))
+		netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
 	if (netif_queue_stopped(dev) &&
 	    np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) {
 		/* The ring is no longer full, wake queue. */
-- 
1.8.4.1

^ permalink raw reply related

* Re: kernel BUG at net/core/skbuff.c:1048!
From: Hannes Frederic Sowa @ 2013-10-20 18:25 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Wim Vandersmissen, netdev, kernelspam
In-Reply-To: <20131005100105.GA2457@macbook.localnet>

Hi Patrick!

On Sat, Oct 05, 2013 at 11:01:05AM +0100, Patrick McHardy wrote:
> On Fri, Oct 04, 2013 at 11:35:55AM +0200, Wim Vandersmissen wrote:
> > Hi,
> > 
> > Got the following BUG when using ipv6 netfilter/conntrack/ipv6
> > forwarding and traffic flowing.
> > 
> > No issues in 3.4.x, but triggered in 3.10.x (introduced in 3.7)
> 
> Please also send me your 3.10.x config and the ip6tables rules you're
> using.
> 
> Are you actually using IPv6 NAT? 

Maybe the same bug was hit by someone else and was reported in kernel
bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=63331

I added him in Cc.

Greetings,

  Hannes

^ permalink raw reply

* Re: [PATCH net 2/3] ipv6: fill rt6i_gateway with nexthop address
From: Hannes Frederic Sowa @ 2013-10-20 18:33 UTC (permalink / raw)
  To: Julian Anastasov
  Cc: David Miller, netdev, netfilter-devel, lvs-devel,
	Hideaki YOSHIFUJI
In-Reply-To: <1382272985-1528-3-git-send-email-ja@ssi.bg>

On Sun, Oct 20, 2013 at 03:43:04PM +0300, Julian Anastasov wrote:
> Make sure rt6i_gateway contains nexthop information in
> all routes returned from lookup or when routes are directly
> attached to skb for generated ICMP packets.
> 
> The effect of this patch should be a faster version of
> rt6_nexthop() and the consideration of local addresses as
> nexthop.
> 
> Signed-off-by: Julian Anastasov <ja@ssi.bg>
> ---
>  include/net/ip6_route.h | 6 ++----
>  net/ipv6/ip6_output.c   | 4 ++--
>  net/ipv6/route.c        | 8 ++++++--
>  3 files changed, 10 insertions(+), 8 deletions(-)
> 
> diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
> index 481404a..2b786b7 100644
> --- a/include/net/ip6_route.h
> +++ b/include/net/ip6_route.h
> @@ -194,11 +194,9 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
>  	       skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
>  }
>  
> -static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, struct in6_addr *dest)
> +static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt)
>  {
> -	if (rt->rt6i_flags & RTF_GATEWAY || !ipv6_addr_any(&rt->rt6i_gateway))
> -		return &rt->rt6i_gateway;
> -	return dest;
> +	return &rt->rt6i_gateway;
>  }
>  

Hm, looks good. Will test is soon.

One small remark:

Maybe we can kill rt6_nexthop completly and use rt6i_gateway directly so a
reader does not have to lookup this function.

Thanks,

  Hannes


^ permalink raw reply

* Re: kernel BUG at net/core/skbuff.c:1048!
From: Patrick McHardy @ 2013-10-20 18:33 UTC (permalink / raw)
  To: Wim Vandersmissen, netdev, kernelspam
In-Reply-To: <20131020182523.GF27787@order.stressinduktion.org>

On Sun, Oct 20, 2013 at 08:25:23PM +0200, Hannes Frederic Sowa wrote:
> Hi Patrick!
> 
> On Sat, Oct 05, 2013 at 11:01:05AM +0100, Patrick McHardy wrote:
> > On Fri, Oct 04, 2013 at 11:35:55AM +0200, Wim Vandersmissen wrote:
> > > Hi,
> > > 
> > > Got the following BUG when using ipv6 netfilter/conntrack/ipv6
> > > forwarding and traffic flowing.
> > > 
> > > No issues in 3.4.x, but triggered in 3.10.x (introduced in 3.7)
> > 
> > Please also send me your 3.10.x config and the ip6tables rules you're
> > using.
> > 
> > Are you actually using IPv6 NAT? 
> 
> Maybe the same bug was hit by someone else and was reported in kernel
> bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=63331
> 
> I added him in Cc.

Thanks, didn't really get to it yet. The problem is obviously that we're
rerouting the individual fragments, during which their headroom gets
expanded while a reference to them is held by the reassembled skb. Just
not sure yet how to fix it.

^ permalink raw reply

* Re: [PATCH net-next v2 01/07] 8139too: Support for byte queue limits
From: Joe Perches @ 2013-10-20 18:51 UTC (permalink / raw)
  To: Tino Reichardt
  Cc: netdev, David S. Miller, Jiri Pirko, Bill Pemberton,
	Greg Kroah-Hartman
In-Reply-To: <1382292803-18875-2-git-send-email-milky-kernel@mcmilk.de>

On Sun, 2013-10-20 at 20:13 +0200, Tino Reichardt wrote:
> Changes to 8139too driver to use byte queue limits.
[]
> diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
[]
> @@ -1409,6 +1413,8 @@ static void rtl8139_hw_start (struct net_device *dev)
[]
>  	netdev_dbg(dev, "init buffer addresses\n");
> +	if (likely(bql_disable == false))
> +		netdev_reset_queue(dev);

Much prefer:

	if (unlikely(bql_disable))

> @@ -1639,6 +1645,9 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
[]
> +	if (likely(bql_disable == false))
> +		netdev_reset_queue(tp->dev);

etc...

^ permalink raw reply

* Re: [PATCH net-next v2 01/07] 8139too: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 19:14 UTC (permalink / raw)
  To: netdev
In-Reply-To: <1382295089.2041.42.camel@joe-AO722>

* Joe Perches <joe@perches.com> wrote:
> On Sun, 2013-10-20 at 20:13 +0200, Tino Reichardt wrote:
> > Changes to 8139too driver to use byte queue limits.
> []
> > diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
> []
> > @@ -1409,6 +1413,8 @@ static void rtl8139_hw_start (struct net_device *dev)
> []
> >  	netdev_dbg(dev, "init buffer addresses\n");
> > +	if (likely(bql_disable == false))
> > +		netdev_reset_queue(dev);
> 
> Much prefer:
> 
> 	if (unlikely(bql_disable))

Okay, i will resend an updated v3 patchset.



-- 
Best regards, TR

^ permalink raw reply

* [PATCHSET net-next v3 00/07] Support for byte queue limits on various drivers
From: Tino Reichardt @ 2013-10-20 19:23 UTC (permalink / raw)
  To: netdev, David S. Miller

Hello again,

this patchset is intended for net-next/linux-3.13.

It adds support for byte queue limits on various network drivers.

Since not all of them are fully tested by now, I added an bql_disable
module parameter, which can be used to disable the BQL code.

"if (likely(bql_disable == false))" was replaced by
"if (unlikely(bql_disable))" ...


Any comments are welcome, thanks.
Tino Reichardt

This BQL patchset contains the following patches by now:
0001-8139too-Support-for-byte-queue-limits.patch
0002-r8169-Support-for-byte-queue-limits.patch
0003-tulip-Support-for-byte-queue-limits.patch
0004-via-rhine-Support-for-byte-queue-limits.patch
0005-via-velocity-Support-for-byte-queue-limits.patch
0006-3c59x-Support-for-byte-queue-limits.patch
0007-natsemi-Support-for-byte-queue-limits.patch

---
 drivers/net/ethernet/3com/3c59x.c           | 47 +++++++++++++++++++++++++----
 drivers/net/ethernet/dec/tulip/interrupt.c  |  4 +++
 drivers/net/ethernet/dec/tulip/tulip.h      |  1 +
 drivers/net/ethernet/dec/tulip/tulip_core.c |  9 +++++-
 drivers/net/ethernet/natsemi/natsemi.c      | 21 +++++++++++++
 drivers/net/ethernet/realtek/8139too.c      | 28 ++++++++++++++---
 drivers/net/ethernet/realtek/r8169.c        | 14 +++++++++
 drivers/net/ethernet/via/via-rhine.c        | 17 +++++++++++
 drivers/net/ethernet/via/via-velocity.c     | 18 +++++++++++
 9 files changed, 147 insertions(+), 12 deletions(-)

^ permalink raw reply

* [PATCH net-next v3 01/07] 8139too: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 19:23 UTC (permalink / raw)
  To: netdev, David S. Miller, Joe Perches, Jiri Pirko, Bill Pemberton,
	Greg Kroah-Hartman
In-Reply-To: <1382296991-20289-1-git-send-email-milky-kernel@mcmilk.de>

Changes to 8139too driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/realtek/8139too.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 3ccedeb..c17c12f 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -160,6 +160,8 @@ static int multicast_filter_limit = 32;
 /* bitmapped message enable number */
 static int debug = -1;
 
+static bool bql_disable;
+
 /*
  * Receive ring size
  * Warning: 64K ring has hardware issues and may lock up.
@@ -626,10 +628,12 @@ module_param(multicast_filter_limit, int, 0);
 module_param_array(media, int, NULL, 0);
 module_param_array(full_duplex, int, NULL, 0);
 module_param(debug, int, 0);
-MODULE_PARM_DESC (debug, "8139too bitmapped message enable number");
-MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
-MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
-MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)");
+module_param(bql_disable, bool, 0);
+MODULE_PARM_DESC(debug, "8139too bitmapped message enable number");
+MODULE_PARM_DESC(multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
+MODULE_PARM_DESC(media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
+MODULE_PARM_DESC(full_duplex, "8139too: Force full duplex for board(s) (1)");
+MODULE_PARM_DESC(bql_disable, "8139too: Disable Byte Queue Limits functionality (default: false)");
 
 static int read_eeprom (void __iomem *ioaddr, int location, int addr_len);
 static int rtl8139_open (struct net_device *dev);
@@ -1409,6 +1413,8 @@ static void rtl8139_hw_start (struct net_device *dev)
 	}
 
 	netdev_dbg(dev, "init buffer addresses\n");
+	if (unlikely(bql_disable))
+		netdev_reset_queue(dev);
 
 	/* Lock Config[01234] and BMCR register writes */
 	RTL_W8 (Cfg9346, Cfg9346_Lock);
@@ -1639,6 +1645,9 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
 	tp->cur_tx = 0;
 	tp->dirty_tx = 0;
 
+	if (unlikely(bql_disable))
+		netdev_reset_queue(tp->dev);
+
 	/* XXX account for unsent Tx packets in tp->stats.tx_dropped */
 }
 
@@ -1729,10 +1738,13 @@ static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,
 	 * to make sure that the device sees the updated data.
 	 */
 	wmb();
+	len = max_t(unsigned int, len, (unsigned int)ETH_ZLEN);
 	RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
-		   tp->tx_flag | max(len, (unsigned int)ETH_ZLEN));
+		   tp->tx_flag | len);
 
 	tp->cur_tx++;
+	if (unlikely(bql_disable))
+		netdev_sent_queue(dev, len);
 
 	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
 		netif_stop_queue (dev);
@@ -1750,6 +1762,7 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
 				  void __iomem *ioaddr)
 {
 	unsigned long dirty_tx, tx_left;
+	unsigned bytes_compl = 0, pkts_compl = 0;
 
 	assert (dev != NULL);
 	assert (ioaddr != NULL);
@@ -1792,6 +1805,8 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
 			u64_stats_update_begin(&tp->tx_stats.syncp);
 			tp->tx_stats.packets++;
 			tp->tx_stats.bytes += txstatus & 0x7ff;
+			pkts_compl++;
+			bytes_compl += txstatus & 0x7ff;
 			u64_stats_update_end(&tp->tx_stats.syncp);
 		}
 
@@ -1807,6 +1822,9 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
 	}
 #endif /* RTL8139_NDEBUG */
 
+	if (unlikely(bql_disable))
+		netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
 	/* only wake the queue if we did work, and the queue is stopped */
 	if (tp->dirty_tx != dirty_tx) {
 		tp->dirty_tx = dirty_tx;
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v3 02/07] r8169: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 19:23 UTC (permalink / raw)
  To: netdev, Realtek linux nic maintainers, Igor Maravic,
	Francois Romieu
In-Reply-To: <1382296991-20289-1-git-send-email-milky-kernel@mcmilk.de>

Changes to r8169 driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/realtek/r8169.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 3397cee..8f12145 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -313,6 +313,7 @@ MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
 static int rx_buf_sz = 16383;
 static int use_dac;
+static bool bql_disable;
 static struct {
 	u32 msg_enable;
 } debug = { -1 };
@@ -818,6 +819,9 @@ MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
 module_param(use_dac, int, 0);
 MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
+module_param(bql_disable, bool, 0);
+MODULE_PARM_DESC(bql_disable,
+	"Disable Byte Queue Limits functionality (default: false)");
 module_param_named(debug, debug.msg_enable, int, 0);
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
 MODULE_LICENSE("GPL");
@@ -5841,6 +5845,8 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp)
 {
 	rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
 	tp->cur_tx = tp->dirty_tx = 0;
+	if (unlikely(bql_disable))
+		netdev_reset_queue(tp->dev);
 }
 
 static void rtl_reset_work(struct rtl8169_private *tp)
@@ -6017,6 +6023,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 	txd->opts2 = cpu_to_le32(opts[1]);
 
 	skb_tx_timestamp(skb);
+	if (unlikely(bql_disable))
+		netdev_sent_queue(dev, skb->len);
 
 	wmb();
 
@@ -6116,6 +6124,7 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
 static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
 {
 	unsigned int dirty_tx, tx_left;
+	unsigned int pkts_compl = 0, bytes_compl = 0;
 
 	dirty_tx = tp->dirty_tx;
 	smp_rmb();
@@ -6138,6 +6147,9 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
 			tp->tx_stats.packets++;
 			tp->tx_stats.bytes += tx_skb->skb->len;
 			u64_stats_update_end(&tp->tx_stats.syncp);
+
+			bytes_compl += tx_skb->skb->len;
+			pkts_compl++;
 			dev_kfree_skb(tx_skb->skb);
 			tx_skb->skb = NULL;
 		}
@@ -6155,6 +6167,8 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
 		 * ring status.
 		 */
 		smp_mb();
+		if (unlikely(bql_disable))
+			netdev_completed_queue(dev, pkts_compl, bytes_compl);
 		if (netif_queue_stopped(dev) &&
 		    TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
 			netif_wake_queue(dev);
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v3 03/07] tulip: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 19:23 UTC (permalink / raw)
  To: netdev, Grant Grundler
In-Reply-To: <1382296991-20289-1-git-send-email-milky-kernel@mcmilk.de>

Changes to tulip driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/dec/tulip/interrupt.c  | 4 ++++
 drivers/net/ethernet/dec/tulip/tulip.h      | 1 +
 drivers/net/ethernet/dec/tulip/tulip_core.c | 9 ++++++++-
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/dec/tulip/interrupt.c b/drivers/net/ethernet/dec/tulip/interrupt.c
index 92306b3..7084267 100644
--- a/drivers/net/ethernet/dec/tulip/interrupt.c
+++ b/drivers/net/ethernet/dec/tulip/interrupt.c
@@ -532,6 +532,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
 #endif
 	unsigned int work_count = tulip_max_interrupt_work;
 	unsigned int handled = 0;
+	unsigned int bytes_compl = 0;
 
 	/* Let's see whether the interrupt really is for us */
 	csr5 = ioread32(ioaddr + CSR5);
@@ -634,6 +635,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
 						 PCI_DMA_TODEVICE);
 
 				/* Free the original skb. */
+				bytes_compl += tp->tx_buffers[entry].skb->len;
 				dev_kfree_skb_irq(tp->tx_buffers[entry].skb);
 				tp->tx_buffers[entry].skb = NULL;
 				tp->tx_buffers[entry].mapping = 0;
@@ -802,6 +804,8 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
 	}
 #endif /* CONFIG_TULIP_NAPI */
 
+	if (likely(tulip_bql_disable == false))
+		netdev_completed_queue(dev, tx, bytes_compl);
 	if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) {
 		dev->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
 	}
diff --git a/drivers/net/ethernet/dec/tulip/tulip.h b/drivers/net/ethernet/dec/tulip/tulip.h
index 38431a1..3c62870 100644
--- a/drivers/net/ethernet/dec/tulip/tulip.h
+++ b/drivers/net/ethernet/dec/tulip/tulip.h
@@ -513,6 +513,7 @@ void comet_timer(unsigned long data);
 
 /* tulip_core.c */
 extern int tulip_debug;
+extern bool tulip_bql_disable;
 extern const char * const medianame[];
 extern const char tulip_media_cap[];
 extern struct tulip_chip_table tulip_tbl[];
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index 4e8cfa2..d02eaa1 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -106,11 +106,13 @@ static int csr0 = 0x00A00000 | 0x4800;
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (4*HZ)
 
-
 MODULE_AUTHOR("The Linux Kernel Team");
 MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
+module_param(tulip_bql_disable, bool, 0);
+MODULE_PARM_DESC(tulip_bql_disable,
+	"Disable Byte Queue Limits functionality (default: false)");
 module_param(tulip_debug, int, 0);
 module_param(max_interrupt_work, int, 0);
 module_param(rx_copybreak, int, 0);
@@ -123,6 +125,7 @@ int tulip_debug = TULIP_DEBUG;
 #else
 int tulip_debug = 1;
 #endif
+bool tulip_bql_disable;
 
 static void tulip_timer(unsigned long data)
 {
@@ -703,6 +706,8 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	wmb();
 
 	tp->cur_tx++;
+	if (likely(tulip_bql_disable == false))
+		netdev_sent_queue(dev, skb->len);
 
 	/* Trigger an immediate transmit demand. */
 	iowrite32(0, tp->base_addr + CSR1);
@@ -746,6 +751,8 @@ static void tulip_clean_tx_ring(struct tulip_private *tp)
 		tp->tx_buffers[entry].skb = NULL;
 		tp->tx_buffers[entry].mapping = 0;
 	}
+	if (likely(tulip_bql_disable == false))
+		netdev_reset_queue(tp->dev);
 }
 
 static void tulip_down (struct net_device *dev)
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v3 04/07] via-rhine: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 19:23 UTC (permalink / raw)
  To: netdev, Roger Luethi
In-Reply-To: <1382296991-20289-1-git-send-email-milky-kernel@mcmilk.de>

Changes to via-rhine driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/via/via-rhine.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index bdf697b..067b4ab 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -53,6 +53,8 @@ static int rx_copybreak = 1518;
 static int rx_copybreak;
 #endif
 
+static bool bql_disable;
+
 /* Work-around for broken BIOSes: they are unable to get the chip back out of
    power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */
 static bool avoid_D3;
@@ -128,9 +130,11 @@ MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
 MODULE_LICENSE("GPL");
 
 module_param(debug, int, 0);
+module_param(bql_disable, bool, 0);
 module_param(rx_copybreak, int, 0);
 module_param(avoid_D3, bool, 0);
 MODULE_PARM_DESC(debug, "VIA Rhine debug message flags");
+MODULE_PARM_DESC(bql_disable, "Disable Byte Queue Limits functionality (default: false)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
 
@@ -1220,6 +1224,8 @@ static void alloc_tbufs(struct net_device* dev)
 	}
 	rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma);
 
+	if (unlikely(bql_disable))
+		netdev_reset_queue(dev);
 }
 
 static void free_tbufs(struct net_device* dev)
@@ -1719,6 +1725,8 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
 	/* lock eth irq */
 	wmb();
 	rp->tx_ring[entry].tx_status |= cpu_to_le32(DescOwn);
+	if (unlikely(bql_disable))
+		netdev_sent_queue(dev, skb->len);
 	wmb();
 
 	rp->cur_tx++;
@@ -1783,6 +1791,7 @@ static void rhine_tx(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
 	int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE;
+	unsigned int pkts_compl = 0, bytes_compl = 0;
 
 	/* find and cleanup dirty tx descriptors */
 	while (rp->dirty_tx != rp->cur_tx) {
@@ -1830,10 +1839,18 @@ static void rhine_tx(struct net_device *dev)
 					 rp->tx_skbuff[entry]->len,
 					 PCI_DMA_TODEVICE);
 		}
+
+		bytes_compl += rp->tx_skbuff[entry]->len;
+		pkts_compl++;
 		dev_kfree_skb(rp->tx_skbuff[entry]);
+
 		rp->tx_skbuff[entry] = NULL;
 		entry = (++rp->dirty_tx) % TX_RING_SIZE;
 	}
+
+	if (unlikely(bql_disable))
+		netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
 	if ((rp->cur_tx - rp->dirty_tx) < TX_QUEUE_LEN - 4)
 		netif_wake_queue(dev);
 }
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v3 05/07] via-velocity: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 19:23 UTC (permalink / raw)
  To: netdev, Francois Romieu
In-Reply-To: <1382296991-20289-1-git-send-email-milky-kernel@mcmilk.de>

Changes to via-velocity driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/via/via-velocity.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index d022bf9..b084404 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -1,3 +1,4 @@
+
 /*
  * This code is derived from the VIA reference driver (copyright message
  * below) provided to Red Hat by VIA Networking Technologies, Inc. for
@@ -368,6 +369,11 @@ static int rx_copybreak = 200;
 module_param(rx_copybreak, int, 0644);
 MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
 
+static bool bql_disable;
+module_param(bql_disable, bool, 0);
+MODULE_PARM_DESC(bql_disable,
+	"Disable Byte Queue Limits functionality (default: false)");
+
 /*
  *	Internal board variants. At the moment we have only one
  */
@@ -1751,6 +1757,9 @@ static void velocity_free_tx_buf(struct velocity_info *vptr,
 					le16_to_cpu(pktlen), DMA_TO_DEVICE);
 		}
 	}
+
+	if (unlikely(bql_disable))
+		netdev_reset_queue(vptr->netdev);
 	dev_kfree_skb_irq(skb);
 	tdinfo->skb = NULL;
 }
@@ -1915,6 +1924,7 @@ static int velocity_tx_srv(struct velocity_info *vptr)
 	int works = 0;
 	struct velocity_td_info *tdinfo;
 	struct net_device_stats *stats = &vptr->netdev->stats;
+	unsigned int pkts_compl = 0, bytes_compl = 0;
 
 	for (qnum = 0; qnum < vptr->tx.numq; qnum++) {
 		for (idx = vptr->tx.tail[qnum]; vptr->tx.used[qnum] > 0;
@@ -1946,6 +1956,8 @@ static int velocity_tx_srv(struct velocity_info *vptr)
 			} else {
 				stats->tx_packets++;
 				stats->tx_bytes += tdinfo->skb->len;
+				pkts_compl++;
+				bytes_compl += tdinfo->skb->len;
 			}
 			velocity_free_tx_buf(vptr, tdinfo, td);
 			vptr->tx.used[qnum]--;
@@ -1955,6 +1967,10 @@ static int velocity_tx_srv(struct velocity_info *vptr)
 		if (AVAIL_TD(vptr, qnum) < 1)
 			full = 1;
 	}
+
+	if (unlikely(bql_disable))
+		netdev_completed_queue(vptr->netdev, pkts_compl, bytes_compl);
+
 	/*
 	 *	Look to see if we should kick the transmit network
 	 *	layer for more work.
@@ -2641,6 +2657,8 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
 	td_ptr->td_buf[0].size |= TD_QUEUE;
 	mac_tx_queue_wake(vptr->mac_regs, qnum);
 
+	if (unlikely(bql_disable))
+		netdev_sent_queue(vptr->netdev, skb->len);
 	spin_unlock_irqrestore(&vptr->lock, flags);
 out:
 	return NETDEV_TX_OK;
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v3 06/07] 3c59x: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 19:23 UTC (permalink / raw)
  To: netdev, Steffen Klassert
In-Reply-To: <1382296991-20289-1-git-send-email-milky-kernel@mcmilk.de>

Changes to 3c59x driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/3com/3c59x.c | 47 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 41 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index ad5272b..6a7b77d 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -795,6 +795,7 @@ static int global_options = -1;
 static int global_full_duplex = -1;
 static int global_enable_wol = -1;
 static int global_use_mmio = -1;
+static bool bql_disable;
 
 /* Variables to work-around the Compaq PCI BIOS32 problem. */
 static int compaq_ioaddr, compaq_irq, compaq_device_id = 0x5900;
@@ -819,6 +820,8 @@ module_param(compaq_device_id, int, 0);
 module_param(watchdog, int, 0);
 module_param(global_use_mmio, int, 0);
 module_param_array(use_mmio, int, NULL, 0);
+module_param(bql_disable, bool, 0);
+
 MODULE_PARM_DESC(debug, "3c59x debug level (0-6)");
 MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex");
 MODULE_PARM_DESC(global_options, "3c59x: same as options, but applies to all NICs if options is unset");
@@ -836,6 +839,7 @@ MODULE_PARM_DESC(compaq_device_id, "3c59x PCI device ID (Compaq BIOS problem wor
 MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds");
 MODULE_PARM_DESC(global_use_mmio, "3c59x: same as use_mmio, but applies to all NICs if options is unset");
 MODULE_PARM_DESC(use_mmio, "3c59x: use memory-mapped PCI I/O resource (0-1)");
+MODULE_PARM_DESC(bql_disable, "3c59x: Disable Byte Queue Limits functionality (default: false)");
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void poll_vortex(struct net_device *dev)
@@ -1726,6 +1730,9 @@ vortex_up(struct net_device *dev)
 	iowrite16(vp->intr_enable, ioaddr + EL3_CMD);
 	if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
 		iowrite32(0x8000, vp->cb_fn_base + 4);
+
+	if (unlikely(bql_disable))
+		netdev_reset_queue(dev);
 	netif_start_queue (dev);
 err_out:
 	return err;
@@ -2080,10 +2087,15 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		spin_unlock_irq(&vp->window_lock);
 		vp->tx_skb = skb;
 		iowrite16(StartDMADown, ioaddr + EL3_CMD);
+		if (unlikely(bql_disable))
+			netdev_sent_queue(dev, len);
 		/* netif_wake_queue() will be called at the DMADone interrupt. */
 	} else {
 		/* ... and the packet rounded to a doubleword. */
-		iowrite32_rep(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+		int len = (skb->len + 3) >> 2;
+		iowrite32_rep(ioaddr + TX_FIFO, skb->data, len);
+		if (unlikely(bql_disable))
+			netdev_sent_queue(dev, len);
 		dev_kfree_skb (skb);
 		if (ioread16(ioaddr + TxFree) > 1536) {
 			netif_start_queue (dev);	/* AKPM: redundant? */
@@ -2094,7 +2106,6 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		}
 	}
 
-
 	/* Clear the Tx status stack. */
 	{
 		int tx_status;
@@ -2164,12 +2175,14 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data,
 										skb->len, PCI_DMA_TODEVICE));
 		vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb->len | LAST_FRAG);
+		netdev_sent_queue(dev, skb->len);
 	} else {
-		int i;
+		int i, len;
 
 		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data,
 										skb_headlen(skb), PCI_DMA_TODEVICE));
 		vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb_headlen(skb));
+		len = skb_headlen(skb);
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -2180,16 +2193,21 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
 						(void *)skb_frag_address(frag),
 						skb_frag_size(frag), PCI_DMA_TODEVICE));
 
-			if (i == skb_shinfo(skb)->nr_frags-1)
+			if (i == skb_shinfo(skb)->nr_frags - 1) {
 					vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag)|LAST_FRAG);
-			else
+					len += skb_frag_size(frag) | LAST_FRAG;
+			} else {
 					vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag));
+					len += skb_frag_size(frag);
+			}
 		}
+		netdev_sent_queue(dev, len);
 	}
 #else
 	vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE));
 	vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
 	vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
+	netdev_sent_queue(dev, skb->len | LAST_FRAG);
 #endif
 
 	spin_lock_irqsave(&vp->lock, flags);
@@ -2234,6 +2252,7 @@ vortex_interrupt(int irq, void *dev_id)
 	int status;
 	int work_done = max_interrupt_work;
 	int handled = 0;
+	unsigned bytes_compl = 0, pkts_compl = 0;
 
 	ioaddr = vp->ioaddr;
 	spin_lock(&vp->lock);
@@ -2279,8 +2298,12 @@ vortex_interrupt(int irq, void *dev_id)
 
 		if (status & DMADone) {
 			if (ioread16(ioaddr + Wn7_MasterStatus) & 0x1000) {
+				int len;
 				iowrite16(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
-				pci_unmap_single(VORTEX_PCI(vp), vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE);
+				len = (vp->tx_skb->len + 3) & ~3;
+				pci_unmap_single(VORTEX_PCI(vp), vp->tx_skb_dma, len, PCI_DMA_TODEVICE);
+				bytes_compl += len;
+				pkts_compl++;
 				dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */
 				if (ioread16(ioaddr + TxFree) > 1536) {
 					/*
@@ -2327,6 +2350,9 @@ vortex_interrupt(int irq, void *dev_id)
 
 	spin_unlock(&vp->window_lock);
 
+	if (unlikely(bql_disable))
+		netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
 	if (vortex_debug > 4)
 		pr_debug("%s: exiting interrupt, status %4.4x.\n",
 			   dev->name, status);
@@ -2348,6 +2374,7 @@ boomerang_interrupt(int irq, void *dev_id)
 	void __iomem *ioaddr;
 	int status;
 	int work_done = max_interrupt_work;
+	unsigned bytes_compl = 0, pkts_compl = 0;
 
 	ioaddr = vp->ioaddr;
 
@@ -2420,6 +2447,8 @@ boomerang_interrupt(int irq, void *dev_id)
 					pci_unmap_single(VORTEX_PCI(vp),
 						le32_to_cpu(vp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE);
 #endif
+					bytes_compl += skb->len;
+					pkts_compl++;
 					dev_kfree_skb_irq(skb);
 					vp->tx_skbuff[entry] = NULL;
 				} else {
@@ -2467,6 +2496,10 @@ boomerang_interrupt(int irq, void *dev_id)
 handler_exit:
 	vp->handling_irq = 0;
 	spin_unlock(&vp->lock);
+
+	if (unlikely(bql_disable))
+		netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
 	return IRQ_HANDLED;
 }
 
@@ -2660,6 +2693,8 @@ vortex_down(struct net_device *dev, int final_down)
 	struct vortex_private *vp = netdev_priv(dev);
 	void __iomem *ioaddr = vp->ioaddr;
 
+	if (unlikely(bql_disable))
+		netdev_reset_queue(dev);
 	netif_stop_queue (dev);
 
 	del_timer_sync(&vp->rx_oom_timer);
-- 
1.8.4.1

^ permalink raw reply related

* [PATCH net-next v3 07/07] natsemi: Support for byte queue limits
From: Tino Reichardt @ 2013-10-20 19:23 UTC (permalink / raw)
  To: netdev, Greg Kroah-Hartman, David S. Miller, Jiri Pirko,
	Bill Pemberton
In-Reply-To: <1382296991-20289-1-git-send-email-milky-kernel@mcmilk.de>

Changes to natsemi driver to use byte queue limits.


Signed-off-by: Tino Reichardt <milky-kernel@mcmilk.de>

---
 drivers/net/ethernet/natsemi/natsemi.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
index 7a5e295..1f6efbc 100644
--- a/drivers/net/ethernet/natsemi/natsemi.c
+++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -71,6 +71,8 @@
 				 NETIF_MSG_TX_ERR)
 static int debug = -1;
 
+static bool bql_disable;
+
 static int mtu;
 
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
@@ -139,12 +141,15 @@ MODULE_LICENSE("GPL");
 
 module_param(mtu, int, 0);
 module_param(debug, int, 0);
+module_param(bql_disable, bool, 0);
 module_param(rx_copybreak, int, 0);
 module_param(dspcfg_workaround, int, 0);
 module_param_array(options, int, NULL, 0);
 module_param_array(full_duplex, int, NULL, 0);
 MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)");
 MODULE_PARM_DESC(debug, "DP8381x default debug level");
+MODULE_PARM_DESC(bql_disable,
+	"Disable Byte Queue Limits functionality (default: false)");
 MODULE_PARM_DESC(rx_copybreak,
 	"DP8381x copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(dspcfg_workaround, "DP8381x: control DspCfg workaround");
@@ -1974,6 +1979,9 @@ static void init_ring(struct net_device *dev)
 		np->tx_ring[i].cmd_status = 0;
 	}
 
+	if (unlikely(bql_disable))
+		netdev_reset_queue(dev);
+
 	/* 2) RX ring */
 	np->dirty_rx = 0;
 	np->cur_rx = RX_RING_SIZE;
@@ -2012,6 +2020,9 @@ static void drain_tx(struct net_device *dev)
 		}
 		np->tx_skbuff[i] = NULL;
 	}
+
+	if (unlikely(bql_disable))
+		netdev_reset_queue(dev);
 }
 
 static void drain_rx(struct net_device *dev)
@@ -2116,6 +2127,9 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
 		dev_kfree_skb_irq(skb);
 		dev->stats.tx_dropped++;
 	}
+
+	if (unlikely(bql_disable))
+		netdev_sent_queue(dev, skb->len);
 	spin_unlock_irqrestore(&np->lock, flags);
 
 	if (netif_msg_tx_queued(np)) {
@@ -2128,6 +2142,7 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
 static void netdev_tx_done(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	unsigned bytes_compl = 0, pkts_compl = 0;
 
 	for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
 		int entry = np->dirty_tx % TX_RING_SIZE;
@@ -2158,9 +2173,15 @@ static void netdev_tx_done(struct net_device *dev)
 					np->tx_skbuff[entry]->len,
 					PCI_DMA_TODEVICE);
 		/* Free the original skb. */
+		bytes_compl += np->tx_skbuff[entry]->len;
+		pkts_compl++;
 		dev_kfree_skb_irq(np->tx_skbuff[entry]);
 		np->tx_skbuff[entry] = NULL;
 	}
+
+	if (unlikely(bql_disable))
+		netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
 	if (netif_queue_stopped(dev) &&
 	    np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) {
 		/* The ring is no longer full, wake queue. */
-- 
1.8.4.1

^ permalink raw reply related

* Re: [PATCHSET net-next v3 00/07] Support for byte queue limits on various drivers
From: Joe Perches @ 2013-10-20 19:38 UTC (permalink / raw)
  To: Tino Reichardt; +Cc: netdev, David S. Miller
In-Reply-To: <1382296991-20289-1-git-send-email-milky-kernel@mcmilk.de>

On Sun, 2013-10-20 at 21:23 +0200, Tino Reichardt wrote:
> Hello again,

Hi again Tino.

> "if (likely(bql_disable == false))" was replaced by
> "if (unlikely(bql_disable))" ...

Sorry for suggesting this, but it's not an
equivalent transform unless the then & else
paths are also inverted.

Here there are no else branches.
Doesn't this need to be?

from:
	if (likely(bql_disable == false))
to:
	if (likely(!bql_disable))

^ permalink raw reply

* Re: [PATCHSET net-next v3 00/07] Support for byte queue limits on various drivers
From: Tino Reichardt @ 2013-10-20 20:19 UTC (permalink / raw)
  To: netdev
In-Reply-To: <1382296991-20289-1-git-send-email-milky-kernel@mcmilk.de>

* Tino Reichardt <milky-kernel@mcmilk.de> wrote:
> Hello again,
> 
> this patchset is intended for net-next/linux-3.13.
> 
> It adds support for byte queue limits on various network drivers.
> 
> Since not all of them are fully tested by now, I added an bql_disable
> module parameter, which can be used to disable the BQL code.
> 
> "if (likely(bql_disable == false))" was replaced by
> "if (unlikely(bql_disable))" ...


Please ignore Patchset v3... "unlikely(bql_disable)" is of cause not
correct :(


Please use "[PATCHSET net-next v3 00/07]" instead.

Sorry for all the noise here ;)

-- 
Best regards, TR

^ permalink raw reply

* Fw: [Bug 63321] New: tcp_fastretrans_alert
From: Stephen Hemminger @ 2013-10-20 20:40 UTC (permalink / raw)
  To: netdev



Begin forwarded message:

Date: Sun, 20 Oct 2013 06:20:25 -0700
From: "bugzilla-daemon@bugzilla.kernel.org" <bugzilla-daemon@bugzilla.kernel.org>
To: "stephen@networkplumber.org" <stephen@networkplumber.org>
Subject: [Bug 63321] New: tcp_fastretrans_alert


https://bugzilla.kernel.org/show_bug.cgi?id=63321

            Bug ID: 63321
           Summary: tcp_fastretrans_alert
           Product: Networking
           Version: 2.5
    Kernel Version: 3.11.6
          Hardware: x86-64
                OS: Linux
              Tree: Mainline
            Status: NEW
          Severity: normal
          Priority: P1
         Component: IPV4
          Assignee: shemminger@linux-foundation.org
          Reporter: warrior-elite@yandex.ru
        Regression: No

[  865.064799] ------------[ cut here ]------------
[  865.064813] WARNING: CPU: 0 PID: 0 at
/home/apw/COD/linux/net/ipv4/tcp_input.c:2711
tcp_fastretrans_alert+0x5df/0x620()
[  865.064815] Modules linked in: pci_stub vboxpci(OF) vboxnetadp(OF)
vboxnetflt(OF) joydev hid_generic usbhid hid vboxdrv(OF) binfmt_misc
snd_hda_codec_realtek ppdev uvcvideo videobuf2_vmalloc videobuf2_memops
videobuf2_core videodev snd_usb_audio snd_usbmidi_lib nvidia(POF) snd_hda_intel
snd_hda_codec snd_hwdep snd_pcm kvm_amd kvm snd_page_alloc snd_seq_midi
snd_seq_midi_event snd_rawmidi snd_seq microcode snd_seq_device snd_timer snd
serio_raw soundcore edac_core k10temp edac_mce_amd drm sp5100_tco ohci_pci
i2c_piix4 wmi mac_hid parport_pc lp parport pata_acpi ahci r8169 pata_atiixp
libahci mii
[  865.064843] CPU: 0 PID: 0 Comm: swapper/0 Tainted: PF          O
3.11.6-031106-generic #201310181453
[  865.064845] Hardware name: Gigabyte Technology Co., Ltd.
GA-MA770-UD3/GA-MA770-UD3, BIOS FKb 07/08/2010
[  865.064846]  0000000000000a97 ffff88012fc039a0 ffffffff81714a56
000000000000259d
[  865.064849]  0000000000000000 ffff88012fc039e0 ffffffff8106539c
ffff88012fc03a00
[  865.064851]  ffff880114f45400 000000000000000c 0000000000004120
0000000000000001
[  865.064853] Call Trace:
[  865.064855]  <IRQ>  [<ffffffff81714a56>] dump_stack+0x46/0x58
[  865.064861]  [<ffffffff8106539c>] warn_slowpath_common+0x8c/0xc0
[  865.064863]  [<ffffffff810653ea>] warn_slowpath_null+0x1a/0x20
[  865.064865]  [<ffffffff8165f9df>] tcp_fastretrans_alert+0x5df/0x620
[  865.064867]  [<ffffffff816608c8>] tcp_ack+0x498/0x630
[  865.064868]  [<ffffffff8166109a>] tcp_rcv_established+0x31a/0x780
[  865.064871]  [<ffffffff8166b3b5>] tcp_v4_do_rcv+0x155/0x240
[  865.064873]  [<ffffffff8166d230>] tcp_v4_rcv+0x5f0/0x770
[  865.064875]  [<ffffffff81099f42>] ? try_to_wake_up+0x192/0x210
[  865.064878]  [<ffffffff81647a6e>] ip_local_deliver_finish+0xce/0x250
[  865.064880]  [<ffffffff81647d7b>] ip_local_deliver+0x4b/0x90
[  865.064881]  [<ffffffff81647761>] ip_rcv_finish+0x121/0x360
[  865.064883]  [<ffffffff81647ff6>] ip_rcv+0x236/0x350
[  865.064886]  [<ffffffff81611a2a>] __netif_receive_skb_core+0x5ca/0x720
[  865.064888]  [<ffffffff81611ba1>] __netif_receive_skb+0x21/0x70
[  865.064890]  [<ffffffff81611c13>] netif_receive_skb+0x23/0x90
[  865.064891]  [<ffffffff81612330>] napi_gro_receive+0xb0/0x130
[  865.064898]  [<ffffffffa00217f2>] rtl_rx+0xe2/0x320 [r8169]
[  865.064903]  [<ffffffffa00254c5>] rtl8169_poll+0x105/0x120 [r8169]
[  865.064905]  [<ffffffff8108d00e>] ? hrtimer_get_next_event+0xce/0xd0
[  865.064907]  [<ffffffff81612ca4>] net_rx_action+0x134/0x260
[  865.064910]  [<ffffffff814734c1>] ? add_interrupt_randomness+0x41/0x190
[  865.064913]  [<ffffffff8106a510>] __do_softirq+0xe0/0x280
[  865.064915]  [<ffffffff8172005e>] ? _raw_spin_lock+0xe/0x20
[  865.064918]  [<ffffffff8172ae9c>] call_softirq+0x1c/0x30
[  865.064921]  [<ffffffff81015e35>] do_softirq+0x65/0xa0
[  865.064923]  [<ffffffff8106a82e>] irq_exit+0x9e/0xc0
[  865.064924]  [<ffffffff8172b7a3>] do_IRQ+0x63/0xe0
[  865.064926]  [<ffffffff8172066d>] common_interrupt+0x6d/0x6d
[  865.064927]  <EOI>  [<ffffffff810504f6>] ? native_safe_halt+0x6/0x10
[  865.064932]  [<ffffffff8101c803>] default_idle+0x23/0xe0
[  865.064934]  [<ffffffff8101c93a>] amd_e400_idle+0x7a/0x100
[  865.064936]  [<ffffffff8101d096>] arch_cpu_idle+0x26/0x30
[  865.064938]  [<ffffffff810ba77e>] cpu_idle_loop+0x7e/0x250
[  865.064940]  [<ffffffff810ba9bb>] cpu_startup_entry+0x6b/0x70
[  865.064943]  [<ffffffff816fcbd7>] rest_init+0x77/0x80
[  865.064946]  [<ffffffff81d24f23>] start_kernel+0x407/0x414
[  865.064948]  [<ffffffff81d249ae>] ? do_early_param+0x87/0x87
[  865.064950]  [<ffffffff81d24120>] ? early_idt_handlers+0x120/0x120
[  865.064952]  [<ffffffff81d245e8>] x86_64_start_reservations+0x2a/0x2c
[  865.064954]  [<ffffffff81d246f2>] x86_64_start_kernel+0x108/0x117
[  865.064955] ---[ end trace 7fed0fa1e4d5f06f ]---

-- 
You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* Re: [PATCHSET net-next v3 00/07] Support for byte queue limits on various drivers
From: Andi Kleen @ 2013-10-20 21:13 UTC (permalink / raw)
  To: Tino Reichardt; +Cc: netdev, David S. Miller
In-Reply-To: <1382296991-20289-1-git-send-email-milky-kernel@mcmilk.de>

Tino Reichardt <milky-kernel@mcmilk.de> writes:
>
> Since not all of them are fully tested by now, I added an bql_disable
> module parameter, which can be used to disable the BQL code.
>
> "if (likely(bql_disable == false))" was replaced by
> "if (unlikely(bql_disable))" ...

If it's untested it should probably be disabled by default,
until someone tests it.

-Andi

-- 
ak@linux.intel.com -- Speaking for myself only

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox