Hi, this is against Greg's newest tree, which includes the pm fix for cdc devices. Do you like the principal approach?
Regards Oliver ----- --- a/drivers/usb/net/usbnet.h 2007-05-03 15:55:56.000000000 +0200 +++ b/drivers/usb/net/usbnet.h 2007-05-03 14:24:05.000000000 +0200 @@ -28,6 +28,7 @@ struct usbnet { /* housekeeping */ struct usb_device *udev; + struct usb_interface *idev; struct driver_info *driver_info; const char *driver_name; wait_queue_head_t *wait; @@ -64,6 +65,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) @@ -178,6 +180,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. --- a/drivers/usb/net/usbnet.c 2007-05-03 15:55:56.000000000 +0200 +++ b/drivers/usb/net/usbnet.c 2007-05-03 14:25:21.000000000 +0200 @@ -588,6 +588,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; } @@ -604,6 +605,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)) @@ -656,8 +660,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; } @@ -758,6 +765,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 @@ -769,6 +793,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->driver_name = name; dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV @@ -1279,7 +1306,8 @@ int usbnet_resume (struct usb_interface if (!--dev->suspend_count) { netif_device_attach (dev->net); - tasklet_schedule (&dev->bh); + if (!test_bit(TASKLET_UNREADY, &dev->flags)) + tasklet_schedule (&dev->bh); } return 0; } --- a/drivers/usb/net/asix.c 2007-05-03 15:53:45.000000000 +0200 +++ b/drivers/usb/net/asix.c 2007-05-03 14:24:05.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