| From foo@baz Fri Nov 2 10:04:04 CET 2018 |
| From: Heiner Kallweit <hkallweit1@gmail.com> |
| Date: Thu, 18 Oct 2018 19:56:01 +0200 |
| Subject: r8169: fix NAPI handling under high load |
| |
| From: Heiner Kallweit <hkallweit1@gmail.com> |
| |
| [ Upstream commit 6b839b6cf9eada30b086effb51e5d6076bafc761 ] |
| |
| rtl_rx() and rtl_tx() are called only if the respective bits are set |
| in the interrupt status register. Under high load NAPI may not be |
| able to process all data (work_done == budget) and it will schedule |
| subsequent calls to the poll callback. |
| rtl_ack_events() however resets the bits in the interrupt status |
| register, therefore subsequent calls to rtl8169_poll() won't call |
| rtl_rx() and rtl_tx() - chip interrupts are still disabled. |
| |
| Fix this by calling rtl_rx() and rtl_tx() independent of the bits |
| set in the interrupt status register. Both functions will detect |
| if there's nothing to do for them. |
| |
| Fixes: da78dbff2e05 ("r8169: remove work from irq handler.") |
| Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/ethernet/realtek/r8169.c | 8 +++----- |
| 1 file changed, 3 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/net/ethernet/realtek/r8169.c |
| +++ b/drivers/net/ethernet/realtek/r8169.c |
| @@ -7559,17 +7559,15 @@ static int rtl8169_poll(struct napi_stru |
| struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); |
| struct net_device *dev = tp->dev; |
| u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow; |
| - int work_done= 0; |
| + int work_done; |
| u16 status; |
| |
| status = rtl_get_events(tp); |
| rtl_ack_events(tp, status & ~tp->event_slow); |
| |
| - if (status & RTL_EVENT_NAPI_RX) |
| - work_done = rtl_rx(dev, tp, (u32) budget); |
| + work_done = rtl_rx(dev, tp, (u32) budget); |
| |
| - if (status & RTL_EVENT_NAPI_TX) |
| - rtl_tx(dev, tp); |
| + rtl_tx(dev, tp); |
| |
| if (status & tp->event_slow) { |
| enable_mask &= ~tp->event_slow; |