Re: [PATCH v5 06/10] ACPI: APEI: GHES: move CXL CPER helpers
Jonathan Cameron <[email protected]> Fri, 29 May 2026 17:16:19 +0100
| Newsgroups | dev.linux.lists.acpica-devel,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-acpi,org.kernel.vger.linux-cxl,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-doc,org.kernel.vger.linux-edac,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260529171619.78f914bb@jic23-huawei> |
On Fri, 29 May 2026 10:50:46 +0100 Ahmed Tiba <[email protected]> wrote: > Move the CXL CPER handling paths out of ghes.c and into ghes_cper.c so the > helpers can be reused. The code is moved as-is, with the public > prototypes updated so GHES keeps calling into the new translation unit. > > Signed-off-by: Ahmed Tiba <[email protected]> This is going to clash with the series Terry is working on for CXL error handling. I think this patch in particular: https://lore.kernel.org/all/[email protected]/ That series is high priority to land from a CXL point of view. +CC Terry Subject to that, Reviewed-by: Jonathan Cameron <[email protected]> Patch left so Terry can see it. No comments. > --- > drivers/acpi/apei/ghes.c | 132 ----------------------------------------- > drivers/acpi/apei/ghes_cper.c | 134 ++++++++++++++++++++++++++++++++++++++++++ > include/acpi/ghes_cper.h | 11 ++++ > 3 files changed, 145 insertions(+), 132 deletions(-) > > diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c > index 81ac51632f21..85be2ebf4d3e 100644 > --- a/drivers/acpi/apei/ghes.c > +++ b/drivers/acpi/apei/ghes.c > @@ -383,69 +383,6 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata) > #endif > } > > -/* Room for 8 entries */ > -#define CXL_CPER_PROT_ERR_FIFO_DEPTH 8 > -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); > -struct work_struct *cxl_cper_prot_err_work; > - > -static void cxl_cper_post_prot_err(struct cxl_cper_sec_prot_err *prot_err, > - int severity) > -{ > -#ifdef CONFIG_ACPI_APEI_PCIEAER > - struct cxl_cper_prot_err_work_data wd; > - > - if (cxl_cper_sec_prot_err_valid(prot_err)) > - return; > - > - guard(spinlock_irqsave)(&cxl_cper_prot_err_work_lock); > - > - if (!cxl_cper_prot_err_work) > - return; > - > - if (cxl_cper_setup_prot_err_work_data(&wd, prot_err, severity)) > - return; > - > - if (!kfifo_put(&cxl_cper_prot_err_fifo, wd)) { > - pr_err_ratelimited("CXL CPER kfifo overflow\n"); > - return; > - } > - > - schedule_work(cxl_cper_prot_err_work); > -#endif > -} > - > -int cxl_cper_register_prot_err_work(struct work_struct *work) > -{ > - if (cxl_cper_prot_err_work) > - return -EINVAL; > - > - guard(spinlock)(&cxl_cper_prot_err_work_lock); > - cxl_cper_prot_err_work = work; > - return 0; > -} > -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; > - > - 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"); > - > -int cxl_cper_prot_err_kfifo_get(struct cxl_cper_prot_err_work_data *wd) > -{ > - return kfifo_get(&cxl_cper_prot_err_fifo, wd); > -} > -EXPORT_SYMBOL_NS_GPL(cxl_cper_prot_err_kfifo_get, "CXL"); > - > static void ghes_vendor_record_notifier_destroy(void *nb) > { > ghes_unregister_vendor_record_notifier(nb); > @@ -464,75 +401,6 @@ int devm_ghes_register_vendor_record_notifier(struct device *dev, > } > EXPORT_SYMBOL_GPL(devm_ghes_register_vendor_record_notifier); > > -/* Room for 8 entries for each of the 4 event log queues */ > -#define CXL_CPER_FIFO_DEPTH 32 > -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); > -struct work_struct *cxl_cper_work; > - > -static void cxl_cper_post_event(enum cxl_event_type event_type, > - struct cxl_cper_event_rec *rec) > -{ > - struct cxl_cper_work_data wd; > - > - if (rec->hdr.length <= sizeof(rec->hdr) || > - rec->hdr.length > sizeof(*rec)) { > - pr_err(FW_WARN "CXL CPER Invalid section length (%u)\n", > - rec->hdr.length); > - return; > - } > - > - if (!(rec->hdr.validation_bits & CPER_CXL_COMP_EVENT_LOG_VALID)) { > - pr_err(FW_WARN "CXL CPER invalid event\n"); > - return; > - } > - > - guard(spinlock_irqsave)(&cxl_cper_work_lock); > - > - if (!cxl_cper_work) > - return; > - > - wd.event_type = event_type; > - memcpy(&wd.rec, rec, sizeof(wd.rec)); > - > - if (!kfifo_put(&cxl_cper_fifo, wd)) { > - pr_err_ratelimited("CXL CPER kfifo overflow\n"); > - return; > - } > - > - schedule_work(cxl_cper_work); > -} > - > -int cxl_cper_register_work(struct work_struct *work) > -{ > - if (cxl_cper_work) > - return -EINVAL; > - > - guard(spinlock)(&cxl_cper_work_lock); > - cxl_cper_work = work; > - return 0; > -} > -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; > - > - guard(spinlock)(&cxl_cper_work_lock); > - cxl_cper_work = NULL; > - return 0; > -} > -EXPORT_SYMBOL_NS_GPL(cxl_cper_unregister_work, "CXL"); > - > -int cxl_cper_kfifo_get(struct cxl_cper_work_data *wd) > -{ > - return kfifo_get(&cxl_cper_fifo, wd); > -} > -EXPORT_SYMBOL_NS_GPL(cxl_cper_kfifo_get, "CXL"); > - > static void ghes_log_hwerr(int sev, guid_t *sec_type) > { > if (sev != CPER_SEV_RECOVERABLE) > diff --git a/drivers/acpi/apei/ghes_cper.c b/drivers/acpi/apei/ghes_cper.c > index 131980d36064..d7a666a163c3 100644 > --- a/drivers/acpi/apei/ghes_cper.c > +++ b/drivers/acpi/apei/ghes_cper.c > @@ -12,10 +12,12 @@ > * Author: Huang Ying <[email protected]> > */ > > +#include <linux/aer.h> > #include <linux/err.h> > #include <linux/genalloc.h> > #include <linux/irq_work.h> > #include <linux/io.h> > +#include <linux/kfifo.h> > #include <linux/kernel.h> > #include <linux/list.h> > #include <linux/math64.h> > @@ -321,6 +323,138 @@ void ghes_defer_non_standard_event(struct acpi_hest_generic_data *gdata, > schedule_work(&entry->work); > } > > +/* Room for 8 entries */ > +#define CXL_CPER_PROT_ERR_FIFO_DEPTH 8 > +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); > +struct work_struct *cxl_cper_prot_err_work; > + > +void cxl_cper_post_prot_err(struct cxl_cper_sec_prot_err *prot_err, > + int severity) > +{ > +#ifdef CONFIG_ACPI_APEI_PCIEAER > + struct cxl_cper_prot_err_work_data wd; > + > + if (cxl_cper_sec_prot_err_valid(prot_err)) > + return; > + > + guard(spinlock_irqsave)(&cxl_cper_prot_err_work_lock); > + > + if (!cxl_cper_prot_err_work) > + return; > + > + if (cxl_cper_setup_prot_err_work_data(&wd, prot_err, severity)) > + return; > + > + if (!kfifo_put(&cxl_cper_prot_err_fifo, wd)) { > + pr_err_ratelimited("CXL CPER kfifo overflow\n"); > + return; > + } > + > + schedule_work(cxl_cper_prot_err_work); > +#endif > +} > + > +int cxl_cper_register_prot_err_work(struct work_struct *work) > +{ > + if (cxl_cper_prot_err_work) > + return -EINVAL; > + > + guard(spinlock)(&cxl_cper_prot_err_work_lock); > + cxl_cper_prot_err_work = work; > + return 0; > +} > +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; > + > + 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"); > + > +int cxl_cper_prot_err_kfifo_get(struct cxl_cper_prot_err_work_data *wd) > +{ > + return kfifo_get(&cxl_cper_prot_err_fifo, wd); > +} > +EXPORT_SYMBOL_NS_GPL(cxl_cper_prot_err_kfifo_get, "CXL"); > + > +/* Room for 8 entries for each of the 4 event log queues */ > +#define CXL_CPER_FIFO_DEPTH 32 > +static 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); > +struct work_struct *cxl_cper_work; > + > +void cxl_cper_post_event(enum cxl_event_type event_type, > + struct cxl_cper_event_rec *rec) > +{ > + struct cxl_cper_work_data wd; > + > + if (rec->hdr.length <= sizeof(rec->hdr) || > + rec->hdr.length > sizeof(*rec)) { > + pr_err(FW_WARN "CXL CPER Invalid section length (%u)\n", > + rec->hdr.length); > + return; > + } > + > + if (!(rec->hdr.validation_bits & CPER_CXL_COMP_EVENT_LOG_VALID)) { > + pr_err(FW_WARN "CXL CPER invalid event\n"); > + return; > + } > + > + guard(spinlock_irqsave)(&cxl_cper_work_lock); > + > + if (!cxl_cper_work) > + return; > + > + wd.event_type = event_type; > + memcpy(&wd.rec, rec, sizeof(wd.rec)); > + > + if (!kfifo_put(&cxl_cper_fifo, wd)) { > + pr_err_ratelimited("CXL CPER kfifo overflow\n"); > + return; > + } > + > + schedule_work(cxl_cper_work); > +} > + > +int cxl_cper_register_work(struct work_struct *work) > +{ > + if (cxl_cper_work) > + return -EINVAL; > + > + guard(spinlock)(&cxl_cper_work_lock); > + cxl_cper_work = work; > + return 0; > +} > +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; > + > + guard(spinlock)(&cxl_cper_work_lock); > + cxl_cper_work = NULL; > + return 0; > +} > +EXPORT_SYMBOL_NS_GPL(cxl_cper_unregister_work, "CXL"); > + > +int cxl_cper_kfifo_get(struct cxl_cper_work_data *wd) > +{ > + return kfifo_get(&cxl_cper_fifo, wd); > +} > +EXPORT_SYMBOL_NS_GPL(cxl_cper_kfifo_get, "CXL"); > + > /* > * GHES error status reporting throttle, to report more kinds of > * errors, instead of just most frequently occurred errors. > diff --git a/include/acpi/ghes_cper.h b/include/acpi/ghes_cper.h > index 51725f25c516..dd49e9179b63 100644 > --- a/include/acpi/ghes_cper.h > +++ b/include/acpi/ghes_cper.h > @@ -20,6 +20,7 @@ > #include <linux/workqueue.h> > > #include <acpi/ghes.h> > +#include <cxl/event.h> > > #define GHES_PFX "GHES: " > > @@ -106,5 +107,15 @@ void ghes_estatus_cache_add(struct acpi_hest_generic *generic, > struct acpi_hest_generic_status *estatus); > void ghes_defer_non_standard_event(struct acpi_hest_generic_data *gdata, > int sev); > +void cxl_cper_post_prot_err(struct cxl_cper_sec_prot_err *prot_err, > + int severity); > +int cxl_cper_register_prot_err_work(struct work_struct *work); > +int cxl_cper_unregister_prot_err_work(struct work_struct *work); > +int cxl_cper_prot_err_kfifo_get(struct cxl_cper_prot_err_work_data *wd); > +void cxl_cper_post_event(enum cxl_event_type event_type, > + struct cxl_cper_event_rec *rec); > +int cxl_cper_register_work(struct work_struct *work); > +int cxl_cper_unregister_work(struct work_struct *work); > +int cxl_cper_kfifo_get(struct cxl_cper_work_data *wd); > > #endif /* ACPI_APEI_GHES_CPER_H */ >