Skip to content

Commit 0a105ab

Browse files
AlisonSchofielddjbw
authored andcommitted
cxl/memdev: Warn of poison inject or clear to a mapped region
Inject and clear poison capabilities and intended for debug usage only. In order to be useful in debug environments, the driver needs to allow inject and clear operations on DPAs mapped in regions. dev_warn_once() when either operation occurs. Signed-off-by: Alison Schofield <alison.schofield@intel.com> Link: https://lore.kernel.org/r/f911ca5277c9d0f9757b72d7e6842871bfff4fa2.1681874357.git.alison.schofield@intel.com Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 9690b07 commit 0a105ab

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

drivers/cxl/core/memdev.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,50 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
160160
}
161161
EXPORT_SYMBOL_NS_GPL(cxl_trigger_poison_list, CXL);
162162

163+
struct cxl_dpa_to_region_context {
164+
struct cxl_region *cxlr;
165+
u64 dpa;
166+
};
167+
168+
static int __cxl_dpa_to_region(struct device *dev, void *arg)
169+
{
170+
struct cxl_dpa_to_region_context *ctx = arg;
171+
struct cxl_endpoint_decoder *cxled;
172+
u64 dpa = ctx->dpa;
173+
174+
if (!is_endpoint_decoder(dev))
175+
return 0;
176+
177+
cxled = to_cxl_endpoint_decoder(dev);
178+
if (!cxled->dpa_res || !resource_size(cxled->dpa_res))
179+
return 0;
180+
181+
if (dpa > cxled->dpa_res->end || dpa < cxled->dpa_res->start)
182+
return 0;
183+
184+
dev_dbg(dev, "dpa:0x%llx mapped in region:%s\n", dpa,
185+
dev_name(&cxled->cxld.region->dev));
186+
187+
ctx->cxlr = cxled->cxld.region;
188+
189+
return 1;
190+
}
191+
192+
static struct cxl_region *cxl_dpa_to_region(struct cxl_memdev *cxlmd, u64 dpa)
193+
{
194+
struct cxl_dpa_to_region_context ctx;
195+
struct cxl_port *port;
196+
197+
ctx = (struct cxl_dpa_to_region_context) {
198+
.dpa = dpa,
199+
};
200+
port = dev_get_drvdata(&cxlmd->dev);
201+
if (port && is_cxl_endpoint(port) && port->commit_end != -1)
202+
device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region);
203+
204+
return ctx.cxlr;
205+
}
206+
163207
static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
164208
{
165209
struct cxl_dev_state *cxlds = cxlmd->cxlds;
@@ -189,6 +233,7 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
189233
struct cxl_dev_state *cxlds = cxlmd->cxlds;
190234
struct cxl_mbox_inject_poison inject;
191235
struct cxl_mbox_cmd mbox_cmd;
236+
struct cxl_region *cxlr;
192237
int rc;
193238

194239
if (!IS_ENABLED(CONFIG_DEBUG_FS))
@@ -209,6 +254,14 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
209254
.payload_in = &inject,
210255
};
211256
rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
257+
if (rc)
258+
goto out;
259+
260+
cxlr = cxl_dpa_to_region(cxlmd, dpa);
261+
if (cxlr)
262+
dev_warn_once(cxlds->dev,
263+
"poison inject dpa:%#llx region: %s\n", dpa,
264+
dev_name(&cxlr->dev));
212265
out:
213266
up_read(&cxl_dpa_rwsem);
214267

@@ -221,6 +274,7 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
221274
struct cxl_dev_state *cxlds = cxlmd->cxlds;
222275
struct cxl_mbox_clear_poison clear;
223276
struct cxl_mbox_cmd mbox_cmd;
277+
struct cxl_region *cxlr;
224278
int rc;
225279

226280
if (!IS_ENABLED(CONFIG_DEBUG_FS))
@@ -252,6 +306,11 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
252306
rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
253307
if (rc)
254308
goto out;
309+
310+
cxlr = cxl_dpa_to_region(cxlmd, dpa);
311+
if (cxlr)
312+
dev_warn_once(cxlds->dev, "poison clear dpa:%#llx region: %s\n",
313+
dpa, dev_name(&cxlr->dev));
255314
out:
256315
up_read(&cxl_dpa_rwsem);
257316

0 commit comments

Comments
 (0)