enum margin_hw { MARGIN_HW_DEFAULT, MARGIN_ICE_LAKE_RC };
// in ps
-static const double margin_ui[] = { 62.5, 31.25 };
+static const double margin_ui[] = { 62.5, 31.25, 31.25 };
/* PCI Device wrapper for margining functions */
struct margin_dev {
bool margin_find_pair(struct pci_access *pacc, struct pci_dev *dev, struct pci_dev **down_port,
struct pci_dev **up_port);
-/* Verify that devices form the link with 16 GT/s or 32 GT/s data rate */
+/* Verify that devices form the link with valid data rate */
bool margin_verify_link(struct pci_dev *down_port, struct pci_dev *up_port);
/* Check Margining Ready bit from Margining Port Status Register */
// (Transmitter Electrical Compliance)
// values in ps
-static const double margin_ew_min[] = { 18.75, 9.375 };
-static const double margin_ew_rec[] = { 23.75, 10.1565 };
+static const double margin_ew_min[] = { 18.75, 9.375, 9.375 };
+static const double margin_ew_rec[] = { 23.75, 10.1565, 10.1565 };
-static const double margin_eh_min[] = { 15, 15 };
-static const double margin_eh_rec[] = { 21, 19.75 };
+static const double margin_eh_min[] = { 15, 15, 5 };
+static const double margin_eh_rec[] = { 21, 19.75, 7 };
void margin_results_print_brief(struct margin_results *results, u8 recvs_n,
struct margin_link_args *args);
margin_find_pair(pacc, p, &down, &up);
if (down && margin_verify_link(down, up)
+ && pci_find_cap(up, PCI_EXT_CAP_ID_LMR, PCI_CAP_EXTENDED)
&& (margin_check_ready_bit(down) || margin_check_ready_bit(up)))
{
if (!cnt_only)
{
margin_gen_bdfs(down, up, err, sizeof(err));
die("Link %s is not ready for margining.\n"
- "Link data rate must be 16 GT/s or 32 GT/s.\n"
+ "Link data rate must be 16 GT/s, 32 GT/s, or 64 GT/s.\n"
"Downstream Component must be at D0 PM state.\n",
err);
}
return false;
if ((pci_read_word(down_port, cap->addr + PCI_EXP_LNKSTA) & PCI_EXP_LNKSTA_SPEED) < 4)
return false;
- if ((pci_read_word(down_port, cap->addr + PCI_EXP_LNKSTA) & PCI_EXP_LNKSTA_SPEED) > 5)
+ if ((pci_read_word(down_port, cap->addr + PCI_EXP_LNKSTA) & PCI_EXP_LNKSTA_SPEED) > 6)
return false;
u8 down_sec = pci_read_byte(down_port, PCI_SECONDARY_BUS);
memset(wrappers, 0, sizeof(*wrappers));
if (!margin_verify_link(down_port, up_port))
return false;
+ if (!pci_find_cap(down_port, PCI_EXT_CAP_ID_LMR, PCI_CAP_EXTENDED))
+ return false;
+ if (!pci_find_cap(up_port, PCI_EXT_CAP_ID_LMR, PCI_CAP_EXTENDED))
+ return false;
wrappers->down_port = fill_dev_wrapper(down_port);
wrappers->up_port = fill_dev_wrapper(up_port);
return true;
margin_log("Link ");
margin_log_bdfs(link->down_port.dev, link->up_port.dev);
margin_log("\nNegotiated Link Width: %d\n", link->down_port.neg_width);
- margin_log("Link Speed: %d.0 GT/s = Gen %d\n", (link->down_port.link_speed - 3) * 16,
+ margin_log("Link Speed: %d.0 GT/s = Gen %d\n", 16 << (link->down_port.link_speed - 4),
link->down_port.link_speed);
margin_log("Available receivers: ");
int receivers_n = 2 + 2 * link->down_port.retimers_n;
char *no_test_msgs[] = { "",
"Margining Ready bit is Clear",
"Error during caps reading",
- "Margining prerequisites are not satisfied (16/32 GT/s, D0)",
+ "Margining prerequisites are not satisfied (supported rate, D0)",
"Invalid lanes specified with arguments",
"Invalid receivers specified with arguments",
"Couldn't disable ASPM" };
struct pci_dev *up = NULL;
margin_find_pair(pacc, p, &down, &up);
- if (down && margin_verify_link(down, up))
+ if (down && margin_verify_link(down, up) && pci_find_cap(up, PCI_EXT_CAP_ID_LMR, PCI_CAP_EXTENDED))
{
margin_log_bdfs(down, up);
if (!only_ready && (margin_check_ready_bit(down) || margin_check_ready_bit(up)))