diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/net/rtl8150.c | 83 |
1 files changed, 71 insertions, 12 deletions
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index e5e6e4f3ef87..bd09232ce13c 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c | |||
@@ -175,6 +175,8 @@ static inline struct sk_buff *pull_skb(rtl8150_t *); | |||
175 | static void rtl8150_disconnect(struct usb_interface *intf); | 175 | static void rtl8150_disconnect(struct usb_interface *intf); |
176 | static int rtl8150_probe(struct usb_interface *intf, | 176 | static int rtl8150_probe(struct usb_interface *intf, |
177 | 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); | ||
178 | 180 | ||
179 | static const char driver_name [] = "rtl8150"; | 181 | static const char driver_name [] = "rtl8150"; |
180 | 182 | ||
@@ -183,6 +185,8 @@ static struct usb_driver rtl8150_driver = { | |||
183 | .probe = rtl8150_probe, | 185 | .probe = rtl8150_probe, |
184 | .disconnect = rtl8150_disconnect, | 186 | .disconnect = rtl8150_disconnect, |
185 | .id_table = rtl8150_table, | 187 | .id_table = rtl8150_table, |
188 | .suspend = rtl8150_suspend, | ||
189 | .resume = rtl8150_resume | ||
186 | }; | 190 | }; |
187 | 191 | ||
188 | /* | 192 | /* |
@@ -238,9 +242,11 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) | |||
238 | usb_fill_control_urb(dev->ctrl_urb, dev->udev, | 242 | usb_fill_control_urb(dev->ctrl_urb, dev->udev, |
239 | usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, | 243 | usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, |
240 | &dev->rx_creg, size, ctrl_callback, dev); | 244 | &dev->rx_creg, size, ctrl_callback, dev); |
241 | 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); | ||
242 | err("control request submission failed: %d", ret); | 248 | err("control request submission failed: %d", ret); |
243 | else | 249 | } else |
244 | set_bit(RX_REG_SET, &dev->flags); | 250 | set_bit(RX_REG_SET, &dev->flags); |
245 | 251 | ||
246 | return ret; | 252 | return ret; |
@@ -416,6 +422,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
416 | struct sk_buff *skb; | 422 | struct sk_buff *skb; |
417 | struct net_device *netdev; | 423 | struct net_device *netdev; |
418 | u16 rx_stat; | 424 | u16 rx_stat; |
425 | int status; | ||
419 | 426 | ||
420 | dev = urb->context; | 427 | dev = urb->context; |
421 | if (!dev) | 428 | if (!dev) |
@@ -465,7 +472,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
465 | goon: | 472 | goon: |
466 | 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), |
467 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); | 474 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); |
468 | 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) { | ||
469 | set_bit(RX_URB_FAIL, &dev->flags); | 479 | set_bit(RX_URB_FAIL, &dev->flags); |
470 | goto resched; | 480 | goto resched; |
471 | } else { | 481 | } else { |
@@ -481,6 +491,7 @@ static void rx_fixup(unsigned long data) | |||
481 | { | 491 | { |
482 | rtl8150_t *dev; | 492 | rtl8150_t *dev; |
483 | struct sk_buff *skb; | 493 | struct sk_buff *skb; |
494 | int status; | ||
484 | 495 | ||
485 | dev = (rtl8150_t *)data; | 496 | dev = (rtl8150_t *)data; |
486 | 497 | ||
@@ -499,10 +510,13 @@ static void rx_fixup(unsigned long data) | |||
499 | 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), |
500 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); | 511 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); |
501 | try_again: | 512 | try_again: |
502 | 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) { | ||
503 | set_bit(RX_URB_FAIL, &dev->flags); | 517 | set_bit(RX_URB_FAIL, &dev->flags); |
504 | goto tlsched; | 518 | goto tlsched; |
505 | } else { | 519 | } else { |
506 | clear_bit(RX_URB_FAIL, &dev->flags); | 520 | clear_bit(RX_URB_FAIL, &dev->flags); |
507 | } | 521 | } |
508 | 522 | ||
@@ -574,12 +588,43 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) | |||
574 | 588 | ||
575 | resubmit: | 589 | resubmit: |
576 | status = usb_submit_urb (urb, SLAB_ATOMIC); | 590 | status = usb_submit_urb (urb, SLAB_ATOMIC); |
577 | if (status) | 591 | if (status == -ENODEV) |
592 | netif_device_detach(dev->netdev); | ||
593 | else if (status) | ||
578 | err ("can't resubmit intr, %s-%s/input0, status %d", | 594 | err ("can't resubmit intr, %s-%s/input0, status %d", |
579 | dev->udev->bus->bus_name, | 595 | dev->udev->bus->bus_name, |
580 | dev->udev->devpath, status); | 596 | dev->udev->devpath, status); |
581 | } | 597 | } |
582 | 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 | } | ||
583 | 628 | ||
584 | /* | 629 | /* |
585 | ** | 630 | ** |
@@ -690,9 +735,14 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
690 | 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), |
691 | skb->data, count, write_bulk_callback, dev); | 736 | skb->data, count, write_bulk_callback, dev); |
692 | if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { | 737 | if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { |
693 | warn("failed tx_urb %d\n", res); | 738 | /* Can we get/handle EPIPE here? */ |
694 | dev->stats.tx_errors++; | 739 | if (res == -ENODEV) |
695 | 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 | } | ||
696 | } else { | 746 | } else { |
697 | dev->stats.tx_packets++; | 747 | dev->stats.tx_packets++; |
698 | dev->stats.tx_bytes += skb->len; | 748 | dev->stats.tx_bytes += skb->len; |
@@ -729,16 +779,25 @@ static int rtl8150_open(struct net_device *netdev) | |||
729 | 779 | ||
730 | 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), |
731 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); | 781 | dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); |
732 | 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); | ||
733 | warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); | 785 | warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); |
786 | return res; | ||
787 | } | ||
734 | 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), |
735 | dev->intr_buff, INTBUFSIZE, intr_callback, | 789 | dev->intr_buff, INTBUFSIZE, intr_callback, |
736 | dev, dev->intr_interval); | 790 | dev, dev->intr_interval); |
737 | 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); | ||
738 | warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); | 794 | warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); |
739 | netif_start_queue(netdev); | 795 | usb_kill_urb(dev->rx_urb); |
796 | return res; | ||
797 | } | ||
740 | enable_net_traffic(dev); | 798 | enable_net_traffic(dev); |
741 | set_carrier(netdev); | 799 | set_carrier(netdev); |
800 | netif_start_queue(netdev); | ||
742 | 801 | ||
743 | return res; | 802 | return res; |
744 | } | 803 | } |