@@ -282,6 +282,7 @@ static int cscfg_load_config(struct cscfg_config_desc *config_desc)
282
282
return err ;
283
283
284
284
list_add (& config_desc -> item , & cscfg_mgr -> config_desc_list );
285
+ atomic_set (& config_desc -> active_cnt , 0 );
285
286
return 0 ;
286
287
}
287
288
@@ -468,6 +469,219 @@ void cscfg_unregister_csdev(struct coresight_device *csdev)
468
469
}
469
470
EXPORT_SYMBOL_GPL (cscfg_unregister_csdev );
470
471
472
+ /**
473
+ * cscfg_csdev_reset_feats - reset features for a CoreSight device.
474
+ *
475
+ * Resets all parameters and register values for any features loaded
476
+ * into @csdev to their default values.
477
+ *
478
+ * @csdev: The CoreSight device.
479
+ */
480
+ void cscfg_csdev_reset_feats (struct coresight_device * csdev )
481
+ {
482
+ struct cscfg_feature_csdev * feat_csdev ;
483
+ unsigned long flags ;
484
+
485
+ spin_lock_irqsave (& csdev -> cscfg_csdev_lock , flags );
486
+ if (list_empty (& csdev -> feature_csdev_list ))
487
+ goto unlock_exit ;
488
+
489
+ list_for_each_entry (feat_csdev , & csdev -> feature_csdev_list , node )
490
+ cscfg_reset_feat (feat_csdev );
491
+
492
+ unlock_exit :
493
+ spin_unlock_irqrestore (& csdev -> cscfg_csdev_lock , flags );
494
+ }
495
+ EXPORT_SYMBOL_GPL (cscfg_csdev_reset_feats );
496
+
497
+ /**
498
+ * cscfg_activate_config - Mark a configuration descriptor as active.
499
+ *
500
+ * This will be seen when csdev devices are enabled in the system.
501
+ * Only activated configurations can be enabled on individual devices.
502
+ * Activation protects the configuration from alteration or removal while
503
+ * active.
504
+ *
505
+ * Selection by hash value - generated from the configuration name when it
506
+ * was loaded and added to the cs_etm/configurations file system for selection
507
+ * by perf.
508
+ *
509
+ * Increments the configuration descriptor active count and the global active
510
+ * count.
511
+ *
512
+ * @cfg_hash: Hash value of the selected configuration name.
513
+ */
514
+ int cscfg_activate_config (unsigned long cfg_hash )
515
+ {
516
+ struct cscfg_config_desc * config_desc ;
517
+ int err = - EINVAL ;
518
+
519
+ mutex_lock (& cscfg_mutex );
520
+
521
+ list_for_each_entry (config_desc , & cscfg_mgr -> config_desc_list , item ) {
522
+ if ((unsigned long )config_desc -> event_ea -> var == cfg_hash ) {
523
+ /*
524
+ * increment the global active count - control changes to
525
+ * active configurations
526
+ */
527
+ atomic_inc (& cscfg_mgr -> sys_active_cnt );
528
+
529
+ /*
530
+ * mark the descriptor as active so enable config on a
531
+ * device instance will use it
532
+ */
533
+ atomic_inc (& config_desc -> active_cnt );
534
+
535
+ err = 0 ;
536
+ dev_dbg (cscfg_device (), "Activate config %s.\n" , config_desc -> name );
537
+ break ;
538
+ }
539
+ }
540
+ mutex_unlock (& cscfg_mutex );
541
+
542
+ return err ;
543
+ }
544
+ EXPORT_SYMBOL_GPL (cscfg_activate_config );
545
+
546
+ /**
547
+ * cscfg_deactivate_config - Mark a config descriptor as inactive.
548
+ *
549
+ * Decrement the configuration and global active counts.
550
+ *
551
+ * @cfg_hash: Hash value of the selected configuration name.
552
+ */
553
+ void cscfg_deactivate_config (unsigned long cfg_hash )
554
+ {
555
+ struct cscfg_config_desc * config_desc ;
556
+
557
+ mutex_lock (& cscfg_mutex );
558
+
559
+ list_for_each_entry (config_desc , & cscfg_mgr -> config_desc_list , item ) {
560
+ if ((unsigned long )config_desc -> event_ea -> var == cfg_hash ) {
561
+ atomic_dec (& config_desc -> active_cnt );
562
+ atomic_dec (& cscfg_mgr -> sys_active_cnt );
563
+ dev_dbg (cscfg_device (), "Deactivate config %s.\n" , config_desc -> name );
564
+ break ;
565
+ }
566
+ }
567
+ mutex_unlock (& cscfg_mutex );
568
+ }
569
+ EXPORT_SYMBOL_GPL (cscfg_deactivate_config );
570
+
571
+ /**
572
+ * cscfg_csdev_enable_active_config - Enable matching active configuration for device.
573
+ *
574
+ * Enables the configuration selected by @cfg_hash if the configuration is supported
575
+ * on the device and has been activated.
576
+ *
577
+ * If active and supported the CoreSight device @csdev will be programmed with the
578
+ * configuration, using @preset parameters.
579
+ *
580
+ * Should be called before driver hardware enable for the requested device, prior to
581
+ * programming and enabling the physical hardware.
582
+ *
583
+ * @csdev: CoreSight device to program.
584
+ * @cfg_hash: Selector for the configuration.
585
+ * @preset: Preset parameter values to use, 0 for current / default values.
586
+ */
587
+ int cscfg_csdev_enable_active_config (struct coresight_device * csdev ,
588
+ unsigned long cfg_hash , int preset )
589
+ {
590
+ struct cscfg_config_csdev * config_csdev_active = NULL , * config_csdev_item ;
591
+ const struct cscfg_config_desc * config_desc ;
592
+ unsigned long flags ;
593
+ int err = 0 ;
594
+
595
+ /* quickly check global count */
596
+ if (!atomic_read (& cscfg_mgr -> sys_active_cnt ))
597
+ return 0 ;
598
+
599
+ /*
600
+ * Look for matching configuration - set the active configuration
601
+ * context if found.
602
+ */
603
+ spin_lock_irqsave (& csdev -> cscfg_csdev_lock , flags );
604
+ list_for_each_entry (config_csdev_item , & csdev -> config_csdev_list , node ) {
605
+ config_desc = config_csdev_item -> config_desc ;
606
+ if ((atomic_read (& config_desc -> active_cnt )) &&
607
+ ((unsigned long )config_desc -> event_ea -> var == cfg_hash )) {
608
+ config_csdev_active = config_csdev_item ;
609
+ csdev -> active_cscfg_ctxt = (void * )config_csdev_active ;
610
+ break ;
611
+ }
612
+ }
613
+ spin_unlock_irqrestore (& csdev -> cscfg_csdev_lock , flags );
614
+
615
+ /*
616
+ * If found, attempt to enable
617
+ */
618
+ if (config_csdev_active ) {
619
+ /*
620
+ * Call the generic routine that will program up the internal
621
+ * driver structures prior to programming up the hardware.
622
+ * This routine takes the driver spinlock saved in the configs.
623
+ */
624
+ err = cscfg_csdev_enable_config (config_csdev_active , preset );
625
+ if (!err ) {
626
+ /*
627
+ * Successful programming. Check the active_cscfg_ctxt
628
+ * pointer to ensure no pre-emption disabled it via
629
+ * cscfg_csdev_disable_active_config() before
630
+ * we could start.
631
+ *
632
+ * Set enabled if OK, err if not.
633
+ */
634
+ spin_lock_irqsave (& csdev -> cscfg_csdev_lock , flags );
635
+ if (csdev -> active_cscfg_ctxt )
636
+ config_csdev_active -> enabled = true;
637
+ else
638
+ err = - EBUSY ;
639
+ spin_unlock_irqrestore (& csdev -> cscfg_csdev_lock , flags );
640
+ }
641
+ }
642
+ return err ;
643
+ }
644
+ EXPORT_SYMBOL_GPL (cscfg_csdev_enable_active_config );
645
+
646
+ /**
647
+ * cscfg_csdev_disable_active_config - disable an active config on the device.
648
+ *
649
+ * Disables the active configuration on the CoreSight device @csdev.
650
+ * Disable will save the values of any registers marked in the configurations
651
+ * as save on disable.
652
+ *
653
+ * Should be called after driver hardware disable for the requested device,
654
+ * after disabling the physical hardware and reading back registers.
655
+ *
656
+ * @csdev: The CoreSight device.
657
+ */
658
+ void cscfg_csdev_disable_active_config (struct coresight_device * csdev )
659
+ {
660
+ struct cscfg_config_csdev * config_csdev ;
661
+ unsigned long flags ;
662
+
663
+ /*
664
+ * Check if we have an active config, and that it was successfully enabled.
665
+ * If it was not enabled, we have no work to do, otherwise mark as disabled.
666
+ * Clear the active config pointer.
667
+ */
668
+ spin_lock_irqsave (& csdev -> cscfg_csdev_lock , flags );
669
+ config_csdev = (struct cscfg_config_csdev * )csdev -> active_cscfg_ctxt ;
670
+ if (config_csdev ) {
671
+ if (!config_csdev -> enabled )
672
+ config_csdev = NULL ;
673
+ else
674
+ config_csdev -> enabled = false;
675
+ }
676
+ csdev -> active_cscfg_ctxt = NULL ;
677
+ spin_unlock_irqrestore (& csdev -> cscfg_csdev_lock , flags );
678
+
679
+ /* true if there was an enabled active config */
680
+ if (config_csdev )
681
+ cscfg_csdev_disable_config (config_csdev );
682
+ }
683
+ EXPORT_SYMBOL_GPL (cscfg_csdev_disable_active_config );
684
+
471
685
/* Initialise system configuration management device. */
472
686
473
687
struct device * cscfg_device (void )
@@ -536,6 +750,7 @@ int __init cscfg_init(void)
536
750
INIT_LIST_HEAD (& cscfg_mgr -> csdev_desc_list );
537
751
INIT_LIST_HEAD (& cscfg_mgr -> feat_desc_list );
538
752
INIT_LIST_HEAD (& cscfg_mgr -> config_desc_list );
753
+ atomic_set (& cscfg_mgr -> sys_active_cnt , 0 );
539
754
540
755
dev_info (cscfg_device (), "CoreSight Configuration manager initialised" );
541
756
return 0 ;
0 commit comments