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, struct drm_device *dev) 111 { 112 u64 print_evts = 0; 113 static bool en_print = true; 114 struct komeda_dev *mdev = dev->dev_private; 115 u16 const err_verbosity = mdev->err_verbosity; 116 117 /* reduce the same msg print, only print the first evt for one frame */ 118 if (evts->global || is_new_frame(evts)) 119 en_print = true; 120 if (!en_print) 121 return; 122 123 if (err_verbosity & KOMEDA_DEV_PRINT_ERR_EVENTS) 124 print_evts |= KOMEDA_ERR_EVENTS; 125 126 if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) { 127 char msg[256]; 128 struct komeda_str str; 129 130 str.str = msg; 131 str.sz = sizeof(msg); 132 str.len = 0; 133 134 komeda_sprintf(&str, "gcu: "); 135 evt_str(&str, evts->global); 136 komeda_sprintf(&str, ", pipes[0]: "); 137 evt_str(&str, evts->pipes[0]); 138 komeda_sprintf(&str, ", pipes[1]: "); 139 evt_str(&str, evts->pipes[1]); 140 141 DRM_ERROR("err detect: %s\n", msg); 142 143 en_print = false; 144 } 145 } 146