From owner-svn-src-stable-10@freebsd.org Thu Jan 5 11:23:57 2017 Return-Path: Delivered-To: svn-src-stable-10@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 8BB90C9F8CC; Thu, 5 Jan 2017 11:23:57 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 375FA1DB4; Thu, 5 Jan 2017 11:23:57 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v05BNu1o048726; Thu, 5 Jan 2017 11:23:56 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v05BNtgI048720; Thu, 5 Jan 2017 11:23:55 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201701051123.v05BNtgI048720@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Thu, 5 Jan 2017 11:23:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r311403 - in stable/10/sys/cam: ctl scsi X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Jan 2017 11:23:57 -0000 Author: mav Date: Thu Jan 5 11:23:55 2017 New Revision: 311403 URL: https://svnweb.freebsd.org/changeset/base/311403 Log: MFC r310257: Improve support for informational exceptions. While CTL still has no real events to report in this way (like SMART), it is possible to trigger false event by manually setting TEST bit in Informational Exceptions Control mode page, that can be useful for initiator testing. This code supports all flavours of IE reporting: UNIT ATTENTION, RECOVERED ERROR and NO SENSE sense keys, REQUEST SENSE command and Informational Exceptions log page. Modified: stable/10/sys/cam/ctl/ctl.c stable/10/sys/cam/ctl/ctl.h stable/10/sys/cam/ctl/ctl_error.c stable/10/sys/cam/ctl/ctl_private.h stable/10/sys/cam/scsi/scsi_all.h stable/10/sys/cam/scsi/scsi_da.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/cam/ctl/ctl.c ============================================================================== --- stable/10/sys/cam/ctl/ctl.c Thu Jan 5 11:20:31 2017 (r311402) +++ stable/10/sys/cam/ctl/ctl.c Thu Jan 5 11:23:55 2017 (r311403) @@ -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_ 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 /*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_pag 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->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_soft 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_scsi 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_scsi 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_scs sizeof(struct scsi_log_param_header); scsi_ulto4b(3, data->ti.exponent); scsi_ulto4b(1, data->ti.integer); + return (0); +} - page_index->page_len = sizeof(*data); +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; + + 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 *cts 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 *cts 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; Modified: stable/10/sys/cam/ctl/ctl.h ============================================================================== --- stable/10/sys/cam/ctl/ctl.h Thu Jan 5 11:20:31 2017 (r311402) +++ stable/10/sys/cam/ctl/ctl.h Thu Jan 5 11:23:55 2017 (r311403) @@ -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 fir 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); Modified: stable/10/sys/cam/ctl/ctl_error.c ============================================================================== --- stable/10/sys/cam/ctl/ctl_error.c Thu Jan 5 11:20:31 2017 (r311402) +++ stable/10/sys/cam/ctl/ctl_error.c Thu Jan 5 11:23:55 2017 (r311403) @@ -84,7 +84,8 @@ ctl_set_sense_data_va(struct scsi_sense_ * 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_ *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); } Modified: stable/10/sys/cam/ctl/ctl_private.h ============================================================================== --- stable/10/sys/cam/ctl/ctl_private.h Thu Jan 5 11:20:31 2017 (r311402) +++ stable/10/sys/cam/ctl/ctl_private.h Thu Jan 5 11:23:55 2017 (r311403) @@ -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_pa 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_p 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; Modified: stable/10/sys/cam/scsi/scsi_all.h ============================================================================== --- stable/10/sys/cam/scsi/scsi_all.h Thu Jan 5 11:20:31 2017 (r311402) +++ stable/10/sys/cam/scsi/scsi_all.h Thu Jan 5 11:23:55 2017 (r311403) @@ -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]; }; Modified: stable/10/sys/cam/scsi/scsi_da.h ============================================================================== --- stable/10/sys/cam/scsi/scsi_da.h Thu Jan 5 11:20:31 2017 (r311402) +++ stable/10/sys/cam/scsi/scsi_da.h Thu Jan 5 11:23:55 2017 (r311403) @@ -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,