Skip to content

Commit

Permalink
CPU: Introduce ARCH_HAS_CPU_AUTOPROBE and X86 parts
Browse files Browse the repository at this point in the history
This patch is based on Andi Kleen's work:
Implement autoprobing/loading of modules serving CPU
specific features (x86cpu autoloading).

And Kay Siever's work to get rid of sysdev cpu structures
and making use of struct device instead.

Before, the cpuid driver had to be loaded to get the x86cpu
autoloading feature. With this patch autoloading works through
the /sys/devices/system/cpu object

Cc: Kay Sievers <kay.sievers@vrfy.org>
Cc: Dave Jones <davej@redhat.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Huang Ying <ying.huang@intel.com>
Cc: Len Brown <lenb@kernel.org>
Acked-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Thomas Renninger <trenn@suse.de>
Acked-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Thomas Renninger authored and Greg Kroah-Hartman committed Jan 27, 2012
1 parent 78ff123 commit fad12ac
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 58 deletions.
3 changes: 3 additions & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ config ARCH_HAS_DEFAULT_IDLE
config ARCH_HAS_CACHE_LINE_SIZE
def_bool y

config ARCH_HAS_CPU_AUTOPROBE
def_bool y

config HAVE_SETUP_PER_CPU_AREA
def_bool y

Expand Down
44 changes: 44 additions & 0 deletions arch/x86/kernel/cpu/match.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <asm/processor.h>
#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/slab.h>

/**
* x86_match_cpu - match current CPU again an array of x86_cpu_ids
Expand Down Expand Up @@ -46,3 +47,46 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
return NULL;
}
EXPORT_SYMBOL(x86_match_cpu);

ssize_t arch_print_cpu_modalias(struct device *dev,
struct device_attribute *attr,
char *bufptr)
{
int size = PAGE_SIZE;
int i, n;
char *buf = bufptr;

n = snprintf(buf, size, "x86cpu:vendor:%04X:family:%04X:"
"model:%04X:feature:",
boot_cpu_data.x86_vendor,
boot_cpu_data.x86,
boot_cpu_data.x86_model);
size -= n;
buf += n;
size -= 2;
for (i = 0; i < NCAPINTS*32; i++) {
if (boot_cpu_has(i)) {
n = snprintf(buf, size, ",%04X", i);
if (n < 0) {
WARN(1, "x86 features overflow page\n");
break;
}
size -= n;
buf += n;
}
}
*buf++ = ',';
*buf++ = '\n';
return buf - bufptr;
}

int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
{
char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (buf) {
arch_print_cpu_modalias(NULL, NULL, buf);
add_uevent_var(env, "MODALIAS=%s", buf);
kfree(buf);
}
return 0;
}
59 changes: 1 addition & 58 deletions arch/x86/kernel/cpuid.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
#include <linux/notifier.h>
#include <linux/uaccess.h>
#include <linux/gfp.h>
#include <linux/slab.h>

#include <asm/processor.h>
#include <asm/msr.h>
Expand Down Expand Up @@ -139,57 +138,13 @@ static const struct file_operations cpuid_fops = {
.open = cpuid_open,
};

static ssize_t print_cpu_modalias(struct device *dev,
struct device_attribute *attr,
char *bufptr)
{
int size = PAGE_SIZE;
int i, n;
char *buf = bufptr;

n = snprintf(buf, size, "x86cpu:vendor:%04X:family:"
"%04X:model:%04X:feature:",
boot_cpu_data.x86_vendor,
boot_cpu_data.x86,
boot_cpu_data.x86_model);
size -= n;
buf += n;
size -= 2;
for (i = 0; i < NCAPINTS*32; i++) {
if (boot_cpu_has(i)) {
n = snprintf(buf, size, ",%04X", i);
if (n < 0) {
WARN(1, "x86 features overflow page\n");
break;
}
size -= n;
buf += n;
}
}
*buf++ = ',';
*buf++ = '\n';
return buf - bufptr;
}

static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);

static __cpuinit int cpuid_device_create(int cpu)
{
struct device *dev;
int err;

dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), NULL,
"cpu%d", cpu);
if (IS_ERR(dev))
return PTR_ERR(dev);

err = device_create_file(dev, &dev_attr_modalias);
if (err) {
/* keep device around on error. attribute is optional. */
err = 0;
}

return 0;
return IS_ERR(dev) ? PTR_ERR(dev) : 0;
}

static void cpuid_device_destroy(int cpu)
Expand Down Expand Up @@ -227,17 +182,6 @@ static char *cpuid_devnode(struct device *dev, umode_t *mode)
return kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt));
}

static int cpuid_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
{
char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (buf) {
print_cpu_modalias(NULL, NULL, buf);
add_uevent_var(env, "MODALIAS=%s", buf);
kfree(buf);
}
return 0;
}

static int __init cpuid_init(void)
{
int i, err = 0;
Expand All @@ -256,7 +200,6 @@ static int __init cpuid_init(void)
goto out_chrdev;
}
cpuid_class->devnode = cpuid_devnode;
cpuid_class->dev_uevent = cpuid_dev_uevent;
for_each_online_cpu(i) {
err = cpuid_device_create(i);
if (err != 0)
Expand Down
11 changes: 11 additions & 0 deletions drivers/base/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/device.h>
#include <linux/node.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/percpu.h>

#include "base.h"
Expand Down Expand Up @@ -223,6 +224,9 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
cpu->node_id = cpu_to_node(num);
cpu->dev.id = num;
cpu->dev.bus = &cpu_subsys;
#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
cpu->dev.bus->uevent = arch_cpu_uevent;
#endif
error = device_register(&cpu->dev);
if (!error && cpu->hotpluggable)
register_cpu_control(cpu);
Expand All @@ -247,6 +251,10 @@ struct device *get_cpu_device(unsigned cpu)
}
EXPORT_SYMBOL_GPL(get_cpu_device);

#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
#endif

static struct attribute *cpu_root_attrs[] = {
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
&dev_attr_probe.attr,
Expand All @@ -257,6 +265,9 @@ static struct attribute *cpu_root_attrs[] = {
&cpu_attrs[2].attr.attr,
&dev_attr_kernel_max.attr,
&dev_attr_offline.attr,
#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
&dev_attr_modalias.attr,
#endif
NULL
};

Expand Down
7 changes: 7 additions & 0 deletions include/linux/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ extern ssize_t arch_cpu_release(const char *, size_t);
#endif
struct notifier_block;

#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env);
extern ssize_t arch_print_cpu_modalias(struct device *dev,
struct device_attribute *attr,
char *bufptr);
#endif

/*
* CPU notifier priorities.
*/
Expand Down

0 comments on commit fad12ac

Please sign in to comment.