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,
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to