cxl: Consolidate dport access_coordinate ->hb_coord and ->sw_coord into ->coord

The driver stores access_coordinate for host bridge in ->hb_coord and
switch CDAT access_coordinate in ->sw_coord. Since neither of these
access_coordinate clobber each other, the variable name can be consolidated
into ->coord to simplify the code.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Davidlohr Bueso <dave@stgolabs.net>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Link: https://lore.kernel.org/r/20240403154844.3403859-5-dave.jiang@intel.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
This commit is contained in:
Dave Jiang 2024-04-03 08:47:15 -07:00
parent 51293c565c
commit 001c5d1934
6 changed files with 94 additions and 48 deletions

View file

@ -529,7 +529,7 @@ static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport)
if (kstrtou32(acpi_device_uid(hb), 0, &uid))
return -EINVAL;
return acpi_get_genport_coordinates(uid, dport->hb_coord);
return acpi_get_genport_coordinates(uid, dport->coord);
}
static int add_host_bridge_dport(struct device *match, void *arg)

View file

@ -14,7 +14,7 @@
struct dsmas_entry {
struct range dpa_range;
u8 handle;
struct access_coordinate coord;
struct access_coordinate coord[ACCESS_COORDINATE_MAX];
int entries;
int qos_class;
@ -88,8 +88,8 @@ static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg,
return 0;
}
static void cxl_access_coordinate_set(struct access_coordinate *coord,
int access, unsigned int val)
static void __cxl_access_coordinate_set(struct access_coordinate *coord,
int access, unsigned int val)
{
switch (access) {
case ACPI_HMAT_ACCESS_LATENCY:
@ -115,6 +115,13 @@ static void cxl_access_coordinate_set(struct access_coordinate *coord,
}
}
static void cxl_access_coordinate_set(struct access_coordinate *coord,
int access, unsigned int val)
{
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
__cxl_access_coordinate_set(&coord[i], access, val);
}
static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
const unsigned long end)
{
@ -156,7 +163,7 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base),
dslbis->data_type);
cxl_access_coordinate_set(&dent->coord, dslbis->data_type, val);
cxl_access_coordinate_set(dent->coord, dslbis->data_type, val);
return 0;
}
@ -190,13 +197,13 @@ static int cxl_cdat_endpoint_process(struct cxl_port *port,
static int cxl_port_perf_data_calculate(struct cxl_port *port,
struct xarray *dsmas_xa)
{
struct access_coordinate ep_c;
struct access_coordinate ep_c[ACCESS_COORDINATE_MAX];
struct dsmas_entry *dent;
int valid_entries = 0;
unsigned long index;
int rc;
rc = cxl_endpoint_get_perf_coordinates(port, &ep_c);
rc = cxl_endpoint_get_perf_coordinates(port, ep_c);
if (rc) {
dev_dbg(&port->dev, "Failed to retrieve ep perf coordinates.\n");
return rc;
@ -213,10 +220,11 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
xa_for_each(dsmas_xa, index, dent) {
int qos_class;
cxl_coordinates_combine(&dent->coord, &dent->coord, &ep_c);
cxl_coordinates_combine(dent->coord, dent->coord, ep_c);
dent->entries = 1;
rc = cxl_root->ops->qos_class(cxl_root, &dent->coord, 1,
&qos_class);
rc = cxl_root->ops->qos_class(cxl_root,
&dent->coord[ACCESS_COORDINATE_CPU],
1, &qos_class);
if (rc != 1)
continue;
@ -233,14 +241,17 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
static void update_perf_entry(struct device *dev, struct dsmas_entry *dent,
struct cxl_dpa_perf *dpa_perf)
{
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
dpa_perf->coord[i] = dent->coord[i];
dpa_perf->dpa_range = dent->dpa_range;
dpa_perf->coord = dent->coord;
dpa_perf->qos_class = dent->qos_class;
dev_dbg(dev,
"DSMAS: dpa: %#llx qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n",
dent->dpa_range.start, dpa_perf->qos_class,
dent->coord.read_bandwidth, dent->coord.write_bandwidth,
dent->coord.read_latency, dent->coord.write_latency);
dent->coord[ACCESS_COORDINATE_CPU].read_bandwidth,
dent->coord[ACCESS_COORDINATE_CPU].write_bandwidth,
dent->coord[ACCESS_COORDINATE_CPU].read_latency,
dent->coord[ACCESS_COORDINATE_CPU].write_latency);
}
static void cxl_memdev_set_qos_class(struct cxl_dev_state *cxlds,
@ -477,10 +488,11 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
xa_for_each(&port->dports, index, dport) {
if (dsp_id == ACPI_CDAT_SSLBIS_ANY_PORT ||
dsp_id == dport->port_id)
cxl_access_coordinate_set(&dport->sw_coord,
dsp_id == dport->port_id) {
cxl_access_coordinate_set(dport->coord,
sslbis->data_type,
val);
}
}
}
@ -502,6 +514,21 @@ void cxl_switch_parse_cdat(struct cxl_port *port)
}
EXPORT_SYMBOL_NS_GPL(cxl_switch_parse_cdat, CXL);
static void __cxl_coordinates_combine(struct access_coordinate *out,
struct access_coordinate *c1,
struct access_coordinate *c2)
{
if (c1->write_bandwidth && c2->write_bandwidth)
out->write_bandwidth = min(c1->write_bandwidth,
c2->write_bandwidth);
out->write_latency = c1->write_latency + c2->write_latency;
if (c1->read_bandwidth && c2->read_bandwidth)
out->read_bandwidth = min(c1->read_bandwidth,
c2->read_bandwidth);
out->read_latency = c1->read_latency + c2->read_latency;
}
/**
* cxl_coordinates_combine - Combine the two input coordinates
*
@ -513,15 +540,8 @@ void cxl_coordinates_combine(struct access_coordinate *out,
struct access_coordinate *c1,
struct access_coordinate *c2)
{
if (c1->write_bandwidth && c2->write_bandwidth)
out->write_bandwidth = min(c1->write_bandwidth,
c2->write_bandwidth);
out->write_latency = c1->write_latency + c2->write_latency;
if (c1->read_bandwidth && c2->read_bandwidth)
out->read_bandwidth = min(c1->read_bandwidth,
c2->read_bandwidth);
out->read_latency = c1->read_latency + c2->read_latency;
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
__cxl_coordinates_combine(&out[i], &c1[i], &c2[i]);
}
MODULE_IMPORT_NS(CXL);
@ -558,12 +578,12 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
/* Get total bandwidth and the worst latency for the cxl region */
cxlr->coord[i].read_latency = max_t(unsigned int,
cxlr->coord[i].read_latency,
perf->coord.read_latency);
perf->coord[i].read_latency);
cxlr->coord[i].write_latency = max_t(unsigned int,
cxlr->coord[i].write_latency,
perf->coord.write_latency);
cxlr->coord[i].read_bandwidth += perf->coord.read_bandwidth;
cxlr->coord[i].write_bandwidth += perf->coord.write_bandwidth;
perf->coord[i].write_latency);
cxlr->coord[i].read_bandwidth += perf->coord[i].read_bandwidth;
cxlr->coord[i].write_bandwidth += perf->coord[i].write_bandwidth;
}
}

