aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/omap2.c8
-rw-r--r--hw/arm/pxa2xx.c4
-rw-r--r--hw/arm/strongarm.c4
-rw-r--r--hw/char/bcm2835_aux.c4
-rw-r--r--hw/char/debugcon.c4
-rw-r--r--hw/char/digic-uart.c2
-rw-r--r--hw/char/escc.c4
-rw-r--r--hw/char/etraxfs_ser.c4
-rw-r--r--hw/char/exynos4210_uart.c4
-rw-r--r--hw/char/grlib_apbuart.c4
-rw-r--r--hw/char/imx_serial.c4
-rw-r--r--hw/char/ipoctal232.c4
-rw-r--r--hw/char/lm32_juart.c2
-rw-r--r--hw/char/lm32_uart.c2
-rw-r--r--hw/char/mcf_uart.c4
-rw-r--r--hw/char/parallel.c4
-rw-r--r--hw/char/pl011.c4
-rw-r--r--hw/char/sclpconsole-lm.c25
-rw-r--r--hw/char/sclpconsole.c2
-rw-r--r--hw/char/sh_serial.c4
-rw-r--r--hw/char/spapr_vty.c5
-rw-r--r--hw/char/stm32f2xx_usart.c2
-rw-r--r--hw/char/virtio-console.c21
-rw-r--r--hw/char/xilinx_uartlite.c4
-rw-r--r--hw/dma/i8257.c2
-rw-r--r--hw/i386/kvm/apic.c27
-rw-r--r--hw/ipmi/ipmi_bmc_extern.c8
-rw-r--r--hw/scsi/lsi53c895a.c280
-rw-r--r--hw/scsi/megasas.c6
-rw-r--r--hw/scsi/mptconfig.c6
-rw-r--r--hw/scsi/scsi-disk.c4
-rw-r--r--hw/scsi/vmw_pvscsi.c30
-rw-r--r--hw/usb/ccid-card-passthru.c7
-rw-r--r--hw/usb/dev-serial.c4
34 files changed, 351 insertions, 152 deletions
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
index 3a0d77714a..7e11c65cba 100644
--- a/hw/arm/omap2.c
+++ b/hw/arm/omap2.c
@@ -769,14 +769,16 @@ static void omap_sti_fifo_write(void *opaque, hwaddr addr,
if (ch == STI_TRACE_CONTROL_CHANNEL) {
/* Flush channel <i>value</i>. */
- qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, (const uint8_t *) "\r", 1);
} else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
if (value == 0xc0 || value == 0xc3) {
/* Open channel <i>ch</i>. */
} else if (value == 0x00)
- qemu_chr_fe_write(s->chr, (const uint8_t *) "\n", 1);
+ qemu_chr_fe_write_all(s->chr, (const uint8_t *) "\n", 1);
else
- qemu_chr_fe_write(s->chr, &byte, 1);
+ qemu_chr_fe_write_all(s->chr, &byte, 1);
}
}
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index cb55704687..0241e07d84 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1903,7 +1903,9 @@ static void pxa2xx_fir_write(void *opaque, hwaddr addr,
else
ch = ~value;
if (s->chr && s->enable && (s->control[0] & (1 << 3))) /* TXE */
- qemu_chr_fe_write(s->chr, &ch, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &ch, 1);
break;
case ICSR0:
s->status[0] &= ~(value & 0x66);
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index f1b2c6c966..021cbf9a0f 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -1108,7 +1108,9 @@ static void strongarm_uart_tx(void *opaque)
if (s->utcr3 & UTCR3_LBM) /* loopback */ {
strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1);
} else if (s->chr) {
- qemu_chr_fe_write(s->chr, &s->tx_fifo[s->tx_start], 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &s->tx_fifo[s->tx_start], 1);
}
s->tx_start = (s->tx_start + 1) % 8;
diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c
index 319f1652f6..f7a845d3e2 100644
--- a/hw/char/bcm2835_aux.c
+++ b/hw/char/bcm2835_aux.c
@@ -169,7 +169,9 @@ static void bcm2835_aux_write(void *opaque, hwaddr offset, uint64_t value,
/* "DLAB bit set means access baudrate register" is NYI */
ch = value;
if (s->chr) {
- qemu_chr_fe_write(s->chr, &ch, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &ch, 1);
}
break;
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index e7f025ec67..4402033861 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -60,7 +60,9 @@ static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val,
printf(" [debugcon: write addr=0x%04" HWADDR_PRIx " val=0x%02" PRIx64 "]\n", addr, val);
#endif
- qemu_chr_fe_write(s->chr, &ch, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &ch, 1);
}
diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c
index c7604e6766..e96a9b2d8d 100644
--- a/hw/char/digic-uart.c
+++ b/hw/char/digic-uart.c
@@ -77,6 +77,8 @@ static void digic_uart_write(void *opaque, hwaddr addr, uint64_t value,
switch (addr) {
case R_TX:
if (s->chr) {
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
}
break;
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 31a5f902f9..aa1739762b 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -557,7 +557,9 @@ static void escc_mem_write(void *opaque, hwaddr addr,
s->tx = val;
if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
if (s->chr)
- qemu_chr_fe_write(s->chr, &s->tx, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &s->tx, 1);
else if (s->type == kbd && !s->disabled) {
handle_kbd_command(s, val);
}
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index 04ca04fe2c..c99cc5d130 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -126,7 +126,9 @@ ser_write(void *opaque, hwaddr addr,
switch (addr)
{
case RW_DOUT:
- qemu_chr_fe_write(s->chr, &ch, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &ch, 1);
s->regs[R_INTR] |= 3;
s->pending_tx = 1;
s->regs[addr] = value;
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index 885ecc027b..1107578138 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -387,7 +387,9 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset,
s->reg[I_(UTRSTAT)] &= ~(UTRSTAT_TRANSMITTER_EMPTY |
UTRSTAT_Tx_BUFFER_EMPTY);
ch = (uint8_t)val;
- qemu_chr_fe_write(s->chr, &ch, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &ch, 1);
#if DEBUG_Tx_DATA
fprintf(stderr, "%c", ch);
#endif
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index 871524c82f..778148a15e 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -203,7 +203,9 @@ static void grlib_apbuart_write(void *opaque, hwaddr addr,
/* Transmit when character device available and transmitter enabled */
if ((uart->chr) && (uart->control & UART_TRANSMIT_ENABLE)) {
c = value & 0xFF;
- qemu_chr_fe_write(uart->chr, &c, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(uart->chr, &c, 1);
/* Generate interrupt */
if (uart->control & UART_TRANSMIT_INTERRUPT) {
qemu_irq_pulse(uart->irq);
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index 44856d671e..5c3fa61e4c 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -182,7 +182,9 @@ static void imx_serial_write(void *opaque, hwaddr offset,
ch = value;
if (s->ucr2 & UCR2_TXEN) {
if (s->chr) {
- qemu_chr_fe_write(s->chr, &ch, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &ch, 1);
}
s->usr1 &= ~USR1_TRDY;
imx_update(s);
diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
index 9ead32af60..2859fdd7fb 100644
--- a/hw/char/ipoctal232.c
+++ b/hw/char/ipoctal232.c
@@ -360,7 +360,9 @@ static void io_write(IPackDevice *ip, uint8_t addr, uint16_t val)
DPRINTF("Write THR%c (0x%x)\n", channel + 'a', reg);
if (ch->dev) {
uint8_t thr = reg;
- qemu_chr_fe_write(ch->dev, &thr, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(ch->dev, &thr, 1);
}
} else {
DPRINTF("Write THR%c (0x%x), Tx disabled\n", channel + 'a', reg);
diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
index 28c2cf702d..cb1ac76731 100644
--- a/hw/char/lm32_juart.c
+++ b/hw/char/lm32_juart.c
@@ -76,6 +76,8 @@ void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx)
s->jtx = jtx;
if (s->chr) {
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
}
}
diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
index b5c760dda3..be93697a39 100644
--- a/hw/char/lm32_uart.c
+++ b/hw/char/lm32_uart.c
@@ -178,6 +178,8 @@ static void uart_write(void *opaque, hwaddr addr,
switch (addr) {
case R_RXTX:
if (s->chr) {
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
}
break;
diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c
index 3c0438fd79..c184859c83 100644
--- a/hw/char/mcf_uart.c
+++ b/hw/char/mcf_uart.c
@@ -114,7 +114,9 @@ static void mcf_uart_do_tx(mcf_uart_state *s)
{
if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) {
if (s->chr)
- qemu_chr_fe_write(s->chr, (unsigned char *)&s->tb, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, (unsigned char *)&s->tb, 1);
s->sr |= MCF_UART_TxEMP;
}
if (s->tx_enabled) {
diff --git a/hw/char/parallel.c b/hw/char/parallel.c
index fa085667ff..da22e36356 100644
--- a/hw/char/parallel.c
+++ b/hw/char/parallel.c
@@ -129,7 +129,9 @@ parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val)
if (val & PARA_CTR_STROBE) {
s->status &= ~PARA_STS_BUSY;
if ((s->control & PARA_CTR_STROBE) == 0)
- qemu_chr_fe_write(s->chr, &s->dataw, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &s->dataw, 1);
} else {
if (s->control & PARA_CTR_INTEN) {
s->irq_pending = 1;
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index c0fbf8a874..786e605fdd 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -146,7 +146,9 @@ static void pl011_write(void *opaque, hwaddr offset,
/* ??? Check if transmitter is enabled. */
ch = value;
if (s->chr)
- qemu_chr_fe_write(s->chr, &ch, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &ch, 1);
s->int_level |= PL011_INT_TX;
pl011_update(s);
break;
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index a22ad8d016..9a563269e6 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -89,7 +89,9 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
scon->buf[scon->length] = *buf;
scon->length += 1;
if (scon->echo) {
- qemu_chr_fe_write(scon->chr, buf, size);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(scon->chr, buf, size);
}
}
@@ -191,9 +193,6 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
*/
static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len)
{
- int ret = 0;
- const uint8_t *buf_offset;
-
SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
if (!scon->chr) {
@@ -201,21 +200,9 @@ static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len)
return len;
}
- buf_offset = buf;
- while (len > 0) {
- ret = qemu_chr_fe_write(scon->chr, buf, len);
- if (ret == 0) {
- /* a pty doesn't seem to be connected - no error */
- len = 0;
- } else if (ret == -EAGAIN || (ret > 0 && ret < len)) {
- len -= ret;
- buf_offset += ret;
- } else {
- len = 0;
- }
- }
-
- return ret;
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ return qemu_chr_fe_write_all(scon->chr, buf, len);
}
static int process_mdb(SCLPEvent *event, MDBO *mdbo)
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index d22464826b..a75ad4f60a 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -168,6 +168,8 @@ static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf,
return len;
}
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
return qemu_chr_fe_write_all(scon->chr, buf, len);
}
diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c
index 4c55dcb7dc..97ce5629a4 100644
--- a/hw/char/sh_serial.c
+++ b/hw/char/sh_serial.c
@@ -111,7 +111,9 @@ static void sh_serial_write(void *opaque, hwaddr offs,
case 0x0c: /* FTDR / TDR */
if (s->chr) {
ch = val;
- qemu_chr_fe_write(s->chr, &ch, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &ch, 1);
}
s->dr = val;
s->flags &= ~SH_SERIAL_FLAG_TDE;
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index 3498d7b052..9aeafc0c42 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -60,8 +60,9 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
{
VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
- /* FIXME: should check the qemu_chr_fe_write() return value */
- qemu_chr_fe_write(dev->chardev, buf, len);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(dev->chardev, buf, len);
}
static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c
index 15657abda9..4c6640dbe9 100644
--- a/hw/char/stm32f2xx_usart.c
+++ b/hw/char/stm32f2xx_usart.c
@@ -153,6 +153,8 @@ static void stm32f2xx_usart_write(void *opaque, hwaddr addr,
if (value < 0xF000) {
ch = value;
if (s->chr) {
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
}
s->usart_sr |= USART_SR_TC;
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index 4f0e03d3b7..d44c18c128 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -68,6 +68,27 @@ static ssize_t flush_buf(VirtIOSerialPort *port,
*/
if (ret < 0)
ret = 0;
+
+ /* XXX we should be queuing data to send later for the
+ * console devices too rather than silently dropping
+ * console data on EAGAIN. The Linux virtio-console
+ * hvc driver though does sends with spinlocks held,
+ * so if we enable throttling that'll stall the entire
+ * guest kernel, not merely the process writing to the
+ * console.
+ *
+ * While we could queue data for later write without
+ * enabling throttling, this would result in the guest
+ * being able to trigger arbitrary memory usage in QEMU
+ * buffering data for later writes.
+ *
+ * So fixing this problem likely requires fixing the
+ * Linux virtio-console hvc driver to not hold spinlocks
+ * while writing, and instead merely block the process
+ * that's writing. QEMU would then need some way to detect
+ * if the guest had the fixed driver too, before we can
+ * use throttling on host side.
+ */
if (!k->is_console) {
virtio_serial_throttle_port(port, true);
if (!vcon->watch) {
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index 4847efb29f..3766dc2c5b 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -144,7 +144,9 @@ uart_write(void *opaque, hwaddr addr,
case R_TX:
if (s->chr)
- qemu_chr_fe_write(s->chr, &ch, 1);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->chr, &ch, 1);
s->regs[addr] = value;
diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c
index bffbdea0ca..8bd82e8bc8 100644
--- a/hw/dma/i8257.c
+++ b/hw/dma/i8257.c
@@ -600,6 +600,8 @@ static void i8257_class_init(ObjectClass *klass, void *data)
idc->release_DREQ = i8257_dma_release_DREQ;
idc->schedule = i8257_dma_schedule;
idc->register_channel = i8257_dma_register_channel;
+ /* Reason: needs to be wired up by isa_bus_dma() to work */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo i8257_info = {
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index 2bd0de82b4..5d140b9341 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -28,9 +28,8 @@ static inline uint32_t kvm_apic_get_reg(struct kvm_lapic_state *kapic,
return *((uint32_t *)(kapic->regs + (reg_id << 4)));
}
-void kvm_put_apic_state(DeviceState *dev, struct kvm_lapic_state *kapic)
+static void kvm_put_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic)
{
- APICCommonState *s = APIC_COMMON(dev);
int i;
memset(kapic, 0, sizeof(*kapic));
@@ -125,6 +124,27 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
}
}
+static void kvm_apic_put(void *data)
+{
+ APICCommonState *s = data;
+ struct kvm_lapic_state kapic;
+ int ret;
+
+ kvm_put_apic_state(s, &kapic);
+
+ ret = kvm_vcpu_ioctl(CPU(s->cpu), KVM_SET_LAPIC, &kapic);
+ if (ret < 0) {
+ fprintf(stderr, "KVM_SET_LAPIC failed: %s\n", strerror(ret));
+ abort();
+ }
+}
+
+static void kvm_apic_post_load(APICCommonState *s)
+{
+ fprintf(stderr, "%s: Yeh\n", __func__);
+ run_on_cpu(CPU(s->cpu), kvm_apic_put, s);
+}
+
static void do_inject_external_nmi(void *data)
{
APICCommonState *s = data;
@@ -178,6 +198,8 @@ static void kvm_apic_reset(APICCommonState *s)
{
/* Not used by KVM, which uses the CPU mp_state instead. */
s->wait_for_sipi = 0;
+
+ run_on_cpu(CPU(s->cpu), kvm_apic_put, s);
}
static void kvm_apic_realize(DeviceState *dev, Error **errp)
@@ -206,6 +228,7 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data)
k->set_base = kvm_apic_set_base;
k->set_tpr = kvm_apic_set_tpr;
k->get_tpr = kvm_apic_get_tpr;
+ k->post_load = kvm_apic_post_load;
k->enable_tpr_reporting = kvm_apic_enable_tpr_reporting;
k->vapic_base_update = kvm_apic_vapic_base_update;
k->external_nmi = kvm_apic_external_nmi;
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
index 5b73983e7d..d93e3f3426 100644
--- a/hw/ipmi/ipmi_bmc_extern.c
+++ b/hw/ipmi/ipmi_bmc_extern.c
@@ -100,12 +100,16 @@ ipmb_checksum(const unsigned char *data, int size, unsigned char start)
static void continue_send(IPMIBmcExtern *ibe)
{
+ int ret;
if (ibe->outlen == 0) {
goto check_reset;
}
send:
- ibe->outpos += qemu_chr_fe_write(ibe->chr, ibe->outbuf + ibe->outpos,
- ibe->outlen - ibe->outpos);
+ ret = qemu_chr_fe_write(ibe->chr, ibe->outbuf + ibe->outpos,
+ ibe->outlen - ibe->outpos);
+ if (ret > 0) {
+ ibe->outpos += ret;
+ }
if (ibe->outpos < ibe->outlen) {
/* Not fully transmitted, try again in a 10ms */
timer_mod_ns(ibe->extern_timer,
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index df205cdafe..feb1191315 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -19,6 +19,7 @@
#include "hw/pci/pci.h"
#include "hw/scsi/scsi.h"
#include "sysemu/dma.h"
+#include "qemu/log.h"
//#define DEBUG_LSI
//#define DEBUG_LSI_REG
@@ -34,6 +35,21 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__); exit(1);} while
do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
#endif
+static const char *names[] = {
+ "SCNTL0", "SCNTL1", "SCNTL2", "SCNTL3", "SCID", "SXFER", "SDID", "GPREG",
+ "SFBR", "SOCL", "SSID", "SBCL", "DSTAT", "SSTAT0", "SSTAT1", "SSTAT2",
+ "DSA0", "DSA1", "DSA2", "DSA3", "ISTAT", "0x15", "0x16", "0x17",
+ "CTEST0", "CTEST1", "CTEST2", "CTEST3", "TEMP0", "TEMP1", "TEMP2", "TEMP3",
+ "DFIFO", "CTEST4", "CTEST5", "CTEST6", "DBC0", "DBC1", "DBC2", "DCMD",
+ "DNAD0", "DNAD1", "DNAD2", "DNAD3", "DSP0", "DSP1", "DSP2", "DSP3",
+ "DSPS0", "DSPS1", "DSPS2", "DSPS3", "SCRATCHA0", "SCRATCHA1", "SCRATCHA2", "SCRATCHA3",
+ "DMODE", "DIEN", "SBR", "DCNTL", "ADDER0", "ADDER1", "ADDER2", "ADDER3",
+ "SIEN0", "SIEN1", "SIST0", "SIST1", "SLPAR", "0x45", "MACNTL", "GPCNTL",
+ "STIME0", "STIME1", "RESPID", "0x4b", "STEST0", "STEST1", "STEST2", "STEST3",
+ "SIDL", "0x51", "0x52", "0x53", "SODL", "0x55", "0x56", "0x57",
+ "SBDL", "0x59", "0x5a", "0x5b", "SCRATCHB0", "SCRATCHB1", "SCRATCHB2", "SCRATCHB3",
+};
+
#define LSI_MAX_DEVS 7
#define LSI_SCNTL0_TRG 0x01
@@ -194,6 +210,7 @@ typedef struct {
MemoryRegion mmio_io;
MemoryRegion ram_io;
MemoryRegion io_io;
+ AddressSpace pci_io_as;
int carry; /* ??? Should this be an a visible register somewhere? */
int status;
@@ -309,7 +326,7 @@ static void lsi_soft_reset(LSIState *s)
s->istat0 = 0;
s->istat1 = 0;
s->dcmd = 0x40;
- s->dstat = LSI_DSTAT_DFE;
+ s->dstat = 0;
s->dien = 0;
s->sist0 = 0;
s->sist1 = 0;
@@ -391,6 +408,30 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val);
static void lsi_execute_script(LSIState *s);
static void lsi_reselect(LSIState *s, lsi_request *p);
+static inline int lsi_mem_read(LSIState *s, dma_addr_t addr,
+ void *buf, dma_addr_t len)
+{
+ if (s->dmode & LSI_DMODE_SIOM) {
+ address_space_read(&s->pci_io_as, addr, MEMTXATTRS_UNSPECIFIED,
+ buf, len);
+ return 0;
+ } else {
+ return pci_dma_read(PCI_DEVICE(s), addr, buf, len);
+ }
+}
+
+static inline int lsi_mem_write(LSIState *s, dma_addr_t addr,
+ const void *buf, dma_addr_t len)
+{
+ if (s->dmode & LSI_DMODE_DIOM) {
+ address_space_write(&s->pci_io_as, addr, MEMTXATTRS_UNSPECIFIED,
+ buf, len);
+ return 0;
+ } else {
+ return pci_dma_write(PCI_DEVICE(s), addr, buf, len);
+ }
+}
+
static inline uint32_t read_dword(LSIState *s, uint32_t addr)
{
uint32_t buf;
@@ -534,7 +575,6 @@ static void lsi_bad_selection(LSIState *s, uint32_t id)
/* Initiate a SCSI layer data transfer. */
static void lsi_do_dma(LSIState *s, int out)
{
- PCIDevice *pci_dev;
uint32_t count;
dma_addr_t addr;
SCSIDevice *dev;
@@ -546,7 +586,6 @@ static void lsi_do_dma(LSIState *s, int out)
return;
}
- pci_dev = PCI_DEVICE(s);
dev = s->current->req->dev;
assert(dev);
@@ -572,9 +611,9 @@ static void lsi_do_dma(LSIState *s, int out)
}
/* ??? Set SFBR to first data byte. */
if (out) {
- pci_dma_read(pci_dev, addr, s->current->dma_buf, count);
+ lsi_mem_read(s, addr, s->current->dma_buf, count);
} else {
- pci_dma_write(pci_dev, addr, s->current->dma_buf, count);
+ lsi_mem_write(s, addr, s->current->dma_buf, count);
}
s->current->dma_len -= count;
if (s->current->dma_len == 0) {
@@ -1006,15 +1045,14 @@ bad:
#define LSI_BUF_SIZE 4096
static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count)
{
- PCIDevice *d = PCI_DEVICE(s);
int n;
uint8_t buf[LSI_BUF_SIZE];
DPRINTF("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count);
while (count) {
n = (count > LSI_BUF_SIZE) ? LSI_BUF_SIZE : count;
- pci_dma_read(d, src, buf, n);
- pci_dma_write(d, dest, buf, n);
+ lsi_mem_read(s, src, buf, n);
+ lsi_mem_write(s, dest, buf, n);
src += n;
dest += n;
count -= n;
@@ -1480,155 +1518,200 @@ again:
static uint8_t lsi_reg_readb(LSIState *s, int offset)
{
- uint8_t tmp;
+ uint8_t ret;
+
#define CASE_GET_REG24(name, addr) \
- case addr: return s->name & 0xff; \
- case addr + 1: return (s->name >> 8) & 0xff; \
- case addr + 2: return (s->name >> 16) & 0xff;
+ case addr: ret = s->name & 0xff; break; \
+ case addr + 1: ret = (s->name >> 8) & 0xff; break; \
+ case addr + 2: ret = (s->name >> 16) & 0xff; break;
#define CASE_GET_REG32(name, addr) \
- case addr: return s->name & 0xff; \
- case addr + 1: return (s->name >> 8) & 0xff; \
- case addr + 2: return (s->name >> 16) & 0xff; \
- case addr + 3: return (s->name >> 24) & 0xff;
+ case addr: ret = s->name & 0xff; break; \
+ case addr + 1: ret = (s->name >> 8) & 0xff; break; \
+ case addr + 2: ret = (s->name >> 16) & 0xff; break; \
+ case addr + 3: ret = (s->name >> 24) & 0xff; break;
-#ifdef DEBUG_LSI_REG
- DPRINTF("Read reg %x\n", offset);
-#endif
switch (offset) {
case 0x00: /* SCNTL0 */
- return s->scntl0;
+ ret = s->scntl0;
+ break;
case 0x01: /* SCNTL1 */
- return s->scntl1;
+ ret = s->scntl1;
+ break;
case 0x02: /* SCNTL2 */
- return s->scntl2;
+ ret = s->scntl2;
+ break;
case 0x03: /* SCNTL3 */
- return s->scntl3;
+ ret = s->scntl3;
+ break;
case 0x04: /* SCID */
- return s->scid;
+ ret = s->scid;
+ break;
case 0x05: /* SXFER */
- return s->sxfer;
+ ret = s->sxfer;
+ break;
case 0x06: /* SDID */
- return s->sdid;
+ ret = s->sdid;
+ break;
case 0x07: /* GPREG0 */
- return 0x7f;
+ ret = 0x7f;
+ break;
case 0x08: /* Revision ID */
- return 0x00;
+ ret = 0x00;
+ break;
case 0x09: /* SOCL */
- return s->socl;
+ ret = s->socl;
+ break;
case 0xa: /* SSID */
- return s->ssid;
+ ret = s->ssid;
+ break;
case 0xb: /* SBCL */
/* ??? This is not correct. However it's (hopefully) only
used for diagnostics, so should be ok. */
- return 0;
+ ret = 0;
+ break;
case 0xc: /* DSTAT */
- tmp = s->dstat | LSI_DSTAT_DFE;
+ ret = s->dstat | LSI_DSTAT_DFE;
if ((s->istat0 & LSI_ISTAT0_INTF) == 0)
s->dstat = 0;
lsi_update_irq(s);
- return tmp;
+ break;
case 0x0d: /* SSTAT0 */
- return s->sstat0;
+ ret = s->sstat0;
+ break;
case 0x0e: /* SSTAT1 */
- return s->sstat1;
+ ret = s->sstat1;
+ break;
case 0x0f: /* SSTAT2 */
- return s->scntl1 & LSI_SCNTL1_CON ? 0 : 2;
+ ret = s->scntl1 & LSI_SCNTL1_CON ? 0 : 2;
+ break;
CASE_GET_REG32(dsa, 0x10)
case 0x14: /* ISTAT0 */
- return s->istat0;
+ ret = s->istat0;
+ break;
case 0x15: /* ISTAT1 */
- return s->istat1;
+ ret = s->istat1;
+ break;
case 0x16: /* MBOX0 */
- return s->mbox0;
+ ret = s->mbox0;
+ break;
case 0x17: /* MBOX1 */
- return s->mbox1;
+ ret = s->mbox1;
+ break;
case 0x18: /* CTEST0 */
- return 0xff;
+ ret = 0xff;
+ break;
case 0x19: /* CTEST1 */
- return 0;
+ ret = 0;
+ break;
case 0x1a: /* CTEST2 */
- tmp = s->ctest2 | LSI_CTEST2_DACK | LSI_CTEST2_CM;
+ ret = s->ctest2 | LSI_CTEST2_DACK | LSI_CTEST2_CM;
if (s->istat0 & LSI_ISTAT0_SIGP) {
s->istat0 &= ~LSI_ISTAT0_SIGP;
- tmp |= LSI_CTEST2_SIGP;
+ ret |= LSI_CTEST2_SIGP;
}
- return tmp;
+ break;
case 0x1b: /* CTEST3 */
- return s->ctest3;
+ ret = s->ctest3;
+ break;
CASE_GET_REG32(temp, 0x1c)
case 0x20: /* DFIFO */
- return 0;
+ ret = 0;
+ break;
case 0x21: /* CTEST4 */
- return s->ctest4;
+ ret = s->ctest4;
+ break;
case 0x22: /* CTEST5 */
- return s->ctest5;
+ ret = s->ctest5;
+ break;
case 0x23: /* CTEST6 */
- return 0;
+ ret = 0;
+ break;
CASE_GET_REG24(dbc, 0x24)
case 0x27: /* DCMD */
- return s->dcmd;
+ ret = s->dcmd;
+ break;
CASE_GET_REG32(dnad, 0x28)
CASE_GET_REG32(dsp, 0x2c)
CASE_GET_REG32(dsps, 0x30)
CASE_GET_REG32(scratch[0], 0x34)
case 0x38: /* DMODE */
- return s->dmode;
+ ret = s->dmode;
+ break;
case 0x39: /* DIEN */
- return s->dien;
+ ret = s->dien;
+ break;
case 0x3a: /* SBR */
- return s->sbr;
+ ret = s->sbr;
+ break;
case 0x3b: /* DCNTL */
- return s->dcntl;
+ ret = s->dcntl;
+ break;
/* ADDER Output (Debug of relative jump address) */
CASE_GET_REG32(adder, 0x3c)
case 0x40: /* SIEN0 */
- return s->sien0;
+ ret = s->sien0;
+ break;
case 0x41: /* SIEN1 */
- return s->sien1;
+ ret = s->sien1;
+ break;
case 0x42: /* SIST0 */
- tmp = s->sist0;
+ ret = s->sist0;
s->sist0 = 0;
lsi_update_irq(s);
- return tmp;
+ break;
case 0x43: /* SIST1 */
- tmp = s->sist1;
+ ret = s->sist1;
s->sist1 = 0;
lsi_update_irq(s);
- return tmp;
+ break;
case 0x46: /* MACNTL */
- return 0x0f;
+ ret = 0x0f;
+ break;
case 0x47: /* GPCNTL0 */
- return 0x0f;
+ ret = 0x0f;
+ break;
case 0x48: /* STIME0 */
- return s->stime0;
+ ret = s->stime0;
+ break;
case 0x4a: /* RESPID0 */
- return s->respid0;
+ ret = s->respid0;
+ break;
case 0x4b: /* RESPID1 */
- return s->respid1;
+ ret = s->respid1;
+ break;
case 0x4d: /* STEST1 */
- return s->stest1;
+ ret = s->stest1;
+ break;
case 0x4e: /* STEST2 */
- return s->stest2;
+ ret = s->stest2;
+ break;
case 0x4f: /* STEST3 */
- return s->stest3;
+ ret = s->stest3;
+ break;
case 0x50: /* SIDL */
/* This is needed by the linux drivers. We currently only update it
during the MSG IN phase. */
- return s->sidl;
+ ret = s->sidl;
+ break;
case 0x52: /* STEST4 */
- return 0xe0;
+ ret = 0xe0;
+ break;
case 0x56: /* CCNTL0 */
- return s->ccntl0;
+ ret = s->ccntl0;
+ break;
case 0x57: /* CCNTL1 */
- return s->ccntl1;
+ ret = s->ccntl1;
+ break;
case 0x58: /* SBDL */
/* Some drivers peek at the data bus during the MSG IN phase. */
if ((s->sstat1 & PHASE_MASK) == PHASE_MI)
return s->msg[0];
- return 0;
+ ret = 0;
+ break;
case 0x59: /* SBDL high */
- return 0;
+ ret = 0;
+ break;
CASE_GET_REG32(mmrs, 0xa0)
CASE_GET_REG32(mmws, 0xa4)
CASE_GET_REG32(sfs, 0xa8)
@@ -1643,18 +1726,34 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
CASE_GET_REG32(ia, 0xd4)
CASE_GET_REG32(sbc, 0xd8)
CASE_GET_REG32(csbc, 0xdc)
- }
- if (offset >= 0x5c && offset < 0xa0) {
+ case 0x5c ... 0x9f:
+ {
int n;
int shift;
n = (offset - 0x58) >> 2;
shift = (offset & 3) * 8;
- return (s->scratch[n] >> shift) & 0xff;
+ ret = (s->scratch[n] >> shift) & 0xff;
+ break;
+ }
+ default:
+ {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "lsi_scsi: invalid read from reg %s %x\n",
+ offset < ARRAY_SIZE(names) ? names[offset] : "???",
+ offset);
+ ret = 0xff;
+ break;
+ }
}
- BADF("readb 0x%x\n", offset);
- exit(1);
#undef CASE_GET_REG24
#undef CASE_GET_REG32
+
+#ifdef DEBUG_LSI_REG
+ DPRINTF("Read reg %s %x = %02x\n",
+ offset < ARRAY_SIZE(names) ? names[offset] : "???", offset, ret);
+#endif
+
+ return ret;
}
static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
@@ -1671,7 +1770,8 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;
#ifdef DEBUG_LSI_REG
- DPRINTF("Write reg %x = %02x\n", offset, val);
+ DPRINTF("Write reg %s %x = %02x\n",
+ offset < ARRAY_SIZE(names) ? names[offset] : "???", offset, val);
#endif
switch (offset) {
case 0x00: /* SCNTL0 */
@@ -1799,9 +1899,6 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
CASE_SET_REG32(dsps, 0x30)
CASE_SET_REG32(scratch[0], 0x34)
case 0x38: /* DMODE */
- if (val & (LSI_DMODE_SIOM | LSI_DMODE_DIOM)) {
- BADF("IO mappings not implemented\n");
- }
s->dmode = val;
break;
case 0x39: /* DIEN */
@@ -1886,7 +1983,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
shift = (offset & 3) * 8;
s->scratch[n] = deposit32(s->scratch[n], shift, 8, val);
} else {
- BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "lsi_scsi: invalid write to reg %s %x (0x%02x)\n",
+ offset < ARRAY_SIZE(names) ? names[offset] : "???",
+ offset, val);
}
}
#undef CASE_SET_REG24
@@ -2108,6 +2208,8 @@ static void lsi_scsi_realize(PCIDevice *dev, Error **errp)
memory_region_init_io(&s->io_io, OBJECT(s), &lsi_io_ops, s,
"lsi-io", 256);
+ address_space_init(&s->pci_io_as, pci_address_space_io(dev), "lsi-pci-io");
+
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_io);
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_io);
pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io);
@@ -2119,6 +2221,13 @@ static void lsi_scsi_realize(PCIDevice *dev, Error **errp)
}
}
+static void lsi_scsi_unrealize(DeviceState *dev, Error **errp)
+{
+ LSIState *s = LSI53C895A(dev);
+
+ address_space_destroy(&s->pci_io_as);
+}
+
static void lsi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -2129,6 +2238,7 @@ static void lsi_class_init(ObjectClass *klass, void *data)
k->device_id = PCI_DEVICE_ID_LSI_53C895A;
k->class_id = PCI_CLASS_STORAGE_SCSI;
k->subsystem_id = 0x1000;
+ dc->unrealize = lsi_scsi_unrealize;
dc->reset = lsi_scsi_reset;
dc->vmsd = &vmstate_lsi_scsi;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index e968302fdc..52a41239cf 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1981,7 +1981,11 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr,
break;
}
if (frame_status != MFI_STAT_INVALID_STATUS) {
- cmd->frame->header.cmd_status = frame_status;
+ if (cmd->frame) {
+ cmd->frame->header.cmd_status = frame_status;
+ } else {
+ megasas_frame_set_cmd_status(s, frame_addr, frame_status);
+ }
megasas_unmap_frame(s, cmd);
megasas_complete_frame(s, cmd->context);
}
diff --git a/hw/scsi/mptconfig.c b/hw/scsi/mptconfig.c
index 707185469e..87a416a5cb 100644
--- a/hw/scsi/mptconfig.c
+++ b/hw/scsi/mptconfig.c
@@ -158,7 +158,7 @@ static size_t mptsas_config_pack(uint8_t **data, const char *fmt, ...)
va_end(ap);
if (data) {
- assert(ret < 256 && (ret % 4) == 0);
+ assert(ret / 4 < 256 && (ret % 4) == 0);
stb_p(*data + 1, ret / 4);
}
return ret;
@@ -203,7 +203,7 @@ size_t mptsas_config_manufacturing_1(MPTSASState *s, uint8_t **data, int address
{
/* VPD - all zeros */
return MPTSAS_CONFIG_PACK(1, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
- "s256");
+ "*s256");
}
static
@@ -328,7 +328,7 @@ size_t mptsas_config_ioc_0(MPTSASState *s, uint8_t **data, int address)
return MPTSAS_CONFIG_PACK(0, MPI_CONFIG_PAGETYPE_IOC, 0x01,
"*l*lwwb*b*b*blww",
pcic->vendor_id, pcic->device_id, pcic->revision,
- pcic->subsystem_vendor_id,
+ pcic->class_id, pcic->subsystem_vendor_id,
pcic->subsystem_id);
}
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 99c9d618da..77cba31e30 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -599,8 +599,8 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
}
l = strlen(s->serial);
- if (l > 20) {
- l = 20;
+ if (l > 36) {
+ l = 36;
}
DPRINTF("Inquiry EVPD[Serial number] "
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 5116f4ad68..babac5a68a 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -40,6 +40,8 @@
#define PVSCSI_MAX_DEVS (64)
#define PVSCSI_MSIX_NUM_VECTORS (1)
+#define PVSCSI_MAX_SG_ELEM 2048
+
#define PVSCSI_MAX_CMD_DATA_WORDS \
(sizeof(PVSCSICmdDescSetupRings)/sizeof(uint32_t))
@@ -152,7 +154,7 @@ pvscsi_log2(uint32_t input)
return log;
}
-static int
+static void
pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri)
{
int i;
@@ -160,10 +162,6 @@ pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri)
uint32_t req_ring_size, cmp_ring_size;
m->rs_pa = ri->ringsStatePPN << VMW_PAGE_SHIFT;
- if ((ri->reqRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES)
- || (ri->cmpRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES)) {
- return -1;
- }
req_ring_size = ri->reqRingNumPages * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
cmp_ring_size = ri->cmpRingNumPages * PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE;
txr_len_log2 = pvscsi_log2(req_ring_size - 1);
@@ -195,8 +193,6 @@ pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri)
/* Flush ring state page changes */
smp_wmb();
-
- return 0;
}
static int
@@ -634,17 +630,16 @@ pvscsi_queue_pending_descriptor(PVSCSIState *s, SCSIDevice **d,
static void
pvscsi_convert_sglist(PVSCSIRequest *r)
{
- int chunk_size;
+ uint32_t chunk_size, elmcnt = 0;
uint64_t data_length = r->req.dataLen;
PVSCSISGState sg = r->sg;
- while (data_length) {
- while (!sg.resid) {
+ while (data_length && elmcnt < PVSCSI_MAX_SG_ELEM) {
+ while (!sg.resid && elmcnt++ < PVSCSI_MAX_SG_ELEM) {
pvscsi_get_next_sg_elem(&sg);
trace_pvscsi_convert_sglist(r->req.context, r->sg.dataAddr,
r->sg.resid);
}
- assert(data_length > 0);
- chunk_size = MIN((unsigned) data_length, sg.resid);
+ chunk_size = MIN(data_length, sg.resid);
if (chunk_size) {
qemu_sglist_add(&r->sgl, sg.dataAddr, chunk_size);
}
@@ -746,7 +741,7 @@ pvscsi_dbg_dump_tx_rings_config(PVSCSICmdDescSetupRings *rc)
trace_pvscsi_tx_rings_num_pages("Confirm Ring", rc->cmpRingNumPages);
for (i = 0; i < rc->cmpRingNumPages; i++) {
- trace_pvscsi_tx_rings_ppn("Confirm Ring", rc->reqRingPPNs[i]);
+ trace_pvscsi_tx_rings_ppn("Confirm Ring", rc->cmpRingPPNs[i]);
}
}
@@ -779,11 +774,16 @@ pvscsi_on_cmd_setup_rings(PVSCSIState *s)
trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_RINGS");
- pvscsi_dbg_dump_tx_rings_config(rc);
- if (pvscsi_ring_init_data(&s->rings, rc) < 0) {
+ if (!rc->reqRingNumPages
+ || rc->reqRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES
+ || !rc->cmpRingNumPages
+ || rc->cmpRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES) {
return PVSCSI_COMMAND_PROCESSING_FAILED;
}
+ pvscsi_dbg_dump_tx_rings_config(rc);
+ pvscsi_ring_init_data(&s->rings, rc);
+
s->rings_info_valid = TRUE;
return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
}
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index c0e90e501c..2eacea72f3 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -75,8 +75,11 @@ static void ccid_card_vscard_send_msg(PassthruState *s,
scr_msg_header.type = htonl(type);
scr_msg_header.reader_id = htonl(reader_id);
scr_msg_header.length = htonl(length);
- qemu_chr_fe_write(s->cs, (uint8_t *)&scr_msg_header, sizeof(VSCMsgHeader));
- qemu_chr_fe_write(s->cs, payload, length);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->cs, (uint8_t *)&scr_msg_header,
+ sizeof(VSCMsgHeader));
+ qemu_chr_fe_write_all(s->cs, payload, length);
}
static void ccid_card_vscard_send_apdu(PassthruState *s,
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index ba8538e60e..966ad84b90 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -366,7 +366,9 @@ static void usb_serial_handle_data(USBDevice *dev, USBPacket *p)
goto fail;
for (i = 0; i < p->iov.niov; i++) {
iov = p->iov.iov + i;
- qemu_chr_fe_write(s->cs, iov->iov_base, iov->iov_len);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(s->cs, iov->iov_base, iov->iov_len);
}
p->actual_length = p->iov.size;
break;