Reviewed-by: Sergei Miroshnichenko <s.miroshnichenko@xxxxxxxxx> Signed-off-by: Nikita Proshkin <n.proshkin@xxxxxxxxx> --- pcilmr.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/pcilmr.c b/pcilmr.c index 3c2f250..43e791d 100644 --- a/pcilmr.c +++ b/pcilmr.c @@ -17,17 +17,19 @@ const char program_name[] = "pcilmr"; -enum mode { MARGIN, FULL }; +enum mode { MARGIN, FULL, SCAN }; static const char usage_msg[] = "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" @@ -106,6 +108,36 @@ parse_csv_arg(char *arg, u8 *vals) return cnt; } +static void +scan_links(struct pci_access *pacc, bool only_ready) +{ + if (only_ready) + printf("Links ready for margining:\n"); + else + printf("Links with Lane Margining at the Receiver capabilities:\n"); + bool flag = true; + for (struct pci_dev *up = pacc->devices; up; up = up->next) + { + if (pci_find_cap(up, PCI_EXT_CAP_ID_LMR, PCI_CAP_EXTENDED)) + { + struct pci_dev *down = find_down_port_for_up(pacc, up); + + if (down && margin_verify_link(down, up)) + { + margin_log_bdfs(down, up); + if (!only_ready && (margin_check_ready_bit(down) || margin_check_ready_bit(up))) + printf(" - Ready"); + printf("\n"); + flag = false; + } + } + } + if (flag) + printf("Links not found or you don't have enough privileges.\n"); + pci_cleanup(pacc); + exit(0); +} + static u8 find_ready_links(struct pci_access *pacc, struct pci_dev **down_ports, struct pci_dev **up_ports, bool cnt_only) @@ -185,7 +217,8 @@ main(int argc, char **argv) struct option long_options[] = { { .name = "margin", .has_arg = no_argument, .flag = NULL, .val = 0 }, - { .name = "full", .has_arg = no_argument, .flag = NULL, .val = 1 }, + { .name = "scan", .has_arg = no_argument, .flag = NULL, .val = 1 }, + { .name = "full", .has_arg = no_argument, .flag = NULL, .val = 2 }, { 0, 0, 0, 0 } }; int c; @@ -199,6 +232,12 @@ main(int argc, char **argv) mode = MARGIN; break; case 1: + mode = SCAN; + if (optind == argc) + scan_links(pacc, false); + optind--; + break; + case 2: mode = FULL; break; default: /* unknown option symbol */ -- 2.34.1