Skip to content

Commit

Permalink
cxl/region: Match auto-discovered region decoders by HPA range
Browse files Browse the repository at this point in the history
Currently, when the region driver attaches a region to a port, it
selects the ports next available decoder to program.

With the addition of auto-discovered regions, a port decoder has
already been programmed so grabbing the next available decoder can
be a mismatch when there is more than one region using the port.

The failure appears like this with CXL DEBUG enabled:

[] cxl_core:alloc_region_ref:754: cxl region0: endpoint9: HPA order violation region0:[mem 0x14780000000-0x1478fffffff flags 0x200] vs [mem 0x880000000-0x185fffffff flags 0x200]
[] cxl_core:cxl_port_attach_region:972: cxl region0: endpoint9: failed to allocate region reference

When CXL DEBUG is not enabled, there is no failure message. The region
just never materializes. Users can suspect this issue if they know their
firmware has programmed decoders so that more than one region is using
a port. Note that the problem may appear intermittently, ie not on
every reboot.

Add a matching method for auto-discovered regions that finds a decoder
based on an HPA range. The decoder range must exactly match the region
resource parameter.

Fixes: a32320b ("cxl/region: Add region autodiscovery")
Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Davidlohr Bueso <dave@stgolabs.net>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/20230905211007.256385-1-alison.schofield@intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
  • Loading branch information
Alison Schofield authored and Dan Williams committed Sep 15, 2023
1 parent d2f7060 commit 9e4edf1
Showing 1 changed file with 23 additions and 1 deletion.
24 changes: 23 additions & 1 deletion drivers/cxl/core/region.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,13 +717,35 @@ static int match_free_decoder(struct device *dev, void *data)
return 0;
}

static int match_auto_decoder(struct device *dev, void *data)
{
struct cxl_region_params *p = data;
struct cxl_decoder *cxld;
struct range *r;

if (!is_switch_decoder(dev))
return 0;

cxld = to_cxl_decoder(dev);
r = &cxld->hpa_range;

if (p->res && p->res->start == r->start && p->res->end == r->end)
return 1;

return 0;
}

static struct cxl_decoder *cxl_region_find_decoder(struct cxl_port *port,
struct cxl_region *cxlr)
{
struct device *dev;
int id = 0;

dev = device_find_child(&port->dev, &id, match_free_decoder);
if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags))
dev = device_find_child(&port->dev, &cxlr->params,
match_auto_decoder);
else
dev = device_find_child(&port->dev, &id, match_free_decoder);
if (!dev)
return NULL;
/*
Expand Down

0 comments on commit 9e4edf1

Please sign in to comment.