[PATCH] staging: rtl8712: Improve suspend/resume functionality.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <hemmo.nieminen@xxxxxx>
---

Notes:
    Tested on x86_64 with RTL8191SU 802.11n WLAN Adapter.

 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.6.3

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel



[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux