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