Skip to content

Commit f10f46a

Browse files
shijujose4davejiang
authored andcommitted
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 <[email protected]> Reviewed-by: Dave Jiang <[email protected]> Signed-off-by: Shiju Jose <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Dave Jiang <[email protected]>
1 parent d8145bb commit f10f46a

File tree

4 files changed

+152
-0
lines changed

4 files changed

+152
-0
lines changed

drivers/cxl/core/mbox.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,10 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd,
899899
trace_cxl_generic_event(cxlmd, type, uuid, &evt->generic);
900900
return;
901901
}
902+
if (event_type == CXL_CPER_EVENT_MEM_SPARING) {
903+
trace_cxl_memory_sparing(cxlmd, type, &evt->mem_sparing);
904+
return;
905+
}
902906

903907
if (trace_cxl_general_media_enabled() || trace_cxl_dram_enabled()) {
904908
u64 dpa, hpa = ULLONG_MAX, hpa_alias = ULLONG_MAX;
@@ -970,6 +974,8 @@ static void __cxl_event_trace_record(const struct cxl_memdev *cxlmd,
970974
ev_type = CXL_CPER_EVENT_DRAM;
971975
else if (uuid_equal(uuid, &CXL_EVENT_MEM_MODULE_UUID))
972976
ev_type = CXL_CPER_EVENT_MEM_MODULE;
977+
else if (uuid_equal(uuid, &CXL_EVENT_MEM_SPARING_UUID))
978+
ev_type = CXL_CPER_EVENT_MEM_SPARING;
973979

974980
cxl_event_trace_record(cxlmd, type, ev_type, uuid, &record->event);
975981
}

drivers/cxl/core/trace.h

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,111 @@ TRACE_EVENT(cxl_memory_module,
887887
)
888888
);
889889

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+
890995
#define show_poison_trace_type(type) \
891996
__print_symbolic(type, \
892997
{ CXL_POISON_TRACE_LIST, "List" }, \

drivers/cxl/cxlmem.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,14 @@ struct cxl_mbox_identify {
633633
UUID_INIT(0xfe927475, 0xdd59, 0x4339, 0xa5, 0x86, 0x79, 0xba, 0xb1, \
634634
0x13, 0xb7, 0x74)
635635

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+
636644
/*
637645
* Get Event Records output payload
638646
* CXL rev 3.0 section 8.2.9.2.2; Table 8-50

include/cxl/event.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,43 @@ struct cxl_event_mem_module {
110110
u8 reserved[0x2a];
111111
} __packed;
112112

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+
113144
union cxl_event {
114145
struct cxl_event_generic generic;
115146
struct cxl_event_gen_media gen_media;
116147
struct cxl_event_dram dram;
117148
struct cxl_event_mem_module mem_module;
149+
struct cxl_event_mem_sparing mem_sparing;
118150
/* dram & gen_media event header */
119151
struct cxl_event_media_hdr media_hdr;
120152
} __packed;
@@ -133,6 +165,7 @@ enum cxl_event_type {
133165
CXL_CPER_EVENT_GEN_MEDIA,
134166
CXL_CPER_EVENT_DRAM,
135167
CXL_CPER_EVENT_MEM_MODULE,
168+
CXL_CPER_EVENT_MEM_SPARING,
136169
};
137170

138171
#define CPER_CXL_DEVICE_ID_VALID BIT(0)

0 commit comments

Comments
 (0)