1*c2e0c6b5SAndroid Build Coastguard Worker /* 2*c2e0c6b5SAndroid Build Coastguard Worker * The PCI Utilities -- Margining utility main header 3*c2e0c6b5SAndroid Build Coastguard Worker * 4*c2e0c6b5SAndroid Build Coastguard Worker * Copyright (c) 2023-2024 KNS Group LLC (YADRO) 5*c2e0c6b5SAndroid Build Coastguard Worker * 6*c2e0c6b5SAndroid Build Coastguard Worker * Can be freely distributed and used under the terms of the GNU GPL v2+. 7*c2e0c6b5SAndroid Build Coastguard Worker * 8*c2e0c6b5SAndroid Build Coastguard Worker * SPDX-License-Identifier: GPL-2.0-or-later 9*c2e0c6b5SAndroid Build Coastguard Worker */ 10*c2e0c6b5SAndroid Build Coastguard Worker 11*c2e0c6b5SAndroid Build Coastguard Worker #ifndef _LMR_H 12*c2e0c6b5SAndroid Build Coastguard Worker #define _LMR_H 13*c2e0c6b5SAndroid Build Coastguard Worker 14*c2e0c6b5SAndroid Build Coastguard Worker #include <stdbool.h> 15*c2e0c6b5SAndroid Build Coastguard Worker 16*c2e0c6b5SAndroid Build Coastguard Worker #include "pciutils.h" 17*c2e0c6b5SAndroid Build Coastguard Worker 18*c2e0c6b5SAndroid Build Coastguard Worker enum margin_hw { MARGIN_HW_DEFAULT, MARGIN_ICE_LAKE_RC }; 19*c2e0c6b5SAndroid Build Coastguard Worker 20*c2e0c6b5SAndroid Build Coastguard Worker // in ps 21*c2e0c6b5SAndroid Build Coastguard Worker static const double margin_ui[] = { 62.5, 31.25 }; 22*c2e0c6b5SAndroid Build Coastguard Worker 23*c2e0c6b5SAndroid Build Coastguard Worker /* PCI Device wrapper for margining functions */ 24*c2e0c6b5SAndroid Build Coastguard Worker struct margin_dev { 25*c2e0c6b5SAndroid Build Coastguard Worker struct pci_dev *dev; 26*c2e0c6b5SAndroid Build Coastguard Worker int lmr_cap_addr; 27*c2e0c6b5SAndroid Build Coastguard Worker u8 neg_width; 28*c2e0c6b5SAndroid Build Coastguard Worker u8 max_width; 29*c2e0c6b5SAndroid Build Coastguard Worker u8 retimers_n; 30*c2e0c6b5SAndroid Build Coastguard Worker u8 link_speed; 31*c2e0c6b5SAndroid Build Coastguard Worker 32*c2e0c6b5SAndroid Build Coastguard Worker enum margin_hw hw; 33*c2e0c6b5SAndroid Build Coastguard Worker 34*c2e0c6b5SAndroid Build Coastguard Worker /* Saved Device settings to restore after margining */ 35*c2e0c6b5SAndroid Build Coastguard Worker u8 aspm; 36*c2e0c6b5SAndroid Build Coastguard Worker bool hasd; // Hardware Autonomous Speed Disable 37*c2e0c6b5SAndroid Build Coastguard Worker bool hawd; // Hardware Autonomous Width Disable 38*c2e0c6b5SAndroid Build Coastguard Worker }; 39*c2e0c6b5SAndroid Build Coastguard Worker 40*c2e0c6b5SAndroid Build Coastguard Worker /* Specification Revision 5.0 Table 8-11 */ 41*c2e0c6b5SAndroid Build Coastguard Worker struct margin_params { 42*c2e0c6b5SAndroid Build Coastguard Worker bool ind_error_sampler; 43*c2e0c6b5SAndroid Build Coastguard Worker bool sample_report_method; 44*c2e0c6b5SAndroid Build Coastguard Worker bool ind_left_right_tim; 45*c2e0c6b5SAndroid Build Coastguard Worker bool ind_up_down_volt; 46*c2e0c6b5SAndroid Build Coastguard Worker bool volt_support; 47*c2e0c6b5SAndroid Build Coastguard Worker 48*c2e0c6b5SAndroid Build Coastguard Worker u8 max_lanes; 49*c2e0c6b5SAndroid Build Coastguard Worker 50*c2e0c6b5SAndroid Build Coastguard Worker u8 timing_steps; 51*c2e0c6b5SAndroid Build Coastguard Worker u8 timing_offset; 52*c2e0c6b5SAndroid Build Coastguard Worker 53*c2e0c6b5SAndroid Build Coastguard Worker u8 volt_steps; 54*c2e0c6b5SAndroid Build Coastguard Worker u8 volt_offset; 55*c2e0c6b5SAndroid Build Coastguard Worker 56*c2e0c6b5SAndroid Build Coastguard Worker u8 sample_rate_v; 57*c2e0c6b5SAndroid Build Coastguard Worker u8 sample_rate_t; 58*c2e0c6b5SAndroid Build Coastguard Worker }; 59*c2e0c6b5SAndroid Build Coastguard Worker 60*c2e0c6b5SAndroid Build Coastguard Worker /* Step Margin Execution Status - Step command response */ 61*c2e0c6b5SAndroid Build Coastguard Worker enum margin_step_exec_sts { 62*c2e0c6b5SAndroid Build Coastguard Worker MARGIN_NAK = 0, // NAK/Set up for margin 63*c2e0c6b5SAndroid Build Coastguard Worker MARGIN_LIM, // Too many errors (device limit) 64*c2e0c6b5SAndroid Build Coastguard Worker MARGIN_THR // Test threshold has been reached 65*c2e0c6b5SAndroid Build Coastguard Worker }; 66*c2e0c6b5SAndroid Build Coastguard Worker 67*c2e0c6b5SAndroid Build Coastguard Worker enum margin_dir { VOLT_UP = 0, VOLT_DOWN, TIM_LEFT, TIM_RIGHT }; 68*c2e0c6b5SAndroid Build Coastguard Worker 69*c2e0c6b5SAndroid Build Coastguard Worker /* Margining results of one lane of the receiver */ 70*c2e0c6b5SAndroid Build Coastguard Worker struct margin_res_lane { 71*c2e0c6b5SAndroid Build Coastguard Worker u8 lane; 72*c2e0c6b5SAndroid Build Coastguard Worker u8 steps[4]; 73*c2e0c6b5SAndroid Build Coastguard Worker enum margin_step_exec_sts statuses[4]; 74*c2e0c6b5SAndroid Build Coastguard Worker }; 75*c2e0c6b5SAndroid Build Coastguard Worker 76*c2e0c6b5SAndroid Build Coastguard Worker /* Reason not to run margining test on the Link/Receiver */ 77*c2e0c6b5SAndroid Build Coastguard Worker enum margin_test_status { 78*c2e0c6b5SAndroid Build Coastguard Worker MARGIN_TEST_OK = 0, 79*c2e0c6b5SAndroid Build Coastguard Worker MARGIN_TEST_READY_BIT, 80*c2e0c6b5SAndroid Build Coastguard Worker MARGIN_TEST_CAPS, 81*c2e0c6b5SAndroid Build Coastguard Worker 82*c2e0c6b5SAndroid Build Coastguard Worker // Couldn't run test 83*c2e0c6b5SAndroid Build Coastguard Worker MARGIN_TEST_PREREQS, 84*c2e0c6b5SAndroid Build Coastguard Worker MARGIN_TEST_ARGS_LANES, 85*c2e0c6b5SAndroid Build Coastguard Worker MARGIN_TEST_ARGS_RECVS, 86*c2e0c6b5SAndroid Build Coastguard Worker MARGIN_TEST_ASPM 87*c2e0c6b5SAndroid Build Coastguard Worker }; 88*c2e0c6b5SAndroid Build Coastguard Worker 89*c2e0c6b5SAndroid Build Coastguard Worker /* All lanes Receiver results */ 90*c2e0c6b5SAndroid Build Coastguard Worker struct margin_results { 91*c2e0c6b5SAndroid Build Coastguard Worker u8 recvn; // Receiver Number; from 1 to 6 92*c2e0c6b5SAndroid Build Coastguard Worker struct margin_params params; 93*c2e0c6b5SAndroid Build Coastguard Worker bool lane_reversal; 94*c2e0c6b5SAndroid Build Coastguard Worker u8 link_speed; 95*c2e0c6b5SAndroid Build Coastguard Worker 96*c2e0c6b5SAndroid Build Coastguard Worker enum margin_test_status test_status; 97*c2e0c6b5SAndroid Build Coastguard Worker 98*c2e0c6b5SAndroid Build Coastguard Worker /* Used to convert steps to physical quantity. 99*c2e0c6b5SAndroid Build Coastguard Worker Calculated from MaxOffset and NumSteps */ 100*c2e0c6b5SAndroid Build Coastguard Worker double tim_coef; // from steps to % UI 101*c2e0c6b5SAndroid Build Coastguard Worker double volt_coef; 102*c2e0c6b5SAndroid Build Coastguard Worker 103*c2e0c6b5SAndroid Build Coastguard Worker bool tim_off_reported; 104*c2e0c6b5SAndroid Build Coastguard Worker bool volt_off_reported; 105*c2e0c6b5SAndroid Build Coastguard Worker 106*c2e0c6b5SAndroid Build Coastguard Worker u8 lanes_n; 107*c2e0c6b5SAndroid Build Coastguard Worker struct margin_res_lane *lanes; 108*c2e0c6b5SAndroid Build Coastguard Worker }; 109*c2e0c6b5SAndroid Build Coastguard Worker 110*c2e0c6b5SAndroid Build Coastguard Worker /* pcilmr arguments */ 111*c2e0c6b5SAndroid Build Coastguard Worker 112*c2e0c6b5SAndroid Build Coastguard Worker // Common args 113*c2e0c6b5SAndroid Build Coastguard Worker struct margin_com_args { 114*c2e0c6b5SAndroid Build Coastguard Worker u8 error_limit; // [0; 63] 115*c2e0c6b5SAndroid Build Coastguard Worker bool run_margin; // Or print params only 116*c2e0c6b5SAndroid Build Coastguard Worker u8 verbosity; // 0 - basic; 117*c2e0c6b5SAndroid Build Coastguard Worker // 1 - add info about remaining time and lanes in progress during margining 118*c2e0c6b5SAndroid Build Coastguard Worker u64 steps_utility; // For ETA logging 119*c2e0c6b5SAndroid Build Coastguard Worker bool save_csv; 120*c2e0c6b5SAndroid Build Coastguard Worker char *dir_for_csv; 121*c2e0c6b5SAndroid Build Coastguard Worker u8 dwell_time; 122*c2e0c6b5SAndroid Build Coastguard Worker }; 123*c2e0c6b5SAndroid Build Coastguard Worker 124*c2e0c6b5SAndroid Build Coastguard Worker struct margin_recv_args { 125*c2e0c6b5SAndroid Build Coastguard Worker // Grading options 126*c2e0c6b5SAndroid Build Coastguard Worker struct { 127*c2e0c6b5SAndroid Build Coastguard Worker bool valid; 128*c2e0c6b5SAndroid Build Coastguard Worker double criteria; // in ps/mV 129*c2e0c6b5SAndroid Build Coastguard Worker bool one_side_is_whole; 130*c2e0c6b5SAndroid Build Coastguard Worker } t, v; 131*c2e0c6b5SAndroid Build Coastguard Worker }; 132*c2e0c6b5SAndroid Build Coastguard Worker 133*c2e0c6b5SAndroid Build Coastguard Worker struct margin_link_args { 134*c2e0c6b5SAndroid Build Coastguard Worker struct margin_com_args *common; 135*c2e0c6b5SAndroid Build Coastguard Worker u8 steps_t; // 0 == use NumTimingSteps 136*c2e0c6b5SAndroid Build Coastguard Worker u8 steps_v; // 0 == use NumVoltageSteps 137*c2e0c6b5SAndroid Build Coastguard Worker u8 parallel_lanes; // [1; MaxLanes + 1] 138*c2e0c6b5SAndroid Build Coastguard Worker u8 recvs[6]; // Receivers Numbers 139*c2e0c6b5SAndroid Build Coastguard Worker u8 recvs_n; // 0 == margin all available receivers 140*c2e0c6b5SAndroid Build Coastguard Worker struct margin_recv_args recv_args[6]; 141*c2e0c6b5SAndroid Build Coastguard Worker u8 lanes[32]; // Lanes to Margin 142*c2e0c6b5SAndroid Build Coastguard Worker u8 lanes_n; // 0 == margin all available lanes 143*c2e0c6b5SAndroid Build Coastguard Worker }; 144*c2e0c6b5SAndroid Build Coastguard Worker 145*c2e0c6b5SAndroid Build Coastguard Worker struct margin_link { 146*c2e0c6b5SAndroid Build Coastguard Worker struct margin_dev down_port; 147*c2e0c6b5SAndroid Build Coastguard Worker struct margin_dev up_port; 148*c2e0c6b5SAndroid Build Coastguard Worker struct margin_link_args args; 149*c2e0c6b5SAndroid Build Coastguard Worker }; 150*c2e0c6b5SAndroid Build Coastguard Worker 151*c2e0c6b5SAndroid Build Coastguard Worker /* Receiver structure */ 152*c2e0c6b5SAndroid Build Coastguard Worker struct margin_recv { 153*c2e0c6b5SAndroid Build Coastguard Worker struct margin_dev *dev; 154*c2e0c6b5SAndroid Build Coastguard Worker u8 recvn; // Receiver Number; from 1 to 6 155*c2e0c6b5SAndroid Build Coastguard Worker bool lane_reversal; 156*c2e0c6b5SAndroid Build Coastguard Worker struct margin_params *params; 157*c2e0c6b5SAndroid Build Coastguard Worker 158*c2e0c6b5SAndroid Build Coastguard Worker u8 parallel_lanes; 159*c2e0c6b5SAndroid Build Coastguard Worker u8 error_limit; 160*c2e0c6b5SAndroid Build Coastguard Worker u8 dwell_time; 161*c2e0c6b5SAndroid Build Coastguard Worker }; 162*c2e0c6b5SAndroid Build Coastguard Worker 163*c2e0c6b5SAndroid Build Coastguard Worker struct margin_lanes_data { 164*c2e0c6b5SAndroid Build Coastguard Worker struct margin_recv *recv; 165*c2e0c6b5SAndroid Build Coastguard Worker 166*c2e0c6b5SAndroid Build Coastguard Worker struct margin_res_lane *results; 167*c2e0c6b5SAndroid Build Coastguard Worker u8 *lanes_numbers; 168*c2e0c6b5SAndroid Build Coastguard Worker u8 lanes_n; 169*c2e0c6b5SAndroid Build Coastguard Worker 170*c2e0c6b5SAndroid Build Coastguard Worker bool ind; 171*c2e0c6b5SAndroid Build Coastguard Worker enum margin_dir dir; 172*c2e0c6b5SAndroid Build Coastguard Worker 173*c2e0c6b5SAndroid Build Coastguard Worker u8 steps_lane_done; 174*c2e0c6b5SAndroid Build Coastguard Worker u8 steps_lane_total; 175*c2e0c6b5SAndroid Build Coastguard Worker u64 *steps_utility; 176*c2e0c6b5SAndroid Build Coastguard Worker 177*c2e0c6b5SAndroid Build Coastguard Worker u8 verbosity; 178*c2e0c6b5SAndroid Build Coastguard Worker }; 179*c2e0c6b5SAndroid Build Coastguard Worker 180*c2e0c6b5SAndroid Build Coastguard Worker /* margin_args */ 181*c2e0c6b5SAndroid Build Coastguard Worker 182*c2e0c6b5SAndroid Build Coastguard Worker enum margin_mode { MARGIN, FULL, SCAN }; 183*c2e0c6b5SAndroid Build Coastguard Worker 184*c2e0c6b5SAndroid Build Coastguard Worker extern const char *usage; 185*c2e0c6b5SAndroid Build Coastguard Worker 186*c2e0c6b5SAndroid Build Coastguard Worker struct margin_link *margin_parse_util_args(struct pci_access *pacc, int argc, char **argv, 187*c2e0c6b5SAndroid Build Coastguard Worker enum margin_mode mode, u8 *links_n); 188*c2e0c6b5SAndroid Build Coastguard Worker 189*c2e0c6b5SAndroid Build Coastguard Worker /* margin_hw */ 190*c2e0c6b5SAndroid Build Coastguard Worker 191*c2e0c6b5SAndroid Build Coastguard Worker bool margin_port_is_down(struct pci_dev *dev); 192*c2e0c6b5SAndroid Build Coastguard Worker 193*c2e0c6b5SAndroid Build Coastguard Worker /* Results through down/up ports */ 194*c2e0c6b5SAndroid Build Coastguard Worker bool margin_find_pair(struct pci_access *pacc, struct pci_dev *dev, struct pci_dev **down_port, 195*c2e0c6b5SAndroid Build Coastguard Worker struct pci_dev **up_port); 196*c2e0c6b5SAndroid Build Coastguard Worker 197*c2e0c6b5SAndroid Build Coastguard Worker /* Verify that devices form the link with 16 GT/s or 32 GT/s data rate */ 198*c2e0c6b5SAndroid Build Coastguard Worker bool margin_verify_link(struct pci_dev *down_port, struct pci_dev *up_port); 199*c2e0c6b5SAndroid Build Coastguard Worker 200*c2e0c6b5SAndroid Build Coastguard Worker /* Check Margining Ready bit from Margining Port Status Register */ 201*c2e0c6b5SAndroid Build Coastguard Worker bool margin_check_ready_bit(struct pci_dev *dev); 202*c2e0c6b5SAndroid Build Coastguard Worker 203*c2e0c6b5SAndroid Build Coastguard Worker /* Verify link and fill wrappers */ 204*c2e0c6b5SAndroid Build Coastguard Worker bool margin_fill_link(struct pci_dev *down_port, struct pci_dev *up_port, 205*c2e0c6b5SAndroid Build Coastguard Worker struct margin_link *wrappers); 206*c2e0c6b5SAndroid Build Coastguard Worker 207*c2e0c6b5SAndroid Build Coastguard Worker /* Disable ASPM, set Hardware Autonomous Speed/Width Disable bits */ 208*c2e0c6b5SAndroid Build Coastguard Worker bool margin_prep_link(struct margin_link *link); 209*c2e0c6b5SAndroid Build Coastguard Worker 210*c2e0c6b5SAndroid Build Coastguard Worker /* Restore ASPM, Hardware Autonomous Speed/Width settings */ 211*c2e0c6b5SAndroid Build Coastguard Worker void margin_restore_link(struct margin_link *link); 212*c2e0c6b5SAndroid Build Coastguard Worker 213*c2e0c6b5SAndroid Build Coastguard Worker /* margin */ 214*c2e0c6b5SAndroid Build Coastguard Worker 215*c2e0c6b5SAndroid Build Coastguard Worker /* Fill margin_params without calling other functions */ 216*c2e0c6b5SAndroid Build Coastguard Worker bool margin_read_params(struct pci_access *pacc, struct pci_dev *dev, u8 recvn, 217*c2e0c6b5SAndroid Build Coastguard Worker struct margin_params *params); 218*c2e0c6b5SAndroid Build Coastguard Worker 219*c2e0c6b5SAndroid Build Coastguard Worker enum margin_test_status margin_process_args(struct margin_link *link); 220*c2e0c6b5SAndroid Build Coastguard Worker 221*c2e0c6b5SAndroid Build Coastguard Worker /* Awaits that links are prepared through process_args. 222*c2e0c6b5SAndroid Build Coastguard Worker Returns number of margined Receivers through recvs_n */ 223*c2e0c6b5SAndroid Build Coastguard Worker struct margin_results *margin_test_link(struct margin_link *link, u8 *recvs_n); 224*c2e0c6b5SAndroid Build Coastguard Worker 225*c2e0c6b5SAndroid Build Coastguard Worker void margin_free_results(struct margin_results *results, u8 results_n); 226*c2e0c6b5SAndroid Build Coastguard Worker 227*c2e0c6b5SAndroid Build Coastguard Worker /* margin_log */ 228*c2e0c6b5SAndroid Build Coastguard Worker 229*c2e0c6b5SAndroid Build Coastguard Worker extern bool margin_global_logging; 230*c2e0c6b5SAndroid Build Coastguard Worker extern bool margin_print_domain; 231*c2e0c6b5SAndroid Build Coastguard Worker 232*c2e0c6b5SAndroid Build Coastguard Worker void margin_log(char *format, ...); 233*c2e0c6b5SAndroid Build Coastguard Worker 234*c2e0c6b5SAndroid Build Coastguard Worker /* b:d.f -> b:d.f */ 235*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_bdfs(struct pci_dev *down_port, struct pci_dev *up_port); 236*c2e0c6b5SAndroid Build Coastguard Worker void margin_gen_bdfs(struct pci_dev *down_port, struct pci_dev *up_port, char *dest, size_t maxlen); 237*c2e0c6b5SAndroid Build Coastguard Worker 238*c2e0c6b5SAndroid Build Coastguard Worker /* Print Link header (bdfs, neg_width, speed) */ 239*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_link(struct margin_link *link); 240*c2e0c6b5SAndroid Build Coastguard Worker 241*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_params(struct margin_params *params); 242*c2e0c6b5SAndroid Build Coastguard Worker 243*c2e0c6b5SAndroid Build Coastguard Worker /* Print receiver number */ 244*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_recvn(struct margin_recv *recv); 245*c2e0c6b5SAndroid Build Coastguard Worker 246*c2e0c6b5SAndroid Build Coastguard Worker /* Print full info from Receiver struct */ 247*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_receiver(struct margin_recv *recv); 248*c2e0c6b5SAndroid Build Coastguard Worker 249*c2e0c6b5SAndroid Build Coastguard Worker /* Margining in progress log */ 250*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_margining(struct margin_lanes_data arg); 251*c2e0c6b5SAndroid Build Coastguard Worker 252*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_hw_quirks(struct margin_recv *recv); 253*c2e0c6b5SAndroid Build Coastguard Worker 254*c2e0c6b5SAndroid Build Coastguard Worker /* margin_results */ 255*c2e0c6b5SAndroid Build Coastguard Worker 256*c2e0c6b5SAndroid Build Coastguard Worker // Min values are taken from PCIe Base Spec Rev. 5.0 Section 8.4.2. 257*c2e0c6b5SAndroid Build Coastguard Worker // Rec values are based on PCIe Arch PHY Test Spec Rev 5.0 258*c2e0c6b5SAndroid Build Coastguard Worker // (Transmitter Electrical Compliance) 259*c2e0c6b5SAndroid Build Coastguard Worker 260*c2e0c6b5SAndroid Build Coastguard Worker // values in ps 261*c2e0c6b5SAndroid Build Coastguard Worker static const double margin_ew_min[] = { 18.75, 9.375 }; 262*c2e0c6b5SAndroid Build Coastguard Worker static const double margin_ew_rec[] = { 23.75, 10.1565 }; 263*c2e0c6b5SAndroid Build Coastguard Worker 264*c2e0c6b5SAndroid Build Coastguard Worker static const double margin_eh_min[] = { 15, 15 }; 265*c2e0c6b5SAndroid Build Coastguard Worker static const double margin_eh_rec[] = { 21, 19.75 }; 266*c2e0c6b5SAndroid Build Coastguard Worker 267*c2e0c6b5SAndroid Build Coastguard Worker void margin_results_print_brief(struct margin_results *results, u8 recvs_n, 268*c2e0c6b5SAndroid Build Coastguard Worker struct margin_link_args *args); 269*c2e0c6b5SAndroid Build Coastguard Worker 270*c2e0c6b5SAndroid Build Coastguard Worker void margin_results_save_csv(struct margin_results *results, u8 recvs_n, struct margin_link *link); 271*c2e0c6b5SAndroid Build Coastguard Worker 272*c2e0c6b5SAndroid Build Coastguard Worker #endif 273