aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/patches-3.18/077-05-bgmac-leave-interrupts-disabled-as-long-as-there-is-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/patches-3.18/077-05-bgmac-leave-interrupts-disabled-as-long-as-there-is-.patch')
-rw-r--r--target/linux/generic/patches-3.18/077-05-bgmac-leave-interrupts-disabled-as-long-as-there-is-.patch87
1 files changed, 87 insertions, 0 deletions
diff --git a/target/linux/generic/patches-3.18/077-05-bgmac-leave-interrupts-disabled-as-long-as-there-is-.patch b/target/linux/generic/patches-3.18/077-05-bgmac-leave-interrupts-disabled-as-long-as-there-is-.patch
new file mode 100644
index 0000000..3bbe9ea
--- /dev/null
+++ b/target/linux/generic/patches-3.18/077-05-bgmac-leave-interrupts-disabled-as-long-as-there-is-.patch
@@ -0,0 +1,87 @@
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sun, 12 Apr 2015 10:08:04 +0200
+Subject: [PATCH] bgmac: leave interrupts disabled as long as there is work
+ to do
+
+Always poll rx and tx during NAPI poll instead of relying on the status
+of the first interrupt. This prevents bgmac_poll from leaving unfinished
+work around until the next IRQ.
+In my tests this makes bridging/routing throughput under heavy load more
+stable and ensures that no new IRQs arrive as long as bgmac_poll uses up
+the entire budget.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+---
+
+--- a/drivers/net/ethernet/broadcom/bgmac.c
++++ b/drivers/net/ethernet/broadcom/bgmac.c
+@@ -1109,8 +1109,6 @@ static void bgmac_chip_reset(struct bgma
+ bgmac_phy_init(bgmac);
+
+ netdev_reset_queue(bgmac->net_dev);
+-
+- bgmac->int_status = 0;
+ }
+
+ static void bgmac_chip_intrs_on(struct bgmac *bgmac)
+@@ -1225,14 +1223,13 @@ static irqreturn_t bgmac_interrupt(int i
+ if (!int_status)
+ return IRQ_NONE;
+
+- /* Ack */
+- bgmac_write(bgmac, BGMAC_INT_STATUS, int_status);
++ int_status &= ~(BGMAC_IS_TX0 | BGMAC_IS_RX);
++ if (int_status)
++ bgmac_err(bgmac, "Unknown IRQs: 0x%08X\n", int_status);
+
+ /* Disable new interrupts until handling existing ones */
+ bgmac_chip_intrs_off(bgmac);
+
+- bgmac->int_status = int_status;
+-
+ napi_schedule(&bgmac->napi);
+
+ return IRQ_HANDLED;
+@@ -1241,25 +1238,17 @@ static irqreturn_t bgmac_interrupt(int i
+ static int bgmac_poll(struct napi_struct *napi, int weight)
+ {
+ struct bgmac *bgmac = container_of(napi, struct bgmac, napi);
+- struct bgmac_dma_ring *ring;
+ int handled = 0;
+
+- if (bgmac->int_status & BGMAC_IS_TX0) {
+- ring = &bgmac->tx_ring[0];
+- bgmac_dma_tx_free(bgmac, ring);
+- bgmac->int_status &= ~BGMAC_IS_TX0;
+- }
++ /* Ack */
++ bgmac_write(bgmac, BGMAC_INT_STATUS, ~0);
+
+- if (bgmac->int_status & BGMAC_IS_RX) {
+- ring = &bgmac->rx_ring[0];
+- handled += bgmac_dma_rx_read(bgmac, ring, weight);
+- bgmac->int_status &= ~BGMAC_IS_RX;
+- }
++ bgmac_dma_tx_free(bgmac, &bgmac->tx_ring[0]);
++ handled += bgmac_dma_rx_read(bgmac, &bgmac->rx_ring[0], weight);
+
+- if (bgmac->int_status) {
+- bgmac_err(bgmac, "Unknown IRQs: 0x%08X\n", bgmac->int_status);
+- bgmac->int_status = 0;
+- }
++ /* Poll again if more events arrived in the meantime */
++ if (bgmac_read(bgmac, BGMAC_INT_STATUS) & (BGMAC_IS_TX0 | BGMAC_IS_RX))
++ return handled;
+
+ if (handled < weight) {
+ napi_complete(napi);
+--- a/drivers/net/ethernet/broadcom/bgmac.h
++++ b/drivers/net/ethernet/broadcom/bgmac.h
+@@ -452,7 +452,6 @@ struct bgmac {
+
+ /* Int */
+ u32 int_mask;
+- u32 int_status;
+
+ /* Current MAC state */
+ int mac_speed;