summaryrefslogtreecommitdiff
path: root/hw/scsi
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2014-10-29 13:00:05 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2014-10-31 11:28:59 +0100
commitd97ae3684863960d12633c845f648d50ce767273 (patch)
tree12357efaf84dd7e0ef367a505f266743c2105962 /hw/scsi
parent1894df02811f6b79ea3ffbf1084599d96f316173 (diff)
downloadqemu-d97ae3684863960d12633c845f648d50ce767273.zip
megasas: fixup MFI_DCMD_LD_LIST_QUERY
The MFI_DCMD_LD_LIST_QUERY function is using a different format than MFI_DCMD_LD_LIST, so we need to implement it differently. Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/scsi')
-rw-r--r--hw/scsi/megasas.c37
-rw-r--r--hw/scsi/mfi.h7
2 files changed, 41 insertions, 3 deletions
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 36a04f31bb..562c35bede 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1123,15 +1123,46 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd)
{
uint16_t flags;
+ struct mfi_ld_targetid_list info;
+ size_t dcmd_size = sizeof(info), resid;
+ uint32_t num_ld_disks = 0, max_ld_disks = s->fw_luns;
+ BusChild *kid;
/* mbox0 contains flags */
flags = le16_to_cpu(cmd->frame->dcmd.mbox[0]);
trace_megasas_dcmd_ld_list_query(cmd->index, flags);
- if (flags == MR_LD_QUERY_TYPE_ALL ||
- flags == MR_LD_QUERY_TYPE_EXPOSED_TO_HOST) {
- return megasas_dcmd_ld_get_list(s, cmd);
+ if (flags != MR_LD_QUERY_TYPE_ALL &&
+ flags != MR_LD_QUERY_TYPE_EXPOSED_TO_HOST) {
+ max_ld_disks = 0;
+ }
+
+ memset(&info, 0, dcmd_size);
+ if (cmd->iov_size < 12) {
+ trace_megasas_dcmd_invalid_xfer_len(cmd->index, cmd->iov_size,
+ dcmd_size);
+ return MFI_STAT_INVALID_PARAMETER;
+ }
+ dcmd_size = sizeof(uint32_t) * 2 + 3;
+
+ if (megasas_is_jbod(s)) {
+ max_ld_disks = 0;
}
+ QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+ SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
+ if (num_ld_disks >= max_ld_disks) {
+ break;
+ }
+ info.targetid[num_ld_disks] = sdev->lun;
+ num_ld_disks++;
+ dcmd_size++;
+ }
+ info.ld_count = cpu_to_le32(num_ld_disks);
+ info.size = dcmd_size;
+ trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks);
+
+ resid = dma_buf_read((uint8_t *)&info, dcmd_size, &cmd->qsg);
+ cmd->iov_size = dcmd_size - resid;
return MFI_STAT_OK;
}
diff --git a/hw/scsi/mfi.h b/hw/scsi/mfi.h
index a3034f6239..5050ce4732 100644
--- a/hw/scsi/mfi.h
+++ b/hw/scsi/mfi.h
@@ -1111,6 +1111,13 @@ struct mfi_ld_list {
} ld_list[MFI_MAX_LD];
} QEMU_PACKED;
+struct mfi_ld_targetid_list {
+ uint32_t size;
+ uint32_t ld_count;
+ uint8_t pad[3];
+ uint8_t targetid[MFI_MAX_LD];
+} QEMU_PACKED;
+
enum mfi_ld_access {
MFI_LD_ACCESS_RW = 0,
MFI_LD_ACCSSS_RO = 2,