diff options
-rw-r--r-- | drivers/net/usb/cdc_ether.c | 8 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.c | 157 | ||||
-rw-r--r-- | include/linux/usb/usbnet.h | 6 |
3 files changed, 142 insertions, 29 deletions
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 197912d9c04a..21e183a83b99 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c | |||
@@ -411,6 +411,12 @@ static int cdc_bind(struct usbnet *dev, struct usb_interface *intf) | |||
411 | return 0; | 411 | return 0; |
412 | } | 412 | } |
413 | 413 | ||
414 | static int cdc_manage_power(struct usbnet *dev, int on) | ||
415 | { | ||
416 | dev->intf->needs_remote_wakeup = on; | ||
417 | return 0; | ||
418 | } | ||
419 | |||
414 | static const struct driver_info cdc_info = { | 420 | static const struct driver_info cdc_info = { |
415 | .description = "CDC Ethernet Device", | 421 | .description = "CDC Ethernet Device", |
416 | .flags = FLAG_ETHER | FLAG_LINK_INTR, | 422 | .flags = FLAG_ETHER | FLAG_LINK_INTR, |
@@ -418,6 +424,7 @@ static const struct driver_info cdc_info = { | |||
418 | .bind = cdc_bind, | 424 | .bind = cdc_bind, |
419 | .unbind = usbnet_cdc_unbind, | 425 | .unbind = usbnet_cdc_unbind, |
420 | .status = cdc_status, | 426 | .status = cdc_status, |
427 | .manage_power = cdc_manage_power, | ||
421 | }; | 428 | }; |
422 | 429 | ||
423 | static const struct driver_info mbm_info = { | 430 | static const struct driver_info mbm_info = { |
@@ -619,6 +626,7 @@ static struct usb_driver cdc_driver = { | |||
619 | .suspend = usbnet_suspend, | 626 | .suspend = usbnet_suspend, |
620 | .resume = usbnet_resume, | 627 | .resume = usbnet_resume, |
621 | .reset_resume = usbnet_resume, | 628 | .reset_resume = usbnet_resume, |
629 | .supports_autosuspend = 1, | ||
622 | }; | 630 | }; |
623 | 631 | ||
624 | 632 | ||
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 511e7bdc4573..035fab04c0a0 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -353,7 +353,8 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) | |||
353 | 353 | ||
354 | if (netif_running (dev->net) && | 354 | if (netif_running (dev->net) && |
355 | netif_device_present (dev->net) && | 355 | netif_device_present (dev->net) && |
356 | !test_bit (EVENT_RX_HALT, &dev->flags)) { | 356 | !test_bit (EVENT_RX_HALT, &dev->flags) && |
357 | !test_bit (EVENT_DEV_ASLEEP, &dev->flags)) { | ||
357 | switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) { | 358 | switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) { |
358 | case -EPIPE: | 359 | case -EPIPE: |
359 | usbnet_defer_kevent (dev, EVENT_RX_HALT); | 360 | usbnet_defer_kevent (dev, EVENT_RX_HALT); |
@@ -611,15 +612,39 @@ EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs); | |||
611 | /*-------------------------------------------------------------------------*/ | 612 | /*-------------------------------------------------------------------------*/ |
612 | 613 | ||
613 | // precondition: never called in_interrupt | 614 | // precondition: never called in_interrupt |
615 | static void usbnet_terminate_urbs(struct usbnet *dev) | ||
616 | { | ||
617 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup); | ||
618 | DECLARE_WAITQUEUE(wait, current); | ||
619 | int temp; | ||
620 | |||
621 | /* ensure there are no more active urbs */ | ||
622 | add_wait_queue(&unlink_wakeup, &wait); | ||
623 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
624 | dev->wait = &unlink_wakeup; | ||
625 | temp = unlink_urbs(dev, &dev->txq) + | ||
626 | unlink_urbs(dev, &dev->rxq); | ||
627 | |||
628 | /* maybe wait for deletions to finish. */ | ||
629 | while (!skb_queue_empty(&dev->rxq) | ||
630 | && !skb_queue_empty(&dev->txq) | ||
631 | && !skb_queue_empty(&dev->done)) { | ||
632 | schedule_timeout(UNLINK_TIMEOUT_MS); | ||
633 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
634 | if (netif_msg_ifdown(dev)) | ||
635 | devdbg(dev, "waited for %d urb completions", | ||
636 | temp); | ||
637 | } | ||
638 | set_current_state(TASK_RUNNING); | ||
639 | dev->wait = NULL; | ||
640 | remove_wait_queue(&unlink_wakeup, &wait); | ||
641 | } | ||
614 | 642 | ||
615 | int usbnet_stop (struct net_device *net) | 643 | int usbnet_stop (struct net_device *net) |
616 | { | 644 | { |
617 | struct usbnet *dev = netdev_priv(net); | 645 | struct usbnet *dev = netdev_priv(net); |
618 | struct driver_info *info = dev->driver_info; | 646 | struct driver_info *info = dev->driver_info; |
619 | int temp; | ||
620 | int retval; | 647 | int retval; |
621 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK (unlink_wakeup); | ||
622 | DECLARE_WAITQUEUE (wait, current); | ||
623 | 648 | ||
624 | netif_stop_queue (net); | 649 | netif_stop_queue (net); |
625 | 650 | ||
@@ -641,25 +666,8 @@ int usbnet_stop (struct net_device *net) | |||
641 | info->description); | 666 | info->description); |
642 | } | 667 | } |
643 | 668 | ||
644 | if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) { | 669 | if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) |
645 | /* ensure there are no more active urbs */ | 670 | usbnet_terminate_urbs(dev); |
646 | add_wait_queue(&unlink_wakeup, &wait); | ||
647 | dev->wait = &unlink_wakeup; | ||
648 | temp = unlink_urbs(dev, &dev->txq) + | ||
649 | unlink_urbs(dev, &dev->rxq); | ||
650 | |||
651 | /* maybe wait for deletions to finish. */ | ||
652 | while (!skb_queue_empty(&dev->rxq) && | ||
653 | !skb_queue_empty(&dev->txq) && | ||
654 | !skb_queue_empty(&dev->done)) { | ||
655 | msleep(UNLINK_TIMEOUT_MS); | ||
656 | if (netif_msg_ifdown(dev)) | ||
657 | devdbg(dev, "waited for %d urb completions", | ||
658 | temp); | ||
659 | } | ||
660 | dev->wait = NULL; | ||
661 | remove_wait_queue(&unlink_wakeup, &wait); | ||
662 | } | ||
663 | 671 | ||
664 | usb_kill_urb(dev->interrupt); | 672 | usb_kill_urb(dev->interrupt); |
665 | 673 | ||
@@ -672,7 +680,10 @@ int usbnet_stop (struct net_device *net) | |||
672 | dev->flags = 0; | 680 | dev->flags = 0; |
673 | del_timer_sync (&dev->delay); | 681 | del_timer_sync (&dev->delay); |
674 | tasklet_kill (&dev->bh); | 682 | tasklet_kill (&dev->bh); |
675 | usb_autopm_put_interface(dev->intf); | 683 | if (info->manage_power) |
684 | info->manage_power(dev, 0); | ||
685 | else | ||
686 | usb_autopm_put_interface(dev->intf); | ||
676 | 687 | ||
677 | return 0; | 688 | return 0; |
678 | } | 689 | } |
@@ -753,6 +764,12 @@ int usbnet_open (struct net_device *net) | |||
753 | 764 | ||
754 | // delay posting reads until we're fully open | 765 | // delay posting reads until we're fully open |
755 | tasklet_schedule (&dev->bh); | 766 | tasklet_schedule (&dev->bh); |
767 | if (info->manage_power) { | ||
768 | retval = info->manage_power(dev, 1); | ||
769 | if (retval < 0) | ||
770 | goto done; | ||
771 | usb_autopm_put_interface(dev->intf); | ||
772 | } | ||
756 | return retval; | 773 | return retval; |
757 | done: | 774 | done: |
758 | usb_autopm_put_interface(dev->intf); | 775 | usb_autopm_put_interface(dev->intf); |
@@ -881,11 +898,16 @@ kevent (struct work_struct *work) | |||
881 | /* usb_clear_halt() needs a thread context */ | 898 | /* usb_clear_halt() needs a thread context */ |
882 | if (test_bit (EVENT_TX_HALT, &dev->flags)) { | 899 | if (test_bit (EVENT_TX_HALT, &dev->flags)) { |
883 | unlink_urbs (dev, &dev->txq); | 900 | unlink_urbs (dev, &dev->txq); |
901 | status = usb_autopm_get_interface(dev->intf); | ||
902 | if (status < 0) | ||
903 | goto fail_pipe; | ||
884 | status = usb_clear_halt (dev->udev, dev->out); | 904 | status = usb_clear_halt (dev->udev, dev->out); |
905 | usb_autopm_put_interface(dev->intf); | ||
885 | if (status < 0 && | 906 | if (status < 0 && |
886 | status != -EPIPE && | 907 | status != -EPIPE && |
887 | status != -ESHUTDOWN) { | 908 | status != -ESHUTDOWN) { |
888 | if (netif_msg_tx_err (dev)) | 909 | if (netif_msg_tx_err (dev)) |
910 | fail_pipe: | ||
889 | deverr (dev, "can't clear tx halt, status %d", | 911 | deverr (dev, "can't clear tx halt, status %d", |
890 | status); | 912 | status); |
891 | } else { | 913 | } else { |
@@ -896,11 +918,16 @@ kevent (struct work_struct *work) | |||
896 | } | 918 | } |
897 | if (test_bit (EVENT_RX_HALT, &dev->flags)) { | 919 | if (test_bit (EVENT_RX_HALT, &dev->flags)) { |
898 | unlink_urbs (dev, &dev->rxq); | 920 | unlink_urbs (dev, &dev->rxq); |
921 | status = usb_autopm_get_interface(dev->intf); | ||
922 | if (status < 0) | ||
923 | goto fail_halt; | ||
899 | status = usb_clear_halt (dev->udev, dev->in); | 924 | status = usb_clear_halt (dev->udev, dev->in); |
925 | usb_autopm_put_interface(dev->intf); | ||
900 | if (status < 0 && | 926 | if (status < 0 && |
901 | status != -EPIPE && | 927 | status != -EPIPE && |
902 | status != -ESHUTDOWN) { | 928 | status != -ESHUTDOWN) { |
903 | if (netif_msg_rx_err (dev)) | 929 | if (netif_msg_rx_err (dev)) |
930 | fail_halt: | ||
904 | deverr (dev, "can't clear rx halt, status %d", | 931 | deverr (dev, "can't clear rx halt, status %d", |
905 | status); | 932 | status); |
906 | } else { | 933 | } else { |
@@ -919,7 +946,12 @@ kevent (struct work_struct *work) | |||
919 | clear_bit (EVENT_RX_MEMORY, &dev->flags); | 946 | clear_bit (EVENT_RX_MEMORY, &dev->flags); |
920 | if (urb != NULL) { | 947 | if (urb != NULL) { |
921 | clear_bit (EVENT_RX_MEMORY, &dev->flags); | 948 | clear_bit (EVENT_RX_MEMORY, &dev->flags); |
949 | status = usb_autopm_get_interface(dev->intf); | ||
950 | if (status < 0) | ||
951 | goto fail_lowmem; | ||
922 | rx_submit (dev, urb, GFP_KERNEL); | 952 | rx_submit (dev, urb, GFP_KERNEL); |
953 | usb_autopm_put_interface(dev->intf); | ||
954 | fail_lowmem: | ||
923 | tasklet_schedule (&dev->bh); | 955 | tasklet_schedule (&dev->bh); |
924 | } | 956 | } |
925 | } | 957 | } |
@@ -929,11 +961,18 @@ kevent (struct work_struct *work) | |||
929 | int retval = 0; | 961 | int retval = 0; |
930 | 962 | ||
931 | clear_bit (EVENT_LINK_RESET, &dev->flags); | 963 | clear_bit (EVENT_LINK_RESET, &dev->flags); |
964 | status = usb_autopm_get_interface(dev->intf); | ||
965 | if (status < 0) | ||
966 | goto skip_reset; | ||
932 | if(info->link_reset && (retval = info->link_reset(dev)) < 0) { | 967 | if(info->link_reset && (retval = info->link_reset(dev)) < 0) { |
968 | usb_autopm_put_interface(dev->intf); | ||
969 | skip_reset: | ||
933 | devinfo(dev, "link reset failed (%d) usbnet usb-%s-%s, %s", | 970 | devinfo(dev, "link reset failed (%d) usbnet usb-%s-%s, %s", |
934 | retval, | 971 | retval, |
935 | dev->udev->bus->bus_name, dev->udev->devpath, | 972 | dev->udev->bus->bus_name, dev->udev->devpath, |
936 | info->description); | 973 | info->description); |
974 | } else { | ||
975 | usb_autopm_put_interface(dev->intf); | ||
937 | } | 976 | } |
938 | } | 977 | } |
939 | 978 | ||
@@ -971,6 +1010,7 @@ static void tx_complete (struct urb *urb) | |||
971 | case -EPROTO: | 1010 | case -EPROTO: |
972 | case -ETIME: | 1011 | case -ETIME: |
973 | case -EILSEQ: | 1012 | case -EILSEQ: |
1013 | usb_mark_last_busy(dev->udev); | ||
974 | if (!timer_pending (&dev->delay)) { | 1014 | if (!timer_pending (&dev->delay)) { |
975 | mod_timer (&dev->delay, | 1015 | mod_timer (&dev->delay, |
976 | jiffies + THROTTLE_JIFFIES); | 1016 | jiffies + THROTTLE_JIFFIES); |
@@ -987,6 +1027,7 @@ static void tx_complete (struct urb *urb) | |||
987 | } | 1027 | } |
988 | } | 1028 | } |
989 | 1029 | ||
1030 | usb_autopm_put_interface_async(dev->intf); | ||
990 | urb->dev = NULL; | 1031 | urb->dev = NULL; |
991 | entry->state = tx_done; | 1032 | entry->state = tx_done; |
992 | defer_bh(dev, skb, &dev->txq); | 1033 | defer_bh(dev, skb, &dev->txq); |
@@ -1057,14 +1098,34 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, | |||
1057 | } | 1098 | } |
1058 | } | 1099 | } |
1059 | 1100 | ||
1060 | spin_lock_irqsave (&dev->txq.lock, flags); | 1101 | spin_lock_irqsave(&dev->txq.lock, flags); |
1102 | retval = usb_autopm_get_interface_async(dev->intf); | ||
1103 | if (retval < 0) { | ||
1104 | spin_unlock_irqrestore(&dev->txq.lock, flags); | ||
1105 | goto drop; | ||
1106 | } | ||
1107 | |||
1108 | #ifdef CONFIG_PM | ||
1109 | /* if this triggers the device is still a sleep */ | ||
1110 | if (test_bit(EVENT_DEV_ASLEEP, &dev->flags)) { | ||
1111 | /* transmission will be done in resume */ | ||
1112 | usb_anchor_urb(urb, &dev->deferred); | ||
1113 | /* no use to process more packets */ | ||
1114 | netif_stop_queue(net); | ||
1115 | spin_unlock_irqrestore(&dev->txq.lock, flags); | ||
1116 | devdbg(dev, "Delaying transmission for resumption"); | ||
1117 | goto deferred; | ||
1118 | } | ||
1119 | #endif | ||
1061 | 1120 | ||
1062 | switch ((retval = usb_submit_urb (urb, GFP_ATOMIC))) { | 1121 | switch ((retval = usb_submit_urb (urb, GFP_ATOMIC))) { |
1063 | case -EPIPE: | 1122 | case -EPIPE: |
1064 | netif_stop_queue (net); | 1123 | netif_stop_queue (net); |
1065 | usbnet_defer_kevent (dev, EVENT_TX_HALT); | 1124 | usbnet_defer_kevent (dev, EVENT_TX_HALT); |
1125 | usb_autopm_put_interface_async(dev->intf); | ||
1066 | break; | 1126 | break; |
1067 | default: | 1127 | default: |
1128 | usb_autopm_put_interface_async(dev->intf); | ||
1068 | if (netif_msg_tx_err (dev)) | 1129 | if (netif_msg_tx_err (dev)) |
1069 | devdbg (dev, "tx: submit urb err %d", retval); | 1130 | devdbg (dev, "tx: submit urb err %d", retval); |
1070 | break; | 1131 | break; |
@@ -1088,6 +1149,9 @@ drop: | |||
1088 | devdbg (dev, "> tx, len %d, type 0x%x", | 1149 | devdbg (dev, "> tx, len %d, type 0x%x", |
1089 | length, skb->protocol); | 1150 | length, skb->protocol); |
1090 | } | 1151 | } |
1152 | #ifdef CONFIG_PM | ||
1153 | deferred: | ||
1154 | #endif | ||
1091 | return NETDEV_TX_OK; | 1155 | return NETDEV_TX_OK; |
1092 | } | 1156 | } |
1093 | EXPORT_SYMBOL_GPL(usbnet_start_xmit); | 1157 | EXPORT_SYMBOL_GPL(usbnet_start_xmit); |
@@ -1263,6 +1327,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) | |||
1263 | dev->bh.func = usbnet_bh; | 1327 | dev->bh.func = usbnet_bh; |
1264 | dev->bh.data = (unsigned long) dev; | 1328 | dev->bh.data = (unsigned long) dev; |
1265 | INIT_WORK (&dev->kevent, kevent); | 1329 | INIT_WORK (&dev->kevent, kevent); |
1330 | init_usb_anchor(&dev->deferred); | ||
1266 | dev->delay.function = usbnet_bh; | 1331 | dev->delay.function = usbnet_bh; |
1267 | dev->delay.data = (unsigned long) dev; | 1332 | dev->delay.data = (unsigned long) dev; |
1268 | init_timer (&dev->delay); | 1333 | init_timer (&dev->delay); |
@@ -1382,13 +1447,23 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message) | |||
1382 | struct usbnet *dev = usb_get_intfdata(intf); | 1447 | struct usbnet *dev = usb_get_intfdata(intf); |
1383 | 1448 | ||
1384 | if (!dev->suspend_count++) { | 1449 | if (!dev->suspend_count++) { |
1450 | spin_lock_irq(&dev->txq.lock); | ||
1451 | /* don't autosuspend while transmitting */ | ||
1452 | if (dev->txq.qlen && (message.event & PM_EVENT_AUTO)) { | ||
1453 | spin_unlock_irq(&dev->txq.lock); | ||
1454 | return -EBUSY; | ||
1455 | } else { | ||
1456 | set_bit(EVENT_DEV_ASLEEP, &dev->flags); | ||
1457 | spin_unlock_irq(&dev->txq.lock); | ||
1458 | } | ||
1385 | /* | 1459 | /* |
1386 | * accelerate emptying of the rx and queues, to avoid | 1460 | * accelerate emptying of the rx and queues, to avoid |
1387 | * having everything error out. | 1461 | * having everything error out. |
1388 | */ | 1462 | */ |
1389 | netif_device_detach (dev->net); | 1463 | netif_device_detach (dev->net); |
1390 | (void) unlink_urbs (dev, &dev->rxq); | 1464 | usbnet_terminate_urbs(dev); |
1391 | (void) unlink_urbs (dev, &dev->txq); | 1465 | usb_kill_urb(dev->interrupt); |
1466 | |||
1392 | /* | 1467 | /* |
1393 | * reattach so runtime management can use and | 1468 | * reattach so runtime management can use and |
1394 | * wake the device | 1469 | * wake the device |
@@ -1402,10 +1477,34 @@ EXPORT_SYMBOL_GPL(usbnet_suspend); | |||
1402 | int usbnet_resume (struct usb_interface *intf) | 1477 | int usbnet_resume (struct usb_interface *intf) |
1403 | { | 1478 | { |
1404 | struct usbnet *dev = usb_get_intfdata(intf); | 1479 | struct usbnet *dev = usb_get_intfdata(intf); |
1480 | struct sk_buff *skb; | ||
1481 | struct urb *res; | ||
1482 | int retval; | ||
1483 | |||
1484 | if (!--dev->suspend_count) { | ||
1485 | spin_lock_irq(&dev->txq.lock); | ||
1486 | while ((res = usb_get_from_anchor(&dev->deferred))) { | ||
1487 | |||
1488 | printk(KERN_INFO"%s has delayed data\n", __func__); | ||
1489 | skb = (struct sk_buff *)res->context; | ||
1490 | retval = usb_submit_urb(res, GFP_ATOMIC); | ||
1491 | if (retval < 0) { | ||
1492 | dev_kfree_skb_any(skb); | ||
1493 | usb_free_urb(res); | ||
1494 | usb_autopm_put_interface_async(dev->intf); | ||
1495 | } else { | ||
1496 | dev->net->trans_start = jiffies; | ||
1497 | __skb_queue_tail(&dev->txq, skb); | ||
1498 | } | ||
1499 | } | ||
1405 | 1500 | ||
1406 | if (!--dev->suspend_count) | 1501 | smp_mb(); |
1502 | clear_bit(EVENT_DEV_ASLEEP, &dev->flags); | ||
1503 | spin_unlock_irq(&dev->txq.lock); | ||
1504 | if (!(dev->txq.qlen >= TX_QLEN(dev))) | ||
1505 | netif_start_queue(dev->net); | ||
1407 | tasklet_schedule (&dev->bh); | 1506 | tasklet_schedule (&dev->bh); |
1408 | 1507 | } | |
1409 | return 0; | 1508 | return 0; |
1410 | } | 1509 | } |
1411 | EXPORT_SYMBOL_GPL(usbnet_resume); | 1510 | EXPORT_SYMBOL_GPL(usbnet_resume); |
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 8c84881f8478..8ce61359bf73 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h | |||
@@ -55,6 +55,7 @@ struct usbnet { | |||
55 | struct sk_buff_head done; | 55 | struct sk_buff_head done; |
56 | struct sk_buff_head rxq_pause; | 56 | struct sk_buff_head rxq_pause; |
57 | struct urb *interrupt; | 57 | struct urb *interrupt; |
58 | struct usb_anchor deferred; | ||
58 | struct tasklet_struct bh; | 59 | struct tasklet_struct bh; |
59 | 60 | ||
60 | struct work_struct kevent; | 61 | struct work_struct kevent; |
@@ -65,6 +66,8 @@ struct usbnet { | |||
65 | # define EVENT_STS_SPLIT 3 | 66 | # define EVENT_STS_SPLIT 3 |
66 | # define EVENT_LINK_RESET 4 | 67 | # define EVENT_LINK_RESET 4 |
67 | # define EVENT_RX_PAUSED 5 | 68 | # define EVENT_RX_PAUSED 5 |
69 | # define EVENT_DEV_WAKING 6 | ||
70 | # define EVENT_DEV_ASLEEP 7 | ||
68 | }; | 71 | }; |
69 | 72 | ||
70 | static inline struct usb_driver *driver_of(struct usb_interface *intf) | 73 | static inline struct usb_driver *driver_of(struct usb_interface *intf) |
@@ -109,6 +112,9 @@ struct driver_info { | |||
109 | /* see if peer is connected ... can sleep */ | 112 | /* see if peer is connected ... can sleep */ |
110 | int (*check_connect)(struct usbnet *); | 113 | int (*check_connect)(struct usbnet *); |
111 | 114 | ||
115 | /* (dis)activate runtime power management */ | ||
116 | int (*manage_power)(struct usbnet *, int); | ||
117 | |||
112 | /* for status polling */ | 118 | /* for status polling */ |
113 | void (*status)(struct usbnet *, struct urb *); | 119 | void (*status)(struct usbnet *, struct urb *); |
114 | 120 | ||