5353#define TYPE1_VER0_COMPLETE BIT(31)
5454#define TYPE1_VER0_TRIGGER_MASK GENMASK(31, 28)
5555
56+ /*
57+ * Type 1 Version 2
58+ * status and control are different registers
59+ */
60+ #define TYPE1_VER2_STATUS_OFFSET 0x00
61+ #define TYPE1_VER2_CONTROL_OFFSET 0x14
62+
63+ /* status register */
64+ #define TYPE1_VER2_CLEAR_SUPPORT BIT(20)
65+ #define TYPE1_VER2_REARMED BIT(25)
66+ #define TYPE1_VER2_ERROR BIT(26)
67+ #define TYPE1_VER2_CONSUMED BIT(27)
68+ #define TYPE1_VER2_DISABLED BIT(28)
69+ #define TYPE1_VER2_CLEARED BIT(29)
70+ #define TYPE1_VER2_IN_PROGRESS BIT(30)
71+ #define TYPE1_VER2_COMPLETE BIT(31)
72+
73+ /* control register */
74+ #define TYPE1_VER2_CONSUME BIT(25)
75+ #define TYPE1_VER2_REARM BIT(28)
76+ #define TYPE1_VER2_EXECUTE BIT(29)
77+ #define TYPE1_VER2_CLEAR BIT(30)
78+ #define TYPE1_VER2_DISABLE BIT(31)
79+ #define TYPE1_VER2_TRIGGER_MASK \
80+ (TYPE1_VER2_EXECUTE | TYPE1_VER2_CLEAR | TYPE1_VER2_DISABLE)
81+
5682/* After offset, order alphabetically, not bit ordered */
5783struct crashlog_status {
5884 u32 offset ;
85+ u32 clear_supported ;
5986 u32 cleared ;
6087 u32 complete ;
88+ u32 consumed ;
6189 u32 disabled ;
90+ u32 error ;
91+ u32 in_progress ;
92+ u32 rearmed ;
6293};
6394
6495struct crashlog_control {
6596 u32 offset ;
6697 u32 trigger_mask ;
6798 u32 clear ;
99+ u32 consume ;
68100 u32 disable ;
69101 u32 manual ;
102+ u32 rearm ;
70103};
71104
72105struct crashlog_info {
73106 const struct crashlog_status status ;
74107 const struct crashlog_control control ;
108+ const struct attribute_group * attr_grp ;
75109};
76110
77111struct crashlog_entry {
@@ -128,19 +162,23 @@ static bool pmt_crashlog_disabled(struct crashlog_entry *crashlog)
128162 return pmt_crashlog_rc (crashlog , crashlog -> info -> status .disabled );
129163}
130164
131- static bool pmt_crashlog_supported (struct intel_pmt_entry * entry )
165+ static bool pmt_crashlog_supported (struct intel_pmt_entry * entry , u32 * crash_type , u32 * version )
132166{
133167 u32 discovery_header = readl (entry -> disc_table + CONTROL_OFFSET );
134- u32 crash_type , version ;
135168
136- crash_type = GET_TYPE (discovery_header );
137- version = GET_VERSION (discovery_header );
169+ * crash_type = GET_TYPE (discovery_header );
170+ * version = GET_VERSION (discovery_header );
138171
139172 /*
140- * Currently we only recognize OOBMSM version 0 devices.
141- * We can ignore all other crashlog devices in the system.
173+ * Currently we only recognize OOBMSM (type 1) and version 0 or 2
174+ * devices.
175+ *
176+ * Ignore all other crashlog devices in the system.
142177 */
143- return crash_type == CRASH_TYPE_OOBMSM && version == 0 ;
178+ if (* crash_type == CRASH_TYPE_OOBMSM && (* version == 0 || * version == 2 ))
179+ return true;
180+
181+ return false;
144182}
145183
146184static void pmt_crashlog_set_disable (struct crashlog_entry * crashlog ,
@@ -159,9 +197,115 @@ static void pmt_crashlog_set_execute(struct crashlog_entry *crashlog)
159197 pmt_crashlog_rmw (crashlog , crashlog -> info -> control .manual , true);
160198}
161199
200+ static bool pmt_crashlog_cleared (struct crashlog_entry * crashlog )
201+ {
202+ return pmt_crashlog_rc (crashlog , crashlog -> info -> status .cleared );
203+ }
204+
205+ static bool pmt_crashlog_consumed (struct crashlog_entry * crashlog )
206+ {
207+ return pmt_crashlog_rc (crashlog , crashlog -> info -> status .consumed );
208+ }
209+
210+ static void pmt_crashlog_set_consumed (struct crashlog_entry * crashlog )
211+ {
212+ pmt_crashlog_rmw (crashlog , crashlog -> info -> control .consume , true);
213+ }
214+
215+ static bool pmt_crashlog_error (struct crashlog_entry * crashlog )
216+ {
217+ return pmt_crashlog_rc (crashlog , crashlog -> info -> status .error );
218+ }
219+
220+ static bool pmt_crashlog_rearm (struct crashlog_entry * crashlog )
221+ {
222+ return pmt_crashlog_rc (crashlog , crashlog -> info -> status .rearmed );
223+ }
224+
225+ static void pmt_crashlog_set_rearm (struct crashlog_entry * crashlog )
226+ {
227+ pmt_crashlog_rmw (crashlog , crashlog -> info -> control .rearm , true);
228+ }
229+
162230/*
163231 * sysfs
164232 */
233+ static ssize_t
234+ clear_show (struct device * dev , struct device_attribute * attr , char * buf )
235+ {
236+ struct crashlog_entry * crashlog = dev_get_drvdata (dev );
237+ bool cleared = pmt_crashlog_cleared (crashlog );
238+
239+ return sysfs_emit (buf , "%d\n" , cleared );
240+ }
241+
242+ static ssize_t
243+ clear_store (struct device * dev , struct device_attribute * attr ,
244+ const char * buf , size_t count )
245+ {
246+ struct crashlog_entry * crashlog ;
247+ bool clear ;
248+ int result ;
249+
250+ crashlog = dev_get_drvdata (dev );
251+
252+ result = kstrtobool (buf , & clear );
253+ if (result )
254+ return result ;
255+
256+ /* set bit only */
257+ if (!clear )
258+ return - EINVAL ;
259+
260+ guard (mutex )(& crashlog -> control_mutex );
261+
262+ pmt_crashlog_set_clear (crashlog );
263+
264+ return count ;
265+ }
266+ static DEVICE_ATTR_RW (clear );
267+
268+ static ssize_t
269+ consumed_show (struct device * dev , struct device_attribute * attr , char * buf )
270+ {
271+ struct crashlog_entry * crashlog = dev_get_drvdata (dev );
272+ bool consumed = pmt_crashlog_consumed (crashlog );
273+
274+ return sysfs_emit (buf , "%d\n" , consumed );
275+ }
276+
277+ static ssize_t
278+ consumed_store (struct device * dev , struct device_attribute * attr , const char * buf ,
279+ size_t count )
280+ {
281+ struct crashlog_entry * crashlog ;
282+ bool consumed ;
283+ int result ;
284+
285+ crashlog = dev_get_drvdata (dev );
286+
287+ result = kstrtobool (buf , & consumed );
288+ if (result )
289+ return result ;
290+
291+ /* set bit only */
292+ if (!consumed )
293+ return - EINVAL ;
294+
295+ guard (mutex )(& crashlog -> control_mutex );
296+
297+ if (pmt_crashlog_disabled (crashlog ))
298+ return - EBUSY ;
299+
300+ if (!pmt_crashlog_complete (crashlog ))
301+ return - EEXIST ;
302+
303+ pmt_crashlog_set_consumed (crashlog );
304+
305+ return count ;
306+ }
307+ static DEVICE_ATTR_RW (consumed );
308+
165309static ssize_t
166310enable_show (struct device * dev , struct device_attribute * attr , char * buf )
167311{
@@ -193,6 +337,51 @@ enable_store(struct device *dev, struct device_attribute *attr,
193337}
194338static DEVICE_ATTR_RW (enable );
195339
340+ static ssize_t
341+ error_show (struct device * dev , struct device_attribute * attr , char * buf )
342+ {
343+ struct crashlog_entry * crashlog = dev_get_drvdata (dev );
344+ bool error = pmt_crashlog_error (crashlog );
345+
346+ return sysfs_emit (buf , "%d\n" , error );
347+ }
348+ static DEVICE_ATTR_RO (error );
349+
350+ static ssize_t
351+ rearm_show (struct device * dev , struct device_attribute * attr , char * buf )
352+ {
353+ struct crashlog_entry * crashlog = dev_get_drvdata (dev );
354+ int rearmed = pmt_crashlog_rearm (crashlog );
355+
356+ return sysfs_emit (buf , "%d\n" , rearmed );
357+ }
358+
359+ static ssize_t
360+ rearm_store (struct device * dev , struct device_attribute * attr , const char * buf ,
361+ size_t count )
362+ {
363+ struct crashlog_entry * crashlog ;
364+ bool rearm ;
365+ int result ;
366+
367+ crashlog = dev_get_drvdata (dev );
368+
369+ result = kstrtobool (buf , & rearm );
370+ if (result )
371+ return result ;
372+
373+ /* set only */
374+ if (!rearm )
375+ return - EINVAL ;
376+
377+ guard (mutex )(& crashlog -> control_mutex );
378+
379+ pmt_crashlog_set_rearm (crashlog );
380+
381+ return count ;
382+ }
383+ static DEVICE_ATTR_RW (rearm );
384+
196385static ssize_t
197386trigger_show (struct device * dev , struct device_attribute * attr , char * buf )
198387{
@@ -240,14 +429,28 @@ trigger_store(struct device *dev, struct device_attribute *attr,
240429}
241430static DEVICE_ATTR_RW (trigger );
242431
243- static struct attribute * pmt_crashlog_attrs [] = {
432+ static struct attribute * pmt_crashlog_type1_ver0_attrs [] = {
244433 & dev_attr_enable .attr ,
245434 & dev_attr_trigger .attr ,
246435 NULL
247436};
248437
249- static const struct attribute_group pmt_crashlog_group = {
250- .attrs = pmt_crashlog_attrs ,
438+ static struct attribute * pmt_crashlog_type1_ver2_attrs [] = {
439+ & dev_attr_clear .attr ,
440+ & dev_attr_consumed .attr ,
441+ & dev_attr_enable .attr ,
442+ & dev_attr_error .attr ,
443+ & dev_attr_rearm .attr ,
444+ & dev_attr_trigger .attr ,
445+ NULL
446+ };
447+
448+ static const struct attribute_group pmt_crashlog_type1_ver0_group = {
449+ .attrs = pmt_crashlog_type1_ver0_attrs ,
450+ };
451+
452+ static const struct attribute_group pmt_crashlog_type1_ver2_group = {
453+ .attrs = pmt_crashlog_type1_ver2_attrs ,
251454};
252455
253456static const struct crashlog_info crashlog_type1_ver0 = {
@@ -261,22 +464,55 @@ static const struct crashlog_info crashlog_type1_ver0 = {
261464 .control .clear = TYPE1_VER0_CLEAR ,
262465 .control .disable = TYPE1_VER0_DISABLE ,
263466 .control .manual = TYPE1_VER0_EXECUTE ,
467+ .attr_grp = & pmt_crashlog_type1_ver0_group ,
264468};
265469
470+ static const struct crashlog_info crashlog_type1_ver2 = {
471+ .status .offset = TYPE1_VER2_STATUS_OFFSET ,
472+ .status .clear_supported = TYPE1_VER2_CLEAR_SUPPORT ,
473+ .status .cleared = TYPE1_VER2_CLEARED ,
474+ .status .complete = TYPE1_VER2_COMPLETE ,
475+ .status .consumed = TYPE1_VER2_CONSUMED ,
476+ .status .disabled = TYPE1_VER2_DISABLED ,
477+ .status .error = TYPE1_VER2_ERROR ,
478+ .status .in_progress = TYPE1_VER2_IN_PROGRESS ,
479+ .status .rearmed = TYPE1_VER2_REARMED ,
480+
481+ .control .offset = TYPE1_VER2_CONTROL_OFFSET ,
482+ .control .trigger_mask = TYPE1_VER2_TRIGGER_MASK ,
483+ .control .clear = TYPE1_VER2_CLEAR ,
484+ .control .consume = TYPE1_VER2_CONSUME ,
485+ .control .disable = TYPE1_VER2_DISABLE ,
486+ .control .manual = TYPE1_VER2_EXECUTE ,
487+ .control .rearm = TYPE1_VER2_REARM ,
488+ .attr_grp = & pmt_crashlog_type1_ver2_group ,
489+ };
490+
491+ static const struct crashlog_info * select_crashlog_info (u32 type , u32 version )
492+ {
493+ if (version == 0 )
494+ return & crashlog_type1_ver0 ;
495+
496+ return & crashlog_type1_ver2 ;
497+ }
498+
266499static int pmt_crashlog_header_decode (struct intel_pmt_entry * entry ,
267500 struct device * dev )
268501{
269502 void __iomem * disc_table = entry -> disc_table ;
270503 struct intel_pmt_header * header = & entry -> header ;
271504 struct crashlog_entry * crashlog ;
505+ u32 version ;
506+ u32 type ;
272507
273- if (!pmt_crashlog_supported (entry ))
508+ if (!pmt_crashlog_supported (entry , & type , & version ))
274509 return 1 ;
275510
276511 /* initialize the crashlog struct */
277512 crashlog = container_of (entry , struct crashlog_entry , entry );
278513 mutex_init (& crashlog -> control_mutex );
279- crashlog -> info = & crashlog_type1_ver0 ;
514+
515+ crashlog -> info = select_crashlog_info (type , version );
280516
281517 header -> access_type = GET_ACCESS (readl (disc_table ));
282518 header -> guid = readl (disc_table + GUID_OFFSET );
@@ -285,7 +521,7 @@ static int pmt_crashlog_header_decode(struct intel_pmt_entry *entry,
285521 /* Size is measured in DWORDS, but accessor returns bytes */
286522 header -> size = GET_SIZE (readl (disc_table + SIZE_OFFSET ));
287523
288- entry -> attr_grp = & pmt_crashlog_group ;
524+ entry -> attr_grp = crashlog -> info -> attr_grp ;
289525
290526 return 0 ;
291527}
0 commit comments