diff options
Diffstat (limited to 'drivers/usb/net/rtl8150.c')
-rw-r--r-- | drivers/usb/net/rtl8150.c | 90 |
1 files changed, 76 insertions, 14 deletions
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index 1bbbae283c0b..2364c2099387 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c | |||
@@ -6,7 +6,6 @@ | |||
6 | * version 2 as published by the Free Software Foundation. | 6 | * version 2 as published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/config.h> | ||
10 | #include <linux/sched.h> | 9 | #include <linux/sched.h> |
11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
12 | #include <linux/signal.h> | 11 | #include <linux/signal.h> |
@@ -129,11 +128,13 @@ | |||
129 | #define VENDOR_ID_MELCO 0x0411 | 128 | #define VENDOR_ID_MELCO 0x0411 |
130 | #define VENDOR_ID_MICRONET 0x3980 | 129 | #define VENDOR_ID_MICRONET 0x3980 |
131 | #define VENDOR_ID_LONGSHINE 0x07b8 | 130 | #define VENDOR_ID_LONGSHINE 0x07b8 |
131 | #define VENDOR_ID_ZYXEL 0x0586 | ||
132 | 132 | ||
133 | #define PRODUCT_ID_RTL8150 0x8150 | 133 | #define PRODUCT_ID_RTL8150 0x8150 |
134 | #define PRODUCT_ID_LUAKTX 0x0012 | 134 | #define PRODUCT_ID_LUAKTX 0x0012 |
135 | #define PRODUCT_ID_LCS8138TX 0x401a | 135 | #define PRODUCT_ID_LCS8138TX 0x401a |
136 | #define PRODUCT_ID_SP128AR 0x0003 | 136 | #define PRODUCT_ID_SP128AR 0x0003 |
137 | #define PRODUCT_ID_PRESTIGE 0x401a | ||
137 | 138 | ||
138 | #undef EEPROM_WRITE | 139 | #undef EEPROM_WRITE |
139 | 140 | ||
@@ -143,6 +144,7 @@ static struct usb_device_id rtl8150_table[] = { | |||
143 | {USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)}, | 144 | {USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)}, |
144 | {USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)}, | 145 | {USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)}, |
145 | {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)}, | ||
146 | {} | 148 | {} |
147 | }; | 149 | }; |
148 | 150 | ||
@@ -173,6 +175,8 @@ static inline struct sk_buff *pull_skb(rtl8150_t *); | |||
173 | static void rtl8150_disconnect(struct usb_interface *intf); | 175 | static void rtl8150_disconnect(struct usb_interface *intf); |
174 | static int rtl8150_probe(struct usb_interface *intf, | 176 | static int rtl8150_probe(struct usb_interface *intf, |
175 | 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); | ||
176 | 180 | ||
177 | static const char driver_name [] = "rtl8150"; | 181 | static const char driver_name [] = "rtl8150"; |
178 | 182 | ||
@@ -181,6 +185,8 @@ static struct usb_driver rtl8150_driver = { | |||
181 | .probe = rtl8150_probe, | 185 | .probe = rtl8150_probe, |
182 | .disconnect = rtl8150_disconnect, | 186 | .disconnect = rtl8150_disconnect, |
183 | .id_table = rtl8150_table, | 187 | .id_table = rtl8150_table, |
188 | .suspend = rtl8150_suspend, | ||
189 | .resume = rtl8150_resume | ||
184 | }; | 190 | }; |
185 | 191 | ||
186 | /* | 192 | /* |
@@ -236,9 +242,11 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) | |||
236 | usb_fill_control_urb(dev->ctrl_urb, dev->udev, | 242 | usb_fill_control_urb(dev->ctrl_urb, dev->udev, |
237 | usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, | 243 | usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, |
238 | &dev->rx_creg, size, ctrl_callback, dev); | 244 | &dev->rx_creg, size, ctrl_callback, dev); |
239 | 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); | ||
240 | err("control request submission failed: %d", ret); | 248 | err("control request submission failed: %d", ret); |
241 | else | 249 | } else |
242 | set_bit(RX_REG_SET, &dev->flags); | 250 | set_bit(RX_REG_SET, &dev->flags); |
243 | 251 | ||
244 | return ret; | 252 | return ret; |
@@ -414,6 +422,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
414 | struct sk_buff *skb; | 422 | struct sk_buff *skb; |
415 | struct net_device *netdev; | 423 | struct net_device *netdev; |
416 | u16 rx_stat; | 424 | u16 rx_stat; |
425 | int status; | ||
417 | 426 | ||
418 | dev = urb->context; | 427 | dev = urb->context; |
419 | if (!dev) | 428 | if (!dev) |
@@ -429,7 +438,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
429 | break; | 438 | break; |
430 | case -ENOENT: | 439 | case -ENOENT: |
431 | return; /* the urb is in unlink state */ | 440 | return; /* the urb is in unlink state */ |
432 | case -ETIMEDOUT: | 441 | case -ETIME: |
433 | warn("may be reset is needed?.."); | 442 | warn("may be reset is needed?.."); |
434 | goto goon; | 443 | goto goon; |
435 | default: | 444 | default: |
@@ -463,7 +472,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
463 | goon: | 472 | goon: |
464 | 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), |
465 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); | 474 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); |
466 | 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) { | ||
467 | set_bit(RX_URB_FAIL, &dev->flags); | 479 | set_bit(RX_URB_FAIL, &dev->flags); |
468 | goto resched; | 480 | goto resched; |
469 | } else { | 481 | } else { |
@@ -479,6 +491,7 @@ static void rx_fixup(unsigned long data) | |||
479 | { | 491 | { |
480 | rtl8150_t *dev; | 492 | rtl8150_t *dev; |
481 | struct sk_buff *skb; | 493 | struct sk_buff *skb; |
494 | int status; | ||
482 | 495 | ||
483 | dev = (rtl8150_t *)data; | 496 | dev = (rtl8150_t *)data; |
484 | 497 | ||
@@ -497,10 +510,13 @@ static void rx_fixup(unsigned long data) | |||
497 | 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), |
498 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); | 511 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); |
499 | try_again: | 512 | try_again: |
500 | 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) { | ||
501 | set_bit(RX_URB_FAIL, &dev->flags); | 517 | set_bit(RX_URB_FAIL, &dev->flags); |
502 | goto tlsched; | 518 | goto tlsched; |
503 | } else { | 519 | } else { |
504 | clear_bit(RX_URB_FAIL, &dev->flags); | 520 | clear_bit(RX_URB_FAIL, &dev->flags); |
505 | } | 521 | } |
506 | 522 | ||
@@ -572,12 +588,43 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) | |||
572 | 588 | ||
573 | resubmit: | 589 | resubmit: |
574 | status = usb_submit_urb (urb, SLAB_ATOMIC); | 590 | status = usb_submit_urb (urb, SLAB_ATOMIC); |
575 | if (status) | 591 | if (status == -ENODEV) |
592 | netif_device_detach(dev->netdev); | ||
593 | else if (status) | ||
576 | err ("can't resubmit intr, %s-%s/input0, status %d", | 594 | err ("can't resubmit intr, %s-%s/input0, status %d", |
577 | dev->udev->bus->bus_name, | 595 | dev->udev->bus->bus_name, |
578 | dev->udev->devpath, status); | 596 | dev->udev->devpath, status); |
579 | } | 597 | } |
580 | 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 | } | ||
581 | 628 | ||
582 | /* | 629 | /* |
583 | ** | 630 | ** |
@@ -688,9 +735,14 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
688 | 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), |
689 | skb->data, count, write_bulk_callback, dev); | 736 | skb->data, count, write_bulk_callback, dev); |
690 | if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { | 737 | if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { |
691 | warn("failed tx_urb %d\n", res); | 738 | /* Can we get/handle EPIPE here? */ |
692 | dev->stats.tx_errors++; | 739 | if (res == -ENODEV) |
693 | 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 | } | ||
694 | } else { | 746 | } else { |
695 | dev->stats.tx_packets++; | 747 | dev->stats.tx_packets++; |
696 | dev->stats.tx_bytes += skb->len; | 748 | dev->stats.tx_bytes += skb->len; |
@@ -727,16 +779,25 @@ static int rtl8150_open(struct net_device *netdev) | |||
727 | 779 | ||
728 | 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), |
729 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); | 781 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); |
730 | 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); | ||
731 | warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); | 785 | warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); |
786 | return res; | ||
787 | } | ||
732 | 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), |
733 | dev->intr_buff, INTBUFSIZE, intr_callback, | 789 | dev->intr_buff, INTBUFSIZE, intr_callback, |
734 | dev, dev->intr_interval); | 790 | dev, dev->intr_interval); |
735 | 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); | ||
736 | warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); | 794 | warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); |
737 | netif_start_queue(netdev); | 795 | usb_kill_urb(dev->rx_urb); |
796 | return res; | ||
797 | } | ||
738 | enable_net_traffic(dev); | 798 | enable_net_traffic(dev); |
739 | set_carrier(netdev); | 799 | set_carrier(netdev); |
800 | netif_start_queue(netdev); | ||
740 | 801 | ||
741 | return res; | 802 | return res; |
742 | } | 803 | } |
@@ -911,6 +972,7 @@ static void rtl8150_disconnect(struct usb_interface *intf) | |||
911 | if (dev) { | 972 | if (dev) { |
912 | set_bit(RTL8150_UNPLUG, &dev->flags); | 973 | set_bit(RTL8150_UNPLUG, &dev->flags); |
913 | tasklet_disable(&dev->tl); | 974 | tasklet_disable(&dev->tl); |
975 | tasklet_kill(&dev->tl); | ||
914 | unregister_netdev(dev->netdev); | 976 | unregister_netdev(dev->netdev); |
915 | unlink_all_urbs(dev); | 977 | unlink_all_urbs(dev); |
916 | free_all_urbs(dev); | 978 | free_all_urbs(dev); |