@@ -259,6 +259,15 @@ static void __mpam_part_sel(u8 ris_idx, u16 partid, struct mpam_msc *msc)
259259 __mpam_part_sel_raw (partsel , msc );
260260}
261261
262+ static void __mpam_intpart_sel (u8 ris_idx , u16 intpartid , struct mpam_msc * msc )
263+ {
264+ u32 partsel = FIELD_PREP (MPAMCFG_PART_SEL_RIS , ris_idx ) |
265+ FIELD_PREP (MPAMCFG_PART_SEL_PARTID_SEL , intpartid ) |
266+ MPAMCFG_PART_SEL_INTERNAL ;
267+
268+ __mpam_part_sel_raw (partsel , msc );
269+ }
270+
262271int mpam_register_requestor (u16 partid_max , u8 pmg_max )
263272{
264273 guard (spinlock )(& partid_max_lock );
@@ -656,10 +665,34 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
656665 struct mpam_msc * msc = ris -> vmsc -> msc ;
657666 struct device * dev = & msc -> pdev -> dev ;
658667 struct mpam_props * props = & ris -> props ;
668+ struct mpam_class * class = ris -> vmsc -> comp -> class ;
659669
660670 lockdep_assert_held (& msc -> probe_lock );
661671 lockdep_assert_held (& msc -> part_sel_lock );
662672
673+ /* Cache Capacity Partitioning */
674+ if (FIELD_GET (MPAMF_IDR_HAS_CCAP_PART , ris -> idr )) {
675+ u32 ccap_features = mpam_read_partsel_reg (msc , CCAP_IDR );
676+
677+ props -> cmax_wd = FIELD_GET (MPAMF_CCAP_IDR_CMAX_WD , ccap_features );
678+ if (props -> cmax_wd &&
679+ FIELD_GET (MPAMF_CCAP_IDR_HAS_CMAX_SOFTLIM , ccap_features ))
680+ mpam_set_feature (mpam_feat_cmax_softlim , props );
681+
682+ if (props -> cmax_wd &&
683+ !FIELD_GET (MPAMF_CCAP_IDR_NO_CMAX , ccap_features ))
684+ mpam_set_feature (mpam_feat_cmax_cmax , props );
685+
686+ if (props -> cmax_wd &&
687+ FIELD_GET (MPAMF_CCAP_IDR_HAS_CMIN , ccap_features ))
688+ mpam_set_feature (mpam_feat_cmax_cmin , props );
689+
690+ props -> cassoc_wd = FIELD_GET (MPAMF_CCAP_IDR_CASSOC_WD , ccap_features );
691+ if (props -> cassoc_wd &&
692+ FIELD_GET (MPAMF_CCAP_IDR_HAS_CASSOC , ccap_features ))
693+ mpam_set_feature (mpam_feat_cmax_cassoc , props );
694+ }
695+
663696 /* Cache Portion partitioning */
664697 if (FIELD_GET (MPAMF_IDR_HAS_CPOR_PART , ris -> idr )) {
665698 u32 cpor_features = mpam_read_partsel_reg (msc , CPOR_IDR );
@@ -682,6 +715,31 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
682715 props -> bwa_wd = FIELD_GET (MPAMF_MBW_IDR_BWA_WD , mbw_features );
683716 if (props -> bwa_wd && FIELD_GET (MPAMF_MBW_IDR_HAS_MAX , mbw_features ))
684717 mpam_set_feature (mpam_feat_mbw_max , props );
718+
719+ if (props -> bwa_wd && FIELD_GET (MPAMF_MBW_IDR_HAS_MIN , mbw_features ))
720+ mpam_set_feature (mpam_feat_mbw_min , props );
721+
722+ if (props -> bwa_wd && FIELD_GET (MPAMF_MBW_IDR_HAS_PROP , mbw_features ))
723+ mpam_set_feature (mpam_feat_mbw_prop , props );
724+ }
725+
726+ /* Priority partitioning */
727+ if (FIELD_GET (MPAMF_IDR_HAS_PRI_PART , ris -> idr )) {
728+ u32 pri_features = mpam_read_partsel_reg (msc , PRI_IDR );
729+
730+ props -> intpri_wd = FIELD_GET (MPAMF_PRI_IDR_INTPRI_WD , pri_features );
731+ if (props -> intpri_wd && FIELD_GET (MPAMF_PRI_IDR_HAS_INTPRI , pri_features )) {
732+ mpam_set_feature (mpam_feat_intpri_part , props );
733+ if (FIELD_GET (MPAMF_PRI_IDR_INTPRI_0_IS_LOW , pri_features ))
734+ mpam_set_feature (mpam_feat_intpri_part_0_low , props );
735+ }
736+
737+ props -> dspri_wd = FIELD_GET (MPAMF_PRI_IDR_DSPRI_WD , pri_features );
738+ if (props -> dspri_wd && FIELD_GET (MPAMF_PRI_IDR_HAS_DSPRI , pri_features )) {
739+ mpam_set_feature (mpam_feat_dspri_part , props );
740+ if (FIELD_GET (MPAMF_PRI_IDR_DSPRI_0_IS_LOW , pri_features ))
741+ mpam_set_feature (mpam_feat_dspri_part_0_low , props );
742+ }
685743 }
686744
687745 /* Performance Monitoring */
@@ -706,6 +764,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
706764
707765 mpam_set_feature (mpam_feat_msmon_csu , props );
708766
767+ if (FIELD_GET (MPAMF_CSUMON_IDR_HAS_XCL , csumonidr ))
768+ mpam_set_feature (mpam_feat_msmon_csu_xcl , props );
769+
709770 /* Is NRDY hardware managed? */
710771 hw_managed = mpam_ris_hw_probe_hw_nrdy (ris , CSU );
711772 if (hw_managed )
@@ -727,6 +788,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
727788 if (props -> num_mbwu_mon )
728789 mpam_set_feature (mpam_feat_msmon_mbwu , props );
729790
791+ if (FIELD_GET (MPAMF_MBWUMON_IDR_HAS_RWBW , mbwumon_idr ))
792+ mpam_set_feature (mpam_feat_msmon_mbwu_rwbw , props );
793+
730794 /* Is NRDY hardware managed? */
731795 hw_managed = mpam_ris_hw_probe_hw_nrdy (ris , MBWU );
732796 if (hw_managed )
@@ -738,6 +802,21 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
738802 */
739803 }
740804 }
805+
806+ /*
807+ * RIS with PARTID narrowing don't have enough storage for one
808+ * configuration per PARTID. If these are in a class we could use,
809+ * reduce the supported partid_max to match the number of intpartid.
810+ * If the class is unknown, just ignore it.
811+ */
812+ if (FIELD_GET (MPAMF_IDR_HAS_PARTID_NRW , ris -> idr ) &&
813+ class -> type != MPAM_CLASS_UNKNOWN ) {
814+ u32 nrwidr = mpam_read_partsel_reg (msc , PARTID_NRW_IDR );
815+ u16 partid_max = FIELD_GET (MPAMF_PARTID_NRW_IDR_INTPARTID_MAX , nrwidr );
816+
817+ mpam_set_feature (mpam_feat_partid_nrw , props );
818+ msc -> partid_max = min (msc -> partid_max , partid_max );
819+ }
741820}
742821
743822static int mpam_msc_hw_probe (struct mpam_msc * msc )
@@ -837,12 +916,28 @@ static void mpam_reset_msc_bitmap(struct mpam_msc *msc, u16 reg, u16 wd)
837916static void mpam_reprogram_ris_partid (struct mpam_msc_ris * ris , u16 partid ,
838917 struct mpam_config * cfg )
839918{
919+ u32 pri_val = 0 ;
920+ u16 cmax = MPAMCFG_CMAX_CMAX ;
840921 struct mpam_msc * msc = ris -> vmsc -> msc ;
841922 struct mpam_props * rprops = & ris -> props ;
923+ u16 dspri = GENMASK (rprops -> dspri_wd , 0 );
924+ u16 intpri = GENMASK (rprops -> intpri_wd , 0 );
842925
843926 mutex_lock (& msc -> part_sel_lock );
844927 __mpam_part_sel (ris -> ris_idx , partid , msc );
845928
929+ if (mpam_has_feature (mpam_feat_partid_nrw , rprops )) {
930+ /* Update the intpartid mapping */
931+ mpam_write_partsel_reg (msc , INTPARTID ,
932+ MPAMCFG_INTPARTID_INTERNAL | partid );
933+
934+ /*
935+ * Then switch to the 'internal' partid to update the
936+ * configuration.
937+ */
938+ __mpam_intpart_sel (ris -> ris_idx , partid , msc );
939+ }
940+
846941 if (mpam_has_feature (mpam_feat_cpor_part , rprops ) &&
847942 mpam_has_feature (mpam_feat_cpor_part , cfg )) {
848943 if (cfg -> reset_cpbm )
@@ -871,6 +966,35 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
871966 mpam_write_partsel_reg (msc , MBW_MAX , cfg -> mbw_max );
872967 }
873968
969+ if (mpam_has_feature (mpam_feat_mbw_prop , rprops ) &&
970+ mpam_has_feature (mpam_feat_mbw_prop , cfg ))
971+ mpam_write_partsel_reg (msc , MBW_PROP , 0 );
972+
973+ if (mpam_has_feature (mpam_feat_cmax_cmax , rprops ))
974+ mpam_write_partsel_reg (msc , CMAX , cmax );
975+
976+ if (mpam_has_feature (mpam_feat_cmax_cmin , rprops ))
977+ mpam_write_partsel_reg (msc , CMIN , 0 );
978+
979+ if (mpam_has_feature (mpam_feat_cmax_cassoc , rprops ))
980+ mpam_write_partsel_reg (msc , CASSOC , MPAMCFG_CASSOC_CASSOC );
981+
982+ if (mpam_has_feature (mpam_feat_intpri_part , rprops ) ||
983+ mpam_has_feature (mpam_feat_dspri_part , rprops )) {
984+ /* aces high? */
985+ if (!mpam_has_feature (mpam_feat_intpri_part_0_low , rprops ))
986+ intpri = 0 ;
987+ if (!mpam_has_feature (mpam_feat_dspri_part_0_low , rprops ))
988+ dspri = 0 ;
989+
990+ if (mpam_has_feature (mpam_feat_intpri_part , rprops ))
991+ pri_val |= FIELD_PREP (MPAMCFG_PRI_INTPRI , intpri );
992+ if (mpam_has_feature (mpam_feat_dspri_part , rprops ))
993+ pri_val |= FIELD_PREP (MPAMCFG_PRI_DSPRI , dspri );
994+
995+ mpam_write_partsel_reg (msc , PRI , pri_val );
996+ }
997+
874998 mutex_unlock (& msc -> part_sel_lock );
875999}
8761000
@@ -1308,6 +1432,18 @@ static bool mpam_has_bwa_wd_feature(struct mpam_props *props)
13081432 return true;
13091433 if (mpam_has_feature (mpam_feat_mbw_max , props ))
13101434 return true;
1435+ if (mpam_has_feature (mpam_feat_mbw_prop , props ))
1436+ return true;
1437+ return false;
1438+ }
1439+
1440+ /* Any of these features mean the CMAX_WD field is valid. */
1441+ static bool mpam_has_cmax_wd_feature (struct mpam_props * props )
1442+ {
1443+ if (mpam_has_feature (mpam_feat_cmax_cmax , props ))
1444+ return true;
1445+ if (mpam_has_feature (mpam_feat_cmax_cmin , props ))
1446+ return true;
13111447 return false;
13121448}
13131449
@@ -1366,6 +1502,23 @@ static void __props_mismatch(struct mpam_props *parent,
13661502 parent -> bwa_wd = min (parent -> bwa_wd , child -> bwa_wd );
13671503 }
13681504
1505+ if (alias && !mpam_has_cmax_wd_feature (parent ) && mpam_has_cmax_wd_feature (child )) {
1506+ parent -> cmax_wd = child -> cmax_wd ;
1507+ } else if (MISMATCHED_HELPER (parent , child , mpam_has_cmax_wd_feature ,
1508+ cmax_wd , alias )) {
1509+ pr_debug ("%s took the min cmax_wd\n" , __func__ );
1510+ parent -> cmax_wd = min (parent -> cmax_wd , child -> cmax_wd );
1511+ }
1512+
1513+ if (CAN_MERGE_FEAT (parent , child , mpam_feat_cmax_cassoc , alias )) {
1514+ parent -> cassoc_wd = child -> cassoc_wd ;
1515+ } else if (MISMATCHED_FEAT (parent , child , mpam_feat_cmax_cassoc ,
1516+ cassoc_wd , alias )) {
1517+ pr_debug ("%s cleared cassoc_wd\n" , __func__ );
1518+ mpam_clear_feature (mpam_feat_cmax_cassoc , parent );
1519+ parent -> cassoc_wd = 0 ;
1520+ }
1521+
13691522 /* For num properties, take the minimum */
13701523 if (CAN_MERGE_FEAT (parent , child , mpam_feat_msmon_csu , alias )) {
13711524 parent -> num_csu_mon = child -> num_csu_mon ;
@@ -1385,6 +1538,41 @@ static void __props_mismatch(struct mpam_props *parent,
13851538 child -> num_mbwu_mon );
13861539 }
13871540
1541+ if (CAN_MERGE_FEAT (parent , child , mpam_feat_intpri_part , alias )) {
1542+ parent -> intpri_wd = child -> intpri_wd ;
1543+ } else if (MISMATCHED_FEAT (parent , child , mpam_feat_intpri_part ,
1544+ intpri_wd , alias )) {
1545+ pr_debug ("%s took the min intpri_wd\n" , __func__ );
1546+ parent -> intpri_wd = min (parent -> intpri_wd , child -> intpri_wd );
1547+ }
1548+
1549+ if (CAN_MERGE_FEAT (parent , child , mpam_feat_dspri_part , alias )) {
1550+ parent -> dspri_wd = child -> dspri_wd ;
1551+ } else if (MISMATCHED_FEAT (parent , child , mpam_feat_dspri_part ,
1552+ dspri_wd , alias )) {
1553+ pr_debug ("%s took the min dspri_wd\n" , __func__ );
1554+ parent -> dspri_wd = min (parent -> dspri_wd , child -> dspri_wd );
1555+ }
1556+
1557+ /* TODO: alias support for these two */
1558+ /* {int,ds}pri may not have differing 0-low behaviour */
1559+ if (mpam_has_feature (mpam_feat_intpri_part , parent ) &&
1560+ (!mpam_has_feature (mpam_feat_intpri_part , child ) ||
1561+ mpam_has_feature (mpam_feat_intpri_part_0_low , parent ) !=
1562+ mpam_has_feature (mpam_feat_intpri_part_0_low , child ))) {
1563+ pr_debug ("%s cleared intpri_part\n" , __func__ );
1564+ mpam_clear_feature (mpam_feat_intpri_part , parent );
1565+ mpam_clear_feature (mpam_feat_intpri_part_0_low , parent );
1566+ }
1567+ if (mpam_has_feature (mpam_feat_dspri_part , parent ) &&
1568+ (!mpam_has_feature (mpam_feat_dspri_part , child ) ||
1569+ mpam_has_feature (mpam_feat_dspri_part_0_low , parent ) !=
1570+ mpam_has_feature (mpam_feat_dspri_part_0_low , child ))) {
1571+ pr_debug ("%s cleared dspri_part\n" , __func__ );
1572+ mpam_clear_feature (mpam_feat_dspri_part , parent );
1573+ mpam_clear_feature (mpam_feat_dspri_part_0_low , parent );
1574+ }
1575+
13881576 if (alias ) {
13891577 /* Merge features for aliased resources */
13901578 bitmap_or (parent -> features , parent -> features , child -> features , MPAM_FEATURE_LAST );
0 commit comments