Misc 2.1 fixes regarding character/serial devices and SCSI.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJTw/aQAAoJEBvWZb6bTYbyQFkQAJ1/P6aG5EOd8dBQ2rNZ72Zp tWLnCQNZFIRLu1PGwiiqKihRk3N+YSMh0xERe1H8ZPwv1xIpia5zfcZ+fwEizyb2 62zaTSSbUssWvt/p/mnb8K4H3HhBnEfEcQsFJi9GiML8G7rFwq5pUYTPfu0DQkq0 +j1sk/sfzaKfdzDuxpz1cxPkFw7BjDTPDJPsKJCSok25sS7EhfN00auc33r8427k k5p/1xz7K/edUhZ86XhCIOs5bHIGxEnpK4bjV5F4MXCMC5vgp1VFFrK8GRG7rncO rB0rYCzpgxLA8DYpSGOIl6VNfZfHfvtrAdPbQwPfh1FzEya2PL/WorfwFcibKU3V 3aa07rVOunIxVsCET49Q36RnSCX9COKww9BJxcsLu7C/G8id4tu67OS0/FMI/EaJ 1oy7miUJuWhZEA115zyBfWBrv88PgNdlYVP8NtekBoHaL5m+Tk6ZAVmmxz5AxDZs zXrzUgotQ+cQZdeHJ/UVvjk4J1RUsolOEIwASgxBFph4fwAT/kRtlkZCpX/2xfDA VSTxKqoiQkdepQzBcNBOJvhQ38kU5qQ3AZb871T+y4WwP6jKj8kqZ7yiFf6yYz4a AqzSpichWVan99HuTLfiexHyq4r2D75To6ZQFVduYhQg8YX5byDcjtiQRFyy1uKv FwkEa/mpZdB1p0fSc7i3 =8zIe -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging Misc 2.1 fixes regarding character/serial devices and SCSI. # gpg: Signature made Mon 14 Jul 2014 16:26:08 BST using RSA key ID 9B4D86F2 # gpg: Can't check signature: public key not found * remotes/bonzini/tags/for-upstream: serial-pci: remove memory regions from BAR before destroying them virtio-scsi: fix with -M pc-i440fx-2.0 serial: change retry logic to avoid concurrency qemu-char: fix deadlock with "-monitor pty" scsi: Report error when lun number is in use Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
0a9934eef1
|
@ -148,6 +148,7 @@ static void multi_serial_pci_exit(PCIDevice *dev)
|
|||
for (i = 0; i < pci->ports; i++) {
|
||||
s = pci->state + i;
|
||||
serial_exit_core(s);
|
||||
memory_region_del_subregion(&pci->iobar, &s->io);
|
||||
memory_region_destroy(&s->io);
|
||||
g_free(pci->name[i]);
|
||||
}
|
||||
|
|
|
@ -223,37 +223,42 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
|
|||
{
|
||||
SerialState *s = opaque;
|
||||
|
||||
if (s->tsr_retry <= 0) {
|
||||
if (s->fcr & UART_FCR_FE) {
|
||||
if (fifo8_is_empty(&s->xmit_fifo)) {
|
||||
do {
|
||||
if (s->tsr_retry <= 0) {
|
||||
if (s->fcr & UART_FCR_FE) {
|
||||
if (fifo8_is_empty(&s->xmit_fifo)) {
|
||||
return FALSE;
|
||||
}
|
||||
s->tsr = fifo8_pop(&s->xmit_fifo);
|
||||
if (!s->xmit_fifo.num) {
|
||||
s->lsr |= UART_LSR_THRE;
|
||||
}
|
||||
} else if ((s->lsr & UART_LSR_THRE)) {
|
||||
return FALSE;
|
||||
} else {
|
||||
s->tsr = s->thr;
|
||||
s->lsr |= UART_LSR_THRE;
|
||||
s->lsr &= ~UART_LSR_TEMT;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->mcr & UART_MCR_LOOP) {
|
||||
/* 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 &&
|
||||
qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
|
||||
serial_xmit, s) > 0) {
|
||||
s->tsr_retry++;
|
||||
return FALSE;
|
||||
}
|
||||
s->tsr = fifo8_pop(&s->xmit_fifo);
|
||||
if (!s->xmit_fifo.num) {
|
||||
s->lsr |= UART_LSR_THRE;
|
||||
}
|
||||
} else if ((s->lsr & UART_LSR_THRE)) {
|
||||
return FALSE;
|
||||
s->tsr_retry = 0;
|
||||
} else {
|
||||
s->tsr = s->thr;
|
||||
s->lsr |= UART_LSR_THRE;
|
||||
s->lsr &= ~UART_LSR_TEMT;
|
||||
s->tsr_retry = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->mcr & UART_MCR_LOOP) {
|
||||
/* 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 &&
|
||||
qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, serial_xmit, s) > 0) {
|
||||
s->tsr_retry++;
|
||||
return FALSE;
|
||||
}
|
||||
s->tsr_retry = 0;
|
||||
} else {
|
||||
s->tsr_retry = 0;
|
||||
}
|
||||
/* Transmit another byte if it is already available. It is only
|
||||
possible when FIFO is enabled and not empty. */
|
||||
} while ((s->fcr & UART_FCR_FE) && !fifo8_is_empty(&s->xmit_fifo));
|
||||
|
||||
s->last_xmit_ts = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
|
||||
|
@ -293,7 +298,9 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
|
|||
s->thr_ipending = 0;
|
||||
s->lsr &= ~UART_LSR_THRE;
|
||||
serial_update_irq(s);
|
||||
serial_xmit(NULL, G_IO_OUT, s);
|
||||
if (s->tsr_retry <= 0) {
|
||||
serial_xmit(NULL, G_IO_OUT, s);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
|
|
|
@ -177,7 +177,8 @@ static int scsi_qdev_init(DeviceState *qdev)
|
|||
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
|
||||
assert(d);
|
||||
if (d->lun == dev->lun && dev != d) {
|
||||
object_unparent(OBJECT(d));
|
||||
error_report("lun already used by '%s'", d->qdev.id);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,6 +178,8 @@ typedef struct {
|
|||
DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128)
|
||||
|
||||
#define DEFINE_VIRTIO_SCSI_FEATURES(_state, _feature_field) \
|
||||
DEFINE_PROP_BIT("any_layout", _state, _feature_field, \
|
||||
VIRTIO_F_ANY_LAYOUT, true), \
|
||||
DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG, \
|
||||
true), \
|
||||
DEFINE_PROP_BIT("param_change", _state, _feature_field, \
|
||||
|
|
23
qemu-char.c
23
qemu-char.c
|
@ -1089,6 +1089,7 @@ typedef struct {
|
|||
/* Protected by the CharDriverState chr_write_lock. */
|
||||
int connected;
|
||||
guint timer_tag;
|
||||
guint open_tag;
|
||||
} PtyCharDriver;
|
||||
|
||||
static void pty_chr_update_read_handler_locked(CharDriverState *chr);
|
||||
|
@ -1101,6 +1102,7 @@ static gboolean pty_chr_timer(gpointer opaque)
|
|||
|
||||
qemu_mutex_lock(&chr->chr_write_lock);
|
||||
s->timer_tag = 0;
|
||||
s->open_tag = 0;
|
||||
if (!s->connected) {
|
||||
/* Next poll ... */
|
||||
pty_chr_update_read_handler_locked(chr);
|
||||
|
@ -1203,12 +1205,26 @@ static gboolean pty_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean qemu_chr_be_generic_open_func(gpointer opaque)
|
||||
{
|
||||
CharDriverState *chr = opaque;
|
||||
PtyCharDriver *s = chr->opaque;
|
||||
|
||||
s->open_tag = 0;
|
||||
qemu_chr_be_generic_open(chr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Called with chr_write_lock held. */
|
||||
static void pty_chr_state(CharDriverState *chr, int connected)
|
||||
{
|
||||
PtyCharDriver *s = chr->opaque;
|
||||
|
||||
if (!connected) {
|
||||
if (s->open_tag) {
|
||||
g_source_remove(s->open_tag);
|
||||
s->open_tag = 0;
|
||||
}
|
||||
remove_fd_in_watch(chr);
|
||||
s->connected = 0;
|
||||
/* (re-)connect poll interval for idle guests: once per second.
|
||||
|
@ -1221,8 +1237,9 @@ static void pty_chr_state(CharDriverState *chr, int connected)
|
|||
s->timer_tag = 0;
|
||||
}
|
||||
if (!s->connected) {
|
||||
g_assert(s->open_tag == 0);
|
||||
s->connected = 1;
|
||||
qemu_chr_be_generic_open(chr);
|
||||
s->open_tag = g_idle_add(qemu_chr_be_generic_open_func, chr);
|
||||
}
|
||||
if (!chr->fd_in_tag) {
|
||||
chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll,
|
||||
|
@ -1236,7 +1253,8 @@ static void pty_chr_close(struct CharDriverState *chr)
|
|||
PtyCharDriver *s = chr->opaque;
|
||||
int fd;
|
||||
|
||||
remove_fd_in_watch(chr);
|
||||
qemu_mutex_lock(&chr->chr_write_lock);
|
||||
pty_chr_state(chr, 0);
|
||||
fd = g_io_channel_unix_get_fd(s->fd);
|
||||
g_io_channel_unref(s->fd);
|
||||
close(fd);
|
||||
|
@ -1244,6 +1262,7 @@ static void pty_chr_close(struct CharDriverState *chr)
|
|||
g_source_remove(s->timer_tag);
|
||||
s->timer_tag = 0;
|
||||
}
|
||||
qemu_mutex_unlock(&chr->chr_write_lock);
|
||||
g_free(s);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue