diff --git a/devicemodel/hw/pci/lpc.c b/devicemodel/hw/pci/lpc.c index d5f0060df..cc14d9759 100644 --- a/devicemodel/hw/pci/lpc.c +++ b/devicemodel/hw/pci/lpc.c @@ -175,7 +175,6 @@ lpc_deinit(struct vmctx *ctx) unregister_inout(&iop); uart_release_backend(lpc_uart->uart, lpc_uart->opts); - uart_deinit(lpc_uart->uart); uart_legacy_dealloc(unit); lpc_uart->uart = NULL; lpc_uart->enabled = 0; @@ -205,23 +204,9 @@ lpc_init(struct vmctx *ctx) } pci_irq_reserve(lpc_uart->irq); - lpc_uart->uart = uart_init(lpc_uart_intr_assert, - lpc_uart_intr_deassert, lpc_uart); - - if (lpc_uart->uart < 0) { - uart_legacy_dealloc(unit); - goto init_failed; - } - - error = uart_set_backend(lpc_uart->uart, lpc_uart->opts); - /* - * Continue to initialize LPC UART device if opts is invalid, - * and the data will be dropped by uart_write in UART DM. - */ - if (error && error != -EINVAL) { - fprintf(stderr, "Unable to initialize backend '%s' " - "for LPC device %s\n", lpc_uart->opts, name); - uart_deinit(lpc_uart->uart); + lpc_uart->uart = uart_set_backend(lpc_uart_intr_assert, lpc_uart_intr_deassert, + lpc_uart, lpc_uart->opts); + if (lpc_uart->uart == NULL) { uart_legacy_dealloc(unit); goto init_failed; } diff --git a/devicemodel/hw/pci/uart.c b/devicemodel/hw/pci/uart.c index a8633198f..cc76f4940 100644 --- a/devicemodel/hw/pci/uart.c +++ b/devicemodel/hw/pci/uart.c @@ -82,9 +82,6 @@ pci_uart_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, static int pci_uart_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts) { - struct uart_vdev *uart; - int ret; - pci_emul_alloc_bar(dev, 0, PCIBAR_IO, UART_IO_BAR_SIZE); pci_lintr_request(dev); @@ -93,11 +90,8 @@ pci_uart_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts) pci_set_cfgdata16(dev, PCIR_VENDOR, COM_VENDOR); pci_set_cfgdata8(dev, PCIR_CLASS, PCIC_SIMPLECOMM); - uart = uart_init(pci_uart_intr_assert, pci_uart_intr_deassert, dev); - dev->arg = uart; - - ret = uart_set_backend(uart, opts); - if (ret && ret != -EINVAL) { + dev->arg = uart_set_backend(pci_uart_intr_assert, pci_uart_intr_deassert, dev, opts); + if (dev->arg == NULL) { fprintf(stderr, "Unable to initialize backend '%s' for " "pci uart at %d:%d\n", opts, dev->slot, dev->func); return -1; @@ -115,7 +109,6 @@ pci_uart_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts) return; uart_release_backend(uart, opts); - uart_deinit(uart); } struct pci_vdev_ops pci_ops_com = { diff --git a/devicemodel/hw/uart_core.c b/devicemodel/hw/uart_core.c index 4ae02b151..0f63bb359 100644 --- a/devicemodel/hw/uart_core.c +++ b/devicemodel/hw/uart_core.c @@ -629,7 +629,7 @@ uart_legacy_dealloc(int which) uart_lres[which].inuse = false; } -struct uart_vdev * +static struct uart_vdev * uart_init(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert, void *arg) { @@ -650,7 +650,7 @@ uart_init(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert, return uart; } -void +static void uart_deinit(struct uart_vdev *uart) { if (uart) { @@ -681,15 +681,19 @@ uart_tty_backend(struct uart_vdev *uart, const char *opts) return retval; } -int -uart_set_backend(struct uart_vdev *uart, const char *opts) +struct uart_vdev * +uart_set_backend(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert, + void *arg, const char *opts) { - int retval; + int retval = -1; + struct uart_vdev *uart; - retval = -1; + uart = uart_init(intr_assert, intr_deassert, arg); + if (!uart) + return NULL; if (opts == NULL) - return -EINVAL; + return uart; if (strcmp("stdio", opts) == 0) { if (!stdio_in_use) { @@ -703,17 +707,29 @@ uart_set_backend(struct uart_vdev *uart, const char *opts) retval = 0; } - if (retval) - return -EINVAL; + if (retval) { + uart_deinit(uart); + return NULL; + } /* Make the backend file descriptor non-blocking */ - if (retval == 0) - retval = fcntl(uart->tty.fd_in, F_SETFL, O_NONBLOCK); + retval = fcntl(uart->tty.fd_in, F_SETFL, O_NONBLOCK); + if (retval != 0) + goto fail_tty_backend; - if (retval == 0) - uart_opentty(uart); + uart_opentty(uart); - return retval; + return uart; + +fail_tty_backend: + if (uart->tty.fd_in) { + close(uart->tty.fd_in); + uart->tty.fd_in = -1; + uart->tty.fd_out = -1; + uart->tty.opened = false; + } + uart_deinit(uart); + return NULL; } void @@ -741,4 +757,6 @@ uart_release_backend(struct uart_vdev *uart, const char *opts) uart->tty.fd_in = -1; uart->tty.fd_out = -1; uart->tty.opened = false; + + uart_deinit(uart); } diff --git a/devicemodel/include/uart_core.h b/devicemodel/include/uart_core.h index 052b87c2c..ef262118b 100644 --- a/devicemodel/include/uart_core.h +++ b/devicemodel/include/uart_core.h @@ -35,14 +35,12 @@ struct uart_vdev; typedef void (*uart_intr_func_t)(void *arg); -struct uart_vdev *uart_init(uart_intr_func_t intr_assert, - uart_intr_func_t intr_deassert, void *arg); -void uart_deinit(struct uart_vdev *uart); - int uart_legacy_alloc(int unit, int *ioaddr, int *irq); void uart_legacy_dealloc(int which); uint8_t uart_read(struct uart_vdev *uart, int offset); void uart_write(struct uart_vdev *uart, int offset, uint8_t value); -int uart_set_backend(struct uart_vdev *uart, const char *opt); +struct uart_vdev* + uart_set_backend(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert, + void *arg, const char *opts); void uart_release_backend(struct uart_vdev *uart, const char *opts); #endif