blob: 60cfce28c8f16d10f58d9eabe4ae6464e051de78 [file] [log] [blame]
/*
* Samsung Exynos SoC series NPU driver
*
* Copyright (c) 2017 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _NPU_LOG_H_
#define _NPU_LOG_H_
#include <linux/types.h>
#include <linux/completion.h>
#include <linux/mutex.h>
#include <linux/kfifo.h>
#include <linux/wait.h>
#include <linux/atomic.h>
#include "npu-device.h"
#define NPU_RING_LOG_BUFFER_MAGIC 0x3920FFAC
/* Log level definition */
typedef enum {
NPU_LOG_TRACE = 0,
NPU_LOG_DBG, /* Default. Set in npu_log.c */
NPU_LOG_INFO,
NPU_LOG_WARN,
NPU_LOG_ERR,
NPU_LOG_NONE,
NPU_LOG_INVALID,
} npu_log_level_e;
/* Default tag definition */
#ifndef NPU_LOG_TAG
#define NPU_LOG_TAG "*"
#endif
/* Structure for log management object */
struct npu_log {
/* kernel logger level */
npu_log_level_e pr_level;
/* memory storage logger level */
npu_log_level_e st_level;
/* Buffer for log storage */
char *st_buf;
size_t wr_pos;
size_t st_size;
size_t line_cnt;
/* Save last dump postion to gracefully handle consecutive error case */
size_t last_dump_line_cnt;
/* Position where the last dump log has read */
size_t last_dump_mark_pos;
/* Reference counter for debugfs interface */
atomic_t fs_ref;
/* Wait queue to notify readers */
wait_queue_head_t wq;
};
extern struct npu_log npu_log;
extern struct npu_log fw_report;
/*
* Define interval mask to printout sync mark on kernel log
* to sync with memory stored log.
* sync mark is printed if (npu_log.line_cnt & MASK == 0)
*/
#define NPU_STORE_LOG_SYNC_MARK_INTERVAL_MASK 0x7F /* Sync mark on every 128 messages */
#define NPU_STORE_LOG_SYNC_MARK_MSG "NPU log sync [%zu]\n"
/* Amount of log dumped on an error occurred */
#define NPU_STORE_LOG_DUMP_SIZE_ON_ERROR (16 * 1024)
/* Log flush wait interval and count when the store log is de-initialized */
#define NPU_STORE_LOG_FLUSH_INTERVAL_MS 500
/* Chunk size used in bitmap_scnprintf */
#define CHUNKSZ 32
/* Log size used in memdump with memcpy */
#define MEMLOGSIZE 16
/* Structure to represent ring buffer log storage */
struct npu_ring_log_buffer {
u32 magic;
const char *name;
struct mutex lock;
struct completion read_wq;
DECLARE_KFIFO_PTR(fifo, char);
size_t size;
size_t wPtr;
};
/* Per file descriptor object for ring log buffer */
struct npu_ring_log_buffer_fd_obj {
struct npu_ring_log_buffer *ring_buf;
size_t last_pos;
};
/* Prototypes */
int npu_store_log(npu_log_level_e loglevel, const char *fmt, ...); /* Shall not be used directly */
void npu_store_log_init(char *buf_addr, size_t size);
void npu_store_log_deinit(void);
void npu_log_on_error(void);
void npu_fw_report_init(char *buf_addr, const size_t size);
void npu_fw_report_store(char *strRep, int nSize);
void dbg_print_fw_report_st(struct npu_log stLog);
void npu_fw_report_deinit(void);
/* Utilities */
s32 atoi(const char *psz_buf);
int bitmap_scnprintf(char *buf, unsigned int buflen, const unsigned long *maskp, int nmaskbits);
/* Memory dump */
int npu_debug_memdump8(u8 *start, u8 *end);
int npu_debug_memdump16(u16 *start, u16 *end);
int npu_debug_memdump32(u32 *start, u32 *end);
int npu_debug_memdump32_by_memcpy(u32 *start, u32 *end);
#define ISPRINTABLE(strValue) (isascii(strValue) && isprint(strValue) ? strValue : '.')
#define probe_info(fmt, ...) pr_info("NPU:" fmt, ##__VA_ARGS__)
#define probe_warn(fmt, args...) pr_warn("NPU:[WRN]" fmt, ##args)
#define probe_err(fmt, args...) pr_err("NPU:[ERR]%s:%d:" fmt, __func__, __LINE__, ##args)
#define probe_trace(fmt, ...) ((npu_log.pr_level <= NPU_LOG_TRACE)?pr_info(fmt, ##__VA_ARGS__):0)
#ifdef DEBUG_LOG_MEMORY
#define npu_log_on_lv_target(LV, PR_FUNC, fmt, ...) PR_FUNC(fmt, ##__VA_ARGS__)
#else
#define npu_log_on_lv_target(LV, PR_FUNC, fmt, ...) \
do { \
int __npu_ret = 0; \
if (npu_log.st_level <= (LV)) \
__npu_ret = npu_store_log((LV), fmt, ##__VA_ARGS__); \
if (__npu_ret) \
pr_err(fmt, ##__VA_ARGS__); \
else { \
if (npu_log.pr_level <= (LV)) \
PR_FUNC(fmt, ##__VA_ARGS__); \
} \
} while (0)
#endif
#define npu_err_target(fmt, ...) \
do { \
npu_log_on_lv_target(NPU_LOG_ERR, pr_err, fmt, ##__VA_ARGS__); \
npu_log_on_error(); \
} while (0)
#define npu_warn_target(fmt, ...) npu_log_on_lv_target(NPU_LOG_WARN, pr_warning, fmt, ##__VA_ARGS__)
#define npu_info_target(fmt, ...) npu_log_on_lv_target(NPU_LOG_INFO, pr_notice, fmt, ##__VA_ARGS__)
#define npu_dbg_target(fmt, ...) npu_log_on_lv_target(NPU_LOG_DBG, pr_info, fmt, ##__VA_ARGS__)
#define npu_trace_target(fmt, ...) npu_log_on_lv_target(NPU_LOG_TRACE, pr_debug, fmt, ##__VA_ARGS__)
#define npu_err(fmt, args...) \
npu_err_target("NPU:[" NPU_LOG_TAG "][ERR]%s(%d):" fmt, __func__, __LINE__, ##args)
#define npu_warn(fmt, args...) \
npu_warn_target("NPU:[" NPU_LOG_TAG "][WRN]%s(%d):" fmt, __func__, __LINE__, ##args)
#define npu_info(fmt, args...) \
npu_info_target("NPU:[" NPU_LOG_TAG "]%s(%d):" fmt, __func__, __LINE__, ##args)
#define npu_dbg(fmt, args...) \
npu_dbg_target("NPU:[" NPU_LOG_TAG "]%s(%d):" fmt, __func__, __LINE__, ##args)
#define npu_trace(fmt, args...) \
npu_trace_target("NPU:[T][" NPU_LOG_TAG "]%s(%d):" fmt, __func__, __LINE__, ##args)
/* Printout context ID */
#define npu_ierr(fmt, vctx, args...) \
npu_err_target("NPU:[" NPU_LOG_TAG "][I%d][ERR]%s(%d):" fmt, (vctx)->id, __func__, __LINE__, ##args)
#define npu_iwarn(fmt, vctx, args...) \
npu_warn_target("NPU:[" NPU_LOG_TAG "][I%d][WRN]%s(%d):" fmt, (vctx)->id, __func__, __LINE__, ##args)
#define npu_iinfo(fmt, vctx, args...) \
npu_info_target("NPU:[" NPU_LOG_TAG "][I%d]%s(%d):" fmt, (vctx)->id, __func__, __LINE__, ##args)
#define npu_idbg(fmt, vctx, args...) \
npu_dbg_target("NPU:[" NPU_LOG_TAG "][I%d]%s(%d):" fmt, (vctx)->id, __func__, __LINE__, ##args)
#define npu_itrace(fmt, vctx, args...) \
npu_trace_target("NPU:[T][" NPU_LOG_TAG "][I%d]%s(%d):" fmt, (vctx)->id, __func__, __LINE__, ##args)
/* Printout unique ID */
#define npu_uerr(fmt, uid_obj, args...) \
npu_err_target("NPU:[" NPU_LOG_TAG "][U%d][ERR]%s(%d):" fmt, (uid_obj)->uid, __func__, __LINE__, ##args)
#define npu_uwarn(fmt, uid_obj, args...) \
npu_warn_target("NPU:[" NPU_LOG_TAG "][U%d][WRN]%s(%d):" fmt, (uid_obj)->uid, __func__, __LINE__, ##args)
#define npu_uinfo(fmt, uid_obj, args...) \
npu_info_target("NPU:[" NPU_LOG_TAG "][U%d]%s(%d):" fmt, (uid_obj)->uid, __func__, __LINE__, ##args)
#define npu_udbg(fmt, uid_obj, args...) \
npu_dbg_target("NPU:[" NPU_LOG_TAG "][U%d]%s(%d):" fmt, (uid_obj)->uid, __func__, __LINE__, ##args)
#define npu_utrace(fmt, uid_obj, args...) \
npu_trace_target("NPU:[T][" NPU_LOG_TAG "][U%d]%s(%d):" fmt, (uid_obj)->uid, __func__, __LINE__, ##args)
/* Printout unique ID and frame ID */
#define npu_uferr(fmt, obj_ptr, args...) \
({ typeof(*obj_ptr) *__pt = (obj_ptr); npu_err_target("NPU:[" NPU_LOG_TAG "][U%u][F%u][ERR]%s(%d):" fmt, (__pt)->uid, (__pt)->frame_id, __func__, __LINE__, ##args); })
#define npu_ufwarn(fmt, obj_ptr, args...) \
({ typeof(*obj_ptr) *__pt = (obj_ptr); npu_warn_target("NPU:[" NPU_LOG_TAG "][U%u][F%u][WRN]%s(%d):" fmt, (__pt)->uid, (__pt)->frame_id, __func__, __LINE__, ##args); })
#define npu_ufinfo(fmt, obj_ptr, args...) \
({ typeof(*obj_ptr) *__pt = (obj_ptr); npu_info_target("NPU:[" NPU_LOG_TAG "][U%u][F%u]%s(%d):" fmt, (__pt)->uid, (__pt)->frame_id, __func__, __LINE__, ##args); })
#define npu_ufdbg(fmt, obj_ptr, args...) \
({ typeof(*obj_ptr) *__pt = (obj_ptr); npu_dbg_target("NPU:[" NPU_LOG_TAG "][U%u][F%u]%s(%d):" fmt, (__pt)->uid, (__pt)->frame_id, __func__, __LINE__, ##args); })
#define npu_uftrace(fmt, obj_ptr, args...) \
({ typeof(*obj_ptr) *__pt = (obj_ptr); npu_trace_target("NPU:[T][" NPU_LOG_TAG "][U%u][F%u]%s(%d):" fmt, (__pt)->uid, (__pt)->frame_id, __func__, __LINE__, ##args); })
/* Exported functions */
struct npu_device;
int npu_log_probe(struct npu_device *npu_device);
int npu_log_release(struct npu_device *npu_device);
int npu_log_open(struct npu_device *npu_device);
int npu_log_close(struct npu_device *npu_device);
int npu_log_start(struct npu_device *npu_device);
int npu_log_stop(struct npu_device *npu_device);
int fw_will_note(size_t len);
#endif /* _NPU_LOG_H_ */