USB: Patch for rtl8150 to fix unplug problems

The RTL8150 driver currently crashes the kernel if the USB lead is unplugged
while the device is active. The attached patch adds error handling to
tell the network layer that the device has gone away when the device is
unplugged. With this patch, the device can be plugged and unplugged
to one's hearts' content, without crashing anything.

Oh, I've also added rudimentary suspend and resume methods.

Signed-off-by: Peter Chubb <peter@gelato.unsw.edu.au>
Acked-by: Petko Manolov <petkan@nucleusys.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by Peter Chubb and committed by Greg Kroah-Hartman 23219c13 6ad576bb

+71 -12
+71 -12
drivers/usb/net/rtl8150.c
··· 175 175 static void rtl8150_disconnect(struct usb_interface *intf); 176 176 static int rtl8150_probe(struct usb_interface *intf, 177 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 181 static const char driver_name [] = "rtl8150"; 180 182 ··· 185 183 .probe = rtl8150_probe, 186 184 .disconnect = rtl8150_disconnect, 187 185 .id_table = rtl8150_table, 186 + .suspend = rtl8150_suspend, 187 + .resume = rtl8150_resume 188 188 }; 189 189 190 190 /* ··· 242 238 usb_fill_control_urb(dev->ctrl_urb, dev->udev, 243 239 usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, 244 240 &dev->rx_creg, size, ctrl_callback, dev); 245 - if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) 241 + if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) { 242 + if (ret == -ENODEV) 243 + netif_device_detach(dev->netdev); 246 244 err("control request submission failed: %d", ret); 247 - else 245 + } else 248 246 set_bit(RX_REG_SET, &dev->flags); 249 247 250 248 return ret; ··· 422 416 struct sk_buff *skb; 423 417 struct net_device *netdev; 424 418 u16 rx_stat; 419 + int status; 425 420 426 421 dev = urb->context; 427 422 if (!dev) ··· 472 465 goon: 473 466 usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), 474 467 dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); 475 - if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { 468 + status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); 469 + if (status == -ENODEV) 470 + netif_device_detach(dev->netdev); 471 + else if (status) { 476 472 set_bit(RX_URB_FAIL, &dev->flags); 477 473 goto resched; 478 474 } else { ··· 491 481 { 492 482 rtl8150_t *dev; 493 483 struct sk_buff *skb; 484 + int status; 494 485 495 486 dev = (rtl8150_t *)data; 496 487 ··· 510 499 usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), 511 500 dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); 512 501 try_again: 513 - if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { 502 + status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); 503 + if (status == -ENODEV) { 504 + netif_device_detach(dev->netdev); 505 + } else if (status) { 514 506 set_bit(RX_URB_FAIL, &dev->flags); 515 507 goto tlsched; 516 - } else { 508 + } else { 517 509 clear_bit(RX_URB_FAIL, &dev->flags); 518 510 } 519 511 ··· 588 574 589 575 resubmit: 590 576 status = usb_submit_urb (urb, SLAB_ATOMIC); 591 - if (status) 577 + if (status == -ENODEV) 578 + netif_device_detach(dev->netdev); 579 + else if (status) 592 580 err ("can't resubmit intr, %s-%s/input0, status %d", 593 581 dev->udev->bus->bus_name, 594 582 dev->udev->devpath, status); 595 583 } 596 584 585 + static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message) 586 + { 587 + rtl8150_t *dev = usb_get_intfdata(intf); 588 + 589 + netif_device_detach(dev->netdev); 590 + 591 + if (netif_running(dev->netdev)) { 592 + usb_kill_urb(dev->rx_urb); 593 + usb_kill_urb(dev->intr_urb); 594 + } 595 + return 0; 596 + } 597 + 598 + static int rtl8150_resume(struct usb_interface *intf) 599 + { 600 + rtl8150_t *dev = usb_get_intfdata(intf); 601 + 602 + netif_device_attach(dev->netdev); 603 + if (netif_running(dev->netdev)) { 604 + dev->rx_urb->status = 0; 605 + dev->rx_urb->actual_length = 0; 606 + read_bulk_callback(dev->rx_urb, NULL); 607 + 608 + dev->intr_urb->status = 0; 609 + dev->intr_urb->actual_length = 0; 610 + intr_callback(dev->intr_urb, NULL); 611 + } 612 + return 0; 613 + } 597 614 598 615 /* 599 616 ** ··· 735 690 usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), 736 691 skb->data, count, write_bulk_callback, dev); 737 692 if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { 738 - warn("failed tx_urb %d\n", res); 739 - dev->stats.tx_errors++; 740 - netif_start_queue(netdev); 693 + /* Can we get/handle EPIPE here? */ 694 + if (res == -ENODEV) 695 + netif_device_detach(dev->netdev); 696 + else { 697 + warn("failed tx_urb %d\n", res); 698 + dev->stats.tx_errors++; 699 + netif_start_queue(netdev); 700 + } 741 701 } else { 742 702 dev->stats.tx_packets++; 743 703 dev->stats.tx_bytes += skb->len; ··· 779 729 780 730 usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), 781 731 dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); 782 - if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) 732 + if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) { 733 + if (res == -ENODEV) 734 + netif_device_detach(dev->netdev); 783 735 warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); 736 + return res; 737 + } 784 738 usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3), 785 739 dev->intr_buff, INTBUFSIZE, intr_callback, 786 740 dev, dev->intr_interval); 787 - if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) 741 + if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) { 742 + if (res == -ENODEV) 743 + netif_device_detach(dev->netdev); 788 744 warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); 789 - netif_start_queue(netdev); 745 + usb_kill_urb(dev->rx_urb); 746 + return res; 747 + } 790 748 enable_net_traffic(dev); 791 749 set_carrier(netdev); 750 + netif_start_queue(netdev); 792 751 793 752 return res; 794 753 }