@@ -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;