From: Nikita Proshkin Date: Mon, 27 May 2024 15:22:55 +0000 (+0300) Subject: pcilmr: Fix margining for ports with Lane reversal X-Git-Tag: v3.13.0~6 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=0e9018e3df2e208c9e5c059d8a84ff0ce71a0f69;p=pciutils.git pcilmr: Fix margining for ports with Lane reversal Current implementation interacts only with first Negotiated Link Width lanes even when Maximum Link Width for the port is bigger than that and Lane reversal is used. Utility in such situation may try to margin lane which is not used right now and erroneously fail with 'Error during caps reading' message. Fix that behaviour. Signed-off-by: Nikita Proshkin --- diff --git a/lmr/lmr.h b/lmr/lmr.h index f070309..98df17a 100644 --- a/lmr/lmr.h +++ b/lmr/lmr.h @@ -24,7 +24,8 @@ static const double margin_ui[] = { 62.5, 31.25 }; struct margin_dev { struct pci_dev *dev; int lmr_cap_addr; - u8 width; + u8 neg_width; + u8 max_width; u8 retimers_n; u8 link_speed; @@ -234,7 +235,7 @@ void margin_log(char *format, ...); void margin_log_bdfs(struct pci_dev *down_port, struct pci_dev *up_port); void margin_gen_bdfs(struct pci_dev *down_port, struct pci_dev *up_port, char *dest, size_t maxlen); -/* Print Link header (bdfs, width, speed) */ +/* Print Link header (bdfs, neg_width, speed) */ void margin_log_link(struct margin_link *link); void margin_log_params(struct margin_params *params); diff --git a/lmr/margin.c b/lmr/margin.c index d05bb59..4d68031 100644 --- a/lmr/margin.c +++ b/lmr/margin.c @@ -165,7 +165,7 @@ read_params_internal(struct margin_dev *dev, u8 recvn, bool lane_reversal, struct margin_params *params) { margin_cmd resp; - u8 lane = lane_reversal ? dev->width - 1 : 0; + u8 lane = lane_reversal ? dev->max_width - 1 : 0; margin_set_cmd(dev, lane, NO_COMMAND); bool status = margin_report_cmd(dev, lane, REPORT_CAPS(recvn), &resp); if (status) @@ -366,7 +366,7 @@ margin_test_receiver(struct margin_dev *dev, u8 recvn, struct margin_link_args * for (int i = 0; i < lanes_n; i++) { results->lanes[i].lane - = recv.lane_reversal ? dev->width - lanes_to_margin[i] - 1 : lanes_to_margin[i]; + = recv.lane_reversal ? dev->max_width - lanes_to_margin[i] - 1 : lanes_to_margin[i]; } if (args->common->run_margin) @@ -510,7 +510,7 @@ margin_process_args(struct margin_link *link) if (!args->lanes_n) { - args->lanes_n = dev->width; + args->lanes_n = dev->neg_width; for (int i = 0; i < args->lanes_n; i++) args->lanes[i] = i; } @@ -518,7 +518,7 @@ margin_process_args(struct margin_link *link) { for (int i = 0; i < args->lanes_n; i++) { - if (args->lanes[i] >= dev->width) + if (args->lanes[i] >= dev->neg_width) { return MARGIN_TEST_ARGS_LANES; } diff --git a/lmr/margin_hw.c b/lmr/margin_hw.c index 2585ca1..c376549 100644 --- a/lmr/margin_hw.c +++ b/lmr/margin_hw.c @@ -112,15 +112,17 @@ static struct margin_dev fill_dev_wrapper(struct pci_dev *dev) { struct pci_cap *cap = pci_find_cap(dev, PCI_CAP_ID_EXP, PCI_CAP_NORMAL); - struct margin_dev res - = { .dev = dev, - .lmr_cap_addr = pci_find_cap(dev, PCI_EXT_CAP_ID_LMR, PCI_CAP_EXTENDED)->addr, - .width = GET_REG_MASK(pci_read_word(dev, cap->addr + PCI_EXP_LNKSTA), PCI_EXP_LNKSTA_WIDTH), - .retimers_n - = (!!(pci_read_word(dev, cap->addr + PCI_EXP_LNKSTA2) & PCI_EXP_LINKSTA2_RETIMER)) - + (!!(pci_read_word(dev, cap->addr + PCI_EXP_LNKSTA2) & PCI_EXP_LINKSTA2_2RETIMERS)), - .link_speed = (pci_read_word(dev, cap->addr + PCI_EXP_LNKSTA) & PCI_EXP_LNKSTA_SPEED), - .hw = detect_unique_hw(dev) }; + struct margin_dev res = { + .dev = dev, + .lmr_cap_addr = pci_find_cap(dev, PCI_EXT_CAP_ID_LMR, PCI_CAP_EXTENDED)->addr, + .neg_width = GET_REG_MASK(pci_read_word(dev, cap->addr + PCI_EXP_LNKSTA), PCI_EXP_LNKSTA_WIDTH), + .max_width = GET_REG_MASK(pci_read_long(dev, cap->addr + PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_WIDTH), + .retimers_n + = (!!(pci_read_word(dev, cap->addr + PCI_EXP_LNKSTA2) & PCI_EXP_LINKSTA2_RETIMER)) + + (!!(pci_read_word(dev, cap->addr + PCI_EXP_LNKSTA2) & PCI_EXP_LINKSTA2_2RETIMERS)), + .link_speed = (pci_read_word(dev, cap->addr + PCI_EXP_LNKSTA) & PCI_EXP_LNKSTA_SPEED), + .hw = detect_unique_hw(dev) + }; return res; } diff --git a/lmr/margin_log.c b/lmr/margin_log.c index 60c135d..2cb01c8 100644 --- a/lmr/margin_log.c +++ b/lmr/margin_log.c @@ -53,7 +53,7 @@ margin_log_link(struct margin_link *link) { margin_log("Link "); margin_log_bdfs(link->down_port.dev, link->up_port.dev); - margin_log("\nNegotiated Link Width: %d\n", link->down_port.width); + 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, link->down_port.link_speed); margin_log("Available receivers: ");