Skip to content

Commit f4fe1db

Browse files
committed
Added tlp injection command
TLP injection command added to use the defined MRPC interface to send a raw TLP to a given destination port. User defined type and enable the ecrc. Raw tlp data is accepted as a string of characters and converted to appropriate dword type and sent as part of new structure defined by spec. Up to 132 dwords of raw tlp data can be sent a time, this limit is defined by a macro in the switchtec header file.
1 parent 1cf1ddc commit f4fe1db

File tree

4 files changed

+139
-1
lines changed

4 files changed

+139
-1
lines changed

cli/diag.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,6 +2026,109 @@ static int refclk(int argc, char **argv)
20262026
return 0;
20272027
}
20282028

2029+
static int convert_str_to_dwords(char *str, uint32_t **dwords, int *num_dwords)
2030+
{
2031+
*num_dwords = 0;
2032+
const char *ptr = str;
2033+
int dword_len = 0;
2034+
while (*ptr != '\0') {
2035+
if (*ptr == '0' && *(ptr + 1) == 'x') {
2036+
(*num_dwords)++;
2037+
ptr += 2;
2038+
dword_len = 0;
2039+
}
2040+
while (*ptr != ' ' && *ptr != '\0') {
2041+
ptr++;
2042+
dword_len++;
2043+
}
2044+
if (dword_len > 8) {
2045+
printf("Entered dword longer than allowed\n");
2046+
return -1;
2047+
}
2048+
if (*ptr == ' ')
2049+
ptr++;
2050+
}
2051+
2052+
*dwords = (uint32_t *)malloc(*num_dwords * sizeof(uint32_t));
2053+
if (*dwords == NULL)
2054+
return -1;
2055+
2056+
ptr = str;
2057+
for (int i = 0; i < *num_dwords; i++) {
2058+
char *endptr;
2059+
(*dwords)[i] = (uint32_t)strtoul(ptr, &endptr, 0);
2060+
if (endptr == ptr || (*endptr != ' ' && *endptr != '\0')) {
2061+
free(*dwords);
2062+
return -1;
2063+
}
2064+
ptr = endptr;
2065+
while (*ptr == ' ')
2066+
ptr++;
2067+
}
2068+
2069+
return 0;
2070+
}
2071+
2072+
#define CMD_TLP_INJECT "Inject a raw TLP"
2073+
2074+
static int tlp_inject (int argc, char **argv)
2075+
{
2076+
int ret = 0;
2077+
uint32_t * raw_tlp_dwords = NULL;
2078+
int num_dwords = 0;
2079+
static struct {
2080+
struct switchtec_dev *dev;
2081+
int port_id;
2082+
int tlp_type;
2083+
int ecrc;
2084+
char * raw_tlp_data;
2085+
} cfg = {
2086+
.tlp_type = 0
2087+
};
2088+
2089+
const struct argconfig_options opts[] = {
2090+
DEVICE_OPTION,
2091+
{"port", 'p', "PORT_ID", CFG_NONNEGATIVE, &cfg.port_id,
2092+
required_argument, "destination port ID"},
2093+
{"tlp_type", 't', "TYPE", CFG_NONNEGATIVE, &cfg.tlp_type,
2094+
required_argument, "tlp type:\n0: P - Posted\n1: NP - Non-posted\n2: CP - Completion\n(default 0)"},
2095+
{"enable_ecrc", 'e', "", CFG_NONE, &cfg.ecrc, no_argument,
2096+
"Enable the ecrc to be included at the end of the input data (Default: disabled)"},
2097+
{"tlp_data", 'd', "\"DW0 DW1 ... DW131\"", CFG_STRING,
2098+
&cfg.raw_tlp_data, required_argument,
2099+
"DWs to be sent as part of the raw TLP (Maximum 132 DWs). Every DW must start with \'0x\'"},
2100+
{NULL}
2101+
};
2102+
2103+
argconfig_parse(argc, argv, CMD_TLP_INJECT, opts, &cfg, sizeof(cfg));
2104+
2105+
if (cfg.raw_tlp_data == NULL) {
2106+
fprintf(stderr, "Must set tlp data --tlp_data -d \n");
2107+
return -1;
2108+
}
2109+
ret = convert_str_to_dwords(cfg.raw_tlp_data, &raw_tlp_dwords,
2110+
&num_dwords);
2111+
if (ret) {
2112+
fprintf(stderr, "Error with tlp data provided \n");
2113+
return -1;
2114+
}
2115+
if (num_dwords > SWITCHTEC_DIAG_MAX_TLP_DWORDS) {
2116+
fprintf(stderr, "TLP data cannot exceed %d dwords \n",
2117+
SWITCHTEC_DIAG_MAX_TLP_DWORDS);
2118+
free(raw_tlp_dwords);
2119+
return -1;
2120+
}
2121+
2122+
ret = switchtec_tlp_inject(cfg.dev, cfg.port_id, cfg.tlp_type,
2123+
num_dwords, cfg.ecrc, raw_tlp_dwords);
2124+
if (ret != 0) {
2125+
switchtec_perror("tlp_inject");
2126+
return -1;
2127+
}
2128+
2129+
return 0;
2130+
}
2131+
20292132
static const struct cmd commands[] = {
20302133
CMD(crosshair, CMD_DESC_CROSS_HAIR),
20312134
CMD(eye, CMD_DESC_EYE),
@@ -2039,6 +2142,7 @@ static const struct cmd commands[] = {
20392142
CMD(rcvr_obj, CMD_DESC_RCVR_OBJ),
20402143
CMD(refclk, CMD_DESC_REF_CLK),
20412144
CMD(ltssm_log, CMD_DESC_LTSSM_LOG),
2145+
CMD(tlp_inject, CMD_TLP_INJECT),
20422146
{}
20432147
};
20442148

inc/switchtec/diag.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#ifndef LIBSWITCHTEC_DIAG_H
2626
#define LIBSWITCHTEC_DIAG_H
2727

28+
#include "switchtec.h"
29+
2830
#include <stdint.h>
2931

3032
/**
@@ -279,5 +281,13 @@ struct switchtec_diag_ltssm_log_dmp_out {
279281
uint32_t arc;
280282
};
281283

284+
struct switchtec_tlp_inject_in {
285+
uint32_t dest_port;
286+
uint32_t tlp_type;
287+
uint32_t tlp_length;
288+
uint32_t ecrc;
289+
uint32_t raw_tlp_data[SWITCHTEC_DIAG_MAX_TLP_DWORDS];
290+
};
291+
282292
#endif
283293
/**@}*/

inc/switchtec/switchtec.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ struct switchtec_dev;
6666
#define SWITCHTEC_PAX_ID_MASK 0x1f
6767
#define SWITCHTEC_PAX_ID_LOCAL SWITCHTEC_PAX_ID_MASK
6868

69+
#define SWITCHTEC_DIAG_MAX_TLP_DWORDS 132
70+
6971
#ifdef __CHECKER__
7072
#define __gas __attribute__((noderef, address_space(1)))
7173
#else
@@ -1243,7 +1245,8 @@ int switchtec_diag_refclk_ctl(struct switchtec_dev *dev, int stack_id, bool en);
12431245
int switchtec_diag_ltssm_log(struct switchtec_dev *dev,
12441246
int port, int *log_count,
12451247
struct switchtec_diag_ltssm_log *log_data);
1246-
1248+
int switchtec_tlp_inject(struct switchtec_dev * dev, int port_id, int tlp_type,
1249+
int tlp_length, int ecrc, uint32_t * raw_tlp_data);
12471250
#ifdef __cplusplus
12481251
}
12491252
#endif

lib/diag.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,4 +1214,25 @@ int switchtec_diag_ltssm_log(struct switchtec_dev *dev,
12141214
return ret;
12151215
}
12161216

1217+
int switchtec_tlp_inject(struct switchtec_dev * dev, int port_id, int tlp_type,
1218+
int tlp_length, int ecrc, uint32_t * raw_tlp_data)
1219+
{
1220+
uint32_t tlp_out;
1221+
int ret = 1;
1222+
struct switchtec_tlp_inject_in tlp_in = {
1223+
.dest_port = port_id,
1224+
.tlp_type = tlp_type,
1225+
.tlp_length = tlp_length,
1226+
.ecrc = ecrc
1227+
};
1228+
for (int i = 0; i < tlp_in.tlp_length; i++) {
1229+
tlp_in.raw_tlp_data[i] = htole32(*(raw_tlp_data + i));
1230+
}
1231+
free(raw_tlp_data);
1232+
1233+
ret = switchtec_cmd(dev, MRPC_DIAG_TLP_INJECT, &tlp_in, sizeof(tlp_in),
1234+
&tlp_out, sizeof(tlp_out));
1235+
return ret;
1236+
}
1237+
12171238
/**@}*/

0 commit comments

Comments
 (0)