aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
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/net
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/net')
-rw-r--r--drivers/net/hamradio/6pack.c7
-rw-r--r--drivers/net/hamradio/mkiss.c7
-rw-r--r--drivers/net/irda/irtty-sir.c18
-rw-r--r--drivers/net/ppp_async.c9
-rw-r--r--drivers/net/ppp_synctty.c9
-rw-r--r--drivers/net/slip.c11
-rw-r--r--drivers/net/wan/pc300_tty.c2
-rw-r--r--drivers/net/wan/x25_asy.c7
-rw-r--r--drivers/net/wireless/strip.c10
9 files changed, 11 insertions, 69 deletions
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 90999867a32c..102c1f0b90da 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -456,11 +456,6 @@ out:
456 456
457/* ----------------------------------------------------------------------- */ 457/* ----------------------------------------------------------------------- */
458 458
459static int sixpack_receive_room(struct tty_struct *tty)
460{
461 return 65536; /* We can handle an infinite amount of data. :-) */
462}
463
464/* 459/*
465 * Handle the 'receiver data ready' interrupt. 460 * Handle the 'receiver data ready' interrupt.
466 * This function is called by the 'tty_io' module in the kernel when 461 * This function is called by the 'tty_io' module in the kernel when
@@ -671,6 +666,7 @@ static int sixpack_open(struct tty_struct *tty)
671 666
672 /* Done. We have linked the TTY line to a channel. */ 667 /* Done. We have linked the TTY line to a channel. */
673 tty->disc_data = sp; 668 tty->disc_data = sp;
669 tty->receive_room = 65536;
674 670
675 /* Now we're ready to register. */ 671 /* Now we're ready to register. */
676 if (register_netdev(dev)) 672 if (register_netdev(dev))
@@ -802,7 +798,6 @@ static struct tty_ldisc sp_ldisc = {
802 .close = sixpack_close, 798 .close = sixpack_close,
803 .ioctl = sixpack_ioctl, 799 .ioctl = sixpack_ioctl,
804 .receive_buf = sixpack_receive_buf, 800 .receive_buf = sixpack_receive_buf,
805 .receive_room = sixpack_receive_room,
806 .write_wakeup = sixpack_write_wakeup, 801 .write_wakeup = sixpack_write_wakeup,
807}; 802};
808 803
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index f4424cf886c5..dc5e9d59deed 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -753,6 +753,7 @@ static int mkiss_open(struct tty_struct *tty)
753 753
754 ax->tty = tty; 754 ax->tty = tty;
755 tty->disc_data = ax; 755 tty->disc_data = ax;
756 tty->receive_room = 65535;
756 757
757 if (tty->driver->flush_buffer) 758 if (tty->driver->flush_buffer)
758 tty->driver->flush_buffer(tty); 759 tty->driver->flush_buffer(tty);
@@ -940,11 +941,6 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
940 tty->driver->unthrottle(tty); 941 tty->driver->unthrottle(tty);
941} 942}
942 943
943static int mkiss_receive_room(struct tty_struct *tty)
944{
945 return 65536; /* We can handle an infinite amount of data. :-) */
946}
947
948/* 944/*
949 * Called by the driver when there's room for more data. If we have 945 * Called by the driver when there's room for more data. If we have
950 * more packets to send, we send them here. 946 * more packets to send, we send them here.
@@ -983,7 +979,6 @@ static struct tty_ldisc ax_ldisc = {
983 .close = mkiss_close, 979 .close = mkiss_close,
984 .ioctl = mkiss_ioctl, 980 .ioctl = mkiss_ioctl,
985 .receive_buf = mkiss_receive_buf, 981 .receive_buf = mkiss_receive_buf,
986 .receive_room = mkiss_receive_room,
987 .write_wakeup = mkiss_write_wakeup 982 .write_wakeup = mkiss_write_wakeup
988}; 983};
989 984
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index b8d112348ba4..101750bf210f 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -289,22 +289,6 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
289} 289}
290 290
291/* 291/*
292 * Function irtty_receive_room (tty)
293 *
294 * Used by the TTY to find out how much data we can receive at a time
295 *
296*/
297static int irtty_receive_room(struct tty_struct *tty)
298{
299 struct sirtty_cb *priv = tty->disc_data;
300
301 IRDA_ASSERT(priv != NULL, return 0;);
302 IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return 0;);
303
304 return 65536; /* We can handle an infinite amount of data. :-) */
305}
306
307/*
308 * Function irtty_write_wakeup (tty) 292 * Function irtty_write_wakeup (tty)
309 * 293 *
310 * Called by the driver when there's room for more data. If we have 294 * Called by the driver when there's room for more data. If we have
@@ -534,6 +518,7 @@ static int irtty_open(struct tty_struct *tty)
534 518
535 dev->priv = priv; 519 dev->priv = priv;
536 tty->disc_data = priv; 520 tty->disc_data = priv;
521 tty->receive_room = 65536;
537 522
538 up(&irtty_sem); 523 up(&irtty_sem);
539 524
@@ -605,7 +590,6 @@ static struct tty_ldisc irda_ldisc = {
605 .ioctl = irtty_ioctl, 590 .ioctl = irtty_ioctl,
606 .poll = NULL, 591 .poll = NULL,
607 .receive_buf = irtty_receive_buf, 592 .receive_buf = irtty_receive_buf,
608 .receive_room = irtty_receive_room,
609 .write_wakeup = irtty_write_wakeup, 593 .write_wakeup = irtty_write_wakeup,
610 .owner = THIS_MODULE, 594 .owner = THIS_MODULE,
611}; 595};
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 400f652282d7..aa6540b39466 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -189,7 +189,7 @@ ppp_asynctty_open(struct tty_struct *tty)
189 goto out_free; 189 goto out_free;
190 190
191 tty->disc_data = ap; 191 tty->disc_data = ap;
192 192 tty->receive_room = 65536;
193 return 0; 193 return 0;
194 194
195 out_free: 195 out_free:
@@ -343,12 +343,6 @@ ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
343 return 0; 343 return 0;
344} 344}
345 345
346static int
347ppp_asynctty_room(struct tty_struct *tty)
348{
349 return 65535;
350}
351
352/* 346/*
353 * This can now be called from hard interrupt level as well 347 * This can now be called from hard interrupt level as well
354 * as soft interrupt level or mainline. 348 * as soft interrupt level or mainline.
@@ -398,7 +392,6 @@ static struct tty_ldisc ppp_ldisc = {
398 .write = ppp_asynctty_write, 392 .write = ppp_asynctty_write,
399 .ioctl = ppp_asynctty_ioctl, 393 .ioctl = ppp_asynctty_ioctl,
400 .poll = ppp_asynctty_poll, 394 .poll = ppp_asynctty_poll,
401 .receive_room = ppp_asynctty_room,
402 .receive_buf = ppp_asynctty_receive, 395 .receive_buf = ppp_asynctty_receive,
403 .write_wakeup = ppp_asynctty_wakeup, 396 .write_wakeup = ppp_asynctty_wakeup,
404}; 397};
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 4d51c0c8023d..33cb8254e79d 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -237,7 +237,7 @@ ppp_sync_open(struct tty_struct *tty)
237 goto out_free; 237 goto out_free;
238 238
239 tty->disc_data = ap; 239 tty->disc_data = ap;
240 240 tty->receive_room = 65536;
241 return 0; 241 return 0;
242 242
243 out_free: 243 out_free:
@@ -384,12 +384,6 @@ ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
384 return 0; 384 return 0;
385} 385}
386 386
387static int
388ppp_sync_room(struct tty_struct *tty)
389{
390 return 65535;
391}
392
393/* 387/*
394 * This can now be called from hard interrupt level as well 388 * This can now be called from hard interrupt level as well
395 * as soft interrupt level or mainline. 389 * as soft interrupt level or mainline.
@@ -439,7 +433,6 @@ static struct tty_ldisc ppp_sync_ldisc = {
439 .write = ppp_sync_write, 433 .write = ppp_sync_write,
440 .ioctl = ppp_synctty_ioctl, 434 .ioctl = ppp_synctty_ioctl,
441 .poll = ppp_sync_poll, 435 .poll = ppp_sync_poll,
442 .receive_room = ppp_sync_room,
443 .receive_buf = ppp_sync_receive, 436 .receive_buf = ppp_sync_receive,
444 .write_wakeup = ppp_sync_wakeup, 437 .write_wakeup = ppp_sync_wakeup,
445}; 438};
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 404ea4297e32..b2e18d28850d 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -651,11 +651,6 @@ static void sl_setup(struct net_device *dev)
651 ******************************************/ 651 ******************************************/
652 652
653 653
654static int slip_receive_room(struct tty_struct *tty)
655{
656 return 65536; /* We can handle an infinite amount of data. :-) */
657}
658
659/* 654/*
660 * Handle the 'receiver data ready' interrupt. 655 * Handle the 'receiver data ready' interrupt.
661 * This function is called by the 'tty_io' module in the kernel when 656 * This function is called by the 'tty_io' module in the kernel when
@@ -869,10 +864,6 @@ static int slip_open(struct tty_struct *tty)
869 sl->line = tty_devnum(tty); 864 sl->line = tty_devnum(tty);
870 sl->pid = current->pid; 865 sl->pid = current->pid;
871 866
872 /* FIXME: already done before we were called - seems this can go */
873 if (tty->driver->flush_buffer)
874 tty->driver->flush_buffer(tty);
875
876 if (!test_bit(SLF_INUSE, &sl->flags)) { 867 if (!test_bit(SLF_INUSE, &sl->flags)) {
877 /* Perform the low-level SLIP initialization. */ 868 /* Perform the low-level SLIP initialization. */
878 if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0) 869 if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
@@ -897,6 +888,7 @@ static int slip_open(struct tty_struct *tty)
897 888
898 /* Done. We have linked the TTY line to a channel. */ 889 /* Done. We have linked the TTY line to a channel. */
899 rtnl_unlock(); 890 rtnl_unlock();
891 tty->receive_room = 65536; /* We don't flow control */
900 return sl->dev->base_addr; 892 return sl->dev->base_addr;
901 893
902err_free_bufs: 894err_free_bufs:
@@ -1329,7 +1321,6 @@ static struct tty_ldisc sl_ldisc = {
1329 .close = slip_close, 1321 .close = slip_close,
1330 .ioctl = slip_ioctl, 1322 .ioctl = slip_ioctl,
1331 .receive_buf = slip_receive_buf, 1323 .receive_buf = slip_receive_buf,
1332 .receive_room = slip_receive_room,
1333 .write_wakeup = slip_write_wakeup, 1324 .write_wakeup = slip_write_wakeup,
1334}; 1325};
1335 1326
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 52f26b9c69d2..931cbdf6d791 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -689,7 +689,7 @@ static void cpc_tty_rx_work(void * data)
689 } 689 }
690 } 690 }
691 cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next; 691 cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
692 kfree(buf); 692 kfree((void *)buf);
693 buf = cpc_tty->buf_rx.first; 693 buf = cpc_tty->buf_rx.first;
694 flg_rx = 1; 694 flg_rx = 1;
695 } 695 }
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index bdf672c48182..9c3ccc669143 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -515,11 +515,6 @@ static int x25_asy_close(struct net_device *dev)
515 return 0; 515 return 0;
516} 516}
517 517
518static int x25_asy_receive_room(struct tty_struct *tty)
519{
520 return 65536; /* We can handle an infinite amount of data. :-) */
521}
522
523/* 518/*
524 * Handle the 'receiver data ready' interrupt. 519 * Handle the 'receiver data ready' interrupt.
525 * This function is called by the 'tty_io' module in the kernel when 520 * This function is called by the 'tty_io' module in the kernel when
@@ -573,6 +568,7 @@ static int x25_asy_open_tty(struct tty_struct *tty)
573 568
574 sl->tty = tty; 569 sl->tty = tty;
575 tty->disc_data = sl; 570 tty->disc_data = sl;
571 tty->receive_room = 65536;
576 if (tty->driver->flush_buffer) { 572 if (tty->driver->flush_buffer) {
577 tty->driver->flush_buffer(tty); 573 tty->driver->flush_buffer(tty);
578 } 574 }
@@ -779,7 +775,6 @@ static struct tty_ldisc x25_ldisc = {
779 .close = x25_asy_close_tty, 775 .close = x25_asy_close_tty,
780 .ioctl = x25_asy_ioctl, 776 .ioctl = x25_asy_ioctl,
781 .receive_buf = x25_asy_receive_buf, 777 .receive_buf = x25_asy_receive_buf,
782 .receive_room = x25_asy_receive_room,
783 .write_wakeup = x25_asy_write_wakeup, 778 .write_wakeup = x25_asy_write_wakeup,
784}; 779};
785 780
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index d25264ba0c0e..18baacfc5a2c 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1675,11 +1675,6 @@ static int strip_rebuild_header(struct sk_buff *skb)
1675/************************************************************************/ 1675/************************************************************************/
1676/* Receiving routines */ 1676/* Receiving routines */
1677 1677
1678static int strip_receive_room(struct tty_struct *tty)
1679{
1680 return 0x10000; /* We can handle an infinite amount of data. :-) */
1681}
1682
1683/* 1678/*
1684 * This function parses the response to the ATS300? command, 1679 * This function parses the response to the ATS300? command,
1685 * extracting the radio version and serial number. 1680 * extracting the radio version and serial number.
@@ -2424,7 +2419,7 @@ static struct net_device_stats *strip_get_stats(struct net_device *dev)
2424/* 2419/*
2425 * Here's the order things happen: 2420 * Here's the order things happen:
2426 * When the user runs "slattach -p strip ..." 2421 * When the user runs "slattach -p strip ..."
2427 * 1. The TTY module calls strip_open 2422 * 1. The TTY module calls strip_open;;
2428 * 2. strip_open calls strip_alloc 2423 * 2. strip_open calls strip_alloc
2429 * 3. strip_alloc calls register_netdev 2424 * 3. strip_alloc calls register_netdev
2430 * 4. register_netdev calls strip_dev_init 2425 * 4. register_netdev calls strip_dev_init
@@ -2652,6 +2647,8 @@ static int strip_open(struct tty_struct *tty)
2652 2647
2653 strip_info->tty = tty; 2648 strip_info->tty = tty;
2654 tty->disc_data = strip_info; 2649 tty->disc_data = strip_info;
2650 tty->receive_room = 65536;
2651
2655 if (tty->driver->flush_buffer) 2652 if (tty->driver->flush_buffer)
2656 tty->driver->flush_buffer(tty); 2653 tty->driver->flush_buffer(tty);
2657 2654
@@ -2762,7 +2759,6 @@ static struct tty_ldisc strip_ldisc = {
2762 .close = strip_close, 2759 .close = strip_close,
2763 .ioctl = strip_ioctl, 2760 .ioctl = strip_ioctl,
2764 .receive_buf = strip_receive_buf, 2761 .receive_buf = strip_receive_buf,
2765 .receive_room = strip_receive_room,
2766 .write_wakeup = strip_write_some_more, 2762 .write_wakeup = strip_write_some_more,
2767}; 2763};
2768 2764