@@ -2194,6 +2194,160 @@ static int aer_event_gen(int argc, char **argv)
21942194 return 0 ;
21952195}
21962196
2197+ #define CMD_DESC_LNKERR_INJECT "Inject a link error"
2198+
2199+ static int linkerr_inject (int argc , char * * argv )
2200+ {
2201+ int ret = 0 ;
2202+ uint32_t * dllp_data_dword = NULL ;
2203+ int num_dwords = 0 ;
2204+ static struct {
2205+ struct switchtec_dev * dev ;
2206+ int inject_dllp ;
2207+ int inject_dllp_crc ;
2208+ int inject_tlp_lcrc ;
2209+ int inject_tlp_seq ;
2210+ int inject_nack ;
2211+ int inject_cto ;
2212+ uint8_t enable ;
2213+ uint8_t count ;
2214+ uint16_t dllp_rate ;
2215+ uint16_t tlp_rate ;
2216+ uint16_t seq_num ;
2217+ char * dllp_data ;
2218+ int phy_port ;
2219+ } cfg = {};
2220+
2221+ const struct argconfig_options opts [] = {
2222+ DEVICE_OPTION ,
2223+ {"dllp" , 'd' , "" , CFG_NONE , & cfg .inject_dllp ,
2224+ no_argument , "Inject a DLLP" },
2225+ {"dllp-crc" , 'D' , "" , CFG_NONE , & cfg .inject_dllp_crc ,
2226+ no_argument , "Inject a DLLP CRC error" },
2227+ {"tlp-lcrc" , 'l' , "" , CFG_NONE , & cfg .inject_tlp_lcrc ,
2228+ no_argument , "Inject a TLP LCRC error" },
2229+ {"tlp-seq" , 's' , "" , CFG_NONE , & cfg .inject_tlp_seq ,
2230+ no_argument , "Inject a TLP Sequence Number error" },
2231+ {"nack" , 'n' , "" , CFG_NONE , & cfg .inject_nack , no_argument ,
2232+ "Inject an ACK to NACK error" },
2233+ {"cto" , 't' , "" , CFG_NONE , & cfg .inject_cto , no_argument ,
2234+ "Inject a TLP Credit Timeout" },
2235+ {"port" , 'p' , "" , CFG_NONNEGATIVE , & cfg .phy_port ,
2236+ required_argument , "physical port ID, default: port 0" },
2237+ {"enable" , 'e' , "" , CFG_NONNEGATIVE , & cfg .enable ,
2238+ required_argument , "enable DLLP CRC Error Injection or TLP LCRC Error Injection, default: 0" },
2239+ {"data" , 'i' , "" , CFG_STRING , & cfg .dllp_data , required_argument ,
2240+ "DLLP data to inject, a single dword in hex prefixed with \"0x\"" },
2241+ {"seq_num" , 'S' , "" , CFG_NONNEGATIVE , & cfg .seq_num ,
2242+ required_argument , "sequence number of ACK to be replaced by NACK (0-4095)" },
2243+ {"count" , 'c' , "" , CFG_NONNEGATIVE , & cfg .count ,
2244+ required_argument , "number of times to replace ACK with NACK (0-255)" },
2245+ {"dllp-crc-rate" , 'r' , "" , CFG_NONNEGATIVE , & cfg .dllp_rate ,
2246+ required_argument , "valid range (0-4096). errors are injected at intervals of rate x 256 x clk " },
2247+ {"tlp-lcrc-rate" , 'R' , "" , CFG_NONNEGATIVE , & cfg .tlp_rate ,
2248+ required_argument , "valid range (0-7). Ex. rate = 1 -> every other TLP has an error" },
2249+ {NULL }
2250+ };
2251+
2252+ argconfig_parse (argc , argv , CMD_DESC_LNKERR_INJECT , opts , & cfg ,
2253+ sizeof (cfg ));
2254+
2255+ uint8_t * ptr = (uint8_t * )& cfg + 5 ;
2256+ int total_en = 0 ;
2257+ for (size_t i = 0 ; i < 6 ; i ++ ) {
2258+ ptr += 3 ;
2259+ if (ptr [i ] == 1 )
2260+ total_en ++ ;
2261+ }
2262+ if (total_en > 1 ) {
2263+ fprintf (stderr , "Cannot enable more than one link error injection command at a time.\n" );
2264+ return -1 ;
2265+ }
2266+ if (total_en == 0 ) {
2267+ fprintf (stderr , "Must enable one link error injection command.\n" );
2268+ return -1 ;
2269+ }
2270+
2271+ if (cfg .enable && !(cfg .inject_dllp_crc || cfg .inject_tlp_lcrc ))
2272+ printf ("Ignoring -e enable flag, not valid for the currently selected command.\n" );
2273+ if (!cfg .inject_nack && cfg .count )
2274+ printf ("Ignoring -c flag, not valid for the currently selected command.\n" );
2275+ if (!cfg .inject_nack && cfg .seq_num )
2276+ printf ("Ignoring -S flag, not valid for the currently selected command.\n" );
2277+ if (!cfg .inject_tlp_lcrc && cfg .tlp_rate )
2278+ printf ("Ignoring -R flag, not valid for the currently selected command.\n" );
2279+ if (!cfg .inject_dllp_crc && cfg .dllp_rate )
2280+ printf ("Ignoring -r flag, not valid for the currently selected command.\n" );
2281+ if (!cfg .inject_dllp && cfg .dllp_data ) {
2282+ printf ("Ignoring -i flag, not valid for the currently selected command.\n" );
2283+ } else if (cfg .inject_dllp && cfg .dllp_data ) {
2284+ ret = convert_str_to_dwords (cfg .dllp_data , & dllp_data_dword ,
2285+ & num_dwords );
2286+ if (ret ) {
2287+ fprintf (stderr , "Error with DLLP data provided\n" );
2288+ return -1 ;
2289+ }
2290+ if (num_dwords == 0 ) {
2291+ fprintf (stderr , "Must provide a single valid DLLP data dword\n" );
2292+ free (dllp_data_dword );
2293+ return -1 ;
2294+ }
2295+ }
2296+
2297+ if (cfg .dllp_rate && cfg .tlp_rate ) {
2298+ fprintf (stderr , "Cannot enable both rate configurations.\n" );
2299+ return -1 ;
2300+ }
2301+
2302+ if (cfg .inject_dllp ) {
2303+ ret = switchtec_inject_err_dllp (cfg .dev , cfg .phy_port ,
2304+ cfg .dllp_data != NULL ? * dllp_data_dword : 0 );
2305+ free (dllp_data_dword );
2306+ }
2307+ if (cfg .inject_dllp_crc ) {
2308+ if (cfg .dllp_rate > 4096 ) {
2309+ fprintf (stderr , "DLLP CRC rate out of range. Valid range is 0-4095.\n" );
2310+ return -1 ;
2311+ }
2312+ ret = switchtec_inject_err_dllp_crc (cfg .dev , cfg .phy_port ,
2313+ cfg .enable , cfg .dllp_rate );
2314+ }
2315+ if (cfg .inject_tlp_lcrc ) {
2316+ if (cfg .tlp_rate > 7 ) {
2317+ fprintf (stderr , "TLP LCRC rate out of range. Valid range is 0-7.\n" );
2318+ return -1 ;
2319+ }
2320+ ret = switchtec_inject_err_tlp_lcrc (cfg .dev , cfg .phy_port ,
2321+ cfg .enable , cfg .tlp_rate );
2322+ if (ret )
2323+ return -1 ;
2324+ }
2325+ if (cfg .inject_tlp_seq )
2326+ ret = switchtec_inject_err_tlp_seq_num (cfg .dev , cfg .phy_port );
2327+ if (cfg .inject_nack ) {
2328+ if (cfg .seq_num > 4095 ) {
2329+ fprintf (stderr , "Sequence number out of range. Valid range is 0-4095).\n" );
2330+ return -1 ;
2331+ }
2332+ if (cfg .count > 255 ) {
2333+ fprintf (stderr , "Count out of range. Valid range is 0-255\n" );
2334+ return -1 ;
2335+ }
2336+ ret = switchtec_inject_err_ack_nack (cfg .dev , cfg .phy_port ,
2337+ cfg .seq_num , cfg .count );
2338+ }
2339+ if (cfg .inject_cto ) {
2340+ if (!switchtec_is_gen5 (cfg .dev )) {
2341+ fprintf (stderr , "Credit timeout error injection is only supported on Gen5.\n" );
2342+ return -1 ;
2343+ }
2344+ ret = switchtec_inject_err_cto (cfg .dev , cfg .phy_port );
2345+ }
2346+
2347+ switchtec_perror ("linkerr-inject" );
2348+ return ret ;
2349+ }
2350+
21972351static const struct cmd commands [] = {
21982352 CMD (crosshair , CMD_DESC_CROSS_HAIR ),
21992353 CMD (eye , CMD_DESC_EYE ),
@@ -2209,6 +2363,7 @@ static const struct cmd commands[] = {
22092363 CMD (ltssm_log , CMD_DESC_LTSSM_LOG ),
22102364 CMD (tlp_inject , CMD_TLP_INJECT ),
22112365 CMD (aer_event_gen , CMD_DESC_AER_EVENT_GEN ),
2366+ CMD (linkerr_inject , CMD_DESC_LNKERR_INJECT ),
22122367 {}
22132368};
22142369
0 commit comments