forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Hayes Wang says: ==================== r8152: fix scheduling napi v3: simply the argument for patch #3. Replace &tp->napi with napi. v2: Add smp_mb__after_atomic() for patch #1. v1: Scheduling the napi during the following periods would let it be ignored. And the events wouldn't be handled until next napi_schedule() is called. 1. after napi_disable and before napi_enable(). 2. after all actions of napi function is completed and before calling napi_complete(). If no next napi_schedule() is called, tx or rx would stop working. In order to avoid these situations, the followings solutions are applied. 1. prevent start_xmit() from calling napi_schedule() during runtime suspend or after napi_disable(). 2. re-schedule the napi for tx if it is necessary. 3. check if any rx is finished or not after napi_enable(). ==================== Signed-off-by: David S. Miller <[email protected]>
- Loading branch information
Showing
1 changed file
with
24 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,7 @@ | |
#define NETNEXT_VERSION "08" | ||
|
||
/* Information for net */ | ||
#define NET_VERSION "7" | ||
#define NET_VERSION "8" | ||
|
||
#define DRIVER_VERSION "v1." NETNEXT_VERSION "." NET_VERSION | ||
#define DRIVER_AUTHOR "Realtek linux nic maintainers <[email protected]>" | ||
|
@@ -1936,6 +1936,9 @@ static int r8152_poll(struct napi_struct *napi, int budget) | |
napi_complete(napi); | ||
if (!list_empty(&tp->rx_done)) | ||
napi_schedule(napi); | ||
else if (!skb_queue_empty(&tp->tx_queue) && | ||
!list_empty(&tp->tx_free)) | ||
napi_schedule(napi); | ||
} | ||
|
||
return work_done; | ||
|
@@ -3155,17 +3158,21 @@ static void set_carrier(struct r8152 *tp) | |
if (!netif_carrier_ok(netdev)) { | ||
tp->rtl_ops.enable(tp); | ||
set_bit(RTL8152_SET_RX_MODE, &tp->flags); | ||
netif_stop_queue(netdev); | ||
napi_disable(&tp->napi); | ||
netif_carrier_on(netdev); | ||
rtl_start_rx(tp); | ||
napi_enable(&tp->napi); | ||
netif_wake_queue(netdev); | ||
netif_info(tp, link, netdev, "carrier on\n"); | ||
} | ||
} else { | ||
if (netif_carrier_ok(netdev)) { | ||
netif_carrier_off(netdev); | ||
napi_disable(&tp->napi); | ||
tp->rtl_ops.disable(tp); | ||
napi_enable(&tp->napi); | ||
netif_info(tp, link, netdev, "carrier off\n"); | ||
} | ||
} | ||
} | ||
|
@@ -3515,12 +3522,12 @@ static int rtl8152_pre_reset(struct usb_interface *intf) | |
if (!netif_running(netdev)) | ||
return 0; | ||
|
||
netif_stop_queue(netdev); | ||
napi_disable(&tp->napi); | ||
clear_bit(WORK_ENABLE, &tp->flags); | ||
usb_kill_urb(tp->intr_urb); | ||
cancel_delayed_work_sync(&tp->schedule); | ||
if (netif_carrier_ok(netdev)) { | ||
netif_stop_queue(netdev); | ||
mutex_lock(&tp->control); | ||
tp->rtl_ops.disable(tp); | ||
mutex_unlock(&tp->control); | ||
|
@@ -3548,12 +3555,15 @@ static int rtl8152_post_reset(struct usb_interface *intf) | |
rtl_start_rx(tp); | ||
rtl8152_set_rx_mode(netdev); | ||
mutex_unlock(&tp->control); | ||
netif_wake_queue(netdev); | ||
} | ||
|
||
napi_enable(&tp->napi); | ||
netif_wake_queue(netdev); | ||
usb_submit_urb(tp->intr_urb, GFP_KERNEL); | ||
|
||
if (!list_empty(&tp->rx_done)) | ||
napi_schedule(&tp->napi); | ||
|
||
return 0; | ||
} | ||
|
||
|
@@ -3585,10 +3595,15 @@ static int rtl8152_rumtime_suspend(struct r8152 *tp) | |
struct net_device *netdev = tp->netdev; | ||
int ret = 0; | ||
|
||
set_bit(SELECTIVE_SUSPEND, &tp->flags); | ||
smp_mb__after_atomic(); | ||
|
||
if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) { | ||
u32 rcr = 0; | ||
|
||
if (delay_autosuspend(tp)) { | ||
clear_bit(SELECTIVE_SUSPEND, &tp->flags); | ||
smp_mb__after_atomic(); | ||
ret = -EBUSY; | ||
goto out1; | ||
} | ||
|
@@ -3605,6 +3620,8 @@ static int rtl8152_rumtime_suspend(struct r8152 *tp) | |
if (!(ocp_data & RXFIFO_EMPTY)) { | ||
rxdy_gated_en(tp, false); | ||
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr); | ||
clear_bit(SELECTIVE_SUSPEND, &tp->flags); | ||
smp_mb__after_atomic(); | ||
ret = -EBUSY; | ||
goto out1; | ||
} | ||
|
@@ -3624,8 +3641,6 @@ static int rtl8152_rumtime_suspend(struct r8152 *tp) | |
} | ||
} | ||
|
||
set_bit(SELECTIVE_SUSPEND, &tp->flags); | ||
|
||
out1: | ||
return ret; | ||
} | ||
|
@@ -3681,12 +3696,15 @@ static int rtl8152_resume(struct usb_interface *intf) | |
if (netif_running(tp->netdev) && tp->netdev->flags & IFF_UP) { | ||
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { | ||
tp->rtl_ops.autosuspend_en(tp, false); | ||
clear_bit(SELECTIVE_SUSPEND, &tp->flags); | ||
napi_disable(&tp->napi); | ||
set_bit(WORK_ENABLE, &tp->flags); | ||
if (netif_carrier_ok(tp->netdev)) | ||
rtl_start_rx(tp); | ||
napi_enable(&tp->napi); | ||
clear_bit(SELECTIVE_SUSPEND, &tp->flags); | ||
smp_mb__after_atomic(); | ||
if (!list_empty(&tp->rx_done)) | ||
napi_schedule(&tp->napi); | ||
} else { | ||
tp->rtl_ops.up(tp); | ||
netif_carrier_off(tp->netdev); | ||
|