aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2006-01-09 23:54:13 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 11:01:59 -0500
commit33f0f88f1c51ae5c2d593d26960c760ea154c2e2 (patch)
treef53a38cf49406863f079d74d0e8f91b276f7c1a9 /drivers/usb/serial
parent6ed80991a2dce4afc113be35089c564d62fa1f11 (diff)
[PATCH] TTY layer buffering revamp
The API and code have been through various bits of initial review by serial driver people but they definitely need to live somewhere for a while so the unconverted drivers can get knocked into shape, existing drivers that have been updated can be better tuned and bugs whacked out. This replaces the tty flip buffers with kmalloc objects in rings. In the normal situation for an IRQ driven serial port at typical speeds the behaviour is pretty much the same, two buffers end up allocated and the kernel cycles between them as before. When there are delays or at high speed we now behave far better as the buffer pool can grow a bit rather than lose characters. This also means that we can operate at higher speeds reliably. For drivers that receive characters in blocks (DMA based, USB and especially virtualisation) the layer allows a lot of driver specific code that works around the tty layer with private secondary queues to be removed. The IBM folks need this sort of layer, the smart serial port people do, the virtualisers do (because a virtualised tty typically operates at infinite speed rather than emulating 9600 baud). Finally many drivers had invalid and unsafe attempts to avoid buffer overflows by directly invoking tty methods extracted out of the innards of work queue structs. These are no longer needed and all go away. That fixes various random hangs with serial ports on overflow. The other change in here is to optimise the receive_room path that is used by some callers. It turns out that only one ldisc uses receive room except asa constant and it updates it far far less than the value is read. We thus make it a variable not a function call. I expect the code to contain bugs due to the size alone but I'll be watching and squashing them and feeding out new patches as it goes. Because the buffers now dynamically expand you should only run out of buffering when the kernel runs out of memory for real. That means a lot of the horrible hacks high performance drivers used to do just aren't needed any more. Description: tty_insert_flip_char is an old API and continues to work as before, as does tty_flip_buffer_push() [this is why many drivers dont need modification]. It does now also return the number of chars inserted There are also tty_buffer_request_room(tty, len) which asks for a buffer block of the length requested and returns the space found. This improves efficiency with hardware that knows how much to transfer. and tty_insert_flip_string_flags(tty, str, flags, len) to insert a string of characters and flags For a smart interface the usual code is len = tty_request_buffer_room(tty, amount_hardware_says); tty_insert_flip_string(tty, buffer_from_card, len); More description! At the moment tty buffers are attached directly to the tty. This is causing a lot of the problems related to tty layer locking, also problems at high speed and also with bursty data (such as occurs in virtualised environments) I'm working on ripping out the flip buffers and replacing them with a pool of dynamically allocated buffers. This allows both for old style "byte I/O" devices and also helps virtualisation and smart devices where large blocks of data suddenely materialise and need storing. So far so good. Lots of drivers reference tty->flip.*. Several of them also call directly and unsafely into function pointers it provides. This will all break. Most drivers can use tty_insert_flip_char which can be kept as an API but others need more. At the moment I've added the following interfaces, if people think more will be needed now is a good time to say int tty_buffer_request_room(tty, size) Try and ensure at least size bytes are available, returns actual room (may be zero). At the moment it just uses the flipbuf space but that will change. Repeated calls without characters being added are not cumulative. (ie if you call it with 1, 1, 1, and then 4 you'll have four characters of space. The other functions will also try and grow buffers in future but this will be a more efficient way when you know block sizes. int tty_insert_flip_char(tty, ch, flag) As before insert a character if there is room. Now returns 1 for success, 0 for failure. int tty_insert_flip_string(tty, str, len) Insert a block of non error characters. Returns the number inserted. int tty_prepare_flip_string(tty, strptr, len) Adjust the buffer to allow len characters to be added. Returns a buffer pointer in strptr and the length available. This allows for hardware that needs to use functions like insl or mencpy_fromio. Signed-off-by: Alan Cox <alan@redhat.com> Cc: Paul Fulghum <paulkf@microgate.com> Signed-off-by: Hirokazu Takata <takata@linux-m32r.org> Signed-off-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: Jeff Dike <jdike@addtoit.com> Signed-off-by: John Hawkes <hawkes@sgi.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/Kconfig2
-rw-r--r--drivers/usb/serial/cyberjack.c11
-rw-r--r--drivers/usb/serial/cypress_m8.c4
-rw-r--r--drivers/usb/serial/digi_acceleport.c28
-rw-r--r--drivers/usb/serial/empeg.c16
-rw-r--r--drivers/usb/serial/ftdi_sio.c15
-rw-r--r--drivers/usb/serial/garmin_gps.c13
-rw-r--r--drivers/usb/serial/generic.c11
-rw-r--r--drivers/usb/serial/io_edgeport.c20
-rw-r--r--drivers/usb/serial/io_ti.c20
-rw-r--r--drivers/usb/serial/ipaq.c12
-rw-r--r--drivers/usb/serial/ipw.c11
-rw-r--r--drivers/usb/serial/kl5kusb105.c13
-rw-r--r--drivers/usb/serial/kobil_sct.c11
-rw-r--r--drivers/usb/serial/option.c9
-rw-r--r--drivers/usb/serial/pl2303.c8
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c20
-rw-r--r--drivers/usb/serial/visor.c11
-rw-r--r--drivers/usb/serial/whiteheat.c11
19 files changed, 65 insertions, 181 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 14f55fd26a64..be5dc80836c3 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -84,7 +84,7 @@ config USB_SERIAL_BELKIN
84 84
85config USB_SERIAL_WHITEHEAT 85config USB_SERIAL_WHITEHEAT
86 tristate "USB ConnectTech WhiteHEAT Serial Driver" 86 tristate "USB ConnectTech WhiteHEAT Serial Driver"
87 depends on USB_SERIAL && BROKEN_ON_SMP 87 depends on USB_SERIAL
88 help 88 help
89 Say Y here if you want to use a ConnectTech WhiteHEAT 4 port 89 Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
90 USB to serial converter device. 90 USB to serial converter device.
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 6d18d4eaba35..2357b1d102d7 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -364,7 +364,6 @@ static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
364 struct tty_struct *tty; 364 struct tty_struct *tty;
365 unsigned char *data = urb->transfer_buffer; 365 unsigned char *data = urb->transfer_buffer;
366 short todo; 366 short todo;
367 int i;
368 int result; 367 int result;
369 368
370 dbg("%s - port %d", __FUNCTION__, port->number); 369 dbg("%s - port %d", __FUNCTION__, port->number);
@@ -381,14 +380,8 @@ static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
381 return; 380 return;
382 } 381 }
383 if (urb->actual_length) { 382 if (urb->actual_length) {
384 for (i = 0; i < urb->actual_length ; ++i) { 383 tty_buffer_request_room(tty, urb->actual_length);
385 /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ 384 tty_insert_flip_string(tty, data, urb->actual_length);
386 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
387 tty_flip_buffer_push(tty);
388 }
389 /* this doesn't actually push the data through unless tty->low_latency is set */
390 tty_insert_flip_char(tty, data[i], 0);
391 }
392 tty_flip_buffer_push(tty); 385 tty_flip_buffer_push(tty);
393 } 386 }
394 387
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 4e9637eb6137..68067fe117a4 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -1263,12 +1263,10 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
1263 1263
1264 /* process read if there is data other than line status */ 1264 /* process read if there is data other than line status */
1265 if (tty && (bytes > i)) { 1265 if (tty && (bytes > i)) {
1266 bytes = tty_buffer_request_room(tty, bytes);
1266 for (; i < bytes ; ++i) { 1267 for (; i < bytes ; ++i) {
1267 dbg("pushing byte number %d - %d - %c", i, data[i], 1268 dbg("pushing byte number %d - %d - %c", i, data[i],
1268 data[i]); 1269 data[i]);
1269 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
1270 tty_flip_buffer_push(tty);
1271 }
1272 tty_insert_flip_char(tty, data[i], tty_flag); 1270 tty_insert_flip_char(tty, data[i], tty_flag);
1273 } 1271 }
1274 tty_flip_buffer_push(port->tty); 1272 tty_flip_buffer_push(port->tty);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 8fc414bd5b24..b3f776a90c93 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -946,13 +946,10 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
946 spin_lock_irqsave( &priv->dp_port_lock, flags ); 946 spin_lock_irqsave( &priv->dp_port_lock, flags );
947 947
948 /* send any buffered chars from throttle time on to tty subsystem */ 948 /* send any buffered chars from throttle time on to tty subsystem */
949 len = min(priv->dp_in_buf_len, TTY_FLIPBUF_SIZE - tty->flip.count ); 949
950 len = tty_buffer_request_room(tty, priv->dp_in_buf_len);
950 if( len > 0 ) { 951 if( len > 0 ) {
951 memcpy( tty->flip.char_buf_ptr, priv->dp_in_buf, len ); 952 tty_insert_flip_string_flags(tty, priv->dp_in_buf, priv->dp_in_flag_buf, len);
952 memcpy( tty->flip.flag_buf_ptr, priv->dp_in_flag_buf, len );
953 tty->flip.char_buf_ptr += len;
954 tty->flip.flag_buf_ptr += len;
955 tty->flip.count += len;
956 tty_flip_buffer_push( tty ); 953 tty_flip_buffer_push( tty );
957 } 954 }
958 955
@@ -1827,6 +1824,7 @@ static int digi_read_inb_callback( struct urb *urb )
1827 int status = ((unsigned char *)urb->transfer_buffer)[2]; 1824 int status = ((unsigned char *)urb->transfer_buffer)[2];
1828 unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3; 1825 unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
1829 int flag,throttled; 1826 int flag,throttled;
1827 int i;
1830 1828
1831 /* do not process callbacks on closed ports */ 1829 /* do not process callbacks on closed ports */
1832 /* but do continue the read chain */ 1830 /* but do continue the read chain */
@@ -1885,20 +1883,18 @@ static int digi_read_inb_callback( struct urb *urb )
1885 } 1883 }
1886 1884
1887 } else { 1885 } else {
1888 1886 len = tty_buffer_request_room(tty, len);
1889 len = min( len, TTY_FLIPBUF_SIZE - tty->flip.count );
1890
1891 if( len > 0 ) { 1887 if( len > 0 ) {
1892 memcpy( tty->flip.char_buf_ptr, data, len ); 1888 /* Hot path */
1893 memset( tty->flip.flag_buf_ptr, flag, len ); 1889 if(flag == TTY_NORMAL)
1894 tty->flip.char_buf_ptr += len; 1890 tty_insert_flip_string(tty, data, len);
1895 tty->flip.flag_buf_ptr += len; 1891 else {
1896 tty->flip.count += len; 1892 for(i = 0; i < len; i++)
1893 tty_insert_flip_char(tty, data[i], flag);
1894 }
1897 tty_flip_buffer_push( tty ); 1895 tty_flip_buffer_push( tty );
1898 } 1896 }
1899
1900 } 1897 }
1901
1902 } 1898 }
1903 1899
1904 spin_unlock( &priv->dp_port_lock ); 1900 spin_unlock( &priv->dp_port_lock );
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 79a766e9ca23..63f7c78a1152 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -344,7 +344,6 @@ static void empeg_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
344 struct usb_serial_port *port = (struct usb_serial_port *)urb->context; 344 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
345 struct tty_struct *tty; 345 struct tty_struct *tty;
346 unsigned char *data = urb->transfer_buffer; 346 unsigned char *data = urb->transfer_buffer;
347 int i;
348 int result; 347 int result;
349 348
350 dbg("%s - port %d", __FUNCTION__, port->number); 349 dbg("%s - port %d", __FUNCTION__, port->number);
@@ -359,19 +358,8 @@ static void empeg_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
359 tty = port->tty; 358 tty = port->tty;
360 359
361 if (urb->actual_length) { 360 if (urb->actual_length) {
362 for (i = 0; i < urb->actual_length ; ++i) { 361 tty_buffer_request_room(tty, urb->actual_length);
363 /* gb - 2000/11/13 362 tty_insert_flip_string(tty, data, urb->actual_length);
364 * If we insert too many characters we'll overflow the buffer.
365 * This means we'll lose bytes - Decidedly bad.
366 */
367 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
368 tty_flip_buffer_push(tty);
369 }
370 tty_insert_flip_char(tty, data[i], 0);
371 }
372 /* gb - 2000/11/13
373 * Goes straight through instead of scheduling - if tty->low_latency is set.
374 */
375 tty_flip_buffer_push(tty); 363 tty_flip_buffer_push(tty);
376 bytes_in += urb->actual_length; 364 bytes_in += urb->actual_length;
377 } 365 }
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index eb863b3f2d79..10bc1bf23b35 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1610,24 +1610,11 @@ static void ftdi_process_read (void *param)
1610 length = 0; 1610 length = 0;
1611 } 1611 }
1612 1612
1613 /* have to make sure we don't overflow the buffer
1614 with tty_insert_flip_char's */
1615 if (tty->flip.count+length > TTY_FLIPBUF_SIZE) {
1616 tty_flip_buffer_push(tty);
1617 need_flip = 0;
1618
1619 if (tty->flip.count != 0) {
1620 /* flip didn't work, this happens when ftdi_process_read() is
1621 * called from ftdi_unthrottle, because TTY_DONT_FLIP is set */
1622 dbg("%s - flip buffer push failed", __FUNCTION__);
1623 break;
1624 }
1625 }
1626 if (priv->rx_flags & THROTTLED) { 1613 if (priv->rx_flags & THROTTLED) {
1627 dbg("%s - throttled", __FUNCTION__); 1614 dbg("%s - throttled", __FUNCTION__);
1628 break; 1615 break;
1629 } 1616 }
1630 if (tty->ldisc.receive_room(tty)-tty->flip.count < length) { 1617 if (tty_buffer_request_room(tty, length) < length) {
1631 /* break out & wait for throttling/unthrottling to happen */ 1618 /* break out & wait for throttling/unthrottling to happen */
1632 dbg("%s - receive room low", __FUNCTION__); 1619 dbg("%s - receive room low", __FUNCTION__);
1633 break; 1620 break;
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 452efce72714..d6f55e9dccae 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -275,23 +275,14 @@ static void send_to_tty(struct usb_serial_port *port,
275 char *data, unsigned int actual_length) 275 char *data, unsigned int actual_length)
276{ 276{
277 struct tty_struct *tty = port->tty; 277 struct tty_struct *tty = port->tty;
278 int i;
279 278
280 if (tty && actual_length) { 279 if (tty && actual_length) {
281 280
282 usb_serial_debug_data(debug, &port->dev, 281 usb_serial_debug_data(debug, &port->dev,
283 __FUNCTION__, actual_length, data); 282 __FUNCTION__, actual_length, data);
284 283
285 for (i = 0; i < actual_length ; ++i) { 284 tty_buffer_request_room(tty, actual_length);
286 /* if we insert more than TTY_FLIPBUF_SIZE characters, 285 tty_insert_flip_string(tty, data, actual_length);
287 we drop them. */
288 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
289 tty_flip_buffer_push(tty);
290 }
291 /* this doesn't actually push the data through unless
292 tty->low_latency is set */
293 tty_insert_flip_char(tty, data[i], 0);
294 }
295 tty_flip_buffer_push(tty); 286 tty_flip_buffer_push(tty);
296 } 287 }
297} 288}
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 4ddac620fc0c..476cda107f4f 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -254,7 +254,6 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *reg
254 struct usb_serial *serial = port->serial; 254 struct usb_serial *serial = port->serial;
255 struct tty_struct *tty; 255 struct tty_struct *tty;
256 unsigned char *data = urb->transfer_buffer; 256 unsigned char *data = urb->transfer_buffer;
257 int i;
258 int result; 257 int result;
259 258
260 dbg("%s - port %d", __FUNCTION__, port->number); 259 dbg("%s - port %d", __FUNCTION__, port->number);
@@ -268,14 +267,8 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *reg
268 267
269 tty = port->tty; 268 tty = port->tty;
270 if (tty && urb->actual_length) { 269 if (tty && urb->actual_length) {
271 for (i = 0; i < urb->actual_length ; ++i) { 270 tty_buffer_request_room(tty, urb->actual_length);
272 /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ 271 tty_insert_flip_string(tty, data, urb->actual_length);
273 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
274 tty_flip_buffer_push(tty);
275 }
276 /* this doesn't actually push the data through unless tty->low_latency is set */
277 tty_insert_flip_char(tty, data[i], 0);
278 }
279 tty_flip_buffer_push(tty); 272 tty_flip_buffer_push(tty);
280 } 273 }
281 274
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index faedbeb6ba49..3f29e6b0fd19 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1965,20 +1965,14 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
1965 int cnt; 1965 int cnt;
1966 1966
1967 do { 1967 do {
1968 if (tty->flip.count >= TTY_FLIPBUF_SIZE) { 1968 cnt = tty_buffer_request_room(tty, length);
1969 tty_flip_buffer_push(tty); 1969 if (cnt < length) {
1970 if (tty->flip.count >= TTY_FLIPBUF_SIZE) { 1970 dev_err(dev, "%s - dropping data, %d bytes lost\n",
1971 dev_err(dev, "%s - dropping data, %d bytes lost\n", 1971 __FUNCTION__, length - cnt);
1972 __FUNCTION__, length); 1972 if(cnt == 0)
1973 return; 1973 break;
1974 }
1975 } 1974 }
1976 cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count); 1975 tty_insert_flip_string(tty, data, cnt);
1977 memcpy(tty->flip.char_buf_ptr, data, cnt);
1978 memset(tty->flip.flag_buf_ptr, 0, cnt);
1979 tty->flip.char_buf_ptr += cnt;
1980 tty->flip.flag_buf_ptr += cnt;
1981 tty->flip.count += cnt;
1982 data += cnt; 1976 data += cnt;
1983 length -= cnt; 1977 length -= cnt;
1984 } while (length > 0); 1978 } while (length > 0);
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 2edf9cabad20..afc0f34b3a46 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -1865,20 +1865,14 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
1865 int cnt; 1865 int cnt;
1866 1866
1867 do { 1867 do {
1868 if (tty->flip.count >= TTY_FLIPBUF_SIZE) { 1868 cnt = tty_buffer_request_room(tty, length);
1869 tty_flip_buffer_push(tty); 1869 if (cnt < length) {
1870 if (tty->flip.count >= TTY_FLIPBUF_SIZE) { 1870 dev_err(dev, "%s - dropping data, %d bytes lost\n",
1871 dev_err(dev, "%s - dropping data, %d bytes lost\n", 1871 __FUNCTION__, length - cnt);
1872 __FUNCTION__, length); 1872 if(cnt == 0)
1873 return; 1873 break;
1874 }
1875 } 1874 }
1876 cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count); 1875 tty_insert_flip_string(tty, data, cnt);
1877 memcpy(tty->flip.char_buf_ptr, data, cnt);
1878 memset(tty->flip.flag_buf_ptr, 0, cnt);
1879 tty->flip.char_buf_ptr += cnt;
1880 tty->flip.flag_buf_ptr += cnt;
1881 tty->flip.count += cnt;
1882 data += cnt; 1876 data += cnt;
1883 length -= cnt; 1877 length -= cnt;
1884 } while (length > 0); 1878 } while (length > 0);
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 06d07cea0b70..9a5c97989562 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -711,7 +711,7 @@ static void ipaq_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
711 struct usb_serial_port *port = (struct usb_serial_port *)urb->context; 711 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
712 struct tty_struct *tty; 712 struct tty_struct *tty;
713 unsigned char *data = urb->transfer_buffer; 713 unsigned char *data = urb->transfer_buffer;
714 int i, result; 714 int result;
715 715
716 dbg("%s - port %d", __FUNCTION__, port->number); 716 dbg("%s - port %d", __FUNCTION__, port->number);
717 717
@@ -724,14 +724,8 @@ static void ipaq_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
724 724
725 tty = port->tty; 725 tty = port->tty;
726 if (tty && urb->actual_length) { 726 if (tty && urb->actual_length) {
727 for (i = 0; i < urb->actual_length ; ++i) { 727 tty_buffer_request_room(tty, urb->actual_length);
728 /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ 728 tty_insert_flip_string(tty, data, urb->actual_length);
729 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
730 tty_flip_buffer_push(tty);
731 }
732 /* this doesn't actually push the data through unless tty->low_latency is set */
733 tty_insert_flip_char(tty, data[i], 0);
734 }
735 tty_flip_buffer_push(tty); 729 tty_flip_buffer_push(tty);
736 bytes_in += urb->actual_length; 730 bytes_in += urb->actual_length;
737 } 731 }
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 2dd191f5fe76..e760a70242c1 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -166,7 +166,6 @@ static void ipw_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
166 struct usb_serial_port *port = urb->context; 166 struct usb_serial_port *port = urb->context;
167 unsigned char *data = urb->transfer_buffer; 167 unsigned char *data = urb->transfer_buffer;
168 struct tty_struct *tty; 168 struct tty_struct *tty;
169 int i;
170 int result; 169 int result;
171 170
172 dbg("%s - port %d", __FUNCTION__, port->number); 171 dbg("%s - port %d", __FUNCTION__, port->number);
@@ -180,14 +179,8 @@ static void ipw_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
180 179
181 tty = port->tty; 180 tty = port->tty;
182 if (tty && urb->actual_length) { 181 if (tty && urb->actual_length) {
183 for (i = 0; i < urb->actual_length ; ++i) { 182 tty_buffer_request_room(tty, urb->actual_length);
184 /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ 183 tty_insert_flip_string(tty, data, urb->actual_length);
185 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
186 tty_flip_buffer_push(tty);
187 }
188 /* this doesn't actually push the data through unless tty->low_latency is set */
189 tty_insert_flip_char(tty, data[i], 0);
190 }
191 tty_flip_buffer_push(tty); 184 tty_flip_buffer_push(tty);
192 } 185 }
193 186
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 4e2f7dfb58b2..78335a5f7743 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -648,7 +648,6 @@ static void klsi_105_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
648 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, 648 usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
649 urb->actual_length, data); 649 urb->actual_length, data);
650 } else { 650 } else {
651 int i;
652 int bytes_sent = ((__u8 *) data)[0] + 651 int bytes_sent = ((__u8 *) data)[0] +
653 ((unsigned int) ((__u8 *) data)[1] << 8); 652 ((unsigned int) ((__u8 *) data)[1] << 8);
654 tty = port->tty; 653 tty = port->tty;
@@ -669,16 +668,8 @@ static void klsi_105_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
669 bytes_sent = urb->actual_length - 2; 668 bytes_sent = urb->actual_length - 2;
670 } 669 }
671 670
672 for (i = 2; i < 2+bytes_sent; i++) { 671 tty_buffer_request_room(tty, bytes_sent);
673 /* if we insert more than TTY_FLIPBUF_SIZE characters, 672 tty_insert_flip_string(tty, data + 2, bytes_sent);
674 * we drop them. */
675 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
676 tty_flip_buffer_push(tty);
677 }
678 /* this doesn't actually push the data through unless
679 * tty->low_latency is set */
680 tty_insert_flip_char(tty, ((__u8*) data)[i], 0);
681 }
682 tty_flip_buffer_push(tty); 673 tty_flip_buffer_push(tty);
683 674
684 /* again lockless, but debug info only */ 675 /* again lockless, but debug info only */
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index d9c21e275130..b8b213185d0f 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -365,7 +365,6 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp)
365 365
366static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs) 366static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
367{ 367{
368 int i;
369 int result; 368 int result;
370 struct usb_serial_port *port = (struct usb_serial_port *) purb->context; 369 struct usb_serial_port *port = (struct usb_serial_port *) purb->context;
371 struct tty_struct *tty; 370 struct tty_struct *tty;
@@ -397,14 +396,8 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
397 */ 396 */
398 // END DEBUG 397 // END DEBUG
399 398
400 for (i = 0; i < purb->actual_length; ++i) { 399 tty_buffer_request_room(tty, purb->actual_length);
401 // if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. 400 tty_insert_flip_string(tty, data, purb->actual_length);
402 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
403 tty_flip_buffer_push(tty);
404 }
405 // this doesn't actually push the data through unless tty->low_latency is set
406 tty_insert_flip_char(tty, data[i], 0);
407 }
408 tty_flip_buffer_push(tty); 401 tty_flip_buffer_push(tty);
409 } 402 }
410 403
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 3fd2405304fd..52bdf6fe46f2 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -321,7 +321,7 @@ static int option_write(struct usb_serial_port *port,
321 321
322static void option_indat_callback(struct urb *urb, struct pt_regs *regs) 322static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
323{ 323{
324 int i, err; 324 int err;
325 int endpoint; 325 int endpoint;
326 struct usb_serial_port *port; 326 struct usb_serial_port *port;
327 struct tty_struct *tty; 327 struct tty_struct *tty;
@@ -338,11 +338,8 @@ static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
338 } else { 338 } else {
339 tty = port->tty; 339 tty = port->tty;
340 if (urb->actual_length) { 340 if (urb->actual_length) {
341 for (i = 0; i < urb->actual_length ; ++i) { 341 tty_buffer_request_room(tty, urb->actual_length);
342 if (tty->flip.count >= TTY_FLIPBUF_SIZE) 342 tty_insert_flip_string(tty, data, urb->actual_length);
343 tty_flip_buffer_push(tty);
344 tty_insert_flip_char(tty, data[i], 0);
345 }
346 tty_flip_buffer_push(tty); 343 tty_flip_buffer_push(tty);
347 } else { 344 } else {
348 dbg("%s: empty read urb received", __FUNCTION__); 345 dbg("%s: empty read urb received", __FUNCTION__);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index f03721056190..9ffff1938239 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -924,16 +924,12 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
924 924
925 tty = port->tty; 925 tty = port->tty;
926 if (tty && urb->actual_length) { 926 if (tty && urb->actual_length) {
927 tty_buffer_request_room(tty, urb->actual_length + 1);
927 /* overrun is special, not associated with a char */ 928 /* overrun is special, not associated with a char */
928 if (status & UART_OVERRUN_ERROR) 929 if (status & UART_OVERRUN_ERROR)
929 tty_insert_flip_char(tty, 0, TTY_OVERRUN); 930 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
930 931 for (i = 0; i < urb->actual_length; ++i)
931 for (i = 0; i < urb->actual_length; ++i) {
932 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
933 tty_flip_buffer_push(tty);
934 }
935 tty_insert_flip_char (tty, data[i], tty_flag); 932 tty_insert_flip_char (tty, data[i], tty_flag);
936 }
937 tty_flip_buffer_push (tty); 933 tty_flip_buffer_push (tty);
938 } 934 }
939 935
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index abb830cb77bd..c18db3257073 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1280,24 +1280,18 @@ static void ti_recv(struct device *dev, struct tty_struct *tty,
1280 int cnt; 1280 int cnt;
1281 1281
1282 do { 1282 do {
1283 if (tty->flip.count >= TTY_FLIPBUF_SIZE) { 1283 cnt = tty_buffer_request_room(tty, length);
1284 tty_flip_buffer_push(tty); 1284 if (cnt < length) {
1285 if (tty->flip.count >= TTY_FLIPBUF_SIZE) { 1285 dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length - cnt);
1286 dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length); 1286 if(cnt == 0)
1287 return; 1287 break;
1288 }
1289 } 1288 }
1290 cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count); 1289 tty_insert_flip_string(tty, data, cnt);
1291 memcpy(tty->flip.char_buf_ptr, data, cnt); 1290 tty_flip_buffer_push(tty);
1292 memset(tty->flip.flag_buf_ptr, 0, cnt);
1293 tty->flip.char_buf_ptr += cnt;
1294 tty->flip.flag_buf_ptr += cnt;
1295 tty->flip.count += cnt;
1296 data += cnt; 1291 data += cnt;
1297 length -= cnt; 1292 length -= cnt;
1298 } while (length > 0); 1293 } while (length > 0);
1299 1294
1300 tty_flip_buffer_push(tty);
1301} 1295}
1302 1296
1303 1297
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 49b1fbe61f25..bce3d55affd8 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -488,7 +488,6 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
488 unsigned char *data = urb->transfer_buffer; 488 unsigned char *data = urb->transfer_buffer;
489 struct tty_struct *tty; 489 struct tty_struct *tty;
490 unsigned long flags; 490 unsigned long flags;
491 int i;
492 int throttled; 491 int throttled;
493 int result; 492 int result;
494 493
@@ -503,14 +502,8 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
503 502
504 tty = port->tty; 503 tty = port->tty;
505 if (tty && urb->actual_length) { 504 if (tty && urb->actual_length) {
506 for (i = 0; i < urb->actual_length ; ++i) { 505 tty_buffer_request_room(tty, urb->actual_length);
507 /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ 506 tty_insert_flip_string(tty, data, urb->actual_length);
508 if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
509 tty_flip_buffer_push(tty);
510 }
511 /* this doesn't actually push the data through unless tty->low_latency is set */
512 tty_insert_flip_char(tty, data[i], 0);
513 }
514 tty_flip_buffer_push(tty); 507 tty_flip_buffer_push(tty);
515 } 508 }
516 spin_lock_irqsave(&priv->lock, flags); 509 spin_lock_irqsave(&priv->lock, flags);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index a7c3c4734d83..557411c6e7c7 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -1434,7 +1434,9 @@ static void rx_data_softint(void *private)
1434 urb = wrap->urb; 1434 urb = wrap->urb;
1435 1435
1436 if (tty && urb->actual_length) { 1436 if (tty && urb->actual_length) {
1437 if (urb->actual_length > TTY_FLIPBUF_SIZE - tty->flip.count) { 1437 int len = tty_buffer_request_room(tty, urb->actual_length);
1438 /* This stuff can go away now I suspect */
1439 if (unlikely(len < urb->actual_length)) {
1438 spin_lock_irqsave(&info->lock, flags); 1440 spin_lock_irqsave(&info->lock, flags);
1439 list_add(tmp, &info->rx_urb_q); 1441 list_add(tmp, &info->rx_urb_q);
1440 spin_unlock_irqrestore(&info->lock, flags); 1442 spin_unlock_irqrestore(&info->lock, flags);
@@ -1442,11 +1444,8 @@ static void rx_data_softint(void *private)
1442 schedule_work(&info->rx_work); 1444 schedule_work(&info->rx_work);
1443 return; 1445 return;
1444 } 1446 }
1445 1447 tty_insert_flip_string(tty, urb->transfer_buffer, len);
1446 memcpy(tty->flip.char_buf_ptr, urb->transfer_buffer, urb->actual_length); 1448 sent += len;
1447 tty->flip.char_buf_ptr += urb->actual_length;
1448 tty->flip.count += urb->actual_length;
1449 sent += urb->actual_length;
1450 } 1449 }
1451 1450
1452 urb->dev = port->serial->dev; 1451 urb->dev = port->serial->dev;