--- drivers/net/usb/r8152.c | 62 +++++++++++++++++++++++++++++++----------------- net/core/dev.c | 14 +++++++++- 2 files changed, 53 insertions(+), 23 deletions(-) --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -704,6 +704,8 @@ struct r8152 { unsigned long flags; struct usb_device *udev; struct napi_struct napi; + int napi_stat; + void *napi_last_en, *napi_last_dis; struct usb_interface *intf; struct net_device *netdev; struct urb *intr_urb; @@ -775,6 +777,31 @@ static unsigned int agg_buf_sz = 16384; #define RTL_LIMITED_TSO_SIZE (agg_buf_sz - sizeof(struct tx_desc) - \ VLAN_ETH_HLEN - ETH_FCS_LEN) +static void my_napi_enable(struct r8152 *tp) +{ + if (tp->napi_stat == 0) { + napi_enable(&tp->napi); + tp->napi_stat++; + tp->napi_last_en = (void *)_RET_IP_; + return; + } + + WARN(1, "napi_stat=%d\n", tp->napi_stat); +} + +static void my_napi_disable(struct r8152 *tp) +{ + if (tp->napi_stat == 1) { + napi_disable(&tp->napi); + tp->napi_stat--; + tp->napi_last_dis = (void *)_RET_IP_; + return; + } + + WARN(1, "napi_stat=%d last_dis=%pF last_en=%pF\n", + tp->napi_stat, tp->napi_last_en, tp->napi_last_dis); +} + static int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) { @@ -3787,7 +3814,6 @@ static bool rtl8153_in_nway(struct r8152 static void set_carrier(struct r8152 *tp) { struct net_device *netdev = tp->netdev; - struct napi_struct *napi = &tp->napi; u8 speed; speed = rtl8152_get_speed(tp); @@ -3796,12 +3822,12 @@ static void set_carrier(struct r8152 *tp if (!netif_carrier_ok(netdev)) { tp->rtl_ops.enable(tp); netif_stop_queue(netdev); - napi_disable(napi); + my_napi_disable(tp); netif_carrier_on(netdev); rtl_start_rx(tp); clear_bit(RTL8152_SET_RX_MODE, &tp->flags); _rtl8152_set_rx_mode(netdev); - napi_enable(&tp->napi); + my_napi_enable(tp); netif_wake_queue(netdev); netif_info(tp, link, netdev, "carrier on\n"); } else if (netif_queue_stopped(netdev) && @@ -3811,9 +3837,9 @@ static void set_carrier(struct r8152 *tp } else { if (netif_carrier_ok(netdev)) { netif_carrier_off(netdev); - napi_disable(napi); + my_napi_disable(tp); tp->rtl_ops.disable(tp); - napi_enable(napi); + my_napi_enable(tp); netif_info(tp, link, netdev, "carrier off\n"); } } @@ -3934,7 +3960,7 @@ static int rtl8152_open(struct net_devic res); goto out_unlock; } - napi_enable(&tp->napi); + my_napi_enable(tp); mutex_unlock(&tp->control); @@ -3962,7 +3988,7 @@ static int rtl8152_close(struct net_devi #ifdef CONFIG_PM_SLEEP unregister_pm_notifier(&tp->pm_notifier); #endif - napi_disable(&tp->napi); + my_napi_disable(tp); clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); cancel_delayed_work_sync(&tp->schedule); @@ -4230,7 +4256,7 @@ static int rtl8152_pre_reset(struct usb_ return 0; netif_stop_queue(netdev); - napi_disable(&tp->napi); + my_napi_disable(tp); clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); cancel_delayed_work_sync(&tp->schedule); @@ -4264,7 +4290,7 @@ static int rtl8152_post_reset(struct usb mutex_unlock(&tp->control); } - napi_enable(&tp->napi); + my_napi_enable(tp); netif_wake_queue(netdev); usb_submit_urb(tp->intr_urb, GFP_KERNEL); @@ -4302,10 +4328,8 @@ static int rtl8152_runtime_resume(struct struct net_device *netdev = tp->netdev; if (netif_running(netdev) && netdev->flags & IFF_UP) { - struct napi_struct *napi = &tp->napi; - tp->rtl_ops.autosuspend_en(tp, false); - napi_disable(napi); + my_napi_disable(tp); set_bit(WORK_ENABLE, &tp->flags); if (netif_carrier_ok(netdev)) { @@ -4318,7 +4342,7 @@ static int rtl8152_runtime_resume(struct } } - napi_enable(napi); + my_napi_enable(tp); clear_bit(SELECTIVE_SUSPEND, &tp->flags); smp_mb__after_atomic(); @@ -4388,13 +4412,11 @@ static int rtl8152_runtime_suspend(struc tp->rtl_ops.autosuspend_en(tp, true); if (netif_carrier_ok(netdev)) { - struct napi_struct *napi = &tp->napi; - - napi_disable(napi); + my_napi_disable(tp); rtl_stop_rx(tp); rxdy_gated_en(tp, false); ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr); - napi_enable(napi); + my_napi_enable(tp); } if (delay_autosuspend(tp)) { @@ -4415,14 +4437,12 @@ static int rtl8152_system_suspend(struct netif_device_detach(netdev); if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) { - struct napi_struct *napi = &tp->napi; - clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); - napi_disable(napi); + my_napi_disable(tp); cancel_delayed_work_sync(&tp->schedule); tp->rtl_ops.down(tp); - napi_enable(napi); + my_napi_enable(tp); } return ret; --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5654,13 +5654,23 @@ EXPORT_SYMBOL(netif_napi_add); void napi_disable(struct napi_struct *n) { + int a; + might_sleep(); set_bit(NAPI_STATE_DISABLE, &n->state); - while (test_and_set_bit(NAPI_STATE_SCHED, &n->state)) + a = 0; + while (test_and_set_bit(NAPI_STATE_SCHED, &n->state)) { msleep(1); - while (test_and_set_bit(NAPI_STATE_NPSVC, &n->state)) + if (WARN(a++ > 20 * 1000, "NAPI_STATE_SCHED never cleared")) + break; + } + a = 0; + while (test_and_set_bit(NAPI_STATE_NPSVC, &n->state)) { msleep(1); + if (WARN(a++ > 20 * 1000, "NAPI_STATE_NPSVC never cleared")) + break; + } hrtimer_cancel(&n->timer);