diff options
author | Johan Hovold <jhovold@gmail.com> | 2010-05-18 18:01:37 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:50 -0400 |
commit | d733cec1ab0ab3b34e4acfc413cb31157eea67c3 (patch) | |
tree | 56b606d0e7ac5fecf2ce162e67d80ced30da33e5 /drivers/usb | |
parent | a3a30f10f56987a1df0dea857a706273145ed6fd (diff) |
USB: io_ti: use kfifo to implement write buffering
Kill custom fifo implementation.
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')
-rw-r--r-- | drivers/usb/serial/io_ti.c | 223 |
1 files changed, 13 insertions, 210 deletions
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 2e3d0acbc389..0fca2659206f 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/spinlock.h> | 36 | #include <linux/spinlock.h> |
37 | #include <linux/mutex.h> | 37 | #include <linux/mutex.h> |
38 | #include <linux/serial.h> | 38 | #include <linux/serial.h> |
39 | #include <linux/kfifo.h> | ||
39 | #include <linux/ioctl.h> | 40 | #include <linux/ioctl.h> |
40 | #include <linux/firmware.h> | 41 | #include <linux/firmware.h> |
41 | #include <linux/uaccess.h> | 42 | #include <linux/uaccess.h> |
@@ -83,14 +84,6 @@ struct product_info { | |||
83 | __u8 hardware_type; /* Type of hardware */ | 84 | __u8 hardware_type; /* Type of hardware */ |
84 | } __attribute__((packed)); | 85 | } __attribute__((packed)); |
85 | 86 | ||
86 | /* circular buffer */ | ||
87 | struct edge_buf { | ||
88 | unsigned int buf_size; | ||
89 | char *buf_buf; | ||
90 | char *buf_get; | ||
91 | char *buf_put; | ||
92 | }; | ||
93 | |||
94 | struct edgeport_port { | 87 | struct edgeport_port { |
95 | __u16 uart_base; | 88 | __u16 uart_base; |
96 | __u16 dma_address; | 89 | __u16 dma_address; |
@@ -114,7 +107,7 @@ struct edgeport_port { | |||
114 | spinlock_t ep_lock; | 107 | spinlock_t ep_lock; |
115 | int ep_read_urb_state; | 108 | int ep_read_urb_state; |
116 | int ep_write_urb_in_use; | 109 | int ep_write_urb_in_use; |
117 | struct edge_buf *ep_out_buf; | 110 | struct kfifo write_fifo; |
118 | }; | 111 | }; |
119 | 112 | ||
120 | struct edgeport_serial { | 113 | struct edgeport_serial { |
@@ -244,17 +237,6 @@ static void edge_send(struct tty_struct *tty); | |||
244 | static int edge_create_sysfs_attrs(struct usb_serial_port *port); | 237 | static int edge_create_sysfs_attrs(struct usb_serial_port *port); |
245 | static int edge_remove_sysfs_attrs(struct usb_serial_port *port); | 238 | static int edge_remove_sysfs_attrs(struct usb_serial_port *port); |
246 | 239 | ||
247 | /* circular buffer */ | ||
248 | static struct edge_buf *edge_buf_alloc(unsigned int size); | ||
249 | static void edge_buf_free(struct edge_buf *eb); | ||
250 | static void edge_buf_clear(struct edge_buf *eb); | ||
251 | static unsigned int edge_buf_data_avail(struct edge_buf *eb); | ||
252 | static unsigned int edge_buf_space_avail(struct edge_buf *eb); | ||
253 | static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf, | ||
254 | unsigned int count); | ||
255 | static unsigned int edge_buf_get(struct edge_buf *eb, char *buf, | ||
256 | unsigned int count); | ||
257 | |||
258 | 240 | ||
259 | static int ti_vread_sync(struct usb_device *dev, __u8 request, | 241 | static int ti_vread_sync(struct usb_device *dev, __u8 request, |
260 | __u16 value, __u16 index, u8 *data, int size) | 242 | __u16 value, __u16 index, u8 *data, int size) |
@@ -585,7 +567,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, | |||
585 | add_wait_queue(&tty->write_wait, &wait); | 567 | add_wait_queue(&tty->write_wait, &wait); |
586 | for (;;) { | 568 | for (;;) { |
587 | set_current_state(TASK_INTERRUPTIBLE); | 569 | set_current_state(TASK_INTERRUPTIBLE); |
588 | if (edge_buf_data_avail(port->ep_out_buf) == 0 | 570 | if (kfifo_len(&port->write_fifo) == 0 |
589 | || timeout == 0 || signal_pending(current) | 571 | || timeout == 0 || signal_pending(current) |
590 | || !usb_get_intfdata(port->port->serial->interface)) | 572 | || !usb_get_intfdata(port->port->serial->interface)) |
591 | /* disconnect */ | 573 | /* disconnect */ |
@@ -597,7 +579,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, | |||
597 | set_current_state(TASK_RUNNING); | 579 | set_current_state(TASK_RUNNING); |
598 | remove_wait_queue(&tty->write_wait, &wait); | 580 | remove_wait_queue(&tty->write_wait, &wait); |
599 | if (flush) | 581 | if (flush) |
600 | edge_buf_clear(port->ep_out_buf); | 582 | kfifo_reset_out(&port->write_fifo); |
601 | spin_unlock_irqrestore(&port->ep_lock, flags); | 583 | spin_unlock_irqrestore(&port->ep_lock, flags); |
602 | tty_kref_put(tty); | 584 | tty_kref_put(tty); |
603 | 585 | ||
@@ -2084,7 +2066,6 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
2084 | const unsigned char *data, int count) | 2066 | const unsigned char *data, int count) |
2085 | { | 2067 | { |
2086 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | 2068 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); |
2087 | unsigned long flags; | ||
2088 | 2069 | ||
2089 | dbg("%s - port %d", __func__, port->number); | 2070 | dbg("%s - port %d", __func__, port->number); |
2090 | 2071 | ||
@@ -2098,10 +2079,8 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
2098 | if (edge_port->close_pending == 1) | 2079 | if (edge_port->close_pending == 1) |
2099 | return -ENODEV; | 2080 | return -ENODEV; |
2100 | 2081 | ||
2101 | spin_lock_irqsave(&edge_port->ep_lock, flags); | 2082 | count = kfifo_in_locked(&edge_port->write_fifo, data, count, |
2102 | count = edge_buf_put(edge_port->ep_out_buf, data, count); | 2083 | &edge_port->ep_lock); |
2103 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
2104 | |||
2105 | edge_send(tty); | 2084 | edge_send(tty); |
2106 | 2085 | ||
2107 | return count; | 2086 | return count; |
@@ -2124,7 +2103,7 @@ static void edge_send(struct tty_struct *tty) | |||
2124 | return; | 2103 | return; |
2125 | } | 2104 | } |
2126 | 2105 | ||
2127 | count = edge_buf_get(edge_port->ep_out_buf, | 2106 | count = kfifo_out(&edge_port->write_fifo, |
2128 | port->write_urb->transfer_buffer, | 2107 | port->write_urb->transfer_buffer, |
2129 | port->bulk_out_size); | 2108 | port->bulk_out_size); |
2130 | 2109 | ||
@@ -2180,7 +2159,7 @@ static int edge_write_room(struct tty_struct *tty) | |||
2180 | return 0; | 2159 | return 0; |
2181 | 2160 | ||
2182 | spin_lock_irqsave(&edge_port->ep_lock, flags); | 2161 | spin_lock_irqsave(&edge_port->ep_lock, flags); |
2183 | room = edge_buf_space_avail(edge_port->ep_out_buf); | 2162 | room = kfifo_avail(&edge_port->write_fifo); |
2184 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | 2163 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); |
2185 | 2164 | ||
2186 | dbg("%s - returns %d", __func__, room); | 2165 | dbg("%s - returns %d", __func__, room); |
@@ -2202,7 +2181,7 @@ static int edge_chars_in_buffer(struct tty_struct *tty) | |||
2202 | return 0; | 2181 | return 0; |
2203 | 2182 | ||
2204 | spin_lock_irqsave(&edge_port->ep_lock, flags); | 2183 | spin_lock_irqsave(&edge_port->ep_lock, flags); |
2205 | chars = edge_buf_data_avail(edge_port->ep_out_buf); | 2184 | chars = kfifo_len(&edge_port->write_fifo); |
2206 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | 2185 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); |
2207 | 2186 | ||
2208 | dbg("%s - returns %d", __func__, chars); | 2187 | dbg("%s - returns %d", __func__, chars); |
@@ -2659,8 +2638,8 @@ static int edge_startup(struct usb_serial *serial) | |||
2659 | goto cleanup; | 2638 | goto cleanup; |
2660 | } | 2639 | } |
2661 | spin_lock_init(&edge_port->ep_lock); | 2640 | spin_lock_init(&edge_port->ep_lock); |
2662 | edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE); | 2641 | if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE, |
2663 | if (edge_port->ep_out_buf == NULL) { | 2642 | GFP_KERNEL)) { |
2664 | dev_err(&serial->dev->dev, "%s - Out of memory\n", | 2643 | dev_err(&serial->dev->dev, "%s - Out of memory\n", |
2665 | __func__); | 2644 | __func__); |
2666 | kfree(edge_port); | 2645 | kfree(edge_port); |
@@ -2677,7 +2656,7 @@ static int edge_startup(struct usb_serial *serial) | |||
2677 | cleanup: | 2656 | cleanup: |
2678 | for (--i; i >= 0; --i) { | 2657 | for (--i; i >= 0; --i) { |
2679 | edge_port = usb_get_serial_port_data(serial->port[i]); | 2658 | edge_port = usb_get_serial_port_data(serial->port[i]); |
2680 | edge_buf_free(edge_port->ep_out_buf); | 2659 | kfifo_free(&edge_port->write_fifo); |
2681 | kfree(edge_port); | 2660 | kfree(edge_port); |
2682 | usb_set_serial_port_data(serial->port[i], NULL); | 2661 | usb_set_serial_port_data(serial->port[i], NULL); |
2683 | } | 2662 | } |
@@ -2708,7 +2687,7 @@ static void edge_release(struct usb_serial *serial) | |||
2708 | 2687 | ||
2709 | for (i = 0; i < serial->num_ports; ++i) { | 2688 | for (i = 0; i < serial->num_ports; ++i) { |
2710 | edge_port = usb_get_serial_port_data(serial->port[i]); | 2689 | edge_port = usb_get_serial_port_data(serial->port[i]); |
2711 | edge_buf_free(edge_port->ep_out_buf); | 2690 | kfifo_free(&edge_port->write_fifo); |
2712 | kfree(edge_port); | 2691 | kfree(edge_port); |
2713 | } | 2692 | } |
2714 | kfree(usb_get_serial_data(serial)); | 2693 | kfree(usb_get_serial_data(serial)); |
@@ -2758,182 +2737,6 @@ static int edge_remove_sysfs_attrs(struct usb_serial_port *port) | |||
2758 | } | 2737 | } |
2759 | 2738 | ||
2760 | 2739 | ||
2761 | /* Circular Buffer */ | ||
2762 | |||
2763 | /* | ||
2764 | * edge_buf_alloc | ||
2765 | * | ||
2766 | * Allocate a circular buffer and all associated memory. | ||
2767 | */ | ||
2768 | |||
2769 | static struct edge_buf *edge_buf_alloc(unsigned int size) | ||
2770 | { | ||
2771 | struct edge_buf *eb; | ||
2772 | |||
2773 | |||
2774 | if (size == 0) | ||
2775 | return NULL; | ||
2776 | |||
2777 | eb = kmalloc(sizeof(struct edge_buf), GFP_KERNEL); | ||
2778 | if (eb == NULL) | ||
2779 | return NULL; | ||
2780 | |||
2781 | eb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
2782 | if (eb->buf_buf == NULL) { | ||
2783 | kfree(eb); | ||
2784 | return NULL; | ||
2785 | } | ||
2786 | |||
2787 | eb->buf_size = size; | ||
2788 | eb->buf_get = eb->buf_put = eb->buf_buf; | ||
2789 | |||
2790 | return eb; | ||
2791 | } | ||
2792 | |||
2793 | |||
2794 | /* | ||
2795 | * edge_buf_free | ||
2796 | * | ||
2797 | * Free the buffer and all associated memory. | ||
2798 | */ | ||
2799 | |||
2800 | static void edge_buf_free(struct edge_buf *eb) | ||
2801 | { | ||
2802 | if (eb) { | ||
2803 | kfree(eb->buf_buf); | ||
2804 | kfree(eb); | ||
2805 | } | ||
2806 | } | ||
2807 | |||
2808 | |||
2809 | /* | ||
2810 | * edge_buf_clear | ||
2811 | * | ||
2812 | * Clear out all data in the circular buffer. | ||
2813 | */ | ||
2814 | |||
2815 | static void edge_buf_clear(struct edge_buf *eb) | ||
2816 | { | ||
2817 | if (eb != NULL) | ||
2818 | eb->buf_get = eb->buf_put; | ||
2819 | /* equivalent to a get of all data available */ | ||
2820 | } | ||
2821 | |||
2822 | |||
2823 | /* | ||
2824 | * edge_buf_data_avail | ||
2825 | * | ||
2826 | * Return the number of bytes of data available in the circular | ||
2827 | * buffer. | ||
2828 | */ | ||
2829 | |||
2830 | static unsigned int edge_buf_data_avail(struct edge_buf *eb) | ||
2831 | { | ||
2832 | if (eb == NULL) | ||
2833 | return 0; | ||
2834 | return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size); | ||
2835 | } | ||
2836 | |||
2837 | |||
2838 | /* | ||
2839 | * edge_buf_space_avail | ||
2840 | * | ||
2841 | * Return the number of bytes of space available in the circular | ||
2842 | * buffer. | ||
2843 | */ | ||
2844 | |||
2845 | static unsigned int edge_buf_space_avail(struct edge_buf *eb) | ||
2846 | { | ||
2847 | if (eb == NULL) | ||
2848 | return 0; | ||
2849 | return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size); | ||
2850 | } | ||
2851 | |||
2852 | |||
2853 | /* | ||
2854 | * edge_buf_put | ||
2855 | * | ||
2856 | * Copy data data from a user buffer and put it into the circular buffer. | ||
2857 | * Restrict to the amount of space available. | ||
2858 | * | ||
2859 | * Return the number of bytes copied. | ||
2860 | */ | ||
2861 | |||
2862 | static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf, | ||
2863 | unsigned int count) | ||
2864 | { | ||
2865 | unsigned int len; | ||
2866 | |||
2867 | |||
2868 | if (eb == NULL) | ||
2869 | return 0; | ||
2870 | |||
2871 | len = edge_buf_space_avail(eb); | ||
2872 | if (count > len) | ||
2873 | count = len; | ||
2874 | |||
2875 | if (count == 0) | ||
2876 | return 0; | ||
2877 | |||
2878 | len = eb->buf_buf + eb->buf_size - eb->buf_put; | ||
2879 | if (count > len) { | ||
2880 | memcpy(eb->buf_put, buf, len); | ||
2881 | memcpy(eb->buf_buf, buf+len, count - len); | ||
2882 | eb->buf_put = eb->buf_buf + count - len; | ||
2883 | } else { | ||
2884 | memcpy(eb->buf_put, buf, count); | ||
2885 | if (count < len) | ||
2886 | eb->buf_put += count; | ||
2887 | else /* count == len */ | ||
2888 | eb->buf_put = eb->buf_buf; | ||
2889 | } | ||
2890 | |||
2891 | return count; | ||
2892 | } | ||
2893 | |||
2894 | |||
2895 | /* | ||
2896 | * edge_buf_get | ||
2897 | * | ||
2898 | * Get data from the circular buffer and copy to the given buffer. | ||
2899 | * Restrict to the amount of data available. | ||
2900 | * | ||
2901 | * Return the number of bytes copied. | ||
2902 | */ | ||
2903 | |||
2904 | static unsigned int edge_buf_get(struct edge_buf *eb, char *buf, | ||
2905 | unsigned int count) | ||
2906 | { | ||
2907 | unsigned int len; | ||
2908 | |||
2909 | |||
2910 | if (eb == NULL) | ||
2911 | return 0; | ||
2912 | |||
2913 | len = edge_buf_data_avail(eb); | ||
2914 | if (count > len) | ||
2915 | count = len; | ||
2916 | |||
2917 | if (count == 0) | ||
2918 | return 0; | ||
2919 | |||
2920 | len = eb->buf_buf + eb->buf_size - eb->buf_get; | ||
2921 | if (count > len) { | ||
2922 | memcpy(buf, eb->buf_get, len); | ||
2923 | memcpy(buf+len, eb->buf_buf, count - len); | ||
2924 | eb->buf_get = eb->buf_buf + count - len; | ||
2925 | } else { | ||
2926 | memcpy(buf, eb->buf_get, count); | ||
2927 | if (count < len) | ||
2928 | eb->buf_get += count; | ||
2929 | else /* count == len */ | ||
2930 | eb->buf_get = eb->buf_buf; | ||
2931 | } | ||
2932 | |||
2933 | return count; | ||
2934 | } | ||
2935 | |||
2936 | |||
2937 | static struct usb_serial_driver edgeport_1port_device = { | 2740 | static struct usb_serial_driver edgeport_1port_device = { |
2938 | .driver = { | 2741 | .driver = { |
2939 | .owner = THIS_MODULE, | 2742 | .owner = THIS_MODULE, |