diff options
Diffstat (limited to 'drivers/mfd/dln2.c')
-rw-r--r-- | drivers/mfd/dln2.c | 71 |
1 files changed, 61 insertions, 10 deletions
diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c index 6d49685d4ee4..1be9bd1c046d 100644 --- a/drivers/mfd/dln2.c +++ b/drivers/mfd/dln2.c | |||
@@ -587,12 +587,19 @@ static void dln2_free_rx_urbs(struct dln2_dev *dln2) | |||
587 | int i; | 587 | int i; |
588 | 588 | ||
589 | for (i = 0; i < DLN2_MAX_URBS; i++) { | 589 | for (i = 0; i < DLN2_MAX_URBS; i++) { |
590 | usb_kill_urb(dln2->rx_urb[i]); | ||
591 | usb_free_urb(dln2->rx_urb[i]); | 590 | usb_free_urb(dln2->rx_urb[i]); |
592 | kfree(dln2->rx_buf[i]); | 591 | kfree(dln2->rx_buf[i]); |
593 | } | 592 | } |
594 | } | 593 | } |
595 | 594 | ||
595 | static void dln2_stop_rx_urbs(struct dln2_dev *dln2) | ||
596 | { | ||
597 | int i; | ||
598 | |||
599 | for (i = 0; i < DLN2_MAX_URBS; i++) | ||
600 | usb_kill_urb(dln2->rx_urb[i]); | ||
601 | } | ||
602 | |||
596 | static void dln2_free(struct dln2_dev *dln2) | 603 | static void dln2_free(struct dln2_dev *dln2) |
597 | { | 604 | { |
598 | dln2_free_rx_urbs(dln2); | 605 | dln2_free_rx_urbs(dln2); |
@@ -604,9 +611,7 @@ static int dln2_setup_rx_urbs(struct dln2_dev *dln2, | |||
604 | struct usb_host_interface *hostif) | 611 | struct usb_host_interface *hostif) |
605 | { | 612 | { |
606 | int i; | 613 | int i; |
607 | int ret; | ||
608 | const int rx_max_size = DLN2_RX_BUF_SIZE; | 614 | const int rx_max_size = DLN2_RX_BUF_SIZE; |
609 | struct device *dev = &dln2->interface->dev; | ||
610 | 615 | ||
611 | for (i = 0; i < DLN2_MAX_URBS; i++) { | 616 | for (i = 0; i < DLN2_MAX_URBS; i++) { |
612 | dln2->rx_buf[i] = kmalloc(rx_max_size, GFP_KERNEL); | 617 | dln2->rx_buf[i] = kmalloc(rx_max_size, GFP_KERNEL); |
@@ -620,8 +625,19 @@ static int dln2_setup_rx_urbs(struct dln2_dev *dln2, | |||
620 | usb_fill_bulk_urb(dln2->rx_urb[i], dln2->usb_dev, | 625 | usb_fill_bulk_urb(dln2->rx_urb[i], dln2->usb_dev, |
621 | usb_rcvbulkpipe(dln2->usb_dev, dln2->ep_in), | 626 | usb_rcvbulkpipe(dln2->usb_dev, dln2->ep_in), |
622 | dln2->rx_buf[i], rx_max_size, dln2_rx, dln2); | 627 | dln2->rx_buf[i], rx_max_size, dln2_rx, dln2); |
628 | } | ||
623 | 629 | ||
624 | ret = usb_submit_urb(dln2->rx_urb[i], GFP_KERNEL); | 630 | return 0; |
631 | } | ||
632 | |||
633 | static int dln2_start_rx_urbs(struct dln2_dev *dln2, gfp_t gfp) | ||
634 | { | ||
635 | struct device *dev = &dln2->interface->dev; | ||
636 | int ret; | ||
637 | int i; | ||
638 | |||
639 | for (i = 0; i < DLN2_MAX_URBS; i++) { | ||
640 | ret = usb_submit_urb(dln2->rx_urb[i], gfp); | ||
625 | if (ret < 0) { | 641 | if (ret < 0) { |
626 | dev_err(dev, "failed to submit RX URB: %d\n", ret); | 642 | dev_err(dev, "failed to submit RX URB: %d\n", ret); |
627 | return ret; | 643 | return ret; |
@@ -665,9 +681,8 @@ static const struct mfd_cell dln2_devs[] = { | |||
665 | }, | 681 | }, |
666 | }; | 682 | }; |
667 | 683 | ||
668 | static void dln2_disconnect(struct usb_interface *interface) | 684 | static void dln2_stop(struct dln2_dev *dln2) |
669 | { | 685 | { |
670 | struct dln2_dev *dln2 = usb_get_intfdata(interface); | ||
671 | int i, j; | 686 | int i, j; |
672 | 687 | ||
673 | /* don't allow starting new transfers */ | 688 | /* don't allow starting new transfers */ |
@@ -696,6 +711,15 @@ static void dln2_disconnect(struct usb_interface *interface) | |||
696 | /* wait for transfers to end */ | 711 | /* wait for transfers to end */ |
697 | wait_event(dln2->disconnect_wq, !dln2->active_transfers); | 712 | wait_event(dln2->disconnect_wq, !dln2->active_transfers); |
698 | 713 | ||
714 | dln2_stop_rx_urbs(dln2); | ||
715 | } | ||
716 | |||
717 | static void dln2_disconnect(struct usb_interface *interface) | ||
718 | { | ||
719 | struct dln2_dev *dln2 = usb_get_intfdata(interface); | ||
720 | |||
721 | dln2_stop(dln2); | ||
722 | |||
699 | mfd_remove_devices(&interface->dev); | 723 | mfd_remove_devices(&interface->dev); |
700 | 724 | ||
701 | dln2_free(dln2); | 725 | dln2_free(dln2); |
@@ -738,28 +762,53 @@ static int dln2_probe(struct usb_interface *interface, | |||
738 | 762 | ||
739 | ret = dln2_setup_rx_urbs(dln2, hostif); | 763 | ret = dln2_setup_rx_urbs(dln2, hostif); |
740 | if (ret) | 764 | if (ret) |
741 | goto out_cleanup; | 765 | goto out_free; |
766 | |||
767 | ret = dln2_start_rx_urbs(dln2, GFP_KERNEL); | ||
768 | if (ret) | ||
769 | goto out_stop_rx; | ||
742 | 770 | ||
743 | ret = dln2_hw_init(dln2); | 771 | ret = dln2_hw_init(dln2); |
744 | if (ret < 0) { | 772 | if (ret < 0) { |
745 | dev_err(dev, "failed to initialize hardware\n"); | 773 | dev_err(dev, "failed to initialize hardware\n"); |
746 | goto out_cleanup; | 774 | goto out_stop_rx; |
747 | } | 775 | } |
748 | 776 | ||
749 | ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs)); | 777 | ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs)); |
750 | if (ret != 0) { | 778 | if (ret != 0) { |
751 | dev_err(dev, "failed to add mfd devices to core\n"); | 779 | dev_err(dev, "failed to add mfd devices to core\n"); |
752 | goto out_cleanup; | 780 | goto out_stop_rx; |
753 | } | 781 | } |
754 | 782 | ||
755 | return 0; | 783 | return 0; |
756 | 784 | ||
757 | out_cleanup: | 785 | out_stop_rx: |
786 | dln2_stop_rx_urbs(dln2); | ||
787 | |||
788 | out_free: | ||
758 | dln2_free(dln2); | 789 | dln2_free(dln2); |
759 | 790 | ||
760 | return ret; | 791 | return ret; |
761 | } | 792 | } |
762 | 793 | ||
794 | static int dln2_suspend(struct usb_interface *iface, pm_message_t message) | ||
795 | { | ||
796 | struct dln2_dev *dln2 = usb_get_intfdata(iface); | ||
797 | |||
798 | dln2_stop(dln2); | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static int dln2_resume(struct usb_interface *iface) | ||
804 | { | ||
805 | struct dln2_dev *dln2 = usb_get_intfdata(iface); | ||
806 | |||
807 | dln2->disconnect = false; | ||
808 | |||
809 | return dln2_start_rx_urbs(dln2, GFP_NOIO); | ||
810 | } | ||
811 | |||
763 | static const struct usb_device_id dln2_table[] = { | 812 | static const struct usb_device_id dln2_table[] = { |
764 | { USB_DEVICE(0xa257, 0x2013) }, | 813 | { USB_DEVICE(0xa257, 0x2013) }, |
765 | { } | 814 | { } |
@@ -772,6 +821,8 @@ static struct usb_driver dln2_driver = { | |||
772 | .probe = dln2_probe, | 821 | .probe = dln2_probe, |
773 | .disconnect = dln2_disconnect, | 822 | .disconnect = dln2_disconnect, |
774 | .id_table = dln2_table, | 823 | .id_table = dln2_table, |
824 | .suspend = dln2_suspend, | ||
825 | .resume = dln2_resume, | ||
775 | }; | 826 | }; |
776 | 827 | ||
777 | module_usb_driver(dln2_driver); | 828 | module_usb_driver(dln2_driver); |