summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorhayeswang <hayeswang@realtek.com>2017-01-10 17:04:07 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-15 13:41:35 +0100
commit0d3b9c2746d34a701f21c143c8f09a0887f5e203 (patch)
tree39ece3773189baa6a0e5fae9d41e26c336fb45ee /drivers/net
parentc31a3c79928bee12a42f997c2f597d9fd68b1170 (diff)
r8152: fix rx issue for runtime suspend
[ Upstream commit 75dc692eda114cb234a46cb11893a9c3ea520934 ] Pause the rx and make sure the rx fifo is empty when the autosuspend occurs. If the rx data comes when the driver is canceling the rx urb, the host controller would stop getting the data from the device and continue it after next rx urb is submitted. That is, one continuing data is split into two different urb buffers. That let the driver take the data as a rx descriptor, and unexpected behavior happens. Signed-off-by: Hayes Wang <hayeswang@realtek.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/usb/r8152.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 7a6d405c172b..32b7ec976dcc 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -3452,17 +3452,42 @@ static int rtl8152_rumtime_suspend(struct r8152 *tp)
int ret = 0;
if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
+ u32 rcr = 0;
+
if (delay_autosuspend(tp)) {
ret = -EBUSY;
goto out1;
}
+ if (netif_carrier_ok(netdev)) {
+ u32 ocp_data;
+
+ rcr = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
+ ocp_data = rcr & ~RCR_ACPT_ALL;
+ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
+ rxdy_gated_en(tp, true);
+ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA,
+ PLA_OOB_CTRL);
+ if (!(ocp_data & RXFIFO_EMPTY)) {
+ rxdy_gated_en(tp, false);
+ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
+ ret = -EBUSY;
+ goto out1;
+ }
+ }
+
clear_bit(WORK_ENABLE, &tp->flags);
usb_kill_urb(tp->intr_urb);
- napi_disable(&tp->napi);
- rtl_stop_rx(tp);
+
rtl_runtime_suspend_enable(tp, true);
- napi_enable(&tp->napi);
+
+ if (netif_carrier_ok(netdev)) {
+ napi_disable(&tp->napi);
+ rtl_stop_rx(tp);
+ rxdy_gated_en(tp, false);
+ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
+ napi_enable(&tp->napi);
+ }
}
set_bit(SELECTIVE_SUSPEND, &tp->flags);