mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Dave Jiang <dave.jiang@intel.com>
To: Richard Cheng <icheng@nvidia.com>,
	dave@stgolabs.net, jic23@kernel.org, alison.schofield@intel.com,
	vishal.l.verma@intel.com, djbw@kernel.org,
	danwilliams@nvidia.com
Cc: iweiny@kernel.org, ming.li@zohomail.com, kobak@nvidia.com,
	kaihengf@nvidia.com, kees@kernel.org, newtonl@nvidia.com,
	kristinc@nvidia.com, mochs@nvidia.com, linux-cxl@vger.kernel.org,
	linux-kernel@vger.kernel.org, Vishal Aslot <vaslot@nvidia.com>
Subject: Re: [PATCH v6 2/2] tools/testing/cxl: Enable zero sized decoders under hb0
Date: Mon, 6 Jul 2026 10:01:00 -0700	[thread overview]
Message-ID: <c6fa720a-6ee3-46c8-9c6f-dc57f802059d@intel.com> (raw)
In-Reply-To: <20260625092857.41139-3-icheng@nvidia.com>



On 6/25/26 2:28 AM, Richard Cheng wrote:
> The kernel now allows committed zero-size HDM decoders so BIOS can lock
> empty decoders; cxl_test needs to exercise that path.
> 
> Add a mock_zero_size_decoders module parameter (default off). When set,
> the special endpoints under host-bridge0 (cxl_mem.0 and cxl_mem.4)
> commit decoders 1 and 2 as zero-size + locked above the decoder[0]
> auto-region, mirrored on the parent switch and host bridge. The mocks
> take a real zero-size DPA reservation, like enumeration of real
> hardware, so commit_end lands on a zero-size decoder and the
> reservation, poison-by-endpoint, and teardown paths all run.
> 
> Signed-off-by: Vishal Aslot <vaslot@nvidia.com>
> Signed-off-by: Richard Cheng <icheng@nvidia.com>

You may want to rebase against for-7.3/cxl-type2-test branch to pick up the module param checks.

DJ

