Skip to content

Commit e2c18eb

Browse files
committed
Merge branch 'for-6.5/cxl-region-fixes' into for-6.5/cxl
Pick up the recent fixes to how CPU caches are managed relative to region setup / teardown, and make sure that all decoders transition successfully before updating the region state from COMMIT => ACTIVE.
2 parents aeaefab + adfe197 commit e2c18eb

2 files changed

Lines changed: 72 additions & 46 deletions

File tree

drivers/cxl/core/region.c

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -125,18 +125,45 @@ static struct cxl_region_ref *cxl_rr_load(struct cxl_port *port,
125125
return xa_load(&port->regions, (unsigned long)cxlr);
126126
}
127127

128+
static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
129+
{
130+
if (!cpu_cache_has_invalidate_memregion()) {
131+
if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) {
132+
dev_warn_once(
133+
&cxlr->dev,
134+
"Bypassing cpu_cache_invalidate_memregion() for testing!\n");
135+
return 0;
136+
} else {
137+
dev_err(&cxlr->dev,
138+
"Failed to synchronize CPU cache state\n");
139+
return -ENXIO;
140+
}
141+
}
142+
143+
cpu_cache_invalidate_memregion(IORES_DESC_CXL);
144+
return 0;
145+
}
146+
128147
static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
129148
{
130149
struct cxl_region_params *p = &cxlr->params;
131-
int i;
150+
int i, rc = 0;
151+
152+
/*
153+
* Before region teardown attempt to flush, and if the flush
154+
* fails cancel the region teardown for data consistency
155+
* concerns
156+
*/
157+
rc = cxl_region_invalidate_memregion(cxlr);
158+
if (rc)
159+
return rc;
132160

133161
for (i = count - 1; i >= 0; i--) {
134162
struct cxl_endpoint_decoder *cxled = p->targets[i];
135163
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
136164
struct cxl_port *iter = cxled_to_port(cxled);
137165
struct cxl_dev_state *cxlds = cxlmd->cxlds;
138166
struct cxl_ep *ep;
139-
int rc = 0;
140167

141168
if (cxlds->rcd)
142169
goto endpoint_reset;
@@ -155,14 +182,19 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
155182
rc = cxld->reset(cxld);
156183
if (rc)
157184
return rc;
185+
set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
158186
}
159187

160188
endpoint_reset:
161189
rc = cxled->cxld.reset(&cxled->cxld);
162190
if (rc)
163191
return rc;
192+
set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
164193
}
165194

195+
/* all decoders associated with this region have been torn down */
196+
clear_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
197+
166198
return 0;
167199
}
168200

@@ -256,9 +288,19 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
256288
goto out;
257289
}
258290

259-
if (commit)
291+
/*
292+
* Invalidate caches before region setup to drop any speculative
293+
* consumption of this address space
294+
*/
295+
rc = cxl_region_invalidate_memregion(cxlr);
296+
if (rc)
297+
return rc;
298+
299+
if (commit) {
260300
rc = cxl_region_decode_commit(cxlr);
261-
else {
301+
if (rc == 0)
302+
p->state = CXL_CONFIG_COMMIT;
303+
} else {
262304
p->state = CXL_CONFIG_RESET_PENDING;
263305
up_write(&cxl_region_rwsem);
264306
device_release_driver(&cxlr->dev);
@@ -268,18 +310,20 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
268310
* The lock was dropped, so need to revalidate that the reset is
269311
* still pending.
270312
*/
271-
if (p->state == CXL_CONFIG_RESET_PENDING)
313+
if (p->state == CXL_CONFIG_RESET_PENDING) {
272314
rc = cxl_region_decode_reset(cxlr, p->interleave_ways);
315+
/*
316+
* Revert to committed since there may still be active
317+
* decoders associated with this region, or move forward
318+
* to active to mark the reset successful
319+
*/
320+
if (rc)
321+
p->state = CXL_CONFIG_COMMIT;
322+
else
323+
p->state = CXL_CONFIG_ACTIVE;
324+
}
273325
}
274326

275-
if (rc)
276-
goto out;
277-
278-
if (commit)
279-
p->state = CXL_CONFIG_COMMIT;
280-
else if (p->state == CXL_CONFIG_RESET_PENDING)
281-
p->state = CXL_CONFIG_ACTIVE;
282-
283327
out:
284328
up_write(&cxl_region_rwsem);
285329

@@ -1686,7 +1730,6 @@ static int cxl_region_attach(struct cxl_region *cxlr,
16861730
if (rc)
16871731
goto err_decrement;
16881732
p->state = CXL_CONFIG_ACTIVE;
1689-
set_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
16901733
}
16911734

16921735
cxled->cxld.interleave_ways = p->interleave_ways;
@@ -2815,30 +2858,6 @@ int cxl_add_to_region(struct cxl_port *root, struct cxl_endpoint_decoder *cxled)
28152858
}
28162859
EXPORT_SYMBOL_NS_GPL(cxl_add_to_region, CXL);
28172860

2818-
static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
2819-
{
2820-
if (!test_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags))
2821-
return 0;
2822-
2823-
if (!cpu_cache_has_invalidate_memregion()) {
2824-
if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) {
2825-
dev_warn_once(
2826-
&cxlr->dev,
2827-
"Bypassing cpu_cache_invalidate_memregion() for testing!\n");
2828-
clear_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
2829-
return 0;
2830-
} else {
2831-
dev_err(&cxlr->dev,
2832-
"Failed to synchronize CPU cache state\n");
2833-
return -ENXIO;
2834-
}
2835-
}
2836-
2837-
cpu_cache_invalidate_memregion(IORES_DESC_CXL);
2838-
clear_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
2839-
return 0;
2840-
}
2841-
28422861
static int is_system_ram(struct resource *res, void *arg)
28432862
{
28442863
struct cxl_region *cxlr = arg;
@@ -2866,7 +2885,12 @@ static int cxl_region_probe(struct device *dev)
28662885
goto out;
28672886
}
28682887

2869-
rc = cxl_region_invalidate_memregion(cxlr);
2888+
if (test_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags)) {
2889+
dev_err(&cxlr->dev,
2890+
"failed to activate, re-commit region and retry\n");
2891+
rc = -ENXIO;
2892+
goto out;
2893+
}
28702894

28712895
/*
28722896
* From this point on any path that changes the region's state away from

drivers/cxl/cxl.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -470,18 +470,20 @@ struct cxl_region_params {
470470
int nr_targets;
471471
};
472472

473-
/*
474-
* Flag whether this region needs to have its HPA span synchronized with
475-
* CPU cache state at region activation time.
476-
*/
477-
#define CXL_REGION_F_INCOHERENT 0
478-
479473
/*
480474
* Indicate whether this region has been assembled by autodetection or
481475
* userspace assembly. Prevent endpoint decoders outside of automatic
482476
* detection from being added to the region.
483477
*/
484-
#define CXL_REGION_F_AUTO 1
478+
#define CXL_REGION_F_AUTO 0
479+
480+
/*
481+
* Require that a committed region successfully complete a teardown once
482+
* any of its associated decoders have been torn down. This maintains
483+
* the commit state for the region since there are committed decoders,
484+
* but blocks cxl_region_probe().
485+
*/
486+
#define CXL_REGION_F_NEEDS_RESET 1
485487

486488
/**
487489
* struct cxl_region - CXL region

0 commit comments

Comments
 (0)