scsi: establish precedence levels for unit attention
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 <pbonzini@redhat.com>
This commit is contained in:
parent
350e6e4199
commit
e48e84ea80
@ -1531,6 +1531,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;
|
||||
@ -1539,7 +1588,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)
|
||||
|
@ -1876,7 +1876,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;
|
||||
}
|
||||
@ -1913,7 +1913,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -412,6 +412,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"
|
||||
|
Loading…
Reference in New Issue
Block a user