[patch]autosuspend for usbnet

Oliver Neukum <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
Hi,

here's an implementation of autosuspend in usbnet and the asix minidriver.
It works for me.

	Regards
		Oliver
Signed-off-by: Oliver Neukum <[email protected]>
-----

--- linux-2.6.21-rc7/drivers/usb/net/usbnet.h	2007-02-04 19:44:54.000000000 +0100
+++ linux-2.6.21-rc7-auto/drivers/usb/net/usbnet.h	2007-04-25 16:01:05.000000000 +0200
@@ -28,6 +28,7 @@
 struct usbnet {
 	/* housekeeping */
 	struct usb_device	*udev;
+	struct usb_interface	*idev;
 	struct driver_info	*driver_info;
 	wait_queue_head_t	*wait;
 	struct mutex		phy_mutex;
@@ -62,6 +63,7 @@ struct usbnet {
 #		define EVENT_RX_MEMORY	2
 #		define EVENT_STS_SPLIT	3
 #		define EVENT_LINK_RESET	4
+#		define TASKLET_UNREADY	5
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -176,6 +178,8 @@ extern u32 usbnet_get_msglevel (struct n
 extern void usbnet_set_msglevel (struct net_device *, u32);
 extern void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *);
 extern int usbnet_nway_reset(struct net_device *net);
+extern int usbnet_ethtool_begin(struct net_device *dev);
+extern void usbnet_ethtool_complete(struct net_device *dev);
 
 /* messaging support includes the interface name, so it must not be
  * used before it has one ... notably, in minidriver bind() calls.
--- linux-2.6.21-rc7/drivers/usb/net/usbnet.c	2007-04-25 17:02:10.000000000 +0200
+++ linux-2.6.21-rc7-auto/drivers/usb/net/usbnet.c	2007-04-25 16:35:01.000000000 +0200
@@ -589,6 +589,7 @@ static int usbnet_stop (struct net_devic
 	dev->flags = 0;
 	del_timer_sync (&dev->delay);
 	tasklet_kill (&dev->bh);
+	usb_autopm_put_interface(dev->idev);
 
 	return 0;
 }
@@ -605,6 +606,9 @@ static int usbnet_open (struct net_devic
 	int			retval = 0;
 	struct driver_info	*info = dev->driver_info;
 
+	/* wake up the device */
+	set_bit(TASKLET_UNREADY, &dev->flags);
+	retval = usb_autopm_get_interface(dev->idev);
 	// put into "known safe" state
 	if (info->reset && (retval = info->reset (dev)) < 0) {
 		if (netif_msg_ifup (dev))
@@ -657,8 +661,11 @@ static int usbnet_open (struct net_devic
 	}
 
 	// delay posting reads until we're fully open
+	clear_bit(TASKLET_UNREADY, &dev->flags);
 	tasklet_schedule (&dev->bh);
+	return retval;
 done:
+	usb_autopm_put_interface(dev->idev);
 	return retval;
 }
 
@@ -760,6 +767,23 @@ void usbnet_set_msglevel (struct net_dev
 }
 EXPORT_SYMBOL_GPL(usbnet_set_msglevel);
 
+int usbnet_ethtool_begin(struct net_device *dev)
+{
+	struct usbnet *und;
+	und = netdev_priv(dev);
+
+	return usb_autopm_get_interface(und->idev);
+}
+EXPORT_SYMBOL(usbnet_ethtool_begin);
+
+void usbnet_ethtool_complete(struct net_device *dev)
+{
+	struct usbnet *und = netdev_priv(dev);
+
+	usb_autopm_put_interface(und->idev);
+}
+EXPORT_SYMBOL(usbnet_ethtool_complete);
+
 /* drivers may override default ethtool_ops in their bind() routine */
 static struct ethtool_ops usbnet_ethtool_ops = {
 #ifdef	HAVE_MII
@@ -771,6 +795,8 @@ static struct ethtool_ops usbnet_ethtool
 	.get_drvinfo		= usbnet_get_drvinfo,
 	.get_msglevel		= usbnet_get_msglevel,
 	.set_msglevel		= usbnet_set_msglevel,
+	.begin			= usbnet_ethtool_begin,
+	.complete		= usbnet_ethtool_complete,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1138,6 +1164,7 @@ usbnet_probe (struct usb_interface *udev
 
 	dev = netdev_priv(net);
 	dev->udev = xdev;
+	dev->idev = udev;
 	dev->driver_info = info;
 	dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
 				| NETIF_MSG_PROBE | NETIF_MSG_LINK);
@@ -1274,7 +1301,8 @@ int usbnet_resume (struct usb_interface 
 	struct usbnet		*dev = usb_get_intfdata(intf);
 
 	netif_device_attach (dev->net);
-	tasklet_schedule (&dev->bh);
+	if (!test_bit(TASKLET_UNREADY, &dev->flags))
+		tasklet_schedule (&dev->bh);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_resume);
--- linux-2.6.21-rc7/drivers/usb/net/asix.c	2007-04-25 17:02:10.000000000 +0200
+++ linux-2.6.21-rc7-auto/drivers/usb/net/asix.c	2007-04-25 15:33:35.000000000 +0200
@@ -734,6 +734,8 @@ static struct ethtool_ops ax88172_ethtoo
 	.get_settings		= usbnet_get_settings,
 	.set_settings		= usbnet_set_settings,
 	.nway_reset		= usbnet_nway_reset,
+	.begin			= usbnet_ethtool_begin,
+	.complete		= usbnet_ethtool_complete,
 };
 
 static void ax88172_set_multicast(struct net_device *net)
@@ -1470,6 +1472,7 @@ static struct usb_driver asix_driver = {
 	.suspend =	usbnet_suspend,
 	.resume =	usbnet_resume,
 	.disconnect =	usbnet_disconnect,
+	.supports_autosuspend = 1,
 };
 
 static int __init asix_init(void)

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.