diff mbox

[12/17] megasas: Clear unit attention on initial reset

Message ID 1414569232-21357-13-git-send-email-hare@suse.de
State New
Headers show

Commit Message

Hannes Reinecke Oct. 29, 2014, 7:53 a.m. UTC
The EFI firmware doesn't handle unit attentions properly,
so we need to clear the Power On/Reset unit attention upon
initial reset.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 hw/scsi/megasas.c | 20 +++++++++++++++++++-
 trace-events      |  2 +-
 2 files changed, 20 insertions(+), 2 deletions(-)

Comments

Paolo Bonzini Oct. 29, 2014, 9:14 a.m. UTC | #1
On 10/29/2014 08:53 AM, Hannes Reinecke wrote:
> +
> +        /*
> +         * The EFI firmware doesn't handle UA,
> +         * so we need to clear the Power On/Reset UA
> +         * after the initial reset.
> +         */
> +        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
> +            SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
> +            SCSISense *ua;
> +
> +            ua = &sdev->unit_attention;
> +            *ua = SENSE_CODE(NO_SENSE);

Just sdev->unit_attention = SENSE_CODE(NO_SENSE)?

> +            sdev->sense_is_ua = false;

Setting sense_is_ua is unnecessary, it refers to dev->sense rather than
dev->unit_attention.  Just assert(dev->sense_len == 0) if you care.

You need this too:

        scsi_device_unit_attention_reported(sdev);

Otherwise the state machine that reports CD-ROM media changes gets
messed up.

Paolo
Hannes Reinecke Oct. 29, 2014, 9:53 a.m. UTC | #2
On 10/29/2014 10:14 AM, Paolo Bonzini wrote:
>
>
> On 10/29/2014 08:53 AM, Hannes Reinecke wrote:
>> +
>> +        /*
>> +         * The EFI firmware doesn't handle UA,
>> +         * so we need to clear the Power On/Reset UA
>> +         * after the initial reset.
>> +         */
>> +        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
>> +            SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
>> +            SCSISense *ua;
>> +
>> +            ua = &sdev->unit_attention;
>> +            *ua = SENSE_CODE(NO_SENSE);
>
> Just sdev->unit_attention = SENSE_CODE(NO_SENSE)?
>
Ok.

>> +            sdev->sense_is_ua = false;
>
> Setting sense_is_ua is unnecessary, it refers to dev->sense rather than
> dev->unit_attention.  Just assert(dev->sense_len == 0) if you care.
>
> You need this too:
>
>          scsi_device_unit_attention_reported(sdev);
>
> Otherwise the state machine that reports CD-ROM media changes gets
> messed up.
>
yeah, this is all a bit ad-hoc. So I'll be fixing it up with the next
round.

Cheers,

Hannes
diff mbox

Patch

diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 56336b0..7a6c94f 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2203,11 +2203,28 @@  static void megasas_soft_reset(MegasasState *s)
     int i;
     MegasasCmd *cmd;
 
-    trace_megasas_reset();
+    trace_megasas_reset(s->fw_state);
     for (i = 0; i < s->fw_cmds; i++) {
         cmd = &s->frames[i];
         megasas_abort_command(cmd);
     }
+    if (s->fw_state == MFI_FWSTATE_READY) {
+        BusChild *kid;
+
+        /*
+         * The EFI firmware doesn't handle UA,
+         * so we need to clear the Power On/Reset UA
+         * after the initial reset.
+         */
+        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+            SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
+            SCSISense *ua;
+
+            ua = &sdev->unit_attention;
+            *ua = SENSE_CODE(NO_SENSE);
+            sdev->sense_is_ua = false;
+        }
+    }
     megasas_reset_frames(s);
     s->reply_queue_len = s->fw_cmds;
     s->reply_queue_pa = 0;
@@ -2335,6 +2352,7 @@  static int megasas_scsi_init(PCIDevice *dev)
         msix_vector_use(dev, 0);
     }
 
+    s->fw_state = MFI_FWSTATE_READY;
     if (!s->sas_addr) {
         s->sas_addr = ((NAA_LOCALLY_ASSIGNED_ID << 24) |
                        IEEE_COMPANY_LOCALLY_ASSIGNED) << 36;
diff --git a/trace-events b/trace-events
index 69b95f5..11cfc44 100644
--- a/trace-events
+++ b/trace-events
@@ -754,7 +754,7 @@  megasas_dcmd_unsupported(int cmd, unsigned long size) "scmd %d: set properties l
 megasas_abort_frame(int cmd, int abort_cmd) "scmd %d: frame %x"
 megasas_abort_no_cmd(int cmd, uint64_t context) "scmd %d: no active command for frame context %" PRIx64 ""
 megasas_abort_invalid_context(int cmd, uint64_t context, int abort_cmd) "scmd %d: invalid frame context %" PRIx64 " for abort frame %x"
-megasas_reset(void) "Reset"
+megasas_reset(int fw_state) "firmware state %x"
 megasas_init(int sges, int cmds, const char *mode) "Using %d sges, %d cmds, %s mode"
 megasas_msix_raise(int vector) "vector %d"
 megasas_msi_raise(int vector) "vector %d"