xref: /linux/drivers/gpu/drm/imagination/pvr_dump.c (revision 4a57e0913e8c7fff407e97909f4ae48caa84d612)
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /* Copyright (c) 2026 Imagination Technologies Ltd. */
3 
4 #include "pvr_device.h"
5 #include "pvr_dump.h"
6 #include "pvr_rogue_fwif.h"
7 
8 #include <drm/drm_print.h>
9 #include <linux/types.h>
10 
11 static const char *
12 get_reset_reason_desc(enum rogue_context_reset_reason reason)
13 {
14 	switch (reason) {
15 	case ROGUE_CONTEXT_RESET_REASON_NONE:
16 		return "None";
17 	case ROGUE_CONTEXT_RESET_REASON_GUILTY_LOCKUP:
18 		return "Guilty lockup";
19 	case ROGUE_CONTEXT_RESET_REASON_INNOCENT_LOCKUP:
20 		return "Innocent lockup";
21 	case ROGUE_CONTEXT_RESET_REASON_GUILTY_OVERRUNING:
22 		return "Guilty overrunning";
23 	case ROGUE_CONTEXT_RESET_REASON_INNOCENT_OVERRUNING:
24 		return "Innocent overrunning";
25 	case ROGUE_CONTEXT_RESET_REASON_HARD_CONTEXT_SWITCH:
26 		return "Hard context switch";
27 	case ROGUE_CONTEXT_RESET_REASON_WGP_CHECKSUM:
28 		return "CDM Mission/safety checksum mismatch";
29 	case ROGUE_CONTEXT_RESET_REASON_TRP_CHECKSUM:
30 		return "TRP checksum mismatch";
31 	case ROGUE_CONTEXT_RESET_REASON_GPU_ECC_OK:
32 		return "GPU ECC error (corrected, OK)";
33 	case ROGUE_CONTEXT_RESET_REASON_GPU_ECC_HWR:
34 		return "GPU ECC error (uncorrected, HWR)";
35 	case ROGUE_CONTEXT_RESET_REASON_FW_ECC_OK:
36 		return "Firmware ECC error (corrected, OK)";
37 	case ROGUE_CONTEXT_RESET_REASON_FW_ECC_ERR:
38 		return "Firmware ECC error (uncorrected, ERR)";
39 	case ROGUE_CONTEXT_RESET_REASON_FW_WATCHDOG:
40 		return "Firmware watchdog";
41 	case ROGUE_CONTEXT_RESET_REASON_FW_PAGEFAULT:
42 		return "Firmware pagefault";
43 	case ROGUE_CONTEXT_RESET_REASON_FW_EXEC_ERR:
44 		return "Firmware execution error";
45 	case ROGUE_CONTEXT_RESET_REASON_HOST_WDG_FW_ERR:
46 		return "Host watchdog";
47 	case ROGUE_CONTEXT_GEOM_OOM_DISABLED:
48 		return "Geometry OOM disabled";
49 
50 	default:
51 		return "Unknown";
52 	}
53 }
54 
55 static const char *
56 get_dm_name(u32 dm)
57 {
58 	switch (dm) {
59 	case PVR_FWIF_DM_GP:
60 		return "General purpose";
61 	/* PVR_FWIF_DM_TDM has the same index, but is discriminated by a device feature */
62 	case PVR_FWIF_DM_2D:
63 		return "2D or TDM";
64 	case PVR_FWIF_DM_GEOM:
65 		return "Geometry";
66 	case PVR_FWIF_DM_FRAG:
67 		return "Fragment";
68 	case PVR_FWIF_DM_CDM:
69 		return "Compute";
70 	case PVR_FWIF_DM_RAY:
71 		return "Raytracing";
72 	case PVR_FWIF_DM_GEOM2:
73 		return "Geometry 2";
74 	case PVR_FWIF_DM_GEOM3:
75 		return "Geometry 3";
76 	case PVR_FWIF_DM_GEOM4:
77 		return "Geometry 4";
78 
79 	default:
80 		return "Unknown";
81 	}
82 }
83 
84 /**
85  * pvr_dump_context_reset_notification() - Handle context reset notification from FW
86  * @pvr_dev: Device pointer.
87  * @data: Data provided by FW.
88  *
89  * This will decode the data structure provided by FW and print the results via drm_info().
90  */
91 void
92 pvr_dump_context_reset_notification(struct pvr_device *pvr_dev,
93 				    struct rogue_fwif_fwccb_cmd_context_reset_data *data)
94 {
95 	struct drm_device *drm_dev = from_pvr_device(pvr_dev);
96 
97 	if (data->flags & ROGUE_FWIF_FWCCB_CMD_CONTEXT_RESET_FLAG_ALL_CTXS) {
98 		drm_info(drm_dev, "Received context reset notification for all contexts\n");
99 	} else {
100 		drm_info(drm_dev, "Received context reset notification on context %u\n",
101 			 data->server_common_context_id);
102 	}
103 
104 	drm_info(drm_dev, "  Reset reason=%u (%s)\n", data->reset_reason,
105 		 get_reset_reason_desc((enum rogue_context_reset_reason)data->reset_reason));
106 	drm_info(drm_dev, "  Data Master=%u (%s)\n", data->dm, get_dm_name(data->dm));
107 	drm_info(drm_dev, "  Job ref=%u\n", data->reset_job_ref);
108 
109 	if (data->flags & ROGUE_FWIF_FWCCB_CMD_CONTEXT_RESET_FLAG_PF) {
110 		drm_info(drm_dev, "  Page fault occurred, fault address=%llx\n",
111 			 data->fault_address);
112 	}
113 }
114