Commit 39e9526c authored by Hemmo Nieminen's avatar Hemmo Nieminen Committed by Greg Kroah-Hartman

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: default avatarHemmo Nieminen <hemmo.nieminen@iki.fi>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 549d33d2
...@@ -159,6 +159,7 @@ struct _adapter { ...@@ -159,6 +159,7 @@ struct _adapter {
struct mp_priv mppriv; struct mp_priv mppriv;
s32 bDriverStopped; s32 bDriverStopped;
s32 bSurpriseRemoved; s32 bSurpriseRemoved;
s32 bSuspended;
u32 IsrContent; u32 IsrContent;
u32 ImrContent; u32 ImrContent;
u8 EepromAddressSize; u8 EepromAddressSize;
......
...@@ -205,12 +205,15 @@ struct drv_priv { ...@@ -205,12 +205,15 @@ struct drv_priv {
static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state) static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state)
{ {
struct net_device *pnetdev = usb_get_intfdata(pusb_intf); struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
struct _adapter *padapter = netdev_priv(pnetdev);
netdev_info(pnetdev, "Suspending...\n"); netdev_info(pnetdev, "Suspending...\n");
if (!pnetdev || !netif_running(pnetdev)) { if (!pnetdev || !netif_running(pnetdev)) {
netdev_info(pnetdev, "Unable to suspend\n"); netdev_info(pnetdev, "Unable to suspend\n");
return 0; return 0;
} }
padapter->bSuspended = true;
rtl871x_intf_stop(padapter);
if (pnetdev->netdev_ops->ndo_stop) if (pnetdev->netdev_ops->ndo_stop)
pnetdev->netdev_ops->ndo_stop(pnetdev); pnetdev->netdev_ops->ndo_stop(pnetdev);
mdelay(10); mdelay(10);
...@@ -218,9 +221,16 @@ static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state) ...@@ -218,9 +221,16 @@ static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state)
return 0; 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) static int r871x_resume(struct usb_interface *pusb_intf)
{ {
struct net_device *pnetdev = usb_get_intfdata(pusb_intf); struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
struct _adapter *padapter = netdev_priv(pnetdev);
netdev_info(pnetdev, "Resuming...\n"); netdev_info(pnetdev, "Resuming...\n");
if (!pnetdev || !netif_running(pnetdev)) { if (!pnetdev || !netif_running(pnetdev)) {
...@@ -230,6 +240,8 @@ static int r871x_resume(struct usb_interface *pusb_intf) ...@@ -230,6 +240,8 @@ static int r871x_resume(struct usb_interface *pusb_intf)
netif_device_attach(pnetdev); netif_device_attach(pnetdev);
if (pnetdev->netdev_ops->ndo_open) if (pnetdev->netdev_ops->ndo_open)
pnetdev->netdev_ops->ndo_open(pnetdev); pnetdev->netdev_ops->ndo_open(pnetdev);
padapter->bSuspended = false;
rtl871x_intf_resume(padapter);
return 0; return 0;
} }
......
...@@ -228,11 +228,14 @@ static void r8712_usb_read_port_complete(struct urb *purb) ...@@ -228,11 +228,14 @@ static void r8712_usb_read_port_complete(struct urb *purb)
} }
} else { } else {
switch (purb->status) { switch (purb->status) {
case -ENOENT:
if (padapter->bSuspended)
break;
/* Fall through. */
case -EINVAL: case -EINVAL:
case -EPIPE: case -EPIPE:
case -ENODEV: case -ENODEV:
case -ESHUTDOWN: case -ESHUTDOWN:
case -ENOENT:
padapter->bDriverStopped = true; padapter->bDriverStopped = true;
break; break;
case -EPROTO: case -EPROTO:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment