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