diff options
Diffstat (limited to 'drivers/usb/gadget/serial.c')
-rw-r--r-- | drivers/usb/gadget/serial.c | 105 |
1 files changed, 21 insertions, 84 deletions
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index b992546c394d..9d6e1d295528 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -45,88 +45,16 @@ | |||
45 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
46 | 46 | ||
47 | #include <linux/usb_ch9.h> | 47 | #include <linux/usb_ch9.h> |
48 | #include <linux/usb_cdc.h> | 48 | #include <linux/usb/cdc.h> |
49 | #include <linux/usb_gadget.h> | 49 | #include <linux/usb_gadget.h> |
50 | 50 | ||
51 | #include "gadget_chips.h" | 51 | #include "gadget_chips.h" |
52 | 52 | ||
53 | 53 | ||
54 | /* Wait Cond */ | ||
55 | |||
56 | #define __wait_cond_interruptible(wq, condition, lock, flags, ret) \ | ||
57 | do { \ | ||
58 | wait_queue_t __wait; \ | ||
59 | init_waitqueue_entry(&__wait, current); \ | ||
60 | \ | ||
61 | add_wait_queue(&wq, &__wait); \ | ||
62 | for (;;) { \ | ||
63 | set_current_state(TASK_INTERRUPTIBLE); \ | ||
64 | if (condition) \ | ||
65 | break; \ | ||
66 | if (!signal_pending(current)) { \ | ||
67 | spin_unlock_irqrestore(lock, flags); \ | ||
68 | schedule(); \ | ||
69 | spin_lock_irqsave(lock, flags); \ | ||
70 | continue; \ | ||
71 | } \ | ||
72 | ret = -ERESTARTSYS; \ | ||
73 | break; \ | ||
74 | } \ | ||
75 | current->state = TASK_RUNNING; \ | ||
76 | remove_wait_queue(&wq, &__wait); \ | ||
77 | } while (0) | ||
78 | |||
79 | #define wait_cond_interruptible(wq, condition, lock, flags) \ | ||
80 | ({ \ | ||
81 | int __ret = 0; \ | ||
82 | if (!(condition)) \ | ||
83 | __wait_cond_interruptible(wq, condition, lock, flags, \ | ||
84 | __ret); \ | ||
85 | __ret; \ | ||
86 | }) | ||
87 | |||
88 | #define __wait_cond_interruptible_timeout(wq, condition, lock, flags, \ | ||
89 | timeout, ret) \ | ||
90 | do { \ | ||
91 | signed long __timeout = timeout; \ | ||
92 | wait_queue_t __wait; \ | ||
93 | init_waitqueue_entry(&__wait, current); \ | ||
94 | \ | ||
95 | add_wait_queue(&wq, &__wait); \ | ||
96 | for (;;) { \ | ||
97 | set_current_state(TASK_INTERRUPTIBLE); \ | ||
98 | if (__timeout == 0) \ | ||
99 | break; \ | ||
100 | if (condition) \ | ||
101 | break; \ | ||
102 | if (!signal_pending(current)) { \ | ||
103 | spin_unlock_irqrestore(lock, flags); \ | ||
104 | __timeout = schedule_timeout(__timeout); \ | ||
105 | spin_lock_irqsave(lock, flags); \ | ||
106 | continue; \ | ||
107 | } \ | ||
108 | ret = -ERESTARTSYS; \ | ||
109 | break; \ | ||
110 | } \ | ||
111 | current->state = TASK_RUNNING; \ | ||
112 | remove_wait_queue(&wq, &__wait); \ | ||
113 | } while (0) | ||
114 | |||
115 | #define wait_cond_interruptible_timeout(wq, condition, lock, flags, \ | ||
116 | timeout) \ | ||
117 | ({ \ | ||
118 | int __ret = 0; \ | ||
119 | if (!(condition)) \ | ||
120 | __wait_cond_interruptible_timeout(wq, condition, lock, \ | ||
121 | flags, timeout, __ret); \ | ||
122 | __ret; \ | ||
123 | }) | ||
124 | |||
125 | |||
126 | /* Defines */ | 54 | /* Defines */ |
127 | 55 | ||
128 | #define GS_VERSION_STR "v2.0" | 56 | #define GS_VERSION_STR "v2.2" |
129 | #define GS_VERSION_NUM 0x0200 | 57 | #define GS_VERSION_NUM 0x0202 |
130 | 58 | ||
131 | #define GS_LONG_NAME "Gadget Serial" | 59 | #define GS_LONG_NAME "Gadget Serial" |
132 | #define GS_SHORT_NAME "g_serial" | 60 | #define GS_SHORT_NAME "g_serial" |
@@ -843,9 +771,19 @@ exit_unlock_dev: | |||
843 | /* | 771 | /* |
844 | * gs_close | 772 | * gs_close |
845 | */ | 773 | */ |
774 | |||
775 | #define GS_WRITE_FINISHED_EVENT_SAFELY(p) \ | ||
776 | ({ \ | ||
777 | int cond; \ | ||
778 | \ | ||
779 | spin_lock_irq(&(p)->port_lock); \ | ||
780 | cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \ | ||
781 | spin_unlock_irq(&(p)->port_lock); \ | ||
782 | cond; \ | ||
783 | }) | ||
784 | |||
846 | static void gs_close(struct tty_struct *tty, struct file *file) | 785 | static void gs_close(struct tty_struct *tty, struct file *file) |
847 | { | 786 | { |
848 | unsigned long flags; | ||
849 | struct gs_port *port = tty->driver_data; | 787 | struct gs_port *port = tty->driver_data; |
850 | struct semaphore *sem; | 788 | struct semaphore *sem; |
851 | 789 | ||
@@ -859,7 +797,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) | |||
859 | sem = &gs_open_close_sem[port->port_num]; | 797 | sem = &gs_open_close_sem[port->port_num]; |
860 | down(sem); | 798 | down(sem); |
861 | 799 | ||
862 | spin_lock_irqsave(&port->port_lock, flags); | 800 | spin_lock_irq(&port->port_lock); |
863 | 801 | ||
864 | if (port->port_open_count == 0) { | 802 | if (port->port_open_count == 0) { |
865 | printk(KERN_ERR | 803 | printk(KERN_ERR |
@@ -887,12 +825,11 @@ static void gs_close(struct tty_struct *tty, struct file *file) | |||
887 | /* wait for write buffer to drain, or */ | 825 | /* wait for write buffer to drain, or */ |
888 | /* at most GS_CLOSE_TIMEOUT seconds */ | 826 | /* at most GS_CLOSE_TIMEOUT seconds */ |
889 | if (gs_buf_data_avail(port->port_write_buf) > 0) { | 827 | if (gs_buf_data_avail(port->port_write_buf) > 0) { |
890 | spin_unlock_irqrestore(&port->port_lock, flags); | 828 | spin_unlock_irq(&port->port_lock); |
891 | wait_cond_interruptible_timeout(port->port_write_wait, | 829 | wait_event_interruptible_timeout(port->port_write_wait, |
892 | port->port_dev == NULL | 830 | GS_WRITE_FINISHED_EVENT_SAFELY(port), |
893 | || gs_buf_data_avail(port->port_write_buf) == 0, | 831 | GS_CLOSE_TIMEOUT * HZ); |
894 | &port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ); | 832 | spin_lock_irq(&port->port_lock); |
895 | spin_lock_irqsave(&port->port_lock, flags); | ||
896 | } | 833 | } |
897 | 834 | ||
898 | /* free disconnected port on final close */ | 835 | /* free disconnected port on final close */ |
@@ -912,7 +849,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) | |||
912 | port->port_num, tty, file); | 849 | port->port_num, tty, file); |
913 | 850 | ||
914 | exit: | 851 | exit: |
915 | spin_unlock_irqrestore(&port->port_lock, flags); | 852 | spin_unlock_irq(&port->port_lock); |
916 | up(sem); | 853 | up(sem); |
917 | } | 854 | } |
918 | 855 | ||