Skip to content

Commit a19d26e

Browse files
Jian Caotobetter
authored andcommitted
gdc: add trace_mode debug node for gdc timeout issue [1/2]
PD#GH-27 Problem: gdc timeout when gdc processing data Solution: add trace_mode debug node Verify: verified on G12B-W400 Change-Id: I85ee5a4203c9da1af755844125716a844da54ad3 Signed-off-by: Jian Cao <[email protected]>
1 parent e4f5038 commit a19d26e

File tree

1 file changed

+275
-4
lines changed

1 file changed

+275
-4
lines changed

drivers/amlogic/media/gdc/app/gdc_module.c

Lines changed: 275 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747

4848
unsigned int gdc_log_level;
4949
struct gdc_manager_s gdc_manager;
50+
static int trace_mode_enable;
51+
static char *config_out_file;
52+
static int config_out_path_defined;
53+
54+
#define WAIT_THRESHOLD 1000
55+
#define CONFIG_PATH_LENG 128
5056

5157
static const struct of_device_id gdc_dt_match[] = {
5258
{.compatible = "amlogic, g12b-gdc"},
@@ -352,7 +358,6 @@ static long meson_gdc_dma_map(struct gdc_dma_cfg *cfg)
352358
return ret;
353359
}
354360

355-
356361
static void meson_gdc_dma_unmap(struct gdc_dma_cfg *cfg)
357362
{
358363
int fd = -1;
@@ -746,6 +751,84 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh,
746751
return 0;
747752
}
748753

754+
u8 __iomem *map_virt_from_phys(phys_addr_t phys, unsigned long total_size)
755+
{
756+
u32 offset, npages;
757+
struct page **pages = NULL;
758+
pgprot_t pgprot;
759+
u8 __iomem *vaddr;
760+
int i;
761+
762+
npages = PAGE_ALIGN(total_size) / PAGE_SIZE;
763+
offset = phys & (~PAGE_MASK);
764+
if (offset)
765+
npages++;
766+
pages = vmalloc(sizeof(struct page *) * npages);
767+
if (!pages)
768+
return NULL;
769+
for (i = 0; i < npages; i++) {
770+
pages[i] = phys_to_page(phys);
771+
phys += PAGE_SIZE;
772+
}
773+
/*nocache*/
774+
pgprot = pgprot_noncached(PAGE_KERNEL);
775+
776+
vaddr = vmap(pages, npages, VM_MAP, pgprot);
777+
if (!vaddr) {
778+
pr_err("vmaped fail, size: %d\n",
779+
npages << PAGE_SHIFT);
780+
vfree(pages);
781+
return NULL;
782+
}
783+
vfree(pages);
784+
785+
return vaddr;
786+
}
787+
788+
void unmap_virt_from_phys(u8 __iomem *vaddr)
789+
{
790+
if (vaddr) {
791+
/* unmap prevois vaddr */
792+
vunmap(vaddr);
793+
vaddr = NULL;
794+
}
795+
}
796+
797+
int write_buf_to_file(char *path, char *buf, int size)
798+
{
799+
int ret = 0;
800+
struct file *fp = NULL;
801+
mm_segment_t old_fs;
802+
loff_t pos = 0;
803+
int w_size = 0;
804+
805+
if (!path || !config_out_path_defined) {
806+
gdc_log(LOG_ERR, "please define path first\n");
807+
return -1;
808+
}
809+
810+
/* change to KERNEL_DS address limit */
811+
old_fs = get_fs();
812+
set_fs(KERNEL_DS);
813+
814+
/* open file to write */
815+
fp = filp_open(path, O_WRONLY|O_CREAT, 0640);
816+
if (IS_ERR(fp)) {
817+
gdc_log(LOG_ERR, "open file error\n");
818+
ret = -1;
819+
}
820+
821+
/* Write buf to file */
822+
w_size = vfs_write(fp, buf, size, &pos);
823+
gdc_log(LOG_INFO, "write w_size = %u, size = %u\n", w_size, size);
824+
825+
vfs_fsync(fp, 0);
826+
filp_close(fp, NULL);
827+
set_fs(old_fs);
828+
829+
return w_size;
830+
}
831+
749832
static long meson_gdc_ioctl(struct file *file, unsigned int cmd,
750833
unsigned long arg)
751834
{
@@ -763,7 +846,12 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd,
763846
ion_phys_addr_t addr;
764847
int index, dma_fd;
765848
void __user *argp = (void __user *)arg;
849+
void __iomem *config_virt_addr;
850+
ktime_t start_time, stop_time, diff_time;
851+
int process_time = 0;
852+
int i = 0;
766853

854+
start_time.tv64 = 0;
767855
switch (cmd) {
768856
case GDC_PROCESS:
769857
ret = copy_from_user(&gs, argp, sizeof(gs));
@@ -815,16 +903,53 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd,
815903

816904
gdc_cmd->fh = fh;
817905
mutex_lock(&fh->gdev->d_mutext);
906+
907+
if (trace_mode_enable >= 1)
908+
start_time = ktime_get();
909+
818910
ret = gdc_run(gdc_cmd);
819911
if (ret < 0)
820912
gdc_log(LOG_ERR, "gdc process ret = %ld\n", ret);
821913

822914
ret = wait_for_completion_timeout(&fh->gdev->d_com,
823-
msecs_to_jiffies(40));
915+
msecs_to_jiffies(WAIT_THRESHOLD));
824916
if (ret == 0)
825917
gdc_log(LOG_ERR, "gdc timeout\n");
826918

919+
if (ret == 0) {
920+
gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n",
921+
gdc_status_read());
922+
923+
if (trace_mode_enable >= 2) {
924+
/* dump regs */
925+
for (i = 0; i <= 0xFF; i += 4)
926+
gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n",
927+
i, system_gdc_read_32(i));
928+
929+
/* dump config buffer */
930+
config_virt_addr =
931+
map_virt_from_phys(gc->config_addr,
932+
PAGE_ALIGN(gc->config_size * 4));
933+
ret = write_buf_to_file(config_out_file,
934+
config_virt_addr,
935+
(gc->config_size * 4));
936+
if (ret <= 0)
937+
gdc_log(LOG_ERR,
938+
"Failed to read_file_to_buf\n");
939+
unmap_virt_from_phys(config_virt_addr);
940+
}
941+
}
942+
827943
gdc_stop(gdc_cmd);
944+
945+
if (trace_mode_enable >= 1) {
946+
stop_time = ktime_get();
947+
diff_time = ktime_sub(stop_time, start_time);
948+
process_time = ktime_to_ms(diff_time);
949+
if (process_time > 50)
950+
gdc_log(LOG_ERR, "gdc process time = %d\n",
951+
process_time);
952+
}
828953
mutex_unlock(&fh->gdev->d_mutext);
829954
break;
830955
case GDC_RUN:
@@ -854,16 +979,52 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd,
854979
fh->i_paddr, fh->i_len);
855980
meson_gdc_dma_flush(&fh->gdev->pdev->dev,
856981
fh->c_paddr, fh->c_len);
982+
983+
if (trace_mode_enable >= 1)
984+
start_time = ktime_get();
985+
857986
ret = gdc_run(gdc_cmd);
858987
if (ret < 0)
859988
gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret);
860989

861990
ret = wait_for_completion_timeout(&fh->gdev->d_com,
862-
msecs_to_jiffies(40));
991+
msecs_to_jiffies(WAIT_THRESHOLD));
863992
if (ret == 0)
864993
gdc_log(LOG_ERR, "gdc timeout\n");
865994

