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