53
53
#define TYPE1_VER0_COMPLETE BIT(31)
54
54
#define TYPE1_VER0_TRIGGER_MASK GENMASK(31, 28)
55
55
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
+
56
82
/* After offset, order alphabetically, not bit ordered */
57
83
struct crashlog_status {
58
84
u32 offset ;
85
+ u32 clear_supported ;
59
86
u32 cleared ;
60
87
u32 complete ;
88
+ u32 consumed ;
61
89
u32 disabled ;
90
+ u32 error ;
91
+ u32 in_progress ;
92
+ u32 rearmed ;
62
93
};
63
94
64
95
struct crashlog_control {
65
96
u32 offset ;
66
97
u32 trigger_mask ;
67
98
u32 clear ;
99
+ u32 consume ;
68
100
u32 disable ;
69
101
u32 manual ;
102
+ u32 rearm ;
70
103
};
71
104
72
105
struct crashlog_info {
73
106
const struct crashlog_status status ;
74
107
const struct crashlog_control control ;
108
+ const struct attribute_group * attr_grp ;
75
109
};
76
110
77
111
struct crashlog_entry {
@@ -128,19 +162,23 @@ static bool pmt_crashlog_disabled(struct crashlog_entry *crashlog)
128
162
return pmt_crashlog_rc (crashlog , crashlog -> info -> status .disabled );
129
163
}
130
164
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 )
132
166
{
133
167
u32 discovery_header = readl (entry -> disc_table + CONTROL_OFFSET );
134
- u32 crash_type , version ;
135
168
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 );
138
171
139
172
/*
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.
142
177
*/
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;
144
182
}
145
183
146
184
static void pmt_crashlog_set_disable (struct crashlog_entry * crashlog ,
@@ -159,9 +197,115 @@ static void pmt_crashlog_set_execute(struct crashlog_entry *crashlog)
159
197
pmt_crashlog_rmw (crashlog , crashlog -> info -> control .manual , true);
160
198
}
161
199
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
+
162
230
/*
163
231
* sysfs
164
232
*/
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
+
165
309
static ssize_t
166
310
enable_show (struct device * dev , struct device_attribute * attr , char * buf )
167
311
{
@@ -193,6 +337,51 @@ enable_store(struct device *dev, struct device_attribute *attr,
193
337
}
194
338
static DEVICE_ATTR_RW (enable );
195
339
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
+
196
385
static ssize_t
197
386
trigger_show (struct device * dev , struct device_attribute * attr , char * buf )
198
387
{
@@ -240,14 +429,28 @@ trigger_store(struct device *dev, struct device_attribute *attr,
240
429
}
241
430
static DEVICE_ATTR_RW (trigger );
242
431
243
- static struct attribute * pmt_crashlog_attrs [] = {
432
+ static struct attribute * pmt_crashlog_type1_ver0_attrs [] = {
244
433
& dev_attr_enable .attr ,
245
434
& dev_attr_trigger .attr ,
246
435
NULL
247
436
};
248
437
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 ,
251
454
};
252
455
253
456
static const struct crashlog_info crashlog_type1_ver0 = {
@@ -261,22 +464,55 @@ static const struct crashlog_info crashlog_type1_ver0 = {
261
464
.control .clear = TYPE1_VER0_CLEAR ,
262
465
.control .disable = TYPE1_VER0_DISABLE ,
263
466
.control .manual = TYPE1_VER0_EXECUTE ,
467
+ .attr_grp = & pmt_crashlog_type1_ver0_group ,
264
468
};
265
469
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
+
266
499
static int pmt_crashlog_header_decode (struct intel_pmt_entry * entry ,
267
500
struct device * dev )
268
501
{
269
502
void __iomem * disc_table = entry -> disc_table ;
270
503
struct intel_pmt_header * header = & entry -> header ;
271
504
struct crashlog_entry * crashlog ;
505
+ u32 version ;
506
+ u32 type ;
272
507
273
- if (!pmt_crashlog_supported (entry ))
508
+ if (!pmt_crashlog_supported (entry , & type , & version ))
274
509
return 1 ;
275
510
276
511
/* initialize the crashlog struct */
277
512
crashlog = container_of (entry , struct crashlog_entry , entry );
278
513
mutex_init (& crashlog -> control_mutex );
279
- crashlog -> info = & crashlog_type1_ver0 ;
514
+
515
+ crashlog -> info = select_crashlog_info (type , version );
280
516
281
517
header -> access_type = GET_ACCESS (readl (disc_table ));
282
518
header -> guid = readl (disc_table + GUID_OFFSET );
@@ -285,7 +521,7 @@ static int pmt_crashlog_header_decode(struct intel_pmt_entry *entry,
285
521
/* Size is measured in DWORDS, but accessor returns bytes */
286
522
header -> size = GET_SIZE (readl (disc_table + SIZE_OFFSET ));
287
523
288
- entry -> attr_grp = & pmt_crashlog_group ;
524
+ entry -> attr_grp = crashlog -> info -> attr_grp ;
289
525
290
526
return 0 ;
291
527
}
0 commit comments