Skip to content

Commit

Permalink
r8152: fix lockup when runtime PM is enabled
Browse files Browse the repository at this point in the history
When an interface is brought up which was previously suspended (via
runtime PM), it would hang. This happens because napi_disable is called
before napi_enable.

Solve this by avoiding napi_enable in the resume during open function
(netif_running is true when open is called, IFF_UP is set after a
successful open; netif_running is false when close is called, but IFF_UP
is then still set).

While at it, remove WORK_ENABLE check from rtl8152_open (introduced with
the original change) because it cannot happen:

 - After this patch, runtime resume will not set it during rtl8152_open.
 - When link is up, rtl8152_open is not called.
 - When link is down during system/auto suspend/resume, it is not set.

Fixes: 41cec84 ("r8152: don't enable napi before rx ready")
Link: https://lkml.kernel.org/r/20151205105912.GA1766@al
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
Acked-by: Hayes Wang <hayeswang@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Peter Wu authored and David S. Miller committed Dec 9, 2015
1 parent f406ce4 commit 90186af
Showing 1 changed file with 3 additions and 18 deletions.
21 changes: 3 additions & 18 deletions drivers/net/usb/r8152.c
Original file line number Diff line number Diff line change
Expand Up @@ -3067,17 +3067,6 @@ static int rtl8152_open(struct net_device *netdev)

mutex_lock(&tp->control);

/* The WORK_ENABLE may be set when autoresume occurs */
if (test_bit(WORK_ENABLE, &tp->flags)) {
clear_bit(WORK_ENABLE, &tp->flags);
usb_kill_urb(tp->intr_urb);
cancel_delayed_work_sync(&tp->schedule);

/* disable the tx/rx, if the workqueue has enabled them. */
if (netif_carrier_ok(netdev))
tp->rtl_ops.disable(tp);
}

tp->rtl_ops.up(tp);

rtl8152_set_speed(tp, AUTONEG_ENABLE,
Expand Down Expand Up @@ -3124,12 +3113,6 @@ static int rtl8152_close(struct net_device *netdev)
} else {
mutex_lock(&tp->control);

/* The autosuspend may have been enabled and wouldn't
* be disable when autoresume occurs, because the
* netif_running() would be false.
*/
rtl_runtime_suspend_enable(tp, false);

tp->rtl_ops.down(tp);

mutex_unlock(&tp->control);
Expand Down Expand Up @@ -3512,7 +3495,7 @@ static int rtl8152_resume(struct usb_interface *intf)
netif_device_attach(tp->netdev);
}

if (netif_running(tp->netdev)) {
if (netif_running(tp->netdev) && tp->netdev->flags & IFF_UP) {
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
rtl_runtime_suspend_enable(tp, false);
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
Expand All @@ -3532,6 +3515,8 @@ static int rtl8152_resume(struct usb_interface *intf)
}
usb_submit_urb(tp->intr_urb, GFP_KERNEL);
} else if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
if (tp->netdev->flags & IFF_UP)
rtl_runtime_suspend_enable(tp, false);
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
}

Expand Down

0 comments on commit 90186af

Please sign in to comment.