Print this page
8074 need to add FMA event for SSD wearout

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/fm/libdiskstatus/common/ds_scsi.c
          +++ new/usr/src/lib/fm/libdiskstatus/common/ds_scsi.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
       24 + * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  24   25   */
  25   26  
  26      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  27      -
  28   27  #include <assert.h>
  29   28  #include <errno.h>
  30   29  #include <libdiskstatus.h>
  31   30  #include <limits.h>
  32   31  #include <stdlib.h>
  33   32  #include <strings.h>
  34   33  #include <sys/fm/io/scsi.h>
  35   34  
  36   35  #include "ds_scsi.h"
  37   36  #include "ds_scsi_sim.h"
↓ open down ↓ 32 lines elided ↑ open up ↑
  70   69          logpage_validation_fn_t ve_validate;
  71   70          logpage_analyze_fn_t    ve_analyze;
  72   71  } logpage_validation_entry_t;
  73   72  
  74   73  static int logpage_ie_verify(ds_scsi_info_t *,
  75   74      scsi_log_parameter_header_t *, int, nvlist_t *);
  76   75  static int logpage_temp_verify(ds_scsi_info_t *,
  77   76      scsi_log_parameter_header_t *, int, nvlist_t *);
  78   77  static int logpage_selftest_verify(ds_scsi_info_t *,
  79   78      scsi_log_parameter_header_t *, int, nvlist_t *);
       79 +static int logpage_ssm_verify(ds_scsi_info_t *,
       80 +    scsi_log_parameter_header_t *, int, nvlist_t *);
  80   81  
  81   82  static int logpage_ie_analyze(ds_scsi_info_t *,
  82   83      scsi_log_parameter_header_t *, int);
  83   84  static int logpage_temp_analyze(ds_scsi_info_t *,
  84   85      scsi_log_parameter_header_t *, int);
  85   86  static int logpage_selftest_analyze(ds_scsi_info_t *,
  86   87      scsi_log_parameter_header_t *, int);
       88 +static int logpage_ssm_analyze(ds_scsi_info_t *,
       89 +    scsi_log_parameter_header_t *, int);
  87   90  
  88   91  static struct logpage_validation_entry log_validation[] = {
  89   92          { LOGPAGE_IE,           LOGPAGE_SUPP_IE,
  90   93              "informational-exceptions",
  91   94              logpage_ie_verify,  logpage_ie_analyze },
  92   95          { LOGPAGE_TEMP,         LOGPAGE_SUPP_TEMP,
  93   96              "temperature",
  94   97              logpage_temp_verify, logpage_temp_analyze },
  95   98          { LOGPAGE_SELFTEST,     LOGPAGE_SUPP_SELFTEST,
  96   99              "self-test",
  97      -            logpage_selftest_verify, logpage_selftest_analyze }
      100 +            logpage_selftest_verify, logpage_selftest_analyze },
      101 +        { LOGPAGE_SSM,          LOGPAGE_SUPP_SSM,
      102 +            FM_EREPORT_SCSI_SSMWEAROUT,
      103 +            logpage_ssm_verify, logpage_ssm_analyze }
  98  104  };
  99  105  
 100  106  #define NLOG_VALIDATION (sizeof (log_validation) / sizeof (log_validation[0]))
 101  107  
 102  108  /*
 103  109   * Given an extended sense page, retrieves the sense key, as well as the
 104  110   * additional sense code information.
 105  111   */
 106  112  static void
 107  113  scsi_translate_error(struct scsi_extended_sense *rq, uint_t *skeyp,
↓ open down ↓ 642 lines elided ↑ open up ↑
 750  756  
 751  757          if (bad) {
 752  758                  sip->si_supp_log &= ~LOGPAGE_SUPP_SELFTEST;
 753  759                  dprintf("selftest logpage validation failed\n");
 754  760          }
 755  761  
 756  762          return (0);
 757  763  }
 758  764  
 759  765  /*
      766 + * Verify the contents of the Solid State Media (SSM) log page.
      767 + * As of SBC3r36 SSM log page contains one log parameter:
      768 + * "Percentage Used Endurance Indicator" which is mandatory.
      769 + * For the verification phase, we sanity check this parameter
      770 + * by making sure it's present and it's length is set to 0x04.
      771 + */
      772 +static int
      773 +logpage_ssm_verify(ds_scsi_info_t *sip,
      774 +    scsi_log_parameter_header_t *lphp, int log_length, nvlist_t *nvl)
      775 +{
      776 +        ushort_t param_code;
      777 +        int i, plen = 0;
      778 +
      779 +        for (i = 0; i < log_length; i += plen) {
      780 +                lphp = (scsi_log_parameter_header_t *)((char *)lphp + plen);
      781 +                param_code = BE_16(lphp->lph_param);
      782 +
      783 +                switch (param_code) {
      784 +                case LOGPARAM_PRCNT_USED:
      785 +                        if (nvlist_add_boolean_value(nvl,
      786 +                            FM_EREPORT_SCSI_SSMWEAROUT, B_TRUE) != 0)
      787 +                                return (scsi_set_errno(sip, EDS_NOMEM));
      788 +                        if (lphp->lph_length != LOGPARAM_PRCNT_USED_PARAM_LEN) {
      789 +                                if (nvlist_add_uint8(nvl,
      790 +                                    "invalid-length", lphp->lph_length) != 0)
      791 +                                        return (scsi_set_errno(sip, EDS_NOMEM));
      792 +
      793 +                                dprintf("solid state media logpage bad len\n");
      794 +                                break;
      795 +                        }
      796 +
      797 +                        /* verification succeded */
      798 +                        return (0);
      799 +                }
      800 +
      801 +                plen = lphp->lph_length +
      802 +                    sizeof (scsi_log_parameter_header_t);
      803 +        }
      804 +
      805 +        /* verification failed */
      806 +        sip->si_supp_log &= ~LOGPAGE_SUPP_SSM;
      807 +        return (0);
      808 +}
      809 +
      810 +/*
 760  811   * Load the current IE mode pages
 761  812   */
 762  813  static int
 763  814  load_ie_modepage(ds_scsi_info_t *sip)
 764  815  {
 765  816          struct scsi_ms_hdrs junk_hdrs;
 766  817          int result;
 767  818          uint_t skey, asc, ascq;
 768  819  
 769  820          if (!(sip->si_supp_mode & MODEPAGE_SUPP_IEC))
↓ open down ↓ 367 lines elided ↑ open up ↑
1137 1188                          }
1138 1189                  }
1139 1190  
1140 1191                  plen = lphp->lph_length +
1141 1192                      sizeof (scsi_log_parameter_header_t);
1142 1193          }
1143 1194  
1144 1195          return (0);
1145 1196  }
1146 1197  
     1198 +/*
     1199 + * Analyze the contents of the Solid State Media (SSM) log page's
     1200 + * "Percentage Used Endurance Indicator" log parameter.
     1201 + * We generate a fault if the percentage used is equal to or over
     1202 + * PRCNT_USED_FAULT_THRSH
     1203 + */
     1204 +static int
     1205 +logpage_ssm_analyze(ds_scsi_info_t *sip, scsi_log_parameter_header_t *lphp,
     1206 +    int log_length)
     1207 +{
     1208 +        uint16_t param_code;
     1209 +        scsi_ssm_log_param_t *ssm;
     1210 +        nvlist_t *nvl;
     1211 +        int i, plen = 0;
     1212 +
     1213 +        assert(sip->si_dsp->ds_overtemp == NULL);
     1214 +        if (nvlist_alloc(&sip->si_dsp->ds_overtemp, NV_UNIQUE_NAME, 0) != 0)
     1215 +                return (scsi_set_errno(sip, EDS_NOMEM));
     1216 +        nvl = sip->si_dsp->ds_overtemp;
     1217 +
     1218 +        for (i = 0; i < log_length; i += plen) {
     1219 +                lphp = (scsi_log_parameter_header_t *)((uint8_t *)lphp + plen);
     1220 +                param_code = BE_16(lphp->lph_param);
     1221 +                ssm = (scsi_ssm_log_param_t *)lphp;
     1222 +
     1223 +                switch (param_code) {
     1224 +                case LOGPARAM_PRCNT_USED:
     1225 +                        if (lphp->lph_length != LOGPARAM_PRCNT_USED_PARAM_LEN)
     1226 +                                break;
     1227 +
     1228 +                        if ((nvlist_add_uint8(nvl,
     1229 +                            FM_EREPORT_PAYLOAD_SCSI_CURSSMWEAROUT,
     1230 +                            ssm->ssm_prcnt_used) != 0) ||
     1231 +                            (nvlist_add_uint8(nvl,
     1232 +                            FM_EREPORT_PAYLOAD_SCSI_THRSHSSMWEAROUT,
     1233 +                            PRCNT_USED_FAULT_THRSH) != 0))
     1234 +                                return (scsi_set_errno(sip, EDS_NOMEM));
     1235 +
     1236 +                        if (ssm->ssm_prcnt_used >= PRCNT_USED_FAULT_THRSH)
     1237 +                                sip->si_dsp->ds_faults |= DS_FAULT_SSMWEAROUT;
     1238 +
     1239 +                        return (0);
     1240 +                }
     1241 +
     1242 +                plen = lphp->lph_length +
     1243 +                    sizeof (scsi_log_parameter_header_t);
     1244 +        }
     1245 +
     1246 +        /*
     1247 +         * If we got this far we didn't see LOGPARAM_PRCNT_USED
     1248 +         * which is strange since we verified that it's there
     1249 +         */
     1250 +        dprintf("solid state media logpage analyze failed\n");
     1251 +#if DEBUG
     1252 +        abort();
     1253 +#endif
     1254 +        return (scsi_set_errno(sip, EDS_NOT_SUPPORTED));
     1255 +}
     1256 +
1147 1257  /*
1148 1258   * Analyze the IE mode sense page explicitly.  This is only needed if the IE log
1149 1259   * page is not supported.
1150 1260   */
1151 1261  static int
1152 1262  analyze_ie_sense(ds_scsi_info_t *sip)
1153 1263  {
1154 1264          uint_t skey, asc, ascq;
1155 1265          nvlist_t *nvl;
1156 1266  
↓ open down ↓ 196 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX