All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
To: <alison.schofield@intel.com>
Cc: Davidlohr Bueso <dave@stgolabs.net>,
	Dave Jiang <dave.jiang@intel.com>,
	Vishal Verma <vishal.l.verma@intel.com>,
	Ira Weiny <ira.weiny@intel.com>,
	Dan Williams <dan.j.williams@intel.com>,
	<linux-cxl@vger.kernel.org>
Subject: Re: [PATCH 3/3] cxl/region: Add inject and clear poison by HPA
Date: Tue, 24 Jun 2025 15:33:59 +0100	[thread overview]
Message-ID: <20250624153359.00006dbe@huawei.com> (raw)
In-Reply-To: <50bd42e0db1ed5979a00e6f5a43147320a1d5b9b.1750725512.git.alison.schofield@intel.com>

On Mon, 23 Jun 2025 17:53:36 -0700
alison.schofield@intel.com wrote:

> From: Alison Schofield <alison.schofield@intel.com>
> 
> Add CXL region debugfs attributes to inject and clear poison based
> on Host Physical Addresses (HPA). These new interfaces allow users
> to operate on poison at the region level without needing to resolve
> Device Physical Addresses (DPA) or target individual memdevs.
> 
> The implementation leverages an internal HPA-to-DPA helper, which
> applies decoder interleave logic, including XOR-based address decoding
> when applicable. Note that XOR decodes rely on driver internal xormaps
> which are not exposed to userspace. So, this support is not only a
> simplification of poison operations that could be done using existing
> per memdev operations, but also it enables the functionality for XOR
> interleaved regions for the first time.
> 
> The new debugfs attributes are added under /sys/kernel/debug/regionX/:
> inject_poison and clear_poison. These are only exposed if all memdevs
> participating in the region support both inject and clear commands,
> ensuring consistent and reliable behavior across multi-device regions.
> 
> If tracing is enabled, these operations are logged as cxl_poison
> events in /sys/kernel/tracing/trace.
> 
> Signed-off-by: Alison Schofield <alison.schofield@intel.com>

A few things inline.

> diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
> index b38141761f47..7616e68fa79e 100644
> --- a/drivers/cxl/core/memdev.c
> +++ b/drivers/cxl/core/memdev.c
> @@ -200,6 +200,17 @@ static ssize_t security_erase_store(struct device *dev,
>  static struct device_attribute dev_attr_security_erase =
>  	__ATTR(erase, 0200, NULL, security_erase_store);
>  
> +bool cxl_memdev_has_poison_cmd(struct cxl_memdev *cxlmd,
> +			       enum poison_cmd_enabled_bits cmd)
> +{
> +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> +
> +	if (test_bit(cmd, mds->poison.enabled_cmds))
> +		return true;
> +
> +	return false;

	return test_bit(cmd, ...);

> +}
> +
>  static int cxl_get_poison_by_memdev(struct cxl_memdev *cxlmd)
>  {
>  	struct cxl_dev_state *cxlds = cxlmd->cxlds;
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index d2d904c4b427..e9ed5ac7309e 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -2,6 +2,7 @@


> +DEFINE_DEBUGFS_ATTRIBUTE(cxl_poison_inject_fops, NULL,
> +			 cxl_region_debugfs_poison_inject, "%llx\n");
> +
> +static int cxl_region_debugfs_poison_clear(void *data, u64 hpa)
> +{
> +	struct cxl_region *cxlr = data;
> +	struct cxl_region_params *p = &cxlr->params;
> +	struct cxl_dpa_result result;
> +	int rc;
> +
> +	rc = down_read_interruptible(&cxl_region_rwsem);

This can use the new shiny ACQUIRE() tool letting us do
early returns and generally making it more readable.

> +	if (rc)
> +		return rc;
> +
> +	rc = down_read_interruptible(&cxl_dpa_rwsem);
> +	if (rc) {
> +		up_read(&cxl_region_rwsem);
> +		return rc;
> +	}
> +
> +	if (hpa < p->res->start || hpa > p->res->end) {
> +		dev_err_once(&cxlr->dev, "HPA 0x%llx not in region %pr\n", hpa,
> +			     p->res);
> +		rc = -EINVAL;
> +		goto out;
> +	}
> +	result = cxl_hpa_to_dpa(cxlr, hpa);
> +	if (!result.cxlmd || result.dpa == ULLONG_MAX) {
> +		dev_err(&cxlr->dev, "Failed to resolve DPA from HPA 0x%llx\n",
> +			hpa);
> +
> +		rc = -EINVAL;
> +		goto out;
> +	}
> +	rc = __clear_poison_locked(result.cxlmd, result.dpa);
> +out:
> +	up_read(&cxl_dpa_rwsem);
> +	up_read(&cxl_region_rwsem);
> +
> +	return rc;
> +}
> +
> +DEFINE_DEBUGFS_ATTRIBUTE(cxl_poison_clear_fops, NULL,
> +			 cxl_region_debugfs_poison_clear, "%llx\n");
> +
>  static int cxl_region_probe(struct device *dev)
>  {
>  	struct cxl_region *cxlr = to_cxl_region(dev);
>  	struct cxl_region_params *p = &cxlr->params;
> +	bool poison_supported = true;
>  	int rc;
>  
>  	rc = down_read_interruptible(&cxl_region_rwsem);
> @@ -3663,6 +3754,31 @@ static int cxl_region_probe(struct device *dev)
>  	if (rc)
>  		return rc;
>  
> +	/* Create poison attributes if all memdevs support the capabilities */
> +	for (int i = 0; i < p->nr_targets; i++) {
> +		struct cxl_endpoint_decoder *cxled = p->targets[i];
> +		struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
> +
> +		if (!cxl_memdev_has_poison_cmd(cxlmd, CXL_POISON_ENABLED_INJECT) ||
> +		    !cxl_memdev_has_poison_cmd(cxlmd, CXL_POISON_ENABLED_CLEAR)) {
> +			poison_supported = false;
You could drop i out of the loop and simply use the early break to detect
that a match occurred.

	if (i < p->nr_targets) {
		struct dentry *dentry;

but maybe that's a bit too subtle.  I don't mind having a variable for this.
	}
> +			break;
> +		}
> +	}
> +
> +	if (poison_supported) {
> +		struct dentry *dentry;
> +
> +		dentry = cxl_debugfs_create_dir(dev_name(dev));
> +		debugfs_create_file("inject_poison", 0200, dentry, cxlr,
> +				    &cxl_poison_inject_fops);
> +		debugfs_create_file("clear_poison", 0200, dentry, cxlr,
> +				    &cxl_poison_clear_fops);
> +		rc = devm_add_action_or_reset(dev, remove_debugfs, dentry);
> +		if (rc)
> +			return rc;
> +	}
> +
>  	switch (cxlr->mode) {
>  	case CXL_PARTMODE_PMEM:
>  		rc = devm_cxl_region_edac_register(cxlr);


  parent reply	other threads:[~2025-06-24 14:34 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-24  0:53 [PATCH 0/3] cxl: Support Poison Inject & Clear by HPA alison.schofield
2025-06-24  0:53 ` [PATCH 1/3] cxl/core: Add locked variants of the poison inject and clear funcs alison.schofield
2025-06-24 13:38   ` Jonathan Cameron
2025-06-25 22:15     ` Dave Jiang
2025-06-30 19:37       ` Alison Schofield
2025-06-30 19:36     ` Alison Schofield
2025-06-24  0:53 ` [PATCH 2/3] cxl/region: Introduce HPA to DPA address translation alison.schofield
2025-06-24 14:27   ` Jonathan Cameron
2025-06-30 20:05     ` Alison Schofield
2025-07-01 20:40     ` Alison Schofield
2025-06-25 22:49   ` Dave Jiang
2025-06-30 20:12     ` Alison Schofield
2025-06-24  0:53 ` [PATCH 3/3] cxl/region: Add inject and clear poison by HPA alison.schofield
2025-06-24  8:06   ` kernel test robot
2025-06-24 14:33   ` Jonathan Cameron [this message]
2025-06-30 20:39     ` Alison Schofield
2025-06-25 23:05   ` dan.j.williams
2025-06-30 20:32     ` Alison Schofield

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250624153359.00006dbe@huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=alison.schofield@intel.com \
    --cc=dan.j.williams@intel.com \
    --cc=dave.jiang@intel.com \
    --cc=dave@stgolabs.net \
    --cc=ira.weiny@intel.com \
    --cc=linux-cxl@vger.kernel.org \
    --cc=vishal.l.verma@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.