Skip to content

Commit 9995576

Browse files
committed
cxl/region: Move region-position validation to a helper
In preparation for region autodiscovery, that needs all devices discovered before their relative position in the region can be determined, consolidate all position dependent validation in a helper. Recall that in the on-demand region creation flow the end-user picks the position of a given endpoint decoder in a region. In the autodiscovery case the position of an endpoint decoder can only be determined after all other endpoint decoders that claim to decode the region's address range have been enumerated and attached. So, in the autodiscovery case endpoint decoders may be attached before their relative position is known. Once all decoders arrive, then positions can be determined and validated with cxl_region_validate_position() the same as user initiated on-demand creation. Reviewed-by: Vishal Verma <[email protected]> Tested-by: Fan Ni <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Link: https://lore.kernel.org/r/167601997584.1924368.4615769326126138969.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams <[email protected]>
1 parent 86987c7 commit 9995576

File tree

1 file changed

+76
-43
lines changed

1 file changed

+76
-43
lines changed

drivers/cxl/core/region.c

Lines changed: 76 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,35 +1211,13 @@ static int cxl_region_setup_targets(struct cxl_region *cxlr)
12111211
return 0;
12121212
}
12131213

1214-
static int cxl_region_attach(struct cxl_region *cxlr,
1215-
struct cxl_endpoint_decoder *cxled, int pos)
1214+
static int cxl_region_validate_position(struct cxl_region *cxlr,
1215+
struct cxl_endpoint_decoder *cxled,
1216+
int pos)
12161217
{
1217-
struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent);
12181218
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
1219-
struct cxl_port *ep_port, *root_port, *iter;
12201219
struct cxl_region_params *p = &cxlr->params;
1221-
struct cxl_dport *dport;
1222-
int i, rc = -ENXIO;
1223-
1224-
if (cxled->mode != cxlr->mode) {
1225-
dev_dbg(&cxlr->dev, "%s region mode: %d mismatch: %d\n",
1226-
dev_name(&cxled->cxld.dev), cxlr->mode, cxled->mode);
1227-
return -EINVAL;
1228-
}
1229-
1230-
if (cxled->mode == CXL_DECODER_DEAD) {
1231-
dev_dbg(&cxlr->dev, "%s dead\n", dev_name(&cxled->cxld.dev));
1232-
return -ENODEV;
1233-
}
1234-
1235-
/* all full of members, or interleave config not established? */
1236-
if (p->state > CXL_CONFIG_INTERLEAVE_ACTIVE) {
1237-
dev_dbg(&cxlr->dev, "region already active\n");
1238-
return -EBUSY;
1239-
} else if (p->state < CXL_CONFIG_INTERLEAVE_ACTIVE) {
1240-
dev_dbg(&cxlr->dev, "interleave config missing\n");
1241-
return -ENXIO;
1242-
}
1220+
int i;
12431221

12441222
if (pos < 0 || pos >= p->interleave_ways) {
12451223
dev_dbg(&cxlr->dev, "position %d out of range %d\n", pos,
@@ -1278,6 +1256,71 @@ static int cxl_region_attach(struct cxl_region *cxlr,
12781256
}
12791257
}
12801258

1259+
return 0;
1260+
}
1261+
1262+
static int cxl_region_attach_position(struct cxl_region *cxlr,
1263+
struct cxl_root_decoder *cxlrd,
1264+
struct cxl_endpoint_decoder *cxled,
1265+
const struct cxl_dport *dport, int pos)
1266+
{
1267+
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
1268+
struct cxl_port *iter;
1269+
int rc;
1270+
1271+
if (cxlrd->calc_hb(cxlrd, pos) != dport) {
1272+
dev_dbg(&cxlr->dev, "%s:%s invalid target position for %s\n",
1273+
dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
1274+
dev_name(&cxlrd->cxlsd.cxld.dev));
1275+
return -ENXIO;
1276+
}
1277+
1278+
for (iter = cxled_to_port(cxled); !is_cxl_root(iter);
1279+
iter = to_cxl_port(iter->dev.parent)) {
1280+
rc = cxl_port_attach_region(iter, cxlr, cxled, pos);
1281+
if (rc)
1282+
goto err;
1283+
}
1284+
1285+
return 0;
1286+
1287+
err:
1288+
for (iter = cxled_to_port(cxled); !is_cxl_root(iter);
1289+
iter = to_cxl_port(iter->dev.parent))
1290+
cxl_port_detach_region(iter, cxlr, cxled);
1291+
return rc;
1292+
}
1293+
1294+
static int cxl_region_attach(struct cxl_region *cxlr,
1295+
struct cxl_endpoint_decoder *cxled, int pos)
1296+
{
1297+
struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent);
1298+
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
1299+
struct cxl_region_params *p = &cxlr->params;
1300+
struct cxl_port *ep_port, *root_port;
1301+
struct cxl_dport *dport;
1302+
int rc = -ENXIO;
1303+
1304+
if (cxled->mode != cxlr->mode) {
1305+
dev_dbg(&cxlr->dev, "%s region mode: %d mismatch: %d\n",
1306+
dev_name(&cxled->cxld.dev), cxlr->mode, cxled->mode);
1307+
return -EINVAL;
1308+
}
1309+
1310+
if (cxled->mode == CXL_DECODER_DEAD) {
1311+
dev_dbg(&cxlr->dev, "%s dead\n", dev_name(&cxled->cxld.dev));
1312+
return -ENODEV;
1313+
}
1314+
1315+
/* all full of members, or interleave config not established? */
1316+
if (p->state > CXL_CONFIG_INTERLEAVE_ACTIVE) {
1317+
dev_dbg(&cxlr->dev, "region already active\n");
1318+
return -EBUSY;
1319+
} else if (p->state < CXL_CONFIG_INTERLEAVE_ACTIVE) {
1320+
dev_dbg(&cxlr->dev, "interleave config missing\n");
1321+
return -ENXIO;
1322+
}
1323+
12811324
ep_port = cxled_to_port(cxled);
12821325
root_port = cxlrd_to_port(cxlrd);
12831326
dport = cxl_find_dport_by_dev(root_port, ep_port->host_bridge);
@@ -1288,13 +1331,6 @@ static int cxl_region_attach(struct cxl_region *cxlr,
12881331
return -ENXIO;
12891332
}
12901333

1291-
if (cxlrd->calc_hb(cxlrd, pos) != dport) {
1292-
dev_dbg(&cxlr->dev, "%s:%s invalid target position for %s\n",
1293-
dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
1294-
dev_name(&cxlrd->cxlsd.cxld.dev));
1295-
return -ENXIO;
1296-
}
1297-
12981334
if (cxled->cxld.target_type != cxlr->type) {
12991335
dev_dbg(&cxlr->dev, "%s:%s type mismatch: %d vs %d\n",
13001336
dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
@@ -1318,12 +1354,13 @@ static int cxl_region_attach(struct cxl_region *cxlr,
13181354
return -EINVAL;
13191355
}
13201356

1321-
for (iter = ep_port; !is_cxl_root(iter);
1322-
iter = to_cxl_port(iter->dev.parent)) {
1323-
rc = cxl_port_attach_region(iter, cxlr, cxled, pos);
1324-
if (rc)
1325-
goto err;
1326-
}
1357+
rc = cxl_region_validate_position(cxlr, cxled, pos);
1358+
if (rc)
1359+
return rc;
1360+
1361+
rc = cxl_region_attach_position(cxlr, cxlrd, cxled, dport, pos);
1362+
if (rc)
1363+
return rc;
13271364

13281365
p->targets[pos] = cxled;
13291366
cxled->pos = pos;
@@ -1349,10 +1386,6 @@ static int cxl_region_attach(struct cxl_region *cxlr,
13491386
p->nr_targets--;
13501387
cxled->pos = -1;
13511388
p->targets[pos] = NULL;
1352-
err:
1353-
for (iter = ep_port; !is_cxl_root(iter);
1354-
iter = to_cxl_port(iter->dev.parent))
1355-
cxl_port_detach_region(iter, cxlr, cxled);
13561389
return rc;
13571390
}
13581391

0 commit comments

Comments
 (0)