]> Git Repo - qemu.git/commitdiff
serial: add flow control to transmit
authorAnthony Liguori <[email protected]>
Tue, 5 Mar 2013 17:51:33 +0000 (23:21 +0530)
committerAnthony Liguori <[email protected]>
Fri, 8 Mar 2013 19:57:17 +0000 (13:57 -0600)
Signed-off-by: Anthony Liguori <[email protected]>
Signed-off-by: Amit Shah <[email protected]>
Message-id: 2976f10d4e66ed4a34011f6f0d6937026d22be5f.1362505276[email protected]
Signed-off-by: Anthony Liguori <[email protected]>
hw/serial.c
hw/serial.h

index f0ce9b0c15001d67e7783a9299d09ba34e6c6892..eb38f2231dec42ef51719d94ab381b80a2788e9c 100644 (file)
@@ -256,16 +256,17 @@ static void serial_update_msl(SerialState *s)
         qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 100);
 }
 
-static void serial_xmit(void *opaque)
+static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
 {
     SerialState *s = opaque;
-    uint64_t new_xmit_ts = qemu_get_clock_ns(vm_clock);
 
     if (s->tsr_retry <= 0) {
         if (s->fcr & UART_FCR_FE) {
             s->tsr = fifo_get(s,XMIT_FIFO);
             if (!s->xmit_fifo.count)
                 s->lsr |= UART_LSR_THRE;
+        } else if ((s->lsr & UART_LSR_THRE)) {
+            return FALSE;
         } else {
             s->tsr = s->thr;
             s->lsr |= UART_LSR_THRE;
@@ -277,30 +278,25 @@ static void serial_xmit(void *opaque)
         /* in loopback mode, say that we just received a char */
         serial_receive1(s, &s->tsr, 1);
     } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
-        if ((s->tsr_retry > 0) && (s->tsr_retry <= MAX_XMIT_RETRY)) {
+        if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
+            qemu_chr_fe_add_watch(s->chr, G_IO_OUT, serial_xmit, s) > 0) {
             s->tsr_retry++;
-            qemu_mod_timer(s->transmit_timer,  new_xmit_ts + s->char_transmit_time);
-            return;
-        } else if (s->poll_msl < 0) {
-            /* If we exceed MAX_XMIT_RETRY and the backend is not a real serial port, then
-            drop any further failed writes instantly, until we get one that goes through.
-            This is to prevent guests that log to unconnected pipes or pty's from stalling. */
-            s->tsr_retry = -1;
+            return FALSE;
         }
-    }
-    else {
+        s->tsr_retry = 0;
+    else {
         s->tsr_retry = 0;
     }
 
     s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
-    if (!(s->lsr & UART_LSR_THRE))
-        qemu_mod_timer(s->transmit_timer, s->last_xmit_ts + s->char_transmit_time);
 
     if (s->lsr & UART_LSR_THRE) {
         s->lsr |= UART_LSR_TEMT;
         s->thr_ipending = 1;
         serial_update_irq(s);
     }
+
+    return FALSE;
 }
 
 
@@ -330,7 +326,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
                 s->lsr &= ~UART_LSR_THRE;
                 serial_update_irq(s);
             }
-            serial_xmit(s);
+            serial_xmit(NULL, G_IO_OUT, s);
         }
         break;
     case 1:
@@ -684,8 +680,6 @@ void serial_init_core(SerialState *s)
     s->modem_status_poll = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_update_msl, s);
 
     s->fifo_timeout_timer = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) fifo_timeout_int, s);
-    s->transmit_timer = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_xmit, s);
-
     qemu_register_reset(serial_reset, s);
 
     qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
index 98ee4241be05eee51918a69cc2c163c28f89ee0c..e57375d03c89bca76aa24811d4a85dbc322b2dd3 100644 (file)
@@ -72,8 +72,6 @@ struct SerialState {
 
     struct QEMUTimer *fifo_timeout_timer;
     int timeout_ipending;           /* timeout interrupt pending state */
-    struct QEMUTimer *transmit_timer;
-
 
     uint64_t char_transmit_time;    /* time to transmit a char in ticks */
     int poll_msl;
This page took 0.033699 seconds and 4 git commands to generate.