diff options
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r-- | drivers/usb/serial/generic.c | 330 |
1 files changed, 111 insertions, 219 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index f804acb138ec..a817ced82835 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * USB Serial Converter Generic functions | 2 | * USB Serial Converter Generic functions |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) | ||
4 | * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) | 5 | * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) |
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
@@ -12,6 +13,7 @@ | |||
12 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
13 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/sysrq.h> | ||
15 | #include <linux/tty.h> | 17 | #include <linux/tty.h> |
16 | #include <linux/tty_flip.h> | 18 | #include <linux/tty_flip.h> |
17 | #include <linux/module.h> | 19 | #include <linux/module.h> |
@@ -117,7 +119,6 @@ void usb_serial_generic_deregister(void) | |||
117 | 119 | ||
118 | int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port) | 120 | int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port) |
119 | { | 121 | { |
120 | struct usb_serial *serial = port->serial; | ||
121 | int result = 0; | 122 | int result = 0; |
122 | unsigned long flags; | 123 | unsigned long flags; |
123 | 124 | ||
@@ -130,23 +131,8 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port | |||
130 | spin_unlock_irqrestore(&port->lock, flags); | 131 | spin_unlock_irqrestore(&port->lock, flags); |
131 | 132 | ||
132 | /* if we have a bulk endpoint, start reading from it */ | 133 | /* if we have a bulk endpoint, start reading from it */ |
133 | if (port->bulk_in_size) { | 134 | if (port->bulk_in_size) |
134 | /* Start reading from the device */ | 135 | result = usb_serial_generic_submit_read_urb(port, GFP_KERNEL); |
135 | usb_fill_bulk_urb(port->read_urb, serial->dev, | ||
136 | usb_rcvbulkpipe(serial->dev, | ||
137 | port->bulk_in_endpointAddress), | ||
138 | port->read_urb->transfer_buffer, | ||
139 | port->read_urb->transfer_buffer_length, | ||
140 | ((serial->type->read_bulk_callback) ? | ||
141 | serial->type->read_bulk_callback : | ||
142 | usb_serial_generic_read_bulk_callback), | ||
143 | port); | ||
144 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
145 | if (result) | ||
146 | dev_err(&port->dev, | ||
147 | "%s - failed resubmitting read urb, error %d\n", | ||
148 | __func__, result); | ||
149 | } | ||
150 | 136 | ||
151 | return result; | 137 | return result; |
152 | } | 138 | } |
@@ -155,13 +141,22 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_open); | |||
155 | static void generic_cleanup(struct usb_serial_port *port) | 141 | static void generic_cleanup(struct usb_serial_port *port) |
156 | { | 142 | { |
157 | struct usb_serial *serial = port->serial; | 143 | struct usb_serial *serial = port->serial; |
144 | unsigned long flags; | ||
145 | int i; | ||
158 | 146 | ||
159 | dbg("%s - port %d", __func__, port->number); | 147 | dbg("%s - port %d", __func__, port->number); |
160 | 148 | ||
161 | if (serial->dev) { | 149 | if (serial->dev) { |
162 | /* shutdown any bulk transfers that might be going on */ | 150 | /* shutdown any bulk transfers that might be going on */ |
163 | if (port->bulk_out_size) | 151 | if (port->bulk_out_size) { |
164 | usb_kill_urb(port->write_urb); | 152 | usb_kill_urb(port->write_urb); |
153 | for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) | ||
154 | usb_kill_urb(port->write_urbs[i]); | ||
155 | |||
156 | spin_lock_irqsave(&port->lock, flags); | ||
157 | kfifo_reset_out(&port->write_fifo); | ||
158 | spin_unlock_irqrestore(&port->lock, flags); | ||
159 | } | ||
165 | if (port->bulk_in_size) | 160 | if (port->bulk_in_size) |
166 | usb_kill_urb(port->read_urb); | 161 | usb_kill_urb(port->read_urb); |
167 | } | 162 | } |
@@ -172,146 +167,68 @@ void usb_serial_generic_close(struct usb_serial_port *port) | |||
172 | dbg("%s - port %d", __func__, port->number); | 167 | dbg("%s - port %d", __func__, port->number); |
173 | generic_cleanup(port); | 168 | generic_cleanup(port); |
174 | } | 169 | } |
170 | EXPORT_SYMBOL_GPL(usb_serial_generic_close); | ||
175 | 171 | ||
176 | static int usb_serial_multi_urb_write(struct tty_struct *tty, | 172 | int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port, |
177 | struct usb_serial_port *port, const unsigned char *buf, int count) | 173 | void *dest, size_t size) |
178 | { | 174 | { |
179 | unsigned long flags; | 175 | return kfifo_out_locked(&port->write_fifo, dest, size, &port->lock); |
180 | struct urb *urb; | ||
181 | unsigned char *buffer; | ||
182 | int status; | ||
183 | int towrite; | ||
184 | int bwrite = 0; | ||
185 | |||
186 | dbg("%s - port %d", __func__, port->number); | ||
187 | |||
188 | if (count == 0) | ||
189 | dbg("%s - write request of 0 bytes", __func__); | ||
190 | |||
191 | while (count > 0) { | ||
192 | towrite = (count > port->bulk_out_size) ? | ||
193 | port->bulk_out_size : count; | ||
194 | spin_lock_irqsave(&port->lock, flags); | ||
195 | if (port->urbs_in_flight > | ||
196 | port->serial->type->max_in_flight_urbs) { | ||
197 | spin_unlock_irqrestore(&port->lock, flags); | ||
198 | dbg("%s - write limit hit", __func__); | ||
199 | return bwrite; | ||
200 | } | ||
201 | port->tx_bytes_flight += towrite; | ||
202 | port->urbs_in_flight++; | ||
203 | spin_unlock_irqrestore(&port->lock, flags); | ||
204 | |||
205 | buffer = kmalloc(towrite, GFP_ATOMIC); | ||
206 | if (!buffer) { | ||
207 | dev_err(&port->dev, | ||
208 | "%s ran out of kernel memory for urb ...\n", __func__); | ||
209 | goto error_no_buffer; | ||
210 | } | ||
211 | |||
212 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
213 | if (!urb) { | ||
214 | dev_err(&port->dev, "%s - no more free urbs\n", | ||
215 | __func__); | ||
216 | goto error_no_urb; | ||
217 | } | ||
218 | |||
219 | /* Copy data */ | ||
220 | memcpy(buffer, buf + bwrite, towrite); | ||
221 | usb_serial_debug_data(debug, &port->dev, __func__, | ||
222 | towrite, buffer); | ||
223 | /* fill the buffer and send it */ | ||
224 | usb_fill_bulk_urb(urb, port->serial->dev, | ||
225 | usb_sndbulkpipe(port->serial->dev, | ||
226 | port->bulk_out_endpointAddress), | ||
227 | buffer, towrite, | ||
228 | usb_serial_generic_write_bulk_callback, port); | ||
229 | |||
230 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
231 | if (status) { | ||
232 | dev_err(&port->dev, | ||
233 | "%s - failed submitting write urb, error %d\n", | ||
234 | __func__, status); | ||
235 | goto error; | ||
236 | } | ||
237 | |||
238 | /* This urb is the responsibility of the host driver now */ | ||
239 | usb_free_urb(urb); | ||
240 | dbg("%s write: %d", __func__, towrite); | ||
241 | count -= towrite; | ||
242 | bwrite += towrite; | ||
243 | } | ||
244 | return bwrite; | ||
245 | |||
246 | error: | ||
247 | usb_free_urb(urb); | ||
248 | error_no_urb: | ||
249 | kfree(buffer); | ||
250 | error_no_buffer: | ||
251 | spin_lock_irqsave(&port->lock, flags); | ||
252 | port->urbs_in_flight--; | ||
253 | port->tx_bytes_flight -= towrite; | ||
254 | spin_unlock_irqrestore(&port->lock, flags); | ||
255 | return bwrite; | ||
256 | } | 176 | } |
257 | 177 | ||
258 | /** | 178 | /** |
259 | * usb_serial_generic_write_start - kick off an URB write | 179 | * usb_serial_generic_write_start - kick off an URB write |
260 | * @port: Pointer to the &struct usb_serial_port data | 180 | * @port: Pointer to the &struct usb_serial_port data |
261 | * | 181 | * |
262 | * Returns the number of bytes queued on success. This will be zero if there | 182 | * Returns zero on success, or a negative errno value |
263 | * was nothing to send. Otherwise, it returns a negative errno value | ||
264 | */ | 183 | */ |
265 | static int usb_serial_generic_write_start(struct usb_serial_port *port) | 184 | static int usb_serial_generic_write_start(struct usb_serial_port *port) |
266 | { | 185 | { |
267 | struct usb_serial *serial = port->serial; | 186 | struct urb *urb; |
268 | unsigned char *data; | 187 | int count, result; |
269 | int result; | ||
270 | int count; | ||
271 | unsigned long flags; | 188 | unsigned long flags; |
272 | bool start_io; | 189 | int i; |
273 | 190 | ||
274 | /* Atomically determine whether we can and need to start a USB | 191 | if (test_and_set_bit_lock(USB_SERIAL_WRITE_BUSY, &port->flags)) |
275 | * operation. */ | 192 | return 0; |
193 | retry: | ||
276 | spin_lock_irqsave(&port->lock, flags); | 194 | spin_lock_irqsave(&port->lock, flags); |
277 | if (port->write_urb_busy) | 195 | if (!port->write_urbs_free || !kfifo_len(&port->write_fifo)) { |
278 | start_io = false; | 196 | clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); |
279 | else { | 197 | spin_unlock_irqrestore(&port->lock, flags); |
280 | start_io = (kfifo_len(&port->write_fifo) != 0); | 198 | return 0; |
281 | port->write_urb_busy = start_io; | ||
282 | } | 199 | } |
200 | i = (int)find_first_bit(&port->write_urbs_free, | ||
201 | ARRAY_SIZE(port->write_urbs)); | ||
283 | spin_unlock_irqrestore(&port->lock, flags); | 202 | spin_unlock_irqrestore(&port->lock, flags); |
284 | 203 | ||
285 | if (!start_io) | 204 | urb = port->write_urbs[i]; |
286 | return 0; | 205 | count = port->serial->type->prepare_write_buffer(port, |
287 | 206 | urb->transfer_buffer, | |
288 | data = port->write_urb->transfer_buffer; | 207 | port->bulk_out_size); |
289 | count = kfifo_out_locked(&port->write_fifo, data, port->bulk_out_size, &port->lock); | 208 | urb->transfer_buffer_length = count; |
290 | usb_serial_debug_data(debug, &port->dev, __func__, count, data); | 209 | usb_serial_debug_data(debug, &port->dev, __func__, count, |
291 | 210 | urb->transfer_buffer); | |
292 | /* set up our urb */ | 211 | result = usb_submit_urb(urb, GFP_ATOMIC); |
293 | usb_fill_bulk_urb(port->write_urb, serial->dev, | ||
294 | usb_sndbulkpipe(serial->dev, | ||
295 | port->bulk_out_endpointAddress), | ||
296 | port->write_urb->transfer_buffer, count, | ||
297 | ((serial->type->write_bulk_callback) ? | ||
298 | serial->type->write_bulk_callback : | ||
299 | usb_serial_generic_write_bulk_callback), | ||
300 | port); | ||
301 | |||
302 | /* send the data out the bulk port */ | ||
303 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
304 | if (result) { | 212 | if (result) { |
305 | dev_err(&port->dev, | 213 | dev_err(&port->dev, "%s - error submitting urb: %d\n", |
306 | "%s - failed submitting write urb, error %d\n", | ||
307 | __func__, result); | 214 | __func__, result); |
308 | /* don't have to grab the lock here, as we will | 215 | clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); |
309 | retry if != 0 */ | 216 | return result; |
310 | port->write_urb_busy = 0; | 217 | } |
311 | } else | 218 | clear_bit(i, &port->write_urbs_free); |
312 | result = count; | ||
313 | 219 | ||
314 | return result; | 220 | spin_lock_irqsave(&port->lock, flags); |
221 | port->tx_bytes += count; | ||
222 | spin_unlock_irqrestore(&port->lock, flags); | ||
223 | |||
224 | /* Try sending off another urb, unless in irq context (in which case | ||
225 | * there will be no free urb). */ | ||
226 | if (!in_irq()) | ||
227 | goto retry; | ||
228 | |||
229 | clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); | ||
230 | |||
231 | return 0; | ||
315 | } | 232 | } |
316 | 233 | ||
317 | /** | 234 | /** |
@@ -328,7 +245,6 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) | |||
328 | int usb_serial_generic_write(struct tty_struct *tty, | 245 | int usb_serial_generic_write(struct tty_struct *tty, |
329 | struct usb_serial_port *port, const unsigned char *buf, int count) | 246 | struct usb_serial_port *port, const unsigned char *buf, int count) |
330 | { | 247 | { |
331 | struct usb_serial *serial = port->serial; | ||
332 | int result; | 248 | int result; |
333 | 249 | ||
334 | dbg("%s - port %d", __func__, port->number); | 250 | dbg("%s - port %d", __func__, port->number); |
@@ -337,31 +253,23 @@ int usb_serial_generic_write(struct tty_struct *tty, | |||
337 | if (!port->bulk_out_size) | 253 | if (!port->bulk_out_size) |
338 | return -ENODEV; | 254 | return -ENODEV; |
339 | 255 | ||
340 | if (count == 0) { | 256 | if (!count) |
341 | dbg("%s - write request of 0 bytes", __func__); | ||
342 | return 0; | 257 | return 0; |
343 | } | ||
344 | |||
345 | if (serial->type->max_in_flight_urbs) | ||
346 | return usb_serial_multi_urb_write(tty, port, | ||
347 | buf, count); | ||
348 | 258 | ||
349 | count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock); | 259 | count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock); |
350 | result = usb_serial_generic_write_start(port); | 260 | result = usb_serial_generic_write_start(port); |
261 | if (result) | ||
262 | return result; | ||
351 | 263 | ||
352 | if (result >= 0) | 264 | return count; |
353 | result = count; | ||
354 | |||
355 | return result; | ||
356 | } | 265 | } |
357 | EXPORT_SYMBOL_GPL(usb_serial_generic_write); | 266 | EXPORT_SYMBOL_GPL(usb_serial_generic_write); |
358 | 267 | ||
359 | int usb_serial_generic_write_room(struct tty_struct *tty) | 268 | int usb_serial_generic_write_room(struct tty_struct *tty) |
360 | { | 269 | { |
361 | struct usb_serial_port *port = tty->driver_data; | 270 | struct usb_serial_port *port = tty->driver_data; |
362 | struct usb_serial *serial = port->serial; | ||
363 | unsigned long flags; | 271 | unsigned long flags; |
364 | int room = 0; | 272 | int room; |
365 | 273 | ||
366 | dbg("%s - port %d", __func__, port->number); | 274 | dbg("%s - port %d", __func__, port->number); |
367 | 275 | ||
@@ -369,14 +277,7 @@ int usb_serial_generic_write_room(struct tty_struct *tty) | |||
369 | return 0; | 277 | return 0; |
370 | 278 | ||
371 | spin_lock_irqsave(&port->lock, flags); | 279 | spin_lock_irqsave(&port->lock, flags); |
372 | if (serial->type->max_in_flight_urbs) { | 280 | room = kfifo_avail(&port->write_fifo); |
373 | if (port->urbs_in_flight < serial->type->max_in_flight_urbs) | ||
374 | room = port->bulk_out_size * | ||
375 | (serial->type->max_in_flight_urbs - | ||
376 | port->urbs_in_flight); | ||
377 | } else { | ||
378 | room = kfifo_avail(&port->write_fifo); | ||
379 | } | ||
380 | spin_unlock_irqrestore(&port->lock, flags); | 281 | spin_unlock_irqrestore(&port->lock, flags); |
381 | 282 | ||
382 | dbg("%s - returns %d", __func__, room); | 283 | dbg("%s - returns %d", __func__, room); |
@@ -386,7 +287,6 @@ int usb_serial_generic_write_room(struct tty_struct *tty) | |||
386 | int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) | 287 | int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) |
387 | { | 288 | { |
388 | struct usb_serial_port *port = tty->driver_data; | 289 | struct usb_serial_port *port = tty->driver_data; |
389 | struct usb_serial *serial = port->serial; | ||
390 | unsigned long flags; | 290 | unsigned long flags; |
391 | int chars; | 291 | int chars; |
392 | 292 | ||
@@ -396,61 +296,47 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) | |||
396 | return 0; | 296 | return 0; |
397 | 297 | ||
398 | spin_lock_irqsave(&port->lock, flags); | 298 | spin_lock_irqsave(&port->lock, flags); |
399 | if (serial->type->max_in_flight_urbs) | 299 | chars = kfifo_len(&port->write_fifo) + port->tx_bytes; |
400 | chars = port->tx_bytes_flight; | ||
401 | else | ||
402 | chars = kfifo_len(&port->write_fifo); | ||
403 | spin_unlock_irqrestore(&port->lock, flags); | 300 | spin_unlock_irqrestore(&port->lock, flags); |
404 | 301 | ||
405 | dbg("%s - returns %d", __func__, chars); | 302 | dbg("%s - returns %d", __func__, chars); |
406 | return chars; | 303 | return chars; |
407 | } | 304 | } |
408 | 305 | ||
409 | 306 | int usb_serial_generic_submit_read_urb(struct usb_serial_port *port, | |
410 | void usb_serial_generic_resubmit_read_urb(struct usb_serial_port *port, | 307 | gfp_t mem_flags) |
411 | gfp_t mem_flags) | ||
412 | { | 308 | { |
413 | struct urb *urb = port->read_urb; | ||
414 | struct usb_serial *serial = port->serial; | ||
415 | int result; | 309 | int result; |
416 | 310 | ||
417 | /* Continue reading from device */ | 311 | result = usb_submit_urb(port->read_urb, mem_flags); |
418 | usb_fill_bulk_urb(urb, serial->dev, | ||
419 | usb_rcvbulkpipe(serial->dev, | ||
420 | port->bulk_in_endpointAddress), | ||
421 | urb->transfer_buffer, | ||
422 | urb->transfer_buffer_length, | ||
423 | ((serial->type->read_bulk_callback) ? | ||
424 | serial->type->read_bulk_callback : | ||
425 | usb_serial_generic_read_bulk_callback), port); | ||
426 | |||
427 | result = usb_submit_urb(urb, mem_flags); | ||
428 | if (result && result != -EPERM) { | 312 | if (result && result != -EPERM) { |
429 | dev_err(&port->dev, | 313 | dev_err(&port->dev, "%s - error submitting urb: %d\n", |
430 | "%s - failed resubmitting read urb, error %d\n", | ||
431 | __func__, result); | 314 | __func__, result); |
432 | } | 315 | } |
316 | return result; | ||
433 | } | 317 | } |
434 | EXPORT_SYMBOL_GPL(usb_serial_generic_resubmit_read_urb); | 318 | EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urb); |
435 | 319 | ||
436 | /* Push data to tty layer and resubmit the bulk read URB */ | 320 | void usb_serial_generic_process_read_urb(struct urb *urb) |
437 | static void flush_and_resubmit_read_urb(struct usb_serial_port *port) | ||
438 | { | 321 | { |
439 | struct urb *urb = port->read_urb; | 322 | struct usb_serial_port *port = urb->context; |
440 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 323 | struct tty_struct *tty; |
441 | char *ch = (char *)urb->transfer_buffer; | 324 | char *ch = (char *)urb->transfer_buffer; |
442 | int i; | 325 | int i; |
443 | 326 | ||
327 | if (!urb->actual_length) | ||
328 | return; | ||
329 | |||
330 | tty = tty_port_tty_get(&port->port); | ||
444 | if (!tty) | 331 | if (!tty) |
445 | goto done; | 332 | return; |
446 | 333 | ||
447 | /* The per character mucking around with sysrq path it too slow for | 334 | /* The per character mucking around with sysrq path it too slow for |
448 | stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases | 335 | stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases |
449 | where the USB serial is not a console anyway */ | 336 | where the USB serial is not a console anyway */ |
450 | if (!port->console || !port->sysrq) | 337 | if (!port->port.console || !port->sysrq) |
451 | tty_insert_flip_string(tty, ch, urb->actual_length); | 338 | tty_insert_flip_string(tty, ch, urb->actual_length); |
452 | else { | 339 | else { |
453 | /* Push data to tty */ | ||
454 | for (i = 0; i < urb->actual_length; i++, ch++) { | 340 | for (i = 0; i < urb->actual_length; i++, ch++) { |
455 | if (!usb_serial_handle_sysrq_char(tty, port, *ch)) | 341 | if (!usb_serial_handle_sysrq_char(tty, port, *ch)) |
456 | tty_insert_flip_char(tty, *ch, TTY_NORMAL); | 342 | tty_insert_flip_char(tty, *ch, TTY_NORMAL); |
@@ -458,9 +344,8 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port) | |||
458 | } | 344 | } |
459 | tty_flip_buffer_push(tty); | 345 | tty_flip_buffer_push(tty); |
460 | tty_kref_put(tty); | 346 | tty_kref_put(tty); |
461 | done: | ||
462 | usb_serial_generic_resubmit_read_urb(port, GFP_ATOMIC); | ||
463 | } | 347 | } |
348 | EXPORT_SYMBOL_GPL(usb_serial_generic_process_read_urb); | ||
464 | 349 | ||
465 | void usb_serial_generic_read_bulk_callback(struct urb *urb) | 350 | void usb_serial_generic_read_bulk_callback(struct urb *urb) |
466 | { | 351 | { |
@@ -479,13 +364,14 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) | |||
479 | 364 | ||
480 | usb_serial_debug_data(debug, &port->dev, __func__, | 365 | usb_serial_debug_data(debug, &port->dev, __func__, |
481 | urb->actual_length, data); | 366 | urb->actual_length, data); |
367 | port->serial->type->process_read_urb(urb); | ||
482 | 368 | ||
483 | /* Throttle the device if requested by tty */ | 369 | /* Throttle the device if requested by tty */ |
484 | spin_lock_irqsave(&port->lock, flags); | 370 | spin_lock_irqsave(&port->lock, flags); |
485 | port->throttled = port->throttle_req; | 371 | port->throttled = port->throttle_req; |
486 | if (!port->throttled) { | 372 | if (!port->throttled) { |
487 | spin_unlock_irqrestore(&port->lock, flags); | 373 | spin_unlock_irqrestore(&port->lock, flags); |
488 | flush_and_resubmit_read_urb(port); | 374 | usb_serial_generic_submit_read_urb(port, GFP_ATOMIC); |
489 | } else | 375 | } else |
490 | spin_unlock_irqrestore(&port->lock, flags); | 376 | spin_unlock_irqrestore(&port->lock, flags); |
491 | } | 377 | } |
@@ -496,30 +382,29 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) | |||
496 | unsigned long flags; | 382 | unsigned long flags; |
497 | struct usb_serial_port *port = urb->context; | 383 | struct usb_serial_port *port = urb->context; |
498 | int status = urb->status; | 384 | int status = urb->status; |
385 | int i; | ||
499 | 386 | ||
500 | dbg("%s - port %d", __func__, port->number); | 387 | dbg("%s - port %d", __func__, port->number); |
501 | 388 | ||
502 | if (port->serial->type->max_in_flight_urbs) { | 389 | for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) |
503 | kfree(urb->transfer_buffer); | 390 | if (port->write_urbs[i] == urb) |
391 | break; | ||
392 | |||
393 | spin_lock_irqsave(&port->lock, flags); | ||
394 | port->tx_bytes -= urb->transfer_buffer_length; | ||
395 | set_bit(i, &port->write_urbs_free); | ||
396 | spin_unlock_irqrestore(&port->lock, flags); | ||
397 | |||
398 | if (status) { | ||
399 | dbg("%s - non-zero urb status: %d", __func__, status); | ||
504 | 400 | ||
505 | spin_lock_irqsave(&port->lock, flags); | 401 | spin_lock_irqsave(&port->lock, flags); |
506 | --port->urbs_in_flight; | 402 | kfifo_reset_out(&port->write_fifo); |
507 | port->tx_bytes_flight -= urb->transfer_buffer_length; | ||
508 | if (port->urbs_in_flight < 0) | ||
509 | port->urbs_in_flight = 0; | ||
510 | spin_unlock_irqrestore(&port->lock, flags); | 403 | spin_unlock_irqrestore(&port->lock, flags); |
511 | } else { | 404 | } else { |
512 | port->write_urb_busy = 0; | 405 | usb_serial_generic_write_start(port); |
513 | |||
514 | if (status) | ||
515 | kfifo_reset_out(&port->write_fifo); | ||
516 | else | ||
517 | usb_serial_generic_write_start(port); | ||
518 | } | 406 | } |
519 | 407 | ||
520 | if (status) | ||
521 | dbg("%s - non-zero urb status: %d", __func__, status); | ||
522 | |||
523 | usb_serial_port_softint(port); | 408 | usb_serial_port_softint(port); |
524 | } | 409 | } |
525 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); | 410 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); |
@@ -537,31 +422,31 @@ void usb_serial_generic_throttle(struct tty_struct *tty) | |||
537 | port->throttle_req = 1; | 422 | port->throttle_req = 1; |
538 | spin_unlock_irqrestore(&port->lock, flags); | 423 | spin_unlock_irqrestore(&port->lock, flags); |
539 | } | 424 | } |
425 | EXPORT_SYMBOL_GPL(usb_serial_generic_throttle); | ||
540 | 426 | ||
541 | void usb_serial_generic_unthrottle(struct tty_struct *tty) | 427 | void usb_serial_generic_unthrottle(struct tty_struct *tty) |
542 | { | 428 | { |
543 | struct usb_serial_port *port = tty->driver_data; | 429 | struct usb_serial_port *port = tty->driver_data; |
544 | int was_throttled; | 430 | int was_throttled; |
545 | unsigned long flags; | ||
546 | 431 | ||
547 | dbg("%s - port %d", __func__, port->number); | 432 | dbg("%s - port %d", __func__, port->number); |
548 | 433 | ||
549 | /* Clear the throttle flags */ | 434 | /* Clear the throttle flags */ |
550 | spin_lock_irqsave(&port->lock, flags); | 435 | spin_lock_irq(&port->lock); |
551 | was_throttled = port->throttled; | 436 | was_throttled = port->throttled; |
552 | port->throttled = port->throttle_req = 0; | 437 | port->throttled = port->throttle_req = 0; |
553 | spin_unlock_irqrestore(&port->lock, flags); | 438 | spin_unlock_irq(&port->lock); |
554 | 439 | ||
555 | if (was_throttled) { | 440 | if (was_throttled) |
556 | /* Resume reading from device */ | 441 | usb_serial_generic_submit_read_urb(port, GFP_KERNEL); |
557 | flush_and_resubmit_read_urb(port); | ||
558 | } | ||
559 | } | 442 | } |
443 | EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle); | ||
560 | 444 | ||
445 | #ifdef CONFIG_MAGIC_SYSRQ | ||
561 | int usb_serial_handle_sysrq_char(struct tty_struct *tty, | 446 | int usb_serial_handle_sysrq_char(struct tty_struct *tty, |
562 | struct usb_serial_port *port, unsigned int ch) | 447 | struct usb_serial_port *port, unsigned int ch) |
563 | { | 448 | { |
564 | if (port->sysrq && port->console) { | 449 | if (port->sysrq && port->port.console) { |
565 | if (ch && time_before(jiffies, port->sysrq)) { | 450 | if (ch && time_before(jiffies, port->sysrq)) { |
566 | handle_sysrq(ch, tty); | 451 | handle_sysrq(ch, tty); |
567 | port->sysrq = 0; | 452 | port->sysrq = 0; |
@@ -571,6 +456,13 @@ int usb_serial_handle_sysrq_char(struct tty_struct *tty, | |||
571 | } | 456 | } |
572 | return 0; | 457 | return 0; |
573 | } | 458 | } |
459 | #else | ||
460 | int usb_serial_handle_sysrq_char(struct tty_struct *tty, | ||
461 | struct usb_serial_port *port, unsigned int ch) | ||
462 | { | ||
463 | return 0; | ||
464 | } | ||
465 | #endif | ||
574 | EXPORT_SYMBOL_GPL(usb_serial_handle_sysrq_char); | 466 | EXPORT_SYMBOL_GPL(usb_serial_handle_sysrq_char); |
575 | 467 | ||
576 | int usb_serial_handle_break(struct usb_serial_port *port) | 468 | int usb_serial_handle_break(struct usb_serial_port *port) |
@@ -600,7 +492,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) | |||
600 | c++; | 492 | c++; |
601 | } | 493 | } |
602 | 494 | ||
603 | if (port->write_urb) { | 495 | if (port->bulk_out_size) { |
604 | r = usb_serial_generic_write_start(port); | 496 | r = usb_serial_generic_write_start(port); |
605 | if (r < 0) | 497 | if (r < 0) |
606 | c++; | 498 | c++; |