Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

arm_mpam: Add quirk framework

The MPAM specification includes the MPAMF_IIDR, which serves to uniquely
identify the MSC implementation through a combination of implementer
details, product ID, variant, and revision. Certain hardware issues/errata
can be resolved using software workarounds.

Introduce a quirk framework to allow workarounds to be enabled based on the
MPAMF_IIDR value.

Tested-by: Gavin Shan <gshan@redhat.com>
Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Tested-by: Zeng Heng <zengheng4@huawei.com>
Tested-by: Punit Agrawal <punit.agrawal@oss.qualcomm.com>
Tested-by: Jesse Chick <jessechick@os.amperecomputing.com>
Reviewed-by: Zeng Heng <zengheng4@huawei.com>
Reviewed-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Gavin Shan <gshan@redhat.com>
Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com>
Co-developed-by: Ben Horgan <ben.horgan@arm.com>
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
Co-developed-by: James Morse <james.morse@arm.com>
Signed-off-by: James Morse <james.morse@arm.com>

authored by

Shanker Donthineni and committed by
James Morse
fa774521 fb481ec0

+57
+32
drivers/resctrl/mpam_devices.c
··· 630 630 return ERR_PTR(-ENOENT); 631 631 } 632 632 633 + static const struct mpam_quirk mpam_quirks[] = { 634 + { NULL } /* Sentinel */ 635 + }; 636 + 637 + static void mpam_enable_quirks(struct mpam_msc *msc) 638 + { 639 + const struct mpam_quirk *quirk; 640 + 641 + for (quirk = &mpam_quirks[0]; quirk->iidr_mask; quirk++) { 642 + int err = 0; 643 + 644 + if (quirk->iidr != (msc->iidr & quirk->iidr_mask)) 645 + continue; 646 + 647 + if (quirk->init) 648 + err = quirk->init(msc, quirk); 649 + 650 + if (err) 651 + continue; 652 + 653 + mpam_set_quirk(quirk->workaround, msc); 654 + } 655 + } 656 + 633 657 /* 634 658 * IHI009A.a has this nugget: "If a monitor does not support automatic behaviour 635 659 * of NRDY, software can use this bit for any purpose" - so hardware might not ··· 888 864 /* Grab an IDR value to find out how many RIS there are */ 889 865 mutex_lock(&msc->part_sel_lock); 890 866 idr = mpam_msc_read_idr(msc); 867 + msc->iidr = mpam_read_partsel_reg(msc, IIDR); 891 868 mutex_unlock(&msc->part_sel_lock); 869 + 870 + mpam_enable_quirks(msc); 892 871 893 872 msc->ris_max = FIELD_GET(MPAMF_IDR_RIS_MAX, idr); 894 873 ··· 1999 1972 * resulting safe value must be compatible with both. When merging values in 2000 1973 * the tree, all the aliasing resources must be handled first. 2001 1974 * On mismatch, parent is modified. 1975 + * Quirks on an MSC will apply to all MSC in that class. 2002 1976 */ 2003 1977 static void __props_mismatch(struct mpam_props *parent, 2004 1978 struct mpam_props *child, bool alias) ··· 2119 2091 * nobble the class feature, as we can't configure all the resources. 2120 2092 * e.g. The L3 cache is composed of two resources with 13 and 17 portion 2121 2093 * bitmaps respectively. 2094 + * Quirks on an MSC will apply to all MSC in that class. 2122 2095 */ 2123 2096 static void 2124 2097 __class_props_mismatch(struct mpam_class *class, struct mpam_vmsc *vmsc) ··· 2132 2103 2133 2104 dev_dbg(dev, "Merging features for class:0x%lx &= vmsc:0x%lx\n", 2134 2105 (long)cprops->features, (long)vprops->features); 2106 + 2107 + /* Merge quirks */ 2108 + class->quirks |= vmsc->msc->quirks; 2135 2109 2136 2110 /* Take the safe value for any common features */ 2137 2111 __props_mismatch(cprops, vprops, false);
+25
drivers/resctrl/mpam_internal.h
··· 85 85 u8 pmg_max; 86 86 unsigned long ris_idxs; 87 87 u32 ris_max; 88 + u32 iidr; 89 + u16 quirks; 88 90 89 91 /* 90 92 * error_irq_lock is taken when registering/unregistering the error ··· 218 216 #define mpam_set_feature(_feat, x) __set_bit(_feat, (x)->features) 219 217 #define mpam_clear_feature(_feat, x) __clear_bit(_feat, (x)->features) 220 218 219 + /* Workaround bits for msc->quirks */ 220 + enum mpam_device_quirks { 221 + MPAM_QUIRK_LAST 222 + }; 223 + 224 + #define mpam_has_quirk(_quirk, x) ((1 << (_quirk) & (x)->quirks)) 225 + #define mpam_set_quirk(_quirk, x) ((x)->quirks |= (1 << (_quirk))) 226 + 227 + struct mpam_quirk { 228 + int (*init)(struct mpam_msc *msc, const struct mpam_quirk *quirk); 229 + 230 + u32 iidr; 231 + u32 iidr_mask; 232 + 233 + enum mpam_device_quirks workaround; 234 + }; 235 + 236 + #define MPAM_IIDR_MATCH_ONE (FIELD_PREP_CONST(MPAMF_IIDR_PRODUCTID, 0xfff) | \ 237 + FIELD_PREP_CONST(MPAMF_IIDR_VARIANT, 0xf) | \ 238 + FIELD_PREP_CONST(MPAMF_IIDR_REVISION, 0xf) | \ 239 + FIELD_PREP_CONST(MPAMF_IIDR_IMPLEMENTER, 0xfff)) 240 + 221 241 /* The values for MSMON_CFG_MBWU_FLT.RWBW */ 222 242 enum mon_filter_options { 223 243 COUNT_BOTH = 0, ··· 283 259 284 260 struct mpam_props props; 285 261 u32 nrdy_usec; 262 + u16 quirks; 286 263 u8 level; 287 264 enum mpam_class_types type; 288 265