[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/5] scsi: establish precedence levels for unit atte
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH 3/5] scsi: establish precedence levels for unit attention |
Date: |
Mon, 16 Jul 2012 16:25:54 +0200 |
When a device is resized, we will report a unit attention condition
for CAPACITY DATA HAS CHANGED. However, we should ensure that this
condition does not override a more important unit attention condition.
Signed-off-by: Paolo Bonzini <address@hidden>
---
hw/scsi-bus.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
hw/scsi-disk.c | 4 ++--
hw/scsi.h | 1 +
trace-events | 1 +
4 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 2547c50..d5e1fb0 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1530,6 +1530,55 @@ void scsi_req_abort(SCSIRequest *req, int status)
scsi_req_unref(req);
}
+static int scsi_ua_precedence(SCSISense sense)
+{
+ if (sense.key != UNIT_ATTENTION) {
+ return INT_MAX;
+ }
+ if (sense.asc == 0x29 && sense.ascq == 0x04) {
+ /* DEVICE INTERNAL RESET goes with POWER ON OCCURRED */
+ return 1;
+ } else if (sense.asc == 0x3F && sense.ascq == 0x01) {
+ /* MICROCODE HAS BEEN CHANGED goes with SCSI BUS RESET OCCURRED */
+ return 2;
+ } else if (sense.asc == 0x29 && (sense.ascq == 0x05 || sense.ascq ==
0x06)) {
+ /* These two go with "all others". */
+ ;
+ } else if (sense.asc == 0x29 && sense.ascq <= 0x07) {
+ /* POWER ON, RESET OR BUS DEVICE RESET OCCURRED = 0
+ * POWER ON OCCURRED = 1
+ * SCSI BUS RESET OCCURRED = 2
+ * BUS DEVICE RESET FUNCTION OCCURRED = 3
+ * I_T NEXUS LOSS OCCURRED = 7
+ */
+ return sense.ascq;
+ } else if (sense.asc == 0x2F && sense.ascq == 0x01) {
+ /* COMMANDS CLEARED BY POWER LOSS NOTIFICATION */
+ return 8;
+ }
+ return (sense.asc << 8) | sense.ascq;
+}
+
+void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense)
+{
+ int prec1, prec2;
+ if (sense.key != UNIT_ATTENTION) {
+ return;
+ }
+ trace_scsi_device_set_ua(sdev->id, sdev->lun, sense.key,
+ sense.asc, sense.ascq);
+
+ /*
+ * Override a pre-existing unit attention condition, except for a more
+ * important reset condition.
+ */
+ prec1 = scsi_ua_precedence(sdev->unit_attention);
+ prec2 = scsi_ua_precedence(sense);
+ if (prec2 < prec1) {
+ sdev->unit_attention = sense;
+ }
+}
+
void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense)
{
SCSIRequest *req;
@@ -1538,7 +1587,8 @@ void scsi_device_purge_requests(SCSIDevice *sdev,
SCSISense sense)
req = QTAILQ_FIRST(&sdev->requests);
scsi_req_cancel(req);
}
- sdev->unit_attention = sense;
+
+ scsi_device_set_ua(sdev, sense);
}
static char *scsibus_get_dev_path(DeviceState *dev)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 0905446..fabd0bf 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1886,7 +1886,7 @@ static void scsi_cd_change_media_cb(void *opaque, bool
load)
*/
s->media_changed = load;
s->tray_open = !load;
- s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
+ scsi_device_set_ua(&s->qdev, SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM));
s->media_event = true;
s->eject_request = false;
}
@@ -1925,7 +1925,7 @@ static void scsi_disk_unit_attention_reported(SCSIDevice
*dev)
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
if (s->media_changed) {
s->media_changed = false;
- s->qdev.unit_attention = SENSE_CODE(MEDIUM_CHANGED);
+ scsi_device_set_ua(&s->qdev, SENSE_CODE(MEDIUM_CHANGED));
}
}
diff --git a/hw/scsi.h b/hw/scsi.h
index e901350..4804be9 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -239,6 +239,7 @@ void scsi_req_abort(SCSIRequest *req, int status);
void scsi_req_cancel(SCSIRequest *req);
void scsi_req_retry(SCSIRequest *req);
void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
+void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
diff --git a/trace-events b/trace-events
index 7baa42d..90e9c2a 100644
--- a/trace-events
+++ b/trace-events
@@ -393,6 +393,7 @@ scsi_req_parsed(int target, int lun, int tag, int cmd, int
mode, int xfer) "targ
scsi_req_parsed_lba(int target, int lun, int tag, int cmd, uint64_t lba)
"target %d lun %d tag %d command %d lba %"PRIu64
scsi_req_parse_bad(int target, int lun, int tag, int cmd) "target %d lun %d
tag %d command %d"
scsi_req_build_sense(int target, int lun, int tag, int key, int asc, int ascq)
"target %d lun %d tag %d key %#02x asc %#02x ascq %#02x"
+scsi_device_set_ua(int target, int lun, int key, int asc, int ascq) "target %d
lun %d key %#02x asc %#02x ascq %#02x"
scsi_report_luns(int target, int lun, int tag) "target %d lun %d tag %d"
scsi_inquiry(int target, int lun, int tag, int cdb1, int cdb2) "target %d lun
%d tag %d page %#02x/%#02x"
scsi_test_unit_ready(int target, int lun, int tag) "target %d lun %d tag %d"
--
1.7.10.4