diff options
Diffstat (limited to 'drivers/usb/net/rtl8150.c')
| -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 | } | 
