[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 4/9] char: keep track of qemu_chr_add_handlers()
From: |
Marc-André Lureau |
Subject: |
[Qemu-devel] [PATCH 4/9] char: keep track of qemu_chr_add_handlers() |
Date: |
Thu, 13 Oct 2016 15:14:44 +0400 |
Frontends should use qemu_chr_add_handlers()/qemu_chr_remove_handlers()
with the appropriate tag. This prevents from growing the mux char
frontends. A following patch will add error handling (check tag return
value and add an Error argument).
Signed-off-by: Marc-André Lureau <address@hidden>
---
backends/rng-egd.c | 13 ++++++++++---
gdbstub.c | 12 +++++++++---
hw/arm/pxa2xx.c | 14 +++++++++++++-
hw/arm/strongarm.c | 19 ++++++++++++++++++-
hw/char/bcm2835_aux.c | 13 ++++++++++++-
hw/char/cadence_uart.c | 16 +++++++++++++++-
hw/char/debugcon.c | 30 ++++++++++++++++--------------
hw/char/digic-uart.c | 13 ++++++++++++-
hw/char/escc.c | 17 ++++++++++++++++-
hw/char/etraxfs_ser.c | 14 +++++++++++++-
hw/char/exynos4210_uart.c | 12 +++++++++++-
hw/char/grlib_apbuart.c | 14 +++++++++++++-
hw/char/imx_serial.c | 15 +++++++++++++--
hw/char/ipoctal232.c | 18 +++++++++++++++++-
hw/char/lm32_juart.c | 14 +++++++++++++-
hw/char/lm32_uart.c | 14 +++++++++++++-
hw/char/mcf_uart.c | 4 +++-
hw/char/milkymist-uart.c | 14 +++++++++++++-
hw/char/pl011.c | 14 +++++++++++++-
hw/char/sclpconsole-lm.c | 11 ++++++++++-
hw/char/sclpconsole.c | 9 ++++++++-
hw/char/serial.c | 10 +++++++---
hw/char/sh_serial.c | 8 ++++++--
hw/char/spapr_vty.c | 14 +++++++++++++-
hw/char/stm32f2xx_usart.c | 13 ++++++++++++-
hw/char/virtio-console.c | 10 ++++++++--
hw/char/xen_console.c | 8 +++++---
hw/char/xilinx_uartlite.c | 17 +++++++++++++++--
hw/ipmi/ipmi_bmc_extern.c | 14 +++++++++++++-
hw/misc/ivshmem.c | 12 ++++++++++--
hw/usb/ccid-card-passthru.c | 9 ++++++++-
hw/usb/dev-serial.c | 16 ++++++++++++++--
hw/usb/redirect.c | 13 ++++++++++++-
monitor.c | 13 ++++++++-----
net/colo-compare.c | 22 ++++++++++++++--------
net/filter-mirror.c | 14 ++++++++++----
net/slirp.c | 6 ++++--
net/vhost-user.c | 8 +++++---
qemu-char.c | 6 ++++--
qtest.c | 4 +++-
tests/vhost-user-test.c | 7 +++++--
include/hw/char/bcm2835_aux.h | 1 +
include/hw/char/cadence_uart.h | 1 +
include/hw/char/digic-uart.h | 1 +
include/hw/char/imx_serial.h | 1 +
include/hw/char/serial.h | 1 +
include/hw/char/stm32f2xx_usart.h | 1 +
47 files changed, 443 insertions(+), 87 deletions(-)
diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index ba17c07..5d8485f 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -25,6 +25,7 @@ typedef struct RngEgd
RngBackend parent;
CharDriverState *chr;
+ int chr_tag;
char *chr_name;
} RngEgd;
@@ -107,8 +108,11 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
}
/* FIXME we should resubmit pending requests when the CDS reconnects. */
- qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
- NULL, s);
+ if (s->chr_tag == -1) {
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read,
+ rng_egd_chr_read, NULL, s);
+ }
}
static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
@@ -137,6 +141,9 @@ static char *rng_egd_get_chardev(Object *obj, Error **errp)
static void rng_egd_init(Object *obj)
{
+ RngEgd *s = RNG_EGD(obj);
+
+ s->chr_tag = -1;
object_property_add_str(obj, "chardev",
rng_egd_get_chardev, rng_egd_set_chardev,
NULL);
@@ -147,7 +154,7 @@ static void rng_egd_finalize(Object *obj)
RngEgd *s = RNG_EGD(obj);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
qemu_chr_fe_release(s->chr);
}
diff --git a/gdbstub.c b/gdbstub.c
index ecea8c4..054a1d3 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -304,6 +304,7 @@ typedef struct GDBState {
int running_state;
#else
CharDriverState *chr;
+ int chr_tag;
CharDriverState *mon_chr;
#endif
char syscall_buf[256];
@@ -1724,6 +1725,7 @@ int gdbserver_start(const char *device)
GDBState *s;
char gdbstub_device_name[128];
CharDriverState *chr = NULL;
+ int chr_tag = -1;
CharDriverState *mon_chr;
ChardevCommon common = { 0 };
@@ -1750,8 +1752,9 @@ int gdbserver_start(const char *device)
return -1;
qemu_chr_fe_claim_no_fail(chr);
- qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
- gdb_chr_event, NULL);
+ chr_tag =
+ qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
+ gdb_chr_event, NULL);
}
s = gdbserver_state;
@@ -1766,14 +1769,17 @@ int gdbserver_start(const char *device)
mon_chr->chr_write = gdb_monitor_write;
monitor_init(mon_chr, 0);
} else {
- if (s->chr)
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
qemu_chr_delete(s->chr);
+ }
mon_chr = s->mon_chr;
memset(s, 0, sizeof(GDBState));
}
s->c_cpu = first_cpu;
s->g_cpu = first_cpu;
s->chr = chr;
+ s->chr_tag = chr_tag;
s->state = chr ? RS_IDLE : RS_INACTIVE;
s->mon_chr = mon_chr;
s->current_syscall_cb = NULL;
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 0241e07..e17b904 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1765,6 +1765,7 @@ struct PXA2xxFIrState {
qemu_irq tx_dma;
uint32_t enable;
CharDriverState *chr;
+ int chr_tag;
uint8_t control[3];
uint8_t status[2];
@@ -1975,11 +1976,21 @@ static void pxa2xx_fir_realize(DeviceState *dev, Error
**errp)
if (s->chr) {
qemu_chr_fe_claim_no_fail(s->chr);
- qemu_chr_add_handlers(s->chr, pxa2xx_fir_is_empty,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, pxa2xx_fir_is_empty,
pxa2xx_fir_rx, pxa2xx_fir_event, s);
}
}
+static void pxa2xx_fir_unrealize(DeviceState *dev, Error **errp)
+{
+ PXA2xxFIrState *s = PXA2XX_FIR(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static bool pxa2xx_fir_vmstate_validate(void *opaque, int version_id)
{
PXA2xxFIrState *s = opaque;
@@ -2013,6 +2024,7 @@ static void pxa2xx_fir_class_init(ObjectClass *klass,
void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = pxa2xx_fir_realize;
+ dc->unrealize = pxa2xx_fir_unrealize;
dc->vmsd = &pxa2xx_fir_vmsd;
dc->props = pxa2xx_fir_properties;
dc->reset = pxa2xx_fir_reset;
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index 021cbf9..48b4a7c 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -913,6 +913,7 @@ typedef struct StrongARMUARTState {
MemoryRegion iomem;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint8_t utcr0;
@@ -1240,7 +1241,8 @@ static void strongarm_uart_init(Object *obj)
s->tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_tx, s);
if (s->chr) {
- qemu_chr_add_handlers(s->chr,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr,
strongarm_uart_can_receive,
strongarm_uart_receive,
strongarm_uart_event,
@@ -1248,6 +1250,20 @@ static void strongarm_uart_init(Object *obj)
}
}
+static void strongarm_uart_finalize(Object *obj)
+{
+ StrongARMUARTState *s = STRONGARM_UART(obj);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+
+ timer_del(s->tx_timer);
+ timer_free(s->tx_timer);
+ timer_del(s->rx_timeout_timer);
+ timer_free(s->rx_timeout_timer);
+}
+
static void strongarm_uart_reset(DeviceState *dev)
{
StrongARMUARTState *s = STRONGARM_UART(dev);
@@ -1327,6 +1343,7 @@ static const TypeInfo strongarm_uart_info = {
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMUARTState),
.instance_init = strongarm_uart_init,
+ .instance_finalize = strongarm_uart_finalize,
.class_init = strongarm_uart_class_init,
};
diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c
index f7a845d..5694c32 100644
--- a/hw/char/bcm2835_aux.c
+++ b/hw/char/bcm2835_aux.c
@@ -283,11 +283,21 @@ static void bcm2835_aux_realize(DeviceState *dev, Error
**errp)
BCM2835AuxState *s = BCM2835_AUX(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, bcm2835_aux_can_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, bcm2835_aux_can_receive,
bcm2835_aux_receive, NULL, s);
}
}
+static void bcm2835_aux_unrealize(DeviceState *dev, Error **errp)
+{
+ BCM2835AuxState *s = BCM2835_AUX(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static Property bcm2835_aux_props[] = {
DEFINE_PROP_CHR("chardev", BCM2835AuxState, chr),
DEFINE_PROP_END_OF_LIST(),
@@ -298,6 +308,7 @@ static void bcm2835_aux_class_init(ObjectClass *oc, void
*data)
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = bcm2835_aux_realize;
+ dc->unrealize = bcm2835_aux_unrealize;
dc->vmsd = &vmstate_bcm2835_aux;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->props = bcm2835_aux_props;
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index e3bc52f..7ca8f0a 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -475,11 +475,24 @@ static void cadence_uart_realize(DeviceState *dev, Error
**errp)
fifo_trigger_update, s);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
uart_event, s);
}
}
+static void cadence_uart_unrealize(DeviceState *dev, Error **errp)
+{
+ CadenceUARTState *s = CADENCE_UART(dev);
+
+ timer_del(s->fifo_trigger_handle);
+ timer_free(s->fifo_trigger_handle);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static void cadence_uart_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@@ -530,6 +543,7 @@ static void cadence_uart_class_init(ObjectClass *klass,
void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = cadence_uart_realize;
+ dc->unrealize = cadence_uart_unrealize;
dc->vmsd = &vmstate_cadence_uart;
dc->reset = cadence_uart_reset;
dc->props = cadence_uart_properties;
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index 4402033..45876a7 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -40,6 +40,7 @@
typedef struct DebugconState {
MemoryRegion io;
CharDriverState *chr;
+ int chr_tag;
uint32_t readback;
} DebugconState;
@@ -85,34 +86,34 @@ static const MemoryRegionOps debugcon_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-static void debugcon_realize_core(DebugconState *s, Error **errp)
-{
- if (!s->chr) {
- error_setg(errp, "Can't create debugcon device, empty char device");
- return;
- }
-
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
-}
-
static void debugcon_isa_realizefn(DeviceState *dev, Error **errp)
{
ISADevice *d = ISA_DEVICE(dev);
ISADebugconState *isa = ISA_DEBUGCON_DEVICE(dev);
DebugconState *s = &isa->state;
- Error *err = NULL;
- debugcon_realize_core(s, &err);
- if (err != NULL) {
- error_propagate(errp, err);
+ if (!s->chr) {
+ error_setg(errp, "Can't create debugcon device, empty char device");
return;
}
+
+ /* necessary to start the be */
+ s->chr_tag = qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
+
memory_region_init_io(&s->io, OBJECT(dev), &debugcon_ops, s,
TYPE_ISA_DEBUGCON_DEVICE, 1);
memory_region_add_subregion(isa_address_space_io(d),
isa->iobase, &s->io);
}
+static void debugcon_isa_unrealizefn(DeviceState *dev, Error **errp)
+{
+ ISADebugconState *isa = ISA_DEBUGCON_DEVICE(dev);
+ DebugconState *s = &isa->state;
+
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+}
+
static Property debugcon_isa_properties[] = {
DEFINE_PROP_UINT32("iobase", ISADebugconState, iobase, 0xe9),
DEFINE_PROP_CHR("chardev", ISADebugconState, state.chr),
@@ -125,6 +126,7 @@ static void debugcon_isa_class_initfn(ObjectClass *klass,
void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = debugcon_isa_realizefn;
+ dc->unrealize = debugcon_isa_unrealizefn;
dc->props = debugcon_isa_properties;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c
index e96a9b2..83217a4 100644
--- a/hw/char/digic-uart.c
+++ b/hw/char/digic-uart.c
@@ -148,7 +148,17 @@ static void digic_uart_realize(DeviceState *dev, Error
**errp)
DigicUartState *s = DIGIC_UART(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ }
+}
+
+static void digic_uart_unrealize(DeviceState *dev, Error **errp)
+{
+ DigicUartState *s = DIGIC_UART(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
}
}
@@ -182,6 +192,7 @@ static void digic_uart_class_init(ObjectClass *klass, void
*data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = digic_uart_realize;
+ dc->unrealize = digic_uart_unrealize;
dc->reset = digic_uart_reset;
dc->vmsd = &vmstate_digic_uart;
dc->props = digic_uart_properties;
diff --git a/hw/char/escc.c b/hw/char/escc.c
index aa17397..0cbaf27 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -89,6 +89,7 @@ typedef struct ChannelState {
uint8_t wregs[SERIAL_REGS], rregs[SERIAL_REGS];
SERIOQueue queue;
CharDriverState *chr;
+ int chr_tag;
int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
int disabled;
int clock;
@@ -1015,7 +1016,8 @@ static void escc_realize(DeviceState *dev, Error **errp)
for (i = 0; i < 2; i++) {
if (s->chn[i].chr) {
s->chn[i].clock = s->frequency / 2;
- qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
+ s->chn[i].chr_tag =
+ qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
serial_receive1, serial_event, &s->chn[i]);
}
}
@@ -1030,6 +1032,18 @@ static void escc_realize(DeviceState *dev, Error **errp)
}
}
+static void escc_unrealize(DeviceState *dev, Error **errp)
+{
+ ESCCState *s = ESCC(dev);
+ unsigned int i;
+
+ for (i = 0; i < 2; i++) {
+ if (s->chn[i].chr) {
+ qemu_chr_remove_handlers(s->chn[i].chr, s->chn[i].chr_tag);
+ }
+ }
+}
+
static Property escc_properties[] = {
DEFINE_PROP_UINT32("frequency", ESCCState, frequency, 0),
DEFINE_PROP_UINT32("it_shift", ESCCState, it_shift, 0),
@@ -1047,6 +1061,7 @@ static void escc_class_init(ObjectClass *klass, void
*data)
dc->reset = escc_reset;
dc->realize = escc_realize;
+ dc->unrealize = escc_unrealize;
dc->vmsd = &vmstate_escc;
dc->props = escc_properties;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index c99cc5d..e606a76 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -54,6 +54,7 @@ typedef struct ETRAXSerial {
MemoryRegion mmio;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
int pending_tx;
@@ -232,12 +233,22 @@ static void etraxfs_ser_realize(DeviceState *dev, Error
**errp)
ETRAXSerial *s = ETRAX_SERIAL(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr,
serial_can_receive, serial_receive,
serial_event, s);
}
}
+static void etraxfs_ser_unrealize(DeviceState *dev, Error **errp)
+{
+ ETRAXSerial *s = ETRAX_SERIAL(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -245,6 +256,7 @@ static void etraxfs_ser_class_init(ObjectClass *klass, void
*data)
dc->reset = etraxfs_ser_reset;
dc->props = etraxfs_ser_properties;
dc->realize = etraxfs_ser_realize;
+ dc->unrealize = etraxfs_ser_unrealize;
}
static const TypeInfo etraxfs_ser_info = {
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index 1107578..ba84a4f 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -182,6 +182,7 @@ typedef struct Exynos4210UartState {
Exynos4210UartFIFO tx;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint32_t channel;
@@ -640,12 +641,20 @@ static int exynos4210_uart_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
- qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
exynos4210_uart_receive, exynos4210_uart_event, s);
return 0;
}
+static void exynos4210_uart_unrealize(DeviceState *dev, Error **errp)
+{
+ Exynos4210UartState *s = EXYNOS4210_UART(dev);
+
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+}
+
static Property exynos4210_uart_properties[] = {
DEFINE_PROP_CHR("chardev", Exynos4210UartState, chr),
DEFINE_PROP_UINT32("channel", Exynos4210UartState, channel, 0),
@@ -663,6 +672,7 @@ static void exynos4210_uart_class_init(ObjectClass *klass,
void *data)
dc->reset = exynos4210_uart_reset;
dc->props = exynos4210_uart_properties;
dc->vmsd = &vmstate_exynos4210_uart;
+ dc->unrealize = exynos4210_uart_unrealize;
}
static const TypeInfo exynos4210_uart_info = {
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index 778148a..963ca6d 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -79,6 +79,7 @@ typedef struct UART {
qemu_irq irq;
CharDriverState *chr;
+ int chr_tag;
/* registers */
uint32_t status;
@@ -242,7 +243,8 @@ static int grlib_apbuart_init(SysBusDevice *dev)
{
UART *uart = GRLIB_APB_UART(dev);
- qemu_chr_add_handlers(uart->chr,
+ uart->chr_tag =
+ qemu_chr_add_handlers(uart->chr,
grlib_apbuart_can_receive,
grlib_apbuart_receive,
grlib_apbuart_event,
@@ -271,6 +273,15 @@ static void grlib_apbuart_reset(DeviceState *d)
uart->current = 0;
}
+static void grlib_apbuart_unrealize(DeviceState *d, Error **errp)
+{
+ UART *uart = GRLIB_APB_UART(d);
+
+ if (uart->chr) {
+ qemu_chr_remove_handlers(uart->chr, uart->chr_tag);
+ }
+}
+
static Property grlib_apbuart_properties[] = {
DEFINE_PROP_CHR("chrdev", UART, chr),
DEFINE_PROP_END_OF_LIST(),
@@ -284,6 +295,7 @@ static void grlib_apbuart_class_init(ObjectClass *klass,
void *data)
k->init = grlib_apbuart_init;
dc->reset = grlib_apbuart_reset;
dc->props = grlib_apbuart_properties;
+ dc->unrealize = grlib_apbuart_unrealize;
}
static const TypeInfo grlib_apbuart_info = {
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index 5c3fa61..5ac3122 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -319,13 +319,23 @@ static void imx_serial_realize(DeviceState *dev, Error
**errp)
IMXSerialState *s = IMX_SERIAL(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
- imx_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
+ imx_event, s);
} else {
DPRINTF("No char dev for uart\n");
}
}
+static void imx_serial_unrealize(DeviceState *dev, Error **errp)
+{
+ IMXSerialState *s = IMX_SERIAL(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static void imx_serial_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@@ -347,6 +357,7 @@ static void imx_serial_class_init(ObjectClass *klass, void
*data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = imx_serial_realize;
+ dc->unrealize = imx_serial_unrealize;
dc->vmsd = &vmstate_imx_serial;
dc->reset = imx_serial_reset_at_boot;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
index 2859fdd..4adc500 100644
--- a/hw/char/ipoctal232.c
+++ b/hw/char/ipoctal232.c
@@ -94,6 +94,7 @@ typedef struct SCC2698Block SCC2698Block;
struct SCC2698Channel {
IPOctalState *ipoctal;
CharDriverState *dev;
+ int chr_tag;
bool rx_enabled;
uint8_t mr[2];
uint8_t mr_idx;
@@ -547,7 +548,7 @@ static void ipoctal_realize(DeviceState *dev, Error **errp)
/* Redirect IP-Octal channels to host character devices */
if (ch->dev) {
- qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
+ ch->chr_tag = qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
hostdev_receive, hostdev_event, ch);
DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label);
} else {
@@ -556,6 +557,20 @@ static void ipoctal_realize(DeviceState *dev, Error **errp)
}
}
+static void ipoctal_unrealize(DeviceState *dev, Error **errp)
+{
+ IPOctalState *s = IPOCTAL(dev);
+ unsigned i;
+
+ for (i = 0; i < N_CHANNELS; i++) {
+ SCC2698Channel *ch = &s->ch[i];
+
+ if (ch->dev) {
+ qemu_chr_remove_handlers(ch->dev, ch->chr_tag);
+ }
+ }
+}
+
static Property ipoctal_properties[] = {
DEFINE_PROP_CHR("chardev0", IPOctalState, ch[0].dev),
DEFINE_PROP_CHR("chardev1", IPOctalState, ch[1].dev),
@@ -574,6 +589,7 @@ static void ipoctal_class_init(ObjectClass *klass, void
*data)
IPackDeviceClass *ic = IPACK_DEVICE_CLASS(klass);
ic->realize = ipoctal_realize;
+ ic->unrealize = ipoctal_unrealize;
ic->io_read = io_read;
ic->io_write = io_write;
ic->id_read = id_read;
diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
index cb1ac76..065195d 100644
--- a/hw/char/lm32_juart.c
+++ b/hw/char/lm32_juart.c
@@ -45,6 +45,7 @@ struct LM32JuartState {
SysBusDevice parent_obj;
CharDriverState *chr;
+ int chr_tag;
uint32_t jtx;
uint32_t jrx;
@@ -121,7 +122,17 @@ static void lm32_juart_realize(DeviceState *dev, Error
**errp)
LM32JuartState *s = LM32_JUART(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
+ s->chr_tag = qemu_chr_add_handlers(s->chr, juart_can_rx,
+ juart_rx, juart_event, s);
+ }
+}
+
+static void lm32_juart_unrealize(DeviceState *dev, Error **errp)
+{
+ LM32JuartState *s = LM32_JUART(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
}
}
@@ -149,6 +160,7 @@ static void lm32_juart_class_init(ObjectClass *klass, void
*data)
dc->vmsd = &vmstate_lm32_juart;
dc->props = lm32_juart_properties;
dc->realize = lm32_juart_realize;
+ dc->unrealize = lm32_juart_unrealize;
}
static const TypeInfo lm32_juart_info = {
diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
index be93697..c94cf19 100644
--- a/hw/char/lm32_uart.c
+++ b/hw/char/lm32_uart.c
@@ -98,6 +98,7 @@ struct LM32UartState {
MemoryRegion iomem;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint32_t regs[R_MAX];
@@ -268,7 +269,17 @@ static void lm32_uart_realize(DeviceState *dev, Error
**errp)
LM32UartState *s = LM32_UART(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ }
+}
+
+static void lm32_uart_unrealize(DeviceState *dev, Error **errp)
+{
+ LM32UartState *s = LM32_UART(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
}
}
@@ -295,6 +306,7 @@ static void lm32_uart_class_init(ObjectClass *klass, void
*data)
dc->vmsd = &vmstate_lm32_uart;
dc->props = lm32_uart_properties;
dc->realize = lm32_uart_realize;
+ dc->unrealize = lm32_uart_unrealize;
}
static const TypeInfo lm32_uart_info = {
diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c
index c184859..7a677c7 100644
--- a/hw/char/mcf_uart.c
+++ b/hw/char/mcf_uart.c
@@ -27,6 +27,7 @@ typedef struct {
int rx_enabled;
qemu_irq irq;
CharDriverState *chr;
+ int chr_tag;
} mcf_uart_state;
/* UART Status Register bits. */
@@ -284,7 +285,8 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
s->irq = irq;
if (chr) {
qemu_chr_fe_claim_no_fail(chr);
- qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
mcf_uart_event, s);
}
mcf_uart_reset(s);
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
index baddb37..0203512 100644
--- a/hw/char/milkymist-uart.c
+++ b/hw/char/milkymist-uart.c
@@ -62,6 +62,7 @@ struct MilkymistUartState {
MemoryRegion regs_region;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint32_t regs[R_MAX];
@@ -201,7 +202,17 @@ static void milkymist_uart_realize(DeviceState *dev, Error
**errp)
MilkymistUartState *s = MILKYMIST_UART(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ }
+}
+
+static void milkymist_uart_unrealize(DeviceState *dev, Error **errp)
+{
+ MilkymistUartState *s = MILKYMIST_UART(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
}
}
@@ -237,6 +248,7 @@ static void milkymist_uart_class_init(ObjectClass *klass,
void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = milkymist_uart_realize;
+ dc->unrealize = milkymist_uart_unrealize;
dc->reset = milkymist_uart_reset;
dc->vmsd = &vmstate_milkymist_uart;
dc->props = milkymist_uart_properties;
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 786e605..903c044 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -36,6 +36,7 @@ typedef struct PL011State {
int read_count;
int read_trigger;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
const unsigned char *id;
} PL011State;
@@ -303,16 +304,27 @@ static void pl011_realize(DeviceState *dev, Error **errp)
PL011State *s = PL011(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
pl011_event, s);
}
}
+static void pl011_unrealize(DeviceState *dev, Error **errp)
+{
+ PL011State *s = PL011(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static void pl011_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = pl011_realize;
+ dc->unrealize = pl011_unrealize;
dc->vmsd = &vmstate_pl011;
dc->props = pl011_properties;
}
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 9a56326..7c76d9e 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -38,6 +38,7 @@ typedef struct OprtnsCommand {
typedef struct SCLPConsoleLM {
SCLPEvent event;
CharDriverState *chr;
+ int chr_tag;
bool echo; /* immediate echo of input if true */
uint32_t write_errors; /* errors writing to char layer */
uint32_t length; /* length of byte stream in buffer */
@@ -313,7 +314,9 @@ static int console_init(SCLPEvent *event)
console_available = true;
if (scon->chr) {
- qemu_chr_add_handlers(scon->chr, chr_can_read, chr_read, NULL, scon);
+ scon->chr_tag =
+ qemu_chr_add_handlers(scon->chr, chr_can_read,
+ chr_read, NULL, scon);
}
return 0;
@@ -321,6 +324,12 @@ static int console_init(SCLPEvent *event)
static int console_exit(SCLPEvent *event)
{
+ SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
+
+ if (scon->chr) {
+ qemu_chr_remove_handlers(scon->chr, scon->chr_tag);
+ }
+
return 0;
}
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index a75ad4f..cf0b309 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -32,6 +32,7 @@ typedef struct ASCIIConsoleData {
typedef struct SCLPConsole {
SCLPEvent event;
CharDriverState *chr;
+ int chr_tag;
uint8_t iov[SIZE_BUFFER_VT220];
uint32_t iov_sclp; /* offset in buf for SCLP read operation */
uint32_t iov_bs; /* offset in buf for char layer read operation */
@@ -228,7 +229,8 @@ static int console_init(SCLPEvent *event)
}
console_available = true;
if (scon->chr) {
- qemu_chr_add_handlers(scon->chr, chr_can_read,
+ scon->chr_tag =
+ qemu_chr_add_handlers(scon->chr, chr_can_read,
chr_read, NULL, scon);
}
@@ -250,6 +252,11 @@ static void console_reset(DeviceState *dev)
static int console_exit(SCLPEvent *event)
{
+ SCLPConsole *scon = SCLP_CONSOLE(event);
+
+ if (scon->chr) {
+ qemu_chr_remove_handlers(scon->chr, scon->chr_tag);
+ }
return 0;
}
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 3442f47..9d7d57b 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -893,8 +893,9 @@ void serial_realize_core(SerialState *s, Error **errp)
s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *)
fifo_timeout_int, s);
qemu_register_reset(serial_reset, s);
- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
- serial_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
+ serial_event, s);
fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
serial_reset(s);
@@ -902,7 +903,9 @@ void serial_realize_core(SerialState *s, Error **errp)
void serial_exit_core(SerialState *s)
{
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ s->chr_tag = -1;
+
qemu_unregister_reset(serial_reset, s);
}
@@ -933,6 +936,7 @@ SerialState *serial_init(int base, qemu_irq irq, int
baudbase,
s->irq = irq;
s->baudbase = baudbase;
s->chr = chr;
+ s->chr_tag = -1;
serial_realize_core(s, &error_fatal);
vmstate_register(NULL, base, &vmstate_serial, s);
diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c
index 97ce562..e093689 100644
--- a/hw/char/sh_serial.c
+++ b/hw/char/sh_serial.c
@@ -398,9 +398,13 @@ void sh_serial_init(MemoryRegion *sysmem,
s->chr = chr;
if (chr) {
+ int tag;
+
qemu_chr_fe_claim_no_fail(chr);
- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
- sh_serial_event, s);
+ tag = qemu_chr_add_handlers(chr, sh_serial_can_receive1,
+ sh_serial_receive1,
+ sh_serial_event, s);
+ assert(tag != -1);
}
s->eri = eri_source;
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index 9aeafc0..fdc32e3 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -12,6 +12,7 @@
typedef struct VIOsPAPRVTYDevice {
VIOsPAPRDevice sdev;
CharDriverState *chardev;
+ int chr_tag;
uint32_t in, out;
uint8_t buf[VTERM_BUFSIZE];
} VIOsPAPRVTYDevice;
@@ -74,10 +75,20 @@ static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error
**errp)
return;
}
- qemu_chr_add_handlers(dev->chardev, vty_can_receive,
+ dev->chr_tag =
+ qemu_chr_add_handlers(dev->chardev, vty_can_receive,
vty_receive, NULL, dev);
}
+static void spapr_vty_unrealize(DeviceState *s, Error **errp)
+{
+ VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(s);
+
+ if (dev->chardev) {
+ qemu_chr_remove_handlers(dev->chardev, dev->chr_tag);
+ }
+}
+
/* Forward declaration */
static target_ulong h_put_term_char(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
@@ -173,6 +184,7 @@ static void spapr_vty_class_init(ObjectClass *klass, void
*data)
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->props = spapr_vty_properties;
dc->vmsd = &vmstate_spapr_vty;
+ dc->unrealize = spapr_vty_unrealize;
}
static const TypeInfo spapr_vty_info = {
diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c
index 4c6640d..9f8aac5 100644
--- a/hw/char/stm32f2xx_usart.c
+++ b/hw/char/stm32f2xx_usart.c
@@ -213,11 +213,21 @@ static void stm32f2xx_usart_realize(DeviceState *dev,
Error **errp)
STM32F2XXUsartState *s = STM32F2XX_USART(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
stm32f2xx_usart_receive, NULL, s);
}
}
+static void stm32f2xx_usart_unrealize(DeviceState *dev, Error **errp)
+{
+ STM32F2XXUsartState *s = STM32F2XX_USART(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -225,6 +235,7 @@ static void stm32f2xx_usart_class_init(ObjectClass *klass,
void *data)
dc->reset = stm32f2xx_usart_reset;
dc->props = stm32f2xx_usart_properties;
dc->realize = stm32f2xx_usart_realize;
+ dc->unrealize = stm32f2xx_usart_unrealize;
}
static const TypeInfo stm32f2xx_usart_info = {
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index d44c18c..f3f3aa3 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -25,6 +25,7 @@ typedef struct VirtConsole {
VirtIOSerialPort parent_obj;
CharDriverState *chr;
+ int chr_tag;
guint watch;
} VirtConsole;
@@ -189,12 +190,14 @@ static void virtconsole_realize(DeviceState *dev, Error
**errp)
*/
if (k->is_console) {
vcon->chr->explicit_fe_open = 0;
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
+ vcon->chr_tag =
+ qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
NULL, vcon);
virtio_serial_open(port);
} else {
vcon->chr->explicit_fe_open = 1;
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
+ vcon->chr_tag =
+ qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
chr_event, vcon);
}
}
@@ -207,6 +210,9 @@ static void virtconsole_unrealize(DeviceState *dev, Error
**errp)
if (vcon->watch) {
g_source_remove(vcon->watch);
}
+ if (vcon->chr) {
+ qemu_chr_remove_handlers(vcon->chr, vcon->chr_tag);
+ }
}
static void virtconsole_class_init(ObjectClass *klass, void *data)
diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c
index 83108b0..f263dfa 100644
--- a/hw/char/xen_console.c
+++ b/hw/char/xen_console.c
@@ -44,6 +44,7 @@ struct XenConsole {
int ring_ref;
void *sring;
CharDriverState *chr;
+ int chr_tag;
int backlog;
};
@@ -237,8 +238,9 @@ static int con_initialise(struct XenDevice *xendev)
xen_be_bind_evtchn(&con->xendev);
if (con->chr) {
if (qemu_chr_fe_claim(con->chr) == 0) {
- qemu_chr_add_handlers(con->chr, xencons_can_receive,
- xencons_receive, NULL, con);
+ con->chr_tag =
+ qemu_chr_add_handlers(con->chr, xencons_can_receive,
+ xencons_receive, NULL, con);
} else {
xen_be_printf(xendev, 0,
"xen_console_init error chardev %s already used\n",
@@ -260,7 +262,7 @@ static void con_disconnect(struct XenDevice *xendev)
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
if (con->chr) {
- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(con->chr, con->chr_tag);
qemu_chr_fe_release(con->chr);
}
xen_be_unbind_evtchn(&con->xendev);
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index 3766dc2..e6b103e 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -56,6 +56,7 @@ typedef struct XilinxUARTLite {
MemoryRegion mmio;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint8_t rx_fifo[8];
@@ -213,8 +214,19 @@ static void xilinx_uartlite_realize(DeviceState *dev,
Error **errp)
{
XilinxUARTLite *s = XILINX_UARTLITE(dev);
- if (s->chr)
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ if (s->chr) {
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ }
+}
+
+static void xilinx_uartlite_unrealize(DeviceState *dev, Error **errp)
+{
+ XilinxUARTLite *s = XILINX_UARTLITE(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
}
static void xilinx_uartlite_init(Object *obj)
@@ -234,6 +246,7 @@ static void xilinx_uartlite_class_init(ObjectClass *klass,
void *data)
dc->reset = xilinx_uartlite_reset;
dc->realize = xilinx_uartlite_realize;
+ dc->unrealize = xilinx_uartlite_unrealize;
dc->props = xilinx_uartlite_properties;
}
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
index d93e3f3..927bed2 100644
--- a/hw/ipmi/ipmi_bmc_extern.c
+++ b/hw/ipmi/ipmi_bmc_extern.c
@@ -63,6 +63,7 @@ typedef struct IPMIBmcExtern {
IPMIBmc parent;
CharDriverState *chr;
+ int chr_tag;
bool connected;
@@ -447,7 +448,17 @@ static void ipmi_bmc_extern_realize(DeviceState *dev,
Error **errp)
return;
}
- qemu_chr_add_handlers(ibe->chr, can_receive, receive, chr_event, ibe);
+ ibe->chr_tag =
+ qemu_chr_add_handlers(ibe->chr, can_receive, receive, chr_event, ibe);
+}
+
+static void ipmi_bmc_extern_unrealize(DeviceState *dev, Error **errp)
+{
+ IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(dev);
+
+ if (ibe->chr) {
+ qemu_chr_remove_handlers(ibe->chr, ibe->chr_tag);
+ }
}
static int ipmi_bmc_extern_post_migrate(void *opaque, int version_id)
@@ -512,6 +523,7 @@ static void ipmi_bmc_extern_class_init(ObjectClass *oc,
void *data)
bk->handle_command = ipmi_bmc_extern_handle_command;
bk->handle_reset = ipmi_bmc_extern_handle_reset;
dc->realize = ipmi_bmc_extern_realize;
+ dc->unrealize = ipmi_bmc_extern_unrealize;
dc->props = ipmi_bmc_extern_properties;
}
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index f803dfd..19079f4 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -89,6 +89,7 @@ typedef struct IVShmemState {
/* exactly one of these two may be set */
HostMemoryBackend *hostmem; /* with interrupts */
CharDriverState *server_chr; /* without interrupts */
+ int server_chr_tag;
/* registers */
uint32_t intrmask;
@@ -841,6 +842,8 @@ static void ivshmem_common_realize(PCIDevice *dev, Error
**errp)
uint8_t attr = PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_PREFETCH;
+ s->server_chr_tag = -1;
+
/* IRQFD requires MSI */
if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD) &&
!ivshmem_has_feature(s, IVSHMEM_MSI)) {
@@ -893,8 +896,9 @@ static void ivshmem_common_realize(PCIDevice *dev, Error
**errp)
return;
}
- qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive,
- ivshmem_read, NULL, s);
+ s->server_chr_tag =
+ qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive,
+ ivshmem_read, NULL, s);
if (ivshmem_setup_interrupts(s) < 0) {
error_setg(errp, "failed to initialize interrupts");
@@ -955,6 +959,10 @@ static void ivshmem_exit(PCIDevice *dev)
}
g_free(s->msi_vectors);
+
+ if (s->server_chr) {
+ qemu_chr_remove_handlers(s->server_chr, s->server_chr_tag);
+ }
}
static int ivshmem_pre_load(void *opaque)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 2eacea7..8960972 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -49,6 +49,7 @@ typedef struct PassthruState PassthruState;
struct PassthruState {
CCIDCardState base;
CharDriverState *cs;
+ int chr_tag;
uint8_t vscard_in_data[VSCARD_IN_SIZE];
uint32_t vscard_in_pos;
uint32_t vscard_in_hdr;
@@ -347,7 +348,7 @@ static int passthru_initfn(CCIDCardState *base)
card->vscard_in_hdr = 0;
if (card->cs) {
DPRINTF(card, D_INFO, "initing chardev\n");
- qemu_chr_add_handlers(card->cs,
+ card->chr_tag = qemu_chr_add_handlers(card->cs,
ccid_card_vscard_can_read,
ccid_card_vscard_read,
ccid_card_vscard_event, card);
@@ -366,6 +367,12 @@ static int passthru_initfn(CCIDCardState *base)
static int passthru_exitfn(CCIDCardState *base)
{
+ PassthruState *card = PASSTHRU_CCID_CARD(base);
+
+ if (card->cs) {
+ qemu_chr_remove_handlers(card->cs, card->chr_tag);
+ }
+
return 0;
}
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 966ad84..4dcfc68 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -104,6 +104,7 @@ typedef struct {
QEMUSerialSetParams params;
int latency; /* ms */
CharDriverState *cs;
+ int chr_tag;
} USBSerialState;
#define TYPE_USB_SERIAL "usb-serial-dev"
@@ -499,8 +500,9 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
return;
}
- qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
- usb_serial_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
+ usb_serial_event, s);
usb_serial_handle_reset(dev);
if (s->cs->be_open && !dev->attached) {
@@ -508,6 +510,15 @@ static void usb_serial_realize(USBDevice *dev, Error
**errp)
}
}
+static void usb_serial_unrealize(USBDevice *dev, Error **errp)
+{
+ USBSerialState *s = USB_SERIAL_DEV(dev);
+
+ if (s->cs) {
+ qemu_chr_remove_handlers(s->cs, s->chr_tag);
+ }
+}
+
static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
{
USBDevice *dev;
@@ -590,6 +601,7 @@ static void usb_serial_dev_class_init(ObjectClass *klass,
void *data)
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
uc->realize = usb_serial_realize;
+ uc->unrealize = usb_serial_unrealize;
uc->handle_reset = usb_serial_handle_reset;
uc->handle_control = usb_serial_handle_control;
uc->handle_data = usb_serial_handle_data;
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index d4ca026..7d73c93 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -106,6 +106,7 @@ struct USBRedirDevice {
USBDevice dev;
/* Properties */
CharDriverState *cs;
+ int chr_tag;
uint8_t debug;
char *filter_str;
int32_t bootindex;
@@ -1375,6 +1376,7 @@ static void usbredir_realize(USBDevice *udev, Error
**errp)
USBRedirDevice *dev = USB_REDIRECT(udev);
int i;
+ dev->chr_tag = -1;
if (dev->cs == NULL) {
error_setg(errp, QERR_MISSING_PARAMETER, "chardev");
return;
@@ -1406,12 +1408,20 @@ static void usbredir_realize(USBDevice *udev, Error
**errp)
dev->compatible_speedmask = USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH;
/* Let the backend know we are ready */
- qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
+ dev->chr_tag =
+ qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
usbredir_chardev_read, usbredir_chardev_event, dev);
qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
}
+static void usbredir_unrealize(USBDevice *udev, Error **errp)
+{
+ USBRedirDevice *dev = USB_REDIRECT(udev);
+
+ qemu_chr_remove_handlers(dev->cs, dev->chr_tag);
+}
+
static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
{
int i;
@@ -2493,6 +2503,7 @@ static void usbredir_class_initfn(ObjectClass *klass,
void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
uc->realize = usbredir_realize;
+ uc->unrealize = usbredir_unrealize;
uc->product_desc = "USB Redirection Device";
uc->handle_destroy = usbredir_handle_destroy;
uc->cancel_packet = usbredir_cancel_packet;
diff --git a/monitor.c b/monitor.c
index 8728dd9..0d6f0ad 100644
--- a/monitor.c
+++ b/monitor.c
@@ -187,6 +187,7 @@ typedef struct {
struct Monitor {
CharDriverState *chr;
+ int chr_tag;
int reset_seen;
int flags;
int suspend_cnt;
@@ -582,7 +583,7 @@ static void monitor_data_init(Monitor *mon)
static void monitor_data_destroy(Monitor *mon)
{
if (mon->chr) {
- qemu_chr_add_handlers(mon->chr, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(mon->chr, mon->chr_tag);
}
if (monitor_is_qmp(mon)) {
json_message_parser_destroy(&mon->qmp.parser);
@@ -3988,13 +3989,15 @@ void monitor_init(CharDriverState *chr, int flags)
}
if (monitor_is_qmp(mon)) {
- qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read,
- monitor_qmp_event, mon);
+ mon->chr_tag =
+ qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read,
+ monitor_qmp_event, mon);
qemu_chr_fe_set_echo(chr, true);
json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
} else {
- qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
- monitor_event, mon);
+ mon->chr_tag =
+ qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
+ monitor_event, mon);
}
qemu_mutex_lock(&monitor_lock);
diff --git a/net/colo-compare.c b/net/colo-compare.c
index 47703c5..88582c8 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -70,6 +70,8 @@ typedef struct CompareState {
char *outdev;
CharDriverState *chr_pri_in;
CharDriverState *chr_sec_in;
+ int chr_pri_tag;
+ int chr_sec_tag;
CharDriverState *chr_out;
SocketReadState pri_rs;
SocketReadState sec_rs;
@@ -451,7 +453,8 @@ static void compare_pri_chr_in(void *opaque, const uint8_t
*buf, int size)
ret = net_fill_rstate(&s->pri_rs, buf, size);
if (ret == -1) {
- qemu_chr_add_handlers(s->chr_pri_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_pri_in, s->chr_pri_tag);
+ s->chr_pri_tag = -1;
error_report("colo-compare primary_in error");
}
}
@@ -467,7 +470,8 @@ static void compare_sec_chr_in(void *opaque, const uint8_t
*buf, int size)
ret = net_fill_rstate(&s->sec_rs, buf, size);
if (ret == -1) {
- qemu_chr_add_handlers(s->chr_sec_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_sec_in, s->chr_sec_tag);
+ s->chr_sec_tag = -1;
error_report("colo-compare secondary_in error");
}
}
@@ -480,10 +484,12 @@ static void *colo_compare_thread(void *opaque)
worker_context = g_main_context_new();
- qemu_chr_add_handlers_full(s->chr_pri_in, compare_chr_can_read,
- compare_pri_chr_in, NULL, s, worker_context);
- qemu_chr_add_handlers_full(s->chr_sec_in, compare_chr_can_read,
- compare_sec_chr_in, NULL, s, worker_context);
+ s->chr_pri_tag =
+ qemu_chr_add_handlers_full(s->chr_pri_in, compare_chr_can_read,
+ compare_pri_chr_in, NULL, s,
worker_context);
+ s->chr_sec_tag =
+ qemu_chr_add_handlers_full(s->chr_sec_in, compare_chr_can_read,
+ compare_sec_chr_in, NULL, s,
worker_context);
compare_loop = g_main_loop_new(worker_context, FALSE);
@@ -703,11 +709,11 @@ static void colo_compare_finalize(Object *obj)
CompareState *s = COLO_COMPARE(obj);
if (s->chr_pri_in) {
- qemu_chr_add_handlers(s->chr_pri_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_pri_in, s->chr_pri_tag);
qemu_chr_fe_release(s->chr_pri_in);
}
if (s->chr_sec_in) {
- qemu_chr_add_handlers(s->chr_sec_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_sec_in, s->chr_sec_tag);
qemu_chr_fe_release(s->chr_sec_in);
}
if (s->chr_out) {
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index 0ee58d9..8c1d613 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -39,6 +39,7 @@ typedef struct MirrorState {
char *indev;
char *outdev;
CharDriverState *chr_in;
+ int chr_in_tag;
CharDriverState *chr_out;
SocketReadState rs;
} MirrorState;
@@ -110,7 +111,8 @@ static void redirector_chr_read(void *opaque, const uint8_t
*buf, int size)
ret = net_fill_rstate(&s->rs, buf, size);
if (ret == -1) {
- qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_in, s->chr_in_tag);
+ s->chr_in_tag = -1;
}
}
@@ -121,7 +123,8 @@ static void redirector_chr_event(void *opaque, int event)
switch (event) {
case CHR_EVENT_CLOSED:
- qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_in, s->chr_in_tag);
+ s->chr_in_tag = -1;
break;
default:
break;
@@ -185,7 +188,8 @@ static void filter_redirector_cleanup(NetFilterState *nf)
MirrorState *s = FILTER_REDIRECTOR(nf);
if (s->chr_in) {
- qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_in, s->chr_in_tag);
+ s->chr_in_tag = -1;
qemu_chr_fe_release(s->chr_in);
}
if (s->chr_out) {
@@ -228,6 +232,7 @@ static void filter_redirector_setup(NetFilterState *nf,
Error **errp)
{
MirrorState *s = FILTER_REDIRECTOR(nf);
+ s->chr_in_tag = -1;
if (!s->indev && !s->outdev) {
error_setg(errp, "filter redirector needs 'indev' or "
"'outdev' at least one property set");
@@ -251,7 +256,8 @@ static void filter_redirector_setup(NetFilterState *nf,
Error **errp)
}
qemu_chr_fe_claim_no_fail(s->chr_in);
- qemu_chr_add_handlers(s->chr_in, redirector_chr_can_read,
+ s->chr_in_tag =
+ qemu_chr_add_handlers(s->chr_in, redirector_chr_can_read,
redirector_chr_read, redirector_chr_event, nf);
}
diff --git a/net/slirp.c b/net/slirp.c
index b60893f..80eefb0 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -683,6 +683,7 @@ int net_slirp_smb(const char *exported_dir)
struct GuestFwd {
CharDriverState *hd;
+ int chr_tag;
struct in_addr server;
int port;
Slirp *slirp;
@@ -765,8 +766,9 @@ static int slirp_guestfwd(SlirpState *s, const char
*config_str,
fwd->slirp = s->slirp;
qemu_chr_fe_claim_no_fail(fwd->hd);
- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
- NULL, fwd);
+ fwd->chr_tag =
+ qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
+ NULL, fwd);
}
return 0;
diff --git a/net/vhost-user.c b/net/vhost-user.c
index 5b94c84..f3cf623 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -21,6 +21,7 @@
typedef struct VhostUserState {
NetClientState nc;
CharDriverState *chr;
+ int chr_tag;
VHostNetState *vhost_net;
guint watch;
uint64_t acked_features;
@@ -151,7 +152,7 @@ static void vhost_user_cleanup(NetClientState *nc)
s->vhost_net = NULL;
}
if (s->chr) {
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
qemu_chr_fe_release(s->chr);
s->chr = NULL;
}
@@ -258,14 +259,15 @@ static int net_vhost_user_init(NetClientState *peer,
const char *device,
}
s = DO_UPCAST(VhostUserState, nc, nc0);
+ s->chr_tag =
+ qemu_chr_add_handlers(chr, NULL, NULL,
+ net_vhost_user_event, nc0->name);
do {
Error *err = NULL;
if (qemu_chr_wait_connected(chr, &err) < 0) {
error_report_err(err);
return -1;
}
- qemu_chr_add_handlers(chr, NULL, NULL,
- net_vhost_user_event, nc0->name);
} while (!s->started);
assert(s->vhost_net);
diff --git a/qemu-char.c b/qemu-char.c
index a7fec6a..261a8f9 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -569,6 +569,7 @@ struct MuxDriver {
CharDriverState *drv;
int focus;
int mux_cnt;
+ int mux_tag;
int term_got_escape;
int max_size;
/* Intermediate input buffer allows to catch escape sequences even if the
@@ -850,8 +851,8 @@ static int mux_chr_new_handler_tag(CharDriverState *chr,
GMainContext *context)
}
/* Fix up the real driver with mux routines */
- if (d->mux_cnt == 0) {
- qemu_chr_add_handlers_full(d->drv, mux_chr_can_read,
+ if (d->mux_tag == -1) {
+ d->mux_tag = qemu_chr_add_handlers_full(d->drv, mux_chr_can_read,
mux_chr_read,
mux_chr_event,
chr, context);
@@ -897,6 +898,7 @@ static CharDriverState *qemu_chr_open_mux(const char *id,
chr->opaque = d;
d->drv = drv;
d->focus = -1;
+ d->mux_tag = -1;
chr->chr_close = mux_chr_close;
chr->chr_write = mux_chr_write;
chr->chr_update_read_handler = mux_chr_update_read_handler;
diff --git a/qtest.c b/qtest.c
index 22482cc..73e07c2 100644
--- a/qtest.c
+++ b/qtest.c
@@ -39,6 +39,7 @@ bool qtest_allowed;
static DeviceState *irq_intercept_dev;
static FILE *qtest_log_fp;
static CharDriverState *qtest_chr;
+static int qtest_chr_tag;
static GString *inbuf;
static int irq_levels[MAX_IRQ];
static qemu_timeval start_time;
@@ -679,7 +680,8 @@ void qtest_init(const char *qtest_chrdev, const char
*qtest_log, Error **errp)
qtest_log_fp = stderr;
}
- qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
+ qtest_chr_tag =
+ qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event,
chr);
qemu_chr_fe_set_echo(chr, true);
inbuf = g_string_new("");
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index d7c48c5..133cbdc 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -142,6 +142,7 @@ typedef struct TestServer {
gchar *mig_path;
gchar *chr_name;
CharDriverState *chr;
+ int chr_tag;
int fds_num;
int fds[VHOST_MEMORY_MAX_NREGIONS];
VhostUserMemory memory;
@@ -458,8 +459,9 @@ static void test_server_create_chr(TestServer *server,
const gchar *opt)
server->chr = qemu_chr_new(server->chr_name, chr_path, NULL);
g_free(chr_path);
- qemu_chr_add_handlers(server->chr, chr_can_read, chr_read,
- chr_event, server);
+ server->chr_tag =
+ qemu_chr_add_handlers(server->chr, chr_can_read, chr_read,
+ chr_event, server);
}
static void test_server_listen(TestServer *server)
@@ -484,6 +486,7 @@ static gboolean _test_server_free(TestServer *server)
{
int i;
+ qemu_chr_remove_handlers(server->chr, server->chr_tag);
qemu_chr_delete(server->chr);
for (i = 0; i < server->fds_num; i++) {
diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h
index 42f0ee7..c55886e 100644
--- a/include/hw/char/bcm2835_aux.h
+++ b/include/hw/char/bcm2835_aux.h
@@ -23,6 +23,7 @@ typedef struct {
MemoryRegion iomem;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN];
diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h
index a12773c..e510d15 100644
--- a/include/hw/char/cadence_uart.h
+++ b/include/hw/char/cadence_uart.h
@@ -45,6 +45,7 @@ typedef struct {
uint32_t tx_count;
uint64_t char_tx_time;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
QEMUTimer *fifo_trigger_handle;
} CadenceUARTState;
diff --git a/include/hw/char/digic-uart.h b/include/hw/char/digic-uart.h
index 7b3f145..160bf03 100644
--- a/include/hw/char/digic-uart.h
+++ b/include/hw/char/digic-uart.h
@@ -38,6 +38,7 @@ typedef struct DigicUartState {
MemoryRegion regs_region;
CharDriverState *chr;
+ int chr_tag;
uint32_t reg_rx;
uint32_t reg_st;
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
index 6cd75c0..cbf5859 100644
--- a/include/hw/char/imx_serial.h
+++ b/include/hw/char/imx_serial.h
@@ -97,6 +97,7 @@ typedef struct IMXSerialState {
qemu_irq irq;
CharDriverState *chr;
+ int chr_tag;
} IMXSerialState;
#endif
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index a4fd3d5..0ec91ea 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -53,6 +53,7 @@ struct SerialState {
int thr_ipending;
qemu_irq irq;
CharDriverState *chr;
+ int chr_tag;
int last_break_enable;
int it_shift;
int baudbase;
diff --git a/include/hw/char/stm32f2xx_usart.h
b/include/hw/char/stm32f2xx_usart.h
index b97f192..d9be1c0 100644
--- a/include/hw/char/stm32f2xx_usart.h
+++ b/include/hw/char/stm32f2xx_usart.h
@@ -68,6 +68,7 @@ typedef struct {
uint32_t usart_gtpr;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
} STM32F2XXUsartState;
#endif /* HW_STM32F2XX_USART_H */
--
2.10.0
- [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2), Marc-André Lureau, 2016/10/13
- [Qemu-devel] [PATCH 1/9] Revert "char: use a fixed idx for child muxed chr", Marc-André Lureau, 2016/10/13
- [Qemu-devel] [PATCH 2/9] char: return a tag when adding the fe handlers, Marc-André Lureau, 2016/10/13
- [Qemu-devel] [PATCH 3/9] char: add qemu_chr_remove_handlers(), Marc-André Lureau, 2016/10/13
- [Qemu-devel] [PATCH 5/9] char: warn on unused qemu_chr_add_handlers() result, Marc-André Lureau, 2016/10/13
- [Qemu-devel] [PATCH 4/9] char: keep track of qemu_chr_add_handlers(),
Marc-André Lureau <=
- [Qemu-devel] [PATCH 6/9] qdev: remove call to qemu_chr_add_handlers(), Marc-André Lureau, 2016/10/13
- [Qemu-devel] [PATCH 8/9] ringbuf: fix chr_write return value, Marc-André Lureau, 2016/10/13
- [Qemu-devel] [PATCH 7/9] char: handle qemu_chr_add_handlers() error, Marc-André Lureau, 2016/10/13
- [Qemu-devel] [PATCH 9/9] tests: start chardev unit tests, Marc-André Lureau, 2016/10/13
- Re: [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2), Paolo Bonzini, 2016/10/13
- Re: [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2), Peter Maydell, 2016/10/13