You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
2.5 KiB
88 lines
2.5 KiB
![]()
8 years ago
|
From: Felix Fietkau <nbd@nbd.name>
|
||
![]()
10 years ago
|
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.
|
||
|
|
||
![]()
8 years ago
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||
![]()
10 years ago
|
---
|
||
|
|
||
|
--- a/drivers/net/ethernet/broadcom/bgmac.c
|
||
|
+++ b/drivers/net/ethernet/broadcom/bgmac.c
|
||
![]()
10 years ago
|
@@ -1109,8 +1109,6 @@ static void bgmac_chip_reset(struct bgma
|
||
![]()
10 years ago
|
bgmac_phy_init(bgmac);
|
||
|
|
||
|
netdev_reset_queue(bgmac->net_dev);
|
||
|
-
|
||
|
- bgmac->int_status = 0;
|
||
|
}
|
||
|
|
||
|
static void bgmac_chip_intrs_on(struct bgmac *bgmac)
|
||
![]()
10 years ago
|
@@ -1225,14 +1223,13 @@ static irqreturn_t bgmac_interrupt(int i
|
||
![]()
10 years ago
|
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;
|
||
![]()
10 years ago
|
@@ -1241,25 +1238,17 @@ static irqreturn_t bgmac_interrupt(int i
|
||
![]()
10 years ago
|
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;
|
||
|
- }
|
||
![]()
10 years ago
|
+ /* Poll again if more events arrived in the meantime */
|
||
![]()
10 years ago
|
+ 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;
|