diff options
author | Oliver Neukum <oneukum@suse.de> | 2007-03-27 10:02:34 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-04-27 16:28:38 -0400 |
commit | 5ec1862e7b612d804ca10a0475dccf98c857efec (patch) | |
tree | 6670e75d9364c9d8871f8f1b85ac12bff9900e34 /drivers/usb | |
parent | 2f007de2f4296e4dafae6ab0b3cc1bc49443137a (diff) |
USB: fix omninet write vs. close race
omninet kills all URBs in close. However write() returns as soon as
the URB has been submitted. Killing the last URB means a race that
can lose that date written in the last call to write().
As a fix this is moved to shutdown().
Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/omninet.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 357cc11915cf..4adfab988e86 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
@@ -69,6 +69,7 @@ static void omninet_write_bulk_callback (struct urb *urb); | |||
69 | static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count); | 69 | static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count); |
70 | static int omninet_write_room (struct usb_serial_port *port); | 70 | static int omninet_write_room (struct usb_serial_port *port); |
71 | static void omninet_shutdown (struct usb_serial *serial); | 71 | static void omninet_shutdown (struct usb_serial *serial); |
72 | static int omninet_attach (struct usb_serial *serial); | ||
72 | 73 | ||
73 | static struct usb_device_id id_table [] = { | 74 | static struct usb_device_id id_table [] = { |
74 | { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) }, | 75 | { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) }, |
@@ -99,6 +100,7 @@ static struct usb_serial_driver zyxel_omninet_device = { | |||
99 | .num_bulk_in = 1, | 100 | .num_bulk_in = 1, |
100 | .num_bulk_out = 2, | 101 | .num_bulk_out = 2, |
101 | .num_ports = 1, | 102 | .num_ports = 1, |
103 | .attach = omninet_attach, | ||
102 | .open = omninet_open, | 104 | .open = omninet_open, |
103 | .close = omninet_close, | 105 | .close = omninet_close, |
104 | .write = omninet_write, | 106 | .write = omninet_write, |
@@ -145,22 +147,30 @@ struct omninet_data | |||
145 | __u8 od_outseq; // Sequence number for bulk_out URBs | 147 | __u8 od_outseq; // Sequence number for bulk_out URBs |
146 | }; | 148 | }; |
147 | 149 | ||
150 | static int omninet_attach (struct usb_serial *serial) | ||
151 | { | ||
152 | struct omninet_data *od; | ||
153 | struct usb_serial_port *port = serial->port[0]; | ||
154 | |||
155 | od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL ); | ||
156 | if( !od ) { | ||
157 | err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct omninet_data)); | ||
158 | return -ENOMEM; | ||
159 | } | ||
160 | usb_set_serial_port_data(port, od); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
148 | static int omninet_open (struct usb_serial_port *port, struct file *filp) | 164 | static int omninet_open (struct usb_serial_port *port, struct file *filp) |
149 | { | 165 | { |
150 | struct usb_serial *serial = port->serial; | 166 | struct usb_serial *serial = port->serial; |
151 | struct usb_serial_port *wport; | 167 | struct usb_serial_port *wport; |
152 | struct omninet_data *od; | 168 | struct omninet_data *od = usb_get_serial_port_data(port); |
153 | int result = 0; | 169 | int result = 0; |
154 | 170 | ||
155 | dbg("%s - port %d", __FUNCTION__, port->number); | 171 | dbg("%s - port %d", __FUNCTION__, port->number); |
156 | 172 | ||
157 | od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL ); | 173 | od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL ); |
158 | if( !od ) { | ||
159 | err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct omninet_data)); | ||
160 | return -ENOMEM; | ||
161 | } | ||
162 | |||
163 | usb_set_serial_port_data(port, od); | ||
164 | wport = serial->port[1]; | 174 | wport = serial->port[1]; |
165 | wport->tty = port->tty; | 175 | wport->tty = port->tty; |
166 | 176 | ||
@@ -172,9 +182,6 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp) | |||
172 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | 182 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); |
173 | if (result) { | 183 | if (result) { |
174 | err("%s - failed submitting read urb, error %d", __FUNCTION__, result); | 184 | err("%s - failed submitting read urb, error %d", __FUNCTION__, result); |
175 | /* open failed - all allocations must be freed */ | ||
176 | kfree(od); | ||
177 | usb_set_serial_port_data(port, NULL); | ||
178 | } | 185 | } |
179 | 186 | ||
180 | return result; | 187 | return result; |
@@ -182,16 +189,8 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp) | |||
182 | 189 | ||
183 | static void omninet_close (struct usb_serial_port *port, struct file * filp) | 190 | static void omninet_close (struct usb_serial_port *port, struct file * filp) |
184 | { | 191 | { |
185 | struct usb_serial *serial = port->serial; | ||
186 | struct usb_serial_port *wport; | ||
187 | |||
188 | dbg("%s - port %d", __FUNCTION__, port->number); | 192 | dbg("%s - port %d", __FUNCTION__, port->number); |
189 | |||
190 | wport = serial->port[1]; | ||
191 | usb_kill_urb(wport->write_urb); | ||
192 | usb_kill_urb(port->read_urb); | 193 | usb_kill_urb(port->read_urb); |
193 | |||
194 | kfree(usb_get_serial_port_data(port)); | ||
195 | } | 194 | } |
196 | 195 | ||
197 | 196 | ||
@@ -330,7 +329,12 @@ static void omninet_write_bulk_callback (struct urb *urb) | |||
330 | 329 | ||
331 | static void omninet_shutdown (struct usb_serial *serial) | 330 | static void omninet_shutdown (struct usb_serial *serial) |
332 | { | 331 | { |
332 | struct usb_serial_port *wport = serial->port[1]; | ||
333 | struct usb_serial_port *port = serial->port[0]; | ||
333 | dbg ("%s", __FUNCTION__); | 334 | dbg ("%s", __FUNCTION__); |
335 | |||
336 | usb_kill_urb(wport->write_urb); | ||
337 | kfree(usb_get_serial_port_data(port)); | ||
334 | } | 338 | } |
335 | 339 | ||
336 | 340 | ||