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