Commit 001c5d19 authored by Dave Jiang's avatar Dave Jiang

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: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: default avatarDavidlohr Bueso <dave@stgolabs.net>
Reviewed-by: default avatarDan Williams <dan.j.williams@intel.com>
Link: https://lore.kernel.org/r/20240403154844.3403859-5-dave.jiang@intel.comSigned-off-by: default avatarDave Jiang <dave.jiang@intel.com>
parent 51293c56
...@@ -529,7 +529,7 @@ static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport) ...@@ -529,7 +529,7 @@ static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport)
if (kstrtou32(acpi_device_uid(hb), 0, &uid)) if (kstrtou32(acpi_device_uid(hb), 0, &uid))
return -EINVAL; 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) static int add_host_bridge_dport(struct device *match, void *arg)
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
struct dsmas_entry { struct dsmas_entry {
struct range dpa_range; struct range dpa_range;
u8 handle; u8 handle;
struct access_coordinate coord; struct access_coordinate coord[ACCESS_COORDINATE_MAX];
int entries; int entries;
int qos_class; int qos_class;
...@@ -88,8 +88,8 @@ static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg, ...@@ -88,8 +88,8 @@ static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg,
return 0; return 0;
} }
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) int access, unsigned int val)
{ {
switch (access) { switch (access) {
case ACPI_HMAT_ACCESS_LATENCY: case ACPI_HMAT_ACCESS_LATENCY:
...@@ -115,6 +115,13 @@ static void cxl_access_coordinate_set(struct access_coordinate *coord, ...@@ -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, static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
const unsigned long end) const unsigned long end)
{ {
...@@ -156,7 +163,7 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg, ...@@ -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), val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base),
dslbis->data_type); 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; return 0;
} }
...@@ -190,13 +197,13 @@ static int cxl_cdat_endpoint_process(struct cxl_port *port, ...@@ -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, static int cxl_port_perf_data_calculate(struct cxl_port *port,
struct xarray *dsmas_xa) struct xarray *dsmas_xa)
{ {
struct access_coordinate ep_c; struct access_coordinate ep_c[ACCESS_COORDINATE_MAX];
struct dsmas_entry *dent; struct dsmas_entry *dent;
int valid_entries = 0; int valid_entries = 0;
unsigned long index; unsigned long index;
int rc; int rc;
rc = cxl_endpoint_get_perf_coordinates(port, &ep_c); rc = cxl_endpoint_get_perf_coordinates(port, ep_c);
if (rc) { if (rc) {
dev_dbg(&port->dev, "Failed to retrieve ep perf coordinates.\n"); dev_dbg(&port->dev, "Failed to retrieve ep perf coordinates.\n");
return rc; return rc;
...@@ -213,10 +220,11 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port, ...@@ -213,10 +220,11 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
xa_for_each(dsmas_xa, index, dent) { xa_for_each(dsmas_xa, index, dent) {
int qos_class; int qos_class;
cxl_coordinates_combine(&dent->coord, &dent->coord, &ep_c); cxl_coordinates_combine(dent->coord, dent->coord, ep_c);
dent->entries = 1; dent->entries = 1;
rc = cxl_root->ops->qos_class(cxl_root, &dent->coord, 1, rc = cxl_root->ops->qos_class(cxl_root,
&qos_class); &dent->coord[ACCESS_COORDINATE_CPU],
1, &qos_class);
if (rc != 1) if (rc != 1)
continue; continue;
...@@ -233,14 +241,17 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port, ...@@ -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, static void update_perf_entry(struct device *dev, struct dsmas_entry *dent,
struct cxl_dpa_perf *dpa_perf) 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->dpa_range = dent->dpa_range;
dpa_perf->coord = dent->coord;
dpa_perf->qos_class = dent->qos_class; dpa_perf->qos_class = dent->qos_class;
dev_dbg(dev, dev_dbg(dev,
"DSMAS: dpa: %#llx qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n", "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->dpa_range.start, dpa_perf->qos_class,
dent->coord.read_bandwidth, dent->coord.write_bandwidth, dent->coord[ACCESS_COORDINATE_CPU].read_bandwidth,
dent->coord.read_latency, dent->coord.write_latency); 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, 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, ...@@ -477,10 +488,11 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
xa_for_each(&port->dports, index, dport) { xa_for_each(&port->dports, index, dport) {
if (dsp_id == ACPI_CDAT_SSLBIS_ANY_PORT || if (dsp_id == ACPI_CDAT_SSLBIS_ANY_PORT ||
dsp_id == dport->port_id) dsp_id == dport->port_id) {
cxl_access_coordinate_set(&dport->sw_coord, cxl_access_coordinate_set(dport->coord,
sslbis->data_type, sslbis->data_type,
val); val);
}
} }
} }
...@@ -502,6 +514,21 @@ void cxl_switch_parse_cdat(struct cxl_port *port) ...@@ -502,6 +514,21 @@ void cxl_switch_parse_cdat(struct cxl_port *port)
} }
EXPORT_SYMBOL_NS_GPL(cxl_switch_parse_cdat, CXL); 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 * cxl_coordinates_combine - Combine the two input coordinates
* *
...@@ -513,15 +540,8 @@ void cxl_coordinates_combine(struct access_coordinate *out, ...@@ -513,15 +540,8 @@ void cxl_coordinates_combine(struct access_coordinate *out,
struct access_coordinate *c1, struct access_coordinate *c1,
struct access_coordinate *c2) struct access_coordinate *c2)
{ {
if (c1->write_bandwidth && c2->write_bandwidth) for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
out->write_bandwidth = min(c1->write_bandwidth, __cxl_coordinates_combine(&out[i], &c1[i], &c2[i]);
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;
} }
MODULE_IMPORT_NS(CXL); MODULE_IMPORT_NS(CXL);
...@@ -558,12 +578,12 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr, ...@@ -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 */ /* 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 = max_t(unsigned int,
cxlr->coord[i].read_latency, 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 = max_t(unsigned int,
cxlr->coord[i].write_latency, cxlr->coord[i].write_latency,
perf->coord.write_latency); perf->coord[i].write_latency);
cxlr->coord[i].read_bandwidth += perf->coord.read_bandwidth; cxlr->coord[i].read_bandwidth += perf->coord[i].read_bandwidth;
cxlr->coord[i].write_bandwidth += perf->coord.write_bandwidth; cxlr->coord[i].write_bandwidth += perf->coord[i].write_bandwidth;
} }
} }
......
...@@ -2133,6 +2133,29 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd) ...@@ -2133,6 +2133,29 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd)
} }
EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, CXL); 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) static bool parent_port_is_cxl_root(struct cxl_port *port)
{ {
return is_cxl_root(to_cxl_port(port->dev.parent)); 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) ...@@ -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, int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
struct access_coordinate *coord) struct access_coordinate *coord)
{ {
struct access_coordinate c = { struct access_coordinate c[] = {
.read_bandwidth = UINT_MAX, {
.write_bandwidth = UINT_MAX, .read_bandwidth = UINT_MAX,
.write_bandwidth = UINT_MAX,
},
{
.read_bandwidth = UINT_MAX,
.write_bandwidth = UINT_MAX,
},
}; };
struct cxl_port *iter = port; struct cxl_port *iter = port;
struct cxl_dport *dport; struct cxl_dport *dport;
...@@ -2178,14 +2207,13 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, ...@@ -2178,14 +2207,13 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
* have CDAT and therefore needs to be skipped. * have CDAT and therefore needs to be skipped.
*/ */
if (!is_cxl_root) if (!is_cxl_root)
cxl_coordinates_combine(&c, &c, &dport->sw_coord); cxl_coordinates_combine(c, c, dport->coord);
c.write_latency += dport->link_latency; add_latency(c, dport->link_latency);
c.read_latency += dport->link_latency;
} while (!is_cxl_root); } while (!is_cxl_root);
dport = iter->parent_dport; dport = iter->parent_dport;
/* Retrieve HB coords */ /* Retrieve HB coords */
cxl_coordinates_combine(&c, &c, dport->hb_coord); cxl_coordinates_combine(c, c, dport->coord);
/* Get the calculated PCI paths bandwidth */ /* Get the calculated PCI paths bandwidth */
pdev = to_pci_dev(port->uport_dev->parent); pdev = to_pci_dev(port->uport_dev->parent);
...@@ -2194,10 +2222,8 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, ...@@ -2194,10 +2222,8 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
return -ENXIO; return -ENXIO;
bw /= BITS_PER_BYTE; bw /= BITS_PER_BYTE;
c.write_bandwidth = min(c.write_bandwidth, bw); set_min_bandwidth(c, bw);
c.read_bandwidth = min(c.read_bandwidth, bw); set_access_coordinates(coord, c);
*coord = c;
return 0; return 0;
} }
......
...@@ -663,8 +663,7 @@ struct cxl_rcrb_info { ...@@ -663,8 +663,7 @@ struct cxl_rcrb_info {
* @rch: Indicate whether this dport was enumerated in RCH or VH mode * @rch: Indicate whether this dport was enumerated in RCH or VH mode
* @port: reference to cxl_port that contains this downstream port * @port: reference to cxl_port that contains this downstream port
* @regs: Dport parsed register blocks * @regs: Dport parsed register blocks
* @sw_coord: access coordinates (performance) for switch from CDAT * @coord: access coordinates (bandwidth and latency performance attributes)
* @hb_coord: access coordinates (performance) from ACPI generic port (host bridge)
* @link_latency: calculated PCIe downstream latency * @link_latency: calculated PCIe downstream latency
*/ */
struct cxl_dport { struct cxl_dport {
...@@ -675,8 +674,7 @@ struct cxl_dport { ...@@ -675,8 +674,7 @@ struct cxl_dport {
bool rch; bool rch;
struct cxl_port *port; struct cxl_port *port;
struct cxl_regs regs; struct cxl_regs regs;
struct access_coordinate sw_coord; struct access_coordinate coord[ACCESS_COORDINATE_MAX];
struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX];
long link_latency; long link_latency;
}; };
......
...@@ -401,7 +401,7 @@ enum cxl_devtype { ...@@ -401,7 +401,7 @@ enum cxl_devtype {
*/ */
struct cxl_dpa_perf { struct cxl_dpa_perf {
struct range dpa_range; struct range dpa_range;
struct access_coordinate coord; struct access_coordinate coord[ACCESS_COORDINATE_MAX];
int qos_class; int qos_class;
}; };
......
...@@ -986,10 +986,12 @@ static void dpa_perf_setup(struct cxl_port *endpoint, struct range *range, ...@@ -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->qos_class = FAKE_QTG_ID;
dpa_perf->dpa_range = *range; dpa_perf->dpa_range = *range;
dpa_perf->coord.read_latency = 500; for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
dpa_perf->coord.write_latency = 500; dpa_perf->coord[i].read_latency = 500;
dpa_perf->coord.read_bandwidth = 1000; dpa_perf->coord[i].write_latency = 500;
dpa_perf->coord.write_bandwidth = 1000; 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) static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment