Skip to content

Commit 592780b

Browse files
committed
cxl: Fix retrieving of access_coordinates in PCIe path
Current loop in cxl_endpoint_get_perf_coordinates() incorrectly assumes the Root Port (RP) dport is the one with generic port access_coordinate. However those coordinates are one level up in the Host Bridge (HB). Current code causes the computation code to pick up 0s as the coordinates and cause minimal bandwidth to result in 0. Add check to skip RP when combining coordinates. Fixes: 14a6960 ("cxl: Add helper function that calculate performance data for downstream ports") Reported-by: Jonathan Cameron <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Reviewed-by: Dan Williams <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dave Jiang <[email protected]>
1 parent 648dae5 commit 592780b

File tree

1 file changed

+22
-13
lines changed

1 file changed

+22
-13
lines changed

drivers/cxl/core/port.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2165,6 +2165,11 @@ int cxl_hb_get_perf_coordinates(struct cxl_port *port,
21652165
return 0;
21662166
}
21672167

2168+
static bool parent_port_is_cxl_root(struct cxl_port *port)
2169+
{
2170+
return is_cxl_root(to_cxl_port(port->dev.parent));
2171+
}
2172+
21682173
/**
21692174
* cxl_endpoint_get_perf_coordinates - Retrieve performance numbers stored in dports
21702175
* of CXL path
@@ -2184,27 +2189,31 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
21842189
struct cxl_dport *dport;
21852190
struct pci_dev *pdev;
21862191
unsigned int bw;
2192+
bool is_cxl_root;
21872193

21882194
if (!is_cxl_endpoint(port))
21892195
return -EINVAL;
21902196

2191-
dport = iter->parent_dport;
2192-
21932197
/*
2194-
* Exit the loop when the parent port of the current port is cxl root.
2195-
* The iterative loop starts at the endpoint and gathers the
2196-
* latency of the CXL link from the current iter to the next downstream
2197-
* port each iteration. If the parent is cxl root then there is
2198-
* nothing to gather.
2198+
* Exit the loop when the parent port of the current iter port is cxl
2199+
* root. The iterative loop starts at the endpoint and gathers the
2200+
* latency of the CXL link from the current device/port to the connected
2201+
* downstream port each iteration.
21992202
*/
2200-
while (!is_cxl_root(to_cxl_port(iter->dev.parent))) {
2201-
cxl_coordinates_combine(&c, &c, &dport->sw_coord);
2203+
do {
2204+
dport = iter->parent_dport;
2205+
iter = to_cxl_port(iter->dev.parent);
2206+
is_cxl_root = parent_port_is_cxl_root(iter);
2207+
2208+
/*
2209+
* There's no valid access_coordinate for a root port since RPs do not
2210+
* have CDAT and therefore needs to be skipped.
2211+
*/
2212+
if (!is_cxl_root)
2213+
cxl_coordinates_combine(&c, &c, &dport->sw_coord);
22022214
c.write_latency += dport->link_latency;
22032215
c.read_latency += dport->link_latency;
2204-
2205-
iter = to_cxl_port(iter->dev.parent);
2206-
dport = iter->parent_dport;
2207-
}
2216+
} while (!is_cxl_root);
22082217

22092218
/* Get the calculated PCI paths bandwidth */
22102219
pdev = to_pci_dev(port->uport_dev->parent);

0 commit comments

Comments
 (0)