From a7fac880e0124d6045529469e66c0f194e97e82b Mon Sep 17 00:00:00 2001 From: Han Gao Date: Tue, 7 May 2024 11:16:20 +0000 Subject: [PATCH] venc: 8000e: sync sdk 1.5.4 Signed-off-by: Han Gao --- .../linux/kernel_module/Makefile | 7 + .../linux/kernel_module/hantro_mmu.c | 2 +- .../linux/kernel_module/vc8000_devfreq.h | 7 +- .../linux/kernel_module/vc8000_driver.h | 20 +- .../linux/kernel_module/vc8000_vcmd_driver.c | 182 +++++++++++++++++- .../linux/kernel_module/venc_trace_point.h | 36 ++++ 6 files changed, 244 insertions(+), 10 deletions(-) create mode 100644 drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/venc_trace_point.h diff --git a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/Makefile b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/Makefile index d7e638ca2..0209f8bfb 100755 --- a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/Makefile +++ b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/Makefile @@ -109,6 +109,12 @@ endif CC += -I$(obj) EXTRA_CFLAGS += -g +ifeq ($(CONFIG_ANDROID), y) +ccflags-y += -DTRACE_INCLUDE_PATH=$(src) +else +ccflags-y += -DTRACE_INCLUDE_PATH=$(PWD) +endif + # Print debugging messages from the device #EXTRA_CFLAGS += -DHANTRO_DRIVER_DEBUG @@ -160,6 +166,7 @@ ifeq ($(inst-m),) inst-m := $(obj-m) endif + # locales seem to cause trouble sometimes. LC_ALL = POSIX export LC_ALL diff --git a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/hantro_mmu.c b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/hantro_mmu.c index 00dc2795b..e5b561dfc 100755 --- a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/hantro_mmu.c +++ b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/hantro_mmu.c @@ -166,7 +166,7 @@ MODULE_LICENSE("GPL"); # define MMUDEBUG(fmt, args...) fprintf(stderr, fmt, ## args) # endif #else -# define MMUDEBUG(fmt, args...) +# define MMUDEBUG(fmt, args...) pr_debug("hantrommu: " fmt, ## args) #endif #define MMU_ON_ERROR(func) \ diff --git a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_devfreq.h b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_devfreq.h index bc1ec8660..fc5b11f1c 100644 --- a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_devfreq.h +++ b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_devfreq.h @@ -7,18 +7,23 @@ struct devfreq; struct opp_table; struct encoder_devfreq { + int busy_count; struct devfreq *df; struct opp_table *clkname_opp_table; bool opp_of_table_added; bool update_freq_flag; unsigned long next_target_freq; unsigned long cur_devfreq; + unsigned long max_freq; wait_queue_head_t target_freq_wait_queue; ktime_t busy_time; ktime_t idle_time; ktime_t time_last_update; - int busy_count; + ktime_t based_maxfreq_busy_time; + ktime_t based_maxfreq_last_busy_t; + int busy_record_count; + /* * Protect busy_time, idle_time, time_last_update and busy_count * because these can be updated concurrently, for example by the GP diff --git a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_driver.h b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_driver.h index ff818889a..55055ac39 100644 --- a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_driver.h +++ b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_driver.h @@ -98,7 +98,7 @@ typedef size_t ptr_t; # define PDEBUG(fmt, args...) printf(__FILE__ ":%d: " fmt, __LINE__ , ## args) # endif #else -# define PDEBUG(fmt, args...) /* not debugging: nothing */ +# define PDEBUG(fmt, args...) pr_debug("vc8000: " fmt, ## args) #endif #define ENC_HW_ID1 0x48320100 @@ -324,6 +324,24 @@ typedef struct SUBSYS_CORE_INFO core_info; }SUBSYS_DATA; +struct vcmd_profile { + int dev_loading_percent; + int dev_loading_max_percent; + + int last_hw_proc_us; + int avg_hw_proc_us; + int proced_count; + int cur_submit_vcmd_id; + int cur_complete_vcmd_id; + int vcmd_num_share_irq; + + //error statistics + u32 vcmd_abort_cnt; + u32 vcmd_buserr_cnt; + u32 vcmd_timeout_cnt; + u32 vcmd_cmderr_cnt; +}; +extern struct vcmd_profile venc_vcmd_profile; #ifdef __cplusplus } #endif diff --git a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_vcmd_driver.c b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_vcmd_driver.c index a620d21c1..582a05a65 100644 --- a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_vcmd_driver.c +++ b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_vcmd_driver.c @@ -110,6 +110,9 @@ #include "vcmdswhwregisters.h" #include "bidirect_list.h" #include "vc8000_driver.h" +#undef linux +#define CREATE_TRACE_POINTS +#include "venc_trace_point.h" /*------------------------------------------------------------------------ *****************************VCMD CONFIGURATION BY CUSTOMER******************************** @@ -1715,7 +1718,8 @@ static long link_and_run_cmdbuf(struct file *filp,struct exchange_parameter* inp if (down_interruptible(&vcmd_reserve_cmdbuf_sem[cmdbuf_obj->module_type])) return -ERESTARTSYS; - + + venc_vcmd_profile.cur_submit_vcmd_id = input_para->cmdbuf_id; encoder_devfreq_record_busy( encoder_get_devfreq_priv_data() ); return_value=select_vcmd(new_cmdbuf_node); @@ -3815,12 +3819,24 @@ static int encoder_resume(struct device *dev) static void encoder_devfreq_update_utilization(struct encoder_devfreq *devfreq) { ktime_t now, last; - + ktime_t busy; now = ktime_get(); last = devfreq->time_last_update; - if (devfreq->busy_count > 0) - devfreq->busy_time += ktime_sub(now, last); + if (devfreq->busy_count > 0) { + busy = ktime_sub(now, last); + devfreq->busy_time += busy; + #ifndef CONFIG_PM_DEVFREQ + devfreq->based_maxfreq_last_busy_t = busy; + #else + if(devfreq->max_freq) + devfreq->based_maxfreq_last_busy_t = busy/(devfreq->max_freq/devfreq->cur_devfreq); + else + devfreq->based_maxfreq_last_busy_t = busy; + #endif + devfreq->based_maxfreq_busy_time += devfreq->based_maxfreq_last_busy_t; + devfreq->busy_record_count++; + } else { if(devfreq->busy_time > 0) //if first time in not recorded busy time,ignore idle time. @@ -3836,12 +3852,20 @@ static void encoder_devfreq_reset(struct encoder_devfreq *devfreq) devfreq->time_last_update = ktime_get(); } +void encoder_devfreq_reset_profile_record(struct encoder_devfreq *devfreq) +{ + devfreq->based_maxfreq_busy_time = 0; + devfreq->busy_record_count = 0; +} + void encoder_devfreq_record_busy(struct encoder_devfreq *devfreq) { unsigned long irqflags; int busy_count; if (!devfreq) return; + //when devfreq not enabled,need into record time also. + encoder_dev_clk_lock(); spin_lock_irqsave(&devfreq->lock, irqflags); busy_count = devfreq->busy_count; @@ -3872,6 +3896,7 @@ void encoder_devfreq_record_idle(struct encoder_devfreq *devfreq) if (!devfreq) return; + spin_lock_irqsave(&devfreq->lock, irqflags); //pr_info("record_idle:busy_count = %d\n",devfreq->busy_count); if(devfreq->busy_count > 1) @@ -4038,8 +4063,9 @@ static int encoder_devfreq_get_cur_freq( struct device *dev, unsigned long *freq *freq = devfreq->cur_devfreq; return 0; } - +#ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND struct devfreq_simple_ondemand_data encoder_gov_data; +#endif static struct devfreq_dev_profile encoder_devfreq_gov_data = { @@ -4081,6 +4107,7 @@ int encoder_devfreq_init(struct device *dev) init_waitqueue_head(&devfreq->target_freq_wait_queue); mutex_init(&devfreq->clk_mutex); +#ifdef CONFIG_PM_DEVFREQ opp_table = dev_pm_opp_set_clkname(dev,"cclk"); if(IS_ERR(opp_table)) { pr_err("enc set cclk failed\n"); @@ -4102,6 +4129,7 @@ int encoder_devfreq_init(struct device *dev) encoder_devfreq_gov_data.initial_freq = devfreq->cur_devfreq; +#ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND encoder_gov_data.upthreshold = 80; encoder_gov_data.downdifferential = 10; @@ -4116,8 +4144,17 @@ int encoder_devfreq_init(struct device *dev) ret = PTR_ERR(df); goto err_fini; } + unsigned long *freq_table = df->profile->freq_table; + if (freq_table[0] < freq_table[df->profile->max_state - 1]) { + devfreq->max_freq = freq_table[df->profile->max_state - 1]; + } else { + devfreq->max_freq = freq_table[0]; + } + pr_info("device max freq %ld\n",devfreq->max_freq); df->suspend_freq = 0; // not set freq when suspend,not suitable for async set rate devfreq->df = df; +#endif +#endif return 0; err_fini: @@ -4129,7 +4166,119 @@ err_fini: ******************************* VPU Devfreq support END ************************ \******************************************************************************/ -int hantroenc_vcmd_probe(struct platform_device *pdev) +void venc_vcmd_profile_update(struct work_struct *work); +static DECLARE_DELAYED_WORK(venc_cmd_profile_work,venc_vcmd_profile_update); +static ktime_t last_update; +static long update_period_ms = 0; + +struct vcmd_profile venc_vcmd_profile; + +void venc_vcmd_profile_update(struct work_struct *work) +{ + //update busy time + ktime_t now,during; + struct encoder_devfreq *devfreq; + devfreq = encoder_get_devfreq_priv_data(); + now = ktime_get(); + during = ktime_sub(now,last_update); + last_update = now; + venc_vcmd_profile.dev_loading_percent = ktime_to_us(devfreq->based_maxfreq_busy_time) * 100/ktime_to_us(during); + if(venc_vcmd_profile.dev_loading_percent > venc_vcmd_profile.dev_loading_max_percent) + venc_vcmd_profile.dev_loading_max_percent = venc_vcmd_profile.dev_loading_percent; + pr_debug("based_maxfreq_busy_time %lldms,during period %lld ms",ktime_to_us(devfreq->based_maxfreq_busy_time)/1000,ktime_to_ms(during)); + + if(devfreq->busy_record_count > 0) + venc_vcmd_profile.avg_hw_proc_us = ktime_to_us(devfreq->based_maxfreq_busy_time)/devfreq->busy_record_count; + else + venc_vcmd_profile.avg_hw_proc_us = 0; + + venc_vcmd_profile.last_hw_proc_us = ktime_to_us(devfreq->based_maxfreq_last_busy_t); + venc_vcmd_profile.proced_count = devfreq->busy_record_count; + encoder_devfreq_reset_profile_record(devfreq); + if(update_period_ms > 0) + schedule_delayed_work(&venc_cmd_profile_work, msecs_to_jiffies(update_period_ms)); +} + +static ssize_t log_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + ssize_t len = 0; + + const char *module_version = "1.0.0"; + int dev_id = 0; + + + len += scnprintf(buf + len, PAGE_SIZE - len, + "[VENC] Version: %s \n" + "----------------------------------------MODULE PARAM-----------------------------\n" + "updatePeriod_ms\n" + " %d\n" + "----------------------------------------MODULE STATUS------------------------------\n" + "DevId DevLoading_%% DevLoadingMax_%%\n" + " %d %d %d\n" + + " avg_hw_proc_us last_hw_proc_us proced_count\n" + " %d %d %d \n" + "cur_submit_vcmd cur_complete_vcmd vcmd_num_share_irq\n" + " %d %d %d \n" + "----------------------------------------EXCEPTION INFO-----------------------------------------\n" + "BusErr Abort Timeout CmdErr\n" + " %d %d %d %d \n", + module_version, update_period_ms, + dev_id, venc_vcmd_profile.dev_loading_percent, venc_vcmd_profile.dev_loading_max_percent, + + venc_vcmd_profile.avg_hw_proc_us, venc_vcmd_profile.last_hw_proc_us,venc_vcmd_profile.proced_count, + venc_vcmd_profile.cur_submit_vcmd_id,venc_vcmd_profile.cur_complete_vcmd_id,venc_vcmd_profile.vcmd_num_share_irq, + venc_vcmd_profile.vcmd_buserr_cnt, venc_vcmd_profile.vcmd_abort_cnt, venc_vcmd_profile.vcmd_timeout_cnt, venc_vcmd_profile.vcmd_cmderr_cnt); + + + return len; +} + +static ssize_t log_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + /******************clear *********************/ + venc_vcmd_profile.vcmd_buserr_cnt = 0; + venc_vcmd_profile.vcmd_abort_cnt = 0; + venc_vcmd_profile.vcmd_timeout_cnt = 0; + venc_vcmd_profile.vcmd_cmderr_cnt = 0; + + venc_vcmd_profile.dev_loading_max_percent = 0; + venc_vcmd_profile.last_hw_proc_us = 0; + return count; +} + +/******************updatePeriod ************************************/ +static ssize_t updatePeriod_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf,"%u\n",update_period_ms); +} + +static ssize_t updatePeriod_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + char *start = (char *)buf; + long old_period = update_period_ms; + update_period_ms = simple_strtoul(start, &start, 0); + if(old_period == 0 && update_period_ms) + schedule_delayed_work(&venc_cmd_profile_work,msecs_to_jiffies(update_period_ms)); + return count; +} +/******************define log *************************************/ +static struct kobj_attribute log_attr = __ATTR(log, 0664, log_show, log_store); +/******************define updatePeriod_ms*************************************/ +static struct kobj_attribute updatePeriod_attr = __ATTR(updatePeriod_ms, 0664, updatePeriod_show, updatePeriod_store); + +static struct attribute *attrs[] = { + &log_attr.attr, + &updatePeriod_attr.attr, + NULL, // must be NULL +}; + +static struct attribute_group venc_dev_attr_group = { + .name = "info", // dir name + .attrs = attrs, +}; + +int __init hantroenc_vcmd_probe(struct platform_device *pdev) { int i,k; int result; @@ -4372,6 +4521,10 @@ int hantroenc_vcmd_probe(struct platform_device *pdev) } else { pr_info("venc devfreq init ok\n"); } + result = sysfs_create_group(&pdev->dev.kobj, &venc_dev_attr_group); + if(result) + pr_warn("venc create sysfs failed\n"); + pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); @@ -4405,6 +4558,7 @@ static int hantroenc_vcmd_remove(struct platform_device *pdev) debugfs_remove_recursive(root_debugfs_dir); root_debugfs_dir = NULL; } + cancel_delayed_work_sync(&venc_cmd_profile_work); pm_runtime_resume_and_get(&pdev->dev); for(i=0;idev.kobj,&venc_dev_attr_group); #ifndef DYNAMIC_MALLOC_VCMDNODE if (g_cmdbuf_obj_pool) { vfree(g_cmdbuf_obj_pool); @@ -4649,6 +4804,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) { //if error,read from register directly. cmdbuf_id = vcmd_get_register_value((const void *)dev->hwregs,dev->reg_mirror,HWIF_VCMD_CMDBUF_EXECUTING_ID); + venc_vcmd_profile.cur_complete_vcmd_id = cmdbuf_id; if(cmdbuf_id>=TOTAL_DISCRETE_CMDBUF_NUM) { pr_err("hantrovcmd_isr error cmdbuf_id greater than the ceiling !!\n"); @@ -4673,6 +4829,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) #endif cmdbuf_id = *(dev->vcmd_reg_mem_virtualAddress+EXECUTING_CMDBUF_ID_ADDR); + venc_vcmd_profile.cur_complete_vcmd_id = cmdbuf_id; pr_debug("hantrovcmd_isr: cmdbuf_id %d from virtual!!\n", cmdbuf_id); if(cmdbuf_id>=TOTAL_DISCRETE_CMDBUF_NUM) { @@ -4707,6 +4864,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) vcmd_start(dev,base_cmdbuf_node); } handled++; + trace_venc_interrupt(0xffffffff,irq_status,0); spin_unlock_irqrestore(dev->spinlock, flags); return IRQ_HANDLED; } @@ -4715,6 +4873,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) //abort error,don't need to reset new_cmdbuf_node = dev->list_manager.head; dev->working_state = WORKING_STATE_IDLE; + venc_vcmd_profile.vcmd_abort_cnt++; if(dev->hw_version_id > HW_ID_1_0_C ) { new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; @@ -4772,6 +4931,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) vcmd_start(dev,base_cmdbuf_node); } } + trace_venc_interrupt(cmdbuf_id,irq_status,cmdbuf_processed_num); spin_unlock_irqrestore(dev->spinlock, flags); if(cmdbuf_processed_num) wake_up_all(dev->wait_queue); @@ -4785,6 +4945,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) //bus error, don't need to reset where to record status? new_cmdbuf_node = dev->list_manager.head; dev->working_state = WORKING_STATE_IDLE; + venc_vcmd_profile.vcmd_buserr_cnt++; if(dev->hw_version_id > HW_ID_1_0_C ) { new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; @@ -4844,6 +5005,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) //restart new command vcmd_start(dev,base_cmdbuf_node); } + trace_venc_interrupt(cmdbuf_id,irq_status,cmdbuf_processed_num); spin_unlock_irqrestore(dev->spinlock, flags); if(cmdbuf_processed_num) wake_up_all(dev->wait_queue); @@ -4854,6 +5016,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) { //time out,need to reset new_cmdbuf_node = dev->list_manager.head; + venc_vcmd_profile.vcmd_timeout_cnt++; dev->working_state = WORKING_STATE_IDLE; if(dev->hw_version_id > HW_ID_1_0_C ) { @@ -4910,6 +5073,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) //restart new command vcmd_start(dev,base_cmdbuf_node); } + trace_venc_interrupt(cmdbuf_id,irq_status,cmdbuf_processed_num); spin_unlock_irqrestore(dev->spinlock, flags); if(cmdbuf_processed_num) wake_up_all(dev->wait_queue); @@ -4921,6 +5085,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) //command error,don't need to reset new_cmdbuf_node = dev->list_manager.head; dev->working_state = WORKING_STATE_IDLE; + venc_vcmd_profile.vcmd_cmderr_cnt++; if(dev->hw_version_id > HW_ID_1_0_C ) { new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; @@ -4980,6 +5145,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) //restart new command vcmd_start(dev,base_cmdbuf_node); } + trace_venc_interrupt(cmdbuf_id,irq_status,cmdbuf_processed_num); spin_unlock_irqrestore(dev->spinlock, flags); if(cmdbuf_processed_num) wake_up_all(dev->wait_queue); @@ -5044,6 +5210,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) //restart new command vcmd_start(dev,base_cmdbuf_node); } + trace_venc_interrupt(cmdbuf_id,irq_status,cmdbuf_processed_num); spin_unlock_irqrestore(dev->spinlock, flags); if(cmdbuf_processed_num) wake_up_all(dev->wait_queue); @@ -5089,7 +5256,8 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) } handled++; } - + venc_vcmd_profile.vcmd_num_share_irq = cmdbuf_processed_num; + trace_venc_interrupt(cmdbuf_id,irq_status,cmdbuf_processed_num); spin_unlock_irqrestore(dev->spinlock, flags); if(cmdbuf_processed_num) wake_up_all(dev->wait_queue); diff --git a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/venc_trace_point.h b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/venc_trace_point.h new file mode 100644 index 000000000..df75dff7b --- /dev/null +++ b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/venc_trace_point.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM venc_trace_point + +#if !defined(_TRACE_VENC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_VENC_H + +#include +#include +#include + +TRACE_EVENT(venc_interrupt, + + TP_PROTO(unsigned int complete_cmd, unsigned int irq_status, unsigned int processed_vcmd_num), + + TP_ARGS(complete_cmd, irq_status,processed_vcmd_num), + + TP_STRUCT__entry( + __field( unsigned int, complete_cmd ) + __field( unsigned int, irq_status) + __field( unsigned int, processed_vcmd_num) + ), + + TP_fast_assign( + __entry->complete_cmd = complete_cmd; + __entry->irq_status = irq_status; + __entry->processed_vcmd_num = processed_vcmd_num; + ), + + TP_printk("venc irq type complete_cmd %u irq status =%x processed_vcmd_num %d ", __entry->complete_cmd, __entry->irq_status,__entry->processed_vcmd_num) +); + +#endif /* _TRACE_VENC_H */ + +/* This part must be outside protection */ +#include \ No newline at end of file