summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/ctl/ctl.c384
-rw-r--r--sys/cam/ctl/ctl.h19
-rw-r--r--sys/cam/ctl/ctl_error.c8
-rw-r--r--sys/cam/ctl/ctl_private.h24
-rw-r--r--sys/cam/scsi/scsi_all.h29
-rw-r--r--sys/cam/scsi/scsi_da.h14
6 files changed, 240 insertions, 238 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 51751d7..c889ec1 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -93,25 +93,6 @@ struct ctl_softc *control_softc = NULL;
* Note that these are default values only. The actual values will be
* filled in when the user does a mode sense.
*/
-const static struct copan_debugconf_subpage debugconf_page_default = {
- DBGCNF_PAGE_CODE | SMPH_SPF, /* page_code */
- DBGCNF_SUBPAGE_CODE, /* subpage */
- {(sizeof(struct copan_debugconf_subpage) - 4) >> 8,
- (sizeof(struct copan_debugconf_subpage) - 4) >> 0}, /* page_length */
- DBGCNF_VERSION, /* page_version */
- {CTL_TIME_IO_DEFAULT_SECS>>8,
- CTL_TIME_IO_DEFAULT_SECS>>0}, /* ctl_time_io_secs */
-};
-
-const static struct copan_debugconf_subpage debugconf_page_changeable = {
- DBGCNF_PAGE_CODE | SMPH_SPF, /* page_code */
- DBGCNF_SUBPAGE_CODE, /* subpage */
- {(sizeof(struct copan_debugconf_subpage) - 4) >> 8,
- (sizeof(struct copan_debugconf_subpage) - 4) >> 0}, /* page_length */
- 0, /* page_version */
- {0xff,0xff}, /* ctl_time_io_secs */
-};
-
const static struct scsi_da_rw_recovery_page rw_er_page_default = {
/*page_code*/SMS_RW_ERROR_RECOVERY_PAGE,
/*page_length*/sizeof(struct scsi_da_rw_recovery_page) - 2,
@@ -129,12 +110,12 @@ const static struct scsi_da_rw_recovery_page rw_er_page_default = {
const static struct scsi_da_rw_recovery_page rw_er_page_changeable = {
/*page_code*/SMS_RW_ERROR_RECOVERY_PAGE,
/*page_length*/sizeof(struct scsi_da_rw_recovery_page) - 2,
- /*byte3*/0,
+ /*byte3*/SMS_RWER_PER,
/*read_retry_count*/0,
/*correction_span*/0,
/*head_offset_count*/0,
/*data_strobe_offset_cnt*/0,
- /*byte8*/0,
+ /*byte8*/SMS_RWER_LBPERE,
/*write_retry_count*/0,
/*reserved2*/0,
/*recovery_time_limit*/{0, 0},
@@ -206,6 +187,24 @@ const static struct scsi_rigid_disk_page rigid_disk_page_changeable = {
/*reserved2*/ {0, 0}
};
+const static struct scsi_da_verify_recovery_page verify_er_page_default = {
+ /*page_code*/SMS_VERIFY_ERROR_RECOVERY_PAGE,
+ /*page_length*/sizeof(struct scsi_da_verify_recovery_page) - 2,
+ /*byte3*/0,
+ /*read_retry_count*/0,
+ /*reserved*/{ 0, 0, 0, 0, 0, 0 },
+ /*recovery_time_limit*/{0, 0},
+};
+
+const static struct scsi_da_verify_recovery_page verify_er_page_changeable = {
+ /*page_code*/SMS_VERIFY_ERROR_RECOVERY_PAGE,
+ /*page_length*/sizeof(struct scsi_da_verify_recovery_page) - 2,
+ /*byte3*/SMS_VER_PER,
+ /*read_retry_count*/0,
+ /*reserved*/{ 0, 0, 0, 0, 0, 0 },
+ /*recovery_time_limit*/{0, 0},
+};
+
const static struct scsi_caching_page caching_page_default = {
/*page_code*/SMS_CACHING_PAGE,
/*page_length*/sizeof(struct scsi_caching_page) - 2,
@@ -285,19 +284,20 @@ const static struct scsi_control_ext_page control_ext_page_changeable = {
const static struct scsi_info_exceptions_page ie_page_default = {
/*page_code*/SMS_INFO_EXCEPTIONS_PAGE,
/*page_length*/sizeof(struct scsi_info_exceptions_page) - 2,
- /*info_flags*/SIEP_FLAGS_DEXCPT,
- /*mrie*/0,
+ /*info_flags*/SIEP_FLAGS_EWASC,
+ /*mrie*/SIEP_MRIE_NO,
/*interval_timer*/{0, 0, 0, 0},
- /*report_count*/{0, 0, 0, 0}
+ /*report_count*/{0, 0, 0, 1}
};
const static struct scsi_info_exceptions_page ie_page_changeable = {
/*page_code*/SMS_INFO_EXCEPTIONS_PAGE,
/*page_length*/sizeof(struct scsi_info_exceptions_page) - 2,
- /*info_flags*/0,
- /*mrie*/0,
- /*interval_timer*/{0, 0, 0, 0},
- /*report_count*/{0, 0, 0, 0}
+ /*info_flags*/SIEP_FLAGS_EWASC | SIEP_FLAGS_DEXCPT | SIEP_FLAGS_TEST |
+ SIEP_FLAGS_LOGERR,
+ /*mrie*/0x0f,
+ /*interval_timer*/{0xff, 0xff, 0xff, 0xff},
+ /*report_count*/{0xff, 0xff, 0xff, 0xff}
};
#define CTL_LBPM_LEN (sizeof(struct ctl_logical_block_provisioning_page) - 4)
@@ -4061,6 +4061,26 @@ ctl_init_page_index(struct ctl_lun *lun)
(uint8_t *)lun->mode_pages.rigid_disk_page;
break;
}
+ case SMS_VERIFY_ERROR_RECOVERY_PAGE: {
+ KASSERT(page_index->subpage == SMS_SUBPAGE_PAGE_0,
+ ("subpage %#x for page %#x is incorrect!",
+ page_index->subpage, page_code));
+ memcpy(&lun->mode_pages.verify_er_page[CTL_PAGE_CURRENT],
+ &verify_er_page_default,
+ sizeof(verify_er_page_default));
+ memcpy(&lun->mode_pages.verify_er_page[CTL_PAGE_CHANGEABLE],
+ &verify_er_page_changeable,
+ sizeof(verify_er_page_changeable));
+ memcpy(&lun->mode_pages.verify_er_page[CTL_PAGE_DEFAULT],
+ &verify_er_page_default,
+ sizeof(verify_er_page_default));
+ memcpy(&lun->mode_pages.verify_er_page[CTL_PAGE_SAVED],
+ &verify_er_page_default,
+ sizeof(verify_er_page_default));
+ page_index->page_data =
+ (uint8_t *)lun->mode_pages.verify_er_page;
+ break;
+ }
case SMS_CACHING_PAGE: {
struct scsi_caching_page *caching_page;
@@ -4271,35 +4291,6 @@ ctl_init_page_index(struct ctl_lun *lun)
(uint8_t *)lun->mode_pages.cddvd_page;
break;
}
- case SMS_VENDOR_SPECIFIC_PAGE:{
- switch (page_index->subpage) {
- case DBGCNF_SUBPAGE_CODE: {
- memcpy(&lun->mode_pages.debugconf_subpage[
- CTL_PAGE_CURRENT],
- &debugconf_page_default,
- sizeof(debugconf_page_default));
- memcpy(&lun->mode_pages.debugconf_subpage[
- CTL_PAGE_CHANGEABLE],
- &debugconf_page_changeable,
- sizeof(debugconf_page_changeable));
- memcpy(&lun->mode_pages.debugconf_subpage[
- CTL_PAGE_DEFAULT],
- &debugconf_page_default,
- sizeof(debugconf_page_default));
- memcpy(&lun->mode_pages.debugconf_subpage[
- CTL_PAGE_SAVED],
- &debugconf_page_default,
- sizeof(debugconf_page_default));
- page_index->page_data =
- (uint8_t *)lun->mode_pages.debugconf_subpage;
- break;
- }
- default:
- panic("subpage %#x for page %#x is incorrect!",
- page_index->subpage, page_code);
- }
- break;
- }
default:
panic("invalid page code value %#x", page_code);
}
@@ -4352,6 +4343,8 @@ ctl_init_log_page_index(struct ctl_lun *lun)
lun->log_pages.index[2].page_len = 12*CTL_NUM_LBP_PARAMS;
lun->log_pages.index[3].page_data = (uint8_t *)&lun->log_pages.stat_page;
lun->log_pages.index[3].page_len = sizeof(lun->log_pages.stat_page);
+ lun->log_pages.index[4].page_data = (uint8_t *)&lun->log_pages.ie_page;
+ lun->log_pages.index[4].page_len = sizeof(lun->log_pages.ie_page);
return (CTL_RETVAL_COMPLETE);
}
@@ -4582,6 +4575,8 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
TAILQ_INIT(&lun->ooa_queue);
TAILQ_INIT(&lun->blocked_queue);
STAILQ_INIT(&lun->error_list);
+ lun->ie_reported = 1;
+ callout_init_mtx(&lun->ie_callout, &lun->lun_lock, 0);
ctl_tpc_lun_init(lun);
/*
@@ -4655,6 +4650,9 @@ ctl_free_lun(struct ctl_lun *lun)
atomic_subtract_int(&lun->be_lun->be->num_luns, 1);
lun->be_lun->lun_shutdown(lun->be_lun->be_lun);
+ lun->ie_reportcnt = UINT32_MAX;
+ callout_drain(&lun->ie_callout);
+
ctl_tpc_lun_shutdown(lun);
mtx_destroy(&lun->lun_lock);
free(lun->lun_devid, M_CTL);
@@ -5823,25 +5821,12 @@ done:
return (CTL_RETVAL_COMPLETE);
}
-/*
- * Note that this function currently doesn't actually do anything inside
- * CTL to enforce things if the DQue bit is turned on.
- *
- * Also note that this function can't be used in the default case, because
- * the DQue bit isn't set in the changeable mask for the control mode page
- * anyway. This is just here as an example for how to implement a page
- * handler, and a placeholder in case we want to allow the user to turn
- * tagged queueing on and off.
- *
- * The D_SENSE bit handling is functional, however, and will turn
- * descriptor sense on and off for a given LUN.
- */
int
-ctl_control_page_handler(struct ctl_scsiio *ctsio,
+ctl_default_page_handler(struct ctl_scsiio *ctsio,
struct ctl_page_index *page_index, uint8_t *page_ptr)
{
- struct scsi_control_page *current_cp, *saved_cp, *user_cp;
struct ctl_lun *lun;
+ uint8_t *current_cp, *saved_cp;
int set_ua;
uint32_t initidx;
@@ -5849,50 +5834,15 @@ ctl_control_page_handler(struct ctl_scsiio *ctsio,
initidx = ctl_get_initindex(&ctsio->io_hdr.nexus);
set_ua = 0;
- user_cp = (struct scsi_control_page *)page_ptr;
- current_cp = (struct scsi_control_page *)
- (page_index->page_data + (page_index->page_len *
- CTL_PAGE_CURRENT));
- saved_cp = (struct scsi_control_page *)
- (page_index->page_data + (page_index->page_len *
- CTL_PAGE_SAVED));
+ current_cp = (page_index->page_data + (page_index->page_len *
+ CTL_PAGE_CURRENT));
+ saved_cp = (page_index->page_data + (page_index->page_len *
+ CTL_PAGE_SAVED));
mtx_lock(&lun->lun_lock);
- if (((current_cp->rlec & SCP_DSENSE) == 0)
- && ((user_cp->rlec & SCP_DSENSE) != 0)) {
- /*
- * Descriptor sense is currently turned off and the user
- * wants to turn it on.
- */
- current_cp->rlec |= SCP_DSENSE;
- saved_cp->rlec |= SCP_DSENSE;
- lun->flags |= CTL_LUN_SENSE_DESC;
- set_ua = 1;
- } else if (((current_cp->rlec & SCP_DSENSE) != 0)
- && ((user_cp->rlec & SCP_DSENSE) == 0)) {
- /*
- * Descriptor sense is currently turned on, and the user
- * wants to turn it off.
- */
- current_cp->rlec &= ~SCP_DSENSE;
- saved_cp->rlec &= ~SCP_DSENSE;
- lun->flags &= ~CTL_LUN_SENSE_DESC;
- set_ua = 1;
- }
- if ((current_cp->queue_flags & SCP_QUEUE_ALG_MASK) !=
- (user_cp->queue_flags & SCP_QUEUE_ALG_MASK)) {
- current_cp->queue_flags &= ~SCP_QUEUE_ALG_MASK;
- current_cp->queue_flags |= user_cp->queue_flags & SCP_QUEUE_ALG_MASK;
- saved_cp->queue_flags &= ~SCP_QUEUE_ALG_MASK;
- saved_cp->queue_flags |= user_cp->queue_flags & SCP_QUEUE_ALG_MASK;
- set_ua = 1;
- }
- if ((current_cp->eca_and_aen & SCP_SWP) !=
- (user_cp->eca_and_aen & SCP_SWP)) {
- current_cp->eca_and_aen &= ~SCP_SWP;
- current_cp->eca_and_aen |= user_cp->eca_and_aen & SCP_SWP;
- saved_cp->eca_and_aen &= ~SCP_SWP;
- saved_cp->eca_and_aen |= user_cp->eca_and_aen & SCP_SWP;
+ if (memcmp(current_cp, page_ptr, page_index->page_len)) {
+ memcpy(current_cp, page_ptr, page_index->page_len);
+ memcpy(saved_cp, page_ptr, page_index->page_len);
set_ua = 1;
}
if (set_ua != 0)
@@ -5903,101 +5853,78 @@ ctl_control_page_handler(struct ctl_scsiio *ctsio,
ctl_get_initindex(&ctsio->io_hdr.nexus),
page_index->page_code, page_index->subpage);
}
- return (0);
+ return (CTL_RETVAL_COMPLETE);
}
-int
-ctl_caching_sp_handler(struct ctl_scsiio *ctsio,
- struct ctl_page_index *page_index, uint8_t *page_ptr)
+static void
+ctl_ie_timer(void *arg)
{
- struct scsi_caching_page *current_cp, *saved_cp, *user_cp;
- struct ctl_lun *lun;
- int set_ua;
- uint32_t initidx;
+ struct ctl_lun *lun = arg;
+ struct scsi_info_exceptions_page *pg;
+ uint64_t t;
- lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
- initidx = ctl_get_initindex(&ctsio->io_hdr.nexus);
- set_ua = 0;
+ if (lun->ie_asc == 0)
+ return;
- user_cp = (struct scsi_caching_page *)page_ptr;
- current_cp = (struct scsi_caching_page *)
- (page_index->page_data + (page_index->page_len *
- CTL_PAGE_CURRENT));
- saved_cp = (struct scsi_caching_page *)
- (page_index->page_data + (page_index->page_len *
- CTL_PAGE_SAVED));
+ pg = &lun->mode_pages.ie_page[CTL_PAGE_CURRENT];
+ if (pg->mrie == SIEP_MRIE_UA)
+ ctl_est_ua_all(lun, -1, CTL_UA_IE);
+ else
+ lun->ie_reported = 0;
- mtx_lock(&lun->lun_lock);
- if ((current_cp->flags1 & (SCP_WCE | SCP_RCD)) !=
- (user_cp->flags1 & (SCP_WCE | SCP_RCD))) {
- current_cp->flags1 &= ~(SCP_WCE | SCP_RCD);
- current_cp->flags1 |= user_cp->flags1 & (SCP_WCE | SCP_RCD);
- saved_cp->flags1 &= ~(SCP_WCE | SCP_RCD);
- saved_cp->flags1 |= user_cp->flags1 & (SCP_WCE | SCP_RCD);
- set_ua = 1;
+ if (lun->ie_reportcnt < scsi_4btoul(pg->report_count)) {
+ lun->ie_reportcnt++;
+ t = scsi_4btoul(pg->interval_timer);
+ if (t == 0 || t == UINT32_MAX)
+ t = 3000; /* 5 min */
+ callout_schedule(&lun->ie_callout, t * hz / 10);
}
- if (set_ua != 0)
- ctl_est_ua_all(lun, initidx, CTL_UA_MODE_CHANGE);
- mtx_unlock(&lun->lun_lock);
- if (set_ua) {
- ctl_isc_announce_mode(lun,
- ctl_get_initindex(&ctsio->io_hdr.nexus),
- page_index->page_code, page_index->subpage);
- }
- return (0);
}
int
-ctl_debugconf_sp_select_handler(struct ctl_scsiio *ctsio,
- struct ctl_page_index *page_index,
- uint8_t *page_ptr)
-{
- uint8_t *c;
- int i;
-
- c = ((struct copan_debugconf_subpage *)page_ptr)->ctl_time_io_secs;
- ctl_time_io_secs =
- (c[0] << 8) |
- (c[1] << 0) |
- 0;
- CTL_DEBUG_PRINT(("set ctl_time_io_secs to %d\n", ctl_time_io_secs));
- printf("set ctl_time_io_secs to %d\n", ctl_time_io_secs);
- printf("page data:");
- for (i=0; i<8; i++)
- printf(" %.2x",page_ptr[i]);
- printf("\n");
- return (0);
-}
-
-int
-ctl_debugconf_sp_sense_handler(struct ctl_scsiio *ctsio,
- struct ctl_page_index *page_index,
- int pc)
+ctl_ie_page_handler(struct ctl_scsiio *ctsio,
+ struct ctl_page_index *page_index, uint8_t *page_ptr)
{
- struct copan_debugconf_subpage *page;
+ struct scsi_info_exceptions_page *pg;
+ struct ctl_lun *lun;
+ uint64_t t;
- page = (struct copan_debugconf_subpage *)page_index->page_data +
- (page_index->page_len * pc);
+ (void)ctl_default_page_handler(ctsio, page_index, page_ptr);
- switch (pc) {
- case SMS_PAGE_CTRL_CHANGEABLE >> 6:
- case SMS_PAGE_CTRL_DEFAULT >> 6:
- case SMS_PAGE_CTRL_SAVED >> 6:
- /*
- * We don't update the changeable or default bits for this page.
- */
- break;
- case SMS_PAGE_CTRL_CURRENT >> 6:
- page->ctl_time_io_secs[0] = ctl_time_io_secs >> 8;
- page->ctl_time_io_secs[1] = ctl_time_io_secs >> 0;
- break;
- default:
- break;
+ lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ pg = (struct scsi_info_exceptions_page *)page_ptr;
+ mtx_lock(&lun->lun_lock);
+ if (pg->info_flags & SIEP_FLAGS_TEST) {
+ lun->ie_asc = 0x5d;
+ lun->ie_ascq = 0xff;
+ if (pg->mrie == SIEP_MRIE_UA) {
+ ctl_est_ua_all(lun, -1, CTL_UA_IE);
+ lun->ie_reported = 1;
+ } else {
+ ctl_clr_ua_all(lun, -1, CTL_UA_IE);
+ lun->ie_reported = -1;
+ }
+ lun->ie_reportcnt = 1;
+ if (lun->ie_reportcnt < scsi_4btoul(pg->report_count)) {
+ lun->ie_reportcnt++;
+ t = scsi_4btoul(pg->interval_timer);
+ if (t == 0 || t == UINT32_MAX)
+ t = 3000; /* 5 min */
+ callout_reset(&lun->ie_callout, t * hz / 10,
+ ctl_ie_timer, lun);
+ }
+ } else {
+ lun->ie_asc = 0;
+ lun->ie_ascq = 0;
+ lun->ie_reported = 1;
+ ctl_clr_ua_all(lun, -1, CTL_UA_IE);
+ lun->ie_reportcnt = UINT32_MAX;
+ callout_stop(&lun->ie_callout);
}
- return (0);
+ mtx_unlock(&lun->lun_lock);
+ return (CTL_RETVAL_COMPLETE);
}
-
static int
ctl_do_mode_select(union ctl_io *io)
{
@@ -6815,8 +6742,27 @@ ctl_sap_log_sense_handler(struct ctl_scsiio *ctsio,
sizeof(struct scsi_log_param_header);
scsi_ulto4b(3, data->ti.exponent);
scsi_ulto4b(1, data->ti.integer);
+ return (0);
+}
+
+int
+ctl_ie_log_sense_handler(struct ctl_scsiio *ctsio,
+ struct ctl_page_index *page_index,
+ int pc)
+{
+ struct ctl_lun *lun;
+ struct scsi_log_informational_exceptions *data;
- page_index->page_len = sizeof(*data);
+ lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ data = (struct scsi_log_informational_exceptions *)page_index->page_data;
+
+ scsi_ulto2b(SLP_IE_GEN, data->hdr.param_code);
+ data->hdr.param_control = SLP_LBIN;
+ data->hdr.param_len = sizeof(struct scsi_log_informational_exceptions) -
+ sizeof(struct scsi_log_param_header);
+ data->ie_asc = lun->ie_asc;
+ data->ie_ascq = lun->ie_ascq;
+ data->temperature = 0xff;
return (0);
}
@@ -9256,6 +9202,7 @@ ctl_request_sense(struct ctl_scsiio *ctsio)
int have_error;
scsi_sense_data_type sense_format;
ctl_ua_type ua_type;
+ uint8_t asc = 0, ascq = 0;
cdb = (struct scsi_request_sense *)ctsio->cdb;
@@ -9374,19 +9321,23 @@ ctl_request_sense(struct ctl_scsiio *ctsio)
return (CTL_RETVAL_COMPLETE);
}
-no_sense:
-
/*
* No sense information to report, so we report that everything is
- * okay.
+ * okay, unless we have allowed Informational Exception.
*/
+ if (lun->mode_pages.ie_page[CTL_PAGE_CURRENT].mrie != SIEP_MRIE_NO) {
+ asc = lun->ie_asc;
+ ascq = lun->ie_ascq;
+ }
+
+no_sense:
ctl_set_sense_data(sense_ptr,
lun,
sense_format,
/*current_error*/ 1,
/*sense_key*/ SSD_KEY_NO_SENSE,
- /*asc*/ 0x00,
- /*ascq*/ 0x00,
+ /*asc*/ asc,
+ /*ascq*/ ascq,
SSD_ELEM_NONE);
/*
@@ -13256,6 +13207,37 @@ ctl_process_done(union ctl_io *io)
mtx_lock(&lun->lun_lock);
/*
+ * Check to see if we have any informational exception and status
+ * of this command can be modified to report it in form of either
+ * RECOVERED ERROR or NO SENSE, depending on MRIE mode page field.
+ */
+ if (lun->ie_reported == 0 && lun->ie_asc != 0 &&
+ io->io_hdr.status == CTL_SUCCESS &&
+ (io->io_hdr.flags & CTL_FLAG_STATUS_SENT) == 0) {
+ uint8_t mrie = lun->mode_pages.ie_page[CTL_PAGE_CURRENT].mrie;
+ uint8_t per =
+ ((lun->mode_pages.rw_er_page[CTL_PAGE_CURRENT].byte3 &
+ SMS_RWER_PER) ||
+ (lun->mode_pages.verify_er_page[CTL_PAGE_CURRENT].byte3 &
+ SMS_VER_PER));
+ if (((mrie == SIEP_MRIE_REC_COND && per) ||
+ mrie == SIEP_MRIE_REC_UNCOND ||
+ mrie == SIEP_MRIE_NO_SENSE) &&
+ (ctl_get_cmd_entry(&io->scsiio, NULL)->flags &
+ CTL_CMD_FLAG_NO_SENSE) == 0) {
+ ctl_set_sense(&io->scsiio,
+ /*current_error*/ 1,
+ /*sense_key*/ (mrie == SIEP_MRIE_NO_SENSE) ?
+ SSD_KEY_NO_SENSE : SSD_KEY_RECOVERED_ERROR,
+ /*asc*/ lun->ie_asc,
+ /*ascq*/ lun->ie_ascq,
+ SSD_ELEM_NONE);
+ lun->ie_reported = 1;
+ }
+ } else if (lun->ie_reported < 0)
+ lun->ie_reported = 0;
+
+ /*
* Check to see if we have any errors to inject here. We only
* inject errors for commands that don't already have errors set.
*/
@@ -13528,10 +13510,6 @@ ctl_done(union ctl_io *io)
#ifdef CTL_IO_DELAY
if (io->io_hdr.flags & CTL_FLAG_DELAY_DONE) {
- struct ctl_lun *lun;
-
- lun =(struct ctl_lun *)io->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
-
io->io_hdr.flags &= ~CTL_FLAG_DELAY_DONE;
} else {
struct ctl_lun *lun;
diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h
index 3c47a6f..7b4d06c 100644
--- a/sys/cam/ctl/ctl.h
+++ b/sys/cam/ctl/ctl.h
@@ -127,7 +127,8 @@ typedef enum {
CTL_UA_ASYM_ACC_CHANGE = 0x2000,
CTL_UA_CAPACITY_CHANGE = 0x4000,
CTL_UA_THIN_PROV_THRES = 0x8000,
- CTL_UA_MEDIUM_CHANGE = 0x10000
+ CTL_UA_MEDIUM_CHANGE = 0x10000,
+ CTL_UA_IE = 0x20000
} ctl_ua_type;
#ifdef _KERNEL
@@ -154,23 +155,21 @@ int ctl_ffz(uint32_t *mask, uint32_t first, uint32_t last);
int ctl_set_mask(uint32_t *mask, uint32_t bit);
int ctl_clear_mask(uint32_t *mask, uint32_t bit);
int ctl_is_set(uint32_t *mask, uint32_t bit);
-int ctl_caching_sp_handler(struct ctl_scsiio *ctsio,
- struct ctl_page_index *page_index, uint8_t *page_ptr);
-int ctl_control_page_handler(struct ctl_scsiio *ctsio,
+int ctl_default_page_handler(struct ctl_scsiio *ctsio,
struct ctl_page_index *page_index,
uint8_t *page_ptr);
-int ctl_debugconf_sp_sense_handler(struct ctl_scsiio *ctsio,
- struct ctl_page_index *page_index,
- int pc);
-int ctl_debugconf_sp_select_handler(struct ctl_scsiio *ctsio,
- struct ctl_page_index *page_index,
- uint8_t *page_ptr);
+int ctl_ie_page_handler(struct ctl_scsiio *ctsio,
+ struct ctl_page_index *page_index,
+ uint8_t *page_ptr);
int ctl_lbp_log_sense_handler(struct ctl_scsiio *ctsio,
struct ctl_page_index *page_index,
int pc);
int ctl_sap_log_sense_handler(struct ctl_scsiio *ctsio,
struct ctl_page_index *page_index,
int pc);
+int ctl_ie_log_sense_handler(struct ctl_scsiio *ctsio,
+ struct ctl_page_index *page_index,
+ int pc);
int ctl_config_move_done(union ctl_io *io);
void ctl_datamove(union ctl_io *io);
void ctl_serseq_done(union ctl_io *io);
diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c
index 61ec4ec..014499f 100644
--- a/sys/cam/ctl/ctl_error.c
+++ b/sys/cam/ctl/ctl_error.c
@@ -84,7 +84,8 @@ ctl_set_sense_data_va(struct scsi_sense_data *sense_data, void *lunptr,
* on for that LUN.
*/
if ((lun != NULL)
- && (lun->flags & CTL_LUN_SENSE_DESC))
+ && (lun->mode_pages.control_page[CTL_PAGE_CURRENT].rlec &
+ SCP_DSENSE))
sense_format = SSD_TYPE_DESC;
else
sense_format = SSD_TYPE_FIXED;
@@ -461,6 +462,11 @@ ctl_ua_to_acsq(struct ctl_lun *lun, ctl_ua_type ua_to_build, int *asc,
*asc = 0x28;
*ascq = 0x00;
break;
+ case CTL_UA_IE:
+ /* Informational exception */
+ *asc = lun->ie_asc;
+ *ascq = lun->ie_ascq;
+ break;
default:
panic("%s: Unknown UA %x", __func__, ua_to_build);
}
diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h
index 959d79e..483feda 100644
--- a/sys/cam/ctl/ctl_private.h
+++ b/sys/cam/ctl/ctl_private.h
@@ -151,7 +151,6 @@ typedef enum {
CTL_LUN_EJECTED = 0x080,
CTL_LUN_PR_RESERVED = 0x100,
CTL_LUN_PRIMARY_SC = 0x200,
- CTL_LUN_SENSE_DESC = 0x400,
CTL_LUN_READONLY = 0x800,
CTL_LUN_PEER_SC_PRIMARY = 0x1000,
CTL_LUN_REMOVABLE = 0x2000
@@ -272,30 +271,29 @@ struct ctl_logical_block_provisioning_page {
static const struct ctl_page_index page_index_template[] = {
{SMS_RW_ERROR_RECOVERY_PAGE, 0, sizeof(struct scsi_da_rw_recovery_page), NULL,
- CTL_PAGE_FLAG_DIRECT | CTL_PAGE_FLAG_CDROM, NULL, NULL},
+ CTL_PAGE_FLAG_DIRECT | CTL_PAGE_FLAG_CDROM, NULL, ctl_default_page_handler},
{SMS_FORMAT_DEVICE_PAGE, 0, sizeof(struct scsi_format_page), NULL,
CTL_PAGE_FLAG_DIRECT, NULL, NULL},
{SMS_RIGID_DISK_PAGE, 0, sizeof(struct scsi_rigid_disk_page), NULL,
CTL_PAGE_FLAG_DIRECT, NULL, NULL},
+ {SMS_VERIFY_ERROR_RECOVERY_PAGE, 0, sizeof(struct scsi_da_verify_recovery_page), NULL,
+ CTL_PAGE_FLAG_DIRECT | CTL_PAGE_FLAG_CDROM, NULL, ctl_default_page_handler},
{SMS_CACHING_PAGE, 0, sizeof(struct scsi_caching_page), NULL,
CTL_PAGE_FLAG_DIRECT | CTL_PAGE_FLAG_CDROM,
- NULL, ctl_caching_sp_handler},
+ NULL, ctl_default_page_handler},
{SMS_CONTROL_MODE_PAGE, 0, sizeof(struct scsi_control_page), NULL,
- CTL_PAGE_FLAG_ALL, NULL, ctl_control_page_handler},
+ CTL_PAGE_FLAG_ALL, NULL, ctl_default_page_handler},
{SMS_CONTROL_MODE_PAGE | SMPH_SPF, 0x01,
sizeof(struct scsi_control_ext_page), NULL,
CTL_PAGE_FLAG_ALL, NULL, NULL},
{SMS_INFO_EXCEPTIONS_PAGE, 0, sizeof(struct scsi_info_exceptions_page), NULL,
- CTL_PAGE_FLAG_ALL, NULL, NULL},
+ CTL_PAGE_FLAG_ALL, NULL, ctl_ie_page_handler},
{SMS_INFO_EXCEPTIONS_PAGE | SMPH_SPF, 0x02,
sizeof(struct ctl_logical_block_provisioning_page), NULL,
CTL_PAGE_FLAG_DIRECT, NULL, NULL},
{SMS_CDDVD_CAPS_PAGE, 0,
sizeof(struct scsi_cddvd_capabilities_page), NULL,
CTL_PAGE_FLAG_CDROM, NULL, NULL},
- {SMS_VENDOR_SPECIFIC_PAGE | SMPH_SPF, DBGCNF_SUBPAGE_CODE,
- sizeof(struct copan_debugconf_subpage), NULL, CTL_PAGE_FLAG_ALL,
- ctl_debugconf_sp_sense_handler, ctl_debugconf_sp_select_handler},
};
#define CTL_NUM_MODE_PAGES sizeof(page_index_template)/ \
@@ -305,13 +303,13 @@ struct ctl_mode_pages {
struct scsi_da_rw_recovery_page rw_er_page[4];
struct scsi_format_page format_page[4];
struct scsi_rigid_disk_page rigid_disk_page[4];
+ struct scsi_da_verify_recovery_page verify_er_page[4];
struct scsi_caching_page caching_page[4];
struct scsi_control_page control_page[4];
struct scsi_control_ext_page control_ext_page[4];
struct scsi_info_exceptions_page ie_page[4];
struct ctl_logical_block_provisioning_page lbp_page[4];
struct scsi_cddvd_capabilities_page cddvd_page[4];
- struct copan_debugconf_subpage debugconf_subpage[4];
struct ctl_page_index index[CTL_NUM_MODE_PAGES];
};
@@ -324,6 +322,8 @@ static const struct ctl_page_index log_page_index_template[] = {
CTL_PAGE_FLAG_DIRECT, ctl_lbp_log_sense_handler, NULL},
{SLS_STAT_AND_PERF, 0, 0, NULL,
CTL_PAGE_FLAG_ALL, ctl_sap_log_sense_handler, NULL},
+ {SLS_IE_PAGE, 0, 0, NULL,
+ CTL_PAGE_FLAG_ALL, ctl_ie_log_sense_handler, NULL},
};
#define CTL_NUM_LOG_PAGES sizeof(log_page_index_template)/ \
@@ -338,6 +338,7 @@ struct ctl_log_pages {
struct scsi_log_idle_time it;
struct scsi_log_time_interval ti;
} stat_page;
+ struct scsi_log_informational_exceptions ie_page;
struct ctl_page_index index[CTL_NUM_LOG_PAGES];
};
@@ -385,6 +386,11 @@ struct ctl_lun {
ctl_ua_type *pending_ua[CTL_MAX_PORTS];
uint8_t ua_tpt_info[8];
time_t lasttpt;
+ uint8_t ie_asc; /* Informational exceptions */
+ uint8_t ie_ascq;
+ int ie_reported; /* Already reported */
+ uint32_t ie_reportcnt; /* REPORT COUNT */
+ struct callout ie_callout; /* INTERVAL TIMER */
struct ctl_mode_pages mode_pages;
struct ctl_log_pages log_pages;
struct ctl_lun_io_stats stats;
diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h
index fc54a6f..7dc70e9 100644
--- a/sys/cam/scsi/scsi_all.h
+++ b/sys/cam/scsi/scsi_all.h
@@ -662,6 +662,14 @@ struct scsi_log_fua_stat_and_perf {
uint8_t fuanv_write_int[8];
};
+struct scsi_log_informational_exceptions {
+ struct scsi_log_param_header hdr;
+#define SLP_IE_GEN 0x0000
+ uint8_t ie_asc;
+ uint8_t ie_ascq;
+ uint8_t temperature;
+};
+
struct scsi_control_page {
u_int8_t page_code;
u_int8_t page_length;
@@ -763,21 +771,6 @@ struct scsi_caching_page {
uint8_t non_cache_seg_size[3];
};
-/*
- * XXX KDM move this off to a vendor shim.
- */
-struct copan_debugconf_subpage {
- uint8_t page_code;
-#define DBGCNF_PAGE_CODE 0x00
- uint8_t subpage;
-#define DBGCNF_SUBPAGE_CODE 0xF0
- uint8_t page_length[2];
- uint8_t page_version;
-#define DBGCNF_VERSION 0x00
- uint8_t ctl_time_io_secs[2];
-};
-
-
struct scsi_info_exceptions_page {
u_int8_t page_code;
#define SIEP_PAGE_SAVABLE 0x80 /* Page is savable */
@@ -791,6 +784,12 @@ struct scsi_info_exceptions_page {
#define SIEP_FLAGS_EBACKERR 0x02
#define SIEP_FLAGS_LOGERR 0x01
u_int8_t mrie;
+#define SIEP_MRIE_NO 0x00
+#define SIEP_MRIE_UA 0x02
+#define SIEP_MRIE_REC_COND 0x03
+#define SIEP_MRIE_REC_UNCOND 0x04
+#define SIEP_MRIE_NO_SENSE 0x05
+#define SIEP_MRIE_ON_REQ 0x06
u_int8_t interval_timer[4];
u_int8_t report_count[4];
};
diff --git a/sys/cam/scsi/scsi_da.h b/sys/cam/scsi/scsi_da.h
index ad4d0db..1af4db4 100644
--- a/sys/cam/scsi/scsi_da.h
+++ b/sys/cam/scsi/scsi_da.h
@@ -554,6 +554,20 @@ struct scsi_da_rw_recovery_page {
u_int8_t recovery_time_limit[2];
};
+struct scsi_da_verify_recovery_page {
+ u_int8_t page_code;
+#define SMS_VERIFY_ERROR_RECOVERY_PAGE 0x07
+ u_int8_t page_length;
+ u_int8_t byte3;
+#define SMS_VER_EER 0x08
+#define SMS_VER_PER 0x04
+#define SMS_VER_DTE 0x02
+#define SMS_VER_DCR 0x01
+ u_int8_t read_retry_count;
+ u_int8_t reserved[6];
+ u_int8_t recovery_time_limit[2];
+};
+
__BEGIN_DECLS
/*
* XXX These are only left out of the kernel build to silence warnings. If,
OpenPOWER on IntegriCloud