]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - arch/x86/kernel/cpu/intel_cacheinfo.c
x86, cacheinfo: Carve out L3 cache slot accessors
[net-next-2.6.git] / arch / x86 / kernel / cpu / intel_cacheinfo.c
index 33eae2062cf55b06c864ad8511062440f37f10fe..898c2f4eab88b28cb74719b943cad01ec06efa29 100644 (file)
@@ -347,8 +347,8 @@ static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node)
        return l3;
 }
 
-static void __cpuinit
-amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
+static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf,
+                                          int index)
 {
        int node;
 
@@ -396,20 +396,39 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
        this_leaf->l3 = l3_caches[node];
 }
 
+/*
+ * check whether a slot used for disabling an L3 index is occupied.
+ * @l3: L3 cache descriptor
+ * @slot: slot number (0..1)
+ *
+ * @returns: the disabled index if used or negative value if slot free.
+ */
+int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot)
+{
+       unsigned int reg = 0;
+
+       pci_read_config_dword(l3->dev, 0x1BC + slot * 4, &reg);
+
+       /* check whether this slot is activated already */
+       if (reg & (3UL << 30))
+               return reg & 0xfff;
+
+       return -1;
+}
+
 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
                                  unsigned int slot)
 {
-       struct pci_dev *dev = this_leaf->l3->dev;
-       unsigned int reg = 0;
+       int index;
 
        if (!this_leaf->l3 || !this_leaf->l3->can_disable)
                return -EINVAL;
 
-       if (!dev)
-               return -EINVAL;
+       index = amd_get_l3_disable_slot(this_leaf->l3, slot);
+       if (index >= 0)
+               return sprintf(buf, "%d\n", index);
 
-       pci_read_config_dword(dev, 0x1BC + slot * 4, &reg);
-       return sprintf(buf, "0x%08x\n", reg);
+       return sprintf(buf, "FREE\n");
 }
 
 #define SHOW_CACHE_DISABLE(slot)                                       \
@@ -451,37 +470,74 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
        }
 }
 
-
-static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
-                                  const char *buf, size_t count,
-                                  unsigned int slot)
+/*
+ * disable a L3 cache index by using a disable-slot
+ *
+ * @l3:    L3 cache descriptor
+ * @cpu:   A CPU on the node containing the L3 cache
+ * @slot:  slot number (0..1)
+ * @index: index to disable
+ *
+ * @return: 0 on success, error status on failure
+ */
+int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot,
+                           unsigned long index)
 {
-       struct pci_dev *dev = this_leaf->l3->dev;
-       int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
-       unsigned long val = 0;
+       int ret = 0;
 
 #define SUBCACHE_MASK  (3UL << 20)
 #define SUBCACHE_INDEX 0xfff
 
-       if (!this_leaf->l3 || !this_leaf->l3->can_disable)
+       /*
+        * check whether this slot is already used or
+        * the index is already disabled
+        */
+       ret = amd_get_l3_disable_slot(l3, slot);
+       if (ret >= 0)
                return -EINVAL;
 
+       /*
+        * check whether the other slot has disabled the
+        * same index already
+        */
+       if (index == amd_get_l3_disable_slot(l3, !slot))
+               return -EINVAL;
+
+       /* do not allow writes outside of allowed bits */
+       if ((index & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) ||
+           ((index & SUBCACHE_INDEX) > l3->indices))
+               return -EINVAL;
+
+       amd_l3_disable_index(l3, cpu, slot, index);
+
+       return 0;
+}
+
+static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
+                                 const char *buf, size_t count,
+                                 unsigned int slot)
+{
+       unsigned long val = 0;
+       int cpu, err = 0;
+
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (!dev)
+       if (!this_leaf->l3 || !this_leaf->l3->can_disable)
                return -EINVAL;
 
-       if (strict_strtoul(buf, 10, &val) < 0)
-               return -EINVAL;
+       cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
 
-       /* do not allow writes outside of allowed bits */
-       if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) ||
-           ((val & SUBCACHE_INDEX) > this_leaf->l3->indices))
+       if (strict_strtoul(buf, 10, &val) < 0)
                return -EINVAL;
 
-       amd_l3_disable_index(this_leaf->l3, cpu, slot, val);
-
+       err = amd_set_l3_disable_slot(this_leaf->l3, cpu, slot, val);
+       if (err) {
+               if (err == -EEXIST)
+                       printk(KERN_WARNING "L3 disable slot %d in use!\n",
+                                           slot);
+               return err;
+       }
        return count;
 }
 
@@ -502,7 +558,7 @@ static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
 
 #else  /* CONFIG_CPU_SUP_AMD */
 static void __cpuinit
-amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
+amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, int index)
 {
 };
 #endif /* CONFIG_CPU_SUP_AMD */
@@ -518,7 +574,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index,
 
        if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
                amd_cpuid4(index, &eax, &ebx, &ecx);
-               amd_check_l3_disable(index, this_leaf);
+               amd_check_l3_disable(this_leaf, index);
        } else {
                cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
        }