Reviewed-by: Sergei Miroshnichenko <s.miroshnichenko@xxxxxxxxx> Signed-off-by: Nikita Proshkin <n.proshkin@xxxxxxxxx> --- pcilmr.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/pcilmr.c b/pcilmr.c index ed37a05..46b9f24 100644 --- a/pcilmr.c +++ b/pcilmr.c @@ -9,19 +9,22 @@ enum mode { MARGIN, - FULL + FULL, + SCAN }; static void usage(void) { printf("Usage:\n" "pcilmr [--margin] [<margining options>] <downstream component> ...\n" - "pcilmr --full [<margining options>]\n\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,7 +109,38 @@ static uint8_t parse_csv_arg(char *arg, uint8_t *lanes) return cnt; } -static uint8_t find_ready_links(struct pci_access *pacc, struct pci_dev **down_ports, +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 uint8_t find_ready_links(struct pci_access *pacc, struct pci_dev **down_ports, struct pci_dev **up_ports, bool cnt_only) { uint8_t cnt = 0; @@ -184,7 +218,8 @@ int 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; @@ -198,6 +233,12 @@ int 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*/ @@ -378,7 +419,7 @@ int main(int argc, char **argv) for (uint8_t j = 0; j < args[i].recvs_n; j++) { if (margin_read_params_standalone(pacc, - args[i].recvs[j] == 6 ? up_ports[i] : down_ports[i], + args[i].recvs[j] == 6 ? up_ports[i] : down_ports[i], args[i].recvs[j], &caps)) { uint8_t steps_t = steps_t_arg == -1 ? caps.timing_steps : steps_t_arg; -- 2.34.1