qemu-char: Call fe_claim / fe_release when not using qdev chr properties

chardev-frontends need to explictly check, increase and decrement the
avail_connections "property" of the chardev when they are not using a
qdev-chardev-property for the chardev.

This fixes things like:
qemu-kvm -chardev stdio,id=foo -device isa-serial,chardev=foo \
  -mon chardev=foo

Working, where they should fail. Most of the changes here are due to
old hardware emulation code which is using serial_hds directly rather then
a qdev-chardev-property.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Message-id: 1364412581-3672-3-git-send-email-hdegoede@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Hans de Goede 2013-03-27 20:29:40 +01:00 committed by Anthony Liguori
parent 44c473decd
commit 456d606923
12 changed files with 42 additions and 7 deletions

View File

@ -149,6 +149,11 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
return; return;
} }
if (qemu_chr_fe_claim(s->chr) != 0) {
error_set(errp, QERR_DEVICE_IN_USE, s->chr_name);
return;
}
/* FIXME we should resubmit pending requests when the CDS reconnects. */ /* 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, qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
NULL, s); NULL, s);
@ -191,6 +196,7 @@ static void rng_egd_finalize(Object *obj)
if (s->chr) { if (s->chr) {
qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL); qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(s->chr);
} }
g_free(s->chr_name); g_free(s->chr_name);

View File

@ -3025,6 +3025,7 @@ int gdbserver_start(const char *device)
if (!chr) if (!chr)
return -1; return -1;
qemu_chr_fe_claim_no_fail(chr);
qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
gdb_chr_event, NULL); gdb_chr_event, NULL);
} }

View File

@ -1981,9 +1981,11 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000); memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
memory_region_add_subregion(sysmem, base, &s->iomem); memory_region_add_subregion(sysmem, base, &s->iomem);
if (chr) if (chr) {
qemu_chr_fe_claim_no_fail(chr);
qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty, qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
pxa2xx_fir_rx, pxa2xx_fir_event, s); pxa2xx_fir_rx, pxa2xx_fir_event, s);
}
register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save, register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
pxa2xx_fir_load, s); pxa2xx_fir_load, s);

View File

@ -439,6 +439,7 @@ CharDriverState *uart_hci_init(qemu_irq wakeup)
s->chr.opaque = s; s->chr.opaque = s;
s->chr.chr_write = csrhci_write; s->chr.chr_write = csrhci_write;
s->chr.chr_ioctl = csrhci_ioctl; s->chr.chr_ioctl = csrhci_ioctl;
s->chr.avail_connections = 1;
s->hci = qemu_next_hci(); s->hci = qemu_next_hci();
s->hci->opaque = s; s->hci->opaque = s;

View File

@ -556,6 +556,7 @@ static int ipoctal_init(IPackDevice *ip)
if (ch->dev) { if (ch->dev) {
index++; index++;
qemu_chr_fe_claim_no_fail(ch->dev);
qemu_chr_add_handlers(ch->dev, hostdev_can_receive, qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
hostdev_receive, hostdev_event, ch); hostdev_receive, hostdev_event, ch);
DPRINTF("Redirecting channel %u to %s (%s)\n", DPRINTF("Redirecting channel %u to %s (%s)\n",

View File

@ -292,6 +292,7 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *
fprintf(stderr, "creating eventfd for eventfd %d failed\n", eventfd); fprintf(stderr, "creating eventfd for eventfd %d failed\n", eventfd);
exit(-1); exit(-1);
} }
qemu_chr_fe_claim_no_fail(chr);
/* if MSI is supported we need multiple interrupts */ /* if MSI is supported we need multiple interrupts */
if (ivshmem_has_feature(s, IVSHMEM_MSI)) { if (ivshmem_has_feature(s, IVSHMEM_MSI)) {

View File

@ -280,6 +280,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
s->chr = chr; s->chr = chr;
s->irq = irq; s->irq = irq;
if (chr) { if (chr) {
qemu_chr_fe_claim_no_fail(chr);
qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive, qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
mcf_uart_event, s); mcf_uart_event, s);
} }

View File

@ -396,9 +396,11 @@ void sh_serial_init(MemoryRegion *sysmem,
s->chr = chr; s->chr = chr;
if (chr) if (chr) {
qemu_chr_fe_claim_no_fail(chr);
qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1, qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
sh_serial_event, s); sh_serial_event, s);
}
s->eri = eri_source; s->eri = eri_source;
s->rxi = rxi_source; s->rxi = rxi_source;

View File

@ -241,9 +241,17 @@ static int con_initialise(struct XenDevice *xendev)
return -1; return -1;
xen_be_bind_evtchn(&con->xendev); xen_be_bind_evtchn(&con->xendev);
if (con->chr) if (con->chr) {
qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive, if (qemu_chr_fe_claim(con->chr) == 0) {
NULL, con); 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",
con->chr->label);
con->chr = NULL;
}
}
xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n", xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
con->ring_ref, con->ring_ref,
@ -260,8 +268,10 @@ static void con_disconnect(struct XenDevice *xendev)
if (!xendev->dev) { if (!xendev->dev) {
return; return;
} }
if (con->chr) if (con->chr) {
qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL); qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(con->chr);
}
xen_be_unbind_evtchn(&con->xendev); xen_be_unbind_evtchn(&con->xendev);
if (con->sring) { if (con->sring) {

View File

@ -660,6 +660,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
fwd->port = port; fwd->port = port;
fwd->slirp = s->slirp; fwd->slirp = s->slirp;
qemu_chr_fe_claim_no_fail(fwd->hd);
qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
NULL, fwd); NULL, fwd);
} }

View File

@ -3411,6 +3411,7 @@ CharDriverState *qemu_chr_new(const char *label, const char *filename, void (*in
error_free(err); error_free(err);
} }
if (chr && qemu_opt_get_bool(opts, "mux", 0)) { if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
qemu_chr_fe_claim_no_fail(chr);
monitor_init(chr, MONITOR_USE_READLINE); monitor_init(chr, MONITOR_USE_READLINE);
} }
return chr; return chr;
@ -3523,9 +3524,16 @@ CharDriverState *qemu_chr_find(const char *name)
CharDriverState *qemu_char_get_next_serial(void) CharDriverState *qemu_char_get_next_serial(void)
{ {
static int next_serial; static int next_serial;
CharDriverState *chr;
/* FIXME: This function needs to go away: use chardev properties! */ /* FIXME: This function needs to go away: use chardev properties! */
return serial_hds[next_serial++];
while (next_serial < MAX_SERIAL_PORTS && serial_hds[next_serial]) {
chr = serial_hds[next_serial++];
qemu_chr_fe_claim_no_fail(chr);
return chr;
}
return NULL;
} }
QemuOptsList qemu_chardev_opts = { QemuOptsList qemu_chardev_opts = {

1
vl.c
View File

@ -2396,6 +2396,7 @@ static int mon_init_func(QemuOpts *opts, void *opaque)
exit(1); exit(1);
} }
qemu_chr_fe_claim_no_fail(chr);
monitor_init(chr, flags); monitor_init(chr, flags);
return 0; return 0;
} }