mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-31 22:23:05 +00:00

CXL rev 3.2 section 8.2.10.2.1.4 Table 8-60 defines the Memory Sparing Event Record. Determine if the event read is memory sparing record and if so trace the record. Memory device shall produce a memory sparing event record 1. After completion of a PPR maintenance operation if the memory sparing event record enable bit is set (Field: sPPR/hPPR Operation Mode in Table 8-128/Table 8-131). 2. In response to a query request by the host (see section 8.2.10.7.1.4) to determine the availability of sparing resources. The device shall report the resource availability by producing the Memory Sparing Event Record (see Table 8-60) in which the channel, rank, nibble mask, bank group, bank, row, column, sub-channel fields are a copy of the values specified in the request. If the controller does not support reporting whether a resource is available, and a perform maintenance operation for memory sparing is issued with query resources set to 1, the controller shall return invalid input. Example trace log for produce memory sparing event record on completion of a soft PPR operation, cxl_memory_sparing: memdev=mem1 host=0000:0f:00.0 serial=3 log=Informational : time=55045163029 uuid=e71f3a40-2d29-4092-8a39-4d1c966c7c65 len=128 flags='0x1' handle=1 related_handle=0 maint_op_class=2 maint_op_sub_class=1 ld_id=0 head_id=0 : flags='' result=0 validity_flags='CHANNEL|RANK|NIBBLE|BANK GROUP|BANK|ROW|COLUMN' spare resource avail=1 channel=2 rank=5 nibble_mask=a59c bank_group=2 bank=4 row=13 column=23 sub_channel=0 comp_id=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 comp_id_pldm_valid_flags='' pldm_entity_id=0x00 pldm_resource_id=0x00 Note: For memory sparing event record, fields 'maintenance operation class' and 'maintenance operation subclass' are defined twice, first in the common event record (Table 8-55) and second in the memory sparing event record (Table 8-60). Thus those in the sparing event record coded as reserved, to be removed when the spec is updated. Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Shiju Jose <shiju.jose@huawei.com> Link: https://patch.msgid.link/20250717101817.2104-5-shiju.jose@huawei.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
324 lines
7.1 KiB
C
324 lines
7.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright(c) 2023 Intel Corporation. */
|
|
#ifndef _LINUX_CXL_EVENT_H
|
|
#define _LINUX_CXL_EVENT_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/uuid.h>
|
|
#include <linux/workqueue_types.h>
|
|
|
|
/*
|
|
* Common Event Record Format
|
|
* CXL rev 3.0 section 8.2.9.2.1; Table 8-42
|
|
*/
|
|
struct cxl_event_record_hdr {
|
|
u8 length;
|
|
u8 flags[3];
|
|
__le16 handle;
|
|
__le16 related_handle;
|
|
__le64 timestamp;
|
|
u8 maint_op_class;
|
|
u8 maint_op_sub_class;
|
|
__le16 ld_id;
|
|
u8 head_id;
|
|
u8 reserved[11];
|
|
} __packed;
|
|
|
|
struct cxl_event_media_hdr {
|
|
struct cxl_event_record_hdr hdr;
|
|
__le64 phys_addr;
|
|
u8 descriptor;
|
|
u8 type;
|
|
u8 transaction_type;
|
|
/*
|
|
* The meaning of Validity Flags from bit 2 is
|
|
* different across DRAM and General Media records
|
|
*/
|
|
u8 validity_flags[2];
|
|
u8 channel;
|
|
u8 rank;
|
|
} __packed;
|
|
|
|
#define CXL_EVENT_RECORD_DATA_LENGTH 0x50
|
|
struct cxl_event_generic {
|
|
struct cxl_event_record_hdr hdr;
|
|
u8 data[CXL_EVENT_RECORD_DATA_LENGTH];
|
|
} __packed;
|
|
|
|
/*
|
|
* General Media Event Record
|
|
* CXL rev 3.1 Section 8.2.9.2.1.1; Table 8-45
|
|
*/
|
|
#define CXL_EVENT_GEN_MED_COMP_ID_SIZE 0x10
|
|
struct cxl_event_gen_media {
|
|
struct cxl_event_media_hdr media_hdr;
|
|
u8 device[3];
|
|
u8 component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE];
|
|
u8 cme_threshold_ev_flags;
|
|
u8 cme_count[3];
|
|
u8 sub_type;
|
|
u8 reserved[41];
|
|
} __packed;
|
|
|
|
/*
|
|
* DRAM Event Record - DER
|
|
* CXL rev 3.1 section 8.2.9.2.1.2; Table 8-46
|
|
*/
|
|
#define CXL_EVENT_DER_CORRECTION_MASK_SIZE 0x20
|
|
struct cxl_event_dram {
|
|
struct cxl_event_media_hdr media_hdr;
|
|
u8 nibble_mask[3];
|
|
u8 bank_group;
|
|
u8 bank;
|
|
u8 row[3];
|
|
u8 column[2];
|
|
u8 correction_mask[CXL_EVENT_DER_CORRECTION_MASK_SIZE];
|
|
u8 component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE];
|
|
u8 sub_channel;
|
|
u8 cme_threshold_ev_flags;
|
|
u8 cvme_count[3];
|
|
u8 sub_type;
|
|
u8 reserved;
|
|
} __packed;
|
|
|
|
/*
|
|
* Get Health Info Record
|
|
* CXL rev 3.1 section 8.2.9.9.3.1; Table 8-133
|
|
*/
|
|
struct cxl_get_health_info {
|
|
u8 health_status;
|
|
u8 media_status;
|
|
u8 add_status;
|
|
u8 life_used;
|
|
u8 device_temp[2];
|
|
u8 dirty_shutdown_cnt[4];
|
|
u8 cor_vol_err_cnt[4];
|
|
u8 cor_per_err_cnt[4];
|
|
} __packed;
|
|
|
|
/*
|
|
* Memory Module Event Record
|
|
* CXL rev 3.1 section 8.2.9.2.1.3; Table 8-47
|
|
*/
|
|
struct cxl_event_mem_module {
|
|
struct cxl_event_record_hdr hdr;
|
|
u8 event_type;
|
|
struct cxl_get_health_info info;
|
|
u8 validity_flags[2];
|
|
u8 component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE];
|
|
u8 event_sub_type;
|
|
u8 reserved[0x2a];
|
|
} __packed;
|
|
|
|
/*
|
|
* Memory Sparing Event Record - MSER
|
|
* CXL rev 3.2 section 8.2.10.2.1.4; Table 8-60
|
|
*/
|
|
struct cxl_event_mem_sparing {
|
|
struct cxl_event_record_hdr hdr;
|
|
/*
|
|
* The fields maintenance operation class and maintenance operation
|
|
* subclass defined in the Memory Sparing Event Record are the
|
|
* duplication of the same in the common event record. Thus defined
|
|
* as reserved and to be removed after the spec correction.
|
|
*/
|
|
u8 rsv1;
|
|
u8 rsv2;
|
|
u8 flags;
|
|
u8 result;
|
|
__le16 validity_flags;
|
|
u8 reserved1[6];
|
|
__le16 res_avail;
|
|
u8 channel;
|
|
u8 rank;
|
|
u8 nibble_mask[3];
|
|
u8 bank_group;
|
|
u8 bank;
|
|
u8 row[3];
|
|
__le16 column;
|
|
u8 component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE];
|
|
u8 sub_channel;
|
|
u8 reserved2[0x25];
|
|
} __packed;
|
|
|
|
union cxl_event {
|
|
struct cxl_event_generic generic;
|
|
struct cxl_event_gen_media gen_media;
|
|
struct cxl_event_dram dram;
|
|
struct cxl_event_mem_module mem_module;
|
|
struct cxl_event_mem_sparing mem_sparing;
|
|
/* dram & gen_media event header */
|
|
struct cxl_event_media_hdr media_hdr;
|
|
} __packed;
|
|
|
|
/*
|
|
* Common Event Record Format; in event logs
|
|
* CXL rev 3.0 section 8.2.9.2.1; Table 8-42
|
|
*/
|
|
struct cxl_event_record_raw {
|
|
uuid_t id;
|
|
union cxl_event event;
|
|
} __packed;
|
|
|
|
enum cxl_event_type {
|
|
CXL_CPER_EVENT_GENERIC,
|
|
CXL_CPER_EVENT_GEN_MEDIA,
|
|
CXL_CPER_EVENT_DRAM,
|
|
CXL_CPER_EVENT_MEM_MODULE,
|
|
CXL_CPER_EVENT_MEM_SPARING,
|
|
};
|
|
|
|
#define CPER_CXL_DEVICE_ID_VALID BIT(0)
|
|
#define CPER_CXL_DEVICE_SN_VALID BIT(1)
|
|
#define CPER_CXL_COMP_EVENT_LOG_VALID BIT(2)
|
|
struct cxl_cper_event_rec {
|
|
struct {
|
|
u32 length;
|
|
u64 validation_bits;
|
|
struct cper_cxl_event_devid {
|
|
u16 vendor_id;
|
|
u16 device_id;
|
|
u8 func_num;
|
|
u8 device_num;
|
|
u8 bus_num;
|
|
u16 segment_num;
|
|
u16 slot_num; /* bits 2:0 reserved */
|
|
u8 reserved;
|
|
} __packed device_id;
|
|
struct cper_cxl_event_sn {
|
|
u32 lower_dw;
|
|
u32 upper_dw;
|
|
} __packed dev_serial_num;
|
|
} __packed hdr;
|
|
|
|
union cxl_event event;
|
|
} __packed;
|
|
|
|
struct cxl_cper_work_data {
|
|
enum cxl_event_type event_type;
|
|
struct cxl_cper_event_rec rec;
|
|
};
|
|
|
|
#define PROT_ERR_VALID_AGENT_TYPE BIT_ULL(0)
|
|
#define PROT_ERR_VALID_AGENT_ADDRESS BIT_ULL(1)
|
|
#define PROT_ERR_VALID_DEVICE_ID BIT_ULL(2)
|
|
#define PROT_ERR_VALID_SERIAL_NUMBER BIT_ULL(3)
|
|
#define PROT_ERR_VALID_CAPABILITY BIT_ULL(4)
|
|
#define PROT_ERR_VALID_DVSEC BIT_ULL(5)
|
|
#define PROT_ERR_VALID_ERROR_LOG BIT_ULL(6)
|
|
|
|
/*
|
|
* The layout of the enumeration and the values matches CXL Agent Type
|
|
* field in the UEFI 2.10 Section N.2.13,
|
|
*/
|
|
enum {
|
|
RCD, /* Restricted CXL Device */
|
|
RCH_DP, /* Restricted CXL Host Downstream Port */
|
|
DEVICE, /* CXL Device */
|
|
LD, /* CXL Logical Device */
|
|
FMLD, /* CXL Fabric Manager managed Logical Device */
|
|
RP, /* CXL Root Port */
|
|
DSP, /* CXL Downstream Switch Port */
|
|
USP, /* CXL Upstream Switch Port */
|
|
};
|
|
|
|
#pragma pack(1)
|
|
|
|
/* Compute Express Link Protocol Error Section, UEFI v2.10 sec N.2.13 */
|
|
struct cxl_cper_sec_prot_err {
|
|
u64 valid_bits;
|
|
u8 agent_type;
|
|
u8 reserved[7];
|
|
|
|
/*
|
|
* Except for RCH Downstream Port, all the remaining CXL Agent
|
|
* types are uniquely identified by the PCIe compatible SBDF number.
|
|
*/
|
|
union {
|
|
u64 rcrb_base_addr;
|
|
struct {
|
|
u8 function;
|
|
u8 device;
|
|
u8 bus;
|
|
u16 segment;
|
|
u8 reserved_1[3];
|
|
};
|
|
} agent_addr;
|
|
|
|
struct {
|
|
u16 vendor_id;
|
|
u16 device_id;
|
|
u16 subsystem_vendor_id;
|
|
u16 subsystem_id;
|
|
u8 class_code[2];
|
|
u16 slot;
|
|
u8 reserved_1[4];
|
|
} device_id;
|
|
|
|
struct {
|
|
u32 lower_dw;
|
|
u32 upper_dw;
|
|
} dev_serial_num;
|
|
|
|
u8 capability[60];
|
|
u16 dvsec_len;
|
|
u16 err_len;
|
|
u8 reserved_2[4];
|
|
};
|
|
|
|
#pragma pack()
|
|
|
|
/* CXL RAS Capability Structure, CXL v3.0 sec 8.2.4.16 */
|
|
struct cxl_ras_capability_regs {
|
|
u32 uncor_status;
|
|
u32 uncor_mask;
|
|
u32 uncor_severity;
|
|
u32 cor_status;
|
|
u32 cor_mask;
|
|
u32 cap_control;
|
|
u32 header_log[16];
|
|
};
|
|
|
|
struct cxl_cper_prot_err_work_data {
|
|
struct cxl_cper_sec_prot_err prot_err;
|
|
struct cxl_ras_capability_regs ras_cap;
|
|
int severity;
|
|
};
|
|
|
|
#ifdef CONFIG_ACPI_APEI_GHES
|
|
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);
|
|
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);
|
|
#else
|
|
static inline int cxl_cper_register_work(struct work_struct *work)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int cxl_cper_unregister_work(struct work_struct *work)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int cxl_cper_kfifo_get(struct cxl_cper_work_data *wd)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int cxl_cper_register_prot_err_work(struct work_struct *work)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int cxl_cper_unregister_prot_err_work(struct work_struct *work)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int cxl_cper_prot_err_kfifo_get(struct cxl_cper_prot_err_work_data *wd)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#endif /* _LINUX_CXL_EVENT_H */
|