1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * (C) COPYRIGHT 2019 ARM Limited. All rights reserved. 4 * Author: James.Qian.Wang <james.qian.wang@arm.com> 5 * 6 */ 7 #include <drm/drm_atomic.h> 8 #include <drm/drm_print.h> 9 10 #include "komeda_dev.h" 11 12 struct komeda_str { 13 char *str; 14 u32 sz; 15 u32 len; 16 }; 17 18 /* return 0 on success, < 0 on no space. 19 */ 20 static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...) 21 { 22 va_list args; 23 int num, free_sz; 24 int err; 25 26 free_sz = str->sz - str->len - 1; 27 if (free_sz <= 0) 28 return -ENOSPC; 29 30 va_start(args, fmt); 31 32 num = vsnprintf(str->str + str->len, free_sz, fmt, args); 33 34 va_end(args); 35 36 if (num < free_sz) { 37 str->len += num; 38 err = 0; 39 } else { 40 str->len = str->sz - 1; 41 err = -ENOSPC; 42 } 43 44 return err; 45 } 46 47 static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg) 48 { 49 if (evt) 50 komeda_sprintf(str, msg); 51 } 52 53 static void evt_str(struct komeda_str *str, u64 events) 54 { 55 if (events == 0ULL) { 56 komeda_sprintf(str, "None"); 57 return; 58 } 59 60 evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|"); 61 evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|"); 62 evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|"); 63 evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|"); 64 65 evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|"); 66 evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|"); 67 68 /* GLB error */ 69 evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|"); 70 evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|"); 71 72 /* DOU error */ 73 evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|"); 74 evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|"); 75 evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|"); 76 evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|"); 77 78 /* LPU errors or events */ 79 evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|"); 80 evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|"); 81 evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|"); 82 evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|"); 83 evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|"); 84 evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|"); 85 86 /* LPU TBU errors*/ 87 evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|"); 88 evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|"); 89 evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|"); 90 evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|"); 91 evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|"); 92 93 /* CU errors*/ 94 evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|"); 95 evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|"); 96 evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|"); 97 evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|"); 98 99 if (str->len > 0 && (str->str[str->len - 1] == '|')) { 100 str->str[str->len - 1] = 0; 101 str->len--; 102 } 103 } 104 105 static bool is_new_frame(struct komeda_events *a) 106 { 107 return (a->pipes[0] | a->pipes[1]) & 108 (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW); 109 } 110 111 void komeda_print_events(struct komeda_events *evts, struct drm_device *dev) 112 { 113 u64 print_evts = 0; 114 static bool en_print = true; 115 struct komeda_dev *mdev = dev->dev_private; 116 u16 const err_verbosity = mdev->err_verbosity; 117 u64 evts_mask = evts->global | evts->pipes[0] | evts->pipes[1]; 118 119 /* reduce the same msg print, only print the first evt for one frame */ 120 if (evts->global || is_new_frame(evts)) 121 en_print = true; 122 if (!(err_verbosity & KOMEDA_DEV_PRINT_DISABLE_RATELIMIT) && !en_print) 123 return; 124 125 if (err_verbosity & KOMEDA_DEV_PRINT_ERR_EVENTS) 126 print_evts |= KOMEDA_ERR_EVENTS; 127 if (err_verbosity & KOMEDA_DEV_PRINT_WARN_EVENTS) 128 print_evts |= KOMEDA_WARN_EVENTS; 129 if (err_verbosity & KOMEDA_DEV_PRINT_INFO_EVENTS) 130 print_evts |= KOMEDA_INFO_EVENTS; 131 132 if (evts_mask & print_evts) { 133 char msg[256]; 134 struct komeda_str str; 135 struct drm_printer p = drm_info_printer(dev->dev); 136 137 str.str = msg; 138 str.sz = sizeof(msg); 139 str.len = 0; 140 141 komeda_sprintf(&str, "gcu: "); 142 evt_str(&str, evts->global); 143 komeda_sprintf(&str, ", pipes[0]: "); 144 evt_str(&str, evts->pipes[0]); 145 komeda_sprintf(&str, ", pipes[1]: "); 146 evt_str(&str, evts->pipes[1]); 147 148 DRM_ERROR("err detect: %s\n", msg); 149 if ((err_verbosity & KOMEDA_DEV_PRINT_DUMP_STATE_ON_EVENT) && 150 (evts_mask & (KOMEDA_ERR_EVENTS | KOMEDA_WARN_EVENTS))) 151 drm_state_dump(dev, &p); 152 153 en_print = false; 154 } 155 } 156