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/ _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel