[PATCH v16 02/10] PCI/CXL: Update unregistration for AER-CXL and CPER-CXL kfifos

Terry Bowman posted 10 patches 7 hours ago
[PATCH v16 02/10] PCI/CXL: Update unregistration for AER-CXL and CPER-CXL kfifos
Posted by Terry Bowman 7 hours ago
The current AER-CXL kfifo unregistration does not cancel pending work after
clearing the work function pointer. In addition, cancel_work_sync() is
called on behalf of the CPER-CXL kfifo in cxl_ras_exit() and should be
moved into the kfifo deregistration function.

Add logic to cancel the AER-CXL kfifo's pending work in
cxl_unregister_proto_err_work().

Move the CPER-CXL kfifo cancel call from cxl_ras_exit() to
cxl_cper_unregister_prot_err_work(). Release the CPER-CXL spinlock
before calling cancel_work_sync() to avoid deadlock.

In both kfifo unregistration cases, add the necessary synchronization
to enforce proper lock ordering: protect pointer updates under the
lock, and clear the work pointer, then cancel any outstanding work
after the lock is released.

Link: https://lore.kernel.org/linux-cxl/6982ca54e094b_55fa1005@dwillia2-mobl4.notmuch/
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Assisted-by: Azure:gtp-4.1-nano-key

----

Changes in v16:
- New commit
---
 drivers/acpi/apei/ghes.c      | 6 +++++-
 drivers/cxl/core/ras.c        | 1 -
 drivers/pci/pcie/aer_cxl_vh.c | 9 ++++++++-
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 8acd2742bb27..de935e0e1dcf 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -776,8 +776,12 @@ int cxl_cper_unregister_prot_err_work(struct work_struct *work)
 	if (cxl_cper_prot_err_work != work)
 		return -EINVAL;
 
-	guard(spinlock)(&cxl_cper_prot_err_work_lock);
+	spin_lock(&cxl_cper_prot_err_work_lock);
 	cxl_cper_prot_err_work = NULL;
+	spin_unlock(&cxl_cper_prot_err_work_lock);
+
+	cancel_work_sync(work);
+
 	return 0;
 }
 EXPORT_SYMBOL_NS_GPL(cxl_cper_unregister_prot_err_work, "CXL");
diff --git a/drivers/cxl/core/ras.c b/drivers/cxl/core/ras.c
index 006c6ffc2f56..949d8c8ecdfe 100644
--- a/drivers/cxl/core/ras.c
+++ b/drivers/cxl/core/ras.c
@@ -124,7 +124,6 @@ int cxl_ras_init(void)
 void cxl_ras_exit(void)
 {
 	cxl_cper_unregister_prot_err_work(&cxl_cper_prot_err_work);
-	cancel_work_sync(&cxl_cper_prot_err_work);
 }
 
 static void cxl_dport_map_ras(struct cxl_dport *dport)
diff --git a/drivers/pci/pcie/aer_cxl_vh.c b/drivers/pci/pcie/aer_cxl_vh.c
index 7e2bc1894395..ebca1112652a 100644
--- a/drivers/pci/pcie/aer_cxl_vh.c
+++ b/drivers/pci/pcie/aer_cxl_vh.c
@@ -74,8 +74,15 @@ EXPORT_SYMBOL_NS_GPL(cxl_register_proto_err_work, "CXL");
 
 void cxl_unregister_proto_err_work(void)
 {
-	guard(rwsem_write)(&cxl_proto_err_kfifo.rwsema);
+	struct work_struct *work;
+
+	down_write(&cxl_proto_err_kfifo.rwsema);
+	work = cxl_proto_err_kfifo.work;
 	cxl_proto_err_kfifo.work = NULL;
+	up_write(&cxl_proto_err_kfifo.rwsema);
+
+	if (work)
+		cancel_work_sync(work);
 }
 EXPORT_SYMBOL_NS_GPL(cxl_unregister_proto_err_work, "CXL");
 
-- 
2.34.1