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 /* PCI Device wrapper for margining functions */
28 /* Saved Device settings to restore after margining */
30 bool hasd; // Hardware Autonomous Speed Disable
31 bool hawd; // Hardware Autonomous Width Disable
35 struct margin_dev down_port;
36 struct margin_dev up_port;
39 /* Specification Revision 5.0 Table 8-11 */
40 struct margin_params {
41 bool ind_error_sampler;
42 bool sample_report_method;
43 bool ind_left_right_tim;
44 bool ind_up_down_volt;
59 /* Step Margin Execution Status - Step command response */
60 enum margin_step_exec_sts {
61 MARGIN_NAK = 0, // NAK/Set up for margin
62 MARGIN_LIM, // Too many errors (device limit)
63 MARGIN_THR // Test threshold has been reached
66 enum margin_dir { VOLT_UP = 0, VOLT_DOWN, TIM_LEFT, TIM_RIGHT };
68 /* Margining results of one lane of the receiver */
69 struct margin_res_lane {
72 enum margin_step_exec_sts statuses[4];
75 /* Reason not to run margining test on the Link/Receiver */
76 enum margin_test_status {
78 MARGIN_TEST_READY_BIT,
83 MARGIN_TEST_ARGS_LANES,
84 MARGIN_TEST_ARGS_RECVS,
88 /* All lanes Receiver results */
89 struct margin_results {
90 u8 recvn; // Receiver Number
91 struct margin_params params;
95 enum margin_test_status test_status;
97 /* Used to convert steps to physical quantity.
98 Calculated from MaxOffset and NumSteps */
103 struct margin_res_lane *lanes;
106 /* pcilmr arguments */
108 u8 steps_t; // 0 == use NumTimingSteps
109 u8 steps_v; // 0 == use NumVoltageSteps
110 u8 parallel_lanes; // [1; MaxLanes + 1]
111 u8 error_limit; // [0; 63]
112 u8 recvs[6]; // Receivers Numbers
113 u8 recvs_n; // 0 == margin all available receivers
114 u8 lanes[32]; // Lanes to Margin
115 u8 lanes_n; // 0 == margin all available lanes
116 bool run_margin; // Or print params only
117 u8 verbosity; // 0 - basic;
118 // 1 - add info about remaining time and lanes in progress during margining
120 u64 *steps_utility; // For ETA logging
123 /* Receiver structure */
125 struct margin_dev *dev;
126 u8 recvn; // Receiver Number
128 struct margin_params *params;
134 struct margin_lanes_data {
135 struct margin_recv *recv;
137 struct margin_res_lane *results;
153 /* Verify that devices form the link with 16 GT/s or 32 GT/s data rate */
154 bool margin_verify_link(struct pci_dev *down_port, struct pci_dev *up_port);
156 /* Check Margining Ready bit from Margining Port Status Register */
157 bool margin_check_ready_bit(struct pci_dev *dev);
159 /* Verify link and fill wrappers */
160 bool margin_fill_link(struct pci_dev *down_port, struct pci_dev *up_port,
161 struct margin_link *wrappers);
163 /* Disable ASPM, set Hardware Autonomous Speed/Width Disable bits */
164 bool margin_prep_link(struct margin_link *link);
166 /* Restore ASPM, Hardware Autonomous Speed/Width settings */
167 void margin_restore_link(struct margin_link *link);
171 /* Fill margin_params without calling other functions */
172 bool margin_read_params(struct pci_access *pacc, struct pci_dev *dev, u8 recvn,
173 struct margin_params *params);
175 enum margin_test_status margin_process_args(struct margin_dev *dev, struct margin_args *args);
177 /* Awaits that args are prepared through process_args.
178 Returns number of margined Receivers through recvs_n */
179 struct margin_results *margin_test_link(struct margin_link *link, struct margin_args *args,
182 void margin_free_results(struct margin_results *results, u8 results_n);
186 extern bool margin_global_logging;
187 extern bool margin_print_domain;
189 void margin_log(char *format, ...);
192 void margin_log_bdfs(struct pci_dev *down_port, struct pci_dev *up_port);
194 /* Print Link header (bdfs, width, speed) */
195 void margin_log_link(struct margin_link *link);
197 void margin_log_params(struct margin_params *params);
199 /* Print receiver number */
200 void margin_log_recvn(struct margin_recv *recv);
202 /* Print full info from Receiver struct */
203 void margin_log_receiver(struct margin_recv *recv);
205 /* Margining in progress log */
206 void margin_log_margining(struct margin_lanes_data arg);