[PATCH v2 06/15] cxl/region: Use endpoint's HPA range to find the port's decoder

Robert Richter posted 15 patches 10 months ago
[PATCH v2 06/15] cxl/region: Use endpoint's HPA range to find the port's decoder
Posted by Robert Richter 10 months ago
For the implementation of address translation it might not be possible
to determine the root decoder in the early enumeration state since the
SPA range is still unknown. Instead, the endpoint's HPA range is known
and from there the topology can be traversed up to the root port while
the memory range is adjusted from one memory domain to the next up to
the root port.

In a first step, use endpoint's HPA range to find the port's decoder.
Without address translation HPA == SPA, so the endpoint's HPA range
can be used since it is the same as the root decoder's.

Signed-off-by: Robert Richter <rrichter@amd.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
---
 drivers/cxl/core/region.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index d898c9f51113..5048511f9de5 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -872,9 +872,8 @@ static int cxl_port_calc_hpa(struct cxl_port *port, struct cxl_decoder *cxld,
 
 static int match_auto_decoder(struct device *dev, const void *data)
 {
-	const struct cxl_region_params *p = data;
+	const struct range *r, *hpa = data;
 	struct cxl_decoder *cxld;
-	struct range *r;
 
 	if (!is_switch_decoder(dev))
 		return 0;
@@ -882,7 +881,7 @@ static int match_auto_decoder(struct device *dev, const void *data)
 	cxld = to_cxl_decoder(dev);
 	r = &cxld->hpa_range;
 
-	if (p->res && p->res->start == r->start && p->res->end == r->end)
+	if (hpa && hpa->start == r->start && hpa->end == r->end)
 		return 1;
 
 	return 0;
@@ -906,7 +905,7 @@ cxl_find_decoder_early(struct cxl_port *port,
 		return &cxled->cxld;
 
 	if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags))
-		dev = device_find_child(&port->dev, &cxlr->params,
+		dev = device_find_child(&port->dev, &cxled->cxld.hpa_range,
 					match_auto_decoder);
 	else
 		dev = device_find_child(&port->dev, NULL, match_free_decoder);
-- 
2.39.5
Re: [PATCH v2 06/15] cxl/region: Use endpoint's HPA range to find the port's decoder
Posted by Gregory Price 7 months, 4 weeks ago
On Tue, Feb 18, 2025 at 02:23:47PM +0100, Robert Richter wrote:
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index d898c9f51113..5048511f9de5 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -906,7 +905,7 @@ cxl_find_decoder_early(struct cxl_port *port,
>  		return &cxled->cxld;
>  
>  	if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags))
> -		dev = device_find_child(&port->dev, &cxlr->params,
> +		dev = device_find_child(&port->dev, &cxled->cxld.hpa_range,
>  					match_auto_decoder);

This semantic has now changed because of the linear caching set.

Working around this with something like this hack for now

Probably we want to pull the range out of the resource and put it right
in the params instead of the local variable, but just getting it working
for testing for now

~Gregory

---

diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index eac873125e6d..c8d38ce55045 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -833,7 +833,8 @@ static int match_free_decoder(struct device *dev, const void *data)
 }

 static bool region_res_match_cxl_range(const struct cxl_region_params *p,
-				       struct range *range)
+				       const struct range *range1,
+				       const struct range *range2)
 {
 	if (!p->res)
 		return false;
@@ -843,8 +844,8 @@ static bool region_res_match_cxl_range(const struct cxl_region_params *p,
 	 * to be fronted by the DRAM range in current known implementation.
 	 * This assumption will be made until a variant implementation exists.
 	 */
-	return p->res->start + p->cache_size == range->start &&
-		p->res->end == range->end;
+	return range1->start + p->cache_size == range2->start &&
+		range1->end == range2->end;
 }

 static int cxl_port_calc_hpa(struct cxl_port *port, struct cxl_decoder *cxld,
@@ -885,11 +886,15 @@ static int cxl_port_calc_hpa(struct cxl_port *port, struct cxl_decoder *cxld,
 	return 1;
 }

+struct mad_context {
+	struct cxl_region_params *p;
+	struct range *r;
+};
 static int match_auto_decoder(struct device *dev, const void *data)
 {
-	const struct cxl_region_params *p = data;
+	const struct range *r;
 	struct cxl_decoder *cxld;
-	struct range *r;
+	const struct mad_context *ctx = data;

 	if (!is_switch_decoder(dev))
 		return 0;
@@ -897,7 +902,7 @@ static int match_auto_decoder(struct device *dev, const void *data)
 	cxld = to_cxl_decoder(dev);
 	r = &cxld->hpa_range;

-	if (region_res_match_cxl_range(p, r))
+	if (region_res_match_cxl_range(ctx->p, ctx->r, r))
 		return 1;

 	return 0;
@@ -916,13 +921,14 @@ cxl_find_decoder_early(struct cxl_port *port,
 		       struct cxl_region *cxlr)
 {
 	struct device *dev;
+	struct mad_context mad = { .p = &cxlr->params,
+				   .r =&cxled->cxld.hpa_range };

 	if (port == cxled_to_port(cxled))
 		return &cxled->cxld;

 	if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags))
-		dev = device_find_child(&port->dev, &cxlr->params,
-					match_auto_decoder);
+		dev = device_find_child(&port->dev, &mad, match_auto_decoder);
 	else
 		dev = device_find_child(&port->dev, NULL, match_free_decoder);
 	if (!dev)
@@ -1363,6 +1369,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
 	struct cxl_decoder *cxld = cxl_rr->decoder;
 	struct cxl_switch_decoder *cxlsd;
 	struct cxl_port *iter = port;
+	struct range r;
 	u16 eig, peig;
 	u8 eiw, peiw;

@@ -1488,10 +1495,12 @@ static int cxl_port_setup_targets(struct cxl_port *port,
 		return -ENXIO;
 	}

+	r.start = p ? p->res->start : 0;
+	r.end = p ? p->res->end : 0;
 	if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) {
 		if (cxld->interleave_ways != iw ||
 		    cxld->interleave_granularity != ig ||
-		    !region_res_match_cxl_range(p, &cxld->hpa_range) ||
+		    !region_res_match_cxl_range(p, &r, &cxld->hpa_range) ||
 		    ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)) {
 			dev_err(&cxlr->dev,
 				"%s:%s %s expected iw: %d ig: %d %pr\n",
Re: [PATCH v2 06/15] cxl/region: Use endpoint's HPA range to find the port's decoder
Posted by Gregory Price 7 months, 4 weeks ago
On Wed, Apr 23, 2025 at 08:28:03PM -0400, Gregory Price wrote:
> @@ -916,13 +921,14 @@ cxl_find_decoder_early(struct cxl_port *port,
>  		       struct cxl_region *cxlr)
>  {
>  	struct device *dev;
> +	struct mad_context mad = { .p = &cxlr->params,
> +				   .r =&cxled->cxld.hpa_range };
                                               ^^^^^^^^^^^^^^
					       spa_range

Woops, missed this.  Not sure if it goes here or a later patch, but
that's needed to make this work.

~Gregory
Re: [PATCH v2 06/15] cxl/region: Use endpoint's HPA range to find the port's decoder
Posted by Gregory Price 7 months, 4 weeks ago
On Thu, Apr 24, 2025 at 05:49:35PM -0400, Gregory Price wrote:
> On Wed, Apr 23, 2025 at 08:28:03PM -0400, Gregory Price wrote:
> > @@ -916,13 +921,14 @@ cxl_find_decoder_early(struct cxl_port *port,
> >  		       struct cxl_region *cxlr)
> >  {
> >  	struct device *dev;
> > +	struct mad_context mad = { .p = &cxlr->params,
> > +				   .r =&cxled->cxld.hpa_range };
>                                                ^^^^^^^^^^^^^^
> 					       spa_range
> 
> Woops, missed this.  Not sure if it goes here or a later patch, but
> that's needed to make this work.
> 
> ~Gregory

And for the sake of completeness - I've confirmed that this is
sufficient to get a Zen5 working on top of

   v6.13 + (v6.14, v6.15, cxl-next) PCI/CXL backports

So a smaller set of changes than I was expecting (some other mild fixups
but nothing major).  Just kind of have to decide what the shape of this
change looks like, if not like this.

I can share my modified line if you'd like, but I haven't incorporated
any suggestions from the chain here.

~Gregory