Skip to content

Commit 14a6960

Browse files
davejiangdjbw
authored andcommitted
cxl: Add helper function that calculate performance data for downstream ports
The CDAT information from the switch, Switch Scoped Latency and Bandwidth Information Structure (SSLBIS), is parsed and stored under a cxl_dport based on the correlated downstream port id from the SSLBIS entry. Walk the entire CXL port paths and collect all the performance data. Also pick up the link latency number that's stored under the dports. The entire path PCIe bandwidth can be retrieved using the pcie_bandwidth_available() call. Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com> Link: https://lore.kernel.org/r/170319623824.2212653.10302079766473698427.stgit@djiang5-mobl3 Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 1037b82 commit 14a6960

2 files changed

Lines changed: 78 additions & 0 deletions

File tree

drivers/cxl/core/port.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/pci.h>
1010
#include <linux/slab.h>
1111
#include <linux/idr.h>
12+
#include <linux/node.h>
1213
#include <cxlmem.h>
1314
#include <cxlpci.h>
1415
#include <cxl.h>
@@ -2094,6 +2095,80 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd)
20942095
}
20952096
EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, CXL);
20962097

2098+
static void combine_coordinates(struct access_coordinate *c1,
2099+
struct access_coordinate *c2)
2100+
{
2101+
if (c2->write_bandwidth)
2102+
c1->write_bandwidth = min(c1->write_bandwidth,
2103+
c2->write_bandwidth);
2104+
c1->write_latency += c2->write_latency;
2105+
2106+
if (c2->read_bandwidth)
2107+
c1->read_bandwidth = min(c1->read_bandwidth,
2108+
c2->read_bandwidth);
2109+
c1->read_latency += c2->read_latency;
2110+
}
2111+
2112+
/**
2113+
* cxl_endpoint_get_perf_coordinates - Retrieve performance numbers stored in dports
2114+
* of CXL path
2115+
* @port: endpoint cxl_port
2116+
* @coord: output performance data
2117+
*
2118+
* Return: errno on failure, 0 on success.
2119+
*/
2120+
int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
2121+
struct access_coordinate *coord)
2122+
{
2123+
struct access_coordinate c = {
2124+
.read_bandwidth = UINT_MAX,
2125+
.write_bandwidth = UINT_MAX,
2126+
};
2127+
struct cxl_port *iter = port;
2128+
struct cxl_dport *dport;
2129+
struct pci_dev *pdev;
2130+
unsigned int bw;
2131+
2132+
if (!is_cxl_endpoint(port))
2133+
return -EINVAL;
2134+
2135+
dport = iter->parent_dport;
2136+
2137+
/*
2138+
* Exit the loop when the parent port of the current port is cxl root.
2139+
* The iterative loop starts at the endpoint and gathers the
2140+
* latency of the CXL link from the current iter to the next downstream
2141+
* port each iteration. If the parent is cxl root then there is
2142+
* nothing to gather.
2143+
*/
2144+
while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) {
2145+
combine_coordinates(&c, &dport->sw_coord);
2146+
c.write_latency += dport->link_latency;
2147+
c.read_latency += dport->link_latency;
2148+
2149+
iter = to_cxl_port(iter->dev.parent);
2150+
dport = iter->parent_dport;
2151+
}
2152+
2153+
/* Augment with the generic port (host bridge) perf data */
2154+
combine_coordinates(&c, &dport->hb_coord);
2155+
2156+
/* Get the calculated PCI paths bandwidth */
2157+
pdev = to_pci_dev(port->uport_dev->parent);
2158+
bw = pcie_bandwidth_available(pdev, NULL, NULL, NULL);
2159+
if (bw == 0)
2160+
return -ENXIO;
2161+
bw /= BITS_PER_BYTE;
2162+
2163+
c.write_bandwidth = min(c.write_bandwidth, bw);
2164+
c.read_bandwidth = min(c.read_bandwidth, bw);
2165+
2166+
*coord = c;
2167+
2168+
return 0;
2169+
}
2170+
EXPORT_SYMBOL_NS_GPL(cxl_endpoint_get_perf_coordinates, CXL);
2171+
20972172
/* for user tooling to ensure port disable work has completed */
20982173
static ssize_t flush_store(const struct bus_type *bus, const char *buf, size_t count)
20992174
{

drivers/cxl/cxl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,9 @@ static inline struct cxl_dax_region *to_cxl_dax_region(struct device *dev)
876876
void cxl_endpoint_parse_cdat(struct cxl_port *port);
877877
void cxl_switch_parse_cdat(struct cxl_port *port);
878878

879+
int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
880+
struct access_coordinate *coord);
881+
879882
/*
880883
* Unit test builds overrides this to __weak, find the 'strong' version
881884
* of these symbols in tools/testing/cxl/.

0 commit comments

Comments
 (0)