diff mbox

usbnet: add reset_resume quirk to prevent resume failure

Message ID 1387942633.112861467283319260.JavaMail.weblogic@epmlwas03c
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Vivek Kumar Bhagat June 30, 2016, 10:41 a.m. UTC
Ideally, usbnet_resume is sufficient for device resume operation.
since usbcore function usb_resume_device() sets udev->reset_resume
flag as a quirk solution, reset_resume() quirk we can keep in
class driver also. We checked on dongle DA-Queen UFE20C,
without reset function resume operation fails. Reason could be
some power glitch during suspend time due to which device lose
its internal state and it needs a device phy reset again during
resume to recover.

Signed-off-by: Vivek Kumar Bhagat <vivek.bhagat@samsung.com>
Signed-off-by: Vikas Bansal <vikas.bansal@samsung.com>
Signed-off-by: Sangmin Bae <sm79.bae@samsung.com>
---
 drivers/net/usb/asix_devices.c |    1 +
 drivers/net/usb/cdc_eem.c      |    1 +
 drivers/net/usb/usbnet.c       |   17 +++++++++++++++++
 include/linux/usb/usbnet.h     |    1 +
 4 files changed, 20 insertions(+)

Comments

David Miller July 1, 2016, 7:58 p.m. UTC | #1
From: Vivek Kumar Bhagat <vivek.bhagat@samsung.com>
Date: Thu, 30 Jun 2016 10:41:59 +0000 (GMT)

> 
> Ideally, usbnet_resume is sufficient for device resume operation.
> since usbcore function usb_resume_device() sets udev->reset_resume
> flag as a quirk solution, reset_resume() quirk we can keep in
> class driver also. We checked on dongle DA-Queen UFE20C,
> without reset function resume operation fails. Reason could be
> some power glitch during suspend time due to which device lose
> its internal state and it needs a device phy reset again during
> resume to recover.
> 
> Signed-off-by: Vivek Kumar Bhagat <vivek.bhagat@samsung.com>
> Signed-off-by: Vikas Bansal <vikas.bansal@samsung.com>
> Signed-off-by: Sangmin Bae <sm79.bae@samsung.com>

You've seen this necessary for one device, yet you are doing this
new reset for all usbnet devices.

That doesn't sound correct or safe at all.

I'm not applying this, sorry.
diff mbox

Patch

diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 5cabefc..68dda61 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -1097,6 +1097,7 @@  static struct usb_driver asix_driver = {
 	.probe =	usbnet_probe,
 	.suspend =	usbnet_suspend,
 	.resume =	usbnet_resume,
+	.reset_resume = usbnet_reset_resume,
 	.disconnect =	usbnet_disconnect,
 	.supports_autosuspend = 1,
 	.disable_hub_initiated_lpm = 1,
diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c
index f7180f8..83b6857 100644
--- a/drivers/net/usb/cdc_eem.c
+++ b/drivers/net/usb/cdc_eem.c
@@ -371,6 +371,7 @@  static struct usb_driver eem_driver = {
 	.disconnect =	usbnet_disconnect,
 	.suspend =	usbnet_suspend,
 	.resume =	usbnet_resume,
+	.reset_resume = usbnet_reset_resume,
 	.disable_hub_initiated_lpm = 1,
 };
 
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 61ba464..f56c176 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1876,6 +1876,23 @@  int usbnet_resume (struct usb_interface *intf)
 }
 EXPORT_SYMBOL_GPL(usbnet_resume);
 
+int usbnet_reset_resume(struct usb_interface *intf)
+{
+	struct usbnet *dev = usb_get_intfdata(intf);
+	int ret;
+
+	if (dev->driver_info->reset) {
+		ret = dev->driver_info->reset(dev);
+		if (ret < 0)
+			return ret;
+
+		return usbnet_resume(intf);
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(usbnet_reset_resume);
+
 /*
  * Either a subdriver implements manage_power, then it is assumed to always
  * be ready to be suspended or it reports the readiness to be suspended
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index 6e0ce8c..0b261d5 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -177,6 +177,7 @@  struct driver_info {
 extern int usbnet_probe(struct usb_interface *, const struct usb_device_id *);
 extern int usbnet_suspend(struct usb_interface *, pm_message_t);
 extern int usbnet_resume(struct usb_interface *);
+extern int usbnet_reset_resume(struct usb_interface *);
 extern void usbnet_disconnect(struct usb_interface *);
 extern void usbnet_device_suggests_idle(struct usbnet *dev);