From 39e9526cec50358725d6f68f271b35c041986800 Mon Sep 17 00:00:00 2001 From: Hemmo Nieminen Date: Fri, 4 Dec 2015 00:11:32 +0200 Subject: [PATCH] staging: rtl8712: Improve suspend/resume functionality. Cancel pending URBs during suspend operation to avoid receiving ESHUTDOWN in read/write completion callbacks while the device is suspended. Receiving ESHUTDOWN in read/write completion callbacks will cause the driver to enter a non-functioning "stopped" state from which the driver is unable to recover without reloading the module. Signed-off-by: Hemmo Nieminen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/drv_types.h | 1 + drivers/staging/rtl8712/usb_intf.c | 12 ++++++++++++ drivers/staging/rtl8712/usb_ops_linux.c | 5 ++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h index 3d64fee..29e47e1 100644 --- a/drivers/staging/rtl8712/drv_types.h +++ b/drivers/staging/rtl8712/drv_types.h @@ -159,6 +159,7 @@ struct _adapter { struct mp_priv mppriv; s32 bDriverStopped; s32 bSurpriseRemoved; + s32 bSuspended; u32 IsrContent; u32 ImrContent; u8 EepromAddressSize; diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index c71333f..b64f10b 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -205,12 +205,15 @@ struct drv_priv { static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state) { struct net_device *pnetdev = usb_get_intfdata(pusb_intf); + struct _adapter *padapter = netdev_priv(pnetdev); netdev_info(pnetdev, "Suspending...\n"); if (!pnetdev || !netif_running(pnetdev)) { netdev_info(pnetdev, "Unable to suspend\n"); return 0; } + padapter->bSuspended = true; + rtl871x_intf_stop(padapter); if (pnetdev->netdev_ops->ndo_stop) pnetdev->netdev_ops->ndo_stop(pnetdev); mdelay(10); @@ -218,9 +221,16 @@ static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state) return 0; } +void rtl871x_intf_resume(struct _adapter *padapter) +{ + if (padapter->dvobjpriv.inirp_init) + padapter->dvobjpriv.inirp_init(padapter); +} + static int r871x_resume(struct usb_interface *pusb_intf) { struct net_device *pnetdev = usb_get_intfdata(pusb_intf); + struct _adapter *padapter = netdev_priv(pnetdev); netdev_info(pnetdev, "Resuming...\n"); if (!pnetdev || !netif_running(pnetdev)) { @@ -230,6 +240,8 @@ static int r871x_resume(struct usb_interface *pusb_intf) netif_device_attach(pnetdev); if (pnetdev->netdev_ops->ndo_open) pnetdev->netdev_ops->ndo_open(pnetdev); + padapter->bSuspended = false; + rtl871x_intf_resume(padapter); return 0; } diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c index 489a9e6..e77be2a 100644 --- a/drivers/staging/rtl8712/usb_ops_linux.c +++ b/drivers/staging/rtl8712/usb_ops_linux.c @@ -228,11 +228,14 @@ static void r8712_usb_read_port_complete(struct urb *purb) } } else { switch (purb->status) { + case -ENOENT: + if (padapter->bSuspended) + break; + /* Fall through. */ case -EINVAL: case -EPIPE: case -ENODEV: case -ESHUTDOWN: - case -ENOENT: padapter->bDriverStopped = true; break; case -EPROTO: -- 2.7.4