@@ -9,6 +9,7 @@
#include "cxlmem.h"
#include "core.h"
#include "cxl.h"
+#include "core.h"
struct dsmas_entry {
struct range dpa_range;
@@ -515,3 +516,67 @@ void cxl_coordinates_combine(struct access_coordinate *out,
}
MODULE_IMPORT_NS(CXL);
+
+void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
+ struct cxl_endpoint_decoder *cxled)
+{
+ struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
+ struct cxl_port *port = cxlmd->endpoint;
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
+ struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX];
+ struct access_coordinate coord;
+ struct range dpa = {
+ .start = cxled->dpa_res->start,
+ .end = cxled->dpa_res->end,
+ };
+ struct cxl_dpa_perf *perf;
+ int rc;
+
+ switch (cxlr->mode) {
+ case CXL_DECODER_RAM:
+ perf = &mds->ram_perf;
+ break;
+ case CXL_DECODER_PMEM:
+ perf = &mds->pmem_perf;
+ break;
+ default:
+ return;
+ }
+
+ lockdep_assert_held(&cxl_dpa_rwsem);
+
+ if (!range_contains(&perf->dpa_range, &dpa))
+ return;
+
+ rc = cxl_hb_get_perf_coordinates(port, hb_coord);
+ if (rc) {
+ dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n");
+ return;
+ }
+
+ for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
+ /* Pickup the host bridge coords */
+ cxl_coordinates_combine(&coord, &hb_coord[i], &perf->coord);
+
+ /* 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,
+ coord.read_latency);
+ cxlr->coord[i].write_latency = max_t(unsigned int,
+ cxlr->coord[i].write_latency,
+ coord.write_latency);
+ cxlr->coord[i].read_bandwidth += coord.read_bandwidth;
+ cxlr->coord[i].write_bandwidth += coord.write_bandwidth;
+
+ /*
+ * Convert latency to nanosec from picosec to be consistent
+ * with the resulting latency coordinates computed by the
+ * HMAT_REPORTING code.
+ */
+ cxlr->coord[i].read_latency =
+ DIV_ROUND_UP(cxlr->coord[i].read_latency, 1000);
+ cxlr->coord[i].write_latency =
+ DIV_ROUND_UP(cxlr->coord[i].write_latency, 1000);
+ }
+}
@@ -1722,6 +1722,8 @@ static int cxl_region_attach(struct cxl_region *cxlr,
return -EINVAL;
}
+ cxl_region_perf_data_calculate(cxlr, cxled);
+
if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) {
int i;
@@ -517,6 +517,7 @@ struct cxl_region_params {
* @cxlr_pmem: (for pmem regions) cached copy of the nvdimm bridge
* @flags: Region state flags
* @params: active + config params for the region
+ * @coord: QoS access coordinates for the region
*/
struct cxl_region {
struct device dev;
@@ -527,6 +528,7 @@ struct cxl_region {
struct cxl_pmem_region *cxlr_pmem;
unsigned long flags;
struct cxl_region_params params;
+ struct access_coordinate coord[ACCESS_COORDINATE_MAX];
};
struct cxl_nvdimm_bridge {
@@ -881,6 +883,8 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
struct access_coordinate *coord);
int cxl_hb_get_perf_coordinates(struct cxl_port *port,
struct access_coordinate *coord);
+void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
+ struct cxl_endpoint_decoder *cxled);
void cxl_memdev_update_perf(struct cxl_memdev *cxlmd);