2828 */
2929
3030#define SWITCHTEC_LIB_CORE
31+ #define SWITCHTEC_LTSSM_MAX_LOGS 61
3132
3233#include "switchtec_priv.h"
3334#include "switchtec/diag.h"
@@ -906,17 +907,183 @@ int switchtec_diag_refclk_ctl(struct switchtec_dev *dev, int stack_id, bool en)
906907 return switchtec_cmd (dev , MRPC_REFCLK_S , & cmd , sizeof (cmd ), NULL , 0 );
907908}
908909
910+ static void switchtec_diag_ltssm_set_log_data (struct switchtec_diag_ltssm_log
911+ * log_data ,
912+ struct switchtec_diag_ltssm_log_dmp_out
913+ * log_dump_out_ptr ,
914+ int curr_idx , uint16_t num_of_logs )
915+ {
916+ uint32_t dw0 ;
917+ uint32_t timestamp ;
918+
919+ int major ;
920+ int minor ;
921+ int rate ;
922+
923+ for (int j = 0 ; j < num_of_logs ; j ++ ) {
924+ dw0 = log_dump_out_ptr [j ].dw0 ;
925+ timestamp = log_dump_out_ptr [j ].ram_timestamp ;
926+
927+ rate = (dw0 >> 13 ) & 0x7 ;
928+ major = (dw0 >> 7 ) & 0x3f ;
929+ minor = (dw0 >> 3 ) & 0xf ;
930+
931+ log_data [curr_idx + j ].timestamp = timestamp ;
932+ log_data [curr_idx + j ].link_rate = switchtec_gen_transfers [rate + 1 ];
933+ log_data [curr_idx + j ].link_state = major | (minor << 8 );
934+ }
935+ }
936+
909937/**
910- * @brief Get the LTSSM log of a port on a switchtec device
938+ * @brief Get the LTSSM log of a port on a gen5 switchtec device
911939 * @param[in] dev Switchtec device handle
912940 * @param[in] port Switchtec Port
913941 * @param[inout] log_count number of log entries
914942 * @param[out] log A pointer to an array containing the log
915943 *
916944 */
917- int switchtec_diag_ltssm_log (struct switchtec_dev * dev ,
918- int port , int * log_count ,
919- struct switchtec_diag_ltssm_log * log_data )
945+ static int switchtec_diag_ltssm_log_gen5 (struct switchtec_dev * dev ,
946+ int port , int * log_count ,
947+ struct switchtec_diag_ltssm_log * log_data )
948+ {
949+ struct {
950+ uint8_t sub_cmd ;
951+ uint8_t port ;
952+ uint8_t freeze ;
953+ uint8_t unused ;
954+ } ltssm_freeze ;
955+
956+ struct {
957+ uint8_t sub_cmd ;
958+ uint8_t port ;
959+ } status ;
960+
961+ struct {
962+ uint16_t log_count ;
963+ uint16_t w0_trigger_count ;
964+ uint16_t w1_trigger_count ;
965+ } status_output ;
966+
967+ struct {
968+ uint8_t sub_cmd ;
969+ uint8_t port ;
970+ uint16_t log_index ;
971+ uint16_t no_of_logs ;
972+ } log_dump ;
973+
974+ uint8_t log_buffer [1024 ];
975+
976+ struct switchtec_diag_ltssm_log_dmp_out * log_dump_out_ptr = NULL ;
977+
978+ int ret ;
979+ int log_dmp_size = sizeof (struct switchtec_diag_ltssm_log_dmp_out );
980+
981+ /* freeze logs */
982+ ltssm_freeze .sub_cmd = MRPC_LTMON_FREEZE ;
983+ ltssm_freeze .port = port ;
984+ ltssm_freeze .freeze = 1 ;
985+
986+ ret = switchtec_cmd (dev , MRPC_DIAG_PORT_LTSSM_LOG , & ltssm_freeze ,
987+ sizeof (ltssm_freeze ), NULL , 0 );
988+ if (ret )
989+ return ret ;
990+
991+ /* get number of entries */
992+ status .sub_cmd = MRPC_LTMON_GET_STATUS_GEN5 ;
993+ status .port = port ;
994+ ret = switchtec_cmd (dev , MRPC_DIAG_PORT_LTSSM_LOG , & status ,
995+ sizeof (status ), & status_output ,
996+ sizeof (status_output ));
997+ if (ret )
998+ return ret ;
999+
1000+ * log_count = status_output .log_count ;
1001+
1002+ /* get log data */
1003+ log_dump .sub_cmd = MRPC_LTMON_LOG_DUMP_GEN5 ;
1004+ log_dump .port = port ;
1005+ log_dump .log_index = 0 ;
1006+ log_dump .no_of_logs = * log_count ;
1007+
1008+ if (log_dump .no_of_logs <= SWITCHTEC_LTSSM_MAX_LOGS ) {
1009+ /* Single buffer log case */
1010+ ret = switchtec_cmd (dev , MRPC_DIAG_PORT_LTSSM_LOG , & log_dump ,
1011+ sizeof (log_dump ), & log_buffer [0 ],
1012+ log_dump .no_of_logs * log_dmp_size + 4 );
1013+ if (ret )
1014+ return ret ;
1015+ log_dump_out_ptr =
1016+ (struct switchtec_diag_ltssm_log_dmp_out * )
1017+ & (log_buffer [4 ]);
1018+
1019+ switchtec_diag_ltssm_set_log_data (log_data ,
1020+ log_dump_out_ptr ,
1021+ 0 , log_dump .no_of_logs );
1022+ } else {
1023+ /* Multiple buffer log case */
1024+ int buff_count = log_dump .no_of_logs / SWITCHTEC_LTSSM_MAX_LOGS ;
1025+ int curr_idx = 0 ;
1026+ int buffer_size = SWITCHTEC_LTSSM_MAX_LOGS * log_dmp_size + 4 ;
1027+
1028+ for (int i = 0 ; i < buff_count ; i ++ ) {
1029+ log_dump .no_of_logs = SWITCHTEC_LTSSM_MAX_LOGS ;
1030+ ret = switchtec_cmd (dev , MRPC_DIAG_PORT_LTSSM_LOG ,
1031+ & log_dump , sizeof (log_dump ),
1032+ & log_buffer [0 ], buffer_size );
1033+ if (ret )
1034+ return ret ;
1035+ log_dump_out_ptr =
1036+ (struct switchtec_diag_ltssm_log_dmp_out * )
1037+ & (log_buffer [4 ]);
1038+
1039+ switchtec_diag_ltssm_set_log_data (log_data ,
1040+ log_dump_out_ptr ,
1041+ curr_idx ,
1042+ log_dump .no_of_logs );
1043+ curr_idx += SWITCHTEC_LTSSM_MAX_LOGS ;
1044+ log_dump .log_index = curr_idx ;
1045+ }
1046+ if (* log_count % SWITCHTEC_LTSSM_MAX_LOGS ) {
1047+ log_dump .no_of_logs = * log_count - curr_idx ;
1048+ buffer_size = log_dump .no_of_logs * log_dmp_size + 4 ;
1049+ ret = switchtec_cmd (dev , MRPC_DIAG_PORT_LTSSM_LOG ,
1050+ & log_dump , sizeof (log_dump ),
1051+ & log_buffer [0 ], buffer_size );
1052+ if (ret )
1053+ return ret ;
1054+ log_dump_out_ptr =
1055+ (struct switchtec_diag_ltssm_log_dmp_out * )
1056+ & (log_buffer [4 ]);
1057+
1058+ switchtec_diag_ltssm_set_log_data (log_data ,
1059+ log_dump_out_ptr ,
1060+ curr_idx ,
1061+ log_dump .no_of_logs );
1062+ }
1063+ }
1064+
1065+ /* unfreeze logs */
1066+ ltssm_freeze .sub_cmd = MRPC_LTMON_FREEZE ;
1067+ ltssm_freeze .port = port ;
1068+ ltssm_freeze .freeze = 0 ;
1069+
1070+ ret = switchtec_cmd (dev , MRPC_DIAG_PORT_LTSSM_LOG , & ltssm_freeze ,
1071+ sizeof (ltssm_freeze ), NULL , 0 );
1072+
1073+ return ret ;
1074+ }
1075+
1076+ /**
1077+ * @brief Get the LTSSM log of a port on a gen4 switchtec device
1078+ * @param[in] dev Switchtec device handle
1079+ * @param[in] port Switchtec Port
1080+ * @param[inout] log_count number of log entries
1081+ * @param[out] log A pointer to an array containing the log
1082+ *
1083+ */
1084+ static int switchtec_diag_ltssm_log_gen4 (struct switchtec_dev * dev ,
1085+ int port , int * log_count ,
1086+ struct switchtec_diag_ltssm_log * log_data )
9201087{
9211088 struct {
9221089 uint8_t sub_cmd ;
@@ -955,7 +1122,7 @@ int switchtec_diag_ltssm_log(struct switchtec_dev *dev,
9551122 int i ;
9561123
9571124 /* freeze logs */
958- ltssm_freeze .sub_cmd = 14 ;
1125+ ltssm_freeze .sub_cmd = MRPC_LTMON_FREEZE ;
9591126 ltssm_freeze .port = port ;
9601127 ltssm_freeze .freeze = 1 ;
9611128
@@ -965,7 +1132,7 @@ int switchtec_diag_ltssm_log(struct switchtec_dev *dev,
9651132 return ret ;
9661133
9671134 /* get number of entries */
968- status .sub_cmd = 13 ;
1135+ status .sub_cmd = MRPC_LTMON_GET_STATUS_GEN4 ;
9691136 status .port = port ;
9701137 ret = switchtec_cmd (dev , MRPC_DIAG_PORT_LTSSM_LOG , & status ,
9711138 sizeof (status ), & status_output ,
@@ -977,7 +1144,7 @@ int switchtec_diag_ltssm_log(struct switchtec_dev *dev,
9771144 * log_count = status_output .log_num ;
9781145
9791146 /* get log data */
980- log_dump .sub_cmd = 15 ;
1147+ log_dump .sub_cmd = MRPC_LTMON_LOG_DUMP_GEN4 ;
9811148 log_dump .port = port ;
9821149 log_dump .log_index = 0 ;
9831150 log_dump .no_of_logs = * log_count ;
@@ -1017,7 +1184,7 @@ int switchtec_diag_ltssm_log(struct switchtec_dev *dev,
10171184 }
10181185
10191186 /* unfreeze logs */
1020- ltssm_freeze .sub_cmd = 14 ;
1187+ ltssm_freeze .sub_cmd = MRPC_LTMON_FREEZE ;
10211188 ltssm_freeze .port = port ;
10221189 ltssm_freeze .freeze = 0 ;
10231190
@@ -1027,4 +1194,24 @@ int switchtec_diag_ltssm_log(struct switchtec_dev *dev,
10271194 return ret ;
10281195}
10291196
1197+ /**
1198+ * @brief Determine the generation and call the related LTSSM log func
1199+ * @param[in] dev Switchtec device handle
1200+ * @param[in] port Switchtec Port
1201+ * @param[inout] log_count number of log entries
1202+ * @param[out] log A pointer to an array containing the log
1203+ *
1204+ */
1205+ int switchtec_diag_ltssm_log (struct switchtec_dev * dev ,
1206+ int port , int * log_count ,
1207+ struct switchtec_diag_ltssm_log * log_data )
1208+ {
1209+ int ret ;
1210+ if (switchtec_is_gen5 (dev ))
1211+ ret = switchtec_diag_ltssm_log_gen5 (dev , port , log_count , log_data );
1212+ else
1213+ ret = switchtec_diag_ltssm_log_gen4 (dev , port , log_count , log_data );
1214+ return ret ;
1215+ }
1216+
10301217/**@}*/
0 commit comments