cxl: Add endpoint decoder flags clear when PCI reset happens

When a PCI reset happens, the lock and enable flags of the CXL device
should be cleared to avoid stale state flags after reset. Add flag
clearing during cxl_reset_done() to clear the relevant endpoint
decoder flags for all decoders of the endpoint device.

Reported-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/20260319152541.2739343-1-dave.jiang@intel.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
This commit is contained in:
Dave Jiang 2026-03-19 08:25:41 -07:00
parent 1e1cd49ded
commit 7974835aa9
2 changed files with 17 additions and 0 deletions

View File

@ -333,6 +333,7 @@ int cxl_dport_map_rcd_linkcap(struct pci_dev *pdev, struct cxl_dport *dport);
#define CXL_DECODER_F_LOCK BIT(4)
#define CXL_DECODER_F_ENABLE BIT(5)
#define CXL_DECODER_F_NORMALIZED_ADDRESSING BIT(6)
#define CXL_DECODER_F_RESET_MASK (CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK)
enum cxl_decoder_type {
CXL_DECODER_DEVMEM = 2,

View File

@ -1030,6 +1030,19 @@ static void cxl_error_resume(struct pci_dev *pdev)
dev->driver ? "successful" : "failed");
}
static int cxl_endpoint_decoder_clear_reset_flags(struct device *dev, void *data)
{
struct cxl_endpoint_decoder *cxled;
if (!is_endpoint_decoder(dev))
return 0;
cxled = to_cxl_endpoint_decoder(dev);
cxled->cxld.flags &= ~CXL_DECODER_F_RESET_MASK;
return 0;
}
static void cxl_reset_done(struct pci_dev *pdev)
{
struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
@ -1045,6 +1058,9 @@ static void cxl_reset_done(struct pci_dev *pdev)
guard(device)(&cxlmd->dev);
if (cxlmd->endpoint &&
cxl_endpoint_decoder_reset_detected(cxlmd->endpoint)) {
device_for_each_child(&cxlmd->endpoint->dev, NULL,
cxl_endpoint_decoder_clear_reset_flags);
dev_crit(dev, "SBR happened without memory regions removal.\n");
dev_crit(dev, "System may be unstable if regions hosted system memory.\n");
add_taint(TAINT_USER, LOCKDEP_STILL_OK);