-enum mode { MARGIN, FULL, SCAN };
-
-static const char usage_msg[]
- = "! Utility requires preliminary preparation of the system. Refer to the pcilmr man page !\n\n"
- "Usage:\n"
- "pcilmr [--margin] [<margining options>] <downstream component> ...\n"
- "pcilmr --full [<margining options>]\n"
- "pcilmr --scan\n\n"
- "Device Specifier:\n"
- "<device/component>:\t[<domain>:]<bus>:<dev>.<func>\n\n"
- "Modes:\n"
- "--margin\t\tMargin selected Links\n"
- "--full\t\t\tMargin all ready for testing Links in the system (one by one)\n"
- "--scan\t\t\tScan for Links available for margining\n\n"
- "Margining options:\n\n"
- "Margining Test settings:\n"
- "-c\t\t\tPrint Device Lane Margining Capabilities only. Do not run margining.\n"
- "-l <lane>[,<lane>...]\tSpecify lanes for margining. Default: all link lanes.\n"
- "\t\t\tRemember that Device may use Lane Reversal for Lane numbering.\n"
- "\t\t\tHowever, utility uses logical lane numbers in arguments and for logging.\n"
- "\t\t\tUtility will automatically determine Lane Reversal and tune its calls.\n"
- "-e <errors>\t\tSpecify Error Count Limit for margining. Default: 4.\n"
- "-r <recvn>[,<recvn>...]\tSpecify Receivers to select margining targets.\n"
- "\t\t\tDefault: all available Receivers (including Retimers).\n"
- "-p <parallel_lanes>\tSpecify number of lanes to margin simultaneously.\n"
- "\t\t\tDefault: 1.\n"
- "\t\t\tAccording to spec it's possible for Receiver to margin up\n"
- "\t\t\tto MaxLanes + 1 lanes simultaneously, but usually this works\n"
- "\t\t\tbad, so this option is for experiments mostly.\n"
- "-T\t\t\tTime Margining will continue until the Error Count is no more\n"
- "\t\t\tthan an Error Count Limit. Use this option to find Link limit.\n"
- "-V\t\t\tSame as -T option, but for Voltage.\n"
- "-t <steps>\t\tSpecify maximum number of steps for Time Margining.\n"
- "-v <steps>\t\tSpecify maximum number of steps for Voltage Margining.\n"
- "Use only one of -T/-t options at the same time (same for -V/-v).\n"
- "Without these options utility will use MaxSteps from Device\n"
- "capabilities as test limit.\n\n"
- "Margining Log settings:\n"
- "-o <directory>\t\tSave margining results in csv form into the\n"
- "\t\t\tspecified directory. Utility will generate file with the\n"
- "\t\t\tname in form of 'lmr_<downstream component>_Rx#_<timestamp>.csv'\n"
- "\t\t\tfor each successfully tested receiver.\n";
-
-static struct pci_dev *
-dev_for_filter(struct pci_access *pacc, char *filter)
-{
- struct pci_filter pci_filter;
- pci_filter_init(pacc, &pci_filter);
- if (pci_filter_parse_slot(&pci_filter, filter))
- die("Invalid device ID: %s\n", filter);
-
- if (pci_filter.bus == -1 || pci_filter.slot == -1 || pci_filter.func == -1)
- die("Invalid device ID: %s\n", filter);
-
- if (pci_filter.domain == -1)
- pci_filter.domain = 0;
-
- for (struct pci_dev *p = pacc->devices; p; p = p->next)
- {
- if (pci_filter_match(&pci_filter, p))
- return p;
- }
-
- die("No such PCI device: %s or you don't have enough privileges.\n", filter);
-}
-
-static struct pci_dev *
-find_down_port_for_up(struct pci_access *pacc, struct pci_dev *up)
-{
- struct pci_dev *down = NULL;
- for (struct pci_dev *p = pacc->devices; p; p = p->next)
- {
- if (pci_read_byte(p, PCI_SECONDARY_BUS) == up->bus && up->domain == p->domain)
- {
- down = p;
- break;
- }
- }
- return down;
-}
-
-static u8
-parse_csv_arg(char *arg, u8 *vals)
-{
- u8 cnt = 0;
- char *token = strtok(arg, ",");
- while (token)
- {
- vals[cnt] = atoi(token);
- cnt++;
- token = strtok(NULL, ",");
- }
- return cnt;
-}
-