// SPDX-License-Identifier: GPL-2.0 /* * (C) COPYRIGHT 2019 ARM Limited. All rights reserved. * Author: James.Qian.Wang * */ #include #include #include "komeda_dev.h" struct komeda_str { char *str; u32 sz; u32 len; }; /* return 0 on success, < 0 on no space. */ __printf(2, 3) static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...) { va_list args; int num, free_sz; int err; free_sz = str->sz - str->len - 1; if (free_sz <= 0) return -ENOSPC; va_start(args, fmt); num = vsnprintf(str->str + str->len, free_sz, fmt, args); va_end(args); if (num < free_sz) { str->len += num; err = 0; } else { str->len = str->sz - 1; err = -ENOSPC; } return err; } static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg) { if (evt) komeda_sprintf(str, msg); } static void evt_str(struct komeda_str *str, u64 events) { if (events == 0ULL) { komeda_sprintf(str, "None"); return; } evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|"); evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|"); evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|"); evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|"); evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|"); evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|"); /* GLB error */ evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|"); evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|"); /* DOU error */ evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|"); evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|"); evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|"); evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|"); /* LPU errors or events */ evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|"); evt_sprintf(str, events & KOMEDA_EVENT_EMPTY, "EMPTY|"); evt_sprintf(str, events & KOMEDA_EVENT_FULL, "FULL|"); evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|"); evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|"); evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|"); evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|"); evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|"); /* LPU TBU errors*/ evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|"); evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|"); evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|"); evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|"); evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|"); /* CU errors*/ evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|"); evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|"); evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|"); evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|"); if (str->len > 0 && (str->str[str->len - 1] == '|')) { str->str[str->len - 1] = 0; str->len--; } } static bool is_new_frame(struct komeda_events *a) { return (a->pipes[0] | a->pipes[1]) & (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW); } void komeda_print_events(struct komeda_events *evts, struct drm_device *dev) { u64 print_evts = 0; static bool en_print = true; struct komeda_dev *mdev = dev->dev_private; u16 const err_verbosity = mdev->err_verbosity; u64 evts_mask = evts->global | evts->pipes[0] | evts->pipes[1]; /* reduce the same msg print, only print the first evt for one frame */ if (evts->global || is_new_frame(evts)) en_print = true; if (!(err_verbosity & KOMEDA_DEV_PRINT_DISABLE_RATELIMIT) && !en_print) return; if (err_verbosity & KOMEDA_DEV_PRINT_ERR_EVENTS) print_evts |= KOMEDA_ERR_EVENTS; if (err_verbosity & KOMEDA_DEV_PRINT_WARN_EVENTS) print_evts |= KOMEDA_WARN_EVENTS; if (err_verbosity & KOMEDA_DEV_PRINT_INFO_EVENTS) print_evts |= KOMEDA_INFO_EVENTS; if (evts_mask & print_evts) { char msg[256]; struct komeda_str str; struct drm_printer p = drm_info_printer(dev->dev); str.str = msg; str.sz = sizeof(msg); str.len = 0; komeda_sprintf(&str, "gcu: "); evt_str(&str, evts->global); komeda_sprintf(&str, ", pipes[0]: "); evt_str(&str, evts->pipes[0]); komeda_sprintf(&str, ", pipes[1]: "); evt_str(&str, evts->pipes[1]); DRM_ERROR("err detect: %s\n", msg); if ((err_verbosity & KOMEDA_DEV_PRINT_DUMP_STATE_ON_EVENT) && (evts_mask & (KOMEDA_ERR_EVENTS | KOMEDA_WARN_EVENTS))) drm_state_dump(dev, &p); en_print = false; } }