On 11/1/2023 2:11 PM, Ira Weiny wrote:
[snip]
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 44a21ab7add5..37add91068c0 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2020 Intel Corporation. All rights reserved. */
+#include <asm-generic/unaligned.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/moduleparam.h>
#include <linux/module.h>
@@ -748,6 +749,60 @@ static bool cxl_event_int_is_fw(u8 setting)
return mode == CXL_INT_FW;
}
+#define CXL_EVENT_HDR_FLAGS_REC_SEVERITY GENMASK(1, 0)
+static int cxl_cper_event_call(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct cxl_cper_notifier_data *nd = data;
+ struct cper_cxl_event_devid *device_id = &nd->rec->hdr.device_id;
+ enum cxl_event_log_type log_type;
+ struct cxl_memdev_state *mds;
+ struct cxl_dev_state *cxlds;
+ struct pci_dev *pdev;
+ unsigned int devfn;
+ u32 hdr_flags;
+
+ mds = container_of(nb, struct cxl_memdev_state, cxl_cper_nb);
+
+ /* PCI_DEVFN() would require 2 extra bit shifts; skip those */
+ devfn = (device_id->slot_num & 0xfff8) | (device_id->func_num & 0x07);
devfn = PCI_DEVFN(device_id->device_num, device_id->func_num) should
also work correct?
+ pdev = pci_get_domain_bus_and_slot(device_id->segment_num,
+ device_id->bus_num, devfn);
+ cxlds = pci_get_drvdata(pdev);
+ if (cxlds != &mds->cxlds) {
Do we need a error message here?
Thanks,
Smita
+ pci_dev_put(pdev);
+ return NOTIFY_DONE;
+ }
+
+ /* Fabricate a log type */
+ hdr_flags = get_unaligned_le24(nd->rec->event.generic.hdr.flags);
+ log_type = FIELD_GET(CXL_EVENT_HDR_FLAGS_REC_SEVERITY, hdr_flags);
+
+ cxl_event_trace_record(mds->cxlds.cxlmd, log_type, nd->event_type,
+ &nd->rec->event);
+ pci_dev_put(pdev);
+ return NOTIFY_OK;
+}
+
+static void cxl_unregister_cper_events(void *_mds)
+{
+ struct cxl_memdev_state *mds = _mds;
+
+ unregister_cxl_cper_notifier(&mds->cxl_cper_nb);
+}
+
+static void register_cper_events(struct cxl_memdev_state *mds)
+{
+ mds->cxl_cper_nb.notifier_call = cxl_cper_event_call;
+
+ if (register_cxl_cper_notifier(&mds->cxl_cper_nb)) {
+ dev_err(mds->cxlds.dev, "CPER registration failed\n");
+ return;
+ }
+
+ devm_add_action_or_reset(mds->cxlds.dev, cxl_unregister_cper_events, mds);
+}
+
static int cxl_event_config(struct pci_host_bridge *host_bridge,
struct cxl_memdev_state *mds)
{
@@ -758,8 +813,10 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge,
* When BIOS maintains CXL error reporting control, it will process
* event records. Only one agent can do so.
*/
- if (!host_bridge->native_cxl_error)
+ if (!host_bridge->native_cxl_error) {
+ register_cper_events(mds);
return 0;
+ }
rc = cxl_mem_alloc_event_buf(mds);
if (rc)