Once the QTG ID _DSM is executed successfully, the QTG ID is retrieved from the return package. Create a list of entries in the cxl_memdev context and store the QTG ID and the associated DPA range. This information can be exposed to user space via sysfs in order to help region setup for hot-plugged CXL memory devices. Signed-off-by: Dave Jiang <dave.jiang@xxxxxxxxx> --- drivers/cxl/core/memdev.c | 1 + drivers/cxl/cxlmem.h | 14 ++++++++++++++ drivers/cxl/port.c | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 28a05f2fe32d..d2605fc39240 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -346,6 +346,7 @@ struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds) */ cxlmd->cxlds = cxlds; cxlds->cxlmd = cxlmd; + INIT_LIST_HEAD(&cxlmd->qos_list); cdev = &cxlmd->cdev; rc = cdev_device_add(cdev, dev); diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 001dabf0231b..c8b8d4865e49 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -40,6 +40,7 @@ * @cxl_nvd: optional bridge to an nvdimm if the device supports pmem * @id: id number of this memdev instance. * @depth: endpoint port depth + * @qos_list: QTG ID related list of entries */ struct cxl_memdev { struct device dev; @@ -50,6 +51,7 @@ struct cxl_memdev { struct cxl_nvdimm *cxl_nvd; int id; int depth; + struct list_head qos_list; }; static inline struct cxl_memdev *to_cxl_memdev(struct device *dev) @@ -215,6 +217,18 @@ struct cxl_event_state { struct mutex log_lock; }; +/** + * struct qos_prop - QoS property entry + * @list - list entry + * @dpa_range - range for DPA address + * @qtg_id - QoS Throttling Group ID + */ +struct qos_prop_entry { + struct list_head list; + struct range dpa_range; + u16 qtg_id; +}; + /** * struct cxl_dev_state - The driver device state * diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c index f6646d91ae26..4e7e22c13790 100644 --- a/drivers/cxl/port.c +++ b/drivers/cxl/port.c @@ -124,6 +124,22 @@ static int cxl_port_qos_calculate(struct cxl_port *port, return 0; } +static void cxl_memdev_set_qtg(struct cxl_memdev *cxlmd, struct list_head *dsmas_list) +{ + struct dsmas_entry *dent; + struct qos_prop_entry *qos; + + list_for_each_entry(dent, dsmas_list, list) { + qos = devm_kzalloc(&cxlmd->dev, sizeof(*qos), GFP_KERNEL); + if (!qos) + return; + + qos->dpa_range = dent->dpa_range; + qos->qtg_id = dent->qtg_id; + list_add_tail(&qos->list, &cxlmd->qos_list); + } +} + static int cxl_switch_port_probe(struct cxl_port *port) { struct cxl_hdm *cxlhdm; @@ -212,6 +228,7 @@ static int cxl_port_probe(struct device *dev) read_cdat_data(port); if (port->cdat.table) { if (is_cxl_endpoint(port)) { + struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport); LIST_HEAD(dsmas_list); rc = cdat_table_parse_dsmas(port->cdat.table, @@ -230,6 +247,8 @@ static int cxl_port_probe(struct device *dev) rc = cxl_port_qos_calculate(port, &dsmas_list); if (rc) dev_dbg(dev, "Failed to do QoS calculations\n"); + + cxl_memdev_set_qtg(cxlmd, &dsmas_list); dsmas_list_destroy(&dsmas_list); } else { rc = cdat_table_parse_sslbis(port->cdat.table,