Commit 051d021d authored by James Morse's avatar James Morse Committed by Zeng Heng
Browse files

arm_mpam: Probe the hardware features resctrl supports

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8T2RT

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/morse/linux.git/log/?h=mpam/snapshot/v6.7-rc2



---------------------------

Expand the probing support with the control and monitor types
we can use with resctrl.

Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarZeng Heng <zengheng4@huawei.com>
parent 9cb26074
Loading
Loading
Loading
Loading
+77 −2
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ LIST_HEAD(mpam_classes);

static u32 __mpam_read_reg(struct mpam_msc *msc, u16 reg)
{
	WARN_ON_ONCE(reg > msc->mapped_hwpage_sz);
	WARN_ON_ONCE(reg + sizeof(u32) > msc->mapped_hwpage_sz);
	WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility));

	return readl_relaxed(msc->mapped_hwpage + reg);
@@ -91,7 +91,7 @@ static u32 __mpam_read_reg(struct mpam_msc *msc, u16 reg)

static void __mpam_write_reg(struct mpam_msc *msc, u16 reg, u32 val)
{
	WARN_ON_ONCE(reg > msc->mapped_hwpage_sz);
	WARN_ON_ONCE(reg + sizeof(u32) > msc->mapped_hwpage_sz);
	WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility));

	writel_relaxed(val, msc->mapped_hwpage + reg);
@@ -516,6 +516,74 @@ static struct mpam_msc_ris *mpam_get_or_create_ris(struct mpam_msc *msc,
	return found;
}

static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
{
	int err;
	struct mpam_msc *msc = ris->msc;
	struct mpam_props *props = &ris->props;

	lockdep_assert_held(&msc->lock);
	lockdep_assert_held(&msc->part_sel_lock);

	/* Cache Portion partitioning */
	if (FIELD_GET(MPAMF_IDR_HAS_CPOR_PART, ris->idr)) {
		u32 cpor_features = mpam_read_partsel_reg(msc, CPOR_IDR);

		props->cpbm_wd = FIELD_GET(MPAMF_CPOR_IDR_CPBM_WD, cpor_features);
		if (props->cpbm_wd)
			mpam_set_feature(mpam_feat_cpor_part, props);
	}

	/* Memory bandwidth partitioning */
	if (FIELD_GET(MPAMF_IDR_HAS_MBW_PART, ris->idr)) {
		u32 mbw_features = mpam_read_partsel_reg(msc, MBW_IDR);

		/* portion bitmap resolution */
		props->mbw_pbm_bits = FIELD_GET(MPAMF_MBW_IDR_BWPBM_WD, mbw_features);
		if (props->mbw_pbm_bits &&
		    FIELD_GET(MPAMF_MBW_IDR_HAS_PBM, mbw_features))
			mpam_set_feature(mpam_feat_mbw_part, props);

		props->bwa_wd = FIELD_GET(MPAMF_MBW_IDR_BWA_WD, mbw_features);
		if (props->bwa_wd && FIELD_GET(MPAMF_MBW_IDR_HAS_MAX, mbw_features))
			mpam_set_feature(mpam_feat_mbw_max, props);
	}

	/* Performance Monitoring */
	if (FIELD_GET(MPAMF_IDR_HAS_MSMON, ris->idr)) {
		u32 msmon_features = mpam_read_partsel_reg(msc, MSMON_IDR);

		if (FIELD_GET(MPAMF_MSMON_IDR_MSMON_CSU, msmon_features)) {
			u32 csumonidr, discard;

			/*
			 * If the firmware max-nrdy-us property is missing, the
			 * CSU counters can't be used. Should we wait forever?
			 */
			err = device_property_read_u32(&msc->pdev->dev,
						       "arm,not-ready-us",
						       &discard);

			csumonidr = mpam_read_partsel_reg(msc, CSUMON_IDR);
			props->num_csu_mon = FIELD_GET(MPAMF_CSUMON_IDR_NUM_MON, csumonidr);
			if (props->num_csu_mon && !err)
				mpam_set_feature(mpam_feat_msmon_csu, props);
			else if (props->num_csu_mon)
				pr_err_once("Counters are not usable because not-ready timeout was not provided by firmware.");
		}
		if (FIELD_GET(MPAMF_MSMON_IDR_MSMON_MBWU, msmon_features)) {
			u32 mbwumonidr = mpam_read_partsel_reg(msc, MBWUMON_IDR);

			props->num_mbwu_mon = FIELD_GET(MPAMF_MBWUMON_IDR_NUM_MON, mbwumonidr);
			if (props->num_mbwu_mon)
				mpam_set_feature(mpam_feat_msmon_mbwu, props);

			if (FIELD_GET(MPAMF_MBWUMON_IDR_HAS_RWBW, mbwumonidr))
				mpam_set_feature(mpam_feat_msmon_mbwu_rwbw, props);
		}
	}
}

static int mpam_msc_hw_probe(struct mpam_msc *msc)
{
	u64 idr;
@@ -536,6 +604,7 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc)

	idr = mpam_msc_read_idr(msc);
	spin_unlock(&msc->part_sel_lock);

	msc->ris_max = FIELD_GET(MPAMF_IDR_RIS_MAX, idr);

	/* Use these values so partid/pmg always starts with a valid value */
@@ -557,6 +626,12 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc)
		if (IS_ERR(ris)) {
			return PTR_ERR(ris);
		}
		ris->idr = idr;

		spin_lock(&msc->part_sel_lock);
		__mpam_part_sel(ris_idx, 0, msc);
		mpam_ris_hw_probe(ris);
		spin_unlock(&msc->part_sel_lock);
	}

	spin_lock(&partid_max_lock);
+50 −0
Original line number Diff line number Diff line
@@ -49,6 +49,54 @@ struct mpam_msc
	size_t			mapped_hwpage_sz;
};

/*
 * When we compact the supported features, we don't care what they are.
 * Storing them as a bitmap makes life easy.
 */
typedef u16 mpam_features_t;

/* Bits for mpam_features_t */
enum mpam_device_features {
	mpam_feat_ccap_part = 0,
	mpam_feat_cpor_part,
	mpam_feat_mbw_part,
	mpam_feat_mbw_min,
	mpam_feat_mbw_max,
	mpam_feat_mbw_prop,
	mpam_feat_msmon,
	mpam_feat_msmon_csu,
	mpam_feat_msmon_csu_capture,
	mpam_feat_msmon_mbwu,
	mpam_feat_msmon_mbwu_capture,
	mpam_feat_msmon_mbwu_rwbw,
	mpam_feat_msmon_capt,
	MPAM_FEATURE_LAST,
};
#define MPAM_ALL_FEATURES      ((1<<MPAM_FEATURE_LAST) - 1)

struct mpam_props
{
	mpam_features_t		features;

	u16			cpbm_wd;
	u16			mbw_pbm_bits;
	u8			bwa_wd;
	u16			num_csu_mon;
	u16			num_mbwu_mon;
};

static inline bool mpam_has_feature(enum mpam_device_features feat,
				    struct mpam_props *props)
{
	return (1<<feat) & props->features;
}

static inline void mpam_set_feature(enum mpam_device_features feat,
				    struct mpam_props *props)
{
	props->features |= (1<<feat);
}

struct mpam_class
{
	/* mpam_components in this class */
@@ -82,6 +130,8 @@ struct mpam_component
struct mpam_msc_ris
{
	u8			ris_idx;
	u64			idr;
	struct mpam_props	props;

	cpumask_t		affinity;