]> mj.ucw.cz Git - pciutils.git/blob - lmr/margin_log.c
Names: Fixed a rare bug in loading of pci.ids
[pciutils.git] / lmr / margin_log.c
1 /*
2  *      The PCI Utilities -- Log margining process
3  *
4  *      Copyright (c) 2023 KNS Group LLC (YADRO)
5  *
6  *      Can be freely distributed and used under the terms of the GNU GPL v2+.
7  *
8  *      SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include <stdarg.h>
12 #include <stdio.h>
13
14 #include "lmr.h"
15
16 bool margin_global_logging = false;
17 bool margin_print_domain = true;
18
19 void
20 margin_log(char *format, ...)
21 {
22   va_list arg;
23   va_start(arg, format);
24   if (margin_global_logging)
25     vprintf(format, arg);
26   va_end(arg);
27 }
28
29 void
30 margin_log_bdfs(struct pci_dev *down, struct pci_dev *up)
31 {
32   if (margin_print_domain)
33     margin_log("%x:%x:%x.%x -> %x:%x:%x.%x", down->domain, down->bus, down->dev, down->func,
34                up->domain, up->bus, up->dev, up->func);
35   else
36     margin_log("%x:%x.%x -> %x:%x.%x", down->bus, down->dev, down->func, up->bus, up->dev,
37                up->func);
38 }
39
40 void
41 margin_log_link(struct margin_link *link)
42 {
43   margin_log("Link ");
44   margin_log_bdfs(link->down_port.dev, link->up_port.dev);
45   margin_log("\nNegotiated Link Width: %d\n", link->down_port.width);
46   margin_log("Link Speed: %d.0 GT/s = Gen %d\n", (link->down_port.link_speed - 3) * 16,
47              link->down_port.link_speed);
48   margin_log("Available receivers: ");
49   int receivers_n = 2 + 2 * link->down_port.retimers_n;
50   for (int i = 1; i < receivers_n; i++)
51     margin_log("Rx(%X) - %d, ", 10 + i - 1, i);
52   margin_log("Rx(F) - 6\n");
53 }
54
55 void
56 margin_log_params(struct margin_params *params)
57 {
58   margin_log("Independent Error Sampler: %d\n", params->ind_error_sampler);
59   margin_log("Sample Reporting Method: %d\n", params->sample_report_method);
60   margin_log("Independent Left and Right Timing Margining: %d\n", params->ind_left_right_tim);
61   margin_log("Voltage Margining Supported: %d\n", params->volt_support);
62   margin_log("Independent Up and Down Voltage Margining: %d\n", params->ind_up_down_volt);
63   margin_log("Number of Timing Steps: %d\n", params->timing_steps);
64   margin_log("Number of Voltage Steps: %d\n", params->volt_steps);
65   margin_log("Max Timing Offset: %d\n", params->timing_offset);
66   margin_log("Max Voltage Offset: %d\n", params->volt_offset);
67   margin_log("Max Lanes: %d\n", params->max_lanes);
68 }
69
70 void
71 margin_log_recvn(struct margin_recv *recv)
72 {
73   margin_log("\nReceiver = Rx(%X)\n", 10 + recv->recvn - 1);
74 }
75
76 void
77 margin_log_receiver(struct margin_recv *recv)
78 {
79   margin_log("\nError Count Limit = %d\n", recv->error_limit);
80   margin_log("Parallel Lanes: %d\n\n", recv->parallel_lanes);
81
82   margin_log_params(recv->params);
83
84   if (recv->lane_reversal)
85     {
86       margin_log("\nWarning: device uses Lane Reversal.\n");
87       margin_log("However, utility uses logical lane numbers in arguments and for logging.\n");
88     }
89
90   if (recv->params->timing_offset == 0)
91     margin_log("\nWarning: Vendor chose not to report the Max Timing Offset.\n"
92                "Utility will use its max possible value - 50 (50%% UI).\n");
93   if (recv->params->volt_support && recv->params->volt_offset == 0)
94     margin_log("\nWarning: Vendor chose not to report the Max Voltage Offset.\n"
95                "Utility will use its max possible value - 50 (500 mV).\n");
96 }
97
98 void
99 margin_log_margining(struct margin_lanes_data arg)
100 {
101   char *ind_dirs[] = { "Up", "Down", "Left", "Right" };
102   char *non_ind_dirs[] = { "Voltage", "", "Timing" };
103
104   if (arg.verbosity > 0)
105     {
106       margin_log("\033[2K\rMargining - ");
107       if (arg.ind)
108         margin_log("%s", ind_dirs[arg.dir]);
109       else
110         margin_log("%s", non_ind_dirs[arg.dir]);
111
112       u8 lanes_counter = 0;
113       margin_log(" - Lanes ");
114       margin_log("[%d", arg.lanes_numbers[0]);
115       for (int i = 1; i < arg.lanes_n; i++)
116         {
117           if (arg.lanes_numbers[i] - 1 == arg.lanes_numbers[i - 1])
118             {
119               lanes_counter++;
120               if (lanes_counter == 1)
121                 margin_log("-");
122               if (i + 1 == arg.lanes_n)
123                 margin_log("%d", arg.lanes_numbers[i]);
124             }
125           else
126             {
127               if (lanes_counter > 0)
128                 margin_log("%d", arg.lanes_numbers[i - 1]);
129               margin_log(",%d", arg.lanes_numbers[i]);
130               lanes_counter = 0;
131             }
132         }
133       margin_log("]");
134
135       u64 lane_eta_s = (arg.steps_lane_total - arg.steps_lane_done) * MARGIN_STEP_MS / 1000;
136       u64 total_eta_s = *arg.steps_utility * MARGIN_STEP_MS / 1000 + lane_eta_s;
137       margin_log(" - ETA: %3ds Steps: %3d Total ETA: %3dm %2ds", lane_eta_s, arg.steps_lane_done,
138                  total_eta_s / 60, total_eta_s % 60);
139
140       fflush(stdout);
141     }
142 }
143
144 void
145 margin_log_hw_quirks(struct margin_recv *recv)
146 {
147   switch (recv->dev->hw)
148     {
149       case MARGIN_ICE_LAKE_RC:
150         if (recv->recvn == 1)
151           margin_log("\nRx(A) is Intel Ice Lake RC port.\n"
152                      "Applying next quirks for margining process:\n"
153                      "  - Set MaxVoltageOffset to 12 (120 mV).\n");
154         break;
155       default:
156         break;
157     }
158 }