@@ -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,9 +1243,11 @@ 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 ;
@@ -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,7 +1311,22 @@ 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+ break ;
1329+ }
13081330
13091331 while (offset != full_size ) {
13101332 args .log = telemetry_log ;
@@ -1431,7 +1453,7 @@ int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options)
14311453
14321454 if (options -> telemetry_log ) {
14331455 if (strstr ((const char * )options -> telemetry_log , "bin" )) {
1434- // Read the data from the telemetry binary file
1456+ /* Read the data from the telemetry binary file */
14351457 ptelemetry_buffer =
14361458 read_binary_file (NULL , (const char * )options -> telemetry_log ,
14371459 & telemetry_buffer_size , 1 );
@@ -1452,7 +1474,7 @@ int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options)
14521474 }
14531475
14541476 if (options -> string_log ) {
1455- // Read the data from the string binary file
1477+ /* Read the data from the string binary file */
14561478 if (strstr ((const char * )options -> string_log , "bin" )) {
14571479 pstring_buffer = read_binary_file (NULL , (const char * )options -> string_log ,
14581480 & string_buffer_size , 1 );
@@ -1483,11 +1505,15 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
14831505 const char * telemetry_log = "Telemetry log binary;\n 'host.bin' or 'controller.bin'" ;
14841506 const char * string_log = "String log binary; 'C9.bin'" ;
14851507 const char * output_file = "Output file name with path;\n"
1486- "e.g. '-o ./path/name'\n'-o ./path1/path2/';\n"
1508+ "e.g. '-f ./path/name'\n'-f ./path1/path2/';\n"
14871509 "If requested path does not exist, the directory will be newly created." ;
14881510 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" ;
1511+ const char * data_area = "Telemetry Data Area; 1, 2, 3, or 4;\n"
1512+ "e.g. '-a 1 for Data Area 1.'\n"
1513+ "e.g. '-a 2 for Data Areas 1 and 2.'\n"
1514+ "e.g. '-a 3 for Data Areas 1, 2, and 3.'\n"
1515+ "e.g. '-a 4 for Data Areas 1, 2, 3, and 4.';\n" ;
1516+
14911517 const char * telemetry_type = "Telemetry Type; 'host', 'host0', 'host1' or 'controller'" ;
14921518
14931519 struct nvme_dev * dev ;
@@ -1500,12 +1526,16 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15001526 struct ocp_telemetry_parse_options opt ;
15011527 int tele_type = 0 ;
15021528 int tele_area = 0 ;
1529+ char file_path_telemetry [PATH_MAX ], file_path_string [PATH_MAX ];
1530+ const char * string_suffix = "string.bin" ;
1531+ const char * tele_log_suffix = "telemetry.bin" ;
1532+ bool host_behavior_changed = false;
15031533
15041534 OPT_ARGS (opts ) = {
15051535 OPT_STR ("telemetry-log" , 'l' , & opt .telemetry_log , telemetry_log ),
15061536 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 ),
1537+ OPT_FILE ("output-file" , 'f ' , & opt .output_file , output_file ),
1538+ OPT_FMT ("output-format" , 'o ' , & opt .output_format , output_format ),
15091539 OPT_INT ("data-area" , 'a' , & opt .data_area , data_area ),
15101540 OPT_STR ("telemetry-type" , 't' , & opt .telemetry_type , telemetry_type ),
15111541 OPT_END ()
@@ -1536,11 +1566,15 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15361566
15371567 is_support_telemetry_controller = ((ctrl .lpa & 0x8 ) >> 3 );
15381568
1569+ if (opt .output_file == NULL )
1570+ opt .output_file = DEFAULT_TELEMETRY_LOG ;
1571+
15391572 if (!opt .data_area ) {
15401573 nvme_show_result ("Missing data-area. Using default data area 1.\n" );
15411574 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" );
1575+ } else if (opt .data_area != 1 && opt .data_area != 2 &&
1576+ opt .data_area != 3 && opt .data_area != 4 ) {
1577+ nvme_show_result ("Invalid data-area specified. Please specify 1, 2, 3, or 4.\n" );
15441578 goto out ;
15451579 }
15461580
@@ -1568,25 +1602,55 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15681602
15691603 if (!opt .telemetry_log ) {
15701604 nvme_show_result ("\nMissing telemetry-log. Fetching from drive...\n" );
1571- err = get_telemetry_log_page_data (dev , tele_type );//Pull Telemetry log
1605+
1606+ if (tele_area == 4 ) {
1607+ if (!(ctrl .lpa & 0x40 )) {
1608+ nvme_show_error ("Telemetry data area 4 not supported by device.\n" );
1609+ goto out ;
1610+ }
1611+
1612+ err = nvme_set_etdas (dev_fd (dev ), & host_behavior_changed );
1613+ if (err ) {
1614+ fprintf (stderr , "%s: Failed to set ETDAS bit\n" , __func__ );
1615+ return err ;
1616+ }
1617+ }
1618+
1619+ /* Pull the Telemetry log */
1620+ sprintf (file_path_telemetry , "%s-%s" , opt .output_file , tele_log_suffix );
1621+ err = get_telemetry_log_page_data (dev ,
1622+ tele_type ,
1623+ tele_area ,
1624+ (const char * )file_path_telemetry );
15721625 if (err ) {
15731626 nvme_show_error ("Failed to fetch telemetry-log from the drive.\n" );
15741627 goto out ;
15751628 }
15761629 nvme_show_result ("telemetry.bin generated. Proceeding with next steps.\n" );
1577- opt .telemetry_log = DEFAULT_TELEMETRY_BIN ;
1630+ opt .telemetry_log = file_path_telemetry ;
1631+
1632+ if (host_behavior_changed ) {
1633+ host_behavior_changed = false;
1634+ err = nvme_clear_etdas (dev_fd (dev ), & host_behavior_changed );
1635+ if (err ) {
1636+ /* Continue on if this fails, it's not a fatal condition */
1637+ nvme_show_error ("Failed to clear ETDAS bit.\n" );
1638+ }
1639+ }
15781640 }
15791641
15801642 if (!opt .string_log ) {
15811643 nvme_show_result ("Missing string-log. Fetching from drive...\n" );
1644+
15821645 /* Pull String log */
1583- err = get_c9_log_page_data (dev , 0 , 1 , (const char * )opt .output_file );
1646+ sprintf (file_path_string , "%s-%s" , opt .output_file , string_suffix );
1647+ err = get_c9_log_page_data (dev , 0 , 1 , (const char * )file_path_string );
15841648 if (err ) {
15851649 nvme_show_error ("Failed to fetch string-log from the drive.\n" );
15861650 goto out ;
15871651 }
15881652 nvme_show_result ("string.bin generated. Proceeding with next steps.\n" );
1589- opt .string_log = DEFAULT_STRING_BIN ;
1653+ opt .string_log = file_path_string ;
15901654 }
15911655
15921656 if (!opt .output_format ) {
@@ -1597,6 +1661,7 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15971661 switch (tele_type ) {
15981662 case TELEMETRY_TYPE_HOST :
15991663 printf ("Extracting Telemetry Host Dump (Data Area %d)...\n" , tele_area );
1664+
16001665 err = parse_ocp_telemetry_log (& opt );
16011666 if (err )
16021667 nvme_show_result ("Status:(%x)\n" , err );
@@ -2634,7 +2699,7 @@ static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *c
26342699 return ret ;
26352700
26362701 if (cfg .output_file != NULL )
2637- sprintf (file_path , "%s%s" , cfg .output_file , string_suffix );
2702+ sprintf (file_path , "%s- %s" , cfg .output_file , string_suffix );
26382703 else
26392704 sprintf (file_path , "%s" , DEFAULT_STRING_BIN );
26402705
0 commit comments