summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-09-27 08:14:15 +0000
committermav <mav@FreeBSD.org>2014-09-27 08:14:15 +0000
commit5df569ca0ad48d57e9e0b747bf73a5361e7cb236 (patch)
tree9d8aca91da1d584db627127c90479faf41f5913c
parent6a9b8ab035c5cd9b9ca271cea31e96c1309f9316 (diff)
downloadFreeBSD-src-5df569ca0ad48d57e9e0b747bf73a5361e7cb236.zip
FreeBSD-src-5df569ca0ad48d57e9e0b747bf73a5361e7cb236.tar.gz
MFC r272040:
When reporting some major UNIT ATTENTION condition, like POWER ON OCCURRED or I_T NEXUS LOSS, clear all minor UAs for the LUN, redundant in this case. All SAM specifications tell that target MAY do it, but libiscsi initiator seems require it to be done, terminating connection with error if some more UAs happen to be reported during iSCSI connection. Approved by: re (gjb)
-rw-r--r--sys/cam/ctl/ctl.c15
-rw-r--r--sys/cam/ctl/ctl.h2
-rw-r--r--sys/cam/ctl/ctl_error.c31
-rw-r--r--sys/cam/ctl/ctl_error.h2
4 files changed, 22 insertions, 28 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 243295d..28aed8d 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -9684,13 +9684,10 @@ ctl_request_sense(struct ctl_scsiio *ctsio)
if (lun->pending_ua[initidx] != CTL_UA_NONE) {
ctl_ua_type ua_type;
- ua_type = ctl_build_ua(lun->pending_ua[initidx],
+ ua_type = ctl_build_ua(&lun->pending_ua[initidx],
sense_ptr, sense_format);
- if (ua_type != CTL_UA_NONE) {
+ if (ua_type != CTL_UA_NONE)
have_error = 1;
- /* We're reporting this UA, so clear it */
- lun->pending_ua[initidx] &= ~ua_type;
- }
}
mtx_unlock(&lun->lun_lock);
@@ -11604,8 +11601,7 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
if ((entry->flags & CTL_CMD_FLAG_NO_SENSE) == 0) {
ctl_ua_type ua_type;
- ua_type = lun->pending_ua[initidx];
- if (ua_type != CTL_UA_NONE) {
+ if (lun->pending_ua[initidx] != CTL_UA_NONE) {
scsi_sense_data_type sense_format;
if (lun != NULL)
@@ -11615,14 +11611,13 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
else
sense_format = SSD_TYPE_FIXED;
- ua_type = ctl_build_ua(ua_type, &ctsio->sense_data,
- sense_format);
+ ua_type = ctl_build_ua(&lun->pending_ua[initidx],
+ &ctsio->sense_data, sense_format);
if (ua_type != CTL_UA_NONE) {
ctsio->scsi_status = SCSI_STATUS_CHECK_COND;
ctsio->io_hdr.status = CTL_SCSI_ERROR |
CTL_AUTOSENSE;
ctsio->sense_len = SSD_FULL_SIZE;
- lun->pending_ua[initidx] &= ~ua_type;
mtx_unlock(&lun->lun_lock);
ctl_done((union ctl_io *)ctsio);
return (retval);
diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h
index 0525a51..918444b 100644
--- a/sys/cam/ctl/ctl.h
+++ b/sys/cam/ctl/ctl.h
@@ -119,7 +119,7 @@ typedef enum {
CTL_UA_I_T_NEXUS_LOSS = 0x0008,
CTL_UA_LUN_RESET = 0x0010,
CTL_UA_LUN_CHANGE = 0x0020,
- CTL_UA_MODE_CHANGE = 0x0030,
+ CTL_UA_MODE_CHANGE = 0x0040,
CTL_UA_LOG_CHANGE = 0x0080,
CTL_UA_LVD = 0x0100,
CTL_UA_SE = 0x0200,
diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c
index 6ecb54b..cb47f6d 100644
--- a/sys/cam/ctl/ctl_error.c
+++ b/sys/cam/ctl/ctl_error.c
@@ -367,44 +367,42 @@ ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq)
}
ctl_ua_type
-ctl_build_ua(ctl_ua_type ua_type, struct scsi_sense_data *sense,
+ctl_build_ua(ctl_ua_type *ua_type, struct scsi_sense_data *sense,
scsi_sense_data_type sense_format)
{
- ctl_ua_type ua_to_build;
- int i, asc, ascq;
+ ctl_ua_type ua_to_build, ua_to_clear;
+ int asc, ascq;
- if (ua_type == CTL_UA_NONE)
- return (ua_type);
+ if (*ua_type == CTL_UA_NONE)
+ return (CTL_UA_NONE);
- ua_to_build = CTL_UA_NONE;
-
- for (i = 0; i < (sizeof(ua_type) * 8); i++) {
- if (ua_type & (1 << i)) {
- ua_to_build = 1 << i;
- break;
- }
- }
+ ua_to_build = (1 << (ffs(*ua_type) - 1));
+ ua_to_clear = ua_to_build;
switch (ua_to_build) {
case CTL_UA_POWERON:
/* 29h/01h POWER ON OCCURRED */
asc = 0x29;
ascq = 0x01;
+ ua_to_clear = ~0;
break;
case CTL_UA_BUS_RESET:
/* 29h/02h SCSI BUS RESET OCCURRED */
asc = 0x29;
ascq = 0x02;
+ ua_to_clear = ~0;
break;
case CTL_UA_TARG_RESET:
/* 29h/03h BUS DEVICE RESET FUNCTION OCCURRED*/
asc = 0x29;
ascq = 0x03;
+ ua_to_clear = ~0;
break;
case CTL_UA_I_T_NEXUS_LOSS:
/* 29h/07h I_T NEXUS LOSS OCCURRED */
asc = 0x29;
ascq = 0x07;
+ ua_to_clear = ~0;
break;
case CTL_UA_LUN_RESET:
/* 29h/00h POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */
@@ -466,9 +464,7 @@ ctl_build_ua(ctl_ua_type ua_type, struct scsi_sense_data *sense,
ascq = 0x09;
break;
default:
- ua_to_build = CTL_UA_NONE;
- return (ua_to_build);
- break; /* NOTREACHED */
+ panic("ctl_build_ua: Unknown UA %x", ua_to_build);
}
ctl_set_sense_data(sense,
@@ -480,6 +476,9 @@ ctl_build_ua(ctl_ua_type ua_type, struct scsi_sense_data *sense,
ascq,
SSD_ELEM_NONE);
+ /* We're reporting this UA, so clear it */
+ *ua_type &= ~ua_to_clear;
+
return (ua_to_build);
}
diff --git a/sys/cam/ctl/ctl_error.h b/sys/cam/ctl/ctl_error.h
index 62596d0..034d14b 100644
--- a/sys/cam/ctl/ctl_error.h
+++ b/sys/cam/ctl/ctl_error.h
@@ -55,7 +55,7 @@ void ctl_sense_to_desc(struct scsi_sense_data_fixed *sense_src,
void ctl_sense_to_fixed(struct scsi_sense_data_desc *sense_src,
struct scsi_sense_data_fixed *sense_dest);
void ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq);
-ctl_ua_type ctl_build_ua(ctl_ua_type ua_type, struct scsi_sense_data *sense,
+ctl_ua_type ctl_build_ua(ctl_ua_type *ua_type, struct scsi_sense_data *sense,
scsi_sense_data_type sense_format);
void ctl_set_overlapped_cmd(struct ctl_scsiio *ctsio);
void ctl_set_overlapped_tag(struct ctl_scsiio *ctsio, uint8_t tag);
OpenPOWER on IntegriCloud