4747
4848unsigned int gdc_log_level ;
4949struct 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
5157static 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-
356361static 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+
749832static 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
11231322static 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+
11251378irqreturn_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