995+
if (ret == 0) {
996+
gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n",
997+
gdc_status_read());
998+
999+
if (trace_mode_enable >= 2) {
1000+
/* dump regs */
1001+
for (i = 0; i <= 0xFF; i += 4)
1002+
gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n",
1003+
i, system_gdc_read_32(i));
1004+
1005+
/* dump config buffer */
1006+
config_virt_addr =
1007+
map_virt_from_phys(gc->config_addr,
1008+
PAGE_ALIGN(gc->config_size * 4));
1009+
ret = write_buf_to_file(config_out_file,
1010+
config_virt_addr,
1011+
(gc->config_size * 4));
1012+
if (ret <= 0)
1013+
gdc_log(LOG_ERR,
1014+
"Failed to read_file_to_buf\n");
1015+
unmap_virt_from_phys(config_virt_addr);
1016+
}
1017+
}
1018+
8661019
gdc_stop(gdc_cmd);
1020+
if (trace_mode_enable >= 1) {
1021+
stop_time = ktime_get();
1022+
diff_time = ktime_sub(stop_time, start_time);
1023+
process_time = ktime_to_ms(diff_time);
1024+
if (process_time > 50)
1025+
gdc_log(LOG_ERR, "gdc process time = %d\n",
1026+
process_time);
1027+
}
8671028
meson_gdc_cache_flush(&fh->gdev->pdev->dev,
8681029
fh->o_paddr, fh->o_len);
8691030
mutex_unlock(&fh->gdev->d_mutext);
@@ -893,16 +1054,54 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd,
8931054
}
8941055
meson_gdc_dma_flush(&fh->gdev->pdev->dev,
8951056
fh->c_paddr, fh->c_len);
1057+
1058+
1059+
if (trace_mode_enable >= 1)
1060+
start_time = ktime_get();
1061+
8961062
ret = gdc_run(gdc_cmd);
8971063
if (ret < 0)
8981064
gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret);
8991065

9001066
ret = wait_for_completion_timeout(&fh->gdev->d_com,
901-
msecs_to_jiffies(40));
1067+
msecs_to_jiffies(WAIT_THRESHOLD));
9021068
if (ret == 0)
9031069
gdc_log(LOG_ERR, "gdc timeout\n");
9041070

