Skip to content

Commit

Permalink
cxl/region: Fix 'distance' calculation with passthrough ports
Browse files Browse the repository at this point in the history
When programming port decode targets, the algorithm wants to ensure that
two devices are compatible to be programmed as peers beneath a given
port. A compatible peer is a target that shares the same dport, and
where that target's interleave position also routes it to the same
dport. Compatibility is determined by the device's interleave position
being >= to distance. For example, if a given dport can only map every
Nth position then positions less than N away from the last target
programmed are incompatible.

The @distance for the host-bridge's cxl_port in a simple dual-ported
host-bridge configuration with 2 direct-attached devices is 1, i.e. An
x2 region divided by 2 dports to reach 2 region targets.

An x4 region under an x2 host-bridge would need 2 intervening switches
where the @distance at the host bridge level is 2 (x4 region divided by
2 switches to reach 4 devices).

However, the distance between peers underneath a single ported
host-bridge is always zero because there is no limit to the number of
devices that can be mapped. In other words, there are no decoders to
program in a passthrough, all descendants are mapped and distance only
starts matters for the intervening descendant ports of the passthrough
port.

Add tracking for the number of dports mapped to a port, and use that to
detect the passthrough case for calculating @distance.

Cc: <[email protected]>
Reported-by: Bobo WL <[email protected]>
Reported-by: Jonathan Cameron <[email protected]>
Link: http://lore.kernel.org/r/[email protected]
Fixes: 27b3f8d ("cxl/region: Program target lists")
Reviewed-by: Vishal Verma <[email protected]>
Link: https://lore.kernel.org/r/166752185440.947915.6617495912508299445.stgit@dwillia2-xfh.jf.intel.com
Signed-off-by: Dan Williams <[email protected]>
  • Loading branch information
djbw committed Nov 4, 2022
1 parent e41c845 commit e4f6dfa
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 3 deletions.
11 changes: 9 additions & 2 deletions drivers/cxl/core/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,7 @@ static struct cxl_dport *find_dport(struct cxl_port *port, int id)
static int add_dport(struct cxl_port *port, struct cxl_dport *new)
{
struct cxl_dport *dup;
int rc;

device_lock_assert(&port->dev);
dup = find_dport(port, new->port_id);
Expand All @@ -821,8 +822,14 @@ static int add_dport(struct cxl_port *port, struct cxl_dport *new)
dev_name(dup->dport));
return -EBUSY;
}
return xa_insert(&port->dports, (unsigned long)new->dport, new,
GFP_KERNEL);

rc = xa_insert(&port->dports, (unsigned long)new->dport, new,
GFP_KERNEL);
if (rc)
return rc;

port->nr_dports++;
return 0;
}

/*
Expand Down
9 changes: 8 additions & 1 deletion drivers/cxl/core/region.c
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,14 @@ static int cxl_port_setup_targets(struct cxl_port *port,
if (cxl_rr->nr_targets_set) {
int i, distance;

distance = p->nr_targets / cxl_rr->nr_targets;
/*
* Passthrough ports impose no distance requirements between
* peers
*/
if (port->nr_dports == 1)
distance = 0;
else
distance = p->nr_targets / cxl_rr->nr_targets;
for (i = 0; i < cxl_rr->nr_targets_set; i++)
if (ep->dport == cxlsd->target[i]) {
rc = check_last_peer(cxled, ep, cxl_rr,
Expand Down
2 changes: 2 additions & 0 deletions drivers/cxl/cxl.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ struct cxl_pmem_region {
* @regions: cxl_region_ref instances, regions mapped by this port
* @parent_dport: dport that points to this port in the parent
* @decoder_ida: allocator for decoder ids
* @nr_dports: number of entries in @dports
* @hdm_end: track last allocated HDM decoder instance for allocation ordering
* @commit_end: cursor to track highest committed decoder for commit ordering
* @component_reg_phys: component register capability base address (optional)
Expand All @@ -475,6 +476,7 @@ struct cxl_port {
struct xarray regions;
struct cxl_dport *parent_dport;
struct ida decoder_ida;
int nr_dports;
int hdm_end;
int commit_end;
resource_size_t component_reg_phys;
Expand Down

0 comments on commit e4f6dfa

Please sign in to comment.