Skip to content

Commit 5459e18

Browse files
committed
cxl/port: Fix missing target list lock
cxl_port_setup_targets() modifies the ->targets[] array of a switch decoder. target_list_show() expects to be able to emit a coherent snapshot of that array by "holding" ->target_lock for read. The target_lock is held for write during initialization of the ->targets[] array, but it is not held for write during cxl_port_setup_targets(). The ->target_lock() predates the introduction of @cxl_region_rwsem. That semaphore protects changes to host-physical-address (HPA) decode which is precisely what writes to a switch decoder's target list affects. Replace ->target_lock with @cxl_region_rwsem. Now the side-effect of snapshotting a unstable view of a decoder's target list is likely benign so the Fixes: tag is presumptive. Fixes: 27b3f8d ("cxl/region: Program target lists") Reviewed-by: Alison Schofield <alison.schofield@intel.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent d6488fe commit 5459e18

2 files changed

Lines changed: 7 additions & 17 deletions

File tree

drivers/cxl/core/port.c

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,10 @@ static ssize_t target_list_show(struct device *dev,
172172
{
173173
struct cxl_switch_decoder *cxlsd = to_cxl_switch_decoder(dev);
174174
ssize_t offset;
175-
unsigned int seq;
176175
int rc;
177176

178-
do {
179-
seq = read_seqbegin(&cxlsd->target_lock);
180-
rc = emit_target_list(cxlsd, buf);
181-
} while (read_seqretry(&cxlsd->target_lock, seq));
182-
177+
guard(rwsem_read)(&cxl_region_rwsem);
178+
rc = emit_target_list(cxlsd, buf);
183179
if (rc < 0)
184180
return rc;
185181
offset = rc;
@@ -1633,7 +1629,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_mem_find_port, CXL);
16331629
static int decoder_populate_targets(struct cxl_switch_decoder *cxlsd,
16341630
struct cxl_port *port, int *target_map)
16351631
{
1636-
int i, rc = 0;
1632+
int i;
16371633

16381634
if (!target_map)
16391635
return 0;
@@ -1643,19 +1639,16 @@ static int decoder_populate_targets(struct cxl_switch_decoder *cxlsd,
16431639
if (xa_empty(&port->dports))
16441640
return -EINVAL;
16451641

1646-
write_seqlock(&cxlsd->target_lock);
1642+
guard(rwsem_write)(&cxl_region_rwsem);
16471643
for (i = 0; i < cxlsd->cxld.interleave_ways; i++) {
16481644
struct cxl_dport *dport = find_dport(port, target_map[i]);
16491645

1650-
if (!dport) {
1651-
rc = -ENXIO;
1652-
break;
1653-
}
1646+
if (!dport)
1647+
return -ENXIO;
16541648
cxlsd->target[i] = dport;
16551649
}
1656-
write_sequnlock(&cxlsd->target_lock);
16571650

1658-
return rc;
1651+
return 0;
16591652
}
16601653

16611654
struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos)
@@ -1725,7 +1718,6 @@ static int cxl_switch_decoder_init(struct cxl_port *port,
17251718
return -EINVAL;
17261719

17271720
cxlsd->nr_targets = nr_targets;
1728-
seqlock_init(&cxlsd->target_lock);
17291721
return cxl_decoder_init(port, &cxlsd->cxld);
17301722
}
17311723

drivers/cxl/cxl.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,6 @@ struct cxl_endpoint_decoder {
412412
/**
413413
* struct cxl_switch_decoder - Switch specific CXL HDM Decoder
414414
* @cxld: base cxl_decoder object
415-
* @target_lock: coordinate coherent reads of the target list
416415
* @nr_targets: number of elements in @target
417416
* @target: active ordered target list in current decoder configuration
418417
*
@@ -424,7 +423,6 @@ struct cxl_endpoint_decoder {
424423
*/
425424
struct cxl_switch_decoder {
426425
struct cxl_decoder cxld;
427-
seqlock_t target_lock;
428426
int nr_targets;
429427
struct cxl_dport *target[];
430428
};

0 commit comments

Comments
 (0)