summaryrefslogtreecommitdiffstats
path: root/hw/scsi
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-11-13 15:44:16 +0000
committerPeter Maydell <peter.maydell@linaro.org>2014-11-13 15:44:16 +0000
commitc52e67924fbdadfa00668248f5c075542943c54c (patch)
tree212dd98dc898ca506ea89b2ba952ea9a94491eec /hw/scsi
parentb56cb288954d900dec79cc55128efa61bebf6178 (diff)
parent3ef0eab178e5120a0e1c079d163d5c71689d9b71 (diff)
downloadhqemu-c52e67924fbdadfa00668248f5c075542943c54c.zip
hqemu-c52e67924fbdadfa00668248f5c075542943c54c.tar.gz
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
x86 and SCSI fixes. I left out the APIC device model patches, pending confirmation from the submitter that they really fix QNX. # gpg: Signature made Thu 13 Nov 2014 15:13:38 GMT using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: acpi: accurate overflow check smbios: change 'ram_addr_t' variables to 'uint64_t' kvmclock: Add comment explaining why we need cpu_clean_all_dirty() target-i386: fix Coverity complaints about overflows apic_common: migrate missing fields target-i386: eliminate dead code and hoist common code out of "if" virtio-scsi: Fix comment for VirtIOSCSIReq virtio-scsi: dataplane: suppress guest notification esp: Do not overwrite ESP_TCHI after reset virtio-scsi: dataplane: fix allocation for 'cmd_vrings' esp: fix coding standards virtio-scsi: work around bug in old BIOSes esp-pci: fixup deadlock with linux Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/scsi')
-rw-r--r--hw/scsi/esp-pci.c3
-rw-r--r--hw/scsi/esp.c11
-rw-r--r--hw/scsi/virtio-scsi-dataplane.c9
-rw-r--r--hw/scsi/virtio-scsi.c17
4 files changed, 36 insertions, 4 deletions
diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
index 82795e6..00b7297 100644
--- a/hw/scsi/esp-pci.c
+++ b/hw/scsi/esp-pci.c
@@ -268,6 +268,9 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
/* update status registers */
pci->dma_regs[DMA_WBC] -= len;
pci->dma_regs[DMA_WAC] += len;
+ if (pci->dma_regs[DMA_WBC] == 0) {
+ pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
+ }
}
static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len)
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 5ab44d8..272d13d 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -364,7 +364,7 @@ void esp_hard_reset(ESPState *s)
{
memset(s->rregs, 0, ESP_REGS);
memset(s->wregs, 0, ESP_REGS);
- s->rregs[ESP_TCHI] = s->chip_id;
+ s->tchi_written = 0;
s->ti_size = 0;
s->ti_rptr = 0;
s->ti_wptr = 0;
@@ -422,6 +422,11 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
esp_lower_irq(s);
return old_val;
+ case ESP_TCHI:
+ /* Return the unique id if the value has never been written */
+ if (!s->tchi_written) {
+ return s->chip_id;
+ }
default:
break;
}
@@ -432,9 +437,11 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
{
trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
switch (saddr) {
+ case ESP_TCHI:
+ s->tchi_written = true;
+ /* fall through */
case ESP_TCLO:
case ESP_TCMID:
- case ESP_TCHI:
s->rregs[ESP_RSTAT] &= ~STAT_TC;
break;
case ESP_FIFO:
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index 9651e6f..03a1e8c 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -92,9 +92,14 @@ VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s,
void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
{
+ VirtIODevice *vdev = VIRTIO_DEVICE(req->vring->parent);
+
vring_push(&req->vring->vring, &req->elem,
req->qsgl.size + req->resp_iov.size);
- event_notifier_set(&req->vring->guest_notifier);
+
+ if (vring_should_notify(vdev, &req->vring->vring)) {
+ event_notifier_set(&req->vring->guest_notifier);
+ }
}
static void virtio_scsi_iothread_handle_ctrl(EventNotifier *notifier)
@@ -230,7 +235,7 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s)
if (!s->event_vring) {
goto fail_vrings;
}
- s->cmd_vrings = g_malloc0(sizeof(VirtIOSCSIVring) * vs->conf.num_queues);
+ s->cmd_vrings = g_new(VirtIOSCSIVring *, vs->conf.num_queues);
for (i = 0; i < vs->conf.num_queues; i++) {
s->cmd_vrings[i] =
virtio_scsi_vring_init(s, vs->cmd_vqs[i],
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index fdcacfd..ef48550 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -118,6 +118,7 @@ static size_t qemu_sgl_concat(VirtIOSCSIReq *req, struct iovec *iov,
static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
unsigned req_size, unsigned resp_size)
{
+ VirtIODevice *vdev = (VirtIODevice *) req->dev;
size_t in_size, out_size;
if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
@@ -130,8 +131,24 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
resp_size) < resp_size) {
return -EINVAL;
}
+
req->resp_size = resp_size;
+ /* Old BIOSes left some padding by mistake after the req_size/resp_size.
+ * As a workaround, always consider the first buffer as the virtio-scsi
+ * request/response, making the payload start at the second element
+ * of the iovec.
+ *
+ * The actual length of the response header, stored in req->resp_size,
+ * does not change.
+ *
+ * TODO: always disable this workaround for virtio 1.0 devices.
+ */
+ if ((vdev->guest_features & VIRTIO_F_ANY_LAYOUT) == 0) {
+ req_size = req->elem.out_sg[0].iov_len;
+ resp_size = req->elem.in_sg[0].iov_len;
+ }
+
out_size = qemu_sgl_concat(req, req->elem.out_sg,
&req->elem.out_addr[0], req->elem.out_num,
req_size);
OpenPOWER on IntegriCloud