Commit c610b5a8 authored by Jean-Christophe Trotin's avatar Jean-Christophe Trotin Committed by Mauro Carvalho Chehab

[media] st-hva: add debug file system

This patch creates 4 static debugfs entries to dump:
- the device-related information ("st-hva/device")
- the list of registered encoders ("st-hva/encoders")
- the current values of the hva registers ("st-hva/regs")
- the information about the last closed instance ("st-hva/last")

It also creates dynamically a debugfs entry for each opened instance,
("st-hva/<instance identifier>") to dump:
- the information about the frame (format, resolution)
- the information about the stream (format, profile, level,
  resolution)
- the control parameters (bitrate mode, framerate, GOP size...)
- the potential (system, encoding...) errors
- the performance information about the encoding (HW processing
  duration, average bitrate, average framerate...)
Each time a running instance is closed, its context (including the
debug information) is saved to feed, on demand, the last closed
instance debugfs entry.
Signed-off-by: default avatarYannick Fertre <yannick.fertre@st.com>
Acked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarJean-Christophe Trotin <jean-christophe.trotin@st.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent f7e1a6db
...@@ -301,6 +301,17 @@ config VIDEO_STI_HVA ...@@ -301,6 +301,17 @@ config VIDEO_STI_HVA
To compile this driver as a module, choose M here: To compile this driver as a module, choose M here:
the module will be called st-hva. the module will be called st-hva.
config VIDEO_STI_HVA_DEBUGFS
bool "Export STMicroelectronics HVA internals in debugfs"
depends on VIDEO_STI_HVA
depends on DEBUG_FS
help
Select this to see information about the internal state and the last
operation of STMicroelectronics HVA multi-format video encoder in
debugfs.
Choose N unless you know you need this.
config VIDEO_SH_VEU config VIDEO_SH_VEU
tristate "SuperH VEU mem2mem video processing driver" tristate "SuperH VEU mem2mem video processing driver"
depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
......
obj-$(CONFIG_VIDEO_STI_HVA) := st-hva.o obj-$(CONFIG_VIDEO_STI_HVA) := st-hva.o
st-hva-y := hva-v4l2.o hva-hw.o hva-mem.o hva-h264.o st-hva-y := hva-v4l2.o hva-hw.o hva-mem.o hva-h264.o
st-hva-$(CONFIG_VIDEO_STI_HVA_DEBUGFS) += hva-debugfs.o
This diff is collapsed.
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
#include <linux/seq_file.h>
#endif
#include "hva.h" #include "hva.h"
#include "hva-hw.h" #include "hva-hw.h"
...@@ -541,3 +544,43 @@ int hva_hw_execute_task(struct hva_ctx *ctx, enum hva_hw_cmd_type cmd, ...@@ -541,3 +544,43 @@ int hva_hw_execute_task(struct hva_ctx *ctx, enum hva_hw_cmd_type cmd,
return ret; return ret;
} }
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
#define DUMP(reg) seq_printf(s, "%-30s: 0x%08X\n",\
#reg, readl_relaxed(hva->regs + reg))
void hva_hw_dump_regs(struct hva_dev *hva, struct seq_file *s)
{
struct device *dev = hva_to_dev(hva);
mutex_lock(&hva->protect_mutex);
if (pm_runtime_get_sync(dev) < 0) {
seq_puts(s, "Cannot wake up IP\n");
mutex_unlock(&hva->protect_mutex);
return;
}
seq_printf(s, "Registers:\nReg @ = 0x%p\n", hva->regs);
DUMP(HVA_HIF_REG_RST);
DUMP(HVA_HIF_REG_RST_ACK);
DUMP(HVA_HIF_REG_MIF_CFG);
DUMP(HVA_HIF_REG_HEC_MIF_CFG);
DUMP(HVA_HIF_REG_CFL);
DUMP(HVA_HIF_REG_SFL);
DUMP(HVA_HIF_REG_LMI_ERR);
DUMP(HVA_HIF_REG_EMI_ERR);
DUMP(HVA_HIF_REG_HEC_MIF_ERR);
DUMP(HVA_HIF_REG_HEC_STS);
DUMP(HVA_HIF_REG_HVC_STS);
DUMP(HVA_HIF_REG_HJE_STS);
DUMP(HVA_HIF_REG_CNT);
DUMP(HVA_HIF_REG_HEC_CHKSYN_DIS);
DUMP(HVA_HIF_REG_CLK_GATING);
DUMP(HVA_HIF_REG_VERSION);
pm_runtime_put_autosuspend(dev);
mutex_unlock(&hva->protect_mutex);
}
#endif
...@@ -38,5 +38,8 @@ int hva_hw_runtime_suspend(struct device *dev); ...@@ -38,5 +38,8 @@ int hva_hw_runtime_suspend(struct device *dev);
int hva_hw_runtime_resume(struct device *dev); int hva_hw_runtime_resume(struct device *dev);
int hva_hw_execute_task(struct hva_ctx *ctx, enum hva_hw_cmd_type cmd, int hva_hw_execute_task(struct hva_ctx *ctx, enum hva_hw_cmd_type cmd,
struct hva_buffer *task); struct hva_buffer *task);
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
void hva_hw_dump_regs(struct hva_dev *hva, struct seq_file *s);
#endif
#endif /* HVA_HW_H */ #endif /* HVA_HW_H */
...@@ -15,8 +15,6 @@ ...@@ -15,8 +15,6 @@
#include "hva.h" #include "hva.h"
#include "hva-hw.h" #include "hva-hw.h"
#define HVA_NAME "st-hva"
#define MIN_FRAMES 1 #define MIN_FRAMES 1
#define MIN_STREAMS 1 #define MIN_STREAMS 1
...@@ -813,6 +811,10 @@ static void hva_run_work(struct work_struct *work) ...@@ -813,6 +811,10 @@ static void hva_run_work(struct work_struct *work)
/* protect instance against reentrancy */ /* protect instance against reentrancy */
mutex_lock(&ctx->lock); mutex_lock(&ctx->lock);
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
hva_dbg_perf_begin(ctx);
#endif
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
...@@ -834,6 +836,10 @@ static void hva_run_work(struct work_struct *work) ...@@ -834,6 +836,10 @@ static void hva_run_work(struct work_struct *work)
ctx->encoded_frames++; ctx->encoded_frames++;
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
hva_dbg_perf_end(ctx, stream);
#endif
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
} }
...@@ -1201,6 +1207,10 @@ static int hva_open(struct file *file) ...@@ -1201,6 +1207,10 @@ static int hva_open(struct file *file)
/* default parameters for frame and stream */ /* default parameters for frame and stream */
set_default_params(ctx); set_default_params(ctx);
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
hva_dbg_ctx_create(ctx);
#endif
dev_info(dev, "%s encoder instance created\n", ctx->name); dev_info(dev, "%s encoder instance created\n", ctx->name);
return 0; return 0;
...@@ -1242,6 +1252,10 @@ static int hva_release(struct file *file) ...@@ -1242,6 +1252,10 @@ static int hva_release(struct file *file)
v4l2_fh_del(&ctx->fh); v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh); v4l2_fh_exit(&ctx->fh);
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
hva_dbg_ctx_remove(ctx);
#endif
dev_info(dev, "%s encoder instance released\n", ctx->name); dev_info(dev, "%s encoder instance released\n", ctx->name);
kfree(ctx); kfree(ctx);
...@@ -1366,6 +1380,10 @@ static int hva_probe(struct platform_device *pdev) ...@@ -1366,6 +1380,10 @@ static int hva_probe(struct platform_device *pdev)
goto err_hw; goto err_hw;
} }
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
hva_debugfs_create(hva);
#endif
hva->work_queue = create_workqueue(HVA_NAME); hva->work_queue = create_workqueue(HVA_NAME);
if (!hva->work_queue) { if (!hva->work_queue) {
dev_err(dev, "%s %s failed to allocate work queue\n", dev_err(dev, "%s %s failed to allocate work queue\n",
...@@ -1387,6 +1405,9 @@ static int hva_probe(struct platform_device *pdev) ...@@ -1387,6 +1405,9 @@ static int hva_probe(struct platform_device *pdev)
err_work_queue: err_work_queue:
destroy_workqueue(hva->work_queue); destroy_workqueue(hva->work_queue);
err_v4l2: err_v4l2:
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
hva_debugfs_remove(hva);
#endif
v4l2_device_unregister(&hva->v4l2_dev); v4l2_device_unregister(&hva->v4l2_dev);
err_hw: err_hw:
hva_hw_remove(hva); hva_hw_remove(hva);
...@@ -1405,6 +1426,10 @@ static int hva_remove(struct platform_device *pdev) ...@@ -1405,6 +1426,10 @@ static int hva_remove(struct platform_device *pdev)
hva_hw_remove(hva); hva_hw_remove(hva);
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
hva_debugfs_remove(hva);
#endif
v4l2_device_unregister(&hva->v4l2_dev); v4l2_device_unregister(&hva->v4l2_dev);
dev_info(dev, "%s %s removed\n", HVA_PREFIX, pdev->name); dev_info(dev, "%s %s removed\n", HVA_PREFIX, pdev->name);
......
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
#define ctx_to_hdev(c) (c->hva_dev) #define ctx_to_hdev(c) (c->hva_dev)
#define HVA_PREFIX "[---:----]" #define HVA_NAME "st-hva"
#define HVA_PREFIX "[---:----]"
extern const struct hva_enc nv12h264enc; extern const struct hva_enc nv12h264enc;
extern const struct hva_enc nv21h264enc; extern const struct hva_enc nv21h264enc;
...@@ -153,6 +154,61 @@ struct hva_stream { ...@@ -153,6 +154,61 @@ struct hva_stream {
#define to_hva_stream(vb) \ #define to_hva_stream(vb) \
container_of(vb, struct hva_stream, vbuf) container_of(vb, struct hva_stream, vbuf)
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
/**
* struct hva_ctx_dbg - instance context debug info
*
* @debugfs_entry: debugfs entry
* @is_valid_period: true if the sequence is valid for performance
* @begin: start time of last HW task
* @total_duration: total HW processing durations in 0.1ms
* @cnt_duration: number of HW processings
* @min_duration: minimum HW processing duration in 0.1ms
* @max_duration: maximum HW processing duration in 0.1ms
* @avg_duration: average HW processing duration in 0.1ms
* @max_fps: maximum frames encoded per second (in 0.1Hz)
* @total_period: total encoding periods in 0.1ms
* @cnt_period: number of periods
* @min_period: minimum encoding period in 0.1ms
* @max_period: maximum encoding period in 0.1ms
* @avg_period: average encoding period in 0.1ms
* @total_stream_size: total number of encoded bytes
* @avg_fps: average frames encoded per second (in 0.1Hz)
* @window_duration: duration of the sampling window in 0.1ms
* @cnt_window: number of samples in the window
* @window_stream_size: number of encoded bytes upon the sampling window
* @last_bitrate: bitrate upon the last sampling window
* @min_bitrate: minimum bitrate in kbps
* @max_bitrate: maximum bitrate in kbps
* @avg_bitrate: average bitrate in kbps
*/
struct hva_ctx_dbg {
struct dentry *debugfs_entry;
bool is_valid_period;
ktime_t begin;
u32 total_duration;
u32 cnt_duration;
u32 min_duration;
u32 max_duration;
u32 avg_duration;
u32 max_fps;
u32 total_period;
u32 cnt_period;
u32 min_period;
u32 max_period;
u32 avg_period;
u32 total_stream_size;
u32 avg_fps;
u32 window_duration;
u32 cnt_window;
u32 window_stream_size;
u32 last_bitrate;
u32 min_bitrate;
u32 max_bitrate;
u32 avg_bitrate;
};
#endif
struct hva_dev; struct hva_dev;
struct hva_enc; struct hva_enc;
...@@ -186,6 +242,7 @@ struct hva_enc; ...@@ -186,6 +242,7 @@ struct hva_enc;
* @sys_errors: number of system errors (memory, resource, pm...) * @sys_errors: number of system errors (memory, resource, pm...)
* @encode_errors: number of encoding errors (hw/driver errors) * @encode_errors: number of encoding errors (hw/driver errors)
* @frame_errors: number of frame errors (format, size, header...) * @frame_errors: number of frame errors (format, size, header...)
* @dbg: context debug info
*/ */
struct hva_ctx { struct hva_ctx {
struct hva_dev *hva_dev; struct hva_dev *hva_dev;
...@@ -215,11 +272,27 @@ struct hva_ctx { ...@@ -215,11 +272,27 @@ struct hva_ctx {
u32 sys_errors; u32 sys_errors;
u32 encode_errors; u32 encode_errors;
u32 frame_errors; u32 frame_errors;
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
struct hva_ctx_dbg dbg;
#endif
}; };
#define HVA_FLAG_STREAMINFO 0x0001 #define HVA_FLAG_STREAMINFO 0x0001
#define HVA_FLAG_FRAMEINFO 0x0002 #define HVA_FLAG_FRAMEINFO 0x0002
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
/**
* struct hva_dev_dbg - device debug info
*
* @debugfs_entry: debugfs entry
* @last_ctx: debug information about last running instance context
*/
struct hva_dev_dbg {
struct dentry *debugfs_entry;
struct hva_ctx last_ctx;
};
#endif
#define HVA_MAX_INSTANCES 16 #define HVA_MAX_INSTANCES 16
#define HVA_MAX_ENCODERS 10 #define HVA_MAX_ENCODERS 10
#define HVA_MAX_FORMATS HVA_MAX_ENCODERS #define HVA_MAX_FORMATS HVA_MAX_ENCODERS
...@@ -258,6 +331,7 @@ struct hva_ctx { ...@@ -258,6 +331,7 @@ struct hva_ctx {
* @lmi_err_reg: local memory interface error register value * @lmi_err_reg: local memory interface error register value
* @emi_err_reg: external memory interface error register value * @emi_err_reg: external memory interface error register value
* @hec_mif_err_reg: HEC memory interface error register value * @hec_mif_err_reg: HEC memory interface error register value
* @dbg: device debug info
*/ */
struct hva_dev { struct hva_dev {
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
...@@ -292,6 +366,9 @@ struct hva_dev { ...@@ -292,6 +366,9 @@ struct hva_dev {
u32 lmi_err_reg; u32 lmi_err_reg;
u32 emi_err_reg; u32 emi_err_reg;
u32 hec_mif_err_reg; u32 hec_mif_err_reg;
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
struct hva_dev_dbg dbg;
#endif
}; };
/** /**
...@@ -320,4 +397,13 @@ struct hva_enc { ...@@ -320,4 +397,13 @@ struct hva_enc {
struct hva_stream *stream); struct hva_stream *stream);
}; };
#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
void hva_debugfs_create(struct hva_dev *hva);
void hva_debugfs_remove(struct hva_dev *hva);
void hva_dbg_ctx_create(struct hva_ctx *ctx);
void hva_dbg_ctx_remove(struct hva_ctx *ctx);
void hva_dbg_perf_begin(struct hva_ctx *ctx);
void hva_dbg_perf_end(struct hva_ctx *ctx, struct hva_stream *stream);
#endif
#endif /* HVA_H */ #endif /* HVA_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment