55#include <linux/acpi.h>
66#include <linux/bitfield.h>
77#include <linux/bitops.h>
8+ #include <linux/debugfs.h>
89#include <linux/interrupt.h>
910#include <linux/io.h>
1011#include <linux/io-64-nonatomic-lo-hi.h>
@@ -287,6 +288,7 @@ struct arm_cmn {
287288 struct hlist_node cpuhp_node ;
288289
289290 struct pmu pmu ;
291+ struct dentry * debug ;
290292};
291293
292294#define to_cmn (p ) container_of(p, struct arm_cmn, pmu)
@@ -351,6 +353,140 @@ static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
351353 return NULL ;
352354}
353355
356+ struct dentry * arm_cmn_debugfs ;
357+
358+ #ifdef CONFIG_DEBUG_FS
359+ static const char * arm_cmn_device_type (u8 type )
360+ {
361+ switch (type ) {
362+ case 0x01 : return " RN-I |" ;
363+ case 0x02 : return " RN-D |" ;
364+ case 0x04 : return " RN-F_B |" ;
365+ case 0x05 : return "RN-F_B_E|" ;
366+ case 0x06 : return " RN-F_A |" ;
367+ case 0x07 : return "RN-F_A_E|" ;
368+ case 0x08 : return " HN-T |" ;
369+ case 0x09 : return " HN-I |" ;
370+ case 0x0a : return " HN-D |" ;
371+ case 0x0c : return " SN-F |" ;
372+ case 0x0d : return " SBSX |" ;
373+ case 0x0e : return " HN-F |" ;
374+ case 0x0f : return " SN-F_E |" ;
375+ case 0x10 : return " SN-F_D |" ;
376+ case 0x11 : return " CXHA |" ;
377+ case 0x12 : return " CXRA |" ;
378+ case 0x13 : return " CXRH |" ;
379+ case 0x14 : return " RN-F_D |" ;
380+ case 0x15 : return "RN-F_D_E|" ;
381+ case 0x16 : return " RN-F_C |" ;
382+ case 0x17 : return "RN-F_C_E|" ;
383+ case 0x1c : return " MTSX |" ;
384+ default : return " |" ;
385+ }
386+ }
387+
388+ static void arm_cmn_show_logid (struct seq_file * s , int x , int y , int p , int d )
389+ {
390+ struct arm_cmn * cmn = s -> private ;
391+ struct arm_cmn_node * dn ;
392+
393+ for (dn = cmn -> dns ; dn -> type ; dn ++ ) {
394+ struct arm_cmn_nodeid nid = arm_cmn_nid (cmn , dn -> id );
395+
396+ if (dn -> type == CMN_TYPE_XP )
397+ continue ;
398+ /* Ignore the extra components that will overlap on some ports */
399+ if (dn -> type < CMN_TYPE_HNI )
400+ continue ;
401+
402+ if (nid .x != x || nid .y != y || nid .port != p || nid .dev != d )
403+ continue ;
404+
405+ seq_printf (s , " #%-2d |" , dn -> logid );
406+ return ;
407+ }
408+ seq_puts (s , " |" );
409+ }
410+
411+ static int arm_cmn_map_show (struct seq_file * s , void * data )
412+ {
413+ struct arm_cmn * cmn = s -> private ;
414+ int x , y , p , pmax = fls (cmn -> ports_used );
415+
416+ seq_puts (s , " X" );
417+ for (x = 0 ; x < cmn -> mesh_x ; x ++ )
418+ seq_printf (s , " %d " , x );
419+ seq_puts (s , "\nY P D+" );
420+ y = cmn -> mesh_y ;
421+ while (y -- ) {
422+ int xp_base = cmn -> mesh_x * y ;
423+ u8 port [6 ][CMN_MAX_DIMENSION ];
424+
425+ for (x = 0 ; x < cmn -> mesh_x ; x ++ )
426+ seq_puts (s , "--------+" );
427+
428+ seq_printf (s , "\n%d |" , y );
429+ for (x = 0 ; x < cmn -> mesh_x ; x ++ ) {
430+ struct arm_cmn_node * xp = cmn -> xps + xp_base + x ;
431+ void __iomem * base = xp -> pmu_base - CMN_PMU_OFFSET ;
432+
433+ port [0 ][x ] = readl_relaxed (base + CMN_MXP__CONNECT_INFO_P0 );
434+ port [1 ][x ] = readl_relaxed (base + CMN_MXP__CONNECT_INFO_P1 );
435+ port [2 ][x ] = readl_relaxed (base + CMN_MXP__CONNECT_INFO_P2 );
436+ port [3 ][x ] = readl_relaxed (base + CMN_MXP__CONNECT_INFO_P3 );
437+ port [4 ][x ] = readl_relaxed (base + CMN_MXP__CONNECT_INFO_P4 );
438+ port [5 ][x ] = readl_relaxed (base + CMN_MXP__CONNECT_INFO_P5 );
439+ seq_printf (s , " XP #%-2d |" , xp_base + x );
440+ }
441+
442+ seq_puts (s , "\n |" );
443+ for (x = 0 ; x < cmn -> mesh_x ; x ++ ) {
444+ u8 dtc = cmn -> xps [xp_base + x ].dtc ;
445+
446+ if (dtc & (dtc - 1 ))
447+ seq_puts (s , " DTC ?? |" );
448+ else
449+ seq_printf (s , " DTC %ld |" , __ffs (dtc ));
450+ }
451+ seq_puts (s , "\n |" );
452+ for (x = 0 ; x < cmn -> mesh_x ; x ++ )
453+ seq_puts (s , "........|" );
454+
455+ for (p = 0 ; p < pmax ; p ++ ) {
456+ seq_printf (s , "\n %d |" , p );
457+ for (x = 0 ; x < cmn -> mesh_x ; x ++ )
458+ seq_puts (s , arm_cmn_device_type (port [p ][x ]));
459+ seq_puts (s , "\n 0|" );
460+ for (x = 0 ; x < cmn -> mesh_x ; x ++ )
461+ arm_cmn_show_logid (s , x , y , p , 0 );
462+ seq_puts (s , "\n 1|" );
463+ for (x = 0 ; x < cmn -> mesh_x ; x ++ )
464+ arm_cmn_show_logid (s , x , y , p , 1 );
465+ }
466+ seq_puts (s , "\n-----+" );
467+ }
468+ for (x = 0 ; x < cmn -> mesh_x ; x ++ )
469+ seq_puts (s , "--------+" );
470+ seq_puts (s , "\n" );
471+ return 0 ;
472+ }
473+ DEFINE_SHOW_ATTRIBUTE (arm_cmn_map );
474+
475+ static void arm_cmn_debugfs_init (struct arm_cmn * cmn , int id )
476+ {
477+ const char * name = "map" ;
478+
479+ if (id > 0 )
480+ name = devm_kasprintf (cmn -> dev , GFP_KERNEL , "map_%d" , id );
481+ if (!name )
482+ return ;
483+
484+ cmn -> debug = debugfs_create_file (name , 0444 , arm_cmn_debugfs , cmn , & arm_cmn_map_fops );
485+ }
486+ #else
487+ static void arm_cmn_debugfs_init (struct arm_cmn * cmn , int id ) {}
488+ #endif
489+
354490struct arm_cmn_hw_event {
355491 struct arm_cmn_node * dn ;
356492 u64 dtm_idx [2 ];
@@ -1738,7 +1874,7 @@ static int arm_cmn_probe(struct platform_device *pdev)
17381874 struct arm_cmn * cmn ;
17391875 const char * name ;
17401876 static atomic_t id ;
1741- int err , rootnode ;
1877+ int err , rootnode , this_id ;
17421878
17431879 cmn = devm_kzalloc (& pdev -> dev , sizeof (* cmn ), GFP_KERNEL );
17441880 if (!cmn )
@@ -1792,7 +1928,8 @@ static int arm_cmn_probe(struct platform_device *pdev)
17921928 .cancel_txn = arm_cmn_end_txn ,
17931929 };
17941930
1795- name = devm_kasprintf (cmn -> dev , GFP_KERNEL , "arm_cmn_%d" , atomic_fetch_inc (& id ));
1931+ this_id = atomic_fetch_inc (& id );
1932+ name = devm_kasprintf (cmn -> dev , GFP_KERNEL , "arm_cmn_%d" , this_id );
17961933 if (!name )
17971934 return - ENOMEM ;
17981935
@@ -1803,6 +1940,8 @@ static int arm_cmn_probe(struct platform_device *pdev)
18031940 err = perf_pmu_register (& cmn -> pmu , name , -1 );
18041941 if (err )
18051942 cpuhp_state_remove_instance_nocalls (arm_cmn_hp_state , & cmn -> cpuhp_node );
1943+ else
1944+ arm_cmn_debugfs_init (cmn , this_id );
18061945
18071946 return err ;
18081947}
@@ -1815,6 +1954,7 @@ static int arm_cmn_remove(struct platform_device *pdev)
18151954
18161955 perf_pmu_unregister (& cmn -> pmu );
18171956 cpuhp_state_remove_instance_nocalls (arm_cmn_hp_state , & cmn -> cpuhp_node );
1957+ debugfs_remove (cmn -> debug );
18181958 return 0 ;
18191959}
18201960
@@ -1857,16 +1997,21 @@ static int __init arm_cmn_init(void)
18571997 return ret ;
18581998
18591999 arm_cmn_hp_state = ret ;
2000+ arm_cmn_debugfs = debugfs_create_dir ("arm-cmn" , NULL );
2001+
18602002 ret = platform_driver_register (& arm_cmn_driver );
1861- if (ret )
2003+ if (ret ) {
18622004 cpuhp_remove_multi_state (arm_cmn_hp_state );
2005+ debugfs_remove (arm_cmn_debugfs );
2006+ }
18632007 return ret ;
18642008}
18652009
18662010static void __exit arm_cmn_exit (void )
18672011{
18682012 platform_driver_unregister (& arm_cmn_driver );
18692013 cpuhp_remove_multi_state (arm_cmn_hp_state );
2014+ debugfs_remove (arm_cmn_debugfs );
18702015}
18712016
18722017module_init (arm_cmn_init );
0 commit comments