1071+
if (ret == 0) {
1072+
gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n",
1073+
gdc_status_read());
1074+
1075+
if (trace_mode_enable >= 2) {
1076+
/* dump regs */
1077+
for (i = 0; i <= 0xFF; i += 4)
1078+
gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n",
1079+
i, system_gdc_read_32(i));
1080+
1081+
/* dump config buffer */
1082+
config_virt_addr =
1083+
map_virt_from_phys(gc->config_addr,
1084+
PAGE_ALIGN(gc->config_size * 4));
1085+
ret = write_buf_to_file(config_out_file,
1086+
config_virt_addr,
1087+
(gc->config_size * 4));
1088+
if (ret <= 0)
1089+
gdc_log(LOG_ERR,
1090+
"Failed to read_file_to_buf\n");
1091+
unmap_virt_from_phys(config_virt_addr);
1092+
}
1093+
}
1094+
9051095
gdc_stop(gdc_cmd);
1096+
1097+
if (trace_mode_enable >= 1) {
1098+
stop_time = ktime_get();
1099+
diff_time = ktime_sub(stop_time, start_time);
1100+
process_time = ktime_to_ms(diff_time);
1101+
if (process_time > 50)
1102+
gdc_log(LOG_ERR, "gdc process time = %d\n",
1103+
process_time);
1104+
}
9061105
meson_gdc_cache_flush(&fh->gdev->pdev->dev,
9071106
fh->o_paddr, fh->o_len);
9081107
meson_gdc_deinit_dma_addr(fh);
@@ -1122,6 +1321,60 @@ static ssize_t loglevel_store(struct device *dev,
11221321

11231322
static DEVICE_ATTR(loglevel, 0664, loglevel_show, loglevel_store);
11241323

1324+
static ssize_t trace_mode_show(struct device *dev,
1325+
struct device_attribute *attr, char *buf)
1326+
{
1327+
ssize_t len = 0;
1328+
1329+
len += sprintf(buf+len, "trace_mode_enable: %d\n",
1330+
trace_mode_enable);
1331+
return len;
1332+
}
1333+
1334+
static ssize_t trace_mode_store(struct device *dev,
1335+
struct device_attribute *attr, const char *buf, size_t len)
1336+
{
1337+
int res = 0;
1338+
int ret = 0;
1339+
1340+
ret = kstrtoint(buf, 0, &res);
1341+
pr_info("trace_mode: %d->%d\n", trace_mode_enable, res);
1342+
trace_mode_enable = res;
1343+
1344+
return len;
1345+
}
1346+
static DEVICE_ATTR(trace_mode, 0664, trace_mode_show, trace_mode_store);
1347+
1348+
static ssize_t config_out_path_show(struct device *dev,
1349+
struct device_attribute *attr, char *buf)
1350+
{
1351+
ssize_t len = 0;
1352+
1353+
if (config_out_path_defined)
1354+
len += sprintf(buf+len, "config out path: %s\n",
1355+
config_out_file);
1356+
else
1357+
len += sprintf(buf+len, "config out path is not set\n");
1358+
1359+
return len;
1360+
}
1361+
1362+
static ssize_t config_out_path_store(struct device *dev,
1363+
struct device_attribute *attr, const char *buf, size_t len)
1364+
{
1365+
if (strlen(buf) >= sizeof(config_out_file)) {
1366+
pr_info("err: path too long\n");
1367+
} else {
1368+
strncpy(config_out_file, buf, CONFIG_PATH_LENG - 1);
1369+
config_out_path_defined = 1;
1370+
pr_info("set config out path: %s\n", config_out_file);
1371+
}
1372+
1373+
return len;
1374+
}
1375+
static DEVICE_ATTR(config_out_path, 0664, config_out_path_show,
1376+
config_out_path_store);
1377+
11251378
irqreturn_t gdc_interrupt_handler(int irq, void *param)
11261379
{
11271380
struct meson_gdc_dev_t *gdc_dev = param;
@@ -1155,6 +1408,13 @@ static int gdc_platform_probe(struct platform_device *pdev)
11551408

11561409
of_reserved_mem_device_init(&(pdev->dev));
11571410

1411+
/* alloc mem to store config out path*/
1412+
config_out_file = kzalloc(CONFIG_PATH_LENG, GFP_KERNEL);
1413+
if (config_out_file == NULL) {
1414+
gdc_log(LOG_ERR, "config out alloc failed\n");
1415+
return -ENOMEM;
1416+
}
1417+
11581418
gdc_dev = devm_kzalloc(&pdev->dev, sizeof(*gdc_dev),
11591419
GFP_KERNEL);
11601420

@@ -1215,6 +1475,10 @@ static int gdc_platform_probe(struct platform_device *pdev)
12151475
&dev_attr_firmware1);
12161476
device_create_file(gdc_dev->misc_dev.this_device,
12171477
&dev_attr_loglevel);
1478+
device_create_file(gdc_dev->misc_dev.this_device,
1479+
&dev_attr_trace_mode);
1480+
device_create_file(gdc_dev->misc_dev.this_device,
1481+
&dev_attr_config_out_path);
12181482

12191483
platform_set_drvdata(pdev, gdc_dev);
12201484
return rc;
@@ -1229,10 +1493,17 @@ static int gdc_platform_remove(struct platform_device *pdev)
12291493
&dev_attr_firmware1);
12301494
device_remove_file(meson_gdc_dev.this_device,
12311495
&dev_attr_loglevel);
1496+
device_remove_file(meson_gdc_dev.this_device,
1497+
&dev_attr_trace_mode);
1498+
device_remove_file(meson_gdc_dev.this_device,
1499+
&dev_attr_config_out_path);
12321500

12331501
gdc_dma_buffer_destroy(gdc_manager.buffer);
12341502
gdc_manager.gdc_dev = NULL;
12351503

1504+
kfree(config_out_file);
1505+
config_out_file = NULL;
1506+
12361507
misc_deregister(&meson_gdc_dev);
12371508
return 0;
12381509
}

0 commit comments

Comments
 (0)