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