From e18958c6a204150f07b24affe6883cb3b938f112 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 22 Mar 2020 19:02:32 +0100 Subject: [PATCH 1/3] r8169: simplify rtl_task Currently rtl_task() is designed to handle a large number of tasks. However we have just one, so we can remove some overhead. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index d2eef3754b33..242b14cc7131 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -4589,31 +4589,17 @@ out: static void rtl_task(struct work_struct *work) { - static const struct { - int bitnr; - void (*action)(struct rtl8169_private *); - } rtl_work[] = { - { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work }, - }; struct rtl8169_private *tp = container_of(work, struct rtl8169_private, wk.work); - struct net_device *dev = tp->dev; - int i; rtl_lock_work(tp); - if (!netif_running(dev) || + if (!netif_running(tp->dev) || !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags)) goto out_unlock; - for (i = 0; i < ARRAY_SIZE(rtl_work); i++) { - bool pending; - - pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags); - if (pending) - rtl_work[i].action(tp); - } - + if (test_and_clear_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags)) + rtl_reset_work(tp); out_unlock: rtl_unlock_work(tp); } From 3f6ca6c739892ed018bc17100efa4703fcc8af46 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 22 Mar 2020 19:03:06 +0100 Subject: [PATCH 2/3] r8169: improve rtl_schedule_task The current implementation makes the implicit assumption that if a bit is set, then the work is scheduled already. Remove the need for this implicit assumption and call schedule_work() always. It will check internally whether the work is scheduled already. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 242b14cc7131..e9ced0360f58 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -2228,8 +2228,8 @@ u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp) static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag) { - if (!test_and_set_bit(flag, tp->wk.flags)) - schedule_work(&tp->wk.work); + set_bit(flag, tp->wk.flags); + schedule_work(&tp->wk.work); } static void rtl8169_init_phy(struct rtl8169_private *tp) From 6b02e407cbf8d421477ebb7792cd6380affcd313 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 22 Mar 2020 19:03:56 +0100 Subject: [PATCH 3/3] r8169: improve RTL8168b FIFO overflow workaround So far only the reset bit it set, but the handler executing the reset is not scheduled. Therefore nothing will happen until some other action schedules the handler. Improve this by ensuring that the handler is scheduled. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index e9ced0360f58..b7dc1c112a94 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -4575,8 +4575,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) if (unlikely(status & RxFIFOOver && tp->mac_version == RTL_GIGA_MAC_VER_11)) { netif_stop_queue(tp->dev); - /* XXX - Hack alert. See rtl_task(). */ - set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags); + rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } rtl_irq_disable(tp);