diff --git a/arch/arm64/include/asm/mpam.h b/arch/arm64/include/asm/mpam.h index 52a334cce91ae21da081725ae9dd0723c2355f10..ec2fc0f2eadb100dcfaf794d64236d44eaeee7f9 100644 --- a/arch/arm64/include/asm/mpam.h +++ b/arch/arm64/include/asm/mpam.h @@ -167,7 +167,7 @@ do { \ bool is_resctrl_cdp_enabled(void); -#define hw_alloc_times_validate(__name, __times, __flag) \ +#define hw_alloc_times_validate(__times, __flag) \ do { \ __flag = is_resctrl_cdp_enabled(); \ __times = flag ? 2 : 1; \ @@ -309,7 +309,7 @@ struct raw_resctrl_resource { u16 num_mon; u64 (*mon_read)(struct rdt_domain *d, void *md_priv); - int (*mon_write)(struct rdt_domain *d, void *md_priv, bool enable); + int (*mon_write)(struct rdt_domain *d, void *md_priv); }; /* 64bit arm64 specified */ @@ -333,14 +333,11 @@ int resctrl_group_schemata_show(struct kernfs_open_file *of, struct rdt_domain *mpam_find_domain(struct resctrl_resource *r, int id, struct list_head **pos); -ssize_t resctrl_group_ctrlmon_write(struct kernfs_open_file *of, - char *buf, size_t nbytes, loff_t off); - -int resctrl_group_ctrlmon_show(struct kernfs_open_file *of, - struct seq_file *s, void *v); - int resctrl_group_alloc_mon(struct rdtgroup *grp); u16 mpam_resctrl_max_mon_num(void); +void pmg_init(void); +void mon_init(void); + #endif /* _ASM_ARM64_MPAM_H */ diff --git a/arch/arm64/include/asm/resctrl.h b/arch/arm64/include/asm/resctrl.h index 90b7683dd4dd3eef0c468cba6d3e8ce6198f198a..68e515ea8779a816b2a8cb862b7e7193b8831b6c 100644 --- a/arch/arm64/include/asm/resctrl.h +++ b/arch/arm64/include/asm/resctrl.h @@ -78,48 +78,14 @@ int schemata_list_init(void); void schemata_list_destroy(void); -int alloc_rmid(void); -void free_rmid(u32 rmid); +int resctrl_lru_request_mon(void); -static inline int alloc_mon_id(void) -{ - - return alloc_rmid(); -} - -static inline void free_mon_id(u32 id) -{ - free_rmid(id); -} +int alloc_mon_id(void); +void free_mon_id(u32 id); -int closid_init(void); -int closid_alloc(void); -void closid_free(int closid); -void pmg_init(void); - -static inline int resctrl_id_init(void) -{ - int ret; - - ret = closid_init(); - if (ret) - goto out; - - pmg_init(); - -out: - return ret; -} - -static inline int resctrl_id_alloc(void) -{ - return closid_alloc(); -} - -static inline void resctrl_id_free(int id) -{ - closid_free(id); -} +int resctrl_id_init(void); +int resctrl_id_alloc(void); +void resctrl_id_free(int id); void update_cpu_closid_rmid(void *info); void update_closid_rmid(const struct cpumask *cpu_mask, struct resctrl_group *r); @@ -131,7 +97,6 @@ extern bool rdt_mon_capable; /* rdtgroup.flags */ #define RDT_DELETED BIT(0) -#define RDT_CTRLMON BIT(1) void rdt_last_cmd_clear(void); void rdt_last_cmd_puts(const char *s); @@ -142,9 +107,6 @@ extern struct mutex resctrl_group_mutex; void release_rdtgroupfs_options(void); int parse_rdtgroupfs_options(char *data); -int alloc_mon(void); -void free_mon(u32 mon); - void resctrl_resource_reset(void); #define release_resctrl_group_fs_options release_rdtgroupfs_options @@ -152,14 +114,6 @@ void resctrl_resource_reset(void); int mpam_get_mon_config(struct resctrl_resource *r); -int mkdir_mondata_all(struct kernfs_node *parent_kn, - struct resctrl_group *prgrp, - struct kernfs_node **dest_kn); - -int -mongroup_create_dir(struct kernfs_node *parent_kn, struct resctrl_group *prgrp, - char *name, struct kernfs_node **dest_kn); - int resctrl_group_init_alloc(struct rdtgroup *rdtgrp); static inline int __resctrl_group_show_options(struct seq_file *seq) @@ -167,9 +121,8 @@ static inline int __resctrl_group_show_options(struct seq_file *seq) return 0; } -int resctrl_mkdir_ctrlmon_mondata(struct kernfs_node *parent_kn, - struct rdtgroup *prgrp, - struct kernfs_node **dest_kn); +int resctrl_mkdir_mondata_all_subdir(struct kernfs_node *parent_kn, + struct resctrl_group *prgrp); struct resctrl_resource * mpam_resctrl_get_resource(enum resctrl_resource_level level); diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c index a94a1f2c5847657b80a1b33002557ae356ec10a0..0c324008d9abf058ea0235be501377120bc5fa36 100644 --- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c +++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c @@ -450,7 +450,7 @@ static int resctrl_group_kn_set_ugid(struct kernfs_node *kn) return kernfs_setattr(kn, &iattr); } -static int mkdir_mondata_subdir(struct kernfs_node *parent_kn, +static int resctrl_mkdir_mondata_dom(struct kernfs_node *parent_kn, struct rdt_domain *d, struct resctrl_schema *s, struct resctrl_group *prgrp) @@ -490,121 +490,12 @@ static int mkdir_mondata_subdir(struct kernfs_node *parent_kn, } /* Could we remove the MATCH_* param ? */ - rr->mon_write(d, md.priv, true); + rr->mon_write(d, md.priv); return ret; } -int resctrl_ctrlmon_enable(struct kernfs_node *parent_kn, - struct resctrl_group *prgrp, - struct kernfs_node **dest_kn) -{ - int ret; - - /* only for RDTCTRL_GROUP */ - if (prgrp->type == RDTMON_GROUP) - return 0; - - ret = alloc_mon(); - if (ret < 0) { - rdt_last_cmd_puts("out of monitors\n"); - pr_info("out of monitors: ret %d\n", ret); - return ret; - } - prgrp->mon.mon = ret; - prgrp->mon.rmid = 0; - - ret = mkdir_mondata_all(parent_kn, prgrp, dest_kn); - if (ret) { - rdt_last_cmd_puts("kernfs subdir error\n"); - free_mon(ret); - } - - return ret; -} - -void resctrl_ctrlmon_disable(struct kernfs_node *kn_mondata, - struct resctrl_group *prgrp) -{ - struct mpam_resctrl_res *r; - struct resctrl_resource *resctrl_res; - struct raw_resctrl_resource *rr; - struct rdt_domain *dom; - int mon = prgrp->mon.mon; - - /* only for RDTCTRL_GROUP */ - if (prgrp->type == RDTMON_GROUP) - return; - - for_each_resctrl_exports(r) { - resctrl_res = &r->resctrl_res; - - if (resctrl_res->mon_enabled) { - rr = (struct raw_resctrl_resource *)resctrl_res->res; - - list_for_each_entry(dom, &resctrl_res->domains, list) { - rr->mon_write(dom, prgrp, false); - } - } - } - - free_mon(mon); - kernfs_remove(kn_mondata); -} - -ssize_t resctrl_group_ctrlmon_write(struct kernfs_open_file *of, - char *buf, size_t nbytes, loff_t off) -{ - struct rdtgroup *rdtgrp; - int ret = 0; - int ctrlmon; - - if (kstrtoint(strstrip(buf), 0, &ctrlmon) || ctrlmon < 0) - return -EINVAL; - rdtgrp = resctrl_group_kn_lock_live(of->kn); - rdt_last_cmd_clear(); - - if (!rdtgrp) { - ret = -ENOENT; - goto unlock; - } - - if ((rdtgrp->flags & RDT_CTRLMON) && !ctrlmon) { - /* disable & remove mon_data dir */ - rdtgrp->flags &= ~RDT_CTRLMON; - resctrl_ctrlmon_disable(rdtgrp->mon.mon_data_kn, rdtgrp); - } else if (!(rdtgrp->flags & RDT_CTRLMON) && ctrlmon) { - ret = resctrl_ctrlmon_enable(rdtgrp->kn, rdtgrp, - &rdtgrp->mon.mon_data_kn); - if (!ret) - rdtgrp->flags |= RDT_CTRLMON; - } else { - ret = -ENOENT; - } - -unlock: - resctrl_group_kn_unlock(of->kn); - return ret ?: nbytes; -} - -int resctrl_group_ctrlmon_show(struct kernfs_open_file *of, - struct seq_file *s, void *v) -{ - struct rdtgroup *rdtgrp; - int ret = 0; - - rdtgrp = resctrl_group_kn_lock_live(of->kn); - if (rdtgrp) - seq_printf(s, "%d", !!(rdtgrp->flags & RDT_CTRLMON)); - else - ret = -ENOENT; - resctrl_group_kn_unlock(of->kn); - - return ret; -} - - -static int mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn, +static int resctrl_mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn, struct resctrl_schema *s, struct resctrl_group *prgrp) { struct resctrl_resource *r; @@ -613,7 +504,7 @@ static int mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn, r = s->res; list_for_each_entry(dom, &r->domains, list) { - ret = mkdir_mondata_subdir(parent_kn, dom, s, prgrp); + ret = resctrl_mkdir_mondata_dom(parent_kn, dom, s, prgrp); if (ret) return ret; } @@ -621,79 +512,13 @@ static int mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn, return 0; } -int -mongroup_create_dir(struct kernfs_node *parent_kn, struct resctrl_group *prgrp, - char *name, struct kernfs_node **dest_kn) -{ - struct kernfs_node *kn; - int ret; - - /* create the directory */ - kn = kernfs_create_dir(parent_kn, name, parent_kn->mode, prgrp); - if (IS_ERR(kn)) { - pr_info("%s: create dir %s, error\n", __func__, name); - return PTR_ERR(kn); - } - - if (dest_kn) - *dest_kn = kn; - - /* - * This extra ref will be put in kernfs_remove() and guarantees - * that @rdtgrp->kn is always accessible. - */ - kernfs_get(kn); - - ret = resctrl_group_kn_set_ugid(kn); - if (ret) - goto out_destroy; - - kernfs_activate(kn); - - return 0; - -out_destroy: - kernfs_remove(kn); - return ret; -} - - -/* - * This creates a directory mon_data which contains the monitored data. - * - * mon_data has one directory for each domain whic are named - * in the format mon__. For ex: A mon_data - * with L3 domain looks as below: - * ./mon_data: - * mon_L3_00 - * mon_L3_01 - * mon_L3_02 - * ... - * - * Each domain directory has one file per event: - * ./mon_L3_00/: - * llc_occupancy - * - */ -int mkdir_mondata_all(struct kernfs_node *parent_kn, - struct resctrl_group *prgrp, - struct kernfs_node **dest_kn) +int resctrl_mkdir_mondata_all_subdir(struct kernfs_node *parent_kn, + struct resctrl_group *prgrp) { struct resctrl_schema *s; struct resctrl_resource *r; - struct kernfs_node *kn; int ret; - /* - * Create the mon_data directory first. - */ - ret = mongroup_create_dir(parent_kn, prgrp, "mon_data", &kn); - if (ret) - return ret; - - if (dest_kn) - *dest_kn = kn; - /* * Create the subdirectories for each domain. Note that all events * in a domain like L3 are grouped into a resource whose domain is L3 @@ -705,61 +530,14 @@ int mkdir_mondata_all(struct kernfs_node *parent_kn, struct raw_resctrl_resource *rr; rr = r->res; - /* - * num pmg of different resources varies, we just - * skip creating those unqualified ones. - */ - if ((prgrp->type == RDTMON_GROUP) && - (prgrp->mon.rmid >= rr->num_pmg)) - continue; - ret = mkdir_mondata_subdir_alldom(kn, s, prgrp); + ret = resctrl_mkdir_mondata_subdir_alldom(parent_kn, + s, prgrp); if (ret) - goto out_destroy; + break; } } - kernfs_activate(kn); - - return 0; - -out_destroy: - kernfs_remove(kn); - return ret; -} - -int resctrl_mkdir_ctrlmon_mondata(struct kernfs_node *parent_kn, - struct resctrl_group *prgrp, - struct kernfs_node **dest_kn) -{ - int ret; - - /* disalbe monitor by default for mpam. */ - if (prgrp->type == RDTCTRL_GROUP) - return 0; - - ret = alloc_mon(); - if (ret < 0) { - rdt_last_cmd_puts("out of monitors\n"); - return ret; - } - prgrp->mon.mon = ret; - - ret = alloc_mon_id(); - if (ret < 0) { - rdt_last_cmd_puts("out of PMGs\n"); - free_mon(prgrp->mon.mon); - return ret; - } - - prgrp->mon.rmid = ret; - - ret = mkdir_mondata_all(parent_kn, prgrp, dest_kn); - if (ret) { - rdt_last_cmd_puts("kernfs subdir error\n"); - free_mon(ret); - } - return ret; } diff --git a/arch/arm64/kernel/mpam/mpam_mon.c b/arch/arm64/kernel/mpam/mpam_mon.c index bb681d1ab7adfb486cbb2a4fcae4c7ab4263d86d..29f84e251b1ebdb26d6cedefd223574e8f851ce8 100644 --- a/arch/arm64/kernel/mpam/mpam_mon.c +++ b/arch/arm64/kernel/mpam/mpam_mon.c @@ -38,7 +38,6 @@ bool rdt_mon_capable; static int pmg_free_map; -void mon_init(void); void pmg_init(void) { u16 num_pmg = USHRT_MAX; @@ -53,15 +52,13 @@ void pmg_init(void) num_pmg = min(num_pmg, rr->num_pmg); } - mon_init(); - pmg_free_map = BIT_MASK(num_pmg) - 1; /* pmg 0 is always reserved for the default group */ pmg_free_map &= ~1; } -int alloc_pmg(void) +static int alloc_pmg(void) { u32 pmg = ffs(pmg_free_map); @@ -74,58 +71,66 @@ int alloc_pmg(void) return pmg; } -void free_pmg(u32 pmg) +static void free_pmg(u32 pmg) { pmg_free_map |= 1 << pmg; } -static int mon_free_map; +int alloc_mon_id(void) +{ + return alloc_pmg(); +} + +void free_mon_id(u32 id) +{ + free_pmg(id); +} + +/* + * A simple LRU monitor allocation machanism, each + * monitor free map occupies two section, one for + * allocation and another for recording. + */ +static int mon_free_map[2]; +static u8 alloc_idx, record_idx; + void mon_init(void) { int num_mon; + u32 times, flag; num_mon = mpam_resctrl_max_mon_num(); - mon_free_map = BIT_MASK(num_mon) - 1; + hw_alloc_times_validate(times, flag); + /* for cdp on or off */ + num_mon = rounddown(num_mon, times); + + mon_free_map[0] = BIT_MASK(num_mon) - 1; + mon_free_map[1] = 0; + + alloc_idx = 0; + record_idx = 1; } -int alloc_mon(void) +int resctrl_lru_request_mon(void) { u32 mon = 0; u32 times, flag; - hw_alloc_times_validate(mon, times, flag); + hw_alloc_times_validate(times, flag); - mon = ffs(mon_free_map); + mon = ffs(mon_free_map[alloc_idx]); if (mon == 0) return -ENOSPC; mon--; - mon_free_map &= ~(GENMASK(mon, mon + times - 1)); + mon_free_map[alloc_idx] &= ~(GENMASK(mon + times - 1, mon)); + mon_free_map[record_idx] |= GENMASK(mon + times - 1, mon); - return mon; -} - -void free_mon(u32 mon) -{ - u32 times, flag; - - hw_alloc_times_validate(mon, times, flag); - - mon_free_map |= GENMASK(mon, mon + times - 1); -} - -/* - * As of now the RMIDs allocation is global. - * However we keep track of which packages the RMIDs - * are used to optimize the limbo list management. - */ -int alloc_rmid(void) -{ - return alloc_pmg(); -} + if (!mon_free_map[alloc_idx]) { + alloc_idx = record_idx; + record_idx ^= 0x1; + } -void free_rmid(u32 pmg) -{ - free_pmg(pmg); + return mon; } diff --git a/arch/arm64/kernel/mpam/mpam_resctrl.c b/arch/arm64/kernel/mpam/mpam_resctrl.c index aafe20473acf15cd585b0380cb4511b147e1b641..ce05b8037a4d885a66ba27b87da34ba7ccbdf837 100644 --- a/arch/arm64/kernel/mpam/mpam_resctrl.c +++ b/arch/arm64/kernel/mpam/mpam_resctrl.c @@ -124,16 +124,7 @@ static u64 mbw_rdmsr(struct rdt_domain *d, int partid); static u64 cache_rdmon(struct rdt_domain *d, void *md_priv); static u64 mbw_rdmon(struct rdt_domain *d, void *md_priv); -static int common_wrmon(struct rdt_domain *d, void *md_priv, bool enable); - -static inline bool is_mon_dyn(u32 mon) -{ - /* - * if rdtgrp->mon.mon has been tagged with value (max_mon_num), - * allocating a monitor in dynamic when getting monitor data. - */ - return (mon == mpam_resctrl_max_mon_num()) ? true : false; -} +static int common_wrmon(struct rdt_domain *d, void *md_priv); static int parse_cbm(char *buf, struct raw_resctrl_resource *r, struct resctrl_staged_config *cfg, hw_closid_t hw_closid); @@ -346,19 +337,12 @@ static u64 cache_rdmon(struct rdt_domain *d, void *md_priv) union mon_data_bits md; struct sync_args args; struct mpam_resctrl_dom *dom; - u32 mon; unsigned long timeout; md.priv = md_priv; - mon = md.u.mon; - - /* Indicates whether allocating a monitor dynamically*/ - if (is_mon_dyn(mon)) - mon = alloc_mon(); - args.partid = md.u.partid; - args.mon = mon; + args.mon = md.u.mon; args.pmg = md.u.pmg; args.match_pmg = true; args.eventid = QOS_L3_OCCUP_EVENT_ID; @@ -380,9 +364,6 @@ static u64 cache_rdmon(struct rdt_domain *d, void *md_priv) WARN_ON(err && (err != -EBUSY)); } while (err == -EBUSY); - if (is_mon_dyn(mon)) - free_mon(mon); - return result; } /* @@ -396,18 +377,12 @@ static u64 mbw_rdmon(struct rdt_domain *d, void *md_priv) union mon_data_bits md; struct sync_args args; struct mpam_resctrl_dom *dom; - u32 mon; unsigned long timeout; md.priv = md_priv; - mon = md.u.mon; - - if (is_mon_dyn(mon)) - mon = alloc_mon(); - args.partid = md.u.partid; - args.mon = mon; + args.mon = md.u.mon; args.pmg = md.u.pmg; args.match_pmg = true; args.eventid = QOS_L3_MBM_LOCAL_EVENT_ID; @@ -429,22 +404,17 @@ static u64 mbw_rdmon(struct rdt_domain *d, void *md_priv) WARN_ON(err && (err != -EBUSY)); } while (err == -EBUSY); - if (is_mon_dyn(mon)) - free_mon(mon); return result; } static int -common_wrmon(struct rdt_domain *d, void *md_priv, bool enable) +common_wrmon(struct rdt_domain *d, void *md_priv) { u64 result; union mon_data_bits md; struct sync_args args; struct mpam_resctrl_dom *dom; - if (!enable) - return -EINVAL; - md.priv = md_priv; args.partid = md.u.partid; args.mon = md.u.mon; @@ -493,7 +463,7 @@ int closid_init(void) num_closid = mpam_sysprops_num_partid(); num_closid = min(num_closid, RESCTRL_MAX_CLOSID); - hw_alloc_times_validate(clos, times, flag); + hw_alloc_times_validate(times, flag); if (flag) num_closid = rounddown(num_closid, 2); @@ -519,7 +489,7 @@ int closid_alloc(void) int pos; u32 times, flag; - hw_alloc_times_validate(clos, times, flag); + hw_alloc_times_validate(times, flag); pos = find_first_bit(closid_free_map, num_closid); if (pos == num_closid) @@ -534,7 +504,7 @@ void closid_free(int closid) { u32 times, flag; - hw_alloc_times_validate(clos, times, flag); + hw_alloc_times_validate(times, flag); bitmap_set(closid_free_map, closid, times); } @@ -1211,15 +1181,7 @@ static struct rftype res_specific_files[] = { .write = resctrl_group_schemata_write, .seq_show = resctrl_group_schemata_show, .fflags = RF_CTRL_BASE, - }, - { - .name = "ctrlmon", - .mode = 0644, - .kf_ops = &resctrl_group_kf_single_ops, - .write = resctrl_group_ctrlmon_write, - .seq_show = resctrl_group_ctrlmon_show, - .fflags = RF_CTRL_BASE, - }, + } }; struct rdt_domain *mpam_find_domain(struct resctrl_resource *r, int id, @@ -1479,3 +1441,28 @@ u16 mpam_resctrl_max_mon_num(void) return mon_num; } + +int resctrl_id_init(void) +{ + int ret; + + ret = closid_init(); + if (ret) + goto out; + + pmg_init(); + mon_init(); + +out: + return ret; +} + +int resctrl_id_alloc(void) +{ + return closid_alloc(); +} + +void resctrl_id_free(int id) +{ + closid_free(id); +} diff --git a/fs/resctrlfs.c b/fs/resctrlfs.c index e4f4f2b35079ffc34f83de014a19018b538b73d5..ebca3fb03e9acc289e9213d0a6e6818a6ade5367 100644 --- a/fs/resctrlfs.c +++ b/fs/resctrlfs.c @@ -313,6 +313,138 @@ void resctrl_group_kn_unlock(struct kernfs_node *kn) } } +static int +mongroup_create_dir(struct kernfs_node *parent_kn, struct resctrl_group *prgrp, + char *name, struct kernfs_node **dest_kn) +{ + struct kernfs_node *kn; + int ret; + + /* create the directory */ + kn = kernfs_create_dir(parent_kn, name, parent_kn->mode, prgrp); + if (IS_ERR(kn)) { + pr_info("%s: create dir %s, error\n", __func__, name); + return PTR_ERR(kn); + } + + if (dest_kn) + *dest_kn = kn; + + /* + * This extra ref will be put in kernfs_remove() and guarantees + * that @rdtgrp->kn is always accessible. + */ + kernfs_get(kn); + + ret = resctrl_group_kn_set_ugid(kn); + if (ret) + goto out_destroy; + + kernfs_activate(kn); + + return 0; + +out_destroy: + kernfs_remove(kn); + return ret; +} + +static void mkdir_mondata_all_prepare_clean(struct resctrl_group *prgrp) +{ + if (prgrp->type == RDTCTRL_GROUP) + return; + + if (prgrp->closid) + resctrl_id_free(prgrp->closid); + if (prgrp->mon.rmid) + free_mon_id(prgrp->mon.rmid); +} + +static int mkdir_mondata_all_prepare(struct resctrl_group *rdtgrp) +{ + int ret = 0; + int mon, mon_id, closid; + + mon = resctrl_lru_request_mon(); + if (mon < 0) { + rdt_last_cmd_puts("out of monitors\n"); + ret = -EINVAL; + goto out; + } + rdtgrp->mon.mon = mon; + + if (rdtgrp->type == RDTMON_GROUP) { + mon_id = alloc_mon_id(); + if (mon_id < 0) { + closid = resctrl_id_alloc(); + if (closid < 0) { + rdt_last_cmd_puts("out of closID\n"); + free_mon_id(mon_id); + ret = -EINVAL; + goto out; + } + rdtgrp->closid = closid; + rdtgrp->mon.rmid = 0; + } else { + struct resctrl_group *prgrp; + + prgrp = rdtgrp->mon.parent; + rdtgrp->closid = prgrp->closid; + rdtgrp->mon.rmid = mon_id; + } + } + +out: + return ret; +} + +/* + * This creates a directory mon_data which contains the monitored data. + * + * mon_data has one directory for each domain whic are named + * in the format mon__. For ex: A mon_data + * with L3 domain looks as below: + * ./mon_data: + * mon_L3_00 + * mon_L3_01 + * mon_L3_02 + * ... + * + * Each domain directory has one file per event: + * ./mon_L3_00/: + * llc_occupancy + * + */ +static int mkdir_mondata_all(struct kernfs_node *parent_kn, + struct resctrl_group *prgrp, + struct kernfs_node **dest_kn) +{ + struct kernfs_node *kn; + int ret; + + /* + * Create the mon_data directory first. + */ + ret = mongroup_create_dir(parent_kn, prgrp, "mon_data", &kn); + if (ret) + return ret; + + if (dest_kn) + *dest_kn = kn; + + ret = resctrl_mkdir_mondata_all_subdir(kn, prgrp); + if (ret) + goto out_destroy; + + kernfs_activate(kn); + + return 0; + +out_destroy: + kernfs_remove(kn); + return ret; +} + static struct dentry *resctrl_mount(struct file_system_type *fs_type, int flags, const char *unused_dev_name, void *data) @@ -365,6 +497,11 @@ static struct dentry *resctrl_mount(struct file_system_type *fs_type, kernfs_get(kn_mongrp); #ifndef CONFIG_ARM64 /* [FIXME] arch specific code */ + ret = mkdir_mondata_all_prepare(&resctrl_group_default); + if (ret < 0) { + dentry = ERR_PTR(ret); + goto out_mongrp; + } ret = mkdir_mondata_all(resctrl_group_default.kn, &resctrl_group_default, &kn_mondata); if (ret) { @@ -562,6 +699,17 @@ static int mkdir_resctrl_prepare(struct kernfs_node *parent_kn, *r = rdtgrp; rdtgrp->mon.parent = prdtgrp; rdtgrp->type = rtype; + + if (rdtgrp->type == RDTCTRL_GROUP) { + ret = resctrl_id_alloc(); + if (ret < 0) { + rdt_last_cmd_puts("out of CLOSIDs\n"); + goto out_unlock; + } + rdtgrp->closid = ret; + ret = 0; + } + INIT_LIST_HEAD(&rdtgrp->mon.crdtgrp_list); /* kernfs creates the directory for rdtgrp */ @@ -595,27 +743,16 @@ static int mkdir_resctrl_prepare(struct kernfs_node *parent_kn, } if (resctrl_mon_capable) { -#ifdef CONFIG_ARM64 - ret = resctrl_mkdir_ctrlmon_mondata(kn, rdtgrp, &rdtgrp->mon.mon_data_kn); - if (ret < 0) { - rdt_last_cmd_puts("out of monitors or PMGs\n"); - goto out_destroy; - } - -#else - ret = alloc_mon_id(); + ret = mkdir_mondata_all_prepare(rdtgrp); if (ret < 0) { - rdt_last_cmd_puts("out of RMIDs\n"); goto out_destroy; } - rdtgrp->mon.rmid = ret; ret = mkdir_mondata_all(kn, rdtgrp, &rdtgrp->mon.mon_data_kn); if (ret) { rdt_last_cmd_puts("kernfs subdir error\n"); - goto out_idfree; + goto out_prepare_clean; } -#endif } kernfs_activate(kn); @@ -624,10 +761,8 @@ static int mkdir_resctrl_prepare(struct kernfs_node *parent_kn, */ return 0; -#ifndef CONFIG_ARM64 -out_idfree: - free_mon_id(rdtgrp->mon.rmid); -#endif +out_prepare_clean: + mkdir_mondata_all_prepare_clean(rdtgrp); out_destroy: kernfs_remove(rdtgrp->kn); out_free_rgrp: @@ -640,7 +775,6 @@ static int mkdir_resctrl_prepare(struct kernfs_node *parent_kn, static void mkdir_resctrl_prepare_clean(struct resctrl_group *rgrp) { kernfs_remove(rgrp->kn); - free_mon_id(rgrp->mon.rmid); kfree(rgrp); } @@ -663,8 +797,6 @@ static int resctrl_group_mkdir_mon(struct kernfs_node *parent_kn, return ret; prgrp = rdtgrp->mon.parent; - rdtgrp->closid = prgrp->closid; - /* * Add the rdtgrp to the list of rdtgrps the parent * ctrl_mon group has to track. @@ -685,7 +817,6 @@ static int resctrl_group_mkdir_ctrl_mon(struct kernfs_node *parent_kn, { struct resctrl_group *rdtgrp; struct kernfs_node *kn; - u32 closid; int ret; ret = mkdir_resctrl_prepare(parent_kn, prgrp_kn, name, mode, RDTCTRL_GROUP, @@ -694,19 +825,10 @@ static int resctrl_group_mkdir_ctrl_mon(struct kernfs_node *parent_kn, return ret; kn = rdtgrp->kn; - ret = resctrl_id_alloc(); - if (ret < 0) { - rdt_last_cmd_puts("out of CLOSIDs\n"); - goto out_common_fail; - } - closid = ret; - ret = 0; - - rdtgrp->closid = closid; ret = resctrl_group_init_alloc(rdtgrp); if (ret < 0) - goto out_id_free; + goto out_common_fail; list_add(&rdtgrp->resctrl_group_list, &resctrl_all_groups); @@ -718,14 +840,13 @@ static int resctrl_group_mkdir_ctrl_mon(struct kernfs_node *parent_kn, ret = mongroup_create_dir(kn, NULL, "mon_groups", NULL); if (ret) { rdt_last_cmd_puts("kernfs subdir error\n"); - goto out_id_free; + goto out_list_del; } } goto out_unlock; -out_id_free: - resctrl_id_free(closid); +out_list_del: list_del(&rdtgrp->resctrl_group_list); out_common_fail: mkdir_resctrl_prepare_clean(rdtgrp); @@ -781,10 +902,6 @@ static void resctrl_group_rm_mon(struct resctrl_group *rdtgrp, struct resctrl_group *prdtgrp = rdtgrp->mon.parent; int cpu; -#ifdef CONFIG_ARM64 /* [FIXME] arch specific code */ - free_mon(rdtgrp->mon.mon); -#endif - /* Give any tasks back to the parent group */ resctrl_move_group_tasks(rdtgrp, prdtgrp, tmpmask); @@ -862,11 +979,6 @@ static void resctrl_group_rm_ctrl(struct resctrl_group *rdtgrp, cpumask_var_t tm static int resctrl_group_rmdir_ctrl(struct kernfs_node *kn, struct resctrl_group *rdtgrp, cpumask_var_t tmpmask) { -#ifdef CONFIG_ARM64 /* [FIXME] arch specific code */ - if (rdtgrp->flags & RDT_CTRLMON) - return -EPERM; -#endif - resctrl_group_rm_ctrl(rdtgrp, tmpmask); /*