]> mj.ucw.cz Git - pciutils.git/blob - lmr/lmr.h
pcilmr: Add logging functions for margining
[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 /* PCI Device wrapper for margining functions */
21 struct margin_dev {
22   struct pci_dev *dev;
23   int lmr_cap_addr;
24   u8 width;
25   u8 retimers_n;
26   u8 link_speed;
27
28   /* Saved Device settings to restore after margining */
29   u8 aspm;
30   bool hasd; // Hardware Autonomous Speed Disable
31   bool hawd; // Hardware Autonomous Width Disable
32 };
33
34 struct margin_link {
35   struct margin_dev down_port;
36   struct margin_dev up_port;
37 };
38
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;
45   bool volt_support;
46
47   u8 max_lanes;
48
49   u8 timing_steps;
50   u8 timing_offset;
51
52   u8 volt_steps;
53   u8 volt_offset;
54
55   u8 sample_rate_v;
56   u8 sample_rate_t;
57 };
58
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
64 };
65
66 enum margin_dir { VOLT_UP = 0, VOLT_DOWN, TIM_LEFT, TIM_RIGHT };
67
68 /* Margining results of one lane of the receiver */
69 struct margin_res_lane {
70   u8 lane;
71   u8 steps[4];
72   enum margin_step_exec_sts statuses[4];
73 };
74
75 /* Reason not to run margining test on the Link/Receiver */
76 enum margin_test_status {
77   MARGIN_TEST_OK = 0,
78   MARGIN_TEST_READY_BIT,
79   MARGIN_TEST_CAPS,
80
81   // Couldn't run test
82   MARGIN_TEST_PREREQS,
83   MARGIN_TEST_ARGS_LANES,
84   MARGIN_TEST_ARGS_RECVS,
85   MARGIN_TEST_ASPM
86 };
87
88 /* All lanes Receiver results */
89 struct margin_results {
90   u8 recvn; // Receiver Number
91   struct margin_params params;
92   bool lane_reversal;
93   u8 link_speed;
94
95   enum margin_test_status test_status;
96
97   /* Used to convert steps to physical quantity.
98      Calculated from MaxOffset and NumSteps     */
99   double tim_coef;
100   double volt_coef;
101
102   u8 lanes_n;
103   struct margin_res_lane *lanes;
104 };
105
106 /* pcilmr arguments */
107 struct margin_args {
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
119
120   u64 *steps_utility; // For ETA logging
121 };
122
123 /* Receiver structure */
124 struct margin_recv {
125   struct margin_dev *dev;
126   u8 recvn; // Receiver Number
127   bool lane_reversal;
128   struct margin_params *params;
129
130   u8 parallel_lanes;
131   u8 error_limit;
132 };
133
134 struct margin_lanes_data {
135   struct margin_recv *recv;
136
137   struct margin_res_lane *results;
138   u8 *lanes_numbers;
139   u8 lanes_n;
140
141   bool ind;
142   enum margin_dir dir;
143
144   u8 steps_lane_done;
145   u8 steps_lane_total;
146   u64 *steps_utility;
147
148   u8 verbosity;
149 };
150
151 /* margin_hw */
152
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);
155
156 /* Check Margining Ready bit from Margining Port Status Register */
157 bool margin_check_ready_bit(struct pci_dev *dev);
158
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);
162
163 /* Disable ASPM, set Hardware Autonomous Speed/Width Disable bits */
164 bool margin_prep_link(struct margin_link *link);
165
166 /* Restore ASPM, Hardware Autonomous Speed/Width settings */
167 void margin_restore_link(struct margin_link *link);
168
169 /* margin */
170
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);
174
175 enum margin_test_status margin_process_args(struct margin_dev *dev, struct margin_args *args);
176
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,
180                                         u8 *recvs_n);
181
182 void margin_free_results(struct margin_results *results, u8 results_n);
183
184 /* margin_log */
185
186 extern bool margin_global_logging;
187 extern bool margin_print_domain;
188
189 void margin_log(char *format, ...);
190
191 /* b:d.f -> b:d.f */
192 void margin_log_bdfs(struct pci_dev *down_port, struct pci_dev *up_port);
193
194 /* Print Link header (bdfs, width, speed) */
195 void margin_log_link(struct margin_link *link);
196
197 void margin_log_params(struct margin_params *params);
198
199 /* Print receiver number */
200 void margin_log_recvn(struct margin_recv *recv);
201
202 /* Print full info from Receiver struct */
203 void margin_log_receiver(struct margin_recv *recv);
204
205 /* Margining in progress log */
206 void margin_log_margining(struct margin_lanes_data arg);
207
208 #endif