aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-01-10 11:46:47 -0500
committerDavid S. Miller <davem@davemloft.net>2017-01-10 11:46:47 -0500
commit2f8225e834618b9b93eaff5cea8aabbd42f04c84 (patch)
tree908721016bb910df80f52f42d21200f2bd305cfe
parentdc647ec88e029307e60e6bf9988056605f11051a (diff)
parent75dc692eda114cb234a46cb11893a9c3ea520934 (diff)
Merge branch 'r8152-fix-autosuspend'
Hayes Wang says: ==================== r8152: fix autosuspend issue Avoid rx is split into two parts when runtime suspend occurs. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/usb/r8152.c80
1 files changed, 64 insertions, 16 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 7dc61228c55b..be418563cb18 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -3576,39 +3576,87 @@ static bool delay_autosuspend(struct r8152 *tp)
3576 return false; 3576 return false;
3577} 3577}
3578 3578
3579static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) 3579static int rtl8152_rumtime_suspend(struct r8152 *tp)
3580{ 3580{
3581 struct r8152 *tp = usb_get_intfdata(intf);
3582 struct net_device *netdev = tp->netdev; 3581 struct net_device *netdev = tp->netdev;
3583 int ret = 0; 3582 int ret = 0;
3584 3583
3585 mutex_lock(&tp->control); 3584 if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
3585 u32 rcr = 0;
3586 3586
3587 if (PMSG_IS_AUTO(message)) { 3587 if (delay_autosuspend(tp)) {
3588 if (netif_running(netdev) && delay_autosuspend(tp)) {
3589 ret = -EBUSY; 3588 ret = -EBUSY;
3590 goto out1; 3589 goto out1;
3591 } 3590 }
3592 3591
3593 set_bit(SELECTIVE_SUSPEND, &tp->flags); 3592 if (netif_carrier_ok(netdev)) {
3594 } else { 3593 u32 ocp_data;
3595 netif_device_detach(netdev); 3594
3595 rcr = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
3596 ocp_data = rcr & ~RCR_ACPT_ALL;
3597 ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
3598 rxdy_gated_en(tp, true);
3599 ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA,
3600 PLA_OOB_CTRL);
3601 if (!(ocp_data & RXFIFO_EMPTY)) {
3602 rxdy_gated_en(tp, false);
3603 ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
3604 ret = -EBUSY;
3605 goto out1;
3606 }
3607 }
3608
3609 clear_bit(WORK_ENABLE, &tp->flags);
3610 usb_kill_urb(tp->intr_urb);
3611
3612 tp->rtl_ops.autosuspend_en(tp, true);
3613
3614 if (netif_carrier_ok(netdev)) {
3615 napi_disable(&tp->napi);
3616 rtl_stop_rx(tp);
3617 rxdy_gated_en(tp, false);
3618 ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
3619 napi_enable(&tp->napi);
3620 }
3596 } 3621 }
3597 3622
3623 set_bit(SELECTIVE_SUSPEND, &tp->flags);
3624
3625out1:
3626 return ret;
3627}
3628
3629static int rtl8152_system_suspend(struct r8152 *tp)
3630{
3631 struct net_device *netdev = tp->netdev;
3632 int ret = 0;
3633
3634 netif_device_detach(netdev);
3635
3598 if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) { 3636 if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
3599 clear_bit(WORK_ENABLE, &tp->flags); 3637 clear_bit(WORK_ENABLE, &tp->flags);
3600 usb_kill_urb(tp->intr_urb); 3638 usb_kill_urb(tp->intr_urb);
3601 napi_disable(&tp->napi); 3639 napi_disable(&tp->napi);
3602 if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { 3640 cancel_delayed_work_sync(&tp->schedule);
3603 rtl_stop_rx(tp); 3641 tp->rtl_ops.down(tp);
3604 tp->rtl_ops.autosuspend_en(tp, true);
3605 } else {
3606 cancel_delayed_work_sync(&tp->schedule);
3607 tp->rtl_ops.down(tp);
3608 }
3609 napi_enable(&tp->napi); 3642 napi_enable(&tp->napi);
3610 } 3643 }
3611out1: 3644
3645 return ret;
3646}
3647
3648static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
3649{
3650 struct r8152 *tp = usb_get_intfdata(intf);
3651 int ret;
3652
3653 mutex_lock(&tp->control);
3654
3655 if (PMSG_IS_AUTO(message))
3656 ret = rtl8152_rumtime_suspend(tp);
3657 else
3658 ret = rtl8152_system_suspend(tp);
3659
3612 mutex_unlock(&tp->control); 3660 mutex_unlock(&tp->control);
3613 3661
3614 return ret; 3662 return ret;