lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250107035708.1134954-5-ming.li@zohomail.com>
Date: Tue,  7 Jan 2025 11:57:04 +0800
From: Li Ming <ming.li@...omail.com>
To: dave@...olabs.net,
	jonathan.cameron@...wei.com,
	dave.jiang@...el.com,
	alison.schofield@...el.com,
	vishal.l.verma@...el.com,
	ira.weiny@...el.com,
	dan.j.williams@...el.com
Cc: linux-cxl@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	Li Ming <ming.li@...omail.com>
Subject: [RFC PATCH 4/8] cxl/port: Remove port HDM during the last endpoint detaching

HDM is set up on a CXL port when the first endpoint under the port
attaching. The HDM should be released when no endpoint is under the port
so that the first endpoint attaching can trigger HDM setup on the port
again next time. So remove HDM and decoders on a CXL port if no endpoint
is working under it.

Signed-off-by: Li Ming <ming.li@...omail.com>
---
 drivers/cxl/core/port.c | 60 +++++++++++++++++++++++++++++++----------
 drivers/cxl/core/regs.c |  9 ++++++-
 2 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index 1022c0775daa..57ed152d96d7 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -1517,6 +1517,49 @@ static int port_has_memdev(struct device *dev, const void *data)
 	return !!cxl_ep_load(port, ctx->cxlmd);
 }
 
+static void cxld_unregister(void *dev)
+{
+	struct cxl_endpoint_decoder *cxled;
+
+	if (is_endpoint_decoder(dev)) {
+		cxled = to_cxl_endpoint_decoder(dev);
+		cxl_decoder_kill_region(cxled);
+	}
+
+	device_unregister(dev);
+}
+
+static int cxl_decoder_remove(struct device *dev, void *data)
+{
+	struct cxl_port *port = (struct cxl_port *)data;
+
+	if (!is_switch_decoder(dev) && !is_endpoint_decoder(dev))
+		return 0;
+
+	devm_release_action(&port->dev, cxld_unregister, dev);
+	return 0;
+}
+
+static void cxl_port_remove_hdm(struct cxl_port *port)
+{
+	const struct cxl_reg_map *rmap = &port->reg_map.component_map.hdm_decoder;
+	struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev);
+	resource_size_t addr, length;
+
+	if (!cxlhdm)
+		return;
+
+	device_for_each_child(&port->dev, port, cxl_decoder_remove);
+	if (cxlhdm->regs.hdm_decoder) {
+		devm_iounmap(&port->dev, cxlhdm->regs.hdm_decoder);
+		addr = port->reg_map.resource + rmap->offset;
+		length = rmap->size;
+		devm_release_mem_region(&port->dev, addr, length);
+	}
+	devm_kfree(&port->dev, cxlhdm);
+	dev_set_drvdata(&port->dev, NULL);
+}
+
 static void cxl_detach_ep(void *data)
 {
 	struct cxl_memdev *cxlmd = data;
@@ -1545,11 +1588,12 @@ static void cxl_detach_ep(void *data)
 		cxl_ep_remove(port, ep);
 		if (ep && xa_empty(&port->endpoints)) {
 			/*
-			 * Reset component registers information on the port
+			 * Reset HDM and component registers information on the port
 			 * during the last ep detaching. So that the next ep
 			 * attaching can trigger component registers probing
-			 * again.
+			 * and HDM setup again.
 			 */
+			cxl_port_remove_hdm(port);
 			cxl_register_map_reset(&port->reg_map);
 
 			if (!port->dead && !is_cxl_root(parent_port) &&
@@ -2031,18 +2075,6 @@ int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map)
 }
 EXPORT_SYMBOL_NS_GPL(cxl_decoder_add, "CXL");
 
-static void cxld_unregister(void *dev)
-{
-	struct cxl_endpoint_decoder *cxled;
-
-	if (is_endpoint_decoder(dev)) {
-		cxled = to_cxl_endpoint_decoder(dev);
-		cxl_decoder_kill_region(cxled);
-	}
-
-	device_unregister(dev);
-}
-
 int cxl_decoder_autoremove(struct device *host, struct cxl_decoder *cxld)
 {
 	return devm_add_action_or_reset(host, cxld_unregister, &cxld->dev);
diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index 59cb35b40c7e..7aba68785287 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -194,8 +194,15 @@ void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr,
 	}
 
 	ret_val = devm_ioremap(dev, addr, length);
-	if (!ret_val)
+	if (!ret_val) {
 		dev_err(dev, "Failed to map region %pr\n", res);
+		/*
+		 * Explicitly release mem region in failure case
+		 * so that no need to consider the case of devm_request_mem_region()
+		 * success but devm_ioremap() failure in cxl_port_remove_hdm().
+		 */
+		devm_release_mem_region(dev, addr, length);
+	}
 
 	return ret_val;
 }
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