@@ -148,6 +148,7 @@ void cxl_cdat_dsmas_list_destroy(struct list_head *dsmas_list)
list_for_each_entry_safe(dentry, n, dsmas_list, list) {
list_del(&dentry->list);
+ kfree(dentry->qos_class);
kfree(dentry);
}
}
@@ -844,6 +844,7 @@ struct dsmas_entry {
struct range dpa_range;
u8 handle;
struct access_coordinate coord;
+ struct qos_class *qos_class;
};
#ifdef CONFIG_FIRMWARE_TABLE
@@ -57,6 +57,53 @@ static int discover_region(struct device *dev, void *root)
return 0;
}
+static int cxl_port_perf_data_calculate(struct cxl_port *port,
+ struct list_head *dsmas_list)
+{
+ struct qos_class *qos_class;
+ struct access_coordinate c;
+ struct qtg_dsm_input input;
+ struct cxl_port *root_port;
+ struct cxl_root *cxl_root;
+ struct dsmas_entry *dent;
+ int rc;
+
+ rc = cxl_endpoint_get_perf_coordinates(port, &c);
+ if (rc) {
+ dev_dbg(&port->dev, "Failed to retrieve perf coordinates.\n");
+ return rc;
+ }
+
+ root_port = find_cxl_root(port);
+ cxl_root = to_cxl_root(root_port);
+ if (!cxl_root->ops || !cxl_root->ops->get_qos_class)
+ return -EOPNOTSUPP;
+
+ list_for_each_entry(dent, dsmas_list, list) {
+ dent->coord.read_latency = dent->coord.read_latency +
+ c.read_latency;
+ dent->coord.write_latency = dent->coord.write_latency +
+ c.write_latency;
+ dent->coord.read_bandwidth = min_t(int, c.read_bandwidth,
+ dent->coord.read_bandwidth);
+ dent->coord.write_bandwidth = min_t(int, c.write_bandwidth,
+ dent->coord.write_bandwidth);
+
+ input.rd_lat = cpu_to_le32(dent->coord.read_latency);
+ input.wr_lat = cpu_to_le32(dent->coord.write_latency);
+ input.rd_bw = cpu_to_le32(dent->coord.read_bandwidth);
+ input.wr_bw = cpu_to_le32(dent->coord.write_bandwidth);
+
+ qos_class = cxl_root->ops->get_qos_class(root_port, &input);
+ if (IS_ERR(qos_class))
+ continue;
+
+ dent->qos_class = qos_class;
+ }
+
+ return 0;
+}
+
static int cxl_switch_port_probe(struct cxl_port *port)
{
struct cxl_hdm *cxlhdm;
@@ -147,10 +194,14 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
LIST_HEAD(dsmas_list);
rc = cxl_cdat_endpoint_process(port, &dsmas_list);
- if (rc < 0)
+ if (rc < 0) {
dev_dbg(&port->dev, "Failed to parse CDAT: %d\n", rc);
-
- /* Performance data processing */
+ } else {
+ rc = cxl_port_perf_data_calculate(port, &dsmas_list);
+ if (rc)
+ dev_dbg(&port->dev,
+ "Failed to do perf coord calculations.\n");
+ }
cxl_cdat_dsmas_list_destroy(&dsmas_list);
}