Commit d2946041 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Ingo Molnar

x86: cache_info: Kill the atomic allocation in amd_init_l3_cache()

It's not a good reason to allocate memory in the smp function call
just because someone thought it's the most conveniant place.

The AMD L3 data is coupled to the northbridge info by a pointer to the
corresponding north bridge data. So allocating it with the northbridge
data and referencing the northbridge in the cache_info code instead
uses less memory and gets rid of that atomic allocation hack in the
smp function call.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarBorislav Petkov <borislav.petkov@amd.com>
Cc: Hans Rosenfeld <hans.rosenfeld@amd.com>
Cc: Andreas Herrmann <andreas.herrmann3@amd.com>
Cc: Mike Travis <travis@sgi.com>
Link: http://lkml.kernel.org/r/20110723212626.688229918@linutronix.deSigned-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent b7d11a76
...@@ -19,9 +19,15 @@ extern int amd_numa_init(void); ...@@ -19,9 +19,15 @@ extern int amd_numa_init(void);
extern int amd_get_subcaches(int); extern int amd_get_subcaches(int);
extern int amd_set_subcaches(int, int); extern int amd_set_subcaches(int, int);
struct amd_l3_cache {
unsigned indices;
u8 subcaches[4];
};
struct amd_northbridge { struct amd_northbridge {
struct pci_dev *misc; struct pci_dev *misc;
struct pci_dev *link; struct pci_dev *link;
struct amd_l3_cache l3_cache;
}; };
struct amd_northbridge_info { struct amd_northbridge_info {
......
...@@ -151,18 +151,12 @@ union _cpuid4_leaf_ecx { ...@@ -151,18 +151,12 @@ union _cpuid4_leaf_ecx {
u32 full; u32 full;
}; };
struct amd_l3_cache {
struct amd_northbridge *nb;
unsigned indices;
u8 subcaches[4];
};
struct _cpuid4_info_regs { struct _cpuid4_info_regs {
union _cpuid4_leaf_eax eax; union _cpuid4_leaf_eax eax;
union _cpuid4_leaf_ebx ebx; union _cpuid4_leaf_ebx ebx;
union _cpuid4_leaf_ecx ecx; union _cpuid4_leaf_ecx ecx;
unsigned long size; unsigned long size;
struct amd_l3_cache *l3; struct amd_northbridge *nb;
}; };
struct _cpuid4_info { struct _cpuid4_info {
...@@ -309,12 +303,13 @@ struct _cache_attr { ...@@ -309,12 +303,13 @@ struct _cache_attr {
/* /*
* L3 cache descriptors * L3 cache descriptors
*/ */
static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb)
{ {
struct amd_l3_cache *l3 = &nb->l3_cache;
unsigned int sc0, sc1, sc2, sc3; unsigned int sc0, sc1, sc2, sc3;
u32 val = 0; u32 val = 0;
pci_read_config_dword(l3->nb->misc, 0x1C4, &val); pci_read_config_dword(nb->misc, 0x1C4, &val);
/* calculate subcache sizes */ /* calculate subcache sizes */
l3->subcaches[0] = sc0 = !(val & BIT(0)); l3->subcaches[0] = sc0 = !(val & BIT(0));
...@@ -328,33 +323,16 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) ...@@ -328,33 +323,16 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf,
int index) int index)
{ {
static struct amd_l3_cache *__cpuinitdata l3_caches;
int node; int node;
/* only for L3, and not in virtualized environments */ /* only for L3, and not in virtualized environments */
if (index < 3 || amd_nb_num() == 0) if (index < 3)
return; return;
/*
* Strictly speaking, the amount in @size below is leaked since it is
* never freed but this is done only on shutdown so it doesn't matter.
*/
if (!l3_caches) {
int size = amd_nb_num() * sizeof(struct amd_l3_cache);
l3_caches = kzalloc(size, GFP_ATOMIC);
if (!l3_caches)
return;
}
node = amd_get_nb_id(smp_processor_id()); node = amd_get_nb_id(smp_processor_id());
this_leaf->nb = node_to_amd_nb(node);
if (!l3_caches[node].nb) { if (this_leaf->nb && !this_leaf->nb->l3_cache.indices)
l3_caches[node].nb = node_to_amd_nb(node); amd_calc_l3_indices(this_leaf->nb);
amd_calc_l3_indices(&l3_caches[node]);
}
this_leaf->l3 = &l3_caches[node];
} }
/* /*
...@@ -364,11 +342,11 @@ static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, ...@@ -364,11 +342,11 @@ static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf,
* *
* @returns: the disabled index if used or negative value if slot free. * @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) int amd_get_l3_disable_slot(struct amd_northbridge *nb, unsigned slot)
{ {
unsigned int reg = 0; unsigned int reg = 0;
pci_read_config_dword(l3->nb->misc, 0x1BC + slot * 4, &reg); pci_read_config_dword(nb->misc, 0x1BC + slot * 4, &reg);
/* check whether this slot is activated already */ /* check whether this slot is activated already */
if (reg & (3UL << 30)) if (reg & (3UL << 30))
...@@ -382,10 +360,10 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, ...@@ -382,10 +360,10 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
{ {
int index; int index;
if (!this_leaf->base.l3 || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
return -EINVAL; return -EINVAL;
index = amd_get_l3_disable_slot(this_leaf->base.l3, slot); index = amd_get_l3_disable_slot(this_leaf->base.nb, slot);
if (index >= 0) if (index >= 0)
return sprintf(buf, "%d\n", index); return sprintf(buf, "%d\n", index);
...@@ -402,7 +380,7 @@ show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf, \ ...@@ -402,7 +380,7 @@ show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf, \
SHOW_CACHE_DISABLE(0) SHOW_CACHE_DISABLE(0)
SHOW_CACHE_DISABLE(1) SHOW_CACHE_DISABLE(1)
static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu,
unsigned slot, unsigned long idx) unsigned slot, unsigned long idx)
{ {
int i; int i;
...@@ -415,10 +393,10 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, ...@@ -415,10 +393,10 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
u32 reg = idx | (i << 20); u32 reg = idx | (i << 20);
if (!l3->subcaches[i]) if (!nb->l3_cache.subcaches[i])
continue; continue;
pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
/* /*
* We need to WBINVD on a core on the node containing the L3 * We need to WBINVD on a core on the node containing the L3
...@@ -428,7 +406,7 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, ...@@ -428,7 +406,7 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
wbinvd_on_cpu(cpu); wbinvd_on_cpu(cpu);
reg |= BIT(31); reg |= BIT(31);
pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
} }
} }
...@@ -442,24 +420,24 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, ...@@ -442,24 +420,24 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
* *
* @return: 0 on success, error status on failure * @return: 0 on success, error status on failure
*/ */
int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot, int amd_set_l3_disable_slot(struct amd_northbridge *nb, int cpu, unsigned slot,
unsigned long index) unsigned long index)
{ {
int ret = 0; int ret = 0;
/* check if @slot is already used or the index is already disabled */ /* check if @slot is already used or the index is already disabled */
ret = amd_get_l3_disable_slot(l3, slot); ret = amd_get_l3_disable_slot(nb, slot);
if (ret >= 0) if (ret >= 0)
return -EINVAL; return -EINVAL;
if (index > l3->indices) if (index > nb->l3_cache.indices)
return -EINVAL; return -EINVAL;
/* check whether the other slot has disabled the same index already */ /* check whether the other slot has disabled the same index already */
if (index == amd_get_l3_disable_slot(l3, !slot)) if (index == amd_get_l3_disable_slot(nb, !slot))
return -EINVAL; return -EINVAL;
amd_l3_disable_index(l3, cpu, slot, index); amd_l3_disable_index(nb, cpu, slot, index);
return 0; return 0;
} }
...@@ -474,7 +452,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, ...@@ -474,7 +452,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (!this_leaf->base.l3 || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
return -EINVAL; return -EINVAL;
cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
...@@ -482,7 +460,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, ...@@ -482,7 +460,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
if (strict_strtoul(buf, 10, &val) < 0) if (strict_strtoul(buf, 10, &val) < 0)
return -EINVAL; return -EINVAL;
err = amd_set_l3_disable_slot(this_leaf->base.l3, cpu, slot, val); err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val);
if (err) { if (err) {
if (err == -EEXIST) if (err == -EEXIST)
printk(KERN_WARNING "L3 disable slot %d in use!\n", printk(KERN_WARNING "L3 disable slot %d in use!\n",
...@@ -511,7 +489,7 @@ static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, ...@@ -511,7 +489,7 @@ static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
static ssize_t static ssize_t
show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu) show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu)
{ {
if (!this_leaf->base.l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
return -EINVAL; return -EINVAL;
return sprintf(buf, "%x\n", amd_get_subcaches(cpu)); return sprintf(buf, "%x\n", amd_get_subcaches(cpu));
...@@ -526,7 +504,7 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count, ...@@ -526,7 +504,7 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (!this_leaf->base.l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
return -EINVAL; return -EINVAL;
if (strict_strtoul(buf, 16, &val) < 0) if (strict_strtoul(buf, 16, &val) < 0)
...@@ -1118,7 +1096,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) ...@@ -1118,7 +1096,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
ktype_cache.default_attrs = default_attrs; ktype_cache.default_attrs = default_attrs;
#ifdef CONFIG_AMD_NB #ifdef CONFIG_AMD_NB
if (this_leaf->base.l3) if (this_leaf->base.nb)
ktype_cache.default_attrs = amd_l3_attrs(); ktype_cache.default_attrs = amd_l3_attrs();
#endif #endif
retval = kobject_init_and_add(&(this_object->kobj), retval = kobject_init_and_add(&(this_object->kobj),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment