diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/Makefile | 1 | ||||
-rw-r--r-- | drivers/base/base.h | 4 | ||||
-rw-r--r-- | drivers/base/bus.c | 3 | ||||
-rw-r--r-- | drivers/base/memory.c | 2 | ||||
-rw-r--r-- | drivers/base/power/resume.c | 3 | ||||
-rw-r--r-- | drivers/base/power/shutdown.c | 2 | ||||
-rw-r--r-- | drivers/base/power/suspend.c | 3 | ||||
-rw-r--r-- | drivers/base/power/sysfs.c | 24 | ||||
-rw-r--r-- | drivers/base/sys.c | 3 | ||||
-rw-r--r-- | drivers/base/topology.c | 148 |
10 files changed, 179 insertions, 14 deletions
diff --git a/drivers/base/Makefile b/drivers/base/Makefile index f12898d53078..e99471d3232b 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile | |||
@@ -8,6 +8,7 @@ obj-y += power/ | |||
8 | obj-$(CONFIG_FW_LOADER) += firmware_class.o | 8 | obj-$(CONFIG_FW_LOADER) += firmware_class.o |
9 | obj-$(CONFIG_NUMA) += node.o | 9 | obj-$(CONFIG_NUMA) += node.o |
10 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o | 10 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o |
11 | obj-$(CONFIG_SMP) += topology.o | ||
11 | 12 | ||
12 | ifeq ($(CONFIG_DEBUG_DRIVER),y) | 13 | ifeq ($(CONFIG_DEBUG_DRIVER),y) |
13 | EXTRA_CFLAGS += -DDEBUG | 14 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/base/base.h b/drivers/base/base.h index e3b548d46cff..5735b38582d0 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -19,6 +19,10 @@ extern void bus_remove_driver(struct device_driver *); | |||
19 | extern void driver_detach(struct device_driver * drv); | 19 | extern void driver_detach(struct device_driver * drv); |
20 | extern int driver_probe_device(struct device_driver *, struct device *); | 20 | extern int driver_probe_device(struct device_driver *, struct device *); |
21 | 21 | ||
22 | extern void sysdev_shutdown(void); | ||
23 | extern int sysdev_suspend(pm_message_t state); | ||
24 | extern int sysdev_resume(void); | ||
25 | |||
22 | static inline struct class_device *to_class_dev(struct kobject *obj) | 26 | static inline struct class_device *to_class_dev(struct kobject *obj) |
23 | { | 27 | { |
24 | return container_of(obj, struct class_device, kobj); | 28 | return container_of(obj, struct class_device, kobj); |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 29f6af554e71..c3141565d59d 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -133,6 +133,8 @@ static struct kobj_type ktype_bus = { | |||
133 | decl_subsys(bus, &ktype_bus, NULL); | 133 | decl_subsys(bus, &ktype_bus, NULL); |
134 | 134 | ||
135 | 135 | ||
136 | #ifdef CONFIG_HOTPLUG | ||
137 | |||
136 | /* Manually detach a device from its associated driver. */ | 138 | /* Manually detach a device from its associated driver. */ |
137 | static int driver_helper(struct device *dev, void *data) | 139 | static int driver_helper(struct device *dev, void *data) |
138 | { | 140 | { |
@@ -193,6 +195,7 @@ static ssize_t driver_bind(struct device_driver *drv, | |||
193 | } | 195 | } |
194 | static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); | 196 | static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); |
195 | 197 | ||
198 | #endif | ||
196 | 199 | ||
197 | static struct device * next_device(struct klist_iter * i) | 200 | static struct device * next_device(struct klist_iter * i) |
198 | { | 201 | { |
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index d1a05224627e..105a0d61eb1f 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
@@ -303,7 +303,7 @@ static int block_size_init(void) | |||
303 | */ | 303 | */ |
304 | #ifdef CONFIG_ARCH_MEMORY_PROBE | 304 | #ifdef CONFIG_ARCH_MEMORY_PROBE |
305 | static ssize_t | 305 | static ssize_t |
306 | memory_probe_store(struct class *class, const char __user *buf, size_t count) | 306 | memory_probe_store(struct class *class, const char *buf, size_t count) |
307 | { | 307 | { |
308 | u64 phys_addr; | 308 | u64 phys_addr; |
309 | int ret; | 309 | int ret; |
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index 0a7aa07b9a2a..317edbf0feca 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c | |||
@@ -9,10 +9,9 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include "../base.h" | ||
12 | #include "power.h" | 13 | #include "power.h" |
13 | 14 | ||
14 | extern int sysdev_resume(void); | ||
15 | |||
16 | 15 | ||
17 | /** | 16 | /** |
18 | * resume_device - Restore state for one device. | 17 | * resume_device - Restore state for one device. |
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index c2475f3134ea..8826a5b6673e 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
13 | #include <asm/semaphore.h> | 13 | #include <asm/semaphore.h> |
14 | 14 | ||
15 | #include "../base.h" | ||
15 | #include "power.h" | 16 | #include "power.h" |
16 | 17 | ||
17 | #define to_dev(node) container_of(node, struct device, kobj.entry) | 18 | #define to_dev(node) container_of(node, struct device, kobj.entry) |
@@ -28,7 +29,6 @@ extern struct subsystem devices_subsys; | |||
28 | * they only get one called once when interrupts are disabled. | 29 | * they only get one called once when interrupts are disabled. |
29 | */ | 30 | */ |
30 | 31 | ||
31 | extern int sysdev_shutdown(void); | ||
32 | 32 | ||
33 | /** | 33 | /** |
34 | * device_shutdown - call ->shutdown() on each device to shutdown. | 34 | * device_shutdown - call ->shutdown() on each device to shutdown. |
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 50501764d050..8660779fb288 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c | |||
@@ -9,10 +9,9 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include "../base.h" | ||
12 | #include "power.h" | 13 | #include "power.h" |
13 | 14 | ||
14 | extern int sysdev_suspend(pm_message_t state); | ||
15 | |||
16 | /* | 15 | /* |
17 | * The entries in the dpm_active list are in a depth first order, simply | 16 | * The entries in the dpm_active list are in a depth first order, simply |
18 | * because children are guaranteed to be discovered after parents, and | 17 | * because children are guaranteed to be discovered after parents, and |
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index f3a0c562bcb5..40d7242a07c1 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
@@ -27,22 +27,30 @@ | |||
27 | 27 | ||
28 | static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf) | 28 | static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf) |
29 | { | 29 | { |
30 | return sprintf(buf, "%u\n", dev->power.power_state.event); | 30 | if (dev->power.power_state.event) |
31 | return sprintf(buf, "2\n"); | ||
32 | else | ||
33 | return sprintf(buf, "0\n"); | ||
31 | } | 34 | } |
32 | 35 | ||
33 | static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n) | 36 | static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n) |
34 | { | 37 | { |
35 | pm_message_t state; | 38 | pm_message_t state; |
36 | char * rest; | 39 | int error = -EINVAL; |
37 | int error = 0; | ||
38 | 40 | ||
39 | state.event = simple_strtoul(buf, &rest, 10); | 41 | state.event = PM_EVENT_SUSPEND; |
40 | if (*rest) | 42 | /* Older apps expected to write "3" here - confused with PCI D3 */ |
41 | return -EINVAL; | 43 | if ((n == 1) && !strcmp(buf, "3")) |
42 | if (state.event) | ||
43 | error = dpm_runtime_suspend(dev, state); | 44 | error = dpm_runtime_suspend(dev, state); |
44 | else | 45 | |
46 | if ((n == 1) && !strcmp(buf, "2")) | ||
47 | error = dpm_runtime_suspend(dev, state); | ||
48 | |||
49 | if ((n == 1) && !strcmp(buf, "0")) { | ||
45 | dpm_runtime_resume(dev); | 50 | dpm_runtime_resume(dev); |
51 | error = 0; | ||
52 | } | ||
53 | |||
46 | return error ? error : n; | 54 | return error ? error : n; |
47 | } | 55 | } |
48 | 56 | ||
diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 66ed8f2fece5..6fc23ab127bd 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c | |||
@@ -21,8 +21,11 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/string.h> | 22 | #include <linux/string.h> |
23 | #include <linux/pm.h> | 23 | #include <linux/pm.h> |
24 | #include <linux/device.h> | ||
24 | #include <asm/semaphore.h> | 25 | #include <asm/semaphore.h> |
25 | 26 | ||
27 | #include "base.h" | ||
28 | |||
26 | extern struct subsystem devices_subsys; | 29 | extern struct subsystem devices_subsys; |
27 | 30 | ||
28 | #define to_sysdev(k) container_of(k, struct sys_device, kobj) | 31 | #define to_sysdev(k) container_of(k, struct sys_device, kobj) |
diff --git a/drivers/base/topology.c b/drivers/base/topology.c new file mode 100644 index 000000000000..915810f6237e --- /dev/null +++ b/drivers/base/topology.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * driver/base/topology.c - Populate sysfs with cpu topology information | ||
3 | * | ||
4 | * Written by: Zhang Yanmin, Intel Corporation | ||
5 | * | ||
6 | * Copyright (C) 2006, Intel Corp. | ||
7 | * | ||
8 | * All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
18 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
19 | * details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | #include <linux/sysdev.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/cpu.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/topology.h> | ||
32 | |||
33 | #define define_one_ro(_name) \ | ||
34 | static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) | ||
35 | |||
36 | #define define_id_show_func(name) \ | ||
37 | static ssize_t show_##name(struct sys_device *dev, char *buf) \ | ||
38 | { \ | ||
39 | unsigned int cpu = dev->id; \ | ||
40 | return sprintf(buf, "%d\n", topology_##name(cpu)); \ | ||
41 | } | ||
42 | |||
43 | #define define_siblings_show_func(name) \ | ||
44 | static ssize_t show_##name(struct sys_device *dev, char *buf) \ | ||
45 | { \ | ||
46 | ssize_t len = -1; \ | ||
47 | unsigned int cpu = dev->id; \ | ||
48 | len = cpumask_scnprintf(buf, NR_CPUS+1, topology_##name(cpu)); \ | ||
49 | return (len + sprintf(buf + len, "\n")); \ | ||
50 | } | ||
51 | |||
52 | #ifdef topology_physical_package_id | ||
53 | define_id_show_func(physical_package_id); | ||
54 | define_one_ro(physical_package_id); | ||
55 | #define ref_physical_package_id_attr &attr_physical_package_id.attr, | ||
56 | #else | ||
57 | #define ref_physical_package_id_attr | ||
58 | #endif | ||
59 | |||
60 | #ifdef topology_core_id | ||
61 | define_id_show_func(core_id); | ||
62 | define_one_ro(core_id); | ||
63 | #define ref_core_id_attr &attr_core_id.attr, | ||
64 | #else | ||
65 | #define ref_core_id_attr | ||
66 | #endif | ||
67 | |||
68 | #ifdef topology_thread_siblings | ||
69 | define_siblings_show_func(thread_siblings); | ||
70 | define_one_ro(thread_siblings); | ||
71 | #define ref_thread_siblings_attr &attr_thread_siblings.attr, | ||
72 | #else | ||
73 | #define ref_thread_siblings_attr | ||
74 | #endif | ||
75 | |||
76 | #ifdef topology_core_siblings | ||
77 | define_siblings_show_func(core_siblings); | ||
78 | define_one_ro(core_siblings); | ||
79 | #define ref_core_siblings_attr &attr_core_siblings.attr, | ||
80 | #else | ||
81 | #define ref_core_siblings_attr | ||
82 | #endif | ||
83 | |||
84 | static struct attribute *default_attrs[] = { | ||
85 | ref_physical_package_id_attr | ||
86 | ref_core_id_attr | ||
87 | ref_thread_siblings_attr | ||
88 | ref_core_siblings_attr | ||
89 | NULL | ||
90 | }; | ||
91 | |||
92 | static struct attribute_group topology_attr_group = { | ||
93 | .attrs = default_attrs, | ||
94 | .name = "topology" | ||
95 | }; | ||
96 | |||
97 | /* Add/Remove cpu_topology interface for CPU device */ | ||
98 | static int __cpuinit topology_add_dev(struct sys_device * sys_dev) | ||
99 | { | ||
100 | sysfs_create_group(&sys_dev->kobj, &topology_attr_group); | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int __cpuinit topology_remove_dev(struct sys_device * sys_dev) | ||
105 | { | ||
106 | sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, | ||
111 | unsigned long action, void *hcpu) | ||
112 | { | ||
113 | unsigned int cpu = (unsigned long)hcpu; | ||
114 | struct sys_device *sys_dev; | ||
115 | |||
116 | sys_dev = get_cpu_sysdev(cpu); | ||
117 | switch (action) { | ||
118 | case CPU_ONLINE: | ||
119 | topology_add_dev(sys_dev); | ||
120 | break; | ||
121 | case CPU_DEAD: | ||
122 | topology_remove_dev(sys_dev); | ||
123 | break; | ||
124 | } | ||
125 | return NOTIFY_OK; | ||
126 | } | ||
127 | |||
128 | static struct notifier_block topology_cpu_notifier = | ||
129 | { | ||
130 | .notifier_call = topology_cpu_callback, | ||
131 | }; | ||
132 | |||
133 | static int __cpuinit topology_sysfs_init(void) | ||
134 | { | ||
135 | int i; | ||
136 | |||
137 | for_each_online_cpu(i) { | ||
138 | topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE, | ||
139 | (void *)(long)i); | ||
140 | } | ||
141 | |||
142 | register_cpu_notifier(&topology_cpu_notifier); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | device_initcall(topology_sysfs_init); | ||
148 | |||