This patch does some changes to get ready to handle more resources like
Memory b/w allocation(MBA).

-Update the control registers only when user changes the controls(cbm for
Cache resources and Mem b/w for memory). Hence not sending IPIs on all
domains when user updates the control vals.
-Introduce next_enabled_resource rather than looping through all
resources while parsing each schemata line. The order of resources
should be anyways the same as the root schemata.
-Return error as soon as we detect a resource not entering all domain
values in schemata rather than waiting till we parse all resources.

Signed-off-by: Vikas Shivappa <[email protected]>
---
 arch/x86/include/asm/intel_rdt.h         | 16 +++++++++++++
 arch/x86/kernel/cpu/intel_rdt_schemata.c | 40 +++++++++++++++++---------------
 2 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h
index 9f66bf5..e1f8acb 100644
--- a/arch/x86/include/asm/intel_rdt.h
+++ b/arch/x86/include/asm/intel_rdt.h
@@ -156,6 +156,22 @@ enum {
             r++)                                                             \
                if (r->enabled)
 
+/*
+ * Parameter r must be NULL or pointing to
+ * a valid rdt_resource_all entry.
+ * Points r to the next enabled RDT resource at the end.
+ */
+#define next_enabled_rdt_resource(r)                                   \
+do {                                                                   \
+       if (!r)                                                         \
+               r = rdt_resources_all;                                  \
+       else                                                            \
+               r++;                                                    \
+       for (; r < rdt_resources_all + RDT_NUM_RESOURCES; r++)          \
+               if (r->enabled)                                         \
+                       break;                                          \
+} while (0)
+
 /* CPUID.(EAX=10H, ECX=ResID=1).EAX */
 union cpuid_0x10_1_eax {
        struct {
diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c 
b/arch/x86/kernel/cpu/intel_rdt_schemata.c
index c50f742..054d771 100644
--- a/arch/x86/kernel/cpu/intel_rdt_schemata.c
+++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c
@@ -94,6 +94,10 @@ static int parse_line(char *line, struct rdt_resource *r)
                        return -EINVAL;
        }
 
+       /* Incorrect number of domains in the line */
+       if (r->num_tmp_ctrl != r->num_domains)
+               return -EINVAL;
+
        /* Any garbage at the end of the line? */
        if (line && line[0])
                return -EINVAL;
@@ -114,9 +118,16 @@ static int update_domains(struct rdt_resource *r, int 
closid)
        msr_param.high = msr_param.low + 1;
        msr_param.res = r;
 
+       /*
+        * Only update the domains that user has changed.
+        * There by avoiding unnecessary IPIs.
+        */
        list_for_each_entry(d, &r->domains, list) {
-               cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
-               d->ctrl_val[msr_param.low] = r->tmp_ctrl[idx++];
+               if (d->ctrl_val[msr_param.low] != r->tmp_ctrl[idx]) {
+                       cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
+                       d->ctrl_val[msr_param.low] = r->tmp_ctrl[idx];
+               }
+               idx++;
        }
        cpu = get_cpu();
        /* Update CBM on this cpu if it's in cpu_mask. */
@@ -164,30 +175,21 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file 
*of,
                r->num_tmp_ctrl = 0;
        }
 
+       r = NULL;
        while ((tok = strsep(&buf, "\n")) != NULL) {
                resname = strsep(&tok, ":");
                if (!tok) {
                        ret = -EINVAL;
                        goto out;
                }
-               for_each_enabled_rdt_resource(r) {
-                       if (!strcmp(resname, r->name) &&
-                           closid < r->num_closid) {
-                               ret = parse_line(tok, r);
-                               if (ret)
-                                       goto out;
-                               break;
-                       }
-               }
-               if (!r->name) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-       }
 
-       /* Did the parser find all the masks we need? */
-       for_each_enabled_rdt_resource(r) {
-               if (r->num_tmp_ctrl != r->num_domains) {
+               next_enabled_rdt_resource(r);
+
+               if (!strcmp(resname, r->name)) {
+                       ret = parse_line(tok, r);
+                       if (ret)
+                               goto out;
+               } else {
                        ret = -EINVAL;
                        goto out;
                }
-- 
1.9.1

Reply via email to