| From 8a712c059e993e86bf7ad0b0bbb0e41703190c0f Mon Sep 17 00:00:00 2001 |
| From: hayeswang <hayeswang@realtek.com> |
| Date: Tue, 10 Jan 2017 17:04:07 +0800 |
| Subject: [PATCH] r8152: fix rx issue for runtime suspend |
| |
| commit 75dc692eda114cb234a46cb11893a9c3ea520934 upstream. |
| |
| 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c |
| index abb683ef913f..56647f79a7bb 100644 |
| --- a/drivers/net/usb/r8152.c |
| +++ b/drivers/net/usb/r8152.c |
| @@ -3580,17 +3580,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); |
| + |
| tp->rtl_ops.autosuspend_en(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); |
| -- |
| 2.10.1 |
| |