@@ -674,23 +674,15 @@ void em_dev_unregister_perf_domain(struct device *dev)
674674}
675675EXPORT_SYMBOL_GPL (em_dev_unregister_perf_domain );
676676
677- /*
678- * Adjustment of CPU performance values after boot, when all CPUs capacites
679- * are correctly calculated.
680- */
681- static void em_adjust_new_capacity (struct device * dev ,
682- struct em_perf_domain * pd ,
683- u64 max_cap )
677+ static struct em_perf_table __rcu * em_table_dup (struct em_perf_domain * pd )
684678{
685679 struct em_perf_table __rcu * em_table ;
686680 struct em_perf_state * ps , * new_ps ;
687- int ret , ps_size ;
681+ int ps_size ;
688682
689683 em_table = em_table_alloc (pd );
690- if (!em_table ) {
691- dev_warn (dev , "EM: allocation failed\n" );
692- return ;
693- }
684+ if (!em_table )
685+ return NULL ;
694686
695687 new_ps = em_table -> state ;
696688
@@ -702,24 +694,52 @@ static void em_adjust_new_capacity(struct device *dev,
702694
703695 rcu_read_unlock ();
704696
705- em_init_performance (dev , pd , new_ps , pd -> nr_perf_states );
706- ret = em_compute_costs (dev , new_ps , NULL , pd -> nr_perf_states ,
697+ return em_table ;
698+ }
699+
700+ static int em_recalc_and_update (struct device * dev , struct em_perf_domain * pd ,
701+ struct em_perf_table __rcu * em_table )
702+ {
703+ int ret ;
704+
705+ ret = em_compute_costs (dev , em_table -> state , NULL , pd -> nr_perf_states ,
707706 pd -> flags );
708- if (ret ) {
709- dev_warn (dev , "EM: compute costs failed\n" );
710- return ;
711- }
707+ if (ret )
708+ goto free_em_table ;
712709
713710 ret = em_dev_update_perf_domain (dev , em_table );
714711 if (ret )
715- dev_warn ( dev , "EM: update failed %d\n" , ret ) ;
712+ goto free_em_table ;
716713
717714 /*
718715 * This is one-time-update, so give up the ownership in this updater.
719716 * The EM framework has incremented the usage counter and from now
720717 * will keep the reference (then free the memory when needed).
721718 */
719+ free_em_table :
722720 em_table_free (em_table );
721+ return ret ;
722+ }
723+
724+ /*
725+ * Adjustment of CPU performance values after boot, when all CPUs capacites
726+ * are correctly calculated.
727+ */
728+ static void em_adjust_new_capacity (struct device * dev ,
729+ struct em_perf_domain * pd ,
730+ u64 max_cap )
731+ {
732+ struct em_perf_table __rcu * em_table ;
733+
734+ em_table = em_table_dup (pd );
735+ if (!em_table ) {
736+ dev_warn (dev , "EM: allocation failed\n" );
737+ return ;
738+ }
739+
740+ em_init_performance (dev , pd , em_table -> state , pd -> nr_perf_states );
741+
742+ em_recalc_and_update (dev , pd , em_table );
723743}
724744
725745static void em_check_capacity_update (void )
@@ -788,3 +808,51 @@ static void em_update_workfn(struct work_struct *work)
788808{
789809 em_check_capacity_update ();
790810}
811+
812+ /**
813+ * em_dev_update_chip_binning() - Update Energy Model after the new voltage
814+ * information is present in the OPPs.
815+ * @dev : Device for which the Energy Model has to be updated.
816+ *
817+ * This function allows to update easily the EM with new values available in
818+ * the OPP framework and DT. It can be used after the chip has been properly
819+ * verified by device drivers and the voltages adjusted for the 'chip binning'.
820+ */
821+ int em_dev_update_chip_binning (struct device * dev )
822+ {
823+ struct em_perf_table __rcu * em_table ;
824+ struct em_perf_domain * pd ;
825+ int i , ret ;
826+
827+ if (IS_ERR_OR_NULL (dev ))
828+ return - EINVAL ;
829+
830+ pd = em_pd_get (dev );
831+ if (!pd ) {
832+ dev_warn (dev , "Couldn't find Energy Model\n" );
833+ return - EINVAL ;
834+ }
835+
836+ em_table = em_table_dup (pd );
837+ if (!em_table ) {
838+ dev_warn (dev , "EM: allocation failed\n" );
839+ return - ENOMEM ;
840+ }
841+
842+ /* Update power values which might change due to new voltage in OPPs */
843+ for (i = 0 ; i < pd -> nr_perf_states ; i ++ ) {
844+ unsigned long freq = em_table -> state [i ].frequency ;
845+ unsigned long power ;
846+
847+ ret = dev_pm_opp_calc_power (dev , & power , & freq );
848+ if (ret ) {
849+ em_table_free (em_table );
850+ return ret ;
851+ }
852+
853+ em_table -> state [i ].power = power ;
854+ }
855+
856+ return em_recalc_and_update (dev , pd , em_table );
857+ }
858+ EXPORT_SYMBOL_GPL (em_dev_update_chip_binning );
0 commit comments