#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "trace.h"
-
+#include "qapi/error.h"
#include "mptsas.h"
#include "mpi.h"
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);
goto bad;
}
- req = g_new(MPTSASRequest, 1);
+ req = g_new0(MPTSASRequest, 1);
QTAILQ_INSERT_TAIL(&s->pending, req, next);
req->scsi_io = *scsi_io;
req->dev = s;
/* Read the message header from the guest first. */
addr = s->host_mfa_high_addr | MPTSAS_FIFO_GET(s, request_post);
- pci_dma_read(pci, addr, req, sizeof(hdr));
+ pci_dma_read(pci, addr, req, sizeof(*hdr));
if (hdr->Function < ARRAY_SIZE(mpi_request_sizes) &&
mpi_request_sizes[hdr->Function]) {
*/
size = mpi_request_sizes[hdr->Function];
assert(size <= MPTSAS_MAX_REQUEST_SIZE);
- pci_dma_read(pci, addr + sizeof(hdr), &req[sizeof(hdr)],
- size - sizeof(hdr));
+ pci_dma_read(pci, addr + sizeof(*hdr), &req[sizeof(*hdr)],
+ size - sizeof(*hdr));
}
if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
.load_request = mptsas_load_request,
};
-static void mptsas_scsi_init(PCIDevice *dev, Error **errp)
+static void mptsas_scsi_realize(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);
+
+ /* Only used for migration. */
+ s->msi_in_use = (ret == 0);
+ }
+
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,
memory_region_init_io(&s->diag_io, OBJECT(s), &mptsas_diag_ops, s,
"mptsas-diag", 0x10000);
- if (s->msi != ON_OFF_AUTO_OFF &&
- msi_init(dev, 0, 1, true, false) >= 0) {
- /* TODO check for errors */
- 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);
QTAILQ_INIT(&s->pending);
scsi_bus_new(&s->bus, sizeof(s->bus), &dev->qdev, &mptsas_scsi_info, NULL);
- if (!d->hotplugged) {
- scsi_bus_legacy_handle_cmdline(&s->bus, errp);
- }
}
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)
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(dev, MPTSASState),
VMSTATE_BOOL(msi_in_use, MPTSASState),
-
VMSTATE_UINT32(state, MPTSASState),
VMSTATE_UINT8(who_init, MPTSASState),
VMSTATE_UINT8(doorbell_state, MPTSASState),
DeviceClass *dc = DEVICE_CLASS(oc);
PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
- pc->realize = mptsas_scsi_init;
+ pc->realize = mptsas_scsi_realize;
pc->exit = mptsas_scsi_uninit;
pc->romfile = 0;
pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;