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_ERR_AXIE, "AXIE|"); 82 evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|"); 83 evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|"); 84 evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|"); 85 evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|"); 86 87 /* LPU TBU errors*/ 88 evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|"); 89 evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|"); 90 evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|"); 91 evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|"); 92 evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|"); 93 94 /* CU errors*/ 95 evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|"); 96 evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|"); 97 evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|"); 98 evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|"); 99 100 if (str->len > 0 && (str->str[str->len - 1] == '|')) { 101 str->str[str->len - 1] = 0; 102 str->len--; 103 } 104 } 105 106 static bool is_new_frame(struct komeda_events *a) 107 { 108 return (a->pipes[0] | a->pipes[1]) & 109 (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW); 110 } 111 112 void komeda_print_events(struct komeda_events *evts, struct drm_device *dev) 113 { 114 u64 print_evts = 0; 115 static bool en_print = true; 116 struct komeda_dev *mdev = dev->dev_private; 117 u16 const err_verbosity = mdev->err_verbosity; 118 u64 evts_mask = evts->global | evts->pipes[0] | evts->pipes[1]; 119 120 /* reduce the same msg print, only print the first evt for one frame */ 121 if (evts->global || is_new_frame(evts)) 122 en_print = true; 123 if (!(err_verbosity & KOMEDA_DEV_PRINT_DISABLE_RATELIMIT) && !en_print) 124 return; 125 126 if (err_verbosity & KOMEDA_DEV_PRINT_ERR_EVENTS) 127 print_evts |= KOMEDA_ERR_EVENTS; 128 if (err_verbosity & KOMEDA_DEV_PRINT_WARN_EVENTS) 129 print_evts |= KOMEDA_WARN_EVENTS; 130 if (err_verbosity & KOMEDA_DEV_PRINT_INFO_EVENTS) 131 print_evts |= KOMEDA_INFO_EVENTS; 132 133 if (evts_mask & print_evts) { 134 char msg[256]; 135 struct komeda_str str; 136 struct drm_printer p = drm_info_printer(dev->dev); 137 138 str.str = msg; 139 str.sz = sizeof(msg); 140 str.len = 0; 141 142 komeda_sprintf(&str, "gcu: "); 143 evt_str(&str, evts->global); 144 komeda_sprintf(&str, ", pipes[0]: "); 145 evt_str(&str, evts->pipes[0]); 146 komeda_sprintf(&str, ", pipes[1]: "); 147 evt_str(&str, evts->pipes[1]); 148 149 DRM_ERROR("err detect: %s\n", msg); 150 if ((err_verbosity & KOMEDA_DEV_PRINT_DUMP_STATE_ON_EVENT) && 151 (evts_mask & (KOMEDA_ERR_EVENTS | KOMEDA_WARN_EVENTS))) 152 drm_state_dump(dev, &p); 153 154 en_print = false; 155 } 156 } 157