xref: /aosp_15_r20/external/pciutils/pcilmr.c (revision c2e0c6b56a71da9abe8df5c8348fb3eb5c2c9251)
1*c2e0c6b5SAndroid Build Coastguard Worker /*
2*c2e0c6b5SAndroid Build Coastguard Worker  *	The PCI Utilities -- Margining utility main function
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 #include <memory.h>
12*c2e0c6b5SAndroid Build Coastguard Worker #include <stdio.h>
13*c2e0c6b5SAndroid Build Coastguard Worker #include <stdlib.h>
14*c2e0c6b5SAndroid Build Coastguard Worker 
15*c2e0c6b5SAndroid Build Coastguard Worker #include "lmr/lmr.h"
16*c2e0c6b5SAndroid Build Coastguard Worker 
17*c2e0c6b5SAndroid Build Coastguard Worker const char program_name[] = "pcilmr";
18*c2e0c6b5SAndroid Build Coastguard Worker 
19*c2e0c6b5SAndroid Build Coastguard Worker static void
scan_links(struct pci_access * pacc,bool only_ready)20*c2e0c6b5SAndroid Build Coastguard Worker scan_links(struct pci_access *pacc, bool only_ready)
21*c2e0c6b5SAndroid Build Coastguard Worker {
22*c2e0c6b5SAndroid Build Coastguard Worker   if (only_ready)
23*c2e0c6b5SAndroid Build Coastguard Worker     printf("Links ready for margining:\n");
24*c2e0c6b5SAndroid Build Coastguard Worker   else
25*c2e0c6b5SAndroid Build Coastguard Worker     printf("Links with Lane Margining at the Receiver capabilities:\n");
26*c2e0c6b5SAndroid Build Coastguard Worker   bool flag = true;
27*c2e0c6b5SAndroid Build Coastguard Worker   for (struct pci_dev *p = pacc->devices; p; p = p->next)
28*c2e0c6b5SAndroid Build Coastguard Worker     {
29*c2e0c6b5SAndroid Build Coastguard Worker       if (pci_find_cap(p, PCI_EXT_CAP_ID_LMR, PCI_CAP_EXTENDED) && margin_port_is_down(p))
30*c2e0c6b5SAndroid Build Coastguard Worker         {
31*c2e0c6b5SAndroid Build Coastguard Worker           struct pci_dev *down = NULL;
32*c2e0c6b5SAndroid Build Coastguard Worker           struct pci_dev *up = NULL;
33*c2e0c6b5SAndroid Build Coastguard Worker           margin_find_pair(pacc, p, &down, &up);
34*c2e0c6b5SAndroid Build Coastguard Worker 
35*c2e0c6b5SAndroid Build Coastguard Worker           if (down && margin_verify_link(down, up))
36*c2e0c6b5SAndroid Build Coastguard Worker             {
37*c2e0c6b5SAndroid Build Coastguard Worker               margin_log_bdfs(down, up);
38*c2e0c6b5SAndroid Build Coastguard Worker               if (!only_ready && (margin_check_ready_bit(down) || margin_check_ready_bit(up)))
39*c2e0c6b5SAndroid Build Coastguard Worker                 printf(" - Ready");
40*c2e0c6b5SAndroid Build Coastguard Worker               printf("\n");
41*c2e0c6b5SAndroid Build Coastguard Worker               flag = false;
42*c2e0c6b5SAndroid Build Coastguard Worker             }
43*c2e0c6b5SAndroid Build Coastguard Worker         }
44*c2e0c6b5SAndroid Build Coastguard Worker     }
45*c2e0c6b5SAndroid Build Coastguard Worker   if (flag)
46*c2e0c6b5SAndroid Build Coastguard Worker     printf("Links not found or you don't have enough privileges.\n");
47*c2e0c6b5SAndroid Build Coastguard Worker   pci_cleanup(pacc);
48*c2e0c6b5SAndroid Build Coastguard Worker   exit(0);
49*c2e0c6b5SAndroid Build Coastguard Worker }
50*c2e0c6b5SAndroid Build Coastguard Worker 
51*c2e0c6b5SAndroid Build Coastguard Worker int
main(int argc,char ** argv)52*c2e0c6b5SAndroid Build Coastguard Worker main(int argc, char **argv)
53*c2e0c6b5SAndroid Build Coastguard Worker {
54*c2e0c6b5SAndroid Build Coastguard Worker   struct pci_access *pacc;
55*c2e0c6b5SAndroid Build Coastguard Worker 
56*c2e0c6b5SAndroid Build Coastguard Worker   u8 links_n = 0;
57*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_link *links;
58*c2e0c6b5SAndroid Build Coastguard Worker   bool *checks_status_ports;
59*c2e0c6b5SAndroid Build Coastguard Worker 
60*c2e0c6b5SAndroid Build Coastguard Worker   enum margin_mode mode;
61*c2e0c6b5SAndroid Build Coastguard Worker 
62*c2e0c6b5SAndroid Build Coastguard Worker   /* each link has several receivers -> several results */
63*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_results **results;
64*c2e0c6b5SAndroid Build Coastguard Worker   u8 *results_n;
65*c2e0c6b5SAndroid Build Coastguard Worker 
66*c2e0c6b5SAndroid Build Coastguard Worker   pacc = pci_alloc();
67*c2e0c6b5SAndroid Build Coastguard Worker   pci_init(pacc);
68*c2e0c6b5SAndroid Build Coastguard Worker   pci_scan_bus(pacc);
69*c2e0c6b5SAndroid Build Coastguard Worker 
70*c2e0c6b5SAndroid Build Coastguard Worker   margin_print_domain = false;
71*c2e0c6b5SAndroid Build Coastguard Worker   for (struct pci_dev *dev = pacc->devices; dev; dev = dev->next)
72*c2e0c6b5SAndroid Build Coastguard Worker     {
73*c2e0c6b5SAndroid Build Coastguard Worker       if (dev->domain != 0)
74*c2e0c6b5SAndroid Build Coastguard Worker         {
75*c2e0c6b5SAndroid Build Coastguard Worker           margin_print_domain = true;
76*c2e0c6b5SAndroid Build Coastguard Worker           break;
77*c2e0c6b5SAndroid Build Coastguard Worker         }
78*c2e0c6b5SAndroid Build Coastguard Worker     }
79*c2e0c6b5SAndroid Build Coastguard Worker 
80*c2e0c6b5SAndroid Build Coastguard Worker   margin_global_logging = true;
81*c2e0c6b5SAndroid Build Coastguard Worker 
82*c2e0c6b5SAndroid Build Coastguard Worker   struct option long_options[]
83*c2e0c6b5SAndroid Build Coastguard Worker     = { { .name = "margin", .has_arg = no_argument, .flag = NULL, .val = 0 },
84*c2e0c6b5SAndroid Build Coastguard Worker         { .name = "scan", .has_arg = no_argument, .flag = NULL, .val = 1 },
85*c2e0c6b5SAndroid Build Coastguard Worker         { .name = "full", .has_arg = no_argument, .flag = NULL, .val = 2 },
86*c2e0c6b5SAndroid Build Coastguard Worker         { 0, 0, 0, 0 } };
87*c2e0c6b5SAndroid Build Coastguard Worker 
88*c2e0c6b5SAndroid Build Coastguard Worker   opterr = 0;
89*c2e0c6b5SAndroid Build Coastguard Worker   int c;
90*c2e0c6b5SAndroid Build Coastguard Worker   c = getopt_long(argc, argv, "+", long_options, NULL);
91*c2e0c6b5SAndroid Build Coastguard Worker 
92*c2e0c6b5SAndroid Build Coastguard Worker   switch (c)
93*c2e0c6b5SAndroid Build Coastguard Worker     {
94*c2e0c6b5SAndroid Build Coastguard Worker       case -1: /* no options (strings like component are possible) */
95*c2e0c6b5SAndroid Build Coastguard Worker         /* FALLTHROUGH */
96*c2e0c6b5SAndroid Build Coastguard Worker       case 0:
97*c2e0c6b5SAndroid Build Coastguard Worker         mode = MARGIN;
98*c2e0c6b5SAndroid Build Coastguard Worker         break;
99*c2e0c6b5SAndroid Build Coastguard Worker       case 1:
100*c2e0c6b5SAndroid Build Coastguard Worker         mode = SCAN;
101*c2e0c6b5SAndroid Build Coastguard Worker         if (optind == argc)
102*c2e0c6b5SAndroid Build Coastguard Worker           scan_links(pacc, false);
103*c2e0c6b5SAndroid Build Coastguard Worker         else
104*c2e0c6b5SAndroid Build Coastguard Worker           die("Invalid arguments\n\n%s", usage);
105*c2e0c6b5SAndroid Build Coastguard Worker         break;
106*c2e0c6b5SAndroid Build Coastguard Worker       case 2:
107*c2e0c6b5SAndroid Build Coastguard Worker         mode = FULL;
108*c2e0c6b5SAndroid Build Coastguard Worker         break;
109*c2e0c6b5SAndroid Build Coastguard Worker       default: /* unknown option symbol */
110*c2e0c6b5SAndroid Build Coastguard Worker         mode = MARGIN;
111*c2e0c6b5SAndroid Build Coastguard Worker         optind--;
112*c2e0c6b5SAndroid Build Coastguard Worker         break;
113*c2e0c6b5SAndroid Build Coastguard Worker     }
114*c2e0c6b5SAndroid Build Coastguard Worker 
115*c2e0c6b5SAndroid Build Coastguard Worker   opterr = 1;
116*c2e0c6b5SAndroid Build Coastguard Worker 
117*c2e0c6b5SAndroid Build Coastguard Worker   links = margin_parse_util_args(pacc, argc, argv, mode, &links_n);
118*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_com_args *com_args = links[0].args.common;
119*c2e0c6b5SAndroid Build Coastguard Worker 
120*c2e0c6b5SAndroid Build Coastguard Worker   results = xmalloc(links_n * sizeof(*results));
121*c2e0c6b5SAndroid Build Coastguard Worker   results_n = xmalloc(links_n * sizeof(*results_n));
122*c2e0c6b5SAndroid Build Coastguard Worker   checks_status_ports = xmalloc(links_n * sizeof(*checks_status_ports));
123*c2e0c6b5SAndroid Build Coastguard Worker 
124*c2e0c6b5SAndroid Build Coastguard Worker   for (int i = 0; i < links_n; i++)
125*c2e0c6b5SAndroid Build Coastguard Worker     {
126*c2e0c6b5SAndroid Build Coastguard Worker       enum margin_test_status args_status;
127*c2e0c6b5SAndroid Build Coastguard Worker 
128*c2e0c6b5SAndroid Build Coastguard Worker       if ((args_status = margin_process_args(&links[i])) != MARGIN_TEST_OK)
129*c2e0c6b5SAndroid Build Coastguard Worker         {
130*c2e0c6b5SAndroid Build Coastguard Worker           checks_status_ports[i] = false;
131*c2e0c6b5SAndroid Build Coastguard Worker           results[i] = xmalloc(sizeof(*results[i]));
132*c2e0c6b5SAndroid Build Coastguard Worker           results[i]->test_status = args_status;
133*c2e0c6b5SAndroid Build Coastguard Worker           continue;
134*c2e0c6b5SAndroid Build Coastguard Worker         }
135*c2e0c6b5SAndroid Build Coastguard Worker 
136*c2e0c6b5SAndroid Build Coastguard Worker       checks_status_ports[i] = true;
137*c2e0c6b5SAndroid Build Coastguard Worker       struct margin_params params;
138*c2e0c6b5SAndroid Build Coastguard Worker       struct margin_link_args *link_args = &links[i].args;
139*c2e0c6b5SAndroid Build Coastguard Worker 
140*c2e0c6b5SAndroid Build Coastguard Worker       for (int j = 0; j < link_args->recvs_n; j++)
141*c2e0c6b5SAndroid Build Coastguard Worker         {
142*c2e0c6b5SAndroid Build Coastguard Worker           if (margin_read_params(
143*c2e0c6b5SAndroid Build Coastguard Worker                 pacc, link_args->recvs[j] == 6 ? links[i].up_port.dev : links[i].down_port.dev,
144*c2e0c6b5SAndroid Build Coastguard Worker                 link_args->recvs[j], &params))
145*c2e0c6b5SAndroid Build Coastguard Worker             {
146*c2e0c6b5SAndroid Build Coastguard Worker               u8 steps_t = link_args->steps_t ? link_args->steps_t : params.timing_steps;
147*c2e0c6b5SAndroid Build Coastguard Worker               u8 steps_v = link_args->steps_v ? link_args->steps_v : params.volt_steps;
148*c2e0c6b5SAndroid Build Coastguard Worker               u8 parallel_recv = link_args->parallel_lanes > params.max_lanes + 1 ?
149*c2e0c6b5SAndroid Build Coastguard Worker                                    params.max_lanes + 1 :
150*c2e0c6b5SAndroid Build Coastguard Worker                                    link_args->parallel_lanes;
151*c2e0c6b5SAndroid Build Coastguard Worker 
152*c2e0c6b5SAndroid Build Coastguard Worker               u8 step_multiplier
153*c2e0c6b5SAndroid Build Coastguard Worker                 = link_args->lanes_n / parallel_recv + ((link_args->lanes_n % parallel_recv) > 0);
154*c2e0c6b5SAndroid Build Coastguard Worker 
155*c2e0c6b5SAndroid Build Coastguard Worker               com_args->steps_utility += steps_t * step_multiplier;
156*c2e0c6b5SAndroid Build Coastguard Worker               if (params.ind_left_right_tim)
157*c2e0c6b5SAndroid Build Coastguard Worker                 com_args->steps_utility += steps_t * step_multiplier;
158*c2e0c6b5SAndroid Build Coastguard Worker               if (params.volt_support)
159*c2e0c6b5SAndroid Build Coastguard Worker                 {
160*c2e0c6b5SAndroid Build Coastguard Worker                   com_args->steps_utility += steps_v * step_multiplier;
161*c2e0c6b5SAndroid Build Coastguard Worker                   if (params.ind_up_down_volt)
162*c2e0c6b5SAndroid Build Coastguard Worker                     com_args->steps_utility += steps_v * step_multiplier;
163*c2e0c6b5SAndroid Build Coastguard Worker                 }
164*c2e0c6b5SAndroid Build Coastguard Worker             }
165*c2e0c6b5SAndroid Build Coastguard Worker         }
166*c2e0c6b5SAndroid Build Coastguard Worker     }
167*c2e0c6b5SAndroid Build Coastguard Worker 
168*c2e0c6b5SAndroid Build Coastguard Worker   for (int i = 0; i < links_n; i++)
169*c2e0c6b5SAndroid Build Coastguard Worker     {
170*c2e0c6b5SAndroid Build Coastguard Worker       if (checks_status_ports[i])
171*c2e0c6b5SAndroid Build Coastguard Worker         results[i] = margin_test_link(&links[i], &results_n[i]);
172*c2e0c6b5SAndroid Build Coastguard Worker       else
173*c2e0c6b5SAndroid Build Coastguard Worker         {
174*c2e0c6b5SAndroid Build Coastguard Worker           results_n[i] = 1;
175*c2e0c6b5SAndroid Build Coastguard Worker           if (results[i]->test_status == MARGIN_TEST_ARGS_RECVS)
176*c2e0c6b5SAndroid Build Coastguard Worker             {
177*c2e0c6b5SAndroid Build Coastguard Worker               margin_log_link(&links[i]);
178*c2e0c6b5SAndroid Build Coastguard Worker               printf("\nInvalid RecNums specified.\n");
179*c2e0c6b5SAndroid Build Coastguard Worker             }
180*c2e0c6b5SAndroid Build Coastguard Worker           else if (results[i]->test_status == MARGIN_TEST_ARGS_LANES)
181*c2e0c6b5SAndroid Build Coastguard Worker             {
182*c2e0c6b5SAndroid Build Coastguard Worker               margin_log_link(&links[i]);
183*c2e0c6b5SAndroid Build Coastguard Worker               printf("\nInvalid lanes specified.\n");
184*c2e0c6b5SAndroid Build Coastguard Worker             }
185*c2e0c6b5SAndroid Build Coastguard Worker         }
186*c2e0c6b5SAndroid Build Coastguard Worker       printf("\n----\n\n");
187*c2e0c6b5SAndroid Build Coastguard Worker     }
188*c2e0c6b5SAndroid Build Coastguard Worker 
189*c2e0c6b5SAndroid Build Coastguard Worker   if (com_args->run_margin)
190*c2e0c6b5SAndroid Build Coastguard Worker     {
191*c2e0c6b5SAndroid Build Coastguard Worker       printf("Results:\n");
192*c2e0c6b5SAndroid Build Coastguard Worker       printf(
193*c2e0c6b5SAndroid Build Coastguard Worker         "Margining statuses:\nLIM -\tErrorCount exceeded Error Count Limit (found device limit)\n");
194*c2e0c6b5SAndroid Build Coastguard Worker       printf("NAK -\tDevice didn't execute last command, \n\tso result may be less reliable\n");
195*c2e0c6b5SAndroid Build Coastguard Worker       printf("THR -\tThe set (using the utility options) \n\tstep threshold has been reached\n\n");
196*c2e0c6b5SAndroid Build Coastguard Worker       printf("Notations:\nst - steps\n\n");
197*c2e0c6b5SAndroid Build Coastguard Worker 
198*c2e0c6b5SAndroid Build Coastguard Worker       for (int i = 0; i < links_n; i++)
199*c2e0c6b5SAndroid Build Coastguard Worker         {
200*c2e0c6b5SAndroid Build Coastguard Worker           printf("Link ");
201*c2e0c6b5SAndroid Build Coastguard Worker           margin_log_bdfs(links[i].down_port.dev, links[i].up_port.dev);
202*c2e0c6b5SAndroid Build Coastguard Worker           printf(":\n\n");
203*c2e0c6b5SAndroid Build Coastguard Worker           margin_results_print_brief(results[i], results_n[i], &links[i].args);
204*c2e0c6b5SAndroid Build Coastguard Worker           if (com_args->save_csv)
205*c2e0c6b5SAndroid Build Coastguard Worker             margin_results_save_csv(results[i], results_n[i], &links[i]);
206*c2e0c6b5SAndroid Build Coastguard Worker           printf("\n");
207*c2e0c6b5SAndroid Build Coastguard Worker         }
208*c2e0c6b5SAndroid Build Coastguard Worker     }
209*c2e0c6b5SAndroid Build Coastguard Worker 
210*c2e0c6b5SAndroid Build Coastguard Worker   for (int i = 0; i < links_n; i++)
211*c2e0c6b5SAndroid Build Coastguard Worker     margin_free_results(results[i], results_n[i]);
212*c2e0c6b5SAndroid Build Coastguard Worker   free(results_n);
213*c2e0c6b5SAndroid Build Coastguard Worker   free(results);
214*c2e0c6b5SAndroid Build Coastguard Worker   free(com_args);
215*c2e0c6b5SAndroid Build Coastguard Worker   free(links);
216*c2e0c6b5SAndroid Build Coastguard Worker   free(checks_status_ports);
217*c2e0c6b5SAndroid Build Coastguard Worker 
218*c2e0c6b5SAndroid Build Coastguard Worker   pci_cleanup(pacc);
219*c2e0c6b5SAndroid Build Coastguard Worker   return 0;
220*c2e0c6b5SAndroid Build Coastguard Worker }
221