aboutsummaryrefslogtreecommitdiff
path: root/hw/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'hw/scsi')
-rw-r--r--hw/scsi/megasas.c59
-rw-r--r--hw/scsi/mptsas.c36
-rw-r--r--hw/scsi/mptsas.h5
-rw-r--r--hw/scsi/vmw_pvscsi.c15
4 files changed, 62 insertions, 53 deletions
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index d1772183cf..52a41239cf 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -29,7 +29,7 @@
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "trace.h"
-
+#include "qapi/error.h"
#include "mfi.h"
#define MEGASAS_VERSION_GEN1 "1.70"
@@ -48,11 +48,7 @@
#define MEGASAS_FLAG_USE_JBOD 0
#define MEGASAS_MASK_USE_JBOD (1 << MEGASAS_FLAG_USE_JBOD)
-#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 3
+#define MEGASAS_FLAG_USE_QUEUE64 1
#define MEGASAS_MASK_USE_QUEUE64 (1 << MEGASAS_FLAG_USE_QUEUE64)
static const char *mfi_frame_desc[] = {
@@ -96,6 +92,8 @@ typedef struct MegasasState {
int busy;
int diag;
int adp_reset;
+ OnOffAuto msi;
+ OnOffAuto msix;
MegasasCmd *event_cmd;
int event_locale;
@@ -157,14 +155,9 @@ 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;
+ return s->msix != ON_OFF_AUTO_OFF;
}
static bool megasas_is_jbod(MegasasState *s)
@@ -2309,9 +2302,7 @@ static void megasas_scsi_uninit(PCIDevice *d)
if (megasas_use_msix(s)) {
msix_uninit(d, &s->mmio_io, &s->mmio_io);
}
- if (megasas_use_msi(s)) {
- msi_uninit(d);
- }
+ msi_uninit(d);
}
static const struct SCSIBusInfo megasas_scsi_info = {
@@ -2332,6 +2323,8 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
MegasasBaseClass *b = MEGASAS_DEVICE_GET_CLASS(s);
uint8_t *pci_conf;
int i, bar_type;
+ Error *err = NULL;
+ int ret;
pci_conf = dev->config;
@@ -2340,6 +2333,24 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
/* Interrupt pin 1 */
pci_conf[PCI_INTERRUPT_PIN] = 0x01;
+ if (s->msi != ON_OFF_AUTO_OFF) {
+ ret = msi_init(dev, 0x50, 1, true, false, &err);
+ /* Any error other than -ENOTSUP(board's MSI support is broken)
+ * is a programming error */
+ assert(!ret || ret == -ENOTSUP);
+ if (ret && s->msi == ON_OFF_AUTO_ON) {
+ /* Can't satisfy user's explicit msi=on request, fail */
+ error_append_hint(&err, "You have to use msi=auto (default) or "
+ "msi=off with this machine type.\n");
+ error_propagate(errp, err);
+ return;
+ } else if (ret) {
+ /* With msi=auto, we fall back to MSI off silently */
+ s->msi = ON_OFF_AUTO_OFF;
+ error_free(err);
+ }
+ }
+
memory_region_init_io(&s->mmio_io, OBJECT(s), &megasas_mmio_ops, s,
"megasas-mmio", 0x4000);
memory_region_init_io(&s->port_io, OBJECT(s), &megasas_port_ops, s,
@@ -2347,14 +2358,10 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
memory_region_init_io(&s->queue_io, OBJECT(s), &megasas_queue_ops, s,
"megasas-queue", 0x40000);
- 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, b->mmio_bar, 0x2000,
&s->mmio_io, b->mmio_bar, 0x3800, 0x68)) {
- s->flags &= ~MEGASAS_MASK_USE_MSIX;
+ s->msix = ON_OFF_AUTO_OFF;
}
if (pci_is_express(dev)) {
pcie_endpoint_cap_init(dev, 0xa0);
@@ -2422,10 +2429,8 @@ static Property megasas_properties_gen1[] = {
MEGASAS_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, false),
- DEFINE_PROP_BIT("use_msix", MegasasState, flags,
- MEGASAS_FLAG_USE_MSIX, false),
+ DEFINE_PROP_ON_OFF_AUTO("msi", MegasasState, msi, ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_ON_OFF_AUTO("msix", MegasasState, msix, ON_OFF_AUTO_AUTO),
DEFINE_PROP_BIT("use_jbod", MegasasState, flags,
MEGASAS_FLAG_USE_JBOD, false),
DEFINE_PROP_END_OF_LIST(),
@@ -2438,10 +2443,8 @@ static Property megasas_properties_gen2[] = {
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_ON_OFF_AUTO("msi", MegasasState, msi, ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_ON_OFF_AUTO("msix", MegasasState, msix, ON_OFF_AUTO_AUTO),
DEFINE_PROP_BIT("use_jbod", MegasasState, flags,
MEGASAS_FLAG_USE_JBOD, false),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
index be88e161a9..1ae32fb7d3 100644
--- a/hw/scsi/mptsas.c
+++ b/hw/scsi/mptsas.c
@@ -32,7 +32,7 @@
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "trace.h"
-
+#include "qapi/error.h"
#include "mptsas.h"
#include "mpi.h"
@@ -63,7 +63,7 @@ static void mptsas_update_interrupt(MPTSASState *s)
PCIDevice *pci = (PCIDevice *) s;
uint32_t state = s->intr_status & ~(s->intr_mask | MPI_HIS_IOP_DOORBELL_STATUS);
- if (s->msi_in_use && msi_enabled(pci)) {
+ if (msi_enabled(pci)) {
if (state) {
trace_mptsas_irq_msi(s);
msi_notify(pci, 0);
@@ -1273,10 +1273,30 @@ static void mptsas_scsi_init(PCIDevice *dev, Error **errp)
{
DeviceState *d = DEVICE(dev);
MPTSASState *s = MPT_SAS(dev);
+ Error *err = NULL;
+ int ret;
dev->config[PCI_LATENCY_TIMER] = 0;
dev->config[PCI_INTERRUPT_PIN] = 0x01;
+ if (s->msi != ON_OFF_AUTO_OFF) {
+ ret = msi_init(dev, 0, 1, true, false, &err);
+ /* Any error other than -ENOTSUP(board's MSI support is broken)
+ * is a programming error */
+ assert(!ret || ret == -ENOTSUP);
+ if (ret && s->msi == ON_OFF_AUTO_ON) {
+ /* Can't satisfy user's explicit msi=on request, fail */
+ error_append_hint(&err, "You have to use msi=auto (default) or "
+ "msi=off with this machine type.\n");
+ error_propagate(errp, err);
+ return;
+ }
+ assert(!err || s->msi == ON_OFF_AUTO_AUTO);
+ /* With msi=auto, we fall back to MSI off silently */
+ error_free(err);
+
+ }
+
memory_region_init_io(&s->mmio_io, OBJECT(s), &mptsas_mmio_ops, s,
"mptsas-mmio", 0x4000);
memory_region_init_io(&s->port_io, OBJECT(s), &mptsas_port_ops, s,
@@ -1284,11 +1304,6 @@ static void mptsas_scsi_init(PCIDevice *dev, Error **errp)
memory_region_init_io(&s->diag_io, OBJECT(s), &mptsas_diag_ops, s,
"mptsas-diag", 0x10000);
- if (s->msi_available &&
- msi_init(dev, 0, 1, true, false) >= 0) {
- s->msi_in_use = true;
- }
-
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io);
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_TYPE_32, &s->mmio_io);
@@ -1319,9 +1334,7 @@ static void mptsas_scsi_uninit(PCIDevice *dev)
MPTSASState *s = MPT_SAS(dev);
qemu_bh_delete(s->request_bh);
- if (s->msi_in_use) {
- msi_uninit(dev);
- }
+ msi_uninit(dev);
}
static void mptsas_reset(DeviceState *dev)
@@ -1357,7 +1370,6 @@ static const VMStateDescription vmstate_mptsas = {
.post_load = mptsas_post_load,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(dev, MPTSASState),
- VMSTATE_BOOL(msi_in_use, MPTSASState),
VMSTATE_UINT32(state, MPTSASState),
VMSTATE_UINT8(who_init, MPTSASState),
@@ -1403,7 +1415,7 @@ static const VMStateDescription vmstate_mptsas = {
static Property mptsas_properties[] = {
DEFINE_PROP_UINT64("sas_address", MPTSASState, sas_addr, 0),
/* TODO: test MSI support under Windows */
- DEFINE_PROP_BIT("msi", MPTSASState, msi_available, 0, true),
+ DEFINE_PROP_ON_OFF_AUTO("msi", MPTSASState, msi, ON_OFF_AUTO_AUTO),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/scsi/mptsas.h b/hw/scsi/mptsas.h
index 595f81fb5b..da014a397e 100644
--- a/hw/scsi/mptsas.h
+++ b/hw/scsi/mptsas.h
@@ -27,11 +27,10 @@ struct MPTSASState {
MemoryRegion diag_io;
QEMUBH *request_bh;
- uint32_t msi_available;
+ /* properties */
+ OnOffAuto msi;
uint64_t sas_addr;
- bool msi_in_use;
-
/* Doorbell register */
uint32_t state;
uint8_t who_init;
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 2d7528d1dd..da71c8c8a5 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -121,8 +121,7 @@ typedef struct {
uint8_t msg_ring_info_valid; /* Whether message ring initialized */
uint8_t use_msg; /* Whether to use message ring */
- uint8_t msi_used; /* Whether MSI support was installed successfully */
-
+ uint8_t msi_used; /* For migration compatibility */
PVSCSIRingInfo rings; /* Data transfer rings manager */
uint32_t resetting; /* Reset in progress */
@@ -362,7 +361,7 @@ pvscsi_update_irq_status(PVSCSIState *s)
trace_pvscsi_update_irq_level(should_raise, s->reg_interrupt_enabled,
s->reg_interrupt_status);
- if (s->msi_used && msi_enabled(d)) {
+ if (msi_enabled(d)) {
if (should_raise) {
trace_pvscsi_update_irq_msi();
msi_notify(d, PVSCSI_VECTOR_COMPLETION);
@@ -1056,22 +1055,20 @@ pvscsi_io_read(void *opaque, hwaddr addr, unsigned size)
}
-static bool
+static void
pvscsi_init_msi(PVSCSIState *s)
{
int res;
PCIDevice *d = PCI_DEVICE(s);
res = msi_init(d, PVSCSI_MSI_OFFSET(s), PVSCSI_MSIX_NUM_VECTORS,
- PVSCSI_USE_64BIT, PVSCSI_PER_VECTOR_MASK);
+ PVSCSI_USE_64BIT, PVSCSI_PER_VECTOR_MASK, NULL);
if (res < 0) {
trace_pvscsi_init_msi_fail(res);
s->msi_used = false;
} else {
s->msi_used = true;
}
-
- return s->msi_used;
}
static void
@@ -1079,9 +1076,7 @@ pvscsi_cleanup_msi(PVSCSIState *s)
{
PCIDevice *d = PCI_DEVICE(s);
- if (s->msi_used) {
- msi_uninit(d);
- }
+ msi_uninit(d);
}
static const MemoryRegionOps pvscsi_ops = {