diff options
Diffstat (limited to 'drivers/usb/net/rtl8150.c')
-rw-r--r-- | drivers/usb/net/rtl8150.c | 87 |
1 files changed, 75 insertions, 12 deletions
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index 718f8e2b552b..a72685b96061 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c | |||
@@ -128,11 +128,13 @@ | |||
128 | #define VENDOR_ID_MELCO 0x0411 | 128 | #define VENDOR_ID_MELCO 0x0411 |
129 | #define VENDOR_ID_MICRONET 0x3980 | 129 | #define VENDOR_ID_MICRONET 0x3980 |
130 | #define VENDOR_ID_LONGSHINE 0x07b8 | 130 | #define VENDOR_ID_LONGSHINE 0x07b8 |
131 | #define VENDOR_ID_ZYXEL 0x0586 | ||
131 | 132 | ||
132 | #define PRODUCT_ID_RTL8150 0x8150 | 133 | #define PRODUCT_ID_RTL8150 0x8150 |
133 | #define PRODUCT_ID_LUAKTX 0x0012 | 134 | #define PRODUCT_ID_LUAKTX 0x0012 |
134 | #define PRODUCT_ID_LCS8138TX 0x401a | 135 | #define PRODUCT_ID_LCS8138TX 0x401a |
135 | #define PRODUCT_ID_SP128AR 0x0003 | 136 | #define PRODUCT_ID_SP128AR 0x0003 |
137 | #define PRODUCT_ID_PRESTIGE 0x401a | ||
136 | 138 | ||
137 | #undef EEPROM_WRITE | 139 | #undef EEPROM_WRITE |
138 | 140 | ||
@@ -142,6 +144,7 @@ static struct usb_device_id rtl8150_table[] = { | |||
142 | {USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)}, | 144 | {USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)}, |
143 | {USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)}, | 145 | {USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)}, |
144 | {USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)}, | 146 | {USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)}, |
147 | {USB_DEVICE(VENDOR_ID_ZYXEL, PRODUCT_ID_PRESTIGE)}, | ||
145 | {} | 148 | {} |
146 | }; | 149 | }; |
147 | 150 | ||
@@ -172,6 +175,8 @@ static inline struct sk_buff *pull_skb(rtl8150_t *); | |||
172 | static void rtl8150_disconnect(struct usb_interface *intf); | 175 | static void rtl8150_disconnect(struct usb_interface *intf); |
173 | static int rtl8150_probe(struct usb_interface *intf, | 176 | static int rtl8150_probe(struct usb_interface *intf, |
174 | const struct usb_device_id *id); | 177 | const struct usb_device_id *id); |
178 | static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message); | ||
179 | static int rtl8150_resume(struct usb_interface *intf); | ||
175 | 180 | ||
176 | static const char driver_name [] = "rtl8150"; | 181 | static const char driver_name [] = "rtl8150"; |
177 | 182 | ||
@@ -180,6 +185,8 @@ static struct usb_driver rtl8150_driver = { | |||
180 | .probe = rtl8150_probe, | 185 | .probe = rtl8150_probe, |
181 | .disconnect = rtl8150_disconnect, | 186 | .disconnect = rtl8150_disconnect, |
182 | .id_table = rtl8150_table, | 187 | .id_table = rtl8150_table, |
188 | .suspend = rtl8150_suspend, | ||
189 | .resume = rtl8150_resume | ||
183 | }; | 190 | }; |
184 | 191 | ||
185 | /* | 192 | /* |
@@ -235,9 +242,11 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) | |||
235 | usb_fill_control_urb(dev->ctrl_urb, dev->udev, | 242 | usb_fill_control_urb(dev->ctrl_urb, dev->udev, |
236 | usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, | 243 | usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, |
237 | &dev->rx_creg, size, ctrl_callback, dev); | 244 | &dev->rx_creg, size, ctrl_callback, dev); |
238 | if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) | 245 | if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) { |
246 | if (ret == -ENODEV) | ||
247 | netif_device_detach(dev->netdev); | ||
239 | err("control request submission failed: %d", ret); | 248 | err("control request submission failed: %d", ret); |
240 | else | 249 | } else |
241 | set_bit(RX_REG_SET, &dev->flags); | 250 | set_bit(RX_REG_SET, &dev->flags); |
242 | 251 | ||
243 | return ret; | 252 | return ret; |
@@ -413,6 +422,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
413 | struct sk_buff *skb; | 422 | struct sk_buff *skb; |
414 | struct net_device *netdev; | 423 | struct net_device *netdev; |
415 | u16 rx_stat; | 424 | u16 rx_stat; |
425 | int status; | ||
416 | 426 | ||
417 | dev = urb->context; | 427 | dev = urb->context; |
418 | if (!dev) | 428 | if (!dev) |
@@ -462,7 +472,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
462 | goon: | 472 | goon: |
463 | usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), | 473 | usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), |
464 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); | 474 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); |
465 | if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { | 475 | status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); |
476 | if (status == -ENODEV) | ||
477 | netif_device_detach(dev->netdev); | ||
478 | else if (status) { | ||
466 | set_bit(RX_URB_FAIL, &dev->flags); | 479 | set_bit(RX_URB_FAIL, &dev->flags); |
467 | goto resched; | 480 | goto resched; |
468 | } else { | 481 | } else { |
@@ -478,6 +491,7 @@ static void rx_fixup(unsigned long data) | |||
478 | { | 491 | { |
479 | rtl8150_t *dev; | 492 | rtl8150_t *dev; |
480 | struct sk_buff *skb; | 493 | struct sk_buff *skb; |
494 | int status; | ||
481 | 495 | ||
482 | dev = (rtl8150_t *)data; | 496 | dev = (rtl8150_t *)data; |
483 | 497 | ||
@@ -496,10 +510,13 @@ static void rx_fixup(unsigned long data) | |||
496 | usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), | 510 | usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), |
497 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); | 511 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); |
498 | try_again: | 512 | try_again: |
499 | if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { | 513 | status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); |
514 | if (status == -ENODEV) { | ||
515 | netif_device_detach(dev->netdev); | ||
516 | } else if (status) { | ||
500 | set_bit(RX_URB_FAIL, &dev->flags); | 517 | set_bit(RX_URB_FAIL, &dev->flags); |
501 | goto tlsched; | 518 | goto tlsched; |
502 | } else { | 519 | } else { |
503 | clear_bit(RX_URB_FAIL, &dev->flags); | 520 | clear_bit(RX_URB_FAIL, &dev->flags); |
504 | } | 521 | } |
505 | 522 | ||
@@ -571,12 +588,43 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) | |||
571 | 588 | ||
572 | resubmit: | 589 | resubmit: |
573 | status = usb_submit_urb (urb, SLAB_ATOMIC); | 590 | status = usb_submit_urb (urb, SLAB_ATOMIC); |
574 | if (status) | 591 | if (status == -ENODEV) |
592 | netif_device_detach(dev->netdev); | ||
593 | else if (status) | ||
575 | err ("can't resubmit intr, %s-%s/input0, status %d", | 594 | err ("can't resubmit intr, %s-%s/input0, status %d", |
576 | dev->udev->bus->bus_name, | 595 | dev->udev->bus->bus_name, |
577 | dev->udev->devpath, status); | 596 | dev->udev->devpath, status); |
578 | } | 597 | } |
579 | 598 | ||
599 | static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message) | ||
600 | { | ||
601 | rtl8150_t *dev = usb_get_intfdata(intf); | ||
602 | |||
603 | netif_device_detach(dev->netdev); | ||
604 | |||
605 | if (netif_running(dev->netdev)) { | ||
606 | usb_kill_urb(dev->rx_urb); | ||
607 | usb_kill_urb(dev->intr_urb); | ||
608 | } | ||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static int rtl8150_resume(struct usb_interface *intf) | ||
613 | { | ||
614 | rtl8150_t *dev = usb_get_intfdata(intf); | ||
615 | |||
616 | netif_device_attach(dev->netdev); | ||
617 | if (netif_running(dev->netdev)) { | ||
618 | dev->rx_urb->status = 0; | ||
619 | dev->rx_urb->actual_length = 0; | ||
620 | read_bulk_callback(dev->rx_urb, NULL); | ||
621 | |||
622 | dev->intr_urb->status = 0; | ||
623 | dev->intr_urb->actual_length = 0; | ||
624 | intr_callback(dev->intr_urb, NULL); | ||
625 | } | ||
626 | return 0; | ||
627 | } | ||
580 | 628 | ||
581 | /* | 629 | /* |
582 | ** | 630 | ** |
@@ -687,9 +735,14 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
687 | usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), | 735 | usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), |
688 | skb->data, count, write_bulk_callback, dev); | 736 | skb->data, count, write_bulk_callback, dev); |
689 | if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { | 737 | if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { |
690 | warn("failed tx_urb %d\n", res); | 738 | /* Can we get/handle EPIPE here? */ |
691 | dev->stats.tx_errors++; | 739 | if (res == -ENODEV) |
692 | netif_start_queue(netdev); | 740 | netif_device_detach(dev->netdev); |
741 | else { | ||
742 | warn("failed tx_urb %d\n", res); | ||
743 | dev->stats.tx_errors++; | ||
744 | netif_start_queue(netdev); | ||
745 | } | ||
693 | } else { | 746 | } else { |
694 | dev->stats.tx_packets++; | 747 | dev->stats.tx_packets++; |
695 | dev->stats.tx_bytes += skb->len; | 748 | dev->stats.tx_bytes += skb->len; |
@@ -726,16 +779,25 @@ static int rtl8150_open(struct net_device *netdev) | |||
726 | 779 | ||
727 | usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), | 780 | usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), |
728 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); | 781 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); |
729 | if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) | 782 | if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) { |
783 | if (res == -ENODEV) | ||
784 | netif_device_detach(dev->netdev); | ||
730 | warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); | 785 | warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); |
786 | return res; | ||
787 | } | ||
731 | usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3), | 788 | usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3), |
732 | dev->intr_buff, INTBUFSIZE, intr_callback, | 789 | dev->intr_buff, INTBUFSIZE, intr_callback, |
733 | dev, dev->intr_interval); | 790 | dev, dev->intr_interval); |
734 | if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) | 791 | if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) { |
792 | if (res == -ENODEV) | ||
793 | netif_device_detach(dev->netdev); | ||
735 | warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); | 794 | warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); |
736 | netif_start_queue(netdev); | 795 | usb_kill_urb(dev->rx_urb); |
796 | return res; | ||
797 | } | ||
737 | enable_net_traffic(dev); | 798 | enable_net_traffic(dev); |
738 | set_carrier(netdev); | 799 | set_carrier(netdev); |
800 | netif_start_queue(netdev); | ||
739 | 801 | ||
740 | return res; | 802 | return res; |
741 | } | 803 | } |
@@ -910,6 +972,7 @@ static void rtl8150_disconnect(struct usb_interface *intf) | |||
910 | if (dev) { | 972 | if (dev) { |
911 | set_bit(RTL8150_UNPLUG, &dev->flags); | 973 | set_bit(RTL8150_UNPLUG, &dev->flags); |
912 | tasklet_disable(&dev->tl); | 974 | tasklet_disable(&dev->tl); |
975 | tasklet_kill(&dev->tl); | ||
913 | unregister_netdev(dev->netdev); | 976 | unregister_netdev(dev->netdev); |
914 | unlink_all_urbs(dev); | 977 | unlink_all_urbs(dev); |
915 | free_all_urbs(dev); | 978 | free_all_urbs(dev); |