Skip to content

Commit d2fbc48

Browse files
AlisonSchofielddjbw
authored andcommitted
cxl/memdev: Add support for the Inject Poison mailbox command
CXL devices optionally support the INJECT POISON mailbox command. Add memdev driver support for the mailbox command. Per the CXL Specification (3.0 8.2.9.8.4.2), after receiving a valid inject poison request, the device will return poison when the address is accessed through the CXL.mem driver. Injecting poison adds the address to the device's Poison List and the error source is set to Injected. In addition, the device adds a poison creation event to its internal Informational Event log, updates the Event Status register, and if configured, interrupts the host. Also, per the CXL Specification, it is not an error to inject poison into an address that already has poison present and no error is returned from the device. If the address is not contained in the device's dpa resource, or is not 64 byte aligned, return -EINVAL without issuing the mbox command. Poison injection is intended for debug only and will be exposed to userspace through debugfs. Restrict compilation to CONFIG_DEBUG_FS. Signed-off-by: Alison Schofield <alison.schofield@intel.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Link: https://lore.kernel.org/r/241c64115e6bd2effed9c7a20b08b3908dd7be8f.1681874357.git.alison.schofield@intel.com Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent f8d22bf commit d2fbc48

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

drivers/cxl/core/memdev.c

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

163+
static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
164+
{
165+
struct cxl_dev_state *cxlds = cxlmd->cxlds;
166+
167+
if (!IS_ENABLED(CONFIG_DEBUG_FS))
168+
return 0;
169+
170+
if (!resource_size(&cxlds->dpa_res)) {
171+
dev_dbg(cxlds->dev, "device has no dpa resource\n");
172+
return -EINVAL;
173+
}
174+
if (dpa < cxlds->dpa_res.start || dpa > cxlds->dpa_res.end) {
175+
dev_dbg(cxlds->dev, "dpa:0x%llx not in resource:%pR\n",
176+
dpa, &cxlds->dpa_res);
177+
return -EINVAL;
178+
}
179+
if (!IS_ALIGNED(dpa, 64)) {
180+
dev_dbg(cxlds->dev, "dpa:0x%llx is not 64-byte aligned\n", dpa);
181+
return -EINVAL;
182+
}
183+
184+
return 0;
185+
}
186+
187+
int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
188+
{
189+
struct cxl_dev_state *cxlds = cxlmd->cxlds;
190+
struct cxl_mbox_inject_poison inject;
191+
struct cxl_mbox_cmd mbox_cmd;
192+
int rc;
193+
194+
if (!IS_ENABLED(CONFIG_DEBUG_FS))
195+
return 0;
196+
197+
rc = down_read_interruptible(&cxl_dpa_rwsem);
198+
if (rc)
199+
return rc;
200+
201+
rc = cxl_validate_poison_dpa(cxlmd, dpa);
202+
if (rc)
203+
goto out;
204+
205+
inject.address = cpu_to_le64(dpa);
206+
mbox_cmd = (struct cxl_mbox_cmd) {
207+
.opcode = CXL_MBOX_OP_INJECT_POISON,
208+
.size_in = sizeof(inject),
209+
.payload_in = &inject,
210+
};
211+
rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
212+
out:
213+
up_read(&cxl_dpa_rwsem);
214+
215+
return rc;
216+
}
217+
EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, CXL);
218+
163219
static struct attribute *cxl_memdev_attributes[] = {
164220
&dev_attr_serial.attr,
165221
&dev_attr_firmware_version.attr,

drivers/cxl/cxlmem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,11 @@ struct cxl_mbox_poison_out {
615615
#define CXL_POISON_SOURCE_INJECTED 3
616616
#define CXL_POISON_SOURCE_VENDOR 7
617617

618+
/* Inject & Clear Poison CXL 3.0 Spec 8.2.9.8.4.2/3 */
619+
struct cxl_mbox_inject_poison {
620+
__le64 address;
621+
};
622+
618623
/**
619624
* struct cxl_mem_command - Driver representation of a memory device command
620625
* @info: Command information as it exists for the UAPI
@@ -689,6 +694,7 @@ int cxl_poison_state_init(struct cxl_dev_state *cxlds);
689694
int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
690695
struct cxl_region *cxlr);
691696
int cxl_trigger_poison_list(struct cxl_memdev *cxlmd);
697+
int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa);
692698

693699
#ifdef CONFIG_CXL_SUSPEND
694700
void cxl_mem_active_inc(void);

0 commit comments

Comments
 (0)