All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hannes Reinecke <hare@suse.de>
To: qemu-devel@nongnu.org
Cc: Hannes Reinecke <hare@suse.de>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Nic Bellinger <nab@datera.com>,
	Andreas Faerber <afaerber@suse.de>,
	Alexander Graf <agraf@suse.de>
Subject: [Qemu-devel] [PATCH 16/17] megasas: Rework frame queueing algorithm
Date: Wed, 29 Oct 2014 08:53:51 +0100	[thread overview]
Message-ID: <1414569232-21357-17-git-send-email-hare@suse.de> (raw)
In-Reply-To: <1414569232-21357-1-git-send-email-hare@suse.de>

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 e775e1f..8c60562 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)
@@ -1895,6 +1887,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);
 }
 
@@ -1998,6 +1991,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

  parent reply	other threads:[~2014-10-29  7:54 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-29  7:53 [Qemu-devel] [PATCH 00/17] megasas: gen2 emulation and MSI-X fixes Hannes Reinecke
2014-10-29  7:53 ` [Qemu-devel] [PATCH 01/17] ahci: Fix CD-ROM signature Hannes Reinecke
2014-10-29  8:07   ` Markus Armbruster
2014-10-29  8:11     ` Hannes Reinecke
2014-10-29 15:47       ` John Snow
2014-10-29 14:30   ` Stefan Hajnoczi
2014-10-29  7:53 ` [Qemu-devel] [PATCH 02/17] atapi: clear sense code Hannes Reinecke
2014-10-29 14:50   ` Stefan Hajnoczi
2014-10-29  7:53 ` [Qemu-devel] [PATCH 03/17] scsi: Rename scsi_cdb_length() to scsi_xfer_length() Hannes Reinecke
2014-10-30 10:38   ` Paolo Bonzini
2014-10-30 11:26     ` Hannes Reinecke
2014-10-30 12:00       ` Paolo Bonzini
2014-10-29  7:53 ` [Qemu-devel] [PATCH 04/17] scsi: fixup lba calculation for 6 byte CDBs Hannes Reinecke
2014-10-29  9:16   ` Paolo Bonzini
2014-10-29  9:52     ` Hannes Reinecke
2014-10-29 10:10       ` Paolo Bonzini
2014-10-29  7:53 ` [Qemu-devel] [PATCH 05/17] scsi: Remove 'lun' argument Hannes Reinecke
2014-10-29  9:05   ` Paolo Bonzini
2014-10-29  9:07   ` Paolo Bonzini
2014-10-29 11:13     ` Hannes Reinecke
2014-10-29 11:35       ` Paolo Bonzini
2014-10-29  7:53 ` [Qemu-devel] [PATCH 06/17] megasas: fixup MFI_DCMD_LD_LIST_QUERY Hannes Reinecke
2014-10-29  7:53 ` [Qemu-devel] [PATCH 07/17] megasas: simplify trace event messages Hannes Reinecke
2014-10-29  7:53 ` [Qemu-devel] [PATCH 08/17] megasas: fixup device mapping Hannes Reinecke
2014-10-29  7:53 ` [Qemu-devel] [PATCH 09/17] megasas: add MegaRAID SAS 2108 emulation Hannes Reinecke
2014-10-29 12:01   ` Andreas Färber
2014-10-29  7:53 ` [Qemu-devel] [PATCH 10/17] megasas: Fix typo in megasas_dcmd_ld_get_list() Hannes Reinecke
2014-10-29  7:53 ` [Qemu-devel] [PATCH 11/17] megasas: Decode register names Hannes Reinecke
2014-10-29  7:53 ` [Qemu-devel] [PATCH 12/17] megasas: Clear unit attention on initial reset Hannes Reinecke
2014-10-29  9:14   ` Paolo Bonzini
2014-10-29  9:53     ` Hannes Reinecke
2014-10-29  7:53 ` [Qemu-devel] [PATCH 13/17] megasas: Ignore duplicate init_firmware commands Hannes Reinecke
2014-10-29  7:53 ` [Qemu-devel] [PATCH 14/17] megasas: Implement DCMD_CLUSTER_RESET_LD Hannes Reinecke
2014-10-29  7:53 ` [Qemu-devel] [PATCH 15/17] megasas: Update queue logging Hannes Reinecke
2014-10-29  7:53 ` Hannes Reinecke [this message]
2014-10-29  7:53 ` [Qemu-devel] [PATCH 17/17] megasas: Fixup MSI-X handling Hannes Reinecke
2014-10-29  9:18 ` [Qemu-devel] [PATCH 00/17] megasas: gen2 emulation and MSI-X fixes Paolo Bonzini
2014-10-29 11:10   ` Hannes Reinecke

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1414569232-21357-17-git-send-email-hare@suse.de \
    --to=hare@suse.de \
    --cc=afaerber@suse.de \
    --cc=agraf@suse.de \
    --cc=nab@datera.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.