5
5
#include <linux/acpi.h>
6
6
#include <linux/bitfield.h>
7
7
#include <linux/bitops.h>
8
+ #include <linux/debugfs.h>
8
9
#include <linux/interrupt.h>
9
10
#include <linux/io.h>
10
11
#include <linux/io-64-nonatomic-lo-hi.h>
@@ -287,6 +288,7 @@ struct arm_cmn {
287
288
struct hlist_node cpuhp_node ;
288
289
289
290
struct pmu pmu ;
291
+ struct dentry * debug ;
290
292
};
291
293
292
294
#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,
351
353
return NULL ;
352
354
}
353
355
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
+
354
490
struct arm_cmn_hw_event {
355
491
struct arm_cmn_node * dn ;
356
492
u64 dtm_idx [2 ];
@@ -1738,7 +1874,7 @@ static int arm_cmn_probe(struct platform_device *pdev)
1738
1874
struct arm_cmn * cmn ;
1739
1875
const char * name ;
1740
1876
static atomic_t id ;
1741
- int err , rootnode ;
1877
+ int err , rootnode , this_id ;
1742
1878
1743
1879
cmn = devm_kzalloc (& pdev -> dev , sizeof (* cmn ), GFP_KERNEL );
1744
1880
if (!cmn )
@@ -1792,7 +1928,8 @@ static int arm_cmn_probe(struct platform_device *pdev)
1792
1928
.cancel_txn = arm_cmn_end_txn ,
1793
1929
};
1794
1930
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 );
1796
1933
if (!name )
1797
1934
return - ENOMEM ;
1798
1935
@@ -1803,6 +1940,8 @@ static int arm_cmn_probe(struct platform_device *pdev)
1803
1940
err = perf_pmu_register (& cmn -> pmu , name , -1 );
1804
1941
if (err )
1805
1942
cpuhp_state_remove_instance_nocalls (arm_cmn_hp_state , & cmn -> cpuhp_node );
1943
+ else
1944
+ arm_cmn_debugfs_init (cmn , this_id );
1806
1945
1807
1946
return err ;
1808
1947
}
@@ -1815,6 +1954,7 @@ static int arm_cmn_remove(struct platform_device *pdev)
1815
1954
1816
1955
perf_pmu_unregister (& cmn -> pmu );
1817
1956
cpuhp_state_remove_instance_nocalls (arm_cmn_hp_state , & cmn -> cpuhp_node );
1957
+ debugfs_remove (cmn -> debug );
1818
1958
return 0 ;
1819
1959
}
1820
1960
@@ -1857,16 +1997,21 @@ static int __init arm_cmn_init(void)
1857
1997
return ret ;
1858
1998
1859
1999
arm_cmn_hp_state = ret ;
2000
+ arm_cmn_debugfs = debugfs_create_dir ("arm-cmn" , NULL );
2001
+
1860
2002
ret = platform_driver_register (& arm_cmn_driver );
1861
- if (ret )
2003
+ if (ret ) {
1862
2004
cpuhp_remove_multi_state (arm_cmn_hp_state );
2005
+ debugfs_remove (arm_cmn_debugfs );
2006
+ }
1863
2007
return ret ;
1864
2008
}
1865
2009
1866
2010
static void __exit arm_cmn_exit (void )
1867
2011
{
1868
2012
platform_driver_unregister (& arm_cmn_driver );
1869
2013
cpuhp_remove_multi_state (arm_cmn_hp_state );
2014
+ debugfs_remove (arm_cmn_debugfs );
1870
2015
}
1871
2016
1872
2017
module_init (arm_cmn_init );
0 commit comments