@@ -170,6 +170,22 @@ static inline void _mpam_write_partsel_reg(struct mpam_msc *msc, u16 reg, u32 va
170170
171171#define mpam_write_partsel_reg (msc , reg , val ) _mpam_write_partsel_reg(msc, MPAMCFG_##reg, val)
172172
173+ static inline u32 _mpam_read_monsel_reg (struct mpam_msc * msc , u16 reg )
174+ {
175+ mpam_mon_sel_lock_held (msc );
176+ return __mpam_read_reg (msc , reg );
177+ }
178+
179+ #define mpam_read_monsel_reg (msc , reg ) _mpam_read_monsel_reg(msc, MSMON_##reg)
180+
181+ static inline void _mpam_write_monsel_reg (struct mpam_msc * msc , u16 reg , u32 val )
182+ {
183+ mpam_mon_sel_lock_held (msc );
184+ __mpam_write_reg (msc , reg , val );
185+ }
186+
187+ #define mpam_write_monsel_reg (msc , reg , val ) _mpam_write_monsel_reg(msc, MSMON_##reg, val)
188+
173189static u64 mpam_msc_read_idr (struct mpam_msc * msc )
174190{
175191 u64 idr_high = 0 , idr_low ;
@@ -548,6 +564,133 @@ static struct mpam_msc_ris *mpam_get_or_create_ris(struct mpam_msc *msc,
548564 return ERR_PTR (- ENOENT );
549565}
550566
567+ /*
568+ * IHI009A.a has this nugget: "If a monitor does not support automatic behaviour
569+ * of NRDY, software can use this bit for any purpose" - so hardware might not
570+ * implement this - but it isn't RES0.
571+ *
572+ * Try and see what values stick in this bit. If we can write either value,
573+ * its probably not implemented by hardware.
574+ */
575+ static bool _mpam_ris_hw_probe_hw_nrdy (struct mpam_msc_ris * ris , u32 mon_reg )
576+ {
577+ u32 now ;
578+ u64 mon_sel ;
579+ bool can_set , can_clear ;
580+ struct mpam_msc * msc = ris -> vmsc -> msc ;
581+
582+ if (WARN_ON_ONCE (!mpam_mon_sel_lock (msc )))
583+ return false;
584+
585+ mon_sel = FIELD_PREP (MSMON_CFG_MON_SEL_MON_SEL , 0 ) |
586+ FIELD_PREP (MSMON_CFG_MON_SEL_RIS , ris -> ris_idx );
587+ _mpam_write_monsel_reg (msc , mon_reg , mon_sel );
588+
589+ _mpam_write_monsel_reg (msc , mon_reg , MSMON___NRDY );
590+ now = _mpam_read_monsel_reg (msc , mon_reg );
591+ can_set = now & MSMON___NRDY ;
592+
593+ _mpam_write_monsel_reg (msc , mon_reg , 0 );
594+ now = _mpam_read_monsel_reg (msc , mon_reg );
595+ can_clear = !(now & MSMON___NRDY );
596+ mpam_mon_sel_unlock (msc );
597+
598+ return (!can_set || !can_clear );
599+ }
600+
601+ #define mpam_ris_hw_probe_hw_nrdy (_ris , _mon_reg ) \
602+ _mpam_ris_hw_probe_hw_nrdy(_ris, MSMON_##_mon_reg)
603+
604+ static void mpam_ris_hw_probe (struct mpam_msc_ris * ris )
605+ {
606+ int err ;
607+ struct mpam_msc * msc = ris -> vmsc -> msc ;
608+ struct device * dev = & msc -> pdev -> dev ;
609+ struct mpam_props * props = & ris -> props ;
610+
611+ lockdep_assert_held (& msc -> probe_lock );
612+ lockdep_assert_held (& msc -> part_sel_lock );
613+
614+ /* Cache Portion partitioning */
615+ if (FIELD_GET (MPAMF_IDR_HAS_CPOR_PART , ris -> idr )) {
616+ u32 cpor_features = mpam_read_partsel_reg (msc , CPOR_IDR );
617+
618+ props -> cpbm_wd = FIELD_GET (MPAMF_CPOR_IDR_CPBM_WD , cpor_features );
619+ if (props -> cpbm_wd )
620+ mpam_set_feature (mpam_feat_cpor_part , props );
621+ }
622+
623+ /* Memory bandwidth partitioning */
624+ if (FIELD_GET (MPAMF_IDR_HAS_MBW_PART , ris -> idr )) {
625+ u32 mbw_features = mpam_read_partsel_reg (msc , MBW_IDR );
626+
627+ /* portion bitmap resolution */
628+ props -> mbw_pbm_bits = FIELD_GET (MPAMF_MBW_IDR_BWPBM_WD , mbw_features );
629+ if (props -> mbw_pbm_bits &&
630+ FIELD_GET (MPAMF_MBW_IDR_HAS_PBM , mbw_features ))
631+ mpam_set_feature (mpam_feat_mbw_part , props );
632+
633+ props -> bwa_wd = FIELD_GET (MPAMF_MBW_IDR_BWA_WD , mbw_features );
634+ if (props -> bwa_wd && FIELD_GET (MPAMF_MBW_IDR_HAS_MAX , mbw_features ))
635+ mpam_set_feature (mpam_feat_mbw_max , props );
636+ }
637+
638+ /* Performance Monitoring */
639+ if (FIELD_GET (MPAMF_IDR_HAS_MSMON , ris -> idr )) {
640+ u32 msmon_features = mpam_read_partsel_reg (msc , MSMON_IDR );
641+
642+ /*
643+ * If the firmware max-nrdy-us property is missing, the
644+ * CSU counters can't be used. Should we wait forever?
645+ */
646+ err = device_property_read_u32 (& msc -> pdev -> dev ,
647+ "arm,not-ready-us" ,
648+ & msc -> nrdy_usec );
649+
650+ if (FIELD_GET (MPAMF_MSMON_IDR_MSMON_CSU , msmon_features )) {
651+ u32 csumonidr ;
652+
653+ csumonidr = mpam_read_partsel_reg (msc , CSUMON_IDR );
654+ props -> num_csu_mon = FIELD_GET (MPAMF_CSUMON_IDR_NUM_MON , csumonidr );
655+ if (props -> num_csu_mon ) {
656+ bool hw_managed ;
657+
658+ mpam_set_feature (mpam_feat_msmon_csu , props );
659+
660+ /* Is NRDY hardware managed? */
661+ hw_managed = mpam_ris_hw_probe_hw_nrdy (ris , CSU );
662+ if (hw_managed )
663+ mpam_set_feature (mpam_feat_msmon_csu_hw_nrdy , props );
664+ }
665+
666+ /*
667+ * Accept the missing firmware property if NRDY appears
668+ * un-implemented.
669+ */
670+ if (err && mpam_has_feature (mpam_feat_msmon_csu_hw_nrdy , props ))
671+ dev_err_once (dev , "Counters are not usable because not-ready timeout was not provided by firmware." );
672+ }
673+ if (FIELD_GET (MPAMF_MSMON_IDR_MSMON_MBWU , msmon_features )) {
674+ bool hw_managed ;
675+ u32 mbwumon_idr = mpam_read_partsel_reg (msc , MBWUMON_IDR );
676+
677+ props -> num_mbwu_mon = FIELD_GET (MPAMF_MBWUMON_IDR_NUM_MON , mbwumon_idr );
678+ if (props -> num_mbwu_mon )
679+ mpam_set_feature (mpam_feat_msmon_mbwu , props );
680+
681+ /* Is NRDY hardware managed? */
682+ hw_managed = mpam_ris_hw_probe_hw_nrdy (ris , MBWU );
683+ if (hw_managed )
684+ mpam_set_feature (mpam_feat_msmon_mbwu_hw_nrdy , props );
685+
686+ /*
687+ * Don't warn about any missing firmware property for
688+ * MBWU NRDY - it doesn't make any sense!
689+ */
690+ }
691+ }
692+ }
693+
551694static int mpam_msc_hw_probe (struct mpam_msc * msc )
552695{
553696 u64 idr ;
@@ -591,6 +734,12 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc)
591734 mutex_unlock (& mpam_list_lock );
592735 if (IS_ERR (ris ))
593736 return PTR_ERR (ris );
737+ ris -> idr = idr ;
738+
739+ mutex_lock (& msc -> part_sel_lock );
740+ __mpam_part_sel (ris_idx , 0 , msc );
741+ mpam_ris_hw_probe (ris );
742+ mutex_unlock (& msc -> part_sel_lock );
594743 }
595744
596745 spin_lock (& partid_max_lock );
0 commit comments