diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-05-19 12:30:06 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-05-19 12:30:06 +0100 |
commit | 6a23082b4eca28df6a26efae8016d2f2f0921da5 (patch) | |
tree | e0726fa2f954e829a12fe5412861d38296d07d92 /hw/scsi | |
parent | 1a381811b495651ddfc2b50d7c8cfaaf375816b0 (diff) | |
parent | 6a86dec61921163b6ab582df988416a6f0ca0ed5 (diff) |
Merge remote-tracking branch 'remotes/bonzini/scsi-next' into staging
* remotes/bonzini/scsi-next:
[PATCH] block/iscsi: bump year in copyright notice
block/iscsi: allow cluster_size of 4K and greater
block/iscsi: clarify the meaning of ISCSI_CHECKALLOC_THRES
block/iscsi: speed up read for unallocated sectors
block/iscsi: allow fall back to WRITE SAME without UNMAP
MAINTAINERS: mark megasas as maintained
megasas: Add MSI support
megasas: Enable MSI-X support
megasas: Implement LD_LIST_QUERY
scsi: Improve error messages more
scsi-disk: Improve error messager if can't get version number
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/scsi')
-rw-r--r-- | hw/scsi/megasas.c | 81 | ||||
-rw-r--r-- | hw/scsi/mfi.h | 9 | ||||
-rw-r--r-- | hw/scsi/scsi-disk.c | 16 | ||||
-rw-r--r-- | hw/scsi/scsi-generic.c | 8 |
4 files changed, 90 insertions, 24 deletions
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index e6e1ffd1bb..baee46f981 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -21,6 +21,7 @@ #include "hw/hw.h" #include "hw/pci/pci.h" #include "sysemu/dma.h" +#include "hw/pci/msi.h" #include "hw/pci/msix.h" #include "qemu/iov.h" #include "hw/scsi/scsi.h" @@ -43,9 +44,11 @@ #define MEGASAS_FLAG_USE_JBOD 0 #define MEGASAS_MASK_USE_JBOD (1 << MEGASAS_FLAG_USE_JBOD) -#define MEGASAS_FLAG_USE_MSIX 1 +#define MEGASAS_FLAG_USE_MSI 1 +#define MEGASAS_MASK_USE_MSI (1 << MEGASAS_FLAG_USE_MSI) +#define MEGASAS_FLAG_USE_MSIX 2 #define MEGASAS_MASK_USE_MSIX (1 << MEGASAS_FLAG_USE_MSIX) -#define MEGASAS_FLAG_USE_QUEUE64 2 +#define MEGASAS_FLAG_USE_QUEUE64 3 #define MEGASAS_MASK_USE_QUEUE64 (1 << MEGASAS_FLAG_USE_QUEUE64) static const char *mfi_frame_desc[] = { @@ -132,6 +135,11 @@ static bool megasas_use_queue64(MegasasState *s) return s->flags & MEGASAS_MASK_USE_QUEUE64; } +static bool megasas_use_msi(MegasasState *s) +{ + return s->flags & MEGASAS_MASK_USE_MSI; +} + static bool megasas_use_msix(MegasasState *s) { return s->flags & MEGASAS_MASK_USE_MSIX; @@ -538,6 +546,9 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context) 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 { trace_megasas_irq_raise(); pci_irq_assert(pci_dev); @@ -1106,6 +1117,21 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) return MFI_STAT_OK; } +static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) +{ + uint16_t flags; + + /* 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); + } + + return MFI_STAT_OK; +} + static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, MegasasCmd *cmd) { @@ -1409,6 +1435,8 @@ static const struct dcmd_cmd_tbl_t { megasas_dcmd_dummy }, { MFI_DCMD_LD_GET_LIST, "LD_GET_LIST", megasas_dcmd_ld_get_list}, + { MFI_DCMD_LD_LIST_QUERY, "LD_LIST_QUERY", + megasas_dcmd_ld_list_query }, { MFI_DCMD_LD_GET_INFO, "LD_GET_INFO", megasas_dcmd_ld_get_info }, { MFI_DCMD_LD_GET_PROP, "LD_GET_PROP", @@ -1939,12 +1967,20 @@ static void megasas_mmio_write(void *opaque, hwaddr addr, break; case MFI_OMSK: s->intr_mask = val; - if (!megasas_intr_enabled(s) && !msix_enabled(pci_dev)) { + if (!megasas_intr_enabled(s) && + !msi_enabled(pci_dev) && + !msix_enabled(pci_dev)) { trace_megasas_irq_lower(); pci_irq_deassert(pci_dev); } if (megasas_intr_enabled(s)) { - trace_megasas_intr_enabled(); + if (msix_enabled(pci_dev)) { + trace_megasas_msix_enabled(0); + } else if (msi_enabled(pci_dev)) { + trace_megasas_msi_enabled(0); + } else { + trace_megasas_intr_enabled(); + } } else { trace_megasas_intr_disabled(); } @@ -2068,6 +2104,7 @@ static const VMStateDescription vmstate_megasas = { .minimum_version_id_old = 0, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(parent_obj, MegasasState), + VMSTATE_MSIX(parent_obj, MegasasState), VMSTATE_INT32(fw_state, MegasasState), VMSTATE_INT32(intr_mask, MegasasState), @@ -2083,9 +2120,12 @@ static void megasas_scsi_uninit(PCIDevice *d) { MegasasState *s = MEGASAS(d); -#ifdef USE_MSIX - msix_uninit(d, &s->mmio_io); -#endif + if (megasas_use_msix(s)) { + msix_uninit(d, &s->mmio_io, &s->mmio_io); + } + if (megasas_use_msi(s)) { + msi_uninit(d); + } memory_region_destroy(&s->mmio_io); memory_region_destroy(&s->port_io); memory_region_destroy(&s->queue_io); @@ -2124,15 +2164,15 @@ static int megasas_scsi_init(PCIDevice *dev) memory_region_init_io(&s->queue_io, OBJECT(s), &megasas_queue_ops, s, "megasas-queue", 0x40000); -#ifdef USE_MSIX - /* MSI-X support is currently broken */ + if (megasas_use_msi(s) && + msi_init(dev, 0x50, 1, true, false)) { + s->flags &= ~MEGASAS_MASK_USE_MSI; + } if (megasas_use_msix(s) && - msix_init(dev, 15, &s->mmio_io, 0, 0x2000)) { + msix_init(dev, 15, &s->mmio_io, 0, 0x2000, + &s->mmio_io, 0, 0x3800, 0x68)) { s->flags &= ~MEGASAS_MASK_USE_MSIX; } -#else - s->flags &= ~MEGASAS_MASK_USE_MSIX; -#endif bar_type = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64; pci_register_bar(dev, 0, bar_type, &s->mmio_io); @@ -2151,7 +2191,7 @@ static int megasas_scsi_init(PCIDevice *dev) s->sas_addr |= PCI_FUNC(dev->devfn); } if (!s->hba_serial) { - s->hba_serial = g_strdup(MEGASAS_HBA_SERIAL); + s->hba_serial = g_strdup(MEGASAS_HBA_SERIAL); } if (s->fw_sge >= MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE) { s->fw_sge = MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE; @@ -2164,7 +2204,6 @@ static int megasas_scsi_init(PCIDevice *dev) s->fw_cmds = MEGASAS_MAX_FRAMES; } trace_megasas_init(s->fw_sge, s->fw_cmds, - megasas_use_msix(s) ? "MSI-X" : "INTx", megasas_is_jbod(s) ? "jbod" : "raid"); s->fw_luns = (MFI_MAX_LD > MAX_SCSI_DEVS) ? MAX_SCSI_DEVS : MFI_MAX_LD; @@ -2189,6 +2228,13 @@ static int megasas_scsi_init(PCIDevice *dev) return 0; } +static void +megasas_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len) +{ + pci_default_write_config(pci, addr, val, len); + msi_write_config(pci, addr, val, len); +} + static Property megasas_properties[] = { DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge, MEGASAS_DEFAULT_SGE), @@ -2196,10 +2242,10 @@ static Property megasas_properties[] = { MEGASAS_DEFAULT_FRAMES), DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial), DEFINE_PROP_UINT64("sas_address", MegasasState, sas_addr, 0), -#ifdef USE_MSIX + DEFINE_PROP_BIT("use_msi", MegasasState, flags, + MEGASAS_FLAG_USE_MSI, false), DEFINE_PROP_BIT("use_msix", MegasasState, flags, MEGASAS_FLAG_USE_MSIX, false), -#endif DEFINE_PROP_BIT("use_jbod", MegasasState, flags, MEGASAS_FLAG_USE_JBOD, false), DEFINE_PROP_END_OF_LIST(), @@ -2222,6 +2268,7 @@ static void megasas_class_init(ObjectClass *oc, void *data) dc->vmsd = &vmstate_megasas; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); dc->desc = "LSI MegaRAID SAS 1078"; + pc->config_write = megasas_write_config; } static const TypeInfo megasas_info = { diff --git a/hw/scsi/mfi.h b/hw/scsi/mfi.h index cd8355badf..a3034f6239 100644 --- a/hw/scsi/mfi.h +++ b/hw/scsi/mfi.h @@ -164,6 +164,7 @@ typedef enum { MFI_DCMD_PD_BLINK = 0x02070100, MFI_DCMD_PD_UNBLINK = 0x02070200, MFI_DCMD_LD_GET_LIST = 0x03010000, + MFI_DCMD_LD_LIST_QUERY = 0x03010100, MFI_DCMD_LD_GET_INFO = 0x03020000, MFI_DCMD_LD_GET_PROP = 0x03030000, MFI_DCMD_LD_SET_PROP = 0x03040000, @@ -411,6 +412,14 @@ typedef enum { MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5, /*query for system drives */ } mfi_pd_query_type; +typedef enum { + MR_LD_QUERY_TYPE_ALL = 0, + MR_LD_QUERY_TYPE_EXPOSED_TO_HOST = 1, + MR_LD_QUERY_TYPE_USED_TGT_IDS = 2, + MR_LD_QUERY_TYPE_CLUSTER_ACCESS = 3, + MR_LD_QUERY_TYPE_CLUSTER_LOCALE = 4, +} mfi_ld_query_type; + /* * Other propertities and definitions */ diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 48a28ae199..4bcef551a6 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2458,21 +2458,27 @@ static int scsi_block_initfn(SCSIDevice *dev) int rc; if (!s->qdev.conf.bs) { - error_report("scsi-block: drive property not set"); + error_report("drive property not set"); return -1; } /* check we are using a driver managing SG_IO (version 3 and after) */ - if (bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 || - sg_version < 30000) { - error_report("scsi-block: scsi generic interface too old"); + rc = bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version); + if (rc < 0) { + error_report("cannot get SG_IO version number: %s. " + "Is this a SCSI device?", + strerror(-rc)); + return -1; + } + if (sg_version < 30000) { + error_report("scsi generic interface too old"); return -1; } /* get device type from INQUIRY data */ rc = get_device_type(s); if (rc < 0) { - error_report("scsi-block: INQUIRY failed"); + error_report("INQUIRY failed"); return -1; } diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 8d92e0da15..3733d2c36c 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -394,6 +394,7 @@ static void scsi_destroy(SCSIDevice *s) static int scsi_generic_initfn(SCSIDevice *s) { + int rc; int sg_version; struct sg_scsi_id scsiid; @@ -412,8 +413,11 @@ static int scsi_generic_initfn(SCSIDevice *s) } /* check we are using a driver managing SG_IO (version 3 and after */ - if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0) { - error_report("scsi generic interface not supported"); + rc = bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version); + if (rc < 0) { + error_report("cannot get SG_IO version number: %s. " + "Is this a SCSI device?", + strerror(-rc)); return -1; } if (sg_version < 30000) { |