@@ -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,25 @@ 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+ while (offset < full_size ) {
13101333 args .log = telemetry_log ;
13111334 args .lpo = offset ;
13121335 args .lsp = NVME_LOG_LSP_NONE ;
@@ -1431,7 +1454,7 @@ int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options)
14311454
14321455 if (options -> telemetry_log ) {
14331456 if (strstr ((const char * )options -> telemetry_log , "bin" )) {
1434- // Read the data from the telemetry binary file
1457+ /* Read the data from the telemetry binary file */
14351458 ptelemetry_buffer =
14361459 read_binary_file (NULL , (const char * )options -> telemetry_log ,
14371460 & telemetry_buffer_size , 1 );
@@ -1452,7 +1475,7 @@ int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options)
14521475 }
14531476
14541477 if (options -> string_log ) {
1455- // Read the data from the string binary file
1478+ /* Read the data from the string binary file */
14561479 if (strstr ((const char * )options -> string_log , "bin" )) {
14571480 pstring_buffer = read_binary_file (NULL , (const char * )options -> string_log ,
14581481 & string_buffer_size , 1 );
@@ -1483,11 +1506,15 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
14831506 const char * telemetry_log = "Telemetry log binary;\n 'host.bin' or 'controller.bin'" ;
14841507 const char * string_log = "String log binary; 'C9.bin'" ;
14851508 const char * output_file = "Output file name with path;\n"
1486- "e.g. '-o ./path/name'\n'-o ./path1/path2/';\n"
1509+ "e.g. '-f ./path/name'\n'-f ./path1/path2/';\n"
14871510 "If requested path does not exist, the directory will be newly created." ;
14881511 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" ;
1512+ const char * data_area = "Telemetry Data Area; 1, 2, 3, or 4;\n"
1513+ "e.g. '-a 1 for Data Area 1.'\n"
1514+ "e.g. '-a 2 for Data Areas 1 and 2.'\n"
1515+ "e.g. '-a 3 for Data Areas 1, 2, and 3.'\n"
1516+ "e.g. '-a 4 for Data Areas 1, 2, 3, and 4.';\n" ;
1517+
14911518 const char * telemetry_type = "Telemetry Type; 'host', 'host0', 'host1' or 'controller'" ;
14921519
14931520 struct nvme_dev * dev ;
@@ -1500,12 +1527,16 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15001527 struct ocp_telemetry_parse_options opt ;
15011528 int tele_type = 0 ;
15021529 int tele_area = 0 ;
1530+ char file_path_telemetry [PATH_MAX ], file_path_string [PATH_MAX ];
1531+ const char * string_suffix = "string.bin" ;
1532+ const char * tele_log_suffix = "telemetry.bin" ;
1533+ bool host_behavior_changed = false;
15031534
15041535 OPT_ARGS (opts ) = {
15051536 OPT_STR ("telemetry-log" , 'l' , & opt .telemetry_log , telemetry_log ),
15061537 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 ),
1538+ OPT_FILE ("output-file" , 'f ' , & opt .output_file , output_file ),
1539+ OPT_FMT ("output-format" , 'o ' , & opt .output_format , output_format ),
15091540 OPT_INT ("data-area" , 'a' , & opt .data_area , data_area ),
15101541 OPT_STR ("telemetry-type" , 't' , & opt .telemetry_type , telemetry_type ),
15111542 OPT_END ()
@@ -1536,11 +1567,15 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15361567
15371568 is_support_telemetry_controller = ((ctrl .lpa & 0x8 ) >> 3 );
15381569
1570+ if (opt .output_file == NULL )
1571+ opt .output_file = DEFAULT_TELEMETRY_LOG ;
1572+
15391573 if (!opt .data_area ) {
15401574 nvme_show_result ("Missing data-area. Using default data area 1.\n" );
15411575 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" );
1576+ } else if (opt .data_area != 1 && opt .data_area != 2 &&
1577+ opt .data_area != 3 && opt .data_area != 4 ) {
1578+ nvme_show_result ("Invalid data-area specified. Please specify 1, 2, 3, or 4.\n" );
15441579 goto out ;
15451580 }
15461581
@@ -1568,25 +1603,55 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15681603
15691604 if (!opt .telemetry_log ) {
15701605 nvme_show_result ("\nMissing telemetry-log. Fetching from drive...\n" );
1571- err = get_telemetry_log_page_data (dev , tele_type );//Pull Telemetry log
1606+
1607+ if (tele_area == 4 ) {
1608+ if (!(ctrl .lpa & 0x40 )) {
1609+ nvme_show_error ("Telemetry data area 4 not supported by device.\n" );
1610+ goto out ;
1611+ }
1612+
1613+ err = nvme_set_etdas (dev_fd (dev ), & host_behavior_changed );
1614+ if (err ) {
1615+ fprintf (stderr , "%s: Failed to set ETDAS bit\n" , __func__ );
1616+ return err ;
1617+ }
1618+ }
1619+
1620+ /* Pull the Telemetry log */
1621+ sprintf (file_path_telemetry , "%s-%s" , opt .output_file , tele_log_suffix );
1622+ err = get_telemetry_log_page_data (dev ,
1623+ tele_type ,
1624+ tele_area ,
1625+ (const char * )file_path_telemetry );
15721626 if (err ) {
15731627 nvme_show_error ("Failed to fetch telemetry-log from the drive.\n" );
15741628 goto out ;
15751629 }
15761630 nvme_show_result ("telemetry.bin generated. Proceeding with next steps.\n" );
1577- opt .telemetry_log = DEFAULT_TELEMETRY_BIN ;
1631+ opt .telemetry_log = file_path_telemetry ;
1632+
1633+ if (host_behavior_changed ) {
1634+ host_behavior_changed = false;
1635+ err = nvme_clear_etdas (dev_fd (dev ), & host_behavior_changed );
1636+ if (err ) {
1637+ /* Continue on if this fails, it's not a fatal condition */
1638+ nvme_show_error ("Failed to clear ETDAS bit.\n" );
1639+ }
1640+ }
15781641 }
15791642
15801643 if (!opt .string_log ) {
15811644 nvme_show_result ("Missing string-log. Fetching from drive...\n" );
1645+
15821646 /* Pull String log */
1583- err = get_c9_log_page_data (dev , 0 , 1 , (const char * )opt .output_file );
1647+ sprintf (file_path_string , "%s-%s" , opt .output_file , string_suffix );
1648+ err = get_c9_log_page_data (dev , 0 , 1 , (const char * )file_path_string );
15841649 if (err ) {
15851650 nvme_show_error ("Failed to fetch string-log from the drive.\n" );
15861651 goto out ;
15871652 }
15881653 nvme_show_result ("string.bin generated. Proceeding with next steps.\n" );
1589- opt .string_log = DEFAULT_STRING_BIN ;
1654+ opt .string_log = file_path_string ;
15901655 }
15911656
15921657 if (!opt .output_format ) {
@@ -1597,6 +1662,7 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct
15971662 switch (tele_type ) {
15981663 case TELEMETRY_TYPE_HOST :
15991664 printf ("Extracting Telemetry Host Dump (Data Area %d)...\n" , tele_area );
1665+
16001666 err = parse_ocp_telemetry_log (& opt );
16011667 if (err )
16021668 nvme_show_result ("Status:(%x)\n" , err );
@@ -2634,7 +2700,7 @@ static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *c
26342700 return ret ;
26352701
26362702 if (cfg .output_file != NULL )
2637- sprintf (file_path , "%s%s" , cfg .output_file , string_suffix );
2703+ sprintf (file_path , "%s- %s" , cfg .output_file , string_suffix );
26382704 else
26392705 sprintf (file_path , "%s" , DEFAULT_STRING_BIN );
26402706
0 commit comments