diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/serial.c | 95 |
1 files changed, 17 insertions, 78 deletions
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index b992546c394d..b58f015554b7 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -51,82 +51,10 @@ | |||
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.1" |
129 | #define GS_VERSION_NUM 0x0200 | 57 | #define GS_VERSION_NUM 0x0201 |
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,6 +771,18 @@ exit_unlock_dev: | |||
843 | /* | 771 | /* |
844 | * gs_close | 772 | * gs_close |
845 | */ | 773 | */ |
774 | |||
775 | #define GS_WRITE_FINISHED_EVENT_SAFELY(p) \ | ||
776 | ({ \ | ||
777 | unsigned long flags; \ | ||
778 | int cond; \ | ||
779 | \ | ||
780 | spin_lock_irqsave(&(p)->port_lock, flags); \ | ||
781 | cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \ | ||
782 | spin_unlock_irqrestore(&(p)->port_lock, flags); \ | ||
783 | cond; \ | ||
784 | }) | ||
785 | |||
846 | static void gs_close(struct tty_struct *tty, struct file *file) | 786 | static void gs_close(struct tty_struct *tty, struct file *file) |
847 | { | 787 | { |
848 | unsigned long flags; | 788 | unsigned long flags; |
@@ -888,10 +828,9 @@ static void gs_close(struct tty_struct *tty, struct file *file) | |||
888 | /* at most GS_CLOSE_TIMEOUT seconds */ | 828 | /* at most GS_CLOSE_TIMEOUT seconds */ |
889 | if (gs_buf_data_avail(port->port_write_buf) > 0) { | 829 | if (gs_buf_data_avail(port->port_write_buf) > 0) { |
890 | spin_unlock_irqrestore(&port->port_lock, flags); | 830 | spin_unlock_irqrestore(&port->port_lock, flags); |
891 | wait_cond_interruptible_timeout(port->port_write_wait, | 831 | wait_event_interruptible_timeout(port->port_write_wait, |
892 | port->port_dev == NULL | 832 | GS_WRITE_FINISHED_EVENT_SAFELY(port), |
893 | || gs_buf_data_avail(port->port_write_buf) == 0, | 833 | GS_CLOSE_TIMEOUT * HZ); |
894 | &port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ); | ||
895 | spin_lock_irqsave(&port->port_lock, flags); | 834 | spin_lock_irqsave(&port->port_lock, flags); |
896 | } | 835 | } |
897 | 836 | ||