qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 14/16] scsi: add support for unit attention conditions
Date: Wed,  3 Aug 2011 10:49:17 +0200	[thread overview]
Message-ID: <1312361359-15445-15-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1312361359-15445-1-git-send-email-pbonzini@redhat.com>

Unit attention conditions override any sense data the device already
has.  Their signaling and clearing is handled entirely by the SCSIBus
code, and they are completely transparent to the SCSIDevices.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c  |   93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 hw/scsi-defs.h |    1 +
 hw/scsi.h      |    2 +
 3 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 0e2e4cd..a5bb517 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -149,6 +149,24 @@ struct SCSIReqOps reqops_invalid_opcode = {
     .send_command = scsi_invalid_command
 };
 
+/* SCSIReqOps implementation for unit attention conditions.  */
+
+static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf)
+{
+    if (req->dev && req->dev->unit_attention.key == UNIT_ATTENTION) {
+        scsi_req_build_sense(req, req->dev->unit_attention);
+    } else if (req->bus->unit_attention.key == UNIT_ATTENTION) {
+        scsi_req_build_sense(req, req->bus->unit_attention);
+    }
+    scsi_req_complete(req, CHECK_CONDITION);
+    return 0;
+}
+
+struct SCSIReqOps reqops_unit_attention = {
+    .size         = sizeof(SCSIRequest),
+    .send_command = scsi_unit_attention
+};
+
 /* SCSIReqOps implementation for REPORT LUNS and for commands sent to
    an invalid LUN.  */
 
@@ -344,6 +362,7 @@ SCSIRequest *scsi_req_alloc(SCSIReqOps *reqops, SCSIDevice *d, uint32_t tag,
 SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
                           uint8_t *buf, void *hba_private)
 {
+    SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
     SCSIRequest *req;
     SCSICommand cmd;
 
@@ -358,7 +377,15 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
                                       cmd.lba);
         }
 
-        if (lun != d->lun ||
+        if ((d->unit_attention.key == UNIT_ATTENTION ||
+             bus->unit_attention.key == UNIT_ATTENTION) &&
+            (buf[0] != INQUIRY &&
+             buf[0] != REPORT_LUNS &&
+             buf[0] != GET_CONFIGURATION &&
+             buf[0] != GET_EVENT_STATUS_NOTIFICATION)) {
+            req = scsi_req_alloc(&reqops_unit_attention, d, tag, lun,
+                                 hba_private);
+        } else if (lun != d->lun ||
             buf[0] == REPORT_LUNS ||
             buf[0] == REQUEST_SENSE) {
             req = scsi_req_alloc(&reqops_target_command, d, tag, lun,
@@ -377,13 +404,68 @@ uint8_t *scsi_req_get_buf(SCSIRequest *req)
     return req->ops->get_buf(req);
 }
 
+static void scsi_clear_unit_attention(SCSIRequest *req)
+{
+    SCSISense *ua;
+    if (req->dev->unit_attention.key != UNIT_ATTENTION &&
+        req->bus->unit_attention.key != UNIT_ATTENTION) {
+        return;
+    }
+
+    /*
+     * If an INQUIRY command enters the enabled command state,
+     * the device server shall [not] clear any unit attention condition;
+     * See also MMC-6, paragraphs 6.5 and 6.6.2.
+     */
+    if (req->cmd.buf[0] == INQUIRY ||
+        req->cmd.buf[0] == GET_CONFIGURATION ||
+        req->cmd.buf[0] == GET_EVENT_STATUS_NOTIFICATION) {
+        return;
+    }
+
+    if (req->dev->unit_attention.key == UNIT_ATTENTION) {
+        ua = &req->dev->unit_attention;
+    } else {
+        ua = &req->bus->unit_attention;
+    }
+
+    /*
+     * If a REPORT LUNS command enters the enabled command state, [...]
+     * the device server shall clear any pending unit attention condition
+     * with an additional sense code of REPORTED LUNS DATA HAS CHANGED.
+     */
+    if (req->cmd.buf[0] == REPORT_LUNS &&
+        !(ua->asc == SENSE_CODE(REPORTED_LUNS_CHANGED).asc &&
+          ua->ascq == SENSE_CODE(REPORTED_LUNS_CHANGED).ascq)) {
+        return;
+    }
+
+    *ua = SENSE_CODE(NO_SENSE);
+}
+
 int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len)
 {
+    int ret;
+
     assert(len >= 14);
     if (!req->sense_len) {
         return 0;
     }
-    return scsi_build_sense(req->sense, req->sense_len, buf, len, true);
+
+    ret = scsi_build_sense(req->sense, req->sense_len, buf, len, true);
+
+    /*
+     * FIXME: clearing unit attention conditions upon autosense should be done
+     * only if the UA_INTLCK_CTRL field in the Control mode page is set to 00b
+     * (SAM-5, 5.14).
+     *
+     * We assume UA_INTLCK_CTRL to be 00b for HBAs that support autosense, and
+     * 10b for HBAs that do not support it (do not call scsi_req_get_sense).
+     * In the latter case, scsi_req_complete clears unit attention conditions
+     * after moving them to the device's sense buffer.
+     */
+    scsi_clear_unit_attention(req);
+    return ret;
 }
 
 int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed)
@@ -973,6 +1055,13 @@ void scsi_req_complete(SCSIRequest *req, int status)
     }
     req->dev->sense_len = req->sense_len;
 
+    /*
+     * Unit attention state is now stored in the device's sense buffer
+     * if the HBA didn't do autosense.  Clear the pending unit attention
+     * flags.
+     */
+    scsi_clear_unit_attention(req);
+
     scsi_req_ref(req);
     scsi_req_dequeue(req);
     req->bus->ops->complete(req, req->status);
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index 79ab9d5..9e0b788 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -102,6 +102,7 @@
 #define REWIND 0x01
 #define REPORT_DENSITY_SUPPORT 0x44
 #define GET_CONFIGURATION 0x46
+#define GET_EVENT_STATUS_NOTIFICATION 0x4a
 #define READ_16 0x88
 #define WRITE_16 0x8a
 #define WRITE_VERIFY_16 0x8e
diff --git a/hw/scsi.h b/hw/scsi.h
index 4d5b596..09c3606 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -62,6 +62,7 @@ struct SCSIDevice
     uint32_t id;
     BlockConf conf;
     SCSIDeviceInfo *info;
+    SCSISense unit_attention;
     uint8_t sense[SCSI_SENSE_BUF_SIZE];
     uint32_t sense_len;
     QTAILQ_HEAD(, SCSIRequest) requests;
@@ -105,6 +106,7 @@ struct SCSIBus {
     BusState qbus;
     int busnr;
 
+    SCSISense unit_attention;
     int tcq, ndev;
     const SCSIBusOps *ops;
 
-- 
1.7.6

  parent reply	other threads:[~2011-08-03  8:49 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-03  8:49 [Qemu-devel] [PATCH 00/16] SCSI sense and target request overhaul Paolo Bonzini
2011-08-03  8:49 ` [Qemu-devel] [PATCH 01/16] scsi-disk: no need to call scsi_req_data on a short read Paolo Bonzini
2011-08-03 16:32   ` Christoph Hellwig
2011-08-04 13:35   ` Stefan Hajnoczi
2011-08-04 13:46     ` Kevin Wolf
2011-08-03  8:49 ` [Qemu-devel] [PATCH 02/16] vscsi: always use get_sense Paolo Bonzini
2011-08-03 16:32   ` Christoph Hellwig
2011-08-03  8:49 ` [Qemu-devel] [PATCH 03/16] scsi: pass status when completing Paolo Bonzini
2011-08-03 16:34   ` Christoph Hellwig
2011-08-03  8:49 ` [Qemu-devel] [PATCH 04/16] scsi: move sense handling to generic code Paolo Bonzini
2011-08-03 16:34   ` Christoph Hellwig
2011-08-03  8:49 ` [Qemu-devel] [PATCH 05/16] scsi: introduce SCSIReqOps Paolo Bonzini
2011-08-03  8:49 ` [Qemu-devel] [PATCH 06/16] scsi: move request-related callbacks from SCSIDeviceInfo to SCSIReqOps Paolo Bonzini
2011-08-03  8:49 ` [Qemu-devel] [PATCH 07/16] scsi: pass cdb already to scsi_req_new Paolo Bonzini
2011-08-03  8:49 ` [Qemu-devel] [PATCH 08/16] scsi: introduce SCSICommand Paolo Bonzini
2011-08-03  8:49 ` [Qemu-devel] [PATCH 09/16] scsi: push lun field to SCSIDevice Paolo Bonzini
2011-08-03  8:49 ` [Qemu-devel] [PATCH 10/16] scsi: move request parsing to common code Paolo Bonzini
2011-08-12 16:12   ` Peter Maydell
2011-08-12 17:05     ` Paolo Bonzini
2011-08-12 16:55   ` Peter Maydell
2011-08-12 17:11     ` Paolo Bonzini
2011-08-03  8:49 ` [Qemu-devel] [PATCH 11/16] scsi: move handling of REPORT LUNS and invalid LUNs " Paolo Bonzini
2011-08-03  8:49 ` [Qemu-devel] [PATCH 12/16] scsi: move handling of REQUEST SENSE " Paolo Bonzini
2011-08-03  8:49 ` [Qemu-devel] [PATCH 13/16] scsi: add a bunch more common sense codes Paolo Bonzini
2011-08-03  8:49 ` Paolo Bonzini [this message]
2011-08-03  8:49 ` [Qemu-devel] [PATCH 15/16] scsi: report unit attention on reset Paolo Bonzini
2011-08-03  8:49 ` [Qemu-devel] [PATCH 16/16] scsi: add special traces for common commands Paolo Bonzini
2011-08-12 13:49 ` [Qemu-devel] [PATCH 00/16] SCSI sense and target request overhaul Anthony Liguori
2011-08-12 15:48   ` Paolo Bonzini

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=1312361359-15445-15-git-send-email-pbonzini@redhat.com \
    --to=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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).