diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2012-11-14 08:50:45 -0600 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-11-14 08:50:45 -0600 |
commit | 5f580e9411a24b7decc07013edeb8abf8d5ae25c (patch) | |
tree | b5f0120fc2acc4080d09ecd903c647b4e8140bbd | |
parent | ce5e5b522e8d3b848b6445c34226b69c77c46403 (diff) | |
parent | dd72fdd06268860a24f9f3828efade547ee2e2a9 (diff) |
Merge remote-tracking branch 'bonzini/scsi-next' into staging
* bonzini/scsi-next:
virtio-scsi: use dma_context_memory
dma: Define dma_context_memory and use in sysbus-ohci
megasas: Correct target/lun mapping
scsi-disk: flush cache after disabling it
megasas: do not include block_int.h
scsi: remove superfluous call to scsi_device_set_ua
virtio-scsi: factor checks for VIRTIO_SCSI_S_DRIVER_OK when reporting events
scsi: do not return short responses for emulated commands
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r-- | dma.h | 5 | ||||
-rw-r--r-- | exec.c | 5 | ||||
-rw-r--r-- | hw/megasas.c | 2 | ||||
-rw-r--r-- | hw/mfi.h | 2 | ||||
-rw-r--r-- | hw/scsi-disk.c | 44 | ||||
-rw-r--r-- | hw/usb/hcd-ohci.c | 2 | ||||
-rw-r--r-- | hw/virtio-scsi.c | 10 |
7 files changed, 46 insertions, 24 deletions
@@ -68,6 +68,11 @@ struct DMAContext { DMAUnmapFunc *unmap; }; +/* A global DMA context corresponding to the address_space_memory + * AddressSpace, for sysbus devices which do DMA. + */ +extern DMAContext dma_context_memory; + static inline void dma_barrier(DMAContext *dma, DMADirection dir) { /* @@ -34,6 +34,7 @@ #include "hw/xen.h" #include "qemu-timer.h" #include "memory.h" +#include "dma.h" #include "exec-memory.h" #if defined(CONFIG_USER_ONLY) #include <qemu.h> @@ -103,6 +104,7 @@ static MemoryRegion *system_io; AddressSpace address_space_io; AddressSpace address_space_memory; +DMAContext dma_context_memory; MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty; static MemoryRegion io_mem_subpage_ram; @@ -3294,6 +3296,9 @@ static void memory_map_init(void) memory_listener_register(&core_memory_listener, &address_space_memory); memory_listener_register(&io_memory_listener, &address_space_io); memory_listener_register(&tcg_memory_listener, &address_space_memory); + + dma_context_init(&dma_context_memory, &address_space_memory, + NULL, NULL, NULL); } MemoryRegion *get_system_memory(void) diff --git a/hw/megasas.c b/hw/megasas.c index 7a2036eb76..291ff40403 100644 --- a/hw/megasas.c +++ b/hw/megasas.c @@ -25,7 +25,6 @@ #include "iov.h" #include "scsi.h" #include "scsi-defs.h" -#include "block_int.h" #include "trace.h" #include "mfi.h" @@ -1080,6 +1079,7 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) /* Logical device size is in blocks */ bdrv_get_geometry(conf->bs, &ld_size); info.ld_list[num_ld_disks].ld.v.target_id = sdev->id; + info.ld_list[num_ld_disks].ld.v.lun_id = sdev->lun; info.ld_list[num_ld_disks].state = MFI_LD_STATE_OPTIMAL; info.ld_list[num_ld_disks].size = cpu_to_le64(ld_size); num_ld_disks++; @@ -1085,7 +1085,7 @@ struct mfi_pd_list { union mfi_ld_ref { struct { uint8_t target_id; - uint8_t reserved; + uint8_t lun_id; uint16_t seq; } v; uint32_t ref; diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 1b0afa6352..49b5686a92 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -652,7 +652,6 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) if (buflen > SCSI_MAX_INQUIRY_LEN) { buflen = SCSI_MAX_INQUIRY_LEN; } - memset(outbuf, 0, buflen); outbuf[0] = s->qdev.type & 0x1f; outbuf[1] = (s->features & (1 << SCSI_DISK_F_REMOVABLE)) ? 0x80 : 0; @@ -1388,6 +1387,7 @@ invalid_param_len: static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf) { + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); uint8_t *p = inbuf; int cmd = r->req.cmd.buf[0]; int len = r->req.cmd.xfer; @@ -1424,6 +1424,14 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf) return; } } + if (!bdrv_enable_write_cache(s->qdev.conf.bs)) { + /* The request is used as the AIO opaque value, so add a ref. */ + scsi_req_ref(&r->req); + bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH); + r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r); + return; + } + scsi_req_complete(&r->req, GOOD); return; @@ -1596,24 +1604,26 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) break; } + /* + * FIXME: we shouldn't return anything bigger than 4k, but the code + * requires the buffer to be as big as req->cmd.xfer in several + * places. So, do not allow CDBs with a very large ALLOCATION + * LENGTH. The real fix would be to modify scsi_read_data and + * dma_buf_read, so that they return data beyond the buflen + * as all zeros. + */ + if (req->cmd.xfer > 65536) { + goto illegal_request; + } + r->buflen = MAX(4096, req->cmd.xfer); + if (!r->iov.iov_base) { - /* - * FIXME: we shouldn't return anything bigger than 4k, but the code - * requires the buffer to be as big as req->cmd.xfer in several - * places. So, do not allow CDBs with a very large ALLOCATION - * LENGTH. The real fix would be to modify scsi_read_data and - * dma_buf_read, so that they return data beyond the buflen - * as all zeros. - */ - if (req->cmd.xfer > 65536) { - goto illegal_request; - } - r->buflen = MAX(4096, req->cmd.xfer); r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen); } buflen = req->cmd.xfer; outbuf = r->iov.iov_base; + memset(outbuf, 0, r->buflen); switch (req->cmd.buf[0]) { case TEST_UNIT_READY: assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs)); @@ -1694,12 +1704,14 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) outbuf[5] = 0; outbuf[6] = s->qdev.blocksize >> 8; outbuf[7] = 0; - buflen = 8; break; case REQUEST_SENSE: /* Just return "NO SENSE". */ buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen, (req->cmd.buf[1] & 1) == 0); + if (buflen < 0) { + goto illegal_request; + } break; case MECHANISM_STATUS: buflen = scsi_emulate_mechanism_status(s, outbuf); @@ -1770,7 +1782,6 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) } /* Protection, exponent and lowest lba field left blank. */ - buflen = req->cmd.xfer; break; } DPRINTF("Unsupported Service Action In\n"); @@ -1827,7 +1838,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) return 0; } assert(!r->req.aiocb); - r->iov.iov_len = MIN(buflen, req->cmd.xfer); + r->iov.iov_len = MIN(r->buflen, req->cmd.xfer); if (r->iov.iov_len == 0) { scsi_req_complete(&r->req, GOOD); } @@ -1962,7 +1973,6 @@ static void scsi_disk_resize_cb(void *opaque) * direct-access devices. */ if (s->qdev.type == TYPE_DISK) { - scsi_device_set_ua(&s->qdev, SENSE_CODE(CAPACITY_CHANGED)); scsi_device_report_change(&s->qdev, SENSE_CODE(CAPACITY_CHANGED)); } } diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 6a39e9697b..64de906e41 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1859,7 +1859,7 @@ static int ohci_init_pxa(SysBusDevice *dev) /* Cannot fail as we pass NULL for masterbus */ usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0, - NULL); + &dma_context_memory); sysbus_init_irq(dev, &s->ohci.irq); sysbus_init_mmio(dev, &s->ohci.mem); diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index b54c7895fc..7d546f6ca7 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -204,7 +204,7 @@ static void virtio_scsi_bad_req(void) static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg, hwaddr *addr, int num) { - memset(qsgl, 0, sizeof(*qsgl)); + qemu_sglist_init(qsgl, num, &dma_context_memory); while (num--) { qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len); } @@ -596,6 +596,10 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev, VirtIOSCSIEvent *evt; int in_size; + if (!(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) { + return; + } + if (!req) { s->events_dropped = true; return; @@ -648,7 +652,6 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); if (((s->vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) && - (s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) && dev->type != TYPE_ROM) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE, sense.asc | (sense.ascq << 8)); @@ -659,8 +662,7 @@ static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev) { VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); - if (((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) && - (s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) { + if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); } |