Commit 25a02078 authored by Alison Schofield's avatar Alison Schofield Committed by Dave Jiang
Browse files

cxl/core: Add locked variants of the poison inject and clear funcs



The core functions that validate and send inject and clear commands
to the memdev devices require holding both the dpa_rwsem and the
region_rwsem.

In preparation for another caller of these functions that must hold
the locks upon entry, split the work into a locked and unlocked pair.

Consideration was given to moving the locking to both callers,
however, the existing caller is not in the core (mem.c) and cannot
access the locks.

Signed-off-by: default avatarAlison Schofield <alison.schofield@intel.com>
Reviewed-by: default avatarDave Jiang <dave.jiang@intel.com>
Reviewed-by: default avatarJonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/1d601f586975195733984ca63d1b5789bbe8690f.1754290144.git.alison.schofield@intel.com


Signed-off-by: default avatarDave Jiang <dave.jiang@intel.com>
parent dc181170
Loading
Loading
Loading
Loading
+36 −16
Original line number Diff line number Diff line
@@ -276,7 +276,7 @@ static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
	return 0;
}

int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
int cxl_inject_poison_locked(struct cxl_memdev *cxlmd, u64 dpa)
{
	struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
	struct cxl_mbox_inject_poison inject;
@@ -288,13 +288,8 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
	if (!IS_ENABLED(CONFIG_DEBUG_FS))
		return 0;

	ACQUIRE(rwsem_read_intr, region_rwsem)(&cxl_rwsem.region);
	if ((rc = ACQUIRE_ERR(rwsem_read_intr, &region_rwsem)))
		return rc;

	ACQUIRE(rwsem_read_intr, dpa_rwsem)(&cxl_rwsem.dpa);
	if ((rc = ACQUIRE_ERR(rwsem_read_intr, &dpa_rwsem)))
		return rc;
	lockdep_assert_held(&cxl_rwsem.dpa);
	lockdep_assert_held(&cxl_rwsem.region);

	rc = cxl_validate_poison_dpa(cxlmd, dpa);
	if (rc)
@@ -324,9 +319,24 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)

	return 0;
}

int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
{
	int rc;

	ACQUIRE(rwsem_read_intr, region_rwsem)(&cxl_rwsem.region);
	if ((rc = ACQUIRE_ERR(rwsem_read_intr, &region_rwsem)))
		return rc;

	ACQUIRE(rwsem_read_intr, dpa_rwsem)(&cxl_rwsem.dpa);
	if ((rc = ACQUIRE_ERR(rwsem_read_intr, &dpa_rwsem)))
		return rc;

	return cxl_inject_poison_locked(cxlmd, dpa);
}
EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, "CXL");

int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
int cxl_clear_poison_locked(struct cxl_memdev *cxlmd, u64 dpa)
{
	struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
	struct cxl_mbox_clear_poison clear;
@@ -338,13 +348,8 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
	if (!IS_ENABLED(CONFIG_DEBUG_FS))
		return 0;

	ACQUIRE(rwsem_read_intr, region_rwsem)(&cxl_rwsem.region);
	if ((rc = ACQUIRE_ERR(rwsem_read_intr, &region_rwsem)))
		return rc;

	ACQUIRE(rwsem_read_intr, dpa_rwsem)(&cxl_rwsem.dpa);
	if ((rc = ACQUIRE_ERR(rwsem_read_intr, &dpa_rwsem)))
		return rc;
	lockdep_assert_held(&cxl_rwsem.dpa);
	lockdep_assert_held(&cxl_rwsem.region);

	rc = cxl_validate_poison_dpa(cxlmd, dpa);
	if (rc)
@@ -383,6 +388,21 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)

	return 0;
}

int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
{
	int rc;

	ACQUIRE(rwsem_read_intr, region_rwsem)(&cxl_rwsem.region);
	if ((rc = ACQUIRE_ERR(rwsem_read_intr, &region_rwsem)))
		return rc;

	ACQUIRE(rwsem_read_intr, dpa_rwsem)(&cxl_rwsem.dpa);
	if ((rc = ACQUIRE_ERR(rwsem_read_intr, &dpa_rwsem)))
		return rc;

	return cxl_clear_poison_locked(cxlmd, dpa);
}
EXPORT_SYMBOL_NS_GPL(cxl_clear_poison, "CXL");

static struct attribute *cxl_memdev_attributes[] = {
+2 −0
Original line number Diff line number Diff line
@@ -869,6 +869,8 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
int cxl_trigger_poison_list(struct cxl_memdev *cxlmd);
int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa);
int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa);
int cxl_inject_poison_locked(struct cxl_memdev *cxlmd, u64 dpa);
int cxl_clear_poison_locked(struct cxl_memdev *cxlmd, u64 dpa);

#ifdef CONFIG_CXL_EDAC_MEM_FEATURES
int devm_cxl_memdev_edac_register(struct cxl_memdev *cxlmd);