]> mj.ucw.cz Git - pciutils.git/blob - lmr/lmr.h
pcilmr: Move most of pcilmr arguments parsing logic to the separate file
[pciutils.git] / lmr / lmr.h
1 /*
2  *      The PCI Utilities -- Margining utility main header
3  *
4  *      Copyright (c) 2023-2024 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 #ifndef _LMR_H
12 #define _LMR_H
13
14 #include <stdbool.h>
15
16 #include "pciutils.h"
17
18 #define MARGIN_STEP_MS 1000
19
20 #define MARGIN_TIM_MIN       20
21 #define MARGIN_TIM_RECOMMEND 30
22 #define MARGIN_VOLT_MIN      50
23
24 enum margin_hw { MARGIN_HW_DEFAULT, MARGIN_ICE_LAKE_RC };
25
26 /* PCI Device wrapper for margining functions */
27 struct margin_dev {
28   struct pci_dev *dev;
29   int lmr_cap_addr;
30   u8 width;
31   u8 retimers_n;
32   u8 link_speed;
33
34   enum margin_hw hw;
35
36   /* Saved Device settings to restore after margining */
37   u8 aspm;
38   bool hasd; // Hardware Autonomous Speed Disable
39   bool hawd; // Hardware Autonomous Width Disable
40 };
41
42 /* Specification Revision 5.0 Table 8-11 */
43 struct margin_params {
44   bool ind_error_sampler;
45   bool sample_report_method;
46   bool ind_left_right_tim;
47   bool ind_up_down_volt;
48   bool volt_support;
49
50   u8 max_lanes;
51
52   u8 timing_steps;
53   u8 timing_offset;
54
55   u8 volt_steps;
56   u8 volt_offset;
57
58   u8 sample_rate_v;
59   u8 sample_rate_t;
60 };
61
62 /* Step Margin Execution Status - Step command response */
63 enum margin_step_exec_sts {
64   MARGIN_NAK = 0, // NAK/Set up for margin
65   MARGIN_LIM,     // Too many errors (device limit)
66   MARGIN_THR      // Test threshold has been reached
67 };
68
69 enum margin_dir { VOLT_UP = 0, VOLT_DOWN, TIM_LEFT, TIM_RIGHT };
70
71 /* Margining results of one lane of the receiver */
72 struct margin_res_lane {
73   u8 lane;
74   u8 steps[4];
75   enum margin_step_exec_sts statuses[4];
76 };
77
78 /* Reason not to run margining test on the Link/Receiver */
79 enum margin_test_status {
80   MARGIN_TEST_OK = 0,
81   MARGIN_TEST_READY_BIT,
82   MARGIN_TEST_CAPS,
83
84   // Couldn't run test
85   MARGIN_TEST_PREREQS,
86   MARGIN_TEST_ARGS_LANES,
87   MARGIN_TEST_ARGS_RECVS,
88   MARGIN_TEST_ASPM
89 };
90
91 /* All lanes Receiver results */
92 struct margin_results {
93   u8 recvn; // Receiver Number; from 1 to 6
94   struct margin_params params;
95   bool lane_reversal;
96   u8 link_speed;
97
98   enum margin_test_status test_status;
99
100   /* Used to convert steps to physical quantity.
101      Calculated from MaxOffset and NumSteps     */
102   double tim_coef; // from steps to % UI
103   double volt_coef;
104
105   bool tim_off_reported;
106   bool volt_off_reported;
107
108   u8 lanes_n;
109   struct margin_res_lane *lanes;
110 };
111
112 /* pcilmr arguments */
113
114 // Common args
115 struct margin_com_args {
116   u8 error_limit;    // [0; 63]
117   bool run_margin;   // Or print params only
118   u8 verbosity;      // 0 - basic;
119                      // 1 - add info about remaining time and lanes in progress during margining
120   u64 steps_utility; // For ETA logging
121   bool save_csv;
122   char *dir_for_csv;
123 };
124
125 struct margin_link_args {
126   struct margin_com_args *common;
127   u8 steps_t;        // 0 == use NumTimingSteps
128   u8 steps_v;        // 0 == use NumVoltageSteps
129   u8 parallel_lanes; // [1; MaxLanes + 1]
130   u8 recvs[6];       // Receivers Numbers
131   u8 recvs_n;        // 0 == margin all available receivers
132   u8 lanes[32];      // Lanes to Margin
133   u8 lanes_n;        // 0 == margin all available lanes
134 };
135
136 struct margin_link {
137   struct margin_dev down_port;
138   struct margin_dev up_port;
139   struct margin_link_args args;
140 };
141
142 /* Receiver structure */
143 struct margin_recv {
144   struct margin_dev *dev;
145   u8 recvn; // Receiver Number; from 1 to 6
146   bool lane_reversal;
147   struct margin_params *params;
148
149   u8 parallel_lanes;
150   u8 error_limit;
151 };
152
153 struct margin_lanes_data {
154   struct margin_recv *recv;
155
156   struct margin_res_lane *results;
157   u8 *lanes_numbers;
158   u8 lanes_n;
159
160   bool ind;
161   enum margin_dir dir;
162
163   u8 steps_lane_done;
164   u8 steps_lane_total;
165   u64 *steps_utility;
166
167   u8 verbosity;
168 };
169
170 /* margin_args */
171
172 enum margin_mode { MARGIN, FULL, SCAN };
173
174 extern const char *usage;
175
176 struct margin_link *margin_parse_util_args(struct pci_access *pacc, int argc, char **argv,
177                                            enum margin_mode mode, u8 *links_n);
178
179 /* margin_hw */
180
181 bool margin_port_is_down(struct pci_dev *dev);
182
183 /* Results through down/up ports */
184 bool margin_find_pair(struct pci_access *pacc, struct pci_dev *dev, struct pci_dev **down_port,
185                       struct pci_dev **up_port);
186
187 /* Verify that devices form the link with 16 GT/s or 32 GT/s data rate */
188 bool margin_verify_link(struct pci_dev *down_port, struct pci_dev *up_port);
189
190 /* Check Margining Ready bit from Margining Port Status Register */
191 bool margin_check_ready_bit(struct pci_dev *dev);
192
193 /* Verify link and fill wrappers */
194 bool margin_fill_link(struct pci_dev *down_port, struct pci_dev *up_port,
195                       struct margin_link *wrappers);
196
197 /* Disable ASPM, set Hardware Autonomous Speed/Width Disable bits */
198 bool margin_prep_link(struct margin_link *link);
199
200 /* Restore ASPM, Hardware Autonomous Speed/Width settings */
201 void margin_restore_link(struct margin_link *link);
202
203 /* margin */
204
205 /* Fill margin_params without calling other functions */
206 bool margin_read_params(struct pci_access *pacc, struct pci_dev *dev, u8 recvn,
207                         struct margin_params *params);
208
209 enum margin_test_status margin_process_args(struct margin_link *link);
210
211 /* Awaits that links are prepared through process_args.
212    Returns number of margined Receivers through recvs_n */
213 struct margin_results *margin_test_link(struct margin_link *link, u8 *recvs_n);
214
215 void margin_free_results(struct margin_results *results, u8 results_n);
216
217 /* margin_log */
218
219 extern bool margin_global_logging;
220 extern bool margin_print_domain;
221
222 void margin_log(char *format, ...);
223
224 /* b:d.f -> b:d.f */
225 void margin_log_bdfs(struct pci_dev *down_port, struct pci_dev *up_port);
226 void margin_gen_bdfs(struct pci_dev *down_port, struct pci_dev *up_port, char *dest, size_t maxlen);
227
228 /* Print Link header (bdfs, width, speed) */
229 void margin_log_link(struct margin_link *link);
230
231 void margin_log_params(struct margin_params *params);
232
233 /* Print receiver number */
234 void margin_log_recvn(struct margin_recv *recv);
235
236 /* Print full info from Receiver struct */
237 void margin_log_receiver(struct margin_recv *recv);
238
239 /* Margining in progress log */
240 void margin_log_margining(struct margin_lanes_data arg);
241
242 void margin_log_hw_quirks(struct margin_recv *recv);
243
244 /* margin_results */
245
246 void margin_results_print_brief(struct margin_results *results, u8 recvs_n);
247
248 void margin_results_save_csv(struct margin_results *results, u8 recvs_n, struct margin_link *link);
249
250 #endif