qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 3/3] megasas: LSI Megaraid SAS emulation


From: Hannes Reinecke
Subject: Re: [Qemu-devel] [PATCH 3/3] megasas: LSI Megaraid SAS emulation
Date: Mon, 04 Jul 2011 10:37:01 +0200
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.14) Gecko/20110221 SUSE/3.1.8 Thunderbird/3.1.8

On 07/02/2011 06:14 PM, Stefan Hajnoczi wrote:
On Fri, Jul 1, 2011 at 4:35 PM, Hannes Reinecke<address@hidden>  wrote:
+static void megasas_mmio_writel(void *opaque, target_phys_addr_t addr,
+                                uint32_t val)
+{
+    MPTState *s = opaque;
+    target_phys_addr_t frame_addr;
+    uint32_t frame_count;
+    int i;
+
+    DPRINTF_REG("writel mmio %lx: %x\n", (unsigned long)addr, val);
+
+    switch (addr) {
+    case MFI_IDB:
+        if (val&  MFI_FWINIT_ABORT) {
+            /* Abort all pending cmds */
+            for (i = 0; i<= s->fw_cmds; i++) {
+                megasas_abort_command(&s->frames[i]);
+            }
+        }
+        if (val&  MFI_FWINIT_READY) {
+            /* move to FW READY */
+            megasas_soft_reset(s);
+        }
+        if (val&  MFI_FWINIT_MFIMODE) {
+            /* discard MFIs */
+        }
+        break;
+    case MFI_OMSK:
+        s->intr_mask = val;
+        if (!MEGASAS_INTR_ENABLED(s)) {
+            qemu_irq_lower(s->dev.irq[0]);
+        }
+        break;
+    case MFI_ODCR0:
+        /* Update reply queue pointer */
+        DPRINTF_QUEUE("Update reply queue head %x busy %d\n",
+                      s->reply_queue_index, s->busy);
+        stl_phys(s->producer_pa, s->reply_queue_index);
+        s->doorbell = 0;
+        qemu_irq_lower(s->dev.irq[0]);
+        break;
+    case MFI_IQPH:
+        s->frame_hi = val;
+        break;
+    case MFI_IQPL:
+    case MFI_IQP:
+        /* Received MFI frame address */
+        frame_addr = (val&  ~0xFF);
+        /* Add possible 64 bit offset */
+        frame_addr |= (uint64_t)s->frame_hi;

Is this missing<<  32 before ORing the high bits?

Yes, true. Linux doesn't use the high part, so
I haven't seen it yet.
Might explain the strange Win7 failures I've had :-)
Fixed.

+static int megasas_scsi_uninit(PCIDevice *d)
+{
+    MPTState *s = DO_UPCAST(MPTState, dev, d);
+
+    cpu_unregister_io_memory(s->mmio_io_addr);

Need to unregister io_addr and queue_addr.

Yeah, the unregister function is a bit of a stub currently.
Fixed.

+
+    return 0;
+}
+
+static const struct SCSIBusOps megasas_scsi_ops = {
+    .transfer_data = megasas_xfer_complete,
+    .complete = megasas_command_complete,
+    .cancel = megasas_command_cancel,
+};
+
+static int megasas_scsi_init(PCIDevice *dev)
+{
+    MPTState *s = DO_UPCAST(MPTState, dev, dev);
+    uint8_t *pci_conf;
+    int i;
+
+    pci_conf = s->dev.config;
+
+    /* PCI Vendor ID (word) */
+    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_LSI_LOGIC);
+    /* PCI device ID (word) */
+    pci_config_set_device_id(pci_conf,  PCI_DEVICE_ID_LSI_SAS1078);
+    /* PCI subsystem ID */
+    pci_set_word(&pci_conf[PCI_SUBSYSTEM_VENDOR_ID], 0x1000);
+    pci_set_word(&pci_conf[PCI_SUBSYSTEM_ID], 0x1013);
+    /* PCI base class code */
+    pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_RAID);


PCIDeviceInfo now has vendor_id, device_id, and other fields.  These
values can be set in the megasas_info definition below.

Argl. Interface change again. Okay, will be doing so.

+
+    /* PCI latency timer = 0 */
+    pci_conf[0x0d] = 0;
+    /* Interrupt pin 1 */
+    pci_conf[0x3d] = 0x01;
+
+    s->mmio_io_addr = cpu_register_io_memory(megasas_mmio_readfn,
+                                             megasas_mmio_writefn, s,
+                                             DEVICE_NATIVE_ENDIAN);
+    s->io_addr = cpu_register_io_memory(megasas_io_readfn,
+                                        megasas_io_writefn, s,
+                                        DEVICE_NATIVE_ENDIAN);
+    s->queue_addr = cpu_register_io_memory(megasas_queue_readfn,
+                                           megasas_queue_writefn, s,
+                                           DEVICE_NATIVE_ENDIAN);

Should these be little-endian?

Presumably. Haven't tested on big-endian emulations as of now.

+    pci_register_bar((struct PCIDevice *)s, 0, 0x40000,
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, megasas_mmio_mapfunc);
+    pci_register_bar((struct PCIDevice *)s, 2, 256,
+                     PCI_BASE_ADDRESS_SPACE_IO, megasas_io_mapfunc);
+    pci_register_bar((struct PCIDevice *)s, 3, 0x40000,
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, megasas_queue_mapfunc);
+    if (s->fw_sge>= MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE) {
+        s->fw_sge = MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE;
+    } else if (s->fw_sge>= 128 - MFI_PASS_FRAME_SIZE) {
+        s->fw_sge = 128 - MFI_PASS_FRAME_SIZE;
+    } else {
+        s->fw_sge = 64 - MFI_PASS_FRAME_SIZE;
+    }
+    if (s->fw_cmds>  MEGASAS_MAX_FRAMES) {
+        s->fw_cmds = MEGASAS_MAX_FRAMES;
+    }
+    if (s->raid_mode_str) {
+        if (!strcmp(s->raid_mode_str, "jbod")) {
+            s->is_jbod = 1;
+        } else {
+            s->is_jbod = 0;
+        }
+    }
+    DPRINTF("Using %d sges, %d cmds, %s mode\n",
+            s->fw_sge, s->fw_cmds, s->is_jbod ? "jbod" : "raid");
+    s->fw_luns = (MFI_MAX_LD>  MAX_SCSI_DEVS) ?
+        MAX_SCSI_DEVS : MFI_MAX_LD;
+    s->producer_pa = 0;
+    s->consumer_pa = 0;
+    for (i = 0; i<  s->fw_cmds; i++) {
+        s->frames[i].index = i;
+        s->frames[i].context = -1;
+        s->frames[i].pa = 0;
+        s->frames[i].state = s;
+    }

It is not clear to me that all register state is initialized here.
megasas_soft_reset() seems to touch fw_state and intr_mask but will
not be called until mmio_writel(MFI_IDB, MFI_FWINIT_READY).  Are there
any missing fields that need to be initialized here?


I was under the impression that we'll be getting a reset after initialising the device, so this should've been taken care of.
And most of the mmio writes are safe against accidental misuse.
I'll be adding a check to MFI_ODCR0, as this indeed might cause
an error when used uninitialized.

Cheers,

Hannes
--
Dr. Hannes Reinecke                   zSeries & Storage
address@hidden                        +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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]