Skip to content

Commit 9e4edf1

Browse files
AlisonSchofielddjbw
authored andcommitted
cxl/region: Match auto-discovered region decoders by HPA range
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 <[email protected]> Reviewed-by: Dave Jiang <[email protected]> Reviewed-by: Davidlohr Bueso <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dan Williams <[email protected]>
1 parent d2f7060 commit 9e4edf1

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

drivers/cxl/core/region.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,13 +717,35 @@ static int match_free_decoder(struct device *dev, void *data)
717717
return 0;
718718
}
719719

720+
static int match_auto_decoder(struct device *dev, void *data)
721+
{
722+
struct cxl_region_params *p = data;
723+
struct cxl_decoder *cxld;
724+
struct range *r;
725+
726+
if (!is_switch_decoder(dev))
727+
return 0;
728+
729+
cxld = to_cxl_decoder(dev);
730+
r = &cxld->hpa_range;
731+
732+
if (p->res && p->res->start == r->start && p->res->end == r->end)
733+
return 1;
734+
735+
return 0;
736+
}
737+
720738
static struct cxl_decoder *cxl_region_find_decoder(struct cxl_port *port,
721739
struct cxl_region *cxlr)
722740
{
723741
struct device *dev;
724742
int id = 0;
725743

726-
dev = device_find_child(&port->dev, &id, match_free_decoder);
744+
if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags))
745+
dev = device_find_child(&port->dev, &cxlr->params,
746+
match_auto_decoder);
747+
else
748+
dev = device_find_child(&port->dev, &id, match_free_decoder);
727749
if (!dev)
728750
return NULL;
729751
/*

0 commit comments

Comments
 (0)