qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Aurelien Jarno <aurelien@aurel32.net>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [4335] 8250: throttle TX-completion IRQs
Date: Sun, 04 May 2008 21:42:01 +0000	[thread overview]
Message-ID: <E1Jsly5-0006BH-C9@cvs.savannah.gnu.org> (raw)

Revision: 4335
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4335
Author:   aurel32
Date:     2008-05-04 21:42:00 +0000 (Sun, 04 May 2008)

Log Message:
-----------
8250: throttle TX-completion IRQs

(Jan Kiszka)

Modified Paths:
--------------
    trunk/hw/serial.c

Modified: trunk/hw/serial.c
===================================================================
--- trunk/hw/serial.c	2008-05-04 20:11:44 UTC (rev 4334)
+++ trunk/hw/serial.c	2008-05-04 21:42:00 UTC (rev 4335)
@@ -25,6 +25,7 @@
 #include "qemu-char.h"
 #include "isa.h"
 #include "pc.h"
+#include "qemu-timer.h"
 
 //#define DEBUG_SERIAL
 
@@ -73,6 +74,13 @@
 #define UART_LSR_OE	0x02	/* Overrun error indicator */
 #define UART_LSR_DR	0x01	/* Receiver data ready */
 
+/*
+ * Delay TX IRQ after sending as much characters as the given interval would
+ * contain on real hardware. This avoids overloading the guest if it processes
+ * its output buffer in a loop inside the TX IRQ handler.
+ */
+#define THROTTLE_TX_INTERVAL	10 /* ms */
+
 struct SerialState {
     uint16_t divider;
     uint8_t rbr; /* receive register */
@@ -91,6 +99,8 @@
     int last_break_enable;
     target_phys_addr_t base;
     int it_shift;
+    QEMUTimer *tx_timer;
+    int tx_burst;
 };
 
 static void serial_receive_byte(SerialState *s, int ch);
@@ -111,6 +121,28 @@
     }
 }
 
+static void serial_tx_done(void *opaque)
+{
+    SerialState *s = opaque;
+
+    if (s->tx_burst < 0) {
+        uint16_t divider;
+
+        if (s->divider)
+          divider = s->divider;
+        else
+          divider = 1;
+
+        /* We assume 10 bits/char, OK for this purpose. */
+        s->tx_burst = THROTTLE_TX_INTERVAL * 1000 /
+            (1000000 * 10 / (115200 / divider));
+    }
+    s->thr_ipending = 1;
+    s->lsr |= UART_LSR_THRE;
+    s->lsr |= UART_LSR_TEMT;
+    serial_update_irq(s);
+}
+
 static void serial_update_parameters(SerialState *s)
 {
     int speed, parity, data_bits, stop_bits;
@@ -166,15 +198,18 @@
             if (!(s->mcr & UART_MCR_LOOP)) {
                 /* when not in loopback mode, send the char */
                 qemu_chr_write(s->chr, &ch, 1);
-            }
-            s->thr_ipending = 1;
-            s->lsr |= UART_LSR_THRE;
-            s->lsr |= UART_LSR_TEMT;
-            serial_update_irq(s);
-            if (s->mcr & UART_MCR_LOOP) {
+            } else {
                 /* in loopback mode, say that we just received a char */
                 serial_receive_byte(s, ch);
             }
+            if (s->tx_burst > 0) {
+                s->tx_burst--;
+                serial_tx_done(s);
+            } else if (s->tx_burst == 0) {
+                s->tx_burst--;
+                qemu_mod_timer(s->tx_timer, qemu_get_clock(vm_clock) +
+                               ticks_per_sec * THROTTLE_TX_INTERVAL / 1000);
+            }
         }
         break;
     case 1:
@@ -387,6 +422,10 @@
         return NULL;
     s->irq = irq;
 
+    s->tx_timer = qemu_new_timer(vm_clock, serial_tx_done, s);
+    if (!s->tx_timer)
+        return NULL;
+
     qemu_register_reset(serial_reset, s);
     serial_reset(s);
 
@@ -486,6 +525,10 @@
     s->base = base;
     s->it_shift = it_shift;
 
+    s->tx_timer = qemu_new_timer(vm_clock, serial_tx_done, s);
+    if (!s->tx_timer)
+        return NULL;
+
     qemu_register_reset(serial_reset, s);
     serial_reset(s);
 

                 reply	other threads:[~2008-05-04 21:42 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E1Jsly5-0006BH-C9@cvs.savannah.gnu.org \
    --to=aurelien@aurel32.net \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).