2 * The PCI Utilities -- Margining utility main header
4 * Copyright (c) 2023 KNS Group LLC (YADRO)
6 * Can be freely distributed and used under the terms of the GNU GPL v2+.
8 * SPDX-License-Identifier: GPL-2.0-or-later
18 #define MARGIN_STEP_MS 1000
20 #define MARGIN_TIM_MIN 20
21 #define MARGIN_TIM_RECOMMEND 30
22 #define MARGIN_VOLT_MIN 50
24 enum margin_hw
{ MARGIN_HW_DEFAULT
, MARGIN_ICE_LAKE_RC
};
26 /* PCI Device wrapper for margining functions */
36 /* Saved Device settings to restore after margining */
38 bool hasd
; // Hardware Autonomous Speed Disable
39 bool hawd
; // Hardware Autonomous Width Disable
43 struct margin_dev down_port
;
44 struct margin_dev up_port
;
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
;
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
74 enum margin_dir
{ VOLT_UP
= 0, VOLT_DOWN
, TIM_LEFT
, TIM_RIGHT
};
76 /* Margining results of one lane of the receiver */
77 struct margin_res_lane
{
80 enum margin_step_exec_sts statuses
[4];
83 /* Reason not to run margining test on the Link/Receiver */
84 enum margin_test_status
{
86 MARGIN_TEST_READY_BIT
,
91 MARGIN_TEST_ARGS_LANES
,
92 MARGIN_TEST_ARGS_RECVS
,
96 /* All lanes Receiver results */
97 struct margin_results
{
98 u8 recvn
; // Receiver Number
99 struct margin_params params
;
103 enum margin_test_status test_status
;
105 /* Used to convert steps to physical quantity.
106 Calculated from MaxOffset and NumSteps */
110 bool tim_off_reported
;
111 bool volt_off_reported
;
114 struct margin_res_lane
*lanes
;
117 /* pcilmr arguments */
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
131 u64
*steps_utility
; // For ETA logging
134 /* Receiver structure */
136 struct margin_dev
*dev
;
137 u8 recvn
; // Receiver Number
139 struct margin_params
*params
;
145 struct margin_lanes_data
{
146 struct margin_recv
*recv
;
148 struct margin_res_lane
*results
;
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
);
167 /* Check Margining Ready bit from Margining Port Status Register */
168 bool margin_check_ready_bit(struct pci_dev
*dev
);
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
);
174 /* Disable ASPM, set Hardware Autonomous Speed/Width Disable bits */
175 bool margin_prep_link(struct margin_link
*link
);
177 /* Restore ASPM, Hardware Autonomous Speed/Width settings */
178 void margin_restore_link(struct margin_link
*link
);
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
);
186 enum margin_test_status
margin_process_args(struct margin_dev
*dev
, struct margin_args
*args
);
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
,
193 void margin_free_results(struct margin_results
*results
, u8 results_n
);
197 extern bool margin_global_logging
;
198 extern bool margin_print_domain
;
200 void margin_log(char *format
, ...);
203 void margin_log_bdfs(struct pci_dev
*down_port
, struct pci_dev
*up_port
);
205 /* Print Link header (bdfs, width, speed) */
206 void margin_log_link(struct margin_link
*link
);
208 void margin_log_params(struct margin_params
*params
);
210 /* Print receiver number */
211 void margin_log_recvn(struct margin_recv
*recv
);
213 /* Print full info from Receiver struct */
214 void margin_log_receiver(struct margin_recv
*recv
);
216 /* Margining in progress log */
217 void margin_log_margining(struct margin_lanes_data arg
);
219 void margin_log_hw_quirks(struct margin_recv
*recv
);
223 void margin_results_print_brief(struct margin_results
*results
, u8 recvs_n
);
225 void margin_results_save_csv(struct margin_results
*results
, u8 recvs_n
, char *dir
,
226 struct pci_dev
*up_port
);