aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikita Proshkin <n.proshkin@yadro.com>2023-12-27 14:45:02 +0500
committerMartin Mares <mj@ucw.cz>2024-02-17 23:44:52 +0100
commit394b24da3faeb7d09ad7ef71ca2f05641887ab2d (patch)
treed846828662d448f75cdb3364fe3c42ee65bf22fb
parent65f3c322709d9a345f7808c14e937a5e3ca882c4 (diff)
downloadpciutils-394b24da3faeb7d09ad7ef71ca2f05641887ab2d.tar.gz
pcilmr: Add option to save margining results in csv form
Reviewed-by: Sergei Miroshnichenko <s.miroshnichenko@yadro.com> Signed-off-by: Nikita Proshkin <n.proshkin@yadro.com>
-rw-r--r--lmr/lmr.h3
-rw-r--r--lmr/margin_results.c111
-rw-r--r--pcilmr.c18
3 files changed, 130 insertions, 2 deletions
diff --git a/lmr/lmr.h b/lmr/lmr.h
index bb188fc..c9dcd69 100644
--- a/lmr/lmr.h
+++ b/lmr/lmr.h
@@ -219,4 +219,7 @@ void margin_log_hw_quirks(struct margin_recv *recv);
void margin_results_print_brief(struct margin_results *results, u8 recvs_n);
+void margin_results_save_csv(struct margin_results *results, u8 recvs_n, char *dir,
+ struct pci_dev *up_port);
+
#endif
diff --git a/lmr/margin_results.c b/lmr/margin_results.c
index 5ee065d..aca3ab7 100644
--- a/lmr/margin_results.c
+++ b/lmr/margin_results.c
@@ -157,3 +157,114 @@ margin_results_print_brief(struct margin_results *results, u8 recvs_n)
printf("\n");
}
}
+
+void
+margin_results_save_csv(struct margin_results *results, u8 recvs_n, char *dir,
+ struct pci_dev *up_port)
+{
+ char timestamp[64];
+ time_t tim = time(NULL);
+ strftime(timestamp, sizeof(timestamp), "%FT%H.%M.%S", gmtime(&tim));
+
+ size_t pathlen = strlen(dir) + 128;
+ char *path = xmalloc(pathlen);
+ FILE *csv;
+
+ struct margin_res_lane *lane;
+ struct margin_results *res;
+ struct margin_params params;
+
+ enum lane_rating lane_rating;
+ u8 link_speed;
+
+ for (int i = 0; i < recvs_n; i++)
+ {
+ res = &(results[i]);
+ params = res->params;
+ link_speed = res->link_speed - 4;
+
+ if (res->test_status != MARGIN_TEST_OK)
+ continue;
+ snprintf(path, pathlen, "%s/lmr_%0*x.%02x.%02x.%x_Rx%X_%s.csv", dir,
+ up_port->domain_16 == 0xffff ? 8 : 4, up_port->domain, up_port->bus, up_port->dev,
+ up_port->func, 10 + res->recvn - 1, timestamp);
+ csv = fopen(path, "w");
+ if (!csv)
+ die("Error while saving %s\n", path);
+
+ fprintf(csv, "Lane,Lane Status,Left %% UI,Left ps,Left Steps,Left Status,"
+ "Right %% UI,Right ps,Right Steps,Right Status,"
+ "Time %% UI,Time ps,Time Steps,Time Status,"
+ "Up mV,Up Steps,Up Status,Down mV,Down Steps,Down Status,"
+ "Voltage mV,Voltage Steps,Voltage Status\n");
+
+ if (check_recv_weird(res, MARGIN_TIM_MIN, MARGIN_VOLT_MIN))
+ lane_rating = WEIRD;
+ else
+ lane_rating = INIT;
+
+ for (int j = 0; j < res->lanes_n; j++)
+ {
+ lane = &(res->lanes[j]);
+ double left_ui = lane->steps[TIM_LEFT] * res->tim_coef;
+ double right_ui = lane->steps[TIM_RIGHT] * res->tim_coef;
+ double up_volt = lane->steps[VOLT_UP] * res->volt_coef;
+ double down_volt = lane->steps[VOLT_DOWN] * res->volt_coef;
+
+ if (lane_rating != WEIRD)
+ {
+ lane_rating = rate_lane(left_ui, MARGIN_TIM_MIN, MARGIN_TIM_RECOMMEND, INIT);
+ if (params.ind_left_right_tim)
+ lane_rating
+ = rate_lane(right_ui, MARGIN_TIM_MIN, MARGIN_TIM_RECOMMEND, lane_rating);
+ if (params.volt_support)
+ {
+ lane_rating = rate_lane(up_volt, MARGIN_VOLT_MIN, MARGIN_VOLT_MIN, lane_rating);
+ if (params.ind_up_down_volt)
+ lane_rating
+ = rate_lane(down_volt, MARGIN_VOLT_MIN, MARGIN_VOLT_MIN, lane_rating);
+ }
+ }
+
+ fprintf(csv, "%d,%s,", lane->lane, grades[lane_rating]);
+ if (params.ind_left_right_tim)
+ {
+ fprintf(csv, "%f,%f,%d,%s,%f,%f,%d,%s,NA,NA,NA,NA,", left_ui,
+ left_ui * ui[link_speed], lane->steps[TIM_LEFT],
+ sts_strings[lane->statuses[TIM_LEFT]], right_ui, right_ui * ui[link_speed],
+ lane->steps[TIM_RIGHT], sts_strings[lane->statuses[TIM_RIGHT]]);
+ }
+ else
+ {
+ for (int k = 0; k < 8; k++)
+ fprintf(csv, "NA,");
+ fprintf(csv, "%f,%f,%d,%s,", left_ui, left_ui * ui[link_speed], lane->steps[TIM_LEFT],
+ sts_strings[lane->statuses[TIM_LEFT]]);
+ }
+ if (params.volt_support)
+ {
+ if (params.ind_up_down_volt)
+ {
+ fprintf(csv, "%f,%d,%s,%f,%d,%s,NA,NA,NA\n", up_volt, lane->steps[VOLT_UP],
+ sts_strings[lane->statuses[VOLT_UP]], down_volt, lane->steps[VOLT_DOWN],
+ sts_strings[lane->statuses[VOLT_DOWN]]);
+ }
+ else
+ {
+ for (int k = 0; k < 6; k++)
+ fprintf(csv, "NA,");
+ fprintf(csv, "%f,%d,%s\n", up_volt, lane->steps[VOLT_UP],
+ sts_strings[lane->statuses[VOLT_UP]]);
+ }
+ }
+ else
+ {
+ for (int k = 0; k < 8; k++)
+ fprintf(csv, "NA,");
+ fprintf(csv, "NA\n");
+ }
+ }
+ fclose(csv);
+ }
+ free(path);
+}
diff --git a/pcilmr.c b/pcilmr.c
index 43e791d..eb5d947 100644
--- a/pcilmr.c
+++ b/pcilmr.c
@@ -52,7 +52,12 @@ static const char usage_msg[]
"-v <steps>\t\tSpecify maximum number of steps for Voltage Margining.\n"
"Use only one of -T/-t options at the same time (same for -V/-v).\n"
"Without these options utility will use MaxSteps from Device\n"
- "capabilities as test limit.\n\n";
+ "capabilities as test limit.\n\n"
+ "Margining Log settings:\n"
+ "-o <directory>\t\tSave margining results in csv form into the\n"
+ "\t\t\tspecified directory. Utility will generate file with the\n"
+ "\t\t\tname in form of 'lmr_<downstream component>_Rx#_<timestamp>.csv'\n"
+ "\t\t\tfor each successfully tested receiver.\n";
static struct pci_dev *
dev_for_filter(struct pci_access *pacc, char *filter)
@@ -197,6 +202,9 @@ main(int argc, char **argv)
bool run_margin = true;
+ char *dir_for_csv = NULL;
+ bool save_csv = false;
+
u64 total_steps = 0;
pacc = pci_alloc();
@@ -246,7 +254,7 @@ main(int argc, char **argv)
break;
}
- while ((c = getopt(argc, argv, ":r:e:l:cp:t:v:VT")) != -1)
+ while ((c = getopt(argc, argv, ":r:e:l:cp:t:v:VTo:")) != -1)
{
switch (c)
{
@@ -277,6 +285,10 @@ main(int argc, char **argv)
case 'r':
recvs_n = parse_csv_arg(optarg, recvs_arg);
break;
+ case 'o':
+ dir_for_csv = optarg;
+ save_csv = true;
+ break;
default:
die("Invalid arguments\n\n%s", usage_msg);
}
@@ -449,6 +461,8 @@ main(int argc, char **argv)
margin_log_bdfs(down_ports[i], up_ports[i]);
printf(":\n\n");
margin_results_print_brief(results[i], results_n[i]);
+ if (save_csv)
+ margin_results_save_csv(results[i], results_n[i], dir_for_csv, up_ports[i]);
printf("\n");
}
}