aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/usb/serial/generic.c206
-rw-r--r--drivers/usb/serial/usb-serial.c7
-rw-r--r--include/linux/usb/serial.h2
3 files changed, 134 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;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 45975b4984ea..ff75a3589e7e 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -35,6 +35,7 @@
35#include <linux/serial.h> 35#include <linux/serial.h>
36#include <linux/usb.h> 36#include <linux/usb.h>
37#include <linux/usb/serial.h> 37#include <linux/usb/serial.h>
38#include <linux/kfifo.h>
38#include "pl2303.h" 39#include "pl2303.h"
39 40
40/* 41/*
@@ -625,6 +626,8 @@ static void port_release(struct device *dev)
625 usb_free_urb(port->write_urb); 626 usb_free_urb(port->write_urb);
626 usb_free_urb(port->interrupt_in_urb); 627 usb_free_urb(port->interrupt_in_urb);
627 usb_free_urb(port->interrupt_out_urb); 628 usb_free_urb(port->interrupt_out_urb);
629 if (!IS_ERR(port->write_fifo) && port->write_fifo)
630 kfifo_free(port->write_fifo);
628 kfree(port->bulk_in_buffer); 631 kfree(port->bulk_in_buffer);
629 kfree(port->bulk_out_buffer); 632 kfree(port->bulk_out_buffer);
630 kfree(port->interrupt_in_buffer); 633 kfree(port->interrupt_in_buffer);
@@ -964,6 +967,10 @@ int usb_serial_probe(struct usb_interface *interface,
964 dev_err(&interface->dev, "No free urbs available\n"); 967 dev_err(&interface->dev, "No free urbs available\n");
965 goto probe_error; 968 goto probe_error;
966 } 969 }
970 port->write_fifo = kfifo_alloc(PAGE_SIZE, GFP_KERNEL,
971 &port->lock);
972 if (IS_ERR(port->write_fifo))
973 goto probe_error;
967 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); 974 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
968 port->bulk_out_size = buffer_size; 975 port->bulk_out_size = buffer_size;
969 port->bulk_out_endpointAddress = endpoint->bEndpointAddress; 976 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 7b85e327af91..c17eb64d7213 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -59,6 +59,7 @@ enum port_dev_state {
59 * @bulk_out_buffer: pointer to the bulk out buffer for this port. 59 * @bulk_out_buffer: pointer to the bulk out buffer for this port.
60 * @bulk_out_size: the size of the bulk_out_buffer, in bytes. 60 * @bulk_out_size: the size of the bulk_out_buffer, in bytes.
61 * @write_urb: pointer to the bulk out struct urb for this port. 61 * @write_urb: pointer to the bulk out struct urb for this port.
62 * @write_fifo: kfifo used to buffer outgoing data
62 * @write_urb_busy: port`s writing status 63 * @write_urb_busy: port`s writing status
63 * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this 64 * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this
64 * port. 65 * port.
@@ -96,6 +97,7 @@ struct usb_serial_port {
96 unsigned char *bulk_out_buffer; 97 unsigned char *bulk_out_buffer;
97 int bulk_out_size; 98 int bulk_out_size;
98 struct urb *write_urb; 99 struct urb *write_urb;
100 struct kfifo *write_fifo;
99 int write_urb_busy; 101 int write_urb_busy;
100 __u8 bulk_out_endpointAddress; 102 __u8 bulk_out_endpointAddress;
101 103