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