View file

@ -2133,6 +2133,29 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd)
}
EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, CXL);
static void add_latency(struct access_coordinate *c, long latency)
{
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
c[i].write_latency += latency;
c[i].read_latency += latency;
}
}
static void set_min_bandwidth(struct access_coordinate *c, unsigned int bw)
{
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
c[i].write_bandwidth = min(c[i].write_bandwidth, bw);
c[i].read_bandwidth = min(c[i].read_bandwidth, bw);
}
}
static void set_access_coordinates(struct access_coordinate *out,
struct access_coordinate *in)
{
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
out[i] = in[i];
}
static bool parent_port_is_cxl_root(struct cxl_port *port)
{
return is_cxl_root(to_cxl_port(port->dev.parent));
@ -2149,9 +2172,15 @@ static bool parent_port_is_cxl_root(struct cxl_port *port)
int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
struct access_coordinate *coord)
{
struct access_coordinate c = {
.read_bandwidth = UINT_MAX,
.write_bandwidth = UINT_MAX,
struct access_coordinate c[] = {
{
.read_bandwidth = UINT_MAX,
.write_bandwidth = UINT_MAX,
},
{
.read_bandwidth = UINT_MAX,
.write_bandwidth = UINT_MAX,
},
};
struct cxl_port *iter = port;
struct cxl_dport *dport;
@ -2178,14 +2207,13 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
* have CDAT and therefore needs to be skipped.
*/
if (!is_cxl_root)
cxl_coordinates_combine(&c, &c, &dport->sw_coord);
c.write_latency += dport->link_latency;
c.read_latency += dport->link_latency;
cxl_coordinates_combine(c, c, dport->coord);
add_latency(c, dport->link_latency);
} while (!is_cxl_root);
dport = iter->parent_dport;
/* Retrieve HB coords */
cxl_coordinates_combine(&c, &c, dport->hb_coord);
cxl_coordinates_combine(c, c, dport->coord);
/* Get the calculated PCI paths bandwidth */
pdev = to_pci_dev(port->uport_dev->parent);
@ -2194,10 +2222,8 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
return -ENXIO;
bw /= BITS_PER_BYTE;
c.write_bandwidth = min(c.write_bandwidth, bw);
c.read_bandwidth = min(c.read_bandwidth, bw);
*coord = c;
set_min_bandwidth(c, bw);
set_access_coordinates(coord, c);
return 0;
}

View file

@ -663,8 +663,7 @@ struct cxl_rcrb_info {
* @rch: Indicate whether this dport was enumerated in RCH or VH mode
* @port: reference to cxl_port that contains this downstream port
* @regs: Dport parsed register blocks
* @sw_coord: access coordinates (performance) for switch from CDAT
* @hb_coord: access coordinates (performance) from ACPI generic port (host bridge)
* @coord: access coordinates (bandwidth and latency performance attributes)
* @link_latency: calculated PCIe downstream latency
*/
struct cxl_dport {
@ -675,8 +674,7 @@ struct cxl_dport {
bool rch;
struct cxl_port *port;
struct cxl_regs regs;
struct access_coordinate sw_coord;
struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX];
struct access_coordinate coord[ACCESS_COORDINATE_MAX];
long link_latency;
};

View file

@ -401,7 +401,7 @@ enum cxl_devtype {
*/
struct cxl_dpa_perf {
struct range dpa_range;
struct access_coordinate coord;
struct access_coordinate coord[ACCESS_COORDINATE_MAX];
int qos_class;
};

View file

@ -986,10 +986,12 @@ static void dpa_perf_setup(struct cxl_port *endpoint, struct range *range,
{
dpa_perf->qos_class = FAKE_QTG_ID;
dpa_perf->dpa_range = *range;
dpa_perf->coord.read_latency = 500;
dpa_perf->coord.write_latency = 500;
dpa_perf->coord.read_bandwidth = 1000;
dpa_perf->coord.write_bandwidth = 1000;
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
dpa_perf->coord[i].read_latency = 500;
dpa_perf->coord[i].write_latency = 500;
dpa_perf->coord[i].read_bandwidth = 1000;
dpa_perf->coord[i].write_bandwidth = 1000;
}
}
static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)