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>
This commit is contained in:
commit
5f580e9411
5
dma.h
5
dma.h
|
@ -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)
|
||||
{
|
||||
/*
|
||||
|
|
5
exec.c
5
exec.c
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
|
|
2
hw/mfi.h
2
hw/mfi.h
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue