aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFranck Bui-Huu <vagabon.xyz@gmail.com>2006-06-14 04:29:21 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-21 18:04:17 -0400
commit943e1b4d60dc7acfabe2ebad31189bcb3b853688 (patch)
tree3a8de95902d0f8699d0c2dd1759a1841960d1720 /drivers
parentb059c81af7a1759a911cfc20ce8a4bf47c435830 (diff)
[PATCH] USB: gadget-serial: fix a deadlock when closing the serial device
When closing the device, the driver acquires/release twice the port lock before/after waiting for the data to be completely sent. Therefore it will dead lock. This patch fixes it and also uses the generic scheduler services for waiting for an event. Signed-off-by: Franck Bui-Huu <vagabon.xyz@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/serial.c95
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) \
57do { \
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) \
90do { \
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
846static void gs_close(struct tty_struct *tty, struct file *file) 786static 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