diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 3236a3ce79d6..ca7a138c1ff2 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -749,7 +749,7 @@ static DEFINE_KFIFO(cxl_cper_prot_err_fifo, struct cxl_cper_prot_err_work_data, CXL_CPER_PROT_ERR_FIFO_DEPTH); /* Synchronize schedule_work() with cxl_cper_prot_err_work changes */ -static DEFINE_SPINLOCK(cxl_cper_prot_err_work_lock); +static DEFINE_RAW_SPINLOCK(cxl_cper_prot_err_work_lock); struct work_struct *cxl_cper_prot_err_work; static void cxl_cper_post_prot_err(struct cxl_cper_sec_prot_err *prot_err, @@ -761,7 +761,7 @@ static void cxl_cper_post_prot_err(struct cxl_cper_sec_prot_err *prot_err, if (cxl_cper_sec_prot_err_valid(prot_err)) return; - guard(spinlock_irqsave)(&cxl_cper_prot_err_work_lock); + guard(raw_spinlock_irqsave)(&cxl_cper_prot_err_work_lock); if (!cxl_cper_prot_err_work) return; @@ -780,10 +780,11 @@ static void cxl_cper_post_prot_err(struct cxl_cper_sec_prot_err *prot_err, int cxl_cper_register_prot_err_work(struct work_struct *work) { - if (cxl_cper_prot_err_work) - return -EINVAL; + guard(raw_spinlock_irqsave)(&cxl_cper_prot_err_work_lock); - guard(spinlock)(&cxl_cper_prot_err_work_lock); + if (WARN_ONCE(cxl_cper_prot_err_work, + "CPER-CXL kfifo consumer already registered\n")) + return -EINVAL; cxl_cper_prot_err_work = work; return 0; } @@ -791,11 +792,18 @@ EXPORT_SYMBOL_NS_GPL(cxl_cper_register_prot_err_work, "CXL"); int cxl_cper_unregister_prot_err_work(struct work_struct *work) { - if (cxl_cper_prot_err_work != work) - return -EINVAL; + scoped_guard(raw_spinlock_irqsave, &cxl_cper_prot_err_work_lock) { + if (WARN_ONCE(cxl_cper_prot_err_work != work, + "CPER-CXL kfifo consumer mismatch on unregister\n")) + return -EINVAL; + cxl_cper_prot_err_work = NULL; + } + + cancel_work_sync(work); + + /* Discard stale entries so they are not replayed on next module load */ + kfifo_reset(&cxl_cper_prot_err_fifo); - guard(spinlock)(&cxl_cper_prot_err_work_lock); - cxl_cper_prot_err_work = NULL; return 0; } EXPORT_SYMBOL_NS_GPL(cxl_cper_unregister_prot_err_work, "CXL"); @@ -811,7 +819,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_cper_prot_err_kfifo_get, "CXL"); DEFINE_KFIFO(cxl_cper_fifo, struct cxl_cper_work_data, CXL_CPER_FIFO_DEPTH); /* Synchronize schedule_work() with cxl_cper_work changes */ -static DEFINE_SPINLOCK(cxl_cper_work_lock); +static DEFINE_RAW_SPINLOCK(cxl_cper_work_lock); struct work_struct *cxl_cper_work; static void cxl_cper_post_event(enum cxl_event_type event_type, @@ -831,7 +839,7 @@ static void cxl_cper_post_event(enum cxl_event_type event_type, return; } - guard(spinlock_irqsave)(&cxl_cper_work_lock); + guard(raw_spinlock_irqsave)(&cxl_cper_work_lock); if (!cxl_cper_work) return; @@ -849,10 +857,11 @@ static void cxl_cper_post_event(enum cxl_event_type event_type, int cxl_cper_register_work(struct work_struct *work) { - if (cxl_cper_work) + guard(raw_spinlock_irqsave)(&cxl_cper_work_lock); + if (WARN_ONCE(cxl_cper_work, + "CXL CPER kfifo consumer already registered\n")) return -EINVAL; - guard(spinlock)(&cxl_cper_work_lock); cxl_cper_work = work; return 0; } @@ -860,11 +869,18 @@ EXPORT_SYMBOL_NS_GPL(cxl_cper_register_work, "CXL"); int cxl_cper_unregister_work(struct work_struct *work) { - if (cxl_cper_work != work) - return -EINVAL; + scoped_guard(raw_spinlock_irqsave, &cxl_cper_work_lock) { + if (WARN_ONCE(cxl_cper_work != work, + "CXL CPER kfifo consumer mismatch on unregister\n")) + return -EINVAL; + cxl_cper_work = NULL; + } + + cancel_work_sync(work); + + /* Discard stale entries so they are not replayed on next module load */ + kfifo_reset(&cxl_cper_fifo); - guard(spinlock)(&cxl_cper_work_lock); - cxl_cper_work = NULL; return 0; } EXPORT_SYMBOL_NS_GPL(cxl_cper_unregister_work, "CXL"); diff --git a/drivers/cxl/core/ras.c b/drivers/cxl/core/ras.c index 99fb00949c2f..bc74d4848132 100644 --- a/drivers/cxl/core/ras.c +++ b/drivers/cxl/core/ras.c @@ -137,7 +137,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/cxl/pci.c b/drivers/cxl/pci.c index 267c679b0b3c..7c6faee7f85e 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -1083,7 +1083,6 @@ static int __init cxl_pci_driver_init(void) static void __exit cxl_pci_driver_exit(void) { cxl_cper_unregister_work(&cxl_cper_work); - cancel_work_sync(&cxl_cper_work); pci_unregister_driver(&cxl_pci_driver); }