aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/generic.c
diff options
context:
space:
mode:
authorDavid VomLehn <dvomlehn@cisco.com>2009-08-28 15:54:27 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:34 -0400
commit8e8dce065088833fc418bfa5fbf035cb0726c04c (patch)
tree146ad73ff1ee9439263678c5493a5c2d180ad794 /drivers/usb/serial/generic.c
parent74aee796c613f54e9f089170df548c0b3f15af69 (diff)
USB: use kfifo to buffer usb-generic serial writes
When do_output_char() attempts to write a carriage return/line feed sequence, it first checks to see how much buffer room is available. If there are at least two characters free, it will write the carriage return/line feed with two calls to tty_put_char(). It calls the tty_operation functions write() for devices that don't support the tty_operations function put_char(). If the USB generic serial device's write URB is not in use, it will return the buffer size when asked how much room is available. The write() of the carriage return will cause it to mark the write URB busy, so the subsequent write() of the line feed will be ignored. This patch uses the kfifo infrastructure to implement a write FIFO that accurately returns the amount of space available in the buffer. Signed-off-by: David VomLehn <dvomlehn@cisco.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r--drivers/usb/serial/generic.c206
1 files changed, 125 insertions, 81 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index d9398e9f30ce..deba08c7a015 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -19,7 +19,7 @@
19#include <linux/usb.h> 19#include <linux/usb.h>
20#include <linux/usb/serial.h> 20#include <linux/usb/serial.h>
21#include <linux/uaccess.h> 21#include <linux/uaccess.h>
22 22#include <linux/kfifo.h>
23 23
24static int debug; 24static int debug;
25 25
@@ -166,24 +166,6 @@ static void generic_cleanup(struct usb_serial_port *port)
166 } 166 }
167} 167}
168 168
169int usb_serial_generic_resume(struct usb_serial *serial)
170{
171 struct usb_serial_port *port;
172 int i, c = 0, r;
173
174 for (i = 0; i < serial->num_ports; i++) {
175 port = serial->port[i];
176 if (port->port.count && port->read_urb) {
177 r = usb_submit_urb(port->read_urb, GFP_NOIO);
178 if (r < 0)
179 c++;
180 }
181 }
182
183 return c ? -EIO : 0;
184}
185EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
186
187void usb_serial_generic_close(struct usb_serial_port *port) 169void usb_serial_generic_close(struct usb_serial_port *port)
188{ 170{
189 dbg("%s - port %d", __func__, port->number); 171 dbg("%s - port %d", __func__, port->number);
@@ -272,12 +254,81 @@ error_no_buffer:
272 return bwrite; 254 return bwrite;
273} 255}
274 256
257/**
258 * usb_serial_generic_write_start - kick off an URB write
259 * @port: Pointer to the &struct usb_serial_port data
260 *
261 * Returns the number of bytes queued on success. This will be zero if there
262 * was nothing to send. Otherwise, it returns a negative errno value
263 */
264static int usb_serial_generic_write_start(struct usb_serial_port *port)
265{
266 struct usb_serial *serial = port->serial;
267 unsigned char *data;
268 int result;
269 int count;
270 unsigned long flags;
271 bool start_io;
272
273 /* Atomically determine whether we can and need to start a USB
274 * operation. */
275 spin_lock_irqsave(&port->lock, flags);
276 if (port->write_urb_busy)
277 start_io = false;
278 else {
279 start_io = (__kfifo_len(port->write_fifo) != 0);
280 port->write_urb_busy = start_io;
281 }
282 spin_unlock_irqrestore(&port->lock, flags);
283
284 if (!start_io)
285 return 0;
286
287 data = port->write_urb->transfer_buffer;
288 count = kfifo_get(port->write_fifo, data, port->bulk_out_size);
289 usb_serial_debug_data(debug, &port->dev, __func__, count, data);
290
291 /* set up our urb */
292 usb_fill_bulk_urb(port->write_urb, serial->dev,
293 usb_sndbulkpipe(serial->dev,
294 port->bulk_out_endpointAddress),
295 port->write_urb->transfer_buffer, count,
296 ((serial->type->write_bulk_callback) ?
297 serial->type->write_bulk_callback :
298 usb_serial_generic_write_bulk_callback),
299 port);
300
301 /* send the data out the bulk port */
302 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
303 if (result) {
304 dev_err(&port->dev,
305 "%s - failed submitting write urb, error %d\n",
306 __func__, result);
307 /* don't have to grab the lock here, as we will
308 retry if != 0 */
309 port->write_urb_busy = 0;
310 } else
311 result = count;
312
313 return result;
314}
315
316/**
317 * usb_serial_generic_write - generic write function for serial USB devices
318 * @tty: Pointer to &struct tty_struct for the device
319 * @port: Pointer to the &usb_serial_port structure for the device
320 * @buf: Pointer to the data to write
321 * @count: Number of bytes to write
322 *
323 * Returns the number of characters actually written, which may be anything
324 * from zero to @count. If an error occurs, it returns the negative errno
325 * value.
326 */
275int usb_serial_generic_write(struct tty_struct *tty, 327int usb_serial_generic_write(struct tty_struct *tty,
276 struct usb_serial_port *port, const unsigned char *buf, int count) 328 struct usb_serial_port *port, const unsigned char *buf, int count)
277{ 329{
278 struct usb_serial *serial = port->serial; 330 struct usb_serial *serial = port->serial;
279 int result; 331 int result;
280 unsigned char *data;
281 332
282 dbg("%s - port %d", __func__, port->number); 333 dbg("%s - port %d", __func__, port->number);
283 334
@@ -287,57 +338,20 @@ int usb_serial_generic_write(struct tty_struct *tty,
287 } 338 }
288 339
289 /* only do something if we have a bulk out endpoint */ 340 /* only do something if we have a bulk out endpoint */
290 if (serial->num_bulk_out) { 341 if (!serial->num_bulk_out)
291 unsigned long flags; 342 return 0;
292
293 if (serial->type->max_in_flight_urbs)
294 return usb_serial_multi_urb_write(tty, port,
295 buf, count);
296
297 spin_lock_irqsave(&port->lock, flags);
298 if (port->write_urb_busy) {
299 spin_unlock_irqrestore(&port->lock, flags);
300 dbg("%s - already writing", __func__);
301 return 0;
302 }
303 port->write_urb_busy = 1;
304 spin_unlock_irqrestore(&port->lock, flags);
305
306 count = (count > port->bulk_out_size) ?
307 port->bulk_out_size : count;
308
309 memcpy(port->write_urb->transfer_buffer, buf, count);
310 data = port->write_urb->transfer_buffer;
311 usb_serial_debug_data(debug, &port->dev, __func__, count, data);
312 343
313 /* set up our urb */ 344 if (serial->type->max_in_flight_urbs)
314 usb_fill_bulk_urb(port->write_urb, serial->dev, 345 return usb_serial_multi_urb_write(tty, port,
315 usb_sndbulkpipe(serial->dev, 346 buf, count);
316 port->bulk_out_endpointAddress),
317 port->write_urb->transfer_buffer, count,
318 ((serial->type->write_bulk_callback) ?
319 serial->type->write_bulk_callback :
320 usb_serial_generic_write_bulk_callback),
321 port);
322 347
323 /* send the data out the bulk port */ 348 count = kfifo_put(port->write_fifo, buf, count);
324 port->write_urb_busy = 1; 349 result = usb_serial_generic_write_start(port);
325 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
326 if (result) {
327 dev_err(&port->dev,
328 "%s - failed submitting write urb, error %d\n",
329 __func__, result);
330 /* don't have to grab the lock here, as we will
331 retry if != 0 */
332 port->write_urb_busy = 0;
333 } else
334 result = count;
335 350
336 return result; 351 if (result >= 0)
337 } 352 result = count;
338 353
339 /* no bulk out, so return 0 bytes written */ 354 return result;
340 return 0;
341} 355}
342EXPORT_SYMBOL_GPL(usb_serial_generic_write); 356EXPORT_SYMBOL_GPL(usb_serial_generic_write);
343 357
@@ -355,9 +369,8 @@ int usb_serial_generic_write_room(struct tty_struct *tty)
355 room = port->bulk_out_size * 369 room = port->bulk_out_size *
356 (serial->type->max_in_flight_urbs - 370 (serial->type->max_in_flight_urbs -
357 port->urbs_in_flight); 371 port->urbs_in_flight);
358 } else if (serial->num_bulk_out && !(port->write_urb_busy)) { 372 } else if (serial->num_bulk_out)
359 room = port->bulk_out_size; 373 room = port->write_fifo->size - __kfifo_len(port->write_fifo);
360 }
361 spin_unlock_irqrestore(&port->lock, flags); 374 spin_unlock_irqrestore(&port->lock, flags);
362 375
363 dbg("%s - returns %d", __func__, room); 376 dbg("%s - returns %d", __func__, room);
@@ -377,11 +390,8 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
377 spin_lock_irqsave(&port->lock, flags); 390 spin_lock_irqsave(&port->lock, flags);
378 chars = port->tx_bytes_flight; 391 chars = port->tx_bytes_flight;
379 spin_unlock_irqrestore(&port->lock, flags); 392 spin_unlock_irqrestore(&port->lock, flags);
380 } else if (serial->num_bulk_out) { 393 } else if (serial->num_bulk_out)
381 /* FIXME: Locking */ 394 chars = kfifo_len(port->write_fifo);
382 if (port->write_urb_busy)
383 chars = port->write_urb->transfer_buffer_length;
384 }
385 395
386 dbg("%s - returns %d", __func__, chars); 396 dbg("%s - returns %d", __func__, chars);
387 return chars; 397 return chars;
@@ -485,16 +495,23 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
485 if (port->urbs_in_flight < 0) 495 if (port->urbs_in_flight < 0)
486 port->urbs_in_flight = 0; 496 port->urbs_in_flight = 0;
487 spin_unlock_irqrestore(&port->lock, flags); 497 spin_unlock_irqrestore(&port->lock, flags);
498
499 if (status) {
500 dbg("%s - nonzero multi-urb write bulk status "
501 "received: %d", __func__, status);
502 return;
503 }
488 } else { 504 } else {
489 /* Handle the case for single urb mode */
490 port->write_urb_busy = 0; 505 port->write_urb_busy = 0;
491 }
492 506
493 if (status) { 507 if (status) {
494 dbg("%s - nonzero write bulk status received: %d", 508 dbg("%s - nonzero multi-urb write bulk status "
495 __func__, status); 509 "received: %d", __func__, status);
496 return; 510 kfifo_reset(port->write_fifo);
511 } else
512 usb_serial_generic_write_start(port);
497 } 513 }
514
498 usb_serial_port_softint(port); 515 usb_serial_port_softint(port);
499} 516}
500EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); 517EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
@@ -559,6 +576,33 @@ int usb_serial_handle_break(struct usb_serial_port *port)
559} 576}
560EXPORT_SYMBOL_GPL(usb_serial_handle_break); 577EXPORT_SYMBOL_GPL(usb_serial_handle_break);
561 578
579int usb_serial_generic_resume(struct usb_serial *serial)
580{
581 struct usb_serial_port *port;
582 int i, c = 0, r;
583
584 for (i = 0; i < serial->num_ports; i++) {
585 port = serial->port[i];
586 if (!port->port.count)
587 continue;
588
589 if (port->read_urb) {
590 r = usb_submit_urb(port->read_urb, GFP_NOIO);
591 if (r < 0)
592 c++;
593 }
594
595 if (port->write_urb) {
596 r = usb_serial_generic_write_start(port);
597 if (r < 0)
598 c++;
599 }
600 }
601
602 return c ? -EIO : 0;
603}
604EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
605
562void usb_serial_generic_disconnect(struct usb_serial *serial) 606void usb_serial_generic_disconnect(struct usb_serial *serial)
563{ 607{
564 int i; 608 int i;