]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm: Improve 8250 serial console interrupt handling
authorPekka Enberg <penberg@kernel.org>
Mon, 10 Jan 2011 18:28:37 +0000 (20:28 +0200)
committerPekka Enberg <penberg@kernel.org>
Tue, 11 Jan 2011 14:49:49 +0000 (16:49 +0200)
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/8250-serial.c

index 2b8e65dcd060d235f6a7f9a7369cc2e1bff7745b..6046c6b14dcc495f05bd8b37e32ccc607e502d6b 100644 (file)
@@ -29,7 +29,6 @@ static struct serial8250_device device = {
        .iobase                 = 0x3f8,        /* ttyS0 */
        .irq                    = 4,
 
-       .iir                    = UART_IIR_NO_INT,
        .lsr                    = UART_LSR_TEMT | UART_LSR_THRE,
 };
 
@@ -55,6 +54,21 @@ static bool is_readable(int fd)
 
 void serial8250__interrupt(struct kvm *self)
 {
+       uint8_t new_iir;
+
+       device.iir      = UART_IIR_NO_INT;
+
+       /* No interrupts enabled. Exit... */
+       if (!(device.ier & (UART_IER_THRI|UART_IER_RDI)))
+               return;
+
+       new_iir         = 0;
+
+       /* We're always good for guest sending data. */
+       if (device.ier & UART_IER_THRI)
+               new_iir                 |= UART_IIR_THRI;
+
+       /* Is there input in stdin to send to the guest? */
        if (!(device.lsr & UART_LSR_DR) && is_readable(fileno(stdin))) {
                int c;
 
@@ -62,11 +76,14 @@ void serial8250__interrupt(struct kvm *self)
                if (c >= 0) {
                        device.thr              = c;
                        device.lsr              |= UART_LSR_DR;
+                       new_iir                 |= UART_IIR_RDI;
                }
        }
 
-       if (device.ier & UART_IER_THRI || device.lsr & UART_LSR_DR) {
-               device.iir              &= ~UART_IIR_NO_INT;
+       /* Only send an IRQ if there's work to do. */
+       if (new_iir) {
+               device.iir              = new_iir;
+               kvm__irq_line(self, device.irq, 0);
                kvm__irq_line(self, device.irq, 1);
        }
 }
@@ -104,9 +121,6 @@ static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size
                        }
                        fflush(stdout);
 
-                       device.iir              |= UART_IIR_NO_INT;
-                       kvm__irq_line(self, device.irq, 0);
-
                        break;
                }
                case UART_IER:
@@ -144,9 +158,6 @@ static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size,
                if (device.lsr & UART_LSR_DR) {
                        device.lsr              &= ~UART_LSR_DR;
                        ioport__write8(data, device.thr);
-
-                       device.iir              |= UART_IIR_NO_INT;
-                       kvm__irq_line(self, device.irq, 0);
                }
                break;
        case UART_IER: