qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes
@ 2014-10-29 12:00 Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 01/13] scsi: Rename scsi_cdb_length() to scsi_xfer_length() Hannes Reinecke
                   ` (12 more replies)
  0 siblings, 13 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

Hi all,

here is an update to the megasas emulation. It adds a new emulation
type (called 'megasas-gen2'), which emulates a newer (PCIe-based)
version of the MegaRAID HBA. As this hardware does MSI-X I've also
fixed up MSI-X support for the megasas emulation.
With these patches Win7 and Linux boot happily with MSI-X.

Upon request from Paolo I've pulled the unrelated fixes which were
present in the original submission. Those fixes will be send
separately.

Hannes Reinecke (13):
  scsi: Rename scsi_cdb_length() to scsi_xfer_length()
  megasas: fixup MFI_DCMD_LD_LIST_QUERY
  megasas: simplify trace event messages
  megasas: fixup device mapping
  megasas: add MegaRAID SAS 2108 emulation
  megasas: Fix typo in megasas_dcmd_ld_get_list()
  megasas: Decode register names
  megasas: Clear unit attention on initial reset
  megasas: Ignore duplicate init_firmware commands
  megasas: Implement DCMD_CLUSTER_RESET_LD
  megasas: Update queue logging
  megasas: Rework frame queueing algorithm
  megasas: Fixup MSI-X handling

 hw/scsi/megasas.c        | 574 +++++++++++++++++++++++++++++++++++------------
 hw/scsi/mfi.h            |  16 +-
 hw/scsi/scsi-bus.c       |  33 +--
 hw/scsi/scsi-disk.c      |   2 +-
 include/hw/pci/pci_ids.h |   1 +
 include/hw/scsi/scsi.h   |   4 +-
 trace-events             |  54 ++---
 7 files changed, 493 insertions(+), 191 deletions(-)

-- 
1.8.4.5

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 01/13] scsi: Rename scsi_cdb_length() to scsi_xfer_length()
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 02/13] megasas: fixup MFI_DCMD_LD_LIST_QUERY Hannes Reinecke
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

scsi_cdb_length() does not return the length of the cdb, but
the transfersize encoded in the cdb. So rename it to scsi_xfer_length()
and add a new scsi_cdb_length() which actually does return the
length of the cdb.
With that DEBUG_SCSI can now display the correct CDB buffer.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/scsi-bus.c     | 31 +++++++++++++++++++------------
 hw/scsi/scsi-disk.c    |  2 +-
 include/hw/scsi/scsi.h |  3 ++-
 3 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 022a524..919a86c 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -879,11 +879,11 @@ uint32_t scsi_data_cdb_length(uint8_t *buf)
     if ((buf[0] >> 5) == 0 && buf[4] == 0) {
         return 256;
     } else {
-        return scsi_cdb_length(buf);
+        return scsi_xfer_length(buf);
     }
 }
 
-uint32_t scsi_cdb_length(uint8_t *buf)
+uint32_t scsi_xfer_length(uint8_t *buf)
 {
     switch (buf[0] >> 5) {
     case 0:
@@ -906,7 +906,7 @@ uint32_t scsi_cdb_length(uint8_t *buf)
 
 static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 {
-    cmd->xfer = scsi_cdb_length(buf);
+    cmd->xfer = scsi_xfer_length(buf);
     switch (buf[0]) {
     case TEST_UNIT_READY:
     case REWIND:
@@ -1213,28 +1213,35 @@ static uint64_t scsi_cmd_lba(SCSICommand *cmd)
     return lba;
 }
 
-int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
-{
-    int rc;
+int scsi_cdb_length(uint8_t *buf) {
+    int cdb_len;
 
-    cmd->lba = -1;
     switch (buf[0] >> 5) {
     case 0:
-        cmd->len = 6;
+        cdb_len = 6;
         break;
     case 1:
     case 2:
-        cmd->len = 10;
+        cdb_len = 10;
         break;
     case 4:
-        cmd->len = 16;
+        cdb_len = 16;
         break;
     case 5:
-        cmd->len = 12;
+        cdb_len = 12;
         break;
     default:
-        return -1;
+        cdb_len = -1;
     }
+    return cdb_len;
+}
+
+int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
+{
+    int rc;
+
+    cmd->lba = -1;
+    cmd->len = scsi_cdb_length(buf);
 
     switch (dev->type) {
     case TYPE_TAPE:
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index ae9e08d..30e3789 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2393,7 +2393,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
     DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
     {
         int i;
-        for (i = 1; i < req->cmd.len; i++) {
+        for (i = 1; i < scsi_cdb_length(buf); i++) {
             printf(" 0x%02x", buf[i]);
         }
         printf("\n");
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index caaa320..4e9bbd1 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -240,7 +240,8 @@ extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
 #define SENSE_CODE(x) sense_code_ ## x
 
 uint32_t scsi_data_cdb_length(uint8_t *buf);
-uint32_t scsi_cdb_length(uint8_t *buf);
+uint32_t scsi_xfer_length(uint8_t *buf);
+int scsi_cdb_length(uint8_t *buf);
 int scsi_sense_valid(SCSISense sense);
 int scsi_build_sense(uint8_t *in_buf, int in_len,
                      uint8_t *buf, int len, bool fixed);
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 02/13] megasas: fixup MFI_DCMD_LD_LIST_QUERY
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 01/13] scsi: Rename scsi_cdb_length() to scsi_xfer_length() Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 03/13] megasas: simplify trace event messages Hannes Reinecke
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

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>
---
 hw/scsi/megasas.c | 37 ++++++++++++++++++++++++++++++++++---
 hw/scsi/mfi.h     |  7 +++++++
 2 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index eedc992..9b9f2d3 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1124,15 +1124,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 a3034f6..5050ce4 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,
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 03/13] megasas: simplify trace event messages
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 01/13] scsi: Rename scsi_cdb_length() to scsi_xfer_length() Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 02/13] megasas: fixup MFI_DCMD_LD_LIST_QUERY Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 04/13] megasas: fixup device mapping Hannes Reinecke
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

The trace events already contain the function name, so the actual
message doesn't need to contain any of these informations.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 trace-events | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/trace-events b/trace-events
index 5290806..380aa83 100644
--- a/trace-events
+++ b/trace-events
@@ -698,34 +698,34 @@ megasas_init_firmware(uint64_t pa) "pa %" PRIx64 " "
 megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) "queue at %" PRIx64 " len %d head %" PRIx64 " tail %" PRIx64 " flags %x"
 megasas_initq_map_failed(int frame) "scmd %d: failed to map queue"
 megasas_initq_mismatch(int queue_len, int fw_cmds) "queue size %d max fw cmds %d"
-megasas_qf_found(unsigned int index, uint64_t pa) "found mapped frame %x pa %" PRIx64 ""
+megasas_qf_found(unsigned int index, uint64_t pa) "mapped frame %x pa %" PRIx64 ""
 megasas_qf_new(unsigned int index, void *cmd) "return new frame %x cmd %p"
 megasas_qf_failed(unsigned long pa) "all frames busy for frame %lx"
 megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int tail, int busy) "enqueue frame %x count %d context %" PRIx64 " tail %x busy %d"
-megasas_qf_update(unsigned int head, unsigned int busy) "update reply queue head %x busy %d"
+megasas_qf_update(unsigned int head, unsigned int busy) "reply queue head %x busy %d"
 megasas_qf_map_failed(int cmd, unsigned long frame) "scmd %d: frame %lu"
 megasas_qf_complete_noirq(uint64_t context) "context %" PRIx64 " "
 megasas_qf_complete(uint64_t context, unsigned int tail, unsigned int offset, int busy, unsigned int doorbell) "context %" PRIx64 " tail %x offset %d busy %d doorbell %x"
 megasas_frame_busy(uint64_t addr) "frame %" PRIx64 " busy"
-megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) "scmd %d: Unhandled MFI cmd %x"
+megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) "scmd %d: MFI cmd %x"
 megasas_handle_scsi(const char *frame, int bus, int dev, int lun, void *sdev, unsigned long size) "%s dev %x/%x/%x sdev %p xfer %lu"
-megasas_scsi_target_not_present(const char *frame, int bus, int dev, int lun) "%s dev %x/%x/%x target not present"
+megasas_scsi_target_not_present(const char *frame, int bus, int dev, int lun) "%s dev %x/%x/%x"
 megasas_scsi_invalid_cdb_len(const char *frame, int bus, int dev, int lun, int len) "%s dev %x/%x/%x invalid cdb len %d"
 megasas_iov_read_overflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
 megasas_iov_write_overflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
 megasas_iov_read_underflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
 megasas_iov_write_underflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
-megasas_scsi_req_alloc_failed(const char *frame, int dev, int lun) "%s dev %x/%x req allocation failed"
+megasas_scsi_req_alloc_failed(const char *frame, int dev, int lun) "%s dev %x/%x"
 megasas_scsi_read_start(int cmd, int len) "scmd %d: transfer %d bytes of data"
 megasas_scsi_write_start(int cmd, int len) "scmd %d: transfer %d bytes of data"
 megasas_scsi_nodata(int cmd) "scmd %d: no data to be transferred"
-megasas_scsi_complete(int cmd, uint32_t status, int len, int xfer) "scmd %d: finished with status %x, len %u/%u"
-megasas_command_complete(int cmd, uint32_t status, uint32_t resid) "scmd %d: command completed, status %x, residual %d"
+megasas_scsi_complete(int cmd, uint32_t status, int len, int xfer) "scmd %d: status %x, len %u/%u"
+megasas_command_complete(int cmd, uint32_t status, uint32_t resid) "scmd %d: status %x, residual %d"
 megasas_handle_io(int cmd, const char *frame, int dev, int lun, unsigned long lba, unsigned long count) "scmd %d: %s dev %x/%x lba %lx count %lu"
 megasas_io_target_not_present(int cmd, const char *frame, int dev, int lun) "scmd %d: %s dev 1/%x/%x LUN not present"
 megasas_io_read_start(int cmd, unsigned long lba, unsigned long count, unsigned long len) "scmd %d: start LBA %lx %lu blocks (%lu bytes)"
 megasas_io_write_start(int cmd, unsigned long lba, unsigned long count, unsigned long len) "scmd %d: start LBA %lx %lu blocks (%lu bytes)"
-megasas_io_complete(int cmd, uint32_t len) "scmd %d: %d bytes completed"
+megasas_io_complete(int cmd, uint32_t len) "scmd %d: %d bytes"
 megasas_iovec_sgl_overflow(int cmd, int index, int limit) "scmd %d: iovec count %d limit %d"
 megasas_iovec_sgl_underflow(int cmd, int index) "scmd %d: iovec count %d"
 megasas_iovec_sgl_invalid(int cmd, int index, uint64_t pa, uint32_t len) "scmd %d: element %d pa %" PRIx64 " len %u"
@@ -733,25 +733,25 @@ megasas_iovec_overflow(int cmd, int len, int limit) "scmd %d: len %d limit %d"
 megasas_iovec_underflow(int cmd, int len, int limit) "scmd %d: len %d limit %d"
 megasas_handle_dcmd(int cmd, int opcode) "scmd %d: MFI DCMD opcode %x"
 megasas_finish_dcmd(int cmd, int size) "scmd %d: MFI DCMD wrote %d bytes"
-megasas_dcmd_req_alloc_failed(int cmd, const char *desc) "scmd %d: %s alloc failed"
+megasas_dcmd_req_alloc_failed(int cmd, const char *desc) "scmd %d: %s"
 megasas_dcmd_internal_submit(int cmd, const char *desc, int dev) "scmd %d: %s to dev %d"
-megasas_dcmd_internal_finish(int cmd, int opcode, int lun) "scmd %d: DCMD finish internal cmd %x lun %d"
-megasas_dcmd_internal_invalid(int cmd, int opcode) "scmd %d: Invalid internal DCMD %x"
+megasas_dcmd_internal_finish(int cmd, int opcode, int lun) "scmd %d: cmd %x lun %d"
+megasas_dcmd_internal_invalid(int cmd, int opcode) "scmd %d: DCMD %x"
 megasas_dcmd_unhandled(int cmd, int opcode, int len) "scmd %d: opcode %x, len %d"
 megasas_dcmd_zero_sge(int cmd) "scmd %d: zero DCMD sge count"
-megasas_dcmd_invalid_sge(int cmd, int count) "scmd %d: invalid DCMD sge count %d"
-megasas_dcmd_invalid_xfer_len(int cmd, unsigned long size, unsigned long max) "scmd %d: invalid xfer len %ld, max %ld"
+megasas_dcmd_invalid_sge(int cmd, int count) "scmd %d: DCMD sge count %d"
+megasas_dcmd_invalid_xfer_len(int cmd, unsigned long size, unsigned long max) "scmd %d: xfer len %ld, max %ld"
 megasas_dcmd_enter(int cmd, const char *dcmd, int len) "scmd %d: DCMD %s len %d"
-megasas_dcmd_dummy(int cmd, unsigned long size) "scmd %d: DCMD dummy xfer len %ld"
+megasas_dcmd_dummy(int cmd, unsigned long size) "scmd %d: xfer len %ld"
 megasas_dcmd_set_fw_time(int cmd, unsigned long time) "scmd %d: Set FW time %lx"
 megasas_dcmd_pd_get_list(int cmd, int num, int max, int offset) "scmd %d: DCMD PD get list: %d / %d PDs, size %d"
 megasas_dcmd_ld_get_list(int cmd, int num, int max) "scmd %d: DCMD LD get list: found %d / %d LDs"
-megasas_dcmd_ld_get_info(int cmd, int ld_id) "scmd %d: DCMD LD get info for dev %d"
-megasas_dcmd_pd_get_info(int cmd, int pd_id) "scmd %d: DCMD PD get info for dev %d"
-megasas_dcmd_pd_list_query(int cmd, int flags) "scmd %d: DCMD PD list query flags %x"
-megasas_dcmd_ld_list_query(int cmd, int flags) "scmd %d: DCMD LD list query flags %x"
+megasas_dcmd_ld_get_info(int cmd, int ld_id) "scmd %d: dev %d"
+megasas_dcmd_ld_list_query(int cmd, int flags) "scmd %d: query flags %x"
+megasas_dcmd_pd_get_info(int cmd, int pd_id) "scmd %d: dev %d"
+megasas_dcmd_pd_list_query(int cmd, int flags) "scmd %d: query flags %x"
 megasas_dcmd_unsupported(int cmd, unsigned long size) "scmd %d: set properties len %ld"
-megasas_abort_frame(int cmd, int abort_cmd) "scmd %d: aborting frame %x"
+megasas_abort_frame(int cmd, int abort_cmd) "scmd %d: frame %x"
 megasas_abort_no_cmd(int cmd, uint64_t context) "scmd %d: no active command for frame context %" PRIx64 ""
 megasas_abort_invalid_context(int cmd, uint64_t context, int abort_cmd) "scmd %d: invalid frame context %" PRIx64 " for abort frame %x"
 megasas_reset(void) "Reset"
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 04/13] megasas: fixup device mapping
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
                   ` (2 preceding siblings ...)
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 03/13] megasas: simplify trace event messages Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 05/13] megasas: add MegaRAID SAS 2108 emulation Hannes Reinecke
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

Logical drives can only be addressed with the 'target_id' number;
LUN numbers cannot be selected.
Physical drives can be selected with both, target and LUN id.

So we should disallow LUN numbers not equal to 0 when in
RAID mode.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c | 95 +++++++++++++++++++++++++++++++++++--------------------
 hw/scsi/mfi.h     |  2 +-
 2 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 9b9f2d3..10e9d7a 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -688,8 +688,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
     struct mfi_ctrl_info info;
     size_t dcmd_size = sizeof(info);
     BusChild *kid;
-    int num_ld_disks = 0;
-    uint16_t sdev_id;
+    int num_pd_disks = 0;
 
     memset(&info, 0x0, cmd->iov_size);
     if (cmd->iov_size < dcmd_size) {
@@ -718,13 +717,14 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
     info.device.port_count = 8;
     QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
         SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
+        uint16_t pd_id;
 
-        if (num_ld_disks < 8) {
-            sdev_id = ((sdev->id & 0xFF) >> 8) | (sdev->lun & 0xFF);
-            info.device.port_addr[num_ld_disks] =
-                cpu_to_le64(megasas_get_sata_addr(sdev_id));
+        if (num_pd_disks < 8) {
+            pd_id = ((sdev->id & 0xFF) << 8) | (sdev->lun & 0xFF);
+            info.device.port_addr[num_pd_disks] =
+                cpu_to_le64(megasas_get_sata_addr(pd_id));
         }
-        num_ld_disks++;
+        num_pd_disks++;
     }
 
     memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20);
@@ -750,13 +750,14 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
     info.max_arms = 32;
     info.max_spans = 8;
     info.max_arrays = MEGASAS_MAX_ARRAYS;
-    info.max_lds = s->fw_luns;
+    info.max_lds = MFI_MAX_LD;
     info.max_cmds = cpu_to_le16(s->fw_cmds);
     info.max_sg_elements = cpu_to_le16(s->fw_sge);
     info.max_request_size = cpu_to_le32(MEGASAS_MAX_SECTORS);
-    info.lds_present = cpu_to_le16(num_ld_disks);
-    info.pd_present = cpu_to_le16(num_ld_disks);
-    info.pd_disks_present = cpu_to_le16(num_ld_disks);
+    if (!megasas_is_jbod(s))
+        info.lds_present = cpu_to_le16(num_pd_disks);
+    info.pd_present = cpu_to_le16(num_pd_disks);
+    info.pd_disks_present = cpu_to_le16(num_pd_disks);
     info.hw_present = cpu_to_le32(MFI_INFO_HW_NVRAM |
                                    MFI_INFO_HW_MEM |
                                    MFI_INFO_HW_FLASH);
@@ -915,7 +916,6 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd)
     size_t dcmd_size = sizeof(info);
     BusChild *kid;
     uint32_t offset, dcmd_limit, num_pd_disks = 0, max_pd_disks;
-    uint16_t sdev_id;
 
     memset(&info, 0, dcmd_size);
     offset = 8;
@@ -927,22 +927,25 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd)
     }
 
     max_pd_disks = (cmd->iov_size - offset) / sizeof(struct mfi_pd_address);
-    if (max_pd_disks > s->fw_luns) {
-        max_pd_disks = s->fw_luns;
+    if (max_pd_disks > MFI_MAX_SYS_PDS) {
+        max_pd_disks = MFI_MAX_SYS_PDS;
     }
-
     QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
         SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
+        uint16_t pd_id;
+
+        if (num_pd_disks >= max_pd_disks)
+            break;
 
-        sdev_id = ((sdev->id & 0xFF) >> 8) | (sdev->lun & 0xFF);
-        info.addr[num_pd_disks].device_id = cpu_to_le16(sdev_id);
+        pd_id = ((sdev->id & 0xFF) << 8) | (sdev->lun & 0xFF);
+        info.addr[num_pd_disks].device_id = cpu_to_le16(pd_id);
         info.addr[num_pd_disks].encl_device_id = 0xFFFF;
         info.addr[num_pd_disks].encl_index = 0;
-        info.addr[num_pd_disks].slot_number = (sdev->id & 0xFF);
+        info.addr[num_pd_disks].slot_number = sdev->id & 0xFF;
         info.addr[num_pd_disks].scsi_dev_type = sdev->type;
         info.addr[num_pd_disks].connect_port_bitmap = 0x1;
         info.addr[num_pd_disks].sas_addr[0] =
-            cpu_to_le64(megasas_get_sata_addr(sdev_id));
+            cpu_to_le64(megasas_get_sata_addr(pd_id));
         num_pd_disks++;
         offset += sizeof(struct mfi_pd_address);
     }
@@ -978,7 +981,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
     size_t dcmd_size = sizeof(struct mfi_pd_info);
     BlockConf *conf = &sdev->conf;
     uint64_t pd_size;
-    uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (lun & 0xFF);
+    uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF);
     uint8_t cmdbuf[6];
     SCSIRequest *req;
     size_t len, resid;
@@ -1034,7 +1037,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
         info->fw_state = cpu_to_le16(MFI_PD_STATE_OFFLINE);
     }
 
-    info->ref.v.device_id = cpu_to_le16(sdev_id);
+    info->ref.v.device_id = cpu_to_le16(pd_id);
     info->state.ddf.pd_type = cpu_to_le16(MFI_PD_DDF_TYPE_IN_VD|
                                           MFI_PD_DDF_TYPE_INTF_SAS);
     bdrv_get_geometry(conf->bs, &pd_size);
@@ -1045,7 +1048,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
     info->slot_number = (sdev->id & 0xFF);
     info->path_info.count = 1;
     info->path_info.sas_addr[0] =
-        cpu_to_le64(megasas_get_sata_addr(sdev_id));
+        cpu_to_le64(megasas_get_sata_addr(pd_id));
     info->connected_port_bitmap = 0x1;
     info->device_speed = 1;
     info->link_speed = 1;
@@ -1060,6 +1063,7 @@ static int megasas_dcmd_pd_get_info(MegasasState *s, MegasasCmd *cmd)
 {
     size_t dcmd_size = sizeof(struct mfi_pd_info);
     uint16_t pd_id;
+    uint8_t target_id, lun_id;
     SCSIDevice *sdev = NULL;
     int retval = MFI_STAT_DEVICE_NOT_FOUND;
 
@@ -1069,7 +1073,9 @@ static int megasas_dcmd_pd_get_info(MegasasState *s, MegasasCmd *cmd)
 
     /* mbox0 has the ID */
     pd_id = le16_to_cpu(cmd->frame->dcmd.mbox[0]);
-    sdev = scsi_device_find(&s->bus, 0, pd_id, 0);
+    target_id = (pd_id >> 8) & 0xFF;
+    lun_id = pd_id & 0xFF;
+    sdev = scsi_device_find(&s->bus, 0, target_id, lun_id);
     trace_megasas_dcmd_pd_get_info(cmd->index, pd_id);
 
     if (sdev) {
@@ -1084,7 +1090,7 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
 {
     struct mfi_ld_list info;
     size_t dcmd_size = sizeof(info), resid;
-    uint32_t num_ld_disks = 0, max_ld_disks = s->fw_luns;
+    uint32_t num_ld_disks = 0, max_ld_disks;
     uint64_t ld_size;
     BusChild *kid;
 
@@ -1095,9 +1101,13 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
         return MFI_STAT_INVALID_PARAMETER;
     }
 
+    max_ld_disks = (cmd->iov_size - 8) / 16;
     if (megasas_is_jbod(s)) {
         max_ld_disks = 0;
     }
+    if (max_ld_disks > MFI_MAX_LD) {
+        max_ld_disks = MFI_MAX_LD;
+    }
     QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
         SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
         BlockConf *conf = &sdev->conf;
@@ -1108,7 +1118,6 @@ 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++;
@@ -1144,10 +1153,13 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd)
         return MFI_STAT_INVALID_PARAMETER;
     }
     dcmd_size = sizeof(uint32_t) * 2 + 3;
-
+    max_ld_disks = cmd->iov_size - dcmd_size;
     if (megasas_is_jbod(s)) {
         max_ld_disks = 0;
     }
+    if (max_ld_disks > MFI_MAX_LD) {
+        max_ld_disks = MFI_MAX_LD;
+    }
     QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
         SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
 
@@ -1176,7 +1188,7 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
     SCSIRequest *req;
     ssize_t len, resid;
     BlockConf *conf = &sdev->conf;
-    uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (lun & 0xFF);
+    uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF);
     uint64_t ld_size;
 
     if (!cmd->iov_buf) {
@@ -1293,7 +1305,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd)
     QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
         SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
         BlockConf *conf = &sdev->conf;
-        uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (sdev->lun & 0xFF);
+        uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (sdev->lun & 0xFF);
         struct mfi_array *array;
         struct mfi_ld_config *ld;
         uint64_t pd_size;
@@ -1319,7 +1331,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd)
         array_offset += sizeof(struct mfi_array);
         ld = (struct mfi_ld_config *)(data + ld_offset);
         memset(ld, 0, sizeof(struct mfi_ld_config));
-        ld->properties.ld.v.target_id = (sdev->id & 0xFF);
+        ld->properties.ld.v.target_id = sdev->id;
         ld->properties.default_cache_policy = MR_LD_CACHE_READ_AHEAD |
             MR_LD_CACHE_READ_ADAPTIVE;
         ld->properties.current_cache_policy = MR_LD_CACHE_READ_AHEAD |
@@ -1606,10 +1618,18 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
 
     cdb = cmd->frame->pass.cdb;
 
-    if (cmd->frame->header.target_id < s->fw_luns) {
-        sdev = scsi_device_find(&s->bus, 0, cmd->frame->header.target_id,
-                                cmd->frame->header.lun_id);
+    if (is_logical) {
+        if (cmd->frame->header.target_id >= MFI_MAX_LD ||
+            cmd->frame->header.lun_id != 0) {
+            trace_megasas_scsi_target_not_present(
+                mfi_frame_desc[cmd->frame->header.frame_cmd], is_logical,
+                cmd->frame->header.target_id, cmd->frame->header.lun_id);
+            return MFI_STAT_DEVICE_NOT_FOUND;
+        }
     }
+    sdev = scsi_device_find(&s->bus, 0, cmd->frame->header.target_id,
+                            cmd->frame->header.lun_id);
+
     cmd->iov_size = le32_to_cpu(cmd->frame->header.data_len);
     trace_megasas_handle_scsi(mfi_frame_desc[cmd->frame->header.frame_cmd],
                               is_logical, cmd->frame->header.target_id,
@@ -1680,7 +1700,8 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd)
     lba_start_hi = le32_to_cpu(cmd->frame->io.lba_hi);
     lba_start = ((uint64_t)lba_start_hi << 32) | lba_start_lo;
 
-    if (cmd->frame->header.target_id < s->fw_luns) {
+    if (cmd->frame->header.target_id < MFI_MAX_LD &&
+        cmd->frame->header.lun_id == 0) {
         sdev = scsi_device_find(&s->bus, 0, cmd->frame->header.target_id,
                                 cmd->frame->header.lun_id);
     }
@@ -2236,8 +2257,12 @@ static int megasas_scsi_init(PCIDevice *dev)
     }
     trace_megasas_init(s->fw_sge, s->fw_cmds,
                        megasas_is_jbod(s) ? "jbod" : "raid");
-    s->fw_luns = (MFI_MAX_LD > MAX_SCSI_DEVS) ?
-        MAX_SCSI_DEVS : MFI_MAX_LD;
+
+    if (megasas_is_jbod(s)) {
+        s->fw_luns = MFI_MAX_SYS_PDS;
+    } else {
+        s->fw_luns = MFI_MAX_LD;
+    }
     s->producer_pa = 0;
     s->consumer_pa = 0;
     for (i = 0; i < s->fw_cmds; i++) {
diff --git a/hw/scsi/mfi.h b/hw/scsi/mfi.h
index 5050ce4..455c96b 100644
--- a/hw/scsi/mfi.h
+++ b/hw/scsi/mfi.h
@@ -1094,7 +1094,7 @@ struct mfi_pd_list {
 union mfi_ld_ref {
     struct {
         uint8_t target_id;
-        uint8_t lun_id;
+        uint8_t reserved;
         uint16_t seq;
     } v;
     uint32_t ref;
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 05/13] megasas: add MegaRAID SAS 2108 emulation
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
                   ` (3 preceding siblings ...)
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 04/13] megasas: fixup device mapping Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-31 17:08   ` Paolo Bonzini
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 06/13] megasas: Fix typo in megasas_dcmd_ld_get_list() Hannes Reinecke
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

The 2108 chip supports MSI and MSI-X, so update the emulation
to support both chips.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c        | 218 +++++++++++++++++++++++++++++++++++++++++------
 hw/scsi/mfi.h            |   7 ++
 include/hw/pci/pci_ids.h |   1 +
 3 files changed, 201 insertions(+), 25 deletions(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 10e9d7a..190a0bd 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -30,9 +30,11 @@
 
 #include "mfi.h"
 
-#define MEGASAS_VERSION "1.70"
+#define MEGASAS_VERSION_GEN1 "1.70"
+#define MEGASAS_VERSION_GEN2 "1.80"
 #define MEGASAS_MAX_FRAMES 2048         /* Firmware limit at 65535 */
 #define MEGASAS_DEFAULT_FRAMES 1000     /* Windows requires this */
+#define MEGASAS_GEN2_DEFAULT_FRAMES 1008     /* Windows requires this */
 #define MEGASAS_MAX_SGE 128             /* Firmware limit */
 #define MEGASAS_DEFAULT_SGE 80
 #define MEGASAS_MAX_SECTORS 0xFFFF      /* No real limit */
@@ -90,6 +92,8 @@ typedef struct MegasasState {
     int intr_mask;
     int doorbell;
     int busy;
+    int diag;
+    int adp_reset;
 
     MegasasCmd *event_cmd;
     int event_locale;
@@ -114,10 +118,26 @@ typedef struct MegasasState {
     SCSIBus bus;
 } MegasasState;
 
-#define TYPE_MEGASAS "megasas"
+typedef struct MegasasBaseClass {
+    PCIDeviceClass parent_class;
+    const char *product_name;
+    const char *product_version;
+    int mmio_bar;
+    int ioport_bar;
+    int osts;
+} MegasasBaseClass;
+
+#define TYPE_MEGASAS_BASE "megasas-base"
+#define TYPE_MEGASAS_GEN1 "megasas"
+#define TYPE_MEGASAS_GEN2 "megasas-gen2"
 
 #define MEGASAS(obj) \
-    OBJECT_CHECK(MegasasState, (obj), TYPE_MEGASAS)
+    OBJECT_CHECK(MegasasState, (obj), TYPE_MEGASAS_BASE)
+
+#define MEGASAS_DEVICE_CLASS(oc) \
+    OBJECT_CLASS_CHECK(MegasasBaseClass, (oc), TYPE_MEGASAS_BASE)
+#define MEGASAS_DEVICE_GET_CLASS(oc) \
+    OBJECT_GET_CLASS(MegasasBaseClass, (oc), TYPE_MEGASAS_BASE)
 
 #define MEGASAS_INTR_DISABLED_MASK 0xFFFFFFFF
 
@@ -685,6 +705,8 @@ static void megasas_finish_dcmd(MegasasCmd *cmd, uint32_t iov_size)
 static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
 {
     PCIDevice *pci_dev = PCI_DEVICE(s);
+    PCIDeviceClass *pci_class = PCI_DEVICE_GET_CLASS(pci_dev);
+    MegasasBaseClass *base_class = MEGASAS_DEVICE_GET_CLASS(s);
     struct mfi_ctrl_info info;
     size_t dcmd_size = sizeof(info);
     BusChild *kid;
@@ -697,10 +719,10 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
         return MFI_STAT_INVALID_PARAMETER;
     }
 
-    info.pci.vendor = cpu_to_le16(PCI_VENDOR_ID_LSI_LOGIC);
-    info.pci.device = cpu_to_le16(PCI_DEVICE_ID_LSI_SAS1078);
-    info.pci.subvendor = cpu_to_le16(PCI_VENDOR_ID_LSI_LOGIC);
-    info.pci.subdevice = cpu_to_le16(0x1013);
+    info.pci.vendor = cpu_to_le16(pci_class->vendor_id);
+    info.pci.device = cpu_to_le16(pci_class->device_id);
+    info.pci.subvendor = cpu_to_le16(pci_class->subsystem_vendor_id);
+    info.pci.subdevice = cpu_to_le16(pci_class->subsystem_id);
 
     /*
      * For some reason the firmware supports
@@ -727,11 +749,12 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
         num_pd_disks++;
     }
 
-    memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20);
+    memcpy(info.product_name, base_class->product_name, 24);
     snprintf(info.serial_number, 32, "%s", s->hba_serial);
     snprintf(info.package_version, 0x60, "%s-QEMU", QEMU_VERSION);
     memcpy(info.image_component[0].name, "APP", 3);
-    memcpy(info.image_component[0].version, MEGASAS_VERSION "-QEMU", 9);
+    snprintf(info.image_component[0].version, 10, "%s-QEMU",
+             base_class->product_version);
     memcpy(info.image_component[0].build_date, "Apr  1 2014", 11);
     memcpy(info.image_component[0].build_time, "12:34:56", 8);
     info.image_component_count = 1;
@@ -1963,6 +1986,8 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
                                   unsigned size)
 {
     MegasasState *s = opaque;
+    PCIDevice *pci_dev = PCI_DEVICE(s);
+    MegasasBaseClass *base_class = MEGASAS_DEVICE_GET_CLASS(s);
     uint32_t retval = 0;
 
     switch (addr) {
@@ -1971,14 +1996,14 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
         break;
     case MFI_OMSG0:
     case MFI_OSP0:
-        retval = (megasas_use_msix(s) ? MFI_FWSTATE_MSIX_SUPPORTED : 0) |
+        retval = (msix_present(pci_dev) ? MFI_FWSTATE_MSIX_SUPPORTED : 0) |
             (s->fw_state & MFI_FWSTATE_MASK) |
             ((s->fw_sge & 0xff) << 16) |
             (s->fw_cmds & 0xFFFF);
         break;
     case MFI_OSTS:
         if (megasas_intr_enabled(s) && s->doorbell) {
-            retval = MFI_1078_RM | 1;
+            retval = base_class->osts;
         }
         break;
     case MFI_OMSK:
@@ -1987,6 +2012,12 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
     case MFI_ODCR0:
         retval = s->doorbell;
         break;
+    case MFI_DIAG:
+        retval = s->diag;
+        break;
+    case MFI_OSP1:
+        retval = 15;
+        break;
     default:
         trace_megasas_mmio_invalid_readl(addr);
         break;
@@ -1995,6 +2026,8 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
     return retval;
 }
 
+static int adp_reset_seq[] = {0x00, 0x04, 0x0b, 0x02, 0x07, 0x0d};
+
 static void megasas_mmio_write(void *opaque, hwaddr addr,
                                uint64_t val, unsigned size)
 {
@@ -2020,6 +2053,10 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
         if (val & MFI_FWINIT_MFIMODE) {
             /* discard MFIs */
         }
+        if (val & MFI_FWINIT_STOP_ADP) {
+            /* Terminal error, stop processing */
+            s->fw_state = MFI_FWSTATE_FAULT;
+        }
         break;
     case MFI_OMSK:
         s->intr_mask = val;
@@ -2039,6 +2076,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
             }
         } else {
             trace_megasas_intr_disabled();
+            megasas_soft_reset(s);
         }
         break;
     case MFI_ODCR0:
@@ -2060,8 +2098,9 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
         break;
     case MFI_IQPL:
         /* Received low 32 bits of a 64 bit MFI frame address */
+        /* Fallthrough */
     case MFI_IQP:
-        /* Received 32 bit MFI frame address */
+        /* Received 64 bit MFI frame address */
         frame_addr = (val & ~0x1F);
         /* Add possible 64 bit offset */
         frame_addr |= ((uint64_t)s->frame_hi << 32);
@@ -2069,6 +2108,28 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
         frame_count = (val >> 1) & 0xF;
         megasas_handle_frame(s, frame_addr, frame_count);
         break;
+    case MFI_SEQ:
+        /* Magic sequence to start ADP reset */
+        if (adp_reset_seq[s->adp_reset] == val) {
+            s->adp_reset++;
+        } else {
+            s->adp_reset = 0;
+            s->diag = 0;
+        }
+        if (s->adp_reset == 6) {
+            s->diag = MFI_DIAG_WRITE_ENABLE;
+        }
+        break;
+    case MFI_DIAG:
+        /* ADP reset */
+        if ((s->diag & MFI_DIAG_WRITE_ENABLE) &&
+            (val & MFI_DIAG_RESET_ADP)) {
+            s->diag |= MFI_DIAG_RESET_ADP;
+            megasas_soft_reset(s);
+            s->adp_reset = 0;
+            s->diag = 0;
+        }
+        break;
     default:
         trace_megasas_mmio_invalid_writel(addr, val);
         break;
@@ -2153,7 +2214,7 @@ static void megasas_scsi_reset(DeviceState *dev)
     megasas_soft_reset(s);
 }
 
-static const VMStateDescription vmstate_megasas = {
+static VMStateDescription vmstate_megasas_gen1 = {
     .name = "megasas",
     .version_id = 0,
     .minimum_version_id = 0,
@@ -2171,6 +2232,25 @@ static const VMStateDescription vmstate_megasas = {
     }
 };
 
+static VMStateDescription vmstate_megasas_gen2 = {
+    .name = "megasas-gen2",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_PCIE_DEVICE(parent_obj, MegasasState),
+        VMSTATE_MSIX(parent_obj, MegasasState),
+
+        VMSTATE_INT32(fw_state, MegasasState),
+        VMSTATE_INT32(intr_mask, MegasasState),
+        VMSTATE_INT32(doorbell, MegasasState),
+        VMSTATE_UINT64(reply_queue_pa, MegasasState),
+        VMSTATE_UINT64(consumer_pa, MegasasState),
+        VMSTATE_UINT64(producer_pa, MegasasState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void megasas_scsi_uninit(PCIDevice *d)
 {
     MegasasState *s = MEGASAS(d);
@@ -2198,6 +2278,7 @@ static int megasas_scsi_init(PCIDevice *dev)
 {
     DeviceState *d = DEVICE(dev);
     MegasasState *s = MEGASAS(dev);
+    MegasasBaseClass *b = MEGASAS_DEVICE_GET_CLASS(s);
     uint8_t *pci_conf;
     int i, bar_type;
     Error *err = NULL;
@@ -2221,14 +2302,18 @@ static int megasas_scsi_init(PCIDevice *dev)
         s->flags &= ~MEGASAS_MASK_USE_MSI;
     }
     if (megasas_use_msix(s) &&
-        msix_init(dev, 15, &s->mmio_io, 0, 0x2000,
-                  &s->mmio_io, 0, 0x3800, 0x68)) {
+        msix_init(dev, 15, &s->mmio_io, b->mmio_bar, 0x2000,
+                  &s->mmio_io, b->mmio_bar, 0x3800, 0x68)) {
         s->flags &= ~MEGASAS_MASK_USE_MSIX;
     }
+    if (pci_is_express(dev)) {
+        pcie_endpoint_cap_init(dev, 0xa0);
+    }
 
     bar_type = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64;
-    pci_register_bar(dev, 0, bar_type, &s->mmio_io);
-    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io);
+    pci_register_bar(dev, b->ioport_bar,
+                     PCI_BASE_ADDRESS_SPACE_IO, &s->port_io);
+    pci_register_bar(dev, b->mmio_bar, bar_type, &s->mmio_io);
     pci_register_bar(dev, 3, bar_type, &s->queue_io);
 
     if (megasas_use_msix(s)) {
@@ -2291,7 +2376,7 @@ megasas_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len)
     msi_write_config(pci, addr, val, len);
 }
 
-static Property megasas_properties[] = {
+static Property megasas_properties_gen1[] = {
     DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge,
                        MEGASAS_DEFAULT_SGE),
     DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds,
@@ -2307,36 +2392,119 @@ static Property megasas_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static Property megasas_properties_gen2[] = {
+    DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge,
+                       MEGASAS_DEFAULT_SGE),
+    DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds,
+                       MEGASAS_GEN2_DEFAULT_FRAMES),
+    DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial),
+    DEFINE_PROP_UINT64("sas_address", MegasasState, sas_addr, 0),
+    DEFINE_PROP_BIT("use_msi", MegasasState, flags,
+                    MEGASAS_FLAG_USE_MSI, true),
+    DEFINE_PROP_BIT("use_msix", MegasasState, flags,
+                    MEGASAS_FLAG_USE_MSIX, true),
+    DEFINE_PROP_BIT("use_jbod", MegasasState, flags,
+                    MEGASAS_FLAG_USE_JBOD, false),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+typedef struct MegasasInfo {
+    const char *name;
+    const char *desc;
+    const char *product_name;
+    const char *product_version;
+    uint16_t device_id;
+    uint16_t subsystem_id;
+    int ioport_bar;
+    int mmio_bar;
+    bool is_express;
+    int osts;
+    VMStateDescription *vmsd;
+    Property *props;
+} MegasasInfo;
+
+static struct MegasasInfo megasas_devices[] = {
+    {
+        .name = TYPE_MEGASAS_GEN1,
+        .desc = "LSI MegaRAID SAS 1078",
+        .product_name = "LSI MegaRAID SAS 8708EM2",
+        .product_version = MEGASAS_VERSION_GEN1,
+        .device_id = PCI_DEVICE_ID_LSI_SAS1078,
+        .subsystem_id = 0x1013,
+        .ioport_bar = 2,
+        .mmio_bar = 0,
+        .osts = MFI_1078_RM | 1,
+        .is_express = false,
+        .vmsd = &vmstate_megasas_gen1,
+        .props = megasas_properties_gen1,
+    },{
+        .name = TYPE_MEGASAS_GEN2,
+        .desc = "LSI MegaRAID SAS 2108",
+        .product_name = "LSI MegaRAID SAS 9260-8i",
+        .product_version = MEGASAS_VERSION_GEN2,
+        .device_id = PCI_DEVICE_ID_LSI_SAS0079,
+        .subsystem_id = 0x9261,
+        .ioport_bar = 0,
+        .mmio_bar = 1,
+        .osts = MFI_GEN2_RM,
+        .is_express = true,
+        .vmsd = &vmstate_megasas_gen2,
+        .props = megasas_properties_gen2,
+    }
+};
+
 static void megasas_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
     PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
+    MegasasBaseClass *e = MEGASAS_DEVICE_CLASS(oc);
+    const MegasasInfo *info = data;
 
     pc->init = megasas_scsi_init;
     pc->exit = megasas_scsi_uninit;
     pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
-    pc->device_id = PCI_DEVICE_ID_LSI_SAS1078;
+    pc->device_id = info->device_id;
     pc->subsystem_vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
-    pc->subsystem_id = 0x1013;
+    pc->subsystem_id = info->subsystem_id;
     pc->class_id = PCI_CLASS_STORAGE_RAID;
-    dc->props = megasas_properties;
+    pc->is_express = info->is_express;
+    e->mmio_bar = info->mmio_bar;
+    e->ioport_bar = info->ioport_bar;
+    e->osts = info->osts;
+    e->product_name = info->product_name;
+    e->product_version = info->product_version;
+    dc->props = info->props;
     dc->reset = megasas_scsi_reset;
-    dc->vmsd = &vmstate_megasas;
+    dc->vmsd = info->vmsd;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
-    dc->desc = "LSI MegaRAID SAS 1078";
+    dc->desc = info->desc;
     pc->config_write = megasas_write_config;
 }
 
 static const TypeInfo megasas_info = {
-    .name  = TYPE_MEGASAS,
+    .name  = TYPE_MEGASAS_BASE,
     .parent = TYPE_PCI_DEVICE,
     .instance_size = sizeof(MegasasState),
-    .class_init = megasas_class_init,
+    .class_size = sizeof(MegasasBaseClass),
+    .abstract = true,
 };
 
 static void megasas_register_types(void)
 {
+    int i;
+
     type_register_static(&megasas_info);
+    for (i = 0; i < ARRAY_SIZE(megasas_devices); i++) {
+        const MegasasInfo *info = &megasas_devices[i];
+        TypeInfo type_info = {};
+
+        type_info.name = info->name;
+        type_info.parent = TYPE_MEGASAS_BASE;
+        type_info.class_data = (void *)info;
+        type_info.class_init = megasas_class_init;
+
+        type_register(&type_info);
+    }
 }
 
 type_init(megasas_register_types)
diff --git a/hw/scsi/mfi.h b/hw/scsi/mfi.h
index 455c96b..29d4177 100644
--- a/hw/scsi/mfi.h
+++ b/hw/scsi/mfi.h
@@ -60,6 +60,7 @@
 #define MFI_ODR0        0x9c            /* outbound doorbell register0 */
 #define MFI_ODCR0       0xa0            /* outbound doorbell clear register0  */
 #define MFI_OSP0        0xb0            /* outbound scratch pad0  */
+#define MFI_OSP1        0xb4            /* outbound scratch pad1  */
 #define MFI_IQPL        0xc0            /* Inbound queue port (low bytes)  */
 #define MFI_IQPH        0xc4            /* Inbound queue port (high bytes)  */
 #define MFI_DIAG        0xf8            /* Host diag */
@@ -116,6 +117,12 @@
 #define MFI_FWINIT_STOP_ADP     0x00000020 /* Move to operational, stop */
 #define MFI_FWINIT_ADP_RESET    0x00000040 /* Reset ADP */
 
+/*
+ * Control bits for the DIAG register
+ */
+#define MFI_DIAG_WRITE_ENABLE 0x00000080
+#define MFI_DIAG_RESET_ADP    0x00000004
+
 /* MFI Commands */
 typedef enum {
     MFI_CMD_INIT = 0x00,
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
index e597070..321d622 100644
--- a/include/hw/pci/pci_ids.h
+++ b/include/hw/pci/pci_ids.h
@@ -56,6 +56,7 @@
 #define PCI_DEVICE_ID_LSI_53C810         0x0001
 #define PCI_DEVICE_ID_LSI_53C895A        0x0012
 #define PCI_DEVICE_ID_LSI_SAS1078        0x0060
+#define PCI_DEVICE_ID_LSI_SAS0079        0x0079
 
 #define PCI_VENDOR_ID_DEC                0x1011
 #define PCI_DEVICE_ID_DEC_21154          0x0026
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 06/13] megasas: Fix typo in megasas_dcmd_ld_get_list()
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
                   ` (4 preceding siblings ...)
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 05/13] megasas: add MegaRAID SAS 2108 emulation Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 07/13] megasas: Decode register names Hannes Reinecke
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

The check for a valid command buffer size was inverted.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 190a0bd..6933b56 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1118,7 +1118,7 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
     BusChild *kid;
 
     memset(&info, 0, dcmd_size);
-    if (cmd->iov_size < dcmd_size) {
+    if (cmd->iov_size > dcmd_size) {
         trace_megasas_dcmd_invalid_xfer_len(cmd->index, cmd->iov_size,
                                             dcmd_size);
         return MFI_STAT_INVALID_PARAMETER;
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 07/13] megasas: Decode register names
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
                   ` (5 preceding siblings ...)
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 06/13] megasas: Fix typo in megasas_dcmd_ld_get_list() Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 08/13] megasas: Clear unit attention on initial reset Hannes Reinecke
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

To ease debugging we should be decoding
the register names.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c | 23 ++++++++++++++++++++---
 trace-events      |  4 ++--
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 6933b56..13a49e8 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1993,6 +1993,7 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
     switch (addr) {
     case MFI_IDB:
         retval = 0;
+        trace_megasas_mmio_readl("MFI_IDB", retval);
         break;
     case MFI_OMSG0:
     case MFI_OSP0:
@@ -2000,29 +2001,35 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
             (s->fw_state & MFI_FWSTATE_MASK) |
             ((s->fw_sge & 0xff) << 16) |
             (s->fw_cmds & 0xFFFF);
+        trace_megasas_mmio_readl(addr == MFI_OMSG0 ? "MFI_OMSG0" : "MFI_OSP0",
+                                 retval);
         break;
     case MFI_OSTS:
         if (megasas_intr_enabled(s) && s->doorbell) {
             retval = base_class->osts;
         }
+        trace_megasas_mmio_readl("MFI_OSTS", retval);
         break;
     case MFI_OMSK:
         retval = s->intr_mask;
+        trace_megasas_mmio_readl("MFI_OMSK", retval);
         break;
     case MFI_ODCR0:
         retval = s->doorbell;
+        trace_megasas_mmio_readl("MFI_ODCR0", retval);
         break;
     case MFI_DIAG:
         retval = s->diag;
+        trace_megasas_mmio_readl("MFI_DIAG", retval);
         break;
     case MFI_OSP1:
         retval = 15;
+        trace_megasas_mmio_readl("MFI_OSP1", retval);
         break;
     default:
         trace_megasas_mmio_invalid_readl(addr);
         break;
     }
-    trace_megasas_mmio_readl(addr, retval);
     return retval;
 }
 
@@ -2037,9 +2044,9 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
     uint32_t frame_count;
     int i;
 
-    trace_megasas_mmio_writel(addr, val);
     switch (addr) {
     case MFI_IDB:
+        trace_megasas_mmio_writel("MFI_IDB", val);
         if (val & MFI_FWINIT_ABORT) {
             /* Abort all pending cmds */
             for (i = 0; i < s->fw_cmds; i++) {
@@ -2059,6 +2066,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
         }
         break;
     case MFI_OMSK:
+        trace_megasas_mmio_writel("MFI_OMSK", val);
         s->intr_mask = val;
         if (!megasas_intr_enabled(s) &&
             !msi_enabled(pci_dev) &&
@@ -2080,6 +2088,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
         }
         break;
     case MFI_ODCR0:
+        trace_megasas_mmio_writel("MFI_ODCR0", val);
         s->doorbell = 0;
         if (s->producer_pa && megasas_intr_enabled(s)) {
             /* Update reply queue pointer */
@@ -2093,14 +2102,20 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
         }
         break;
     case MFI_IQPH:
+        trace_megasas_mmio_writel("MFI_IQPH", val);
         /* Received high 32 bits of a 64 bit MFI frame address */
         s->frame_hi = val;
         break;
     case MFI_IQPL:
+        trace_megasas_mmio_writel("MFI_IQPL", val);
         /* Received low 32 bits of a 64 bit MFI frame address */
         /* Fallthrough */
     case MFI_IQP:
-        /* Received 64 bit MFI frame address */
+        if (addr == MFI_IQP) {
+            trace_megasas_mmio_writel("MFI_IQP", val);
+            /* Received 64 bit MFI frame address */
+            s->frame_hi = 0;
+        }
         frame_addr = (val & ~0x1F);
         /* Add possible 64 bit offset */
         frame_addr |= ((uint64_t)s->frame_hi << 32);
@@ -2109,6 +2124,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
         megasas_handle_frame(s, frame_addr, frame_count);
         break;
     case MFI_SEQ:
+        trace_megasas_mmio_writel("MFI_SEQ", val);
         /* Magic sequence to start ADP reset */
         if (adp_reset_seq[s->adp_reset] == val) {
             s->adp_reset++;
@@ -2121,6 +2137,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
         }
         break;
     case MFI_DIAG:
+        trace_megasas_mmio_writel("MFI_DIAG", val);
         /* ADP reset */
         if ((s->diag & MFI_DIAG_WRITE_ENABLE) &&
             (val & MFI_DIAG_RESET_ADP)) {
diff --git a/trace-events b/trace-events
index 380aa83..69b95f5 100644
--- a/trace-events
+++ b/trace-events
@@ -764,9 +764,9 @@ megasas_intr_enabled(void) "Interrupts enabled"
 megasas_intr_disabled(void) "Interrupts disabled"
 megasas_msix_enabled(int vector) "vector %d"
 megasas_msi_enabled(int vector) "vector %d"
-megasas_mmio_readl(unsigned long addr, uint32_t val) "addr 0x%lx: 0x%x"
+megasas_mmio_readl(const char *reg, uint32_t val) "reg %s: 0x%x"
 megasas_mmio_invalid_readl(unsigned long addr) "addr 0x%lx"
-megasas_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x"
+megasas_mmio_writel(const char *reg, uint32_t val) "reg %s: 0x%x"
 megasas_mmio_invalid_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x"
 
 # hw/audio/milkymist-ac97.c
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 08/13] megasas: Clear unit attention on initial reset
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
                   ` (6 preceding siblings ...)
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 07/13] megasas: Decode register names Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 09/13] megasas: Ignore duplicate init_firmware commands Hannes Reinecke
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

The EFI firmware doesn't handle unit attentions properly,
so we need to clear the Power On/Reset unit attention upon
initial reset.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c      | 18 +++++++++++++++++-
 hw/scsi/scsi-bus.c     |  2 +-
 include/hw/scsi/scsi.h |  1 +
 trace-events           |  2 +-
 4 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 13a49e8..53dda3d 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2205,11 +2205,26 @@ static void megasas_soft_reset(MegasasState *s)
     int i;
     MegasasCmd *cmd;
 
-    trace_megasas_reset();
+    trace_megasas_reset(s->fw_state);
     for (i = 0; i < s->fw_cmds; i++) {
         cmd = &s->frames[i];
         megasas_abort_command(cmd);
     }
+    if (s->fw_state == MFI_FWSTATE_READY) {
+        BusChild *kid;
+
+        /*
+         * The EFI firmware doesn't handle UA,
+         * so we need to clear the Power On/Reset UA
+         * after the initial reset.
+         */
+        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+            SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
+
+            sdev->unit_attention = SENSE_CODE(NO_SENSE);
+            scsi_device_unit_attention_reported(sdev);
+        }
+    }
     megasas_reset_frames(s);
     s->reply_queue_len = s->fw_cmds;
     s->reply_queue_pa = 0;
@@ -2337,6 +2352,7 @@ static int megasas_scsi_init(PCIDevice *dev)
         msix_vector_use(dev, 0);
     }
 
+    s->fw_state = MFI_FWSTATE_READY;
     if (!s->sas_addr) {
         s->sas_addr = ((NAA_LOCALLY_ASSIGNED_ID << 24) |
                        IEEE_COMPANY_LOCALLY_ASSIGNED) << 36;
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 919a86c..1f4d540 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -83,7 +83,7 @@ static SCSIRequest *scsi_device_alloc_req(SCSIDevice *s, uint32_t tag, uint32_t
     return NULL;
 }
 
-static void scsi_device_unit_attention_reported(SCSIDevice *s)
+void scsi_device_unit_attention_reported(SCSIDevice *s)
 {
     SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
     if (sc->unit_attention_reported) {
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 4e9bbd1..268d4ad 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -272,6 +272,7 @@ void scsi_req_retry(SCSIRequest *req);
 void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
 void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
 void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
+void scsi_device_unit_attention_reported(SCSIDevice *dev);
 int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
 SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
 
diff --git a/trace-events b/trace-events
index 69b95f5..11cfc44 100644
--- a/trace-events
+++ b/trace-events
@@ -754,7 +754,7 @@ megasas_dcmd_unsupported(int cmd, unsigned long size) "scmd %d: set properties l
 megasas_abort_frame(int cmd, int abort_cmd) "scmd %d: frame %x"
 megasas_abort_no_cmd(int cmd, uint64_t context) "scmd %d: no active command for frame context %" PRIx64 ""
 megasas_abort_invalid_context(int cmd, uint64_t context, int abort_cmd) "scmd %d: invalid frame context %" PRIx64 " for abort frame %x"
-megasas_reset(void) "Reset"
+megasas_reset(int fw_state) "firmware state %x"
 megasas_init(int sges, int cmds, const char *mode) "Using %d sges, %d cmds, %s mode"
 megasas_msix_raise(int vector) "vector %d"
 megasas_msi_raise(int vector) "vector %d"
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 09/13] megasas: Ignore duplicate init_firmware commands
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
                   ` (7 preceding siblings ...)
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 08/13] megasas: Clear unit attention on initial reset Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 10/13] megasas: Implement DCMD_CLUSTER_RESET_LD Hannes Reinecke
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

The windows driver is sending several init_firmware commands
when in MSI-X mode. It is, however, using only the first
queue. So disregard any additional init_firmware commands
until the HBA is reset.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c | 9 ++++++---
 trace-events      | 1 +
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 53dda3d..a240cf1 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -609,16 +609,19 @@ static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd)
 {
     PCIDevice *pcid = PCI_DEVICE(s);
     uint32_t pa_hi, pa_lo;
-    hwaddr iq_pa, initq_size;
-    struct mfi_init_qinfo *initq;
+    hwaddr iq_pa, initq_size = sizeof(struct mfi_init_qinfo);
+    struct mfi_init_qinfo *initq = NULL;
     uint32_t flags;
     int ret = MFI_STAT_OK;
 
+    if (s->reply_queue_pa) {
+        trace_megasas_initq_mapped(s->reply_queue_pa);
+        goto out;
+    }
     pa_lo = le32_to_cpu(cmd->frame->init.qinfo_new_addr_lo);
     pa_hi = le32_to_cpu(cmd->frame->init.qinfo_new_addr_hi);
     iq_pa = (((uint64_t) pa_hi << 32) | pa_lo);
     trace_megasas_init_firmware((uint64_t)iq_pa);
-    initq_size = sizeof(*initq);
     initq = pci_dma_map(pcid, iq_pa, &initq_size, 0);
     if (!initq || initq_size != sizeof(*initq)) {
         trace_megasas_initq_map_failed(cmd->index);
diff --git a/trace-events b/trace-events
index 11cfc44..62f04da 100644
--- a/trace-events
+++ b/trace-events
@@ -697,6 +697,7 @@ lm32_uart_irq_state(int level) "irq state %d"
 megasas_init_firmware(uint64_t pa) "pa %" PRIx64 " "
 megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) "queue at %" PRIx64 " len %d head %" PRIx64 " tail %" PRIx64 " flags %x"
 megasas_initq_map_failed(int frame) "scmd %d: failed to map queue"
+megasas_initq_mapped(uint64_t pa) "queue already mapped at %" PRIx64 ""
 megasas_initq_mismatch(int queue_len, int fw_cmds) "queue size %d max fw cmds %d"
 megasas_qf_found(unsigned int index, uint64_t pa) "mapped frame %x pa %" PRIx64 ""
 megasas_qf_new(unsigned int index, void *cmd) "return new frame %x cmd %p"
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 10/13] megasas: Implement DCMD_CLUSTER_RESET_LD
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
                   ` (8 preceding siblings ...)
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 09/13] megasas: Ignore duplicate init_firmware commands Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:54   ` Paolo Bonzini
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 11/13] megasas: Update queue logging Hannes Reinecke
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

Some implementations use DCMD_CLUSTER_RESET_LD to simulate
a device reset.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index a240cf1..4be4e88 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1419,9 +1419,23 @@ static int megasas_ctrl_shutdown(MegasasState *s, MegasasCmd *cmd)
     return MFI_STAT_OK;
 }
 
+/* Some implementations use CLUSTER RESET LD to simulate a device reset */
 static int megasas_cluster_reset_ld(MegasasState *s, MegasasCmd *cmd)
 {
-    return MFI_STAT_INVALID_DCMD;
+    uint16_t target_id;
+    int i;
+
+    /* mbox0 contains the device index */
+    target_id = le16_to_cpu(cmd->frame->dcmd.mbox[0]);
+    trace_megasas_dcmd_reset_ld(cmd->index, target_id);
+    for (i = 0; i < s->fw_cmds; i++) {
+        MegasasCmd *tmp_cmd = &s->frames[i];
+        if (tmp_cmd->req && tmp_cmd->req->dev->lun == target_id) {
+            SCSIDevice *d = tmp_cmd->req->dev;
+            qdev_reset_all(&d->qdev);
+        }
+    }
+    return MFI_STAT_OK;
 }
 
 static int megasas_dcmd_set_properties(MegasasState *s, MegasasCmd *cmd)
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 11/13] megasas: Update queue logging
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
                   ` (9 preceding siblings ...)
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 10/13] megasas: Implement DCMD_CLUSTER_RESET_LD Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 12/13] megasas: Rework frame queueing algorithm Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 13/13] megasas: Fixup MSI-X handling Hannes Reinecke
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

Improve queue logging by displaying head and tail pointer
of the completion queue.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c | 26 +++++++++++++++++---------
 trace-events      |  7 ++++---
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 4be4e88..e6dc7ec 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -526,8 +526,12 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s,
     cmd->count = count;
     s->busy++;
 
+    if (s->consumer_pa) {
+        s->reply_queue_tail = ldl_le_phys(&address_space_memory,
+                                          s->consumer_pa);
+    }
     trace_megasas_qf_enqueue(cmd->index, cmd->count, cmd->context,
-                             s->reply_queue_head, s->busy);
+                             s->reply_queue_head, s->reply_queue_tail, s->busy);
 
     return cmd;
 }
@@ -557,8 +561,10 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context)
                         s->reply_queue_pa + queue_offset, context);
         }
         s->reply_queue_head = megasas_next_index(s, tail, s->fw_cmds);
-        trace_megasas_qf_complete(context, tail, queue_offset,
-                                  s->busy, s->doorbell);
+        s->reply_queue_tail = ldl_le_phys(&address_space_memory,
+                                          s->consumer_pa);
+        trace_megasas_qf_complete(context, s->reply_queue_head,
+                                  s->reply_queue_tail, s->busy, s->doorbell);
     }
 
     if (megasas_intr_enabled(s)) {
@@ -1652,7 +1658,6 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
                                bool is_logical)
 {
     uint8_t *cdb;
-    int len;
     bool is_write;
     struct SCSIDevice *sdev = NULL;
 
@@ -1713,16 +1718,16 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
     }
 
     is_write = (cmd->req->cmd.mode == SCSI_XFER_TO_DEV);
-    len = megasas_enqueue_req(cmd, is_write);
-    if (len > 0) {
+    if (cmd->iov_size) {
         if (is_write) {
-            trace_megasas_scsi_write_start(cmd->index, len);
+            trace_megasas_scsi_write_start(cmd->index, cmd->iov_size);
         } else {
-            trace_megasas_scsi_read_start(cmd->index, len);
+            trace_megasas_scsi_read_start(cmd->index, cmd->iov_size);
         }
     } else {
         trace_megasas_scsi_nodata(cmd->index);
     }
+    megasas_enqueue_req(cmd, is_write);
     return MFI_STAT_INVALID_STATUS;
 }
 
@@ -2109,7 +2114,10 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
         s->doorbell = 0;
         if (s->producer_pa && megasas_intr_enabled(s)) {
             /* Update reply queue pointer */
-            trace_megasas_qf_update(s->reply_queue_head, s->busy);
+            s->reply_queue_tail = ldl_le_phys(&address_space_memory,
+                                              s->consumer_pa);
+            trace_megasas_qf_update(s->reply_queue_head, s->reply_queue_tail,
+                                    s->busy);
             stl_le_phys(&address_space_memory,
                         s->producer_pa, s->reply_queue_head);
             if (!msix_enabled(pci_dev)) {
diff --git a/trace-events b/trace-events
index 62f04da..9c75501 100644
--- a/trace-events
+++ b/trace-events
@@ -702,11 +702,11 @@ megasas_initq_mismatch(int queue_len, int fw_cmds) "queue size %d max fw cmds %d
 megasas_qf_found(unsigned int index, uint64_t pa) "mapped frame %x pa %" PRIx64 ""
 megasas_qf_new(unsigned int index, void *cmd) "return new frame %x cmd %p"
 megasas_qf_failed(unsigned long pa) "all frames busy for frame %lx"
-megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int tail, int busy) "enqueue frame %x count %d context %" PRIx64 " tail %x busy %d"
-megasas_qf_update(unsigned int head, unsigned int busy) "reply queue head %x busy %d"
+megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int head, unsigned int tail, int busy) "frame %x count %d context %" PRIx64 " head %x tail %x busy %d"
+megasas_qf_update(unsigned int head, unsigned int tail, unsigned int busy) "head %x tail %x busy %d"
 megasas_qf_map_failed(int cmd, unsigned long frame) "scmd %d: frame %lu"
 megasas_qf_complete_noirq(uint64_t context) "context %" PRIx64 " "
-megasas_qf_complete(uint64_t context, unsigned int tail, unsigned int offset, int busy, unsigned int doorbell) "context %" PRIx64 " tail %x offset %d busy %d doorbell %x"
+megasas_qf_complete(uint64_t context, unsigned int head, unsigned int tail, int busy, unsigned int doorbell) "context %" PRIx64 " head %x tail %x busy %d doorbell %x"
 megasas_frame_busy(uint64_t addr) "frame %" PRIx64 " busy"
 megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) "scmd %d: MFI cmd %x"
 megasas_handle_scsi(const char *frame, int bus, int dev, int lun, void *sdev, unsigned long size) "%s dev %x/%x/%x sdev %p xfer %lu"
@@ -751,6 +751,7 @@ megasas_dcmd_ld_get_info(int cmd, int ld_id) "scmd %d: dev %d"
 megasas_dcmd_ld_list_query(int cmd, int flags) "scmd %d: query flags %x"
 megasas_dcmd_pd_get_info(int cmd, int pd_id) "scmd %d: dev %d"
 megasas_dcmd_pd_list_query(int cmd, int flags) "scmd %d: query flags %x"
+megasas_dcmd_reset_ld(int cmd, int target_id) "scmd %d: dev %d"
 megasas_dcmd_unsupported(int cmd, unsigned long size) "scmd %d: set properties len %ld"
 megasas_abort_frame(int cmd, int abort_cmd) "scmd %d: frame %x"
 megasas_abort_no_cmd(int cmd, uint64_t context) "scmd %d: no active command for frame context %" PRIx64 ""
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 12/13] megasas: Rework frame queueing algorithm
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
                   ` (10 preceding siblings ...)
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 11/13] megasas: Update queue logging Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 13/13] megasas: Fixup MSI-X handling Hannes Reinecke
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

Windows requires the frames to be unmapped, otherwise we run
into a race condition where the updated frame data is not
visible to the guest.
With that we can simplify the queue algorithm and use a bitmap
for tracking free frames.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c | 96 ++++++++++++++++++++++++++-----------------------------
 trace-events      |  6 ++--
 2 files changed, 48 insertions(+), 54 deletions(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index e6dc7ec..8e21ed5 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -114,7 +114,7 @@ typedef struct MegasasState {
     uint64_t producer_pa;
 
     MegasasCmd frames[MEGASAS_MAX_FRAMES];
-
+    DECLARE_BITMAP(frame_map, MEGASAS_MAX_FRAMES);
     SCSIBus bus;
 } MegasasState;
 
@@ -462,34 +462,20 @@ static MegasasCmd *megasas_lookup_frame(MegasasState *s,
     return cmd;
 }
 
-static MegasasCmd *megasas_next_frame(MegasasState *s,
-    hwaddr frame)
+static void megasas_unmap_frame(MegasasState *s, MegasasCmd *cmd)
 {
-    MegasasCmd *cmd = NULL;
-    int num = 0, index;
+    PCIDevice *p = PCI_DEVICE(s);
 
-    cmd = megasas_lookup_frame(s, frame);
-    if (cmd) {
-        trace_megasas_qf_found(cmd->index, cmd->pa);
-        return cmd;
-    }
-    index = s->reply_queue_head;
-    num = 0;
-    while (num < s->fw_cmds) {
-        if (!s->frames[index].pa) {
-            cmd = &s->frames[index];
-            break;
-        }
-        index = megasas_next_index(s, index, s->fw_cmds);
-        num++;
-    }
-    if (!cmd) {
-        trace_megasas_qf_failed(frame);
-    }
-    trace_megasas_qf_new(index, cmd);
-    return cmd;
+    pci_dma_unmap(p, cmd->frame, cmd->pa_size, 0, 0);
+    cmd->frame = NULL;
+    cmd->pa = 0;
+    clear_bit(cmd->index, s->frame_map);
 }
 
+/*
+ * This absolutely needs to be locked if
+ * qemu ever goes multithreaded.
+ */
 static MegasasCmd *megasas_enqueue_frame(MegasasState *s,
     hwaddr frame, uint64_t context, int count)
 {
@@ -497,31 +483,40 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s,
     MegasasCmd *cmd = NULL;
     int frame_size = MFI_FRAME_SIZE * 16;
     hwaddr frame_size_p = frame_size;
+    unsigned long index;
 
-    cmd = megasas_next_frame(s, frame);
-    /* All frames busy */
-    if (!cmd) {
+    index = 0;
+    while (index < s->fw_cmds) {
+        index = find_next_zero_bit(s->frame_map, s->fw_cmds, index);
+        if (!s->frames[index].pa)
+            break;
+        /* Busy frame found */
+        trace_megasas_qf_mapped(index);
+    }
+    if (index >= s->fw_cmds) {
+        /* All frames busy */
+        trace_megasas_qf_busy(frame);
         return NULL;
     }
-    if (!cmd->pa) {
-        cmd->pa = frame;
-        /* Map all possible frames */
-        cmd->frame = pci_dma_map(pcid, frame, &frame_size_p, 0);
-        if (frame_size_p != frame_size) {
-            trace_megasas_qf_map_failed(cmd->index, (unsigned long)frame);
-            if (cmd->frame) {
-                pci_dma_unmap(pcid, cmd->frame, frame_size_p, 0, 0);
-                cmd->frame = NULL;
-                cmd->pa = 0;
-            }
-            s->event_count++;
-            return NULL;
-        }
-        cmd->pa_size = frame_size_p;
-        cmd->context = context;
-        if (!megasas_use_queue64(s)) {
-            cmd->context &= (uint64_t)0xFFFFFFFF;
+    cmd = &s->frames[index];
+    set_bit(index, s->frame_map);
+    trace_megasas_qf_new(index, frame);
+
+    cmd->pa = frame;
+    /* Map all possible frames */
+    cmd->frame = pci_dma_map(pcid, frame, &frame_size_p, 0);
+    if (frame_size_p != frame_size) {
+        trace_megasas_qf_map_failed(cmd->index, (unsigned long)frame);
+        if (cmd->frame) {
+            megasas_unmap_frame(s, cmd);
         }
+        s->event_count++;
+        return NULL;
+    }
+    cmd->pa_size = frame_size_p;
+    cmd->context = context;
+    if (!megasas_use_queue64(s)) {
+        cmd->context &= (uint64_t)0xFFFFFFFF;
     }
     cmd->count = count;
     s->busy++;
@@ -543,7 +538,6 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context)
 
     /* Decrement busy count */
     s->busy--;
-
     if (s->reply_queue_pa) {
         /*
          * Put command on the reply queue.
@@ -589,18 +583,16 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context)
 
 static void megasas_reset_frames(MegasasState *s)
 {
-    PCIDevice *pcid = PCI_DEVICE(s);
     int i;
     MegasasCmd *cmd;
 
     for (i = 0; i < s->fw_cmds; i++) {
         cmd = &s->frames[i];
         if (cmd->pa) {
-            pci_dma_unmap(pcid, cmd->frame, cmd->pa_size, 0, 0);
-            cmd->frame = NULL;
-            cmd->pa = 0;
+            megasas_unmap_frame(s, cmd);
         }
     }
+    bitmap_zero(s->frame_map, MEGASAS_MAX_FRAMES);
 }
 
 static void megasas_abort_command(MegasasCmd *cmd)
@@ -1897,6 +1889,7 @@ static void megasas_command_complete(SCSIRequest *req, uint32_t status,
         cmd->req = NULL;
     }
     cmd->frame->header.cmd_status = cmd_status;
+    megasas_unmap_frame(cmd->state, cmd);
     megasas_complete_frame(cmd->state, cmd->context);
 }
 
@@ -2000,6 +1993,7 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr,
         } else {
             megasas_frame_set_cmd_status(frame_addr, frame_status);
         }
+        megasas_unmap_frame(s, cmd);
         megasas_complete_frame(s, cmd->context);
     }
 }
diff --git a/trace-events b/trace-events
index 9c75501..8bf133b 100644
--- a/trace-events
+++ b/trace-events
@@ -699,9 +699,9 @@ megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tai
 megasas_initq_map_failed(int frame) "scmd %d: failed to map queue"
 megasas_initq_mapped(uint64_t pa) "queue already mapped at %" PRIx64 ""
 megasas_initq_mismatch(int queue_len, int fw_cmds) "queue size %d max fw cmds %d"
-megasas_qf_found(unsigned int index, uint64_t pa) "mapped frame %x pa %" PRIx64 ""
-megasas_qf_new(unsigned int index, void *cmd) "return new frame %x cmd %p"
-megasas_qf_failed(unsigned long pa) "all frames busy for frame %lx"
+megasas_qf_mapped(unsigned int index) "skip mapped frame %x"
+megasas_qf_new(unsigned int index, uint64_t frame) "frame %x addr %" PRIx64 ""
+megasas_qf_busy(unsigned long pa) "all frames busy for frame %lx"
 megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int head, unsigned int tail, int busy) "frame %x count %d context %" PRIx64 " head %x tail %x busy %d"
 megasas_qf_update(unsigned int head, unsigned int tail, unsigned int busy) "head %x tail %x busy %d"
 megasas_qf_map_failed(int cmd, unsigned long frame) "scmd %d: frame %lu"
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH 13/13] megasas: Fixup MSI-X handling
  2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
                   ` (11 preceding siblings ...)
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 12/13] megasas: Rework frame queueing algorithm Hannes Reinecke
@ 2014-10-29 12:00 ` Hannes Reinecke
  12 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 12:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Hannes Reinecke, Andreas Faerber, Nic Bellinger,
	Alexander Graf

MSI-X works slightly different than INTx; the doorbell
registers are not necessarily used as MSI-X interrupts
are directed anyway. So the head pointer on the
reply queue needs to be updated as soon as a frame
is completed, and we can set the doorbell only
when in INTx mode.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c | 48 ++++++++++++++++++++++++------------------------
 trace-events      |  2 +-
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 8e21ed5..8b5250c 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -544,34 +544,41 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context)
          * Context is opaque, but emulation is running in
          * little endian. So convert it.
          */
-        tail = s->reply_queue_head;
         if (megasas_use_queue64(s)) {
-            queue_offset = tail * sizeof(uint64_t);
+            queue_offset = s->reply_queue_head * sizeof(uint64_t);
             stq_le_phys(&address_space_memory,
                         s->reply_queue_pa + queue_offset, context);
         } else {
-            queue_offset = tail * sizeof(uint32_t);
+            queue_offset = s->reply_queue_head * sizeof(uint32_t);
             stl_le_phys(&address_space_memory,
                         s->reply_queue_pa + queue_offset, context);
         }
-        s->reply_queue_head = megasas_next_index(s, tail, s->fw_cmds);
         s->reply_queue_tail = ldl_le_phys(&address_space_memory,
                                           s->consumer_pa);
         trace_megasas_qf_complete(context, s->reply_queue_head,
-                                  s->reply_queue_tail, s->busy, s->doorbell);
+                                  s->reply_queue_tail, s->busy);
     }
 
     if (megasas_intr_enabled(s)) {
+        /* Update reply queue pointer */
+        s->reply_queue_tail = ldl_le_phys(&address_space_memory,
+                                          s->consumer_pa);
+        tail = s->reply_queue_head;
+        s->reply_queue_head = megasas_next_index(s, tail, s->fw_cmds);
+        trace_megasas_qf_update(s->reply_queue_head, s->reply_queue_tail,
+                                s->busy);
+        stl_le_phys(&address_space_memory,
+                    s->producer_pa, s->reply_queue_head);
         /* Notify HBA */
-        s->doorbell++;
-        if (s->doorbell == 1) {
-            if (msix_enabled(pci_dev)) {
-                trace_megasas_msix_raise(0);
-                msix_notify(pci_dev, 0);
-            } else if (msi_enabled(pci_dev)) {
-                trace_megasas_msi_raise(0);
-                msi_notify(pci_dev, 0);
-            } else {
+        if (msix_enabled(pci_dev)) {
+            trace_megasas_msix_raise(0);
+            msix_notify(pci_dev, 0);
+        } else if (msi_enabled(pci_dev)) {
+            trace_megasas_msi_raise(0);
+            msi_notify(pci_dev, 0);
+        } else {
+            s->doorbell++;
+            if (s->doorbell == 1) {
                 trace_megasas_irq_raise();
                 pci_irq_assert(pci_dev);
             }
@@ -2031,7 +2038,7 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
         trace_megasas_mmio_readl("MFI_OMSK", retval);
         break;
     case MFI_ODCR0:
-        retval = s->doorbell;
+        retval = s->doorbell ? 1 : 0;
         trace_megasas_mmio_readl("MFI_ODCR0", retval);
         break;
     case MFI_DIAG:
@@ -2106,15 +2113,8 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
     case MFI_ODCR0:
         trace_megasas_mmio_writel("MFI_ODCR0", val);
         s->doorbell = 0;
-        if (s->producer_pa && megasas_intr_enabled(s)) {
-            /* Update reply queue pointer */
-            s->reply_queue_tail = ldl_le_phys(&address_space_memory,
-                                              s->consumer_pa);
-            trace_megasas_qf_update(s->reply_queue_head, s->reply_queue_tail,
-                                    s->busy);
-            stl_le_phys(&address_space_memory,
-                        s->producer_pa, s->reply_queue_head);
-            if (!msix_enabled(pci_dev)) {
+        if (megasas_intr_enabled(s)) {
+            if (!msix_enabled(pci_dev) && !msi_enabled(pci_dev)) {
                 trace_megasas_irq_lower();
                 pci_irq_deassert(pci_dev);
             }
diff --git a/trace-events b/trace-events
index 8bf133b..a87767a 100644
--- a/trace-events
+++ b/trace-events
@@ -706,7 +706,7 @@ megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, uns
 megasas_qf_update(unsigned int head, unsigned int tail, unsigned int busy) "head %x tail %x busy %d"
 megasas_qf_map_failed(int cmd, unsigned long frame) "scmd %d: frame %lu"
 megasas_qf_complete_noirq(uint64_t context) "context %" PRIx64 " "
-megasas_qf_complete(uint64_t context, unsigned int head, unsigned int tail, int busy, unsigned int doorbell) "context %" PRIx64 " head %x tail %x busy %d doorbell %x"
+megasas_qf_complete(uint64_t context, unsigned int head, unsigned int tail, int busy) "context %" PRIx64 " head %x tail %x busy %d"
 megasas_frame_busy(uint64_t addr) "frame %" PRIx64 " busy"
 megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) "scmd %d: MFI cmd %x"
 megasas_handle_scsi(const char *frame, int bus, int dev, int lun, void *sdev, unsigned long size) "%s dev %x/%x/%x sdev %p xfer %lu"
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH 10/13] megasas: Implement DCMD_CLUSTER_RESET_LD
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 10/13] megasas: Implement DCMD_CLUSTER_RESET_LD Hannes Reinecke
@ 2014-10-29 12:54   ` Paolo Bonzini
  2014-10-29 13:23     ` Hannes Reinecke
  0 siblings, 1 reply; 21+ messages in thread
From: Paolo Bonzini @ 2014-10-29 12:54 UTC (permalink / raw)
  To: Hannes Reinecke, qemu-devel
  Cc: Andreas Faerber, Nic Bellinger, Alexander Graf



On 10/29/2014 01:00 PM, Hannes Reinecke wrote:
> +    trace_megasas_dcmd_reset_ld(cmd->index, target_id);
> +    for (i = 0; i < s->fw_cmds; i++) {
> +        MegasasCmd *tmp_cmd = &s->frames[i];
> +        if (tmp_cmd->req && tmp_cmd->req->dev->lun == target_id) {

Why ->lun?

Paolo

> +            SCSIDevice *d = tmp_cmd->req->dev;
> +            qdev_reset_all(&d->qdev);

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH 10/13] megasas: Implement DCMD_CLUSTER_RESET_LD
  2014-10-29 12:54   ` Paolo Bonzini
@ 2014-10-29 13:23     ` Hannes Reinecke
  2014-10-29 13:28       ` Paolo Bonzini
  0 siblings, 1 reply; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-29 13:23 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: Andreas Faerber, Nic Bellinger, Alexander Graf

On 10/29/2014 01:54 PM, Paolo Bonzini wrote:
>
>
> On 10/29/2014 01:00 PM, Hannes Reinecke wrote:
>> +    trace_megasas_dcmd_reset_ld(cmd->index, target_id);
>> +    for (i = 0; i < s->fw_cmds; i++) {
>> +        MegasasCmd *tmp_cmd = &s->frames[i];
>> +        if (tmp_cmd->req && tmp_cmd->req->dev->lun == target_id) {
>
> Why ->lun?
>
Gna. You are correct, it should be ->id.

Cheers,

Hannes

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH 10/13] megasas: Implement DCMD_CLUSTER_RESET_LD
  2014-10-29 13:23     ` Hannes Reinecke
@ 2014-10-29 13:28       ` Paolo Bonzini
  0 siblings, 0 replies; 21+ messages in thread
From: Paolo Bonzini @ 2014-10-29 13:28 UTC (permalink / raw)
  To: Hannes Reinecke, qemu-devel
  Cc: Andreas Faerber, Nic Bellinger, Alexander Graf



On 10/29/2014 02:23 PM, Hannes Reinecke wrote:
> On 10/29/2014 01:54 PM, Paolo Bonzini wrote:
>>
>>
>> On 10/29/2014 01:00 PM, Hannes Reinecke wrote:
>>> +    trace_megasas_dcmd_reset_ld(cmd->index, target_id);
>>> +    for (i = 0; i < s->fw_cmds; i++) {
>>> +        MegasasCmd *tmp_cmd = &s->frames[i];
>>> +        if (tmp_cmd->req && tmp_cmd->req->dev->lun == target_id) {
>>
>> Why ->lun?
>>
> Gna. You are correct, it should be ->id.

No big deal, fixing it myself.

Paolo

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH 05/13] megasas: add MegaRAID SAS 2108 emulation
  2014-10-29 12:00 ` [Qemu-devel] [PATCH 05/13] megasas: add MegaRAID SAS 2108 emulation Hannes Reinecke
@ 2014-10-31 17:08   ` Paolo Bonzini
  2014-10-31 17:30     ` Hannes Reinecke
  0 siblings, 1 reply; 21+ messages in thread
From: Paolo Bonzini @ 2014-10-31 17:08 UTC (permalink / raw)
  To: Hannes Reinecke, qemu-devel
  Cc: Andreas Faerber, Nic Bellinger, Alexander Graf



On 29/10/2014 13:00, Hannes Reinecke wrote:
> The 2108 chip supports MSI and MSI-X, so update the emulation
> to support both chips.

Is it expected that it doesn't work with latest SeaBIOS?

> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
>  hw/scsi/megasas.c        | 218 +++++++++++++++++++++++++++++++++++++++++------
>  hw/scsi/mfi.h            |   7 ++
>  include/hw/pci/pci_ids.h |   1 +
>  3 files changed, 201 insertions(+), 25 deletions(-)
> 
> diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
> index 10e9d7a..190a0bd 100644
> --- a/hw/scsi/megasas.c
> +++ b/hw/scsi/megasas.c
> @@ -30,9 +30,11 @@
>  
>  #include "mfi.h"
>  
> -#define MEGASAS_VERSION "1.70"
> +#define MEGASAS_VERSION_GEN1 "1.70"
> +#define MEGASAS_VERSION_GEN2 "1.80"
>  #define MEGASAS_MAX_FRAMES 2048         /* Firmware limit at 65535 */
>  #define MEGASAS_DEFAULT_FRAMES 1000     /* Windows requires this */
> +#define MEGASAS_GEN2_DEFAULT_FRAMES 1008     /* Windows requires this */
>  #define MEGASAS_MAX_SGE 128             /* Firmware limit */
>  #define MEGASAS_DEFAULT_SGE 80
>  #define MEGASAS_MAX_SECTORS 0xFFFF      /* No real limit */
> @@ -90,6 +92,8 @@ typedef struct MegasasState {
>      int intr_mask;
>      int doorbell;
>      int busy;
> +    int diag;
> +    int adp_reset;
>  
>      MegasasCmd *event_cmd;
>      int event_locale;
> @@ -114,10 +118,26 @@ typedef struct MegasasState {
>      SCSIBus bus;
>  } MegasasState;
>  
> -#define TYPE_MEGASAS "megasas"
> +typedef struct MegasasBaseClass {
> +    PCIDeviceClass parent_class;
> +    const char *product_name;
> +    const char *product_version;
> +    int mmio_bar;
> +    int ioport_bar;
> +    int osts;
> +} MegasasBaseClass;
> +
> +#define TYPE_MEGASAS_BASE "megasas-base"
> +#define TYPE_MEGASAS_GEN1 "megasas"
> +#define TYPE_MEGASAS_GEN2 "megasas-gen2"
>  
>  #define MEGASAS(obj) \
> -    OBJECT_CHECK(MegasasState, (obj), TYPE_MEGASAS)
> +    OBJECT_CHECK(MegasasState, (obj), TYPE_MEGASAS_BASE)
> +
> +#define MEGASAS_DEVICE_CLASS(oc) \
> +    OBJECT_CLASS_CHECK(MegasasBaseClass, (oc), TYPE_MEGASAS_BASE)
> +#define MEGASAS_DEVICE_GET_CLASS(oc) \
> +    OBJECT_GET_CLASS(MegasasBaseClass, (oc), TYPE_MEGASAS_BASE)
>  
>  #define MEGASAS_INTR_DISABLED_MASK 0xFFFFFFFF
>  
> @@ -685,6 +705,8 @@ static void megasas_finish_dcmd(MegasasCmd *cmd, uint32_t iov_size)
>  static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
>  {
>      PCIDevice *pci_dev = PCI_DEVICE(s);
> +    PCIDeviceClass *pci_class = PCI_DEVICE_GET_CLASS(pci_dev);
> +    MegasasBaseClass *base_class = MEGASAS_DEVICE_GET_CLASS(s);
>      struct mfi_ctrl_info info;
>      size_t dcmd_size = sizeof(info);
>      BusChild *kid;
> @@ -697,10 +719,10 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
>          return MFI_STAT_INVALID_PARAMETER;
>      }
>  
> -    info.pci.vendor = cpu_to_le16(PCI_VENDOR_ID_LSI_LOGIC);
> -    info.pci.device = cpu_to_le16(PCI_DEVICE_ID_LSI_SAS1078);
> -    info.pci.subvendor = cpu_to_le16(PCI_VENDOR_ID_LSI_LOGIC);
> -    info.pci.subdevice = cpu_to_le16(0x1013);
> +    info.pci.vendor = cpu_to_le16(pci_class->vendor_id);
> +    info.pci.device = cpu_to_le16(pci_class->device_id);
> +    info.pci.subvendor = cpu_to_le16(pci_class->subsystem_vendor_id);
> +    info.pci.subdevice = cpu_to_le16(pci_class->subsystem_id);
>  
>      /*
>       * For some reason the firmware supports
> @@ -727,11 +749,12 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
>          num_pd_disks++;
>      }
>  
> -    memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20);
> +    memcpy(info.product_name, base_class->product_name, 24);
>      snprintf(info.serial_number, 32, "%s", s->hba_serial);
>      snprintf(info.package_version, 0x60, "%s-QEMU", QEMU_VERSION);
>      memcpy(info.image_component[0].name, "APP", 3);
> -    memcpy(info.image_component[0].version, MEGASAS_VERSION "-QEMU", 9);
> +    snprintf(info.image_component[0].version, 10, "%s-QEMU",
> +             base_class->product_version);
>      memcpy(info.image_component[0].build_date, "Apr  1 2014", 11);
>      memcpy(info.image_component[0].build_time, "12:34:56", 8);
>      info.image_component_count = 1;
> @@ -1963,6 +1986,8 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
>                                    unsigned size)
>  {
>      MegasasState *s = opaque;
> +    PCIDevice *pci_dev = PCI_DEVICE(s);
> +    MegasasBaseClass *base_class = MEGASAS_DEVICE_GET_CLASS(s);
>      uint32_t retval = 0;
>  
>      switch (addr) {
> @@ -1971,14 +1996,14 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
>          break;
>      case MFI_OMSG0:
>      case MFI_OSP0:
> -        retval = (megasas_use_msix(s) ? MFI_FWSTATE_MSIX_SUPPORTED : 0) |
> +        retval = (msix_present(pci_dev) ? MFI_FWSTATE_MSIX_SUPPORTED : 0) |
>              (s->fw_state & MFI_FWSTATE_MASK) |
>              ((s->fw_sge & 0xff) << 16) |
>              (s->fw_cmds & 0xFFFF);
>          break;
>      case MFI_OSTS:
>          if (megasas_intr_enabled(s) && s->doorbell) {
> -            retval = MFI_1078_RM | 1;
> +            retval = base_class->osts;
>          }
>          break;
>      case MFI_OMSK:
> @@ -1987,6 +2012,12 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
>      case MFI_ODCR0:
>          retval = s->doorbell;
>          break;
> +    case MFI_DIAG:
> +        retval = s->diag;
> +        break;
> +    case MFI_OSP1:
> +        retval = 15;
> +        break;
>      default:
>          trace_megasas_mmio_invalid_readl(addr);
>          break;
> @@ -1995,6 +2026,8 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
>      return retval;
>  }
>  
> +static int adp_reset_seq[] = {0x00, 0x04, 0x0b, 0x02, 0x07, 0x0d};
> +
>  static void megasas_mmio_write(void *opaque, hwaddr addr,
>                                 uint64_t val, unsigned size)
>  {
> @@ -2020,6 +2053,10 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
>          if (val & MFI_FWINIT_MFIMODE) {
>              /* discard MFIs */
>          }
> +        if (val & MFI_FWINIT_STOP_ADP) {
> +            /* Terminal error, stop processing */
> +            s->fw_state = MFI_FWSTATE_FAULT;
> +        }
>          break;
>      case MFI_OMSK:
>          s->intr_mask = val;
> @@ -2039,6 +2076,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
>              }
>          } else {
>              trace_megasas_intr_disabled();
> +            megasas_soft_reset(s);
>          }
>          break;
>      case MFI_ODCR0:
> @@ -2060,8 +2098,9 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
>          break;
>      case MFI_IQPL:
>          /* Received low 32 bits of a 64 bit MFI frame address */
> +        /* Fallthrough */
>      case MFI_IQP:
> -        /* Received 32 bit MFI frame address */
> +        /* Received 64 bit MFI frame address */
>          frame_addr = (val & ~0x1F);
>          /* Add possible 64 bit offset */
>          frame_addr |= ((uint64_t)s->frame_hi << 32);
> @@ -2069,6 +2108,28 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
>          frame_count = (val >> 1) & 0xF;
>          megasas_handle_frame(s, frame_addr, frame_count);
>          break;
> +    case MFI_SEQ:
> +        /* Magic sequence to start ADP reset */
> +        if (adp_reset_seq[s->adp_reset] == val) {
> +            s->adp_reset++;
> +        } else {
> +            s->adp_reset = 0;
> +            s->diag = 0;
> +        }
> +        if (s->adp_reset == 6) {
> +            s->diag = MFI_DIAG_WRITE_ENABLE;
> +        }
> +        break;
> +    case MFI_DIAG:
> +        /* ADP reset */
> +        if ((s->diag & MFI_DIAG_WRITE_ENABLE) &&
> +            (val & MFI_DIAG_RESET_ADP)) {
> +            s->diag |= MFI_DIAG_RESET_ADP;
> +            megasas_soft_reset(s);
> +            s->adp_reset = 0;
> +            s->diag = 0;
> +        }
> +        break;
>      default:
>          trace_megasas_mmio_invalid_writel(addr, val);
>          break;
> @@ -2153,7 +2214,7 @@ static void megasas_scsi_reset(DeviceState *dev)
>      megasas_soft_reset(s);
>  }
>  
> -static const VMStateDescription vmstate_megasas = {
> +static VMStateDescription vmstate_megasas_gen1 = {
>      .name = "megasas",
>      .version_id = 0,
>      .minimum_version_id = 0,
> @@ -2171,6 +2232,25 @@ static const VMStateDescription vmstate_megasas = {
>      }
>  };
>  
> +static VMStateDescription vmstate_megasas_gen2 = {
> +    .name = "megasas-gen2",
> +    .version_id = 0,
> +    .minimum_version_id = 0,
> +    .minimum_version_id_old = 0,
> +    .fields      = (VMStateField[]) {
> +        VMSTATE_PCIE_DEVICE(parent_obj, MegasasState),
> +        VMSTATE_MSIX(parent_obj, MegasasState),
> +
> +        VMSTATE_INT32(fw_state, MegasasState),
> +        VMSTATE_INT32(intr_mask, MegasasState),
> +        VMSTATE_INT32(doorbell, MegasasState),
> +        VMSTATE_UINT64(reply_queue_pa, MegasasState),
> +        VMSTATE_UINT64(consumer_pa, MegasasState),
> +        VMSTATE_UINT64(producer_pa, MegasasState),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
>  static void megasas_scsi_uninit(PCIDevice *d)
>  {
>      MegasasState *s = MEGASAS(d);
> @@ -2198,6 +2278,7 @@ static int megasas_scsi_init(PCIDevice *dev)
>  {
>      DeviceState *d = DEVICE(dev);
>      MegasasState *s = MEGASAS(dev);
> +    MegasasBaseClass *b = MEGASAS_DEVICE_GET_CLASS(s);
>      uint8_t *pci_conf;
>      int i, bar_type;
>      Error *err = NULL;
> @@ -2221,14 +2302,18 @@ static int megasas_scsi_init(PCIDevice *dev)
>          s->flags &= ~MEGASAS_MASK_USE_MSI;
>      }
>      if (megasas_use_msix(s) &&
> -        msix_init(dev, 15, &s->mmio_io, 0, 0x2000,
> -                  &s->mmio_io, 0, 0x3800, 0x68)) {
> +        msix_init(dev, 15, &s->mmio_io, b->mmio_bar, 0x2000,
> +                  &s->mmio_io, b->mmio_bar, 0x3800, 0x68)) {
>          s->flags &= ~MEGASAS_MASK_USE_MSIX;
>      }
> +    if (pci_is_express(dev)) {
> +        pcie_endpoint_cap_init(dev, 0xa0);
> +    }
>  
>      bar_type = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64;
> -    pci_register_bar(dev, 0, bar_type, &s->mmio_io);
> -    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io);
> +    pci_register_bar(dev, b->ioport_bar,
> +                     PCI_BASE_ADDRESS_SPACE_IO, &s->port_io);
> +    pci_register_bar(dev, b->mmio_bar, bar_type, &s->mmio_io);
>      pci_register_bar(dev, 3, bar_type, &s->queue_io);
>  
>      if (megasas_use_msix(s)) {
> @@ -2291,7 +2376,7 @@ megasas_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len)
>      msi_write_config(pci, addr, val, len);
>  }
>  
> -static Property megasas_properties[] = {
> +static Property megasas_properties_gen1[] = {
>      DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge,
>                         MEGASAS_DEFAULT_SGE),
>      DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds,
> @@ -2307,36 +2392,119 @@ static Property megasas_properties[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> +static Property megasas_properties_gen2[] = {
> +    DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge,
> +                       MEGASAS_DEFAULT_SGE),
> +    DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds,
> +                       MEGASAS_GEN2_DEFAULT_FRAMES),
> +    DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial),
> +    DEFINE_PROP_UINT64("sas_address", MegasasState, sas_addr, 0),
> +    DEFINE_PROP_BIT("use_msi", MegasasState, flags,
> +                    MEGASAS_FLAG_USE_MSI, true),
> +    DEFINE_PROP_BIT("use_msix", MegasasState, flags,
> +                    MEGASAS_FLAG_USE_MSIX, true),
> +    DEFINE_PROP_BIT("use_jbod", MegasasState, flags,
> +                    MEGASAS_FLAG_USE_JBOD, false),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +typedef struct MegasasInfo {
> +    const char *name;
> +    const char *desc;
> +    const char *product_name;
> +    const char *product_version;
> +    uint16_t device_id;
> +    uint16_t subsystem_id;
> +    int ioport_bar;
> +    int mmio_bar;
> +    bool is_express;
> +    int osts;
> +    VMStateDescription *vmsd;
> +    Property *props;
> +} MegasasInfo;
> +
> +static struct MegasasInfo megasas_devices[] = {
> +    {
> +        .name = TYPE_MEGASAS_GEN1,
> +        .desc = "LSI MegaRAID SAS 1078",
> +        .product_name = "LSI MegaRAID SAS 8708EM2",
> +        .product_version = MEGASAS_VERSION_GEN1,
> +        .device_id = PCI_DEVICE_ID_LSI_SAS1078,
> +        .subsystem_id = 0x1013,
> +        .ioport_bar = 2,
> +        .mmio_bar = 0,
> +        .osts = MFI_1078_RM | 1,
> +        .is_express = false,
> +        .vmsd = &vmstate_megasas_gen1,
> +        .props = megasas_properties_gen1,
> +    },{
> +        .name = TYPE_MEGASAS_GEN2,
> +        .desc = "LSI MegaRAID SAS 2108",
> +        .product_name = "LSI MegaRAID SAS 9260-8i",
> +        .product_version = MEGASAS_VERSION_GEN2,
> +        .device_id = PCI_DEVICE_ID_LSI_SAS0079,
> +        .subsystem_id = 0x9261,
> +        .ioport_bar = 0,
> +        .mmio_bar = 1,
> +        .osts = MFI_GEN2_RM,
> +        .is_express = true,
> +        .vmsd = &vmstate_megasas_gen2,
> +        .props = megasas_properties_gen2,
> +    }
> +};
> +
>  static void megasas_class_init(ObjectClass *oc, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(oc);
>      PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
> +    MegasasBaseClass *e = MEGASAS_DEVICE_CLASS(oc);
> +    const MegasasInfo *info = data;
>  
>      pc->init = megasas_scsi_init;
>      pc->exit = megasas_scsi_uninit;
>      pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
> -    pc->device_id = PCI_DEVICE_ID_LSI_SAS1078;
> +    pc->device_id = info->device_id;
>      pc->subsystem_vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
> -    pc->subsystem_id = 0x1013;
> +    pc->subsystem_id = info->subsystem_id;
>      pc->class_id = PCI_CLASS_STORAGE_RAID;
> -    dc->props = megasas_properties;
> +    pc->is_express = info->is_express;
> +    e->mmio_bar = info->mmio_bar;
> +    e->ioport_bar = info->ioport_bar;
> +    e->osts = info->osts;
> +    e->product_name = info->product_name;
> +    e->product_version = info->product_version;
> +    dc->props = info->props;
>      dc->reset = megasas_scsi_reset;
> -    dc->vmsd = &vmstate_megasas;
> +    dc->vmsd = info->vmsd;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> -    dc->desc = "LSI MegaRAID SAS 1078";
> +    dc->desc = info->desc;
>      pc->config_write = megasas_write_config;
>  }
>  
>  static const TypeInfo megasas_info = {
> -    .name  = TYPE_MEGASAS,
> +    .name  = TYPE_MEGASAS_BASE,
>      .parent = TYPE_PCI_DEVICE,
>      .instance_size = sizeof(MegasasState),
> -    .class_init = megasas_class_init,
> +    .class_size = sizeof(MegasasBaseClass),
> +    .abstract = true,
>  };
>  
>  static void megasas_register_types(void)
>  {
> +    int i;
> +
>      type_register_static(&megasas_info);
> +    for (i = 0; i < ARRAY_SIZE(megasas_devices); i++) {
> +        const MegasasInfo *info = &megasas_devices[i];
> +        TypeInfo type_info = {};
> +
> +        type_info.name = info->name;
> +        type_info.parent = TYPE_MEGASAS_BASE;
> +        type_info.class_data = (void *)info;
> +        type_info.class_init = megasas_class_init;
> +
> +        type_register(&type_info);
> +    }
>  }
>  
>  type_init(megasas_register_types)
> diff --git a/hw/scsi/mfi.h b/hw/scsi/mfi.h
> index 455c96b..29d4177 100644
> --- a/hw/scsi/mfi.h
> +++ b/hw/scsi/mfi.h
> @@ -60,6 +60,7 @@
>  #define MFI_ODR0        0x9c            /* outbound doorbell register0 */
>  #define MFI_ODCR0       0xa0            /* outbound doorbell clear register0  */
>  #define MFI_OSP0        0xb0            /* outbound scratch pad0  */
> +#define MFI_OSP1        0xb4            /* outbound scratch pad1  */
>  #define MFI_IQPL        0xc0            /* Inbound queue port (low bytes)  */
>  #define MFI_IQPH        0xc4            /* Inbound queue port (high bytes)  */
>  #define MFI_DIAG        0xf8            /* Host diag */
> @@ -116,6 +117,12 @@
>  #define MFI_FWINIT_STOP_ADP     0x00000020 /* Move to operational, stop */
>  #define MFI_FWINIT_ADP_RESET    0x00000040 /* Reset ADP */
>  
> +/*
> + * Control bits for the DIAG register
> + */
> +#define MFI_DIAG_WRITE_ENABLE 0x00000080
> +#define MFI_DIAG_RESET_ADP    0x00000004
> +
>  /* MFI Commands */
>  typedef enum {
>      MFI_CMD_INIT = 0x00,
> diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
> index e597070..321d622 100644
> --- a/include/hw/pci/pci_ids.h
> +++ b/include/hw/pci/pci_ids.h
> @@ -56,6 +56,7 @@
>  #define PCI_DEVICE_ID_LSI_53C810         0x0001
>  #define PCI_DEVICE_ID_LSI_53C895A        0x0012
>  #define PCI_DEVICE_ID_LSI_SAS1078        0x0060
> +#define PCI_DEVICE_ID_LSI_SAS0079        0x0079
>  
>  #define PCI_VENDOR_ID_DEC                0x1011
>  #define PCI_DEVICE_ID_DEC_21154          0x0026
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH 05/13] megasas: add MegaRAID SAS 2108 emulation
  2014-10-31 17:08   ` Paolo Bonzini
@ 2014-10-31 17:30     ` Hannes Reinecke
  2014-10-31 17:31       ` Paolo Bonzini
  0 siblings, 1 reply; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-31 17:30 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: Andreas Faerber, Nic Bellinger, Alexander Graf

On 10/31/2014 06:08 PM, Paolo Bonzini wrote:
> 
> 
> On 29/10/2014 13:00, Hannes Reinecke wrote:
>> The 2108 chip supports MSI and MSI-X, so update the emulation
>> to support both chips.
> 
> Is it expected that it doesn't work with latest SeaBIOS?
> 
Not expected, but apparently this is the case.
I'll be updating SeaBIOS once the patches are in qemu.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		      zSeries & Storage
hare@suse.de			      +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH 05/13] megasas: add MegaRAID SAS 2108 emulation
  2014-10-31 17:30     ` Hannes Reinecke
@ 2014-10-31 17:31       ` Paolo Bonzini
  2014-10-31 17:32         ` Hannes Reinecke
  0 siblings, 1 reply; 21+ messages in thread
From: Paolo Bonzini @ 2014-10-31 17:31 UTC (permalink / raw)
  To: Hannes Reinecke, qemu-devel
  Cc: Andreas Faerber, Nic Bellinger, Alexander Graf

On 31/10/2014 18:30, Hannes Reinecke wrote:
>>> The 2108 chip supports MSI and MSI-X, so update the emulation
>>> to support both chips.
>> 
>> Is it expected that it doesn't work with latest SeaBIOS?
> 
> Not expected, but apparently this is the case.
> I'll be updating SeaBIOS once the patches are in qemu.

It works with RHEL6, so I went ahead and sent a pull request.

Paolo

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH 05/13] megasas: add MegaRAID SAS 2108 emulation
  2014-10-31 17:31       ` Paolo Bonzini
@ 2014-10-31 17:32         ` Hannes Reinecke
  0 siblings, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2014-10-31 17:32 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: Andreas Faerber, Nic Bellinger, Alexander Graf

On 10/31/2014 06:31 PM, Paolo Bonzini wrote:
> On 31/10/2014 18:30, Hannes Reinecke wrote:
>>>> The 2108 chip supports MSI and MSI-X, so update the emulation
>>>> to support both chips.
>>>
>>> Is it expected that it doesn't work with latest SeaBIOS?
>>
>> Not expected, but apparently this is the case.
>> I'll be updating SeaBIOS once the patches are in qemu.
> 
> It works with RHEL6, so I went ahead and sent a pull request.
> 
I've seen it. Thanks.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		      zSeries & Storage
hare@suse.de			      +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2014-10-31 17:32 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-29 12:00 [Qemu-devel] [PATCHv2 00/13] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 01/13] scsi: Rename scsi_cdb_length() to scsi_xfer_length() Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 02/13] megasas: fixup MFI_DCMD_LD_LIST_QUERY Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 03/13] megasas: simplify trace event messages Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 04/13] megasas: fixup device mapping Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 05/13] megasas: add MegaRAID SAS 2108 emulation Hannes Reinecke
2014-10-31 17:08   ` Paolo Bonzini
2014-10-31 17:30     ` Hannes Reinecke
2014-10-31 17:31       ` Paolo Bonzini
2014-10-31 17:32         ` Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 06/13] megasas: Fix typo in megasas_dcmd_ld_get_list() Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 07/13] megasas: Decode register names Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 08/13] megasas: Clear unit attention on initial reset Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 09/13] megasas: Ignore duplicate init_firmware commands Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 10/13] megasas: Implement DCMD_CLUSTER_RESET_LD Hannes Reinecke
2014-10-29 12:54   ` Paolo Bonzini
2014-10-29 13:23     ` Hannes Reinecke
2014-10-29 13:28       ` Paolo Bonzini
2014-10-29 12:00 ` [Qemu-devel] [PATCH 11/13] megasas: Update queue logging Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 12/13] megasas: Rework frame queueing algorithm Hannes Reinecke
2014-10-29 12:00 ` [Qemu-devel] [PATCH 13/13] megasas: Fixup MSI-X handling Hannes Reinecke

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).