提交 3022a1c3 编写于 作者: J James Morse 提交者: Zheng Zengkai

arm64/mpam: Summarize feature support during mpam_enable()

hulk inclusion
category: feature
feature: ARM MPAM support
bugzilla: 48265
CVE: NA

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

To make a decision about whether to expose an mpam class as
a resctrl resource we need to know its overall supported
features and properties.

Once we've probed all the devices, we can walk the tree
and produced overall values. If bitmap properties are mismatched
within a component we cannot support that bitmap.

[Wang ShaoBo: few version adaption changes]
Signed-off-by: NJames Morse <james.morse@arm.com>
Link: http://www.linux-arm.org/git?p=linux-jm.git;a=patch;h=96d7c0b933c0334abf9c45d73f239ac3f382c074Signed-off-by: NWang ShaoBo <bobo.shaobowang@huawei.com>
Reviewed-by: NXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: NCheng Jian <cj.chengjian@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 675345bc
......@@ -252,6 +252,112 @@ static int mpam_device_probe(struct mpam_device *dev)
return 0;
}
/*
* If device doesn't match class feature/configuration, do the right thing.
* For 'num' properties we can just take the minimum.
* For properties where the mismatched unused bits would make a difference, we
* nobble the class feature, as we can't configure all the devices.
* e.g. The L3 cache is composed of two devices with 13 and 17 portion
* bitmaps respectively.
*/
static void __device_class_feature_mismatch(struct mpam_device *dev,
struct mpam_class *class)
{
lockdep_assert_held(&mpam_devices_lock); /* we modify class */
if (class->cpbm_wd != dev->cpbm_wd)
mpam_clear_feature(mpam_feat_cpor_part, &class->features);
if (class->mbw_pbm_bits != dev->mbw_pbm_bits)
mpam_clear_feature(mpam_feat_mbw_part, &class->features);
/* For num properties, take the minimum */
if (class->num_partid != dev->num_partid)
class->num_partid = min(class->num_partid, dev->num_partid);
if (class->num_intpartid != dev->num_intpartid)
class->num_intpartid = min(class->num_intpartid, dev->num_intpartid);
if (class->num_pmg != dev->num_pmg)
class->num_pmg = min(class->num_pmg, dev->num_pmg);
if (class->num_csu_mon != dev->num_csu_mon)
class->num_csu_mon = min(class->num_csu_mon, dev->num_csu_mon);
if (class->num_mbwu_mon != dev->num_mbwu_mon)
class->num_mbwu_mon = min(class->num_mbwu_mon,
dev->num_mbwu_mon);
/* bwa_wd is a count of bits, fewer bits means less precision */
if (class->bwa_wd != dev->bwa_wd)
class->bwa_wd = min(class->bwa_wd, dev->bwa_wd);
if (class->intpri_wd != dev->intpri_wd)
class->intpri_wd = min(class->intpri_wd, dev->intpri_wd);
if (class->dspri_wd != dev->dspri_wd)
class->dspri_wd = min(class->dspri_wd, dev->dspri_wd);
/* {int,ds}pri may not have differing 0-low behaviour */
if (mpam_has_feature(mpam_feat_intpri_part_0_low, class->features) !=
mpam_has_feature(mpam_feat_intpri_part_0_low, dev->features))
mpam_clear_feature(mpam_feat_intpri_part, &class->features);
if (mpam_has_feature(mpam_feat_dspri_part_0_low, class->features) !=
mpam_has_feature(mpam_feat_dspri_part_0_low, dev->features))
mpam_clear_feature(mpam_feat_dspri_part, &class->features);
}
/*
* Squash common class=>component=>device->features down to the
* class->features
*/
static void mpam_enable_squash_features(void)
{
unsigned long flags;
struct mpam_device *dev;
struct mpam_class *class;
struct mpam_component *comp;
lockdep_assert_held(&mpam_devices_lock);
list_for_each_entry(class, &mpam_classes, classes_list) {
/*
* Copy the first component's first device's properties and
* features to the class. __device_class_feature_mismatch()
* will fix them as appropriate.
* It is not possible to have a component with no devices.
*/
if (!list_empty(&class->components)) {
comp = list_first_entry_or_null(&class->components,
struct mpam_component, class_list);
if (WARN_ON(!comp))
break;
dev = list_first_entry_or_null(&comp->devices,
struct mpam_device, comp_list);
if (WARN_ON(!dev))
break;
spin_lock_irqsave(&dev->lock, flags);
class->features = dev->features;
class->cpbm_wd = dev->cpbm_wd;
class->mbw_pbm_bits = dev->mbw_pbm_bits;
class->bwa_wd = dev->bwa_wd;
class->intpri_wd = dev->intpri_wd;
class->dspri_wd = dev->dspri_wd;
class->num_partid = dev->num_partid;
class->num_intpartid = dev->num_intpartid;
class->num_pmg = dev->num_pmg;
class->num_csu_mon = dev->num_csu_mon;
class->num_mbwu_mon = dev->num_mbwu_mon;
spin_unlock_irqrestore(&dev->lock, flags);
}
list_for_each_entry(comp, &class->components, class_list) {
list_for_each_entry(dev, &comp->devices, comp_list) {
spin_lock_irqsave(&dev->lock, flags);
__device_class_feature_mismatch(dev, class);
class->features &= dev->features;
spin_unlock_irqrestore(&dev->lock, flags);
}
}
}
}
/*
* Enable mpam once all devices have been probed.
* Scheduled by mpam_discovery_complete() once all devices have been created.
......@@ -278,6 +384,10 @@ static void __init mpam_enable(struct work_struct *work)
if (!all_devices_probed)
return;
mutex_lock(&mpam_devices_lock);
mpam_enable_squash_features();
mutex_unlock(&mpam_devices_lock);
}
static void mpam_failed(struct work_struct *work)
......
......@@ -98,10 +98,25 @@ struct mpam_class {
u8 level;
enum mpam_class_types type;
/* Once enabled, the common features */
u32 features;
struct mutex lock;
/* member of mpam_classes */
struct list_head classes_list;
u16 cmax_wd;
u16 cpbm_wd;
u16 mbw_pbm_bits;
u16 bwa_wd;
u16 intpri_wd;
u16 dspri_wd;
u16 num_partid;
u16 num_intpartid;
u16 num_pmg;
u16 num_csu_mon;
u16 num_mbwu_mon;
};
/* System wide properties */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册