@@ -859,12 +859,16 @@ static inline struct cxl_dax_region *to_cxl_dax_region(struct device *dev)
}
#endif
+
/* CDAT related bits */
struct dsmas_entry {
struct list_head list;
struct range dpa_range;
u8 handle;
struct access_coordinate coord;
+
+ int entries;
+ int qos_class;
};
#ifdef CONFIG_FIRMWARE_TABLE
@@ -57,6 +57,54 @@ 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 access_coordinate c;
+ struct cxl_port *root_port;
+ struct cxl_root *cxl_root;
+ struct dsmas_entry *dent;
+ int valid_entries = 0;
+ 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) {
+ int qos_class;
+
+ 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);
+
+ dent->entries = 1;
+ rc = cxl_root->ops->get_qos_class(root_port, &dent->coord, 1, &qos_class);
+ if (rc != 1)
+ continue;
+
+ valid_entries++;
+ dent->qos_class = qos_class;
+ }
+
+ if (!valid_entries)
+ return -ENOENT;
+
+ return 0;
+}
+
static int cxl_switch_port_probe(struct cxl_port *port)
{
struct cxl_hdm *cxlhdm;
@@ -146,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);
}