Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

cxl/events: Trace Memory Sparing Event Record

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>

authored by

Shiju Jose and committed by
Dave Jiang
f10f46a0 d8145bb8

+152
+6
drivers/cxl/core/mbox.c
··· 899 899 trace_cxl_generic_event(cxlmd, type, uuid, &evt->generic); 900 900 return; 901 901 } 902 + if (event_type == CXL_CPER_EVENT_MEM_SPARING) { 903 + trace_cxl_memory_sparing(cxlmd, type, &evt->mem_sparing); 904 + return; 905 + } 902 906 903 907 if (trace_cxl_general_media_enabled() || trace_cxl_dram_enabled()) { 904 908 u64 dpa, hpa = ULLONG_MAX, hpa_alias = ULLONG_MAX; ··· 974 970 ev_type = CXL_CPER_EVENT_DRAM; 975 971 else if (uuid_equal(uuid, &CXL_EVENT_MEM_MODULE_UUID)) 976 972 ev_type = CXL_CPER_EVENT_MEM_MODULE; 973 + else if (uuid_equal(uuid, &CXL_EVENT_MEM_SPARING_UUID)) 974 + ev_type = CXL_CPER_EVENT_MEM_SPARING; 977 975 978 976 cxl_event_trace_record(cxlmd, type, ev_type, uuid, &record->event); 979 977 }
+105
drivers/cxl/core/trace.h
··· 887 887 ) 888 888 ); 889 889 890 + /* 891 + * Memory Sparing Event Record - MSER 892 + * 893 + * CXL rev 3.2 section 8.2.10.2.1.4; Table 8-60 894 + */ 895 + #define CXL_MSER_QUERY_RESOURCE_FLAG BIT(0) 896 + #define CXL_MSER_HARD_SPARING_FLAG BIT(1) 897 + #define CXL_MSER_DEV_INITED_FLAG BIT(2) 898 + #define show_mem_sparing_flags(flags) __print_flags(flags, "|", \ 899 + { CXL_MSER_QUERY_RESOURCE_FLAG, "Query Resources" }, \ 900 + { CXL_MSER_HARD_SPARING_FLAG, "Hard Sparing" }, \ 901 + { CXL_MSER_DEV_INITED_FLAG, "Device Initiated Sparing" } \ 902 + ) 903 + 904 + #define CXL_MSER_VALID_CHANNEL BIT(0) 905 + #define CXL_MSER_VALID_RANK BIT(1) 906 + #define CXL_MSER_VALID_NIBBLE BIT(2) 907 + #define CXL_MSER_VALID_BANK_GROUP BIT(3) 908 + #define CXL_MSER_VALID_BANK BIT(4) 909 + #define CXL_MSER_VALID_ROW BIT(5) 910 + #define CXL_MSER_VALID_COLUMN BIT(6) 911 + #define CXL_MSER_VALID_COMPONENT_ID BIT(7) 912 + #define CXL_MSER_VALID_COMPONENT_ID_FORMAT BIT(8) 913 + #define CXL_MSER_VALID_SUB_CHANNEL BIT(9) 914 + #define show_mem_sparing_valid_flags(flags) __print_flags(flags, "|", \ 915 + { CXL_MSER_VALID_CHANNEL, "CHANNEL" }, \ 916 + { CXL_MSER_VALID_RANK, "RANK" }, \ 917 + { CXL_MSER_VALID_NIBBLE, "NIBBLE" }, \ 918 + { CXL_MSER_VALID_BANK_GROUP, "BANK GROUP" }, \ 919 + { CXL_MSER_VALID_BANK, "BANK" }, \ 920 + { CXL_MSER_VALID_ROW, "ROW" }, \ 921 + { CXL_MSER_VALID_COLUMN, "COLUMN" }, \ 922 + { CXL_MSER_VALID_COMPONENT_ID, "COMPONENT ID" }, \ 923 + { CXL_MSER_VALID_COMPONENT_ID_FORMAT, "COMPONENT ID PLDM FORMAT" }, \ 924 + { CXL_MSER_VALID_SUB_CHANNEL, "SUB CHANNEL" } \ 925 + ) 926 + 927 + TRACE_EVENT(cxl_memory_sparing, 928 + 929 + TP_PROTO(const struct cxl_memdev *cxlmd, enum cxl_event_log_type log, 930 + struct cxl_event_mem_sparing *rec), 931 + 932 + TP_ARGS(cxlmd, log, rec), 933 + 934 + TP_STRUCT__entry( 935 + CXL_EVT_TP_entry 936 + 937 + /* Memory Sparing Event */ 938 + __field(u8, flags) 939 + __field(u8, result) 940 + __field(u16, validity_flags) 941 + __field(u16, res_avail) 942 + __field(u8, channel) 943 + __field(u8, rank) 944 + __field(u32, nibble_mask) 945 + __field(u8, bank_group) 946 + __field(u8, bank) 947 + __field(u32, row) 948 + __field(u16, column) 949 + __field(u8, sub_channel) 950 + __array(u8, comp_id, CXL_EVENT_GEN_MED_COMP_ID_SIZE) 951 + ), 952 + 953 + TP_fast_assign( 954 + CXL_EVT_TP_fast_assign(cxlmd, log, rec->hdr); 955 + __entry->hdr_uuid = CXL_EVENT_MEM_SPARING_UUID; 956 + 957 + /* Memory Sparing Event */ 958 + __entry->flags = rec->flags; 959 + __entry->result = rec->result; 960 + __entry->validity_flags = le16_to_cpu(rec->validity_flags); 961 + __entry->res_avail = le16_to_cpu(rec->res_avail); 962 + __entry->channel = rec->channel; 963 + __entry->rank = rec->rank; 964 + __entry->nibble_mask = get_unaligned_le24(rec->nibble_mask); 965 + __entry->bank_group = rec->bank_group; 966 + __entry->bank = rec->bank; 967 + __entry->row = get_unaligned_le24(rec->row); 968 + __entry->column = le16_to_cpu(rec->column); 969 + __entry->sub_channel = rec->sub_channel; 970 + memcpy(__entry->comp_id, &rec->component_id, 971 + CXL_EVENT_GEN_MED_COMP_ID_SIZE); 972 + ), 973 + 974 + CXL_EVT_TP_printk("flags='%s' result=%u validity_flags='%s' " \ 975 + "spare resource avail=%u channel=%u rank=%u " \ 976 + "nibble_mask=%x bank_group=%u bank=%u " \ 977 + "row=%u column=%u sub_channel=%u " \ 978 + "comp_id=%s comp_id_pldm_valid_flags='%s' " \ 979 + "pldm_entity_id=%s pldm_resource_id=%s", 980 + show_mem_sparing_flags(__entry->flags), 981 + __entry->result, 982 + show_mem_sparing_valid_flags(__entry->validity_flags), 983 + __entry->res_avail, __entry->channel, __entry->rank, 984 + __entry->nibble_mask, __entry->bank_group, __entry->bank, 985 + __entry->row, __entry->column, __entry->sub_channel, 986 + __print_hex(__entry->comp_id, CXL_EVENT_GEN_MED_COMP_ID_SIZE), 987 + show_comp_id_pldm_flags(__entry->comp_id[0]), 988 + show_pldm_entity_id(__entry->validity_flags, CXL_MSER_VALID_COMPONENT_ID, 989 + CXL_MSER_VALID_COMPONENT_ID_FORMAT, __entry->comp_id), 990 + show_pldm_resource_id(__entry->validity_flags, CXL_MSER_VALID_COMPONENT_ID, 991 + CXL_MSER_VALID_COMPONENT_ID_FORMAT, __entry->comp_id) 992 + ) 993 + ); 994 + 890 995 #define show_poison_trace_type(type) \ 891 996 __print_symbolic(type, \ 892 997 { CXL_POISON_TRACE_LIST, "List" }, \
+8
drivers/cxl/cxlmem.h
··· 634 634 0x13, 0xb7, 0x74) 635 635 636 636 /* 637 + * Memory Sparing Event Record UUID 638 + * CXL rev 3.2 section 8.2.10.2.1.4: Table 8-60 639 + */ 640 + #define CXL_EVENT_MEM_SPARING_UUID \ 641 + UUID_INIT(0xe71f3a40, 0x2d29, 0x4092, 0x8a, 0x39, 0x4d, 0x1c, 0x96, \ 642 + 0x6c, 0x7c, 0x65) 643 + 644 + /* 637 645 * Get Event Records output payload 638 646 * CXL rev 3.0 section 8.2.9.2.2; Table 8-50 639 647 */
+33
include/cxl/event.h
··· 110 110 u8 reserved[0x2a]; 111 111 } __packed; 112 112 113 + /* 114 + * Memory Sparing Event Record - MSER 115 + * CXL rev 3.2 section 8.2.10.2.1.4; Table 8-60 116 + */ 117 + struct cxl_event_mem_sparing { 118 + struct cxl_event_record_hdr hdr; 119 + /* 120 + * The fields maintenance operation class and maintenance operation 121 + * subclass defined in the Memory Sparing Event Record are the 122 + * duplication of the same in the common event record. Thus defined 123 + * as reserved and to be removed after the spec correction. 124 + */ 125 + u8 rsv1; 126 + u8 rsv2; 127 + u8 flags; 128 + u8 result; 129 + __le16 validity_flags; 130 + u8 reserved1[6]; 131 + __le16 res_avail; 132 + u8 channel; 133 + u8 rank; 134 + u8 nibble_mask[3]; 135 + u8 bank_group; 136 + u8 bank; 137 + u8 row[3]; 138 + __le16 column; 139 + u8 component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE]; 140 + u8 sub_channel; 141 + u8 reserved2[0x25]; 142 + } __packed; 143 + 113 144 union cxl_event { 114 145 struct cxl_event_generic generic; 115 146 struct cxl_event_gen_media gen_media; 116 147 struct cxl_event_dram dram; 117 148 struct cxl_event_mem_module mem_module; 149 + struct cxl_event_mem_sparing mem_sparing; 118 150 /* dram & gen_media event header */ 119 151 struct cxl_event_media_hdr media_hdr; 120 152 } __packed; ··· 165 133 CXL_CPER_EVENT_GEN_MEDIA, 166 134 CXL_CPER_EVENT_DRAM, 167 135 CXL_CPER_EVENT_MEM_MODULE, 136 + CXL_CPER_EVENT_MEM_SPARING, 168 137 }; 169 138 170 139 #define CPER_CXL_DEVICE_ID_VALID BIT(0)