diff options
author | Johan Hovold <jhovold@gmail.com> | 2010-05-15 11:53:46 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:48 -0400 |
commit | 6b6962f9c489ecfa43ae27eb798c46717e203322 (patch) | |
tree | 80efc634058a09fe1b6c95fe5c8cfc8e94c2d4dd /drivers/usb/serial/ipaq.c | |
parent | 695aaae684e249f9f0e7f1ed4caafa0687dbfa5b (diff) |
USB: ipaq: reimplement using generic framework
Kill custom fifo, read and write implementations (single-urb and fifo,
but still maintained list of 256*256b urb buffers per port).
Compile-only tested.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/ipaq.c')
-rw-r--r-- | drivers/usb/serial/ipaq.c | 333 |
1 files changed, 10 insertions, 323 deletions
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 87b11461bf11..28913fa95fb7 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -56,7 +56,6 @@ | |||
56 | #include <linux/uaccess.h> | 56 | #include <linux/uaccess.h> |
57 | #include <linux/usb.h> | 57 | #include <linux/usb.h> |
58 | #include <linux/usb/serial.h> | 58 | #include <linux/usb/serial.h> |
59 | #include "ipaq.h" | ||
60 | 59 | ||
61 | #define KP_RETRIES 100 | 60 | #define KP_RETRIES 100 |
62 | 61 | ||
@@ -64,7 +63,7 @@ | |||
64 | * Version Information | 63 | * Version Information |
65 | */ | 64 | */ |
66 | 65 | ||
67 | #define DRIVER_VERSION "v0.5" | 66 | #define DRIVER_VERSION "v1.0" |
68 | #define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>" | 67 | #define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>" |
69 | #define DRIVER_DESC "USB PocketPC PDA driver" | 68 | #define DRIVER_DESC "USB PocketPC PDA driver" |
70 | 69 | ||
@@ -76,20 +75,8 @@ static int initial_wait; | |||
76 | /* Function prototypes for an ipaq */ | 75 | /* Function prototypes for an ipaq */ |
77 | static int ipaq_open(struct tty_struct *tty, | 76 | static int ipaq_open(struct tty_struct *tty, |
78 | struct usb_serial_port *port); | 77 | struct usb_serial_port *port); |
79 | static void ipaq_close(struct usb_serial_port *port); | ||
80 | static int ipaq_calc_num_ports(struct usb_serial *serial); | 78 | static int ipaq_calc_num_ports(struct usb_serial *serial); |
81 | static int ipaq_startup(struct usb_serial *serial); | 79 | static int ipaq_startup(struct usb_serial *serial); |
82 | static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
83 | const unsigned char *buf, int count); | ||
84 | static int ipaq_write_bulk(struct usb_serial_port *port, | ||
85 | const unsigned char *buf, int count); | ||
86 | static void ipaq_write_gather(struct usb_serial_port *port); | ||
87 | static void ipaq_read_bulk_callback(struct urb *urb); | ||
88 | static void ipaq_write_bulk_callback(struct urb *urb); | ||
89 | static int ipaq_write_room(struct tty_struct *tty); | ||
90 | static int ipaq_chars_in_buffer(struct tty_struct *tty); | ||
91 | static void ipaq_destroy_lists(struct usb_serial_port *port); | ||
92 | |||
93 | 80 | ||
94 | static struct usb_device_id ipaq_id_table [] = { | 81 | static struct usb_device_id ipaq_id_table [] = { |
95 | /* The first entry is a placeholder for the insmod-specified device */ | 82 | /* The first entry is a placeholder for the insmod-specified device */ |
@@ -558,7 +545,7 @@ static struct usb_driver ipaq_driver = { | |||
558 | .probe = usb_serial_probe, | 545 | .probe = usb_serial_probe, |
559 | .disconnect = usb_serial_disconnect, | 546 | .disconnect = usb_serial_disconnect, |
560 | .id_table = ipaq_id_table, | 547 | .id_table = ipaq_id_table, |
561 | .no_dynamic_id = 1, | 548 | .no_dynamic_id = 1, |
562 | }; | 549 | }; |
563 | 550 | ||
564 | 551 | ||
@@ -569,67 +556,24 @@ static struct usb_serial_driver ipaq_device = { | |||
569 | .name = "ipaq", | 556 | .name = "ipaq", |
570 | }, | 557 | }, |
571 | .description = "PocketPC PDA", | 558 | .description = "PocketPC PDA", |
572 | .usb_driver = &ipaq_driver, | 559 | .usb_driver = &ipaq_driver, |
573 | .id_table = ipaq_id_table, | 560 | .id_table = ipaq_id_table, |
574 | .bulk_in_size = URBDATA_SIZE, | 561 | .bulk_in_size = 256, |
575 | .bulk_out_size = URBDATA_SIZE, | 562 | .bulk_out_size = 256, |
576 | .open = ipaq_open, | 563 | .open = ipaq_open, |
577 | .close = ipaq_close, | ||
578 | .attach = ipaq_startup, | 564 | .attach = ipaq_startup, |
579 | .calc_num_ports = ipaq_calc_num_ports, | 565 | .calc_num_ports = ipaq_calc_num_ports, |
580 | .write = ipaq_write, | ||
581 | .write_room = ipaq_write_room, | ||
582 | .chars_in_buffer = ipaq_chars_in_buffer, | ||
583 | .read_bulk_callback = ipaq_read_bulk_callback, | ||
584 | .write_bulk_callback = ipaq_write_bulk_callback, | ||
585 | }; | 566 | }; |
586 | 567 | ||
587 | static spinlock_t write_list_lock; | ||
588 | static int bytes_in; | ||
589 | static int bytes_out; | ||
590 | |||
591 | static int ipaq_open(struct tty_struct *tty, | 568 | static int ipaq_open(struct tty_struct *tty, |
592 | struct usb_serial_port *port) | 569 | struct usb_serial_port *port) |
593 | { | 570 | { |
594 | struct usb_serial *serial = port->serial; | 571 | struct usb_serial *serial = port->serial; |
595 | struct ipaq_private *priv; | 572 | int result = 0; |
596 | struct ipaq_packet *pkt; | ||
597 | int i, result = 0; | ||
598 | int retries = connect_retries; | 573 | int retries = connect_retries; |
599 | 574 | ||
600 | dbg("%s - port %d", __func__, port->number); | 575 | dbg("%s - port %d", __func__, port->number); |
601 | 576 | ||
602 | bytes_in = 0; | ||
603 | bytes_out = 0; | ||
604 | priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL); | ||
605 | if (priv == NULL) { | ||
606 | dev_err(&port->dev, "%s - Out of memory\n", __func__); | ||
607 | return -ENOMEM; | ||
608 | } | ||
609 | usb_set_serial_port_data(port, priv); | ||
610 | priv->active = 0; | ||
611 | priv->queue_len = 0; | ||
612 | priv->free_len = 0; | ||
613 | INIT_LIST_HEAD(&priv->queue); | ||
614 | INIT_LIST_HEAD(&priv->freelist); | ||
615 | |||
616 | for (i = 0; i < URBDATA_QUEUE_MAX / PACKET_SIZE; i++) { | ||
617 | pkt = kmalloc(sizeof(struct ipaq_packet), GFP_KERNEL); | ||
618 | if (pkt == NULL) | ||
619 | goto enomem; | ||
620 | |||
621 | pkt->data = kmalloc(PACKET_SIZE, GFP_KERNEL); | ||
622 | if (pkt->data == NULL) { | ||
623 | kfree(pkt); | ||
624 | goto enomem; | ||
625 | } | ||
626 | pkt->len = 0; | ||
627 | pkt->written = 0; | ||
628 | INIT_LIST_HEAD(&pkt->list); | ||
629 | list_add(&pkt->list, &priv->freelist); | ||
630 | priv->free_len += PACKET_SIZE; | ||
631 | } | ||
632 | |||
633 | msleep(1000*initial_wait); | 577 | msleep(1000*initial_wait); |
634 | 578 | ||
635 | /* | 579 | /* |
@@ -639,7 +583,6 @@ static int ipaq_open(struct tty_struct *tty, | |||
639 | * through. Since this has a reasonably high failure rate, we retry | 583 | * through. Since this has a reasonably high failure rate, we retry |
640 | * several times. | 584 | * several times. |
641 | */ | 585 | */ |
642 | |||
643 | while (retries--) { | 586 | while (retries--) { |
644 | result = usb_control_msg(serial->dev, | 587 | result = usb_control_msg(serial->dev, |
645 | usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21, | 588 | usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21, |
@@ -649,269 +592,15 @@ static int ipaq_open(struct tty_struct *tty, | |||
649 | 592 | ||
650 | msleep(1000); | 593 | msleep(1000); |
651 | } | 594 | } |
652 | |||
653 | if (!retries && result) { | 595 | if (!retries && result) { |
654 | dev_err(&port->dev, "%s - failed doing control urb, error %d\n", __func__, result); | 596 | dev_err(&port->dev, "%s - failed doing control urb, error %d\n", |
655 | goto error; | 597 | __func__, result); |
656 | } | 598 | return result; |
657 | |||
658 | /* Start reading from the device */ | ||
659 | usb_fill_bulk_urb(port->read_urb, serial->dev, | ||
660 | usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), | ||
661 | port->read_urb->transfer_buffer, | ||
662 | port->read_urb->transfer_buffer_length, | ||
663 | ipaq_read_bulk_callback, port); | ||
664 | |||
665 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
666 | if (result) { | ||
667 | dev_err(&port->dev, | ||
668 | "%s - failed submitting read urb, error %d\n", | ||
669 | __func__, result); | ||
670 | goto error; | ||
671 | } | ||
672 | |||
673 | return 0; | ||
674 | |||
675 | enomem: | ||
676 | result = -ENOMEM; | ||
677 | dev_err(&port->dev, "%s - Out of memory\n", __func__); | ||
678 | error: | ||
679 | ipaq_destroy_lists(port); | ||
680 | kfree(priv); | ||
681 | return result; | ||
682 | } | ||
683 | |||
684 | |||
685 | static void ipaq_close(struct usb_serial_port *port) | ||
686 | { | ||
687 | struct ipaq_private *priv = usb_get_serial_port_data(port); | ||
688 | |||
689 | dbg("%s - port %d", __func__, port->number); | ||
690 | |||
691 | /* | ||
692 | * shut down bulk read and write | ||
693 | */ | ||
694 | usb_kill_urb(port->write_urb); | ||
695 | usb_kill_urb(port->read_urb); | ||
696 | ipaq_destroy_lists(port); | ||
697 | kfree(priv); | ||
698 | usb_set_serial_port_data(port, NULL); | ||
699 | |||
700 | /* Uncomment the following line if you want to see some statistics | ||
701 | * in your syslog */ | ||
702 | /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */ | ||
703 | } | ||
704 | |||
705 | static void ipaq_read_bulk_callback(struct urb *urb) | ||
706 | { | ||
707 | struct usb_serial_port *port = urb->context; | ||
708 | struct tty_struct *tty; | ||
709 | unsigned char *data = urb->transfer_buffer; | ||
710 | int result; | ||
711 | int status = urb->status; | ||
712 | |||
713 | dbg("%s - port %d", __func__, port->number); | ||
714 | |||
715 | if (status) { | ||
716 | dbg("%s - nonzero read bulk status received: %d", | ||
717 | __func__, status); | ||
718 | return; | ||
719 | } | 599 | } |
720 | 600 | ||
721 | usb_serial_debug_data(debug, &port->dev, __func__, | 601 | return usb_serial_generic_open(tty, port); |
722 | urb->actual_length, data); | ||
723 | |||
724 | tty = tty_port_tty_get(&port->port); | ||
725 | if (tty && urb->actual_length) { | ||
726 | tty_insert_flip_string(tty, data, urb->actual_length); | ||
727 | tty_flip_buffer_push(tty); | ||
728 | bytes_in += urb->actual_length; | ||
729 | } | ||
730 | tty_kref_put(tty); | ||
731 | |||
732 | /* Continue trying to always read */ | ||
733 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | ||
734 | usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), | ||
735 | port->read_urb->transfer_buffer, | ||
736 | port->read_urb->transfer_buffer_length, | ||
737 | ipaq_read_bulk_callback, port); | ||
738 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
739 | if (result) | ||
740 | dev_err(&port->dev, | ||
741 | "%s - failed resubmitting read urb, error %d\n", | ||
742 | __func__, result); | ||
743 | return; | ||
744 | } | 602 | } |
745 | 603 | ||
746 | static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
747 | const unsigned char *buf, int count) | ||
748 | { | ||
749 | const unsigned char *current_position = buf; | ||
750 | int bytes_sent = 0; | ||
751 | int transfer_size; | ||
752 | |||
753 | dbg("%s - port %d", __func__, port->number); | ||
754 | |||
755 | while (count > 0) { | ||
756 | transfer_size = min(count, PACKET_SIZE); | ||
757 | if (ipaq_write_bulk(port, current_position, transfer_size)) | ||
758 | break; | ||
759 | current_position += transfer_size; | ||
760 | bytes_sent += transfer_size; | ||
761 | count -= transfer_size; | ||
762 | bytes_out += transfer_size; | ||
763 | } | ||
764 | |||
765 | return bytes_sent; | ||
766 | } | ||
767 | |||
768 | static int ipaq_write_bulk(struct usb_serial_port *port, | ||
769 | const unsigned char *buf, int count) | ||
770 | { | ||
771 | struct ipaq_private *priv = usb_get_serial_port_data(port); | ||
772 | struct ipaq_packet *pkt = NULL; | ||
773 | int result = 0; | ||
774 | unsigned long flags; | ||
775 | |||
776 | if (priv->free_len <= 0) { | ||
777 | dbg("%s - we're stuffed", __func__); | ||
778 | return -EAGAIN; | ||
779 | } | ||
780 | |||
781 | spin_lock_irqsave(&write_list_lock, flags); | ||
782 | if (!list_empty(&priv->freelist)) { | ||
783 | pkt = list_entry(priv->freelist.next, struct ipaq_packet, list); | ||
784 | list_del(&pkt->list); | ||
785 | priv->free_len -= PACKET_SIZE; | ||
786 | } | ||
787 | spin_unlock_irqrestore(&write_list_lock, flags); | ||
788 | if (pkt == NULL) { | ||
789 | dbg("%s - we're stuffed", __func__); | ||
790 | return -EAGAIN; | ||
791 | } | ||
792 | |||
793 | memcpy(pkt->data, buf, count); | ||
794 | usb_serial_debug_data(debug, &port->dev, __func__, count, pkt->data); | ||
795 | |||
796 | pkt->len = count; | ||
797 | pkt->written = 0; | ||
798 | spin_lock_irqsave(&write_list_lock, flags); | ||
799 | list_add_tail(&pkt->list, &priv->queue); | ||
800 | priv->queue_len += count; | ||
801 | if (priv->active == 0) { | ||
802 | priv->active = 1; | ||
803 | ipaq_write_gather(port); | ||
804 | spin_unlock_irqrestore(&write_list_lock, flags); | ||
805 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
806 | if (result) | ||
807 | dev_err(&port->dev, | ||
808 | "%s - failed submitting write urb, error %d\n", | ||
809 | __func__, result); | ||
810 | } else { | ||
811 | spin_unlock_irqrestore(&write_list_lock, flags); | ||
812 | } | ||
813 | return result; | ||
814 | } | ||
815 | |||
816 | static void ipaq_write_gather(struct usb_serial_port *port) | ||
817 | { | ||
818 | struct ipaq_private *priv = usb_get_serial_port_data(port); | ||
819 | struct usb_serial *serial = port->serial; | ||
820 | int count, room; | ||
821 | struct ipaq_packet *pkt, *tmp; | ||
822 | struct urb *urb = port->write_urb; | ||
823 | |||
824 | room = URBDATA_SIZE; | ||
825 | list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { | ||
826 | count = min(room, (int)(pkt->len - pkt->written)); | ||
827 | memcpy(urb->transfer_buffer + (URBDATA_SIZE - room), | ||
828 | pkt->data + pkt->written, count); | ||
829 | room -= count; | ||
830 | pkt->written += count; | ||
831 | priv->queue_len -= count; | ||
832 | if (pkt->written == pkt->len) { | ||
833 | list_move(&pkt->list, &priv->freelist); | ||
834 | priv->free_len += PACKET_SIZE; | ||
835 | } | ||
836 | if (room == 0) | ||
837 | break; | ||
838 | } | ||
839 | |||
840 | count = URBDATA_SIZE - room; | ||
841 | usb_fill_bulk_urb(port->write_urb, serial->dev, | ||
842 | usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), | ||
843 | port->write_urb->transfer_buffer, count, | ||
844 | ipaq_write_bulk_callback, port); | ||
845 | return; | ||
846 | } | ||
847 | |||
848 | static void ipaq_write_bulk_callback(struct urb *urb) | ||
849 | { | ||
850 | struct usb_serial_port *port = urb->context; | ||
851 | struct ipaq_private *priv = usb_get_serial_port_data(port); | ||
852 | unsigned long flags; | ||
853 | int result; | ||
854 | int status = urb->status; | ||
855 | |||
856 | dbg("%s - port %d", __func__, port->number); | ||
857 | |||
858 | if (status) { | ||
859 | dbg("%s - nonzero write bulk status received: %d", | ||
860 | __func__, status); | ||
861 | return; | ||
862 | } | ||
863 | |||
864 | spin_lock_irqsave(&write_list_lock, flags); | ||
865 | if (!list_empty(&priv->queue)) { | ||
866 | ipaq_write_gather(port); | ||
867 | spin_unlock_irqrestore(&write_list_lock, flags); | ||
868 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
869 | if (result) | ||
870 | dev_err(&port->dev, | ||
871 | "%s - failed submitting write urb, error %d\n", | ||
872 | __func__, result); | ||
873 | } else { | ||
874 | priv->active = 0; | ||
875 | spin_unlock_irqrestore(&write_list_lock, flags); | ||
876 | } | ||
877 | |||
878 | usb_serial_port_softint(port); | ||
879 | } | ||
880 | |||
881 | static int ipaq_write_room(struct tty_struct *tty) | ||
882 | { | ||
883 | struct usb_serial_port *port = tty->driver_data; | ||
884 | struct ipaq_private *priv = usb_get_serial_port_data(port); | ||
885 | |||
886 | dbg("%s - freelen %d", __func__, priv->free_len); | ||
887 | return priv->free_len; | ||
888 | } | ||
889 | |||
890 | static int ipaq_chars_in_buffer(struct tty_struct *tty) | ||
891 | { | ||
892 | struct usb_serial_port *port = tty->driver_data; | ||
893 | struct ipaq_private *priv = usb_get_serial_port_data(port); | ||
894 | |||
895 | dbg("%s - queuelen %d", __func__, priv->queue_len); | ||
896 | return priv->queue_len; | ||
897 | } | ||
898 | |||
899 | static void ipaq_destroy_lists(struct usb_serial_port *port) | ||
900 | { | ||
901 | struct ipaq_private *priv = usb_get_serial_port_data(port); | ||
902 | struct ipaq_packet *pkt, *tmp; | ||
903 | |||
904 | list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { | ||
905 | kfree(pkt->data); | ||
906 | kfree(pkt); | ||
907 | } | ||
908 | list_for_each_entry_safe(pkt, tmp, &priv->freelist, list) { | ||
909 | kfree(pkt->data); | ||
910 | kfree(pkt); | ||
911 | } | ||
912 | } | ||
913 | |||
914 | |||
915 | static int ipaq_calc_num_ports(struct usb_serial *serial) | 604 | static int ipaq_calc_num_ports(struct usb_serial *serial) |
916 | { | 605 | { |
917 | /* | 606 | /* |
@@ -970,7 +659,6 @@ static int ipaq_startup(struct usb_serial *serial) | |||
970 | static int __init ipaq_init(void) | 659 | static int __init ipaq_init(void) |
971 | { | 660 | { |
972 | int retval; | 661 | int retval; |
973 | spin_lock_init(&write_list_lock); | ||
974 | retval = usb_serial_register(&ipaq_device); | 662 | retval = usb_serial_register(&ipaq_device); |
975 | if (retval) | 663 | if (retval) |
976 | goto failed_usb_serial_register; | 664 | goto failed_usb_serial_register; |
@@ -991,7 +679,6 @@ failed_usb_serial_register: | |||
991 | return retval; | 679 | return retval; |
992 | } | 680 | } |
993 | 681 | ||
994 | |||
995 | static void __exit ipaq_exit(void) | 682 | static void __exit ipaq_exit(void) |
996 | { | 683 | { |
997 | usb_deregister(&ipaq_driver); | 684 | usb_deregister(&ipaq_driver); |