@@ -1,4 +1,4 @@
-OBJS=margin_hw margin
+OBJS=margin_hw margin margin_log
INCL=$(addsuffix .h,$(OBJS)) $(addprefix ../,$(PCIINC))
$(addsuffix .o, $(OBJS)): %.o: %.c $(INCL)
@@ -4,6 +4,7 @@
#include <malloc.h>
#include "margin.h"
+#include "margin_log.h"
#define MARG_LANE_CTRL(lmr_cap_addr, lane) ((lmr_cap_addr) + 8 + 4 * (lane))
#define MARG_LANE_STATUS(lmr_cap_addr, lane) ((lmr_cap_addr) + 10 + 4 * (lane))
@@ -196,6 +197,7 @@ void margin_lanes(struct margin_lanes_data arg)
}
arg.steps_lane_done = steps_done;
+ margin_log_margining(arg);
}
for (uint8_t i = 0; i < arg.lanes_n; i++)
@@ -219,9 +221,11 @@ bool margin_receiver(struct margin_recv *recv, struct margin_args *args, struct
recv->error_limit = args->error_limit;
recv->parallel_lanes = (args->parallel_lanes < 0 ? 1 : args->parallel_lanes);
results->lanes_n = lanes_n;
+ margin_log_receiver(recv);
if (!margin_check_ready_bit(recv->dev->dev))
{
+ margin_log("\nMargining Ready bit is Clear.\n");
results->test_status = MARGIN_TEST_READY_BIT;
status = false;
}
@@ -234,6 +238,7 @@ bool margin_receiver(struct margin_recv *recv, struct margin_args *args, struct
recv->lane_reversal = true;
if (!margin_read_params(recv))
{
+ margin_log("\nError during caps reading.\n");
results->test_status = MARGIN_TEST_CAPS;
status = false;
}
@@ -255,6 +260,8 @@ bool margin_receiver(struct margin_recv *recv, struct margin_args *args, struct
results->link_speed = recv->dev->link_speed;
results->test_status = MARGIN_TEST_OK;
+ margin_log_print_caps(recv);
+
results->lanes = malloc(sizeof(struct margin_res_lane) * lanes_n);
for (uint8_t i = 0; i < lanes_n; i++)
{
@@ -263,6 +270,7 @@ bool margin_receiver(struct margin_recv *recv, struct margin_args *args, struct
if (args->run_margin)
{
+ if (args->verbosity > 0) margin_log("\n");
struct margin_lanes_data margin_lanes_data = {.recv = recv,
.verbosity = args->verbosity,
.steps_margin_remaining = args->steps_margin_remaining};
@@ -302,6 +310,7 @@ bool margin_receiver(struct margin_recv *recv, struct margin_args *args, struct
}
lanes_done += use_lanes;
}
+ if (args->verbosity > 0) margin_log("\n");
if (recv->lane_reversal)
{
for (uint8_t i = 0; i < lanes_n; i++)
@@ -368,12 +377,15 @@ struct margin_results *margin_link(struct margin_dev *down_port, struct margin_d
uint8_t receivers_n = status ? args->recvs_n : 1;
uint8_t *receivers = args->recvs;
+ margin_log_link(down_port, up_port);
+
struct margin_results *results = malloc(sizeof(*results) * receivers_n);
struct margin_recv receiver;
if (!status)
{
results[0].test_status = MARGIN_TEST_ASPM;
+ margin_log("\nCouldn't disable ASPM on the given Link.\n");
}
if (status)
new file mode 100644
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "margin_log.h"
+
+bool margin_global_logging = false;
+bool margin_print_domain = true;
+
+void margin_log(char *format, ...)
+{
+ va_list arg;
+ va_start(arg, format);
+ if (margin_global_logging)
+ vprintf(format, arg);
+ va_end(arg);
+}
+
+void margin_log_bdfs(struct pci_dev *down, struct pci_dev *up)
+{
+ if (margin_print_domain)
+ {
+ margin_log("%x:%x:%x.%x -> %x:%x:%x.%x", down->domain, down->bus, down->dev,
+ down->func, up->domain, up->bus, up->dev, up->func);
+ }
+ else
+ {
+ margin_log("%x:%x.%x -> %x:%x.%x", down->bus, down->dev,
+ down->func, up->bus, up->dev, up->func);
+ }
+}
+
+void margin_log_print_caps(struct margin_recv *recv)
+{
+ margin_log("\nError Count Limit = %d\n", recv->error_limit);
+ margin_log("Parallel Lanes: %d\n", recv->parallel_lanes);
+ margin_log("\nIndependent Error Sampler: %d\n", recv->ind_error_sampler);
+ margin_log("Sample Reporting Method: %d\n", recv->sample_report_method);
+ margin_log("Independent Left and Right Timing Margining: %d\n", recv->ind_left_right_tim);
+ margin_log("Voltage Margining Supported: %d\n", recv->volt_support);
+ margin_log("Independent Up and Down Voltage Margining: %d\n", recv->ind_up_down_volt);
+ margin_log("Number of Timing Steps: %d\n", recv->timing_steps);
+ margin_log("Number of Voltage Steps: %d\n", recv->volt_steps);
+ margin_log("Max Timing Offset: %d\n", recv->timing_offset);
+ margin_log("Max Voltage Offset: %d\n", recv->volt_offset);
+ margin_log("Max Lanes: %d\n", recv->max_lanes);
+
+ if (recv->lane_reversal)
+ {
+ margin_log("\nWarning: device uses Lane Reversal.\n");
+ margin_log("However, utility uses logical lane numbers in arguments and for logging.\n");
+ }
+}
+
+void margin_log_link(struct margin_dev *down, struct margin_dev *up)
+{
+ margin_log("Link ");
+ margin_log_bdfs(down->dev, up->dev);
+ margin_log("\nNegotiated Link Width: %d\n", down->width);
+ margin_log("Link Speed: %d.0 GT/s = Gen %d\n", (down->link_speed - 3) * 16, down->link_speed);
+ margin_log("Available receivers: ");
+ uint8_t receivers_n = 2 + 2 * down->retimers_n;
+ for (uint8_t i = 1; i < receivers_n; i++)
+ margin_log("Rx(%X) - %d, ", 10 + i - 1, i);
+ margin_log("Rx(F) - 6\n");
+}
+
+void margin_log_receiver(struct margin_recv *recv)
+{
+ margin_log("\nReceiver = Rx(%X)\n", 10 + recv->recvn - 1);
+}
+
+void margin_log_margining(struct margin_lanes_data arg)
+{
+ char *ind_dirs[] = {"Up", "Down", "Left", "Right"};
+ char *non_ind_dirs[] = {"Voltage", "", "Timing"};
+
+ if (arg.verbosity > 0)
+ {
+ margin_log("\033[2K\rMargining - ");
+ if (arg.ind)
+ margin_log("%s", ind_dirs[arg.dir]);
+ else
+ margin_log("%s", non_ind_dirs[arg.dir]);
+
+ uint8_t lanes_counter = 0;
+ margin_log(" - Lanes ");
+ margin_log("[%d", arg.lanes_numbers[0]);
+ for (uint8_t i = 1; i < arg.lanes_n; i++)
+ {
+ if (arg.lanes_numbers[i] - 1 == arg.lanes_numbers[i - 1])
+ {
+ lanes_counter++;
+ if (lanes_counter == 1)
+ margin_log("-");
+ if (i + 1 == arg.lanes_n)
+ margin_log("%d", arg.lanes_numbers[i]);
+ }
+ else
+ {
+ if (lanes_counter > 0)
+ margin_log("%d", arg.lanes_numbers[i - 1]);
+ margin_log(",%d", arg.lanes_numbers[i]);
+ lanes_counter = 0;
+ }
+ }
+ margin_log("]");
+
+ uint64_t lane_eta_s = (arg.steps_lane_total - arg.steps_lane_done) * MARGIN_STEP_MS / 1000;
+ uint64_t total_eta_s = *arg.steps_margin_remaining * MARGIN_STEP_MS / 1000 + lane_eta_s;
+ margin_log(" - ETA: %3ds Steps: %3d Total ETA: %3dm %2ds",
+ lane_eta_s, arg.steps_lane_done, total_eta_s / 60, total_eta_s % 60);
+
+ fflush(stdout);
+ }
+}
new file mode 100644
@@ -0,0 +1,21 @@
+#ifndef _MARGIN_LOG_H
+#define _MARGIN_LOG_H
+
+#include "margin.h"
+
+extern bool margin_global_logging;
+extern bool margin_print_domain;
+
+void margin_log(char *format, ...);
+
+void margin_log_bdfs(struct pci_dev *down, struct pci_dev *up);
+
+void margin_log_print_caps(struct margin_recv *recv);
+
+void margin_log_link(struct margin_dev *down, struct margin_dev *up);
+
+void margin_log_receiver(struct margin_recv *recv);
+
+void margin_log_margining(struct margin_lanes_data arg);
+
+#endif