aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/dln2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/dln2.c')
-rw-r--r--drivers/mfd/dln2.c71
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
595static 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
596static void dln2_free(struct dln2_dev *dln2) 603static 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
633static 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
668static void dln2_disconnect(struct usb_interface *interface) 684static 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
717static 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
757out_cleanup: 785out_stop_rx:
786 dln2_stop_rx_urbs(dln2);
787
788out_free:
758 dln2_free(dln2); 789 dln2_free(dln2);
759 790
760 return ret; 791 return ret;
761} 792}
762 793
794static 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
803static 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
763static const struct usb_device_id dln2_table[] = { 812static 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
777module_usb_driver(dln2_driver); 828module_usb_driver(dln2_driver);