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