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