> ---
> v5->v6:
>      - Reword a mock comment, no functional change.
> v4->v5:
>       - Mirror the v5 core semantics: mock zero-size decoders take a real
>         zero-size DPA reservation via devm_cxl_dpa_reserve() so
>         dpa_res/hdm_end/cxled->part match real hardware enumeration and
>         the poison-by-endpoint walk reaches commit_end.
>       - Set cxled->state = CXL_DECODER_STATE_AUTO to match
>         init_hdm_decoder()'s fall-through (undoes the v2 switch to
>         MANUAL).
>       - cxld_registry_restore(): reserve unconditionally for enabled
>         endpoint decoders; enabled now implies reserved, sized or not.
> 
> v3->v4:
>      - No change.
> 
> v2->v3:
>       - Gate the zero-size + locked decoder injection behind a new
>         mock_zero_size_decoders module parameter (default off). v2
>         applied it unconditionally on the host-bridge0 auto-region
>         endpoints, which the region test suite reuses, regressing 7 of
>         17 cxl unit tests; defaulting off leaves the shared topology
>         untouched.
> 
> v1->v2:
>       - Replace second_decoder(), third_decoder() with a single
>         match_decoder_by_index() helper, so all lookups share one
>         matcher.
>       - Use DEFINE_RANGE() for the empty range instead of an open-coded
>         struct.
>       - Set cxled->state = CXL_DECODER_STATE_MANUAL rather than
>         STATE_AUTO.
>       - Set CXL_DECODER_F_LOCK on the mock zero-size decoders to model
>         the BIOS-burns-slots case.
> ---
>  tools/testing/cxl/test/cxl.c | 100 ++++++++++++++++++++++++++++++-----
>  1 file changed, 86 insertions(+), 14 deletions(-)
> 
> diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
> index 418669927fb0..117691b3c62f 100644
> --- a/tools/testing/cxl/test/cxl.c
> +++ b/tools/testing/cxl/test/cxl.c
> @@ -17,6 +17,7 @@
>  static int interleave_arithmetic;
>  static bool extended_linear_cache;
>  static bool fail_autoassemble;
> +static bool mock_zero_size_decoders;
>  
>  #define FAKE_QTG_ID	42
>  
> @@ -841,14 +842,13 @@ static int cxld_registry_restore(struct cxl_decoder *cxld,
>  		cxld_copy(cxld, &td->cxled.cxld);
>  		cxled->state = td->cxled.state;
>  		cxled->skip = td->cxled.skip;
> -		if (range_len(&td->dpa_range)) {
> -			rc = devm_cxl_dpa_reserve(cxled, td->dpa_range.start,
> -						  range_len(&td->dpa_range),
> -						  td->cxled.skip);
> -			if (rc) {
> -				init_disabled_mock_decoder(cxld);
> -				return rc;
> -			}
> +		/* enabled endpoint decoders hold a reservation, sized or not */
> +		rc = devm_cxl_dpa_reserve(cxled, td->dpa_range.start,
> +					  range_len(&td->dpa_range),
> +					  td->cxled.skip);
> +		if (rc) {
> +			init_disabled_mock_decoder(cxld);
> +			return rc;
>  		}
>  		port->commit_end = cxld->id;
>  	}
> @@ -1041,16 +1041,49 @@ static void default_mock_decoder(struct cxl_decoder *cxld)
>  	WARN_ON_ONCE(!cxld_registry_new(cxld));
>  }
>  
> -static int first_decoder(struct device *dev, const void *data)
> +static int match_decoder_by_index(struct device *dev, const void *data)
>  {
> +	int target_id = *(const int *)data;
>  	struct cxl_decoder *cxld;
>  
>  	if (!is_switch_decoder(dev))
>  		return 0;
>  	cxld = to_cxl_decoder(dev);
> -	if (cxld->id == 0)
> -		return 1;
> -	return 0;
> +	return cxld->id == target_id;
> +}
> +
> +/*
> + * Mock a committed, locked, empty decoder
> + * (CXL r4.0 8.2.4.20.12). Gated by the mock_zero_size_decoders module
> + * param so the default cxl_test topology, shared by the region test
> + * suite, is left undisturbed.
> + */
> +static void size_zero_mock_decoder_ep(struct cxl_decoder *cxld, u64 base)
> +{
> +	struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(&cxld->dev);
> +
> +	cxld->hpa_range = DEFINE_RANGE(base, base - 1);
> +	cxld->interleave_ways = 2;
> +	cxld->interleave_granularity = 4096;
> +	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
> +	cxld->flags = CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK;
> +	cxled->state = CXL_DECODER_STATE_AUTO;
> +	/* decoder[0] reserved [0, size/2), empty decoders sit at that watermark */
> +	devm_cxl_dpa_reserve(cxled, mock_auto_region_size / 2, 0, 0);
> +	cxld->commit = mock_decoder_commit;
> +	cxld->reset = mock_decoder_reset;
> +}
> +
> +static void size_zero_mock_decoder_sw(struct cxl_decoder *cxld, u64 base,
> +				      int level)
> +{
> +	cxld->flags = CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK;
> +	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
> +	cxld->interleave_ways = level == 0 ? 2 : 1;
> +	cxld->interleave_granularity = 4096;
> +	cxld->hpa_range = DEFINE_RANGE(base, base - 1);
> +	cxld->commit = mock_decoder_commit;
> +	cxld->reset = mock_decoder_reset;
>  }
>  
>  /*
> @@ -1131,7 +1164,7 @@ static bool mock_init_hdm_decoder(struct cxl_decoder *cxld)
>  	 * See 'cxl list -BMPu -m cxl_mem.0,cxl_mem.4'
>  	 */
>  	if (!is_endpoint_decoder(&cxld->dev) || !hb0 || pdev->id % 4 ||
> -	    pdev->id > 4 || cxld->id > 0) {
> +	    pdev->id > 4 || cxld->id > (mock_zero_size_decoders ? 2 : 0)) {
>  		default_mock_decoder(cxld);
>  		return false;
>  	}
> @@ -1145,6 +1178,20 @@ static bool mock_init_hdm_decoder(struct cxl_decoder *cxld)
>  	base = window->base_hpa;
>  	if (extended_linear_cache)
>  		base += mock_auto_region_size;
> +
> +	/*
> +	 * With mock_zero_size_decoders, decoders 1 and 2 of the special
> +	 * endpoints mock committed, locked, empty decoders above the
> +	 * decoder[0] auto-region (CXL r4.0 8.2.4.20.12). commit_end then
> +	 * points at a zero-size decoder, exercising the zero-size
> +	 * reservation and poison-by-endpoint code paths.
> +	 */
> +	if (cxld->id == 1 || cxld->id == 2) {
> +		size_zero_mock_decoder_ep(cxld, base);
> +		port->commit_end = cxld->id;
> +		WARN_ON_ONCE(!cxld_registry_new(cxld));
> +		return false;
> +	}
>  	cxld->hpa_range = (struct range) {
>  		.start = base,
>  		.end = base + mock_auto_region_size - 1,
> @@ -1168,9 +1215,11 @@ static bool mock_init_hdm_decoder(struct cxl_decoder *cxld)
>  	 */
>  	iter = port;
>  	for (i = 0; i < 2; i++) {
> +		int id = 0;
> +
>  		dport = iter->parent_dport;
>  		iter = dport->port;
> -		dev = device_find_child(&iter->dev, NULL, first_decoder);
> +		dev = device_find_child(&iter->dev, &id, match_decoder_by_index);
>  		/*
>  		 * Ancestor ports are guaranteed to be enumerated before
>  		 * @port, and all ports have at least one decoder.
> @@ -1214,6 +1263,26 @@ static bool mock_init_hdm_decoder(struct cxl_decoder *cxld)
>  
>  		cxld_registry_update(cxld);
>  		put_device(dev);
> +
> +		if (!mock_zero_size_decoders)
> +			continue;
> +
> +		/*
> +		 * Mirror the endpoint: commit the next two switch decoders
> +		 * as zero-size + locked so the empty-decoder layout extends
> +		 * end-to-end through the switch and host bridge.
> +		 */
> +		for (id = 1; id <= 2; id++) {
> +			dev = device_find_child(&iter->dev, &id,
> +						match_decoder_by_index);
> +			if (WARN_ON(!dev))
> +				continue;
> +			cxld = to_cxl_decoder(dev);
> +			size_zero_mock_decoder_sw(cxld, base, i);
> +			iter->commit_end = id;
> +			cxld_registry_update(cxld);
> +			put_device(dev);
> +		}
>  	}
>  
>  	return false;
> @@ -2049,6 +2118,9 @@ module_param(extended_linear_cache, bool, 0444);
>  MODULE_PARM_DESC(extended_linear_cache, "Enable extended linear cache support");
>  module_param(fail_autoassemble, bool, 0444);
>  MODULE_PARM_DESC(fail_autoassemble, "Simulate missing member of an auto-region");
> +module_param(mock_zero_size_decoders, bool, 0444);
> +MODULE_PARM_DESC(mock_zero_size_decoders,
> +		 "Mock committed, locked, empty decoders under host-bridge0");
>  module_init(cxl_test_init);
>  module_exit(cxl_test_exit);
>  MODULE_LICENSE("GPL v2");


      reply	other threads:[~2026-07-06 17:01 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-25  9:28 [PATCH v6 0/2] Support zero-sized HDM decoders Richard Cheng
2026-06-25  9:28 ` [PATCH v6 1/2] cxl/hdm: Allow zero sized " Richard Cheng
2026-06-25  9:28 ` [PATCH v6 2/2] tools/testing/cxl: Enable zero sized decoders under hb0 Richard Cheng
2026-07-06 17:01   ` Dave Jiang [this message]

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=c6fa720a-6ee3-46c8-9c6f-dc57f802059d@intel.com \
    --to=dave.jiang@intel.com \
    --cc=alison.schofield@intel.com \
    --cc=danwilliams@nvidia.com \
    --cc=dave@stgolabs.net \
    --cc=djbw@kernel.org \
    --cc=icheng@nvidia.com \
    --cc=iweiny@kernel.org \
    --cc=jic23@kernel.org \
    --cc=kaihengf@nvidia.com \
    --cc=kees@kernel.org \
    --cc=kobak@nvidia.com \
    --cc=kristinc@nvidia.com \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ming.li@zohomail.com \
    --cc=mochs@nvidia.com \
    --cc=newtonl@nvidia.com \
    --cc=vaslot@nvidia.com \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome