@@ -1221,6 +1221,12 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn,
12211221 size = le16_to_cpu (logheader -> DataArea3LastBlock ) -
12221222 le16_to_cpu (logheader -> DataArea2LastBlock );
12231223 break ;
1224+ case 4 :
1225+ offset = TELEMETRY_HEADER_SIZE +
1226+ (le16_to_cpu (logheader -> DataArea3LastBlock ) * TELEMETRY_BYTE_PER_BLOCK );
1227+ size = le16_to_cpu (logheader -> DataArea4LastBlock ) -
1228+ le16_to_cpu (logheader -> DataArea3LastBlock );
1229+ break ;
12241230 default :
12251231 break ;
12261232 }
@@ -1237,13 +1243,15 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn,
12371243 return err ;
12381244}
12391245
1240- static int get_telemetry_log_page_data (struct nvme_dev * dev , int tele_type )
1246+ static int get_telemetry_log_page_data (struct nvme_dev * dev ,
1247+ int tele_type ,
1248+ int tele_area ,
1249+ const char * output_file )
12411250{
1242- char file_path [PATH_MAX ];
12431251 void * telemetry_log ;
12441252 const size_t bs = 512 ;
12451253 struct nvme_telemetry_log * hdr ;
1246- size_t full_size , offset = bs ;
1254+ size_t full_size = 0 , offset = bs ;
12471255 int err , fd ;
12481256
12491257 if ((tele_type == TELEMETRY_TYPE_HOST_0 ) || (tele_type == TELEMETRY_TYPE_HOST_1 ))
@@ -1262,11 +1270,10 @@ static int get_telemetry_log_page_data(struct nvme_dev *dev, int tele_type)
12621270 }
12631271 memset (hdr , 0 , bs );
12641272
1265- sprintf (file_path , DEFAULT_TELEMETRY_BIN );
1266- fd = open (file_path , O_WRONLY | O_CREAT | O_TRUNC , 0666 );
1273+ fd = open (output_file , O_WRONLY | O_CREAT | O_TRUNC , 0666 );
12671274 if (fd < 0 ) {
12681275 fprintf (stderr , "Failed to open output file %s: %s!\n" ,
1269- file_path , strerror (errno ));
1276+ output_file , strerror (errno ));
12701277 err = fd ;
12711278 goto exit_status ;
12721279 }
@@ -1304,9 +1311,27 @@ static int get_telemetry_log_page_data(struct nvme_dev *dev, int tele_type)
13041311 goto close_fd ;
13051312 }
13061313
1307- full_size = (le16_to_cpu (hdr -> dalb3 ) * bs ) + offset ;
1314+ switch (tele_area ) {
1315+ case 1 :
1316+ full_size = (le16_to_cpu (hdr -> dalb1 ) * bs ) + offset ;
1317+ break ;
1318+ case 2 :
1319+ full_size = (le16_to_cpu (hdr -> dalb2 ) * bs ) + offset ;
1320+ break ;
1321+ case 3 :
1322+ full_size = (le16_to_cpu (hdr -> dalb3 ) * bs ) + offset ;
1323+ break ;
1324+ case 4 :
1325+ full_size = (le32_to_cpu (hdr -> dalb4 ) * bs ) + offset ;
1326+ break ;
1327+ default :
1328+ full_size = offset ;
1329+ break ;
1330+ }
13081331
1309- while (offset != full_size ) {
1332+ printf ("%s: full size = %lx\n" , __func__ , full_size );
1333+
1334+ while (offset < full_size ) {
13101335 args .log = telemetry_log ;
13111336 args .lpo = offset ;
13121337 args .lsp = NVME_LOG_LSP_NONE ;
@@ -1431,7 +1456,7 @@ int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options)
14311456
14321457 if (options -> telemetry_log ) {
14331458 if (strstr ((const char * )options -> telemetry_log , "bin" )) {
1434- // Read the data from the telemetry binary file
1459+ /* Read the data from the telemetry binary file */
14351460 ptelemetry_buffer =
14361461 read_binary_file (NULL , (const char * )options -> telemetry_log ,
14371462 & telemetry_buffer_size , 1 );
@@ -1452,7 +1477,7 @@ int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options)
14521477 }
14531478
14541479 if (options -> string_log ) {
1455- // Read the data from the string binary file
1480+ /* Read the data from the string binary file */
14561481 if (strstr ((const char * )options -> string_log , "bin" )) {
14571482 pstring_buffer = read_binary_file (NULL , (const char * )options -> string_log ,
14581483 & string_buffer_size , 1 );
@@ -1483,11 +1508,15 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
14831508 const char * telemetry_log = "Telemetry log binary;\n 'host.bin' or 'controller.bin'" ;
14841509 const char * string_log = "String log binary; 'C9.bin'" ;
14851510 const char * output_file = "Output file name with path;\n"
1486- "e.g. '-o ./path/name'\n'-o ./path1/path2/';\n"
1511+ "e.g. '-f ./path/name'\n'-f ./path1/path2/';\n"
14871512 "If requested path does not exist, the directory will be newly created." ;
14881513 const char * output_format = "output format normal|json" ;
1489- const char * data_area = "Telemetry Data Area; 1 or 2;\n"
1490- "e.g. '-a 1 for Data Area 1.'\n'-a 2 for Data Areas 1 and 2.';\n" ;
1514+ const char * data_area = "Telemetry Data Area; 1, 2, 3, or 4;\n"
1515+ "e.g. '-a 1 for Data Area 1.'\n"
1516+ "e.g. '-a 2 for Data Areas 1 and 2.'\n"
1517+ "e.g. '-a 3 for Data Areas 1, 2, and 3.'\n"
1518+ "e.g. '-a 4 for Data Areas 1, 2, 3, and 4.';\n" ;
1519+
14911520 const char * telemetry_type = "Telemetry Type; 'host', 'host0', 'host1' or 'controller'" ;
14921521
14931522 struct nvme_dev * dev ;
@@ -1500,12 +1529,16 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15001529 struct ocp_telemetry_parse_options opt ;
15011530 int tele_type = 0 ;
15021531 int tele_area = 0 ;
1532+ char file_path_telemetry [PATH_MAX ], file_path_string [PATH_MAX ];
1533+ const char * string_suffix = "string.bin" ;
1534+ const char * tele_log_suffix = "telemetry.bin" ;
1535+ bool host_behavior_changed = false;
15031536
15041537 OPT_ARGS (opts ) = {
15051538 OPT_STR ("telemetry-log" , 'l' , & opt .telemetry_log , telemetry_log ),
15061539 OPT_STR ("string-log" , 's' , & opt .string_log , string_log ),
1507- OPT_FILE ("output-file" , 'o ' , & opt .output_file , output_file ),
1508- OPT_FMT ("output-format" , 'f ' , & opt .output_format , output_format ),
1540+ OPT_FILE ("output-file" , 'f ' , & opt .output_file , output_file ),
1541+ OPT_FMT ("output-format" , 'o ' , & opt .output_format , output_format ),
15091542 OPT_INT ("data-area" , 'a' , & opt .data_area , data_area ),
15101543 OPT_STR ("telemetry-type" , 't' , & opt .telemetry_type , telemetry_type ),
15111544 OPT_END ()
@@ -1536,11 +1569,15 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15361569
15371570 is_support_telemetry_controller = ((ctrl .lpa & 0x8 ) >> 3 );
15381571
1572+ if (opt .output_file == NULL )
1573+ opt .output_file = DEFAULT_TELEMETRY_LOG ;
1574+
15391575 if (!opt .data_area ) {
15401576 nvme_show_result ("Missing data-area. Using default data area 1.\n" );
15411577 opt .data_area = DATA_AREA_1 ;//Default data area 1
1542- } else if (opt .data_area != 1 && opt .data_area != 2 ) {
1543- nvme_show_result ("Invalid data-area specified. Please specify 1 or 2.\n" );
1578+ } else if (opt .data_area != 1 && opt .data_area != 2 &&
1579+ opt .data_area != 3 && opt .data_area != 4 ) {
1580+ nvme_show_result ("Invalid data-area specified. Please specify 1, 2, 3, or 4.\n" );
15441581 goto out ;
15451582 }
15461583
@@ -1568,25 +1605,55 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15681605
15691606 if (!opt .telemetry_log ) {
15701607 nvme_show_result ("\nMissing telemetry-log. Fetching from drive...\n" );
1571- err = get_telemetry_log_page_data (dev , tele_type );//Pull Telemetry log
1608+
1609+ if (tele_area == 4 ) {
1610+ if (!(ctrl .lpa & 0x40 )) {
1611+ nvme_show_error ("Telemetry data area 4 not supported by device.\n" );
1612+ goto out ;
1613+ }
1614+
1615+ err = nvme_set_etdas (dev_fd (dev ), & host_behavior_changed );
1616+ if (err ) {
1617+ fprintf (stderr , "%s: Failed to set ETDAS bit\n" , __func__ );
1618+ return err ;
1619+ }
1620+ }
1621+
1622+ /* Pull the Telemetry log */
1623+ sprintf (file_path_telemetry , "%s-%s" , opt .output_file , tele_log_suffix );
1624+ err = get_telemetry_log_page_data (dev ,
1625+ tele_type ,
1626+ tele_area ,
1627+ (const char * )file_path_telemetry );
15721628 if (err ) {
15731629 nvme_show_error ("Failed to fetch telemetry-log from the drive.\n" );
15741630 goto out ;
15751631 }
15761632 nvme_show_result ("telemetry.bin generated. Proceeding with next steps.\n" );
1577- opt .telemetry_log = DEFAULT_TELEMETRY_BIN ;
1633+ opt .telemetry_log = file_path_telemetry ;
1634+
1635+ if (host_behavior_changed ) {
1636+ host_behavior_changed = false;
1637+ err = nvme_clear_etdas (dev_fd (dev ), & host_behavior_changed );
1638+ if (err ) {
1639+ /* Continue on if this fails, it's not a fatal condition */
1640+ nvme_show_error ("Failed to clear ETDAS bit.\n" );
1641+ }
1642+ }
15781643 }
15791644
15801645 if (!opt .string_log ) {
15811646 nvme_show_result ("Missing string-log. Fetching from drive...\n" );
1647+
15821648 /* Pull String log */
1583- err = get_c9_log_page_data (dev , 0 , 1 , (const char * )opt .output_file );
1649+ sprintf (file_path_string , "%s-%s" , opt .output_file , string_suffix );
1650+ err = get_c9_log_page_data (dev , 0 , 1 , (const char * )file_path_string );
15841651 if (err ) {
15851652 nvme_show_error ("Failed to fetch string-log from the drive.\n" );
15861653 goto out ;
15871654 }
15881655 nvme_show_result ("string.bin generated. Proceeding with next steps.\n" );
1589- opt .string_log = DEFAULT_STRING_BIN ;
1656+ opt .string_log = file_path_string ;
15901657 }
15911658
15921659 if (!opt .output_format ) {
@@ -1597,6 +1664,7 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15971664 switch (tele_type ) {
15981665 case TELEMETRY_TYPE_HOST :
15991666 printf ("Extracting Telemetry Host Dump (Data Area %d)...\n" , tele_area );
1667+
16001668 err = parse_ocp_telemetry_log (& opt );
16011669 if (err )
16021670 nvme_show_result ("Status:(%x)\n" , err );
@@ -2634,7 +2702,7 @@ static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *c
26342702 return ret ;
26352703
26362704 if (cfg .output_file != NULL )
2637- sprintf (file_path , "%s%s" , cfg .output_file , string_suffix );
2705+ sprintf (file_path , "%s- %s" , cfg .output_file , string_suffix );
26382706 else
26392707 sprintf (file_path , "%s" , DEFAULT_STRING_BIN );
26402708
0 commit comments