Commit 864bdfb912e372670b5b2541dac9d273a4a7722a
Committed by
Len Brown
1 parent
872aad45d6
Exists in
master
and in
7 other branches
ACPI: Export events via generic netlink
Upon ACPI events, send an "acpi_event" via Generic Netlink. This is in addition to /proc/acpi/event, which remains intact for now. Thanks to Jamal for his great help. Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Showing 3 changed files with 165 additions and 8 deletions Inline Diff
drivers/acpi/bus.c
1 | /* | 1 | /* |
2 | * acpi_bus.c - ACPI Bus Driver ($Revision: 80 $) | 2 | * acpi_bus.c - ACPI Bus Driver ($Revision: 80 $) |
3 | * | 3 | * |
4 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | 4 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> |
5 | * | 5 | * |
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or (at | 10 | * the Free Software Foundation; either version 2 of the License, or (at |
11 | * your option) any later version. | 11 | * your option) any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, but | 13 | * This program is distributed in the hope that it will be useful, but |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * General Public License for more details. | 16 | * General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License along | 18 | * You should have received a copy of the GNU General Public License along |
19 | * with this program; if not, write to the Free Software Foundation, Inc., | 19 | * with this program; if not, write to the Free Software Foundation, Inc., |
20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | 20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
21 | * | 21 | * |
22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/pm.h> | 31 | #include <linux/pm.h> |
32 | #include <linux/pm_legacy.h> | 32 | #include <linux/pm_legacy.h> |
33 | #include <linux/device.h> | 33 | #include <linux/device.h> |
34 | #include <linux/proc_fs.h> | 34 | #include <linux/proc_fs.h> |
35 | #ifdef CONFIG_X86 | 35 | #ifdef CONFIG_X86 |
36 | #include <asm/mpspec.h> | 36 | #include <asm/mpspec.h> |
37 | #endif | 37 | #endif |
38 | #include <acpi/acpi_bus.h> | 38 | #include <acpi/acpi_bus.h> |
39 | #include <acpi/acpi_drivers.h> | 39 | #include <acpi/acpi_drivers.h> |
40 | 40 | ||
41 | #define _COMPONENT ACPI_BUS_COMPONENT | 41 | #define _COMPONENT ACPI_BUS_COMPONENT |
42 | ACPI_MODULE_NAME("bus"); | 42 | ACPI_MODULE_NAME("bus"); |
43 | #ifdef CONFIG_X86 | 43 | #ifdef CONFIG_X86 |
44 | extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger); | 44 | extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger); |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | struct acpi_device *acpi_root; | 47 | struct acpi_device *acpi_root; |
48 | struct proc_dir_entry *acpi_root_dir; | 48 | struct proc_dir_entry *acpi_root_dir; |
49 | EXPORT_SYMBOL(acpi_root_dir); | 49 | EXPORT_SYMBOL(acpi_root_dir); |
50 | 50 | ||
51 | #define STRUCT_TO_INT(s) (*((int*)&s)) | 51 | #define STRUCT_TO_INT(s) (*((int*)&s)) |
52 | 52 | ||
53 | /* -------------------------------------------------------------------------- | 53 | /* -------------------------------------------------------------------------- |
54 | Device Management | 54 | Device Management |
55 | -------------------------------------------------------------------------- */ | 55 | -------------------------------------------------------------------------- */ |
56 | 56 | ||
57 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | 57 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) |
58 | { | 58 | { |
59 | acpi_status status = AE_OK; | 59 | acpi_status status = AE_OK; |
60 | 60 | ||
61 | 61 | ||
62 | if (!device) | 62 | if (!device) |
63 | return -EINVAL; | 63 | return -EINVAL; |
64 | 64 | ||
65 | /* TBD: Support fixed-feature devices */ | 65 | /* TBD: Support fixed-feature devices */ |
66 | 66 | ||
67 | status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device); | 67 | status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device); |
68 | if (ACPI_FAILURE(status) || !*device) { | 68 | if (ACPI_FAILURE(status) || !*device) { |
69 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", | 69 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", |
70 | handle)); | 70 | handle)); |
71 | return -ENODEV; | 71 | return -ENODEV; |
72 | } | 72 | } |
73 | 73 | ||
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
77 | EXPORT_SYMBOL(acpi_bus_get_device); | 77 | EXPORT_SYMBOL(acpi_bus_get_device); |
78 | 78 | ||
79 | int acpi_bus_get_status(struct acpi_device *device) | 79 | int acpi_bus_get_status(struct acpi_device *device) |
80 | { | 80 | { |
81 | acpi_status status = AE_OK; | 81 | acpi_status status = AE_OK; |
82 | unsigned long sta = 0; | 82 | unsigned long sta = 0; |
83 | 83 | ||
84 | 84 | ||
85 | if (!device) | 85 | if (!device) |
86 | return -EINVAL; | 86 | return -EINVAL; |
87 | 87 | ||
88 | /* | 88 | /* |
89 | * Evaluate _STA if present. | 89 | * Evaluate _STA if present. |
90 | */ | 90 | */ |
91 | if (device->flags.dynamic_status) { | 91 | if (device->flags.dynamic_status) { |
92 | status = | 92 | status = |
93 | acpi_evaluate_integer(device->handle, "_STA", NULL, &sta); | 93 | acpi_evaluate_integer(device->handle, "_STA", NULL, &sta); |
94 | if (ACPI_FAILURE(status)) | 94 | if (ACPI_FAILURE(status)) |
95 | return -ENODEV; | 95 | return -ENODEV; |
96 | STRUCT_TO_INT(device->status) = (int)sta; | 96 | STRUCT_TO_INT(device->status) = (int)sta; |
97 | } | 97 | } |
98 | 98 | ||
99 | /* | 99 | /* |
100 | * Otherwise we assume the status of our parent (unless we don't | 100 | * Otherwise we assume the status of our parent (unless we don't |
101 | * have one, in which case status is implied). | 101 | * have one, in which case status is implied). |
102 | */ | 102 | */ |
103 | else if (device->parent) | 103 | else if (device->parent) |
104 | device->status = device->parent->status; | 104 | device->status = device->parent->status; |
105 | else | 105 | else |
106 | STRUCT_TO_INT(device->status) = | 106 | STRUCT_TO_INT(device->status) = |
107 | ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | | 107 | ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | |
108 | ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING; | 108 | ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING; |
109 | 109 | ||
110 | if (device->status.functional && !device->status.present) { | 110 | if (device->status.functional && !device->status.present) { |
111 | printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: " | 111 | printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: " |
112 | "functional but not present; setting present\n", | 112 | "functional but not present; setting present\n", |
113 | device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status)); | 113 | device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status)); |
114 | device->status.present = 1; | 114 | device->status.present = 1; |
115 | } | 115 | } |
116 | 116 | ||
117 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", | 117 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", |
118 | device->pnp.bus_id, | 118 | device->pnp.bus_id, |
119 | (u32) STRUCT_TO_INT(device->status))); | 119 | (u32) STRUCT_TO_INT(device->status))); |
120 | 120 | ||
121 | return 0; | 121 | return 0; |
122 | } | 122 | } |
123 | 123 | ||
124 | EXPORT_SYMBOL(acpi_bus_get_status); | 124 | EXPORT_SYMBOL(acpi_bus_get_status); |
125 | 125 | ||
126 | /* -------------------------------------------------------------------------- | 126 | /* -------------------------------------------------------------------------- |
127 | Power Management | 127 | Power Management |
128 | -------------------------------------------------------------------------- */ | 128 | -------------------------------------------------------------------------- */ |
129 | 129 | ||
130 | int acpi_bus_get_power(acpi_handle handle, int *state) | 130 | int acpi_bus_get_power(acpi_handle handle, int *state) |
131 | { | 131 | { |
132 | int result = 0; | 132 | int result = 0; |
133 | acpi_status status = 0; | 133 | acpi_status status = 0; |
134 | struct acpi_device *device = NULL; | 134 | struct acpi_device *device = NULL; |
135 | unsigned long psc = 0; | 135 | unsigned long psc = 0; |
136 | 136 | ||
137 | 137 | ||
138 | result = acpi_bus_get_device(handle, &device); | 138 | result = acpi_bus_get_device(handle, &device); |
139 | if (result) | 139 | if (result) |
140 | return result; | 140 | return result; |
141 | 141 | ||
142 | *state = ACPI_STATE_UNKNOWN; | 142 | *state = ACPI_STATE_UNKNOWN; |
143 | 143 | ||
144 | if (!device->flags.power_manageable) { | 144 | if (!device->flags.power_manageable) { |
145 | /* TBD: Non-recursive algorithm for walking up hierarchy */ | 145 | /* TBD: Non-recursive algorithm for walking up hierarchy */ |
146 | if (device->parent) | 146 | if (device->parent) |
147 | *state = device->parent->power.state; | 147 | *state = device->parent->power.state; |
148 | else | 148 | else |
149 | *state = ACPI_STATE_D0; | 149 | *state = ACPI_STATE_D0; |
150 | } else { | 150 | } else { |
151 | /* | 151 | /* |
152 | * Get the device's power state either directly (via _PSC) or | 152 | * Get the device's power state either directly (via _PSC) or |
153 | * indirectly (via power resources). | 153 | * indirectly (via power resources). |
154 | */ | 154 | */ |
155 | if (device->power.flags.explicit_get) { | 155 | if (device->power.flags.explicit_get) { |
156 | status = acpi_evaluate_integer(device->handle, "_PSC", | 156 | status = acpi_evaluate_integer(device->handle, "_PSC", |
157 | NULL, &psc); | 157 | NULL, &psc); |
158 | if (ACPI_FAILURE(status)) | 158 | if (ACPI_FAILURE(status)) |
159 | return -ENODEV; | 159 | return -ENODEV; |
160 | device->power.state = (int)psc; | 160 | device->power.state = (int)psc; |
161 | } else if (device->power.flags.power_resources) { | 161 | } else if (device->power.flags.power_resources) { |
162 | result = acpi_power_get_inferred_state(device); | 162 | result = acpi_power_get_inferred_state(device); |
163 | if (result) | 163 | if (result) |
164 | return result; | 164 | return result; |
165 | } | 165 | } |
166 | 166 | ||
167 | *state = device->power.state; | 167 | *state = device->power.state; |
168 | } | 168 | } |
169 | 169 | ||
170 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", | 170 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", |
171 | device->pnp.bus_id, device->power.state)); | 171 | device->pnp.bus_id, device->power.state)); |
172 | 172 | ||
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
175 | 175 | ||
176 | EXPORT_SYMBOL(acpi_bus_get_power); | 176 | EXPORT_SYMBOL(acpi_bus_get_power); |
177 | 177 | ||
178 | int acpi_bus_set_power(acpi_handle handle, int state) | 178 | int acpi_bus_set_power(acpi_handle handle, int state) |
179 | { | 179 | { |
180 | int result = 0; | 180 | int result = 0; |
181 | acpi_status status = AE_OK; | 181 | acpi_status status = AE_OK; |
182 | struct acpi_device *device = NULL; | 182 | struct acpi_device *device = NULL; |
183 | char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; | 183 | char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; |
184 | 184 | ||
185 | 185 | ||
186 | result = acpi_bus_get_device(handle, &device); | 186 | result = acpi_bus_get_device(handle, &device); |
187 | if (result) | 187 | if (result) |
188 | return result; | 188 | return result; |
189 | 189 | ||
190 | if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) | 190 | if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) |
191 | return -EINVAL; | 191 | return -EINVAL; |
192 | 192 | ||
193 | /* Make sure this is a valid target state */ | 193 | /* Make sure this is a valid target state */ |
194 | 194 | ||
195 | if (!device->flags.power_manageable) { | 195 | if (!device->flags.power_manageable) { |
196 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", | 196 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", |
197 | device->dev.kobj.name)); | 197 | device->dev.kobj.name)); |
198 | return -ENODEV; | 198 | return -ENODEV; |
199 | } | 199 | } |
200 | /* | 200 | /* |
201 | * Get device's current power state if it's unknown | 201 | * Get device's current power state if it's unknown |
202 | * This means device power state isn't initialized or previous setting failed | 202 | * This means device power state isn't initialized or previous setting failed |
203 | */ | 203 | */ |
204 | if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state) | 204 | if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state) |
205 | acpi_bus_get_power(device->handle, &device->power.state); | 205 | acpi_bus_get_power(device->handle, &device->power.state); |
206 | if ((state == device->power.state) && !device->flags.force_power_state) { | 206 | if ((state == device->power.state) && !device->flags.force_power_state) { |
207 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", | 207 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", |
208 | state)); | 208 | state)); |
209 | return 0; | 209 | return 0; |
210 | } | 210 | } |
211 | 211 | ||
212 | if (!device->power.states[state].flags.valid) { | 212 | if (!device->power.states[state].flags.valid) { |
213 | printk(KERN_WARNING PREFIX "Device does not support D%d\n", state); | 213 | printk(KERN_WARNING PREFIX "Device does not support D%d\n", state); |
214 | return -ENODEV; | 214 | return -ENODEV; |
215 | } | 215 | } |
216 | if (device->parent && (state < device->parent->power.state)) { | 216 | if (device->parent && (state < device->parent->power.state)) { |
217 | printk(KERN_WARNING PREFIX | 217 | printk(KERN_WARNING PREFIX |
218 | "Cannot set device to a higher-powered" | 218 | "Cannot set device to a higher-powered" |
219 | " state than parent\n"); | 219 | " state than parent\n"); |
220 | return -ENODEV; | 220 | return -ENODEV; |
221 | } | 221 | } |
222 | 222 | ||
223 | /* | 223 | /* |
224 | * Transition Power | 224 | * Transition Power |
225 | * ---------------- | 225 | * ---------------- |
226 | * On transitions to a high-powered state we first apply power (via | 226 | * On transitions to a high-powered state we first apply power (via |
227 | * power resources) then evalute _PSx. Conversly for transitions to | 227 | * power resources) then evalute _PSx. Conversly for transitions to |
228 | * a lower-powered state. | 228 | * a lower-powered state. |
229 | */ | 229 | */ |
230 | if (state < device->power.state) { | 230 | if (state < device->power.state) { |
231 | if (device->power.flags.power_resources) { | 231 | if (device->power.flags.power_resources) { |
232 | result = acpi_power_transition(device, state); | 232 | result = acpi_power_transition(device, state); |
233 | if (result) | 233 | if (result) |
234 | goto end; | 234 | goto end; |
235 | } | 235 | } |
236 | if (device->power.states[state].flags.explicit_set) { | 236 | if (device->power.states[state].flags.explicit_set) { |
237 | status = acpi_evaluate_object(device->handle, | 237 | status = acpi_evaluate_object(device->handle, |
238 | object_name, NULL, NULL); | 238 | object_name, NULL, NULL); |
239 | if (ACPI_FAILURE(status)) { | 239 | if (ACPI_FAILURE(status)) { |
240 | result = -ENODEV; | 240 | result = -ENODEV; |
241 | goto end; | 241 | goto end; |
242 | } | 242 | } |
243 | } | 243 | } |
244 | } else { | 244 | } else { |
245 | if (device->power.states[state].flags.explicit_set) { | 245 | if (device->power.states[state].flags.explicit_set) { |
246 | status = acpi_evaluate_object(device->handle, | 246 | status = acpi_evaluate_object(device->handle, |
247 | object_name, NULL, NULL); | 247 | object_name, NULL, NULL); |
248 | if (ACPI_FAILURE(status)) { | 248 | if (ACPI_FAILURE(status)) { |
249 | result = -ENODEV; | 249 | result = -ENODEV; |
250 | goto end; | 250 | goto end; |
251 | } | 251 | } |
252 | } | 252 | } |
253 | if (device->power.flags.power_resources) { | 253 | if (device->power.flags.power_resources) { |
254 | result = acpi_power_transition(device, state); | 254 | result = acpi_power_transition(device, state); |
255 | if (result) | 255 | if (result) |
256 | goto end; | 256 | goto end; |
257 | } | 257 | } |
258 | } | 258 | } |
259 | 259 | ||
260 | end: | 260 | end: |
261 | if (result) | 261 | if (result) |
262 | printk(KERN_WARNING PREFIX | 262 | printk(KERN_WARNING PREFIX |
263 | "Transitioning device [%s] to D%d\n", | 263 | "Transitioning device [%s] to D%d\n", |
264 | device->pnp.bus_id, state); | 264 | device->pnp.bus_id, state); |
265 | else | 265 | else |
266 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 266 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
267 | "Device [%s] transitioned to D%d\n", | 267 | "Device [%s] transitioned to D%d\n", |
268 | device->pnp.bus_id, state)); | 268 | device->pnp.bus_id, state)); |
269 | 269 | ||
270 | return result; | 270 | return result; |
271 | } | 271 | } |
272 | 272 | ||
273 | EXPORT_SYMBOL(acpi_bus_set_power); | 273 | EXPORT_SYMBOL(acpi_bus_set_power); |
274 | 274 | ||
275 | /* -------------------------------------------------------------------------- | 275 | /* -------------------------------------------------------------------------- |
276 | Event Management | 276 | Event Management |
277 | -------------------------------------------------------------------------- */ | 277 | -------------------------------------------------------------------------- */ |
278 | 278 | ||
279 | static DEFINE_SPINLOCK(acpi_bus_event_lock); | 279 | static DEFINE_SPINLOCK(acpi_bus_event_lock); |
280 | 280 | ||
281 | LIST_HEAD(acpi_bus_event_list); | 281 | LIST_HEAD(acpi_bus_event_list); |
282 | DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); | 282 | DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); |
283 | 283 | ||
284 | extern int event_is_open; | 284 | extern int event_is_open; |
285 | 285 | ||
286 | int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data) | 286 | int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data) |
287 | { | 287 | { |
288 | struct acpi_bus_event *event = NULL; | 288 | struct acpi_bus_event *event = NULL; |
289 | unsigned long flags = 0; | 289 | unsigned long flags = 0; |
290 | 290 | ||
291 | 291 | ||
292 | if (!device) | 292 | if (!device) |
293 | return -EINVAL; | 293 | return -EINVAL; |
294 | 294 | ||
295 | if (acpi_bus_generate_genetlink_event(device, type, data)) | ||
296 | printk(KERN_WARNING PREFIX | ||
297 | "Failed to generate an ACPI event via genetlink!\n"); | ||
298 | |||
295 | /* drop event on the floor if no one's listening */ | 299 | /* drop event on the floor if no one's listening */ |
296 | if (!event_is_open) | 300 | if (!event_is_open) |
297 | return 0; | 301 | return 0; |
298 | 302 | ||
299 | event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); | 303 | event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); |
300 | if (!event) | 304 | if (!event) |
301 | return -ENOMEM; | 305 | return -ENOMEM; |
302 | 306 | ||
303 | strcpy(event->device_class, device->pnp.device_class); | 307 | strcpy(event->device_class, device->pnp.device_class); |
304 | strcpy(event->bus_id, device->pnp.bus_id); | 308 | strcpy(event->bus_id, device->pnp.bus_id); |
305 | event->type = type; | 309 | event->type = type; |
306 | event->data = data; | 310 | event->data = data; |
307 | 311 | ||
308 | spin_lock_irqsave(&acpi_bus_event_lock, flags); | 312 | spin_lock_irqsave(&acpi_bus_event_lock, flags); |
309 | list_add_tail(&event->node, &acpi_bus_event_list); | 313 | list_add_tail(&event->node, &acpi_bus_event_list); |
310 | spin_unlock_irqrestore(&acpi_bus_event_lock, flags); | 314 | spin_unlock_irqrestore(&acpi_bus_event_lock, flags); |
311 | 315 | ||
312 | wake_up_interruptible(&acpi_bus_event_queue); | 316 | wake_up_interruptible(&acpi_bus_event_queue); |
313 | 317 | ||
314 | return 0; | 318 | return 0; |
315 | } | 319 | } |
316 | 320 | ||
317 | EXPORT_SYMBOL(acpi_bus_generate_event); | 321 | EXPORT_SYMBOL(acpi_bus_generate_event); |
318 | 322 | ||
319 | int acpi_bus_receive_event(struct acpi_bus_event *event) | 323 | int acpi_bus_receive_event(struct acpi_bus_event *event) |
320 | { | 324 | { |
321 | unsigned long flags = 0; | 325 | unsigned long flags = 0; |
322 | struct acpi_bus_event *entry = NULL; | 326 | struct acpi_bus_event *entry = NULL; |
323 | 327 | ||
324 | DECLARE_WAITQUEUE(wait, current); | 328 | DECLARE_WAITQUEUE(wait, current); |
325 | 329 | ||
326 | 330 | ||
327 | if (!event) | 331 | if (!event) |
328 | return -EINVAL; | 332 | return -EINVAL; |
329 | 333 | ||
330 | if (list_empty(&acpi_bus_event_list)) { | 334 | if (list_empty(&acpi_bus_event_list)) { |
331 | 335 | ||
332 | set_current_state(TASK_INTERRUPTIBLE); | 336 | set_current_state(TASK_INTERRUPTIBLE); |
333 | add_wait_queue(&acpi_bus_event_queue, &wait); | 337 | add_wait_queue(&acpi_bus_event_queue, &wait); |
334 | 338 | ||
335 | if (list_empty(&acpi_bus_event_list)) | 339 | if (list_empty(&acpi_bus_event_list)) |
336 | schedule(); | 340 | schedule(); |
337 | 341 | ||
338 | remove_wait_queue(&acpi_bus_event_queue, &wait); | 342 | remove_wait_queue(&acpi_bus_event_queue, &wait); |
339 | set_current_state(TASK_RUNNING); | 343 | set_current_state(TASK_RUNNING); |
340 | 344 | ||
341 | if (signal_pending(current)) | 345 | if (signal_pending(current)) |
342 | return -ERESTARTSYS; | 346 | return -ERESTARTSYS; |
343 | } | 347 | } |
344 | 348 | ||
345 | spin_lock_irqsave(&acpi_bus_event_lock, flags); | 349 | spin_lock_irqsave(&acpi_bus_event_lock, flags); |
346 | entry = | 350 | entry = |
347 | list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node); | 351 | list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node); |
348 | if (entry) | 352 | if (entry) |
349 | list_del(&entry->node); | 353 | list_del(&entry->node); |
350 | spin_unlock_irqrestore(&acpi_bus_event_lock, flags); | 354 | spin_unlock_irqrestore(&acpi_bus_event_lock, flags); |
351 | 355 | ||
352 | if (!entry) | 356 | if (!entry) |
353 | return -ENODEV; | 357 | return -ENODEV; |
354 | 358 | ||
355 | memcpy(event, entry, sizeof(struct acpi_bus_event)); | 359 | memcpy(event, entry, sizeof(struct acpi_bus_event)); |
356 | 360 | ||
357 | kfree(entry); | 361 | kfree(entry); |
358 | 362 | ||
359 | return 0; | 363 | return 0; |
360 | } | 364 | } |
361 | 365 | ||
362 | EXPORT_SYMBOL(acpi_bus_receive_event); | 366 | EXPORT_SYMBOL(acpi_bus_receive_event); |
363 | 367 | ||
364 | /* -------------------------------------------------------------------------- | 368 | /* -------------------------------------------------------------------------- |
365 | Notification Handling | 369 | Notification Handling |
366 | -------------------------------------------------------------------------- */ | 370 | -------------------------------------------------------------------------- */ |
367 | 371 | ||
368 | static int | 372 | static int |
369 | acpi_bus_check_device(struct acpi_device *device, int *status_changed) | 373 | acpi_bus_check_device(struct acpi_device *device, int *status_changed) |
370 | { | 374 | { |
371 | acpi_status status = 0; | 375 | acpi_status status = 0; |
372 | struct acpi_device_status old_status; | 376 | struct acpi_device_status old_status; |
373 | 377 | ||
374 | 378 | ||
375 | if (!device) | 379 | if (!device) |
376 | return -EINVAL; | 380 | return -EINVAL; |
377 | 381 | ||
378 | if (status_changed) | 382 | if (status_changed) |
379 | *status_changed = 0; | 383 | *status_changed = 0; |
380 | 384 | ||
381 | old_status = device->status; | 385 | old_status = device->status; |
382 | 386 | ||
383 | /* | 387 | /* |
384 | * Make sure this device's parent is present before we go about | 388 | * Make sure this device's parent is present before we go about |
385 | * messing with the device. | 389 | * messing with the device. |
386 | */ | 390 | */ |
387 | if (device->parent && !device->parent->status.present) { | 391 | if (device->parent && !device->parent->status.present) { |
388 | device->status = device->parent->status; | 392 | device->status = device->parent->status; |
389 | if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) { | 393 | if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) { |
390 | if (status_changed) | 394 | if (status_changed) |
391 | *status_changed = 1; | 395 | *status_changed = 1; |
392 | } | 396 | } |
393 | return 0; | 397 | return 0; |
394 | } | 398 | } |
395 | 399 | ||
396 | status = acpi_bus_get_status(device); | 400 | status = acpi_bus_get_status(device); |
397 | if (ACPI_FAILURE(status)) | 401 | if (ACPI_FAILURE(status)) |
398 | return -ENODEV; | 402 | return -ENODEV; |
399 | 403 | ||
400 | if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) | 404 | if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) |
401 | return 0; | 405 | return 0; |
402 | 406 | ||
403 | if (status_changed) | 407 | if (status_changed) |
404 | *status_changed = 1; | 408 | *status_changed = 1; |
405 | 409 | ||
406 | /* | 410 | /* |
407 | * Device Insertion/Removal | 411 | * Device Insertion/Removal |
408 | */ | 412 | */ |
409 | if ((device->status.present) && !(old_status.present)) { | 413 | if ((device->status.present) && !(old_status.present)) { |
410 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); | 414 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); |
411 | /* TBD: Handle device insertion */ | 415 | /* TBD: Handle device insertion */ |
412 | } else if (!(device->status.present) && (old_status.present)) { | 416 | } else if (!(device->status.present) && (old_status.present)) { |
413 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); | 417 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); |
414 | /* TBD: Handle device removal */ | 418 | /* TBD: Handle device removal */ |
415 | } | 419 | } |
416 | 420 | ||
417 | return 0; | 421 | return 0; |
418 | } | 422 | } |
419 | 423 | ||
420 | static int acpi_bus_check_scope(struct acpi_device *device) | 424 | static int acpi_bus_check_scope(struct acpi_device *device) |
421 | { | 425 | { |
422 | int result = 0; | 426 | int result = 0; |
423 | int status_changed = 0; | 427 | int status_changed = 0; |
424 | 428 | ||
425 | 429 | ||
426 | if (!device) | 430 | if (!device) |
427 | return -EINVAL; | 431 | return -EINVAL; |
428 | 432 | ||
429 | /* Status Change? */ | 433 | /* Status Change? */ |
430 | result = acpi_bus_check_device(device, &status_changed); | 434 | result = acpi_bus_check_device(device, &status_changed); |
431 | if (result) | 435 | if (result) |
432 | return result; | 436 | return result; |
433 | 437 | ||
434 | if (!status_changed) | 438 | if (!status_changed) |
435 | return 0; | 439 | return 0; |
436 | 440 | ||
437 | /* | 441 | /* |
438 | * TBD: Enumerate child devices within this device's scope and | 442 | * TBD: Enumerate child devices within this device's scope and |
439 | * run acpi_bus_check_device()'s on them. | 443 | * run acpi_bus_check_device()'s on them. |
440 | */ | 444 | */ |
441 | 445 | ||
442 | return 0; | 446 | return 0; |
443 | } | 447 | } |
444 | 448 | ||
445 | /** | 449 | /** |
446 | * acpi_bus_notify | 450 | * acpi_bus_notify |
447 | * --------------- | 451 | * --------------- |
448 | * Callback for all 'system-level' device notifications (values 0x00-0x7F). | 452 | * Callback for all 'system-level' device notifications (values 0x00-0x7F). |
449 | */ | 453 | */ |
450 | static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | 454 | static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) |
451 | { | 455 | { |
452 | int result = 0; | 456 | int result = 0; |
453 | struct acpi_device *device = NULL; | 457 | struct acpi_device *device = NULL; |
454 | 458 | ||
455 | 459 | ||
456 | if (acpi_bus_get_device(handle, &device)) | 460 | if (acpi_bus_get_device(handle, &device)) |
457 | return; | 461 | return; |
458 | 462 | ||
459 | switch (type) { | 463 | switch (type) { |
460 | 464 | ||
461 | case ACPI_NOTIFY_BUS_CHECK: | 465 | case ACPI_NOTIFY_BUS_CHECK: |
462 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 466 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
463 | "Received BUS CHECK notification for device [%s]\n", | 467 | "Received BUS CHECK notification for device [%s]\n", |
464 | device->pnp.bus_id)); | 468 | device->pnp.bus_id)); |
465 | result = acpi_bus_check_scope(device); | 469 | result = acpi_bus_check_scope(device); |
466 | /* | 470 | /* |
467 | * TBD: We'll need to outsource certain events to non-ACPI | 471 | * TBD: We'll need to outsource certain events to non-ACPI |
468 | * drivers via the device manager (device.c). | 472 | * drivers via the device manager (device.c). |
469 | */ | 473 | */ |
470 | break; | 474 | break; |
471 | 475 | ||
472 | case ACPI_NOTIFY_DEVICE_CHECK: | 476 | case ACPI_NOTIFY_DEVICE_CHECK: |
473 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 477 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
474 | "Received DEVICE CHECK notification for device [%s]\n", | 478 | "Received DEVICE CHECK notification for device [%s]\n", |
475 | device->pnp.bus_id)); | 479 | device->pnp.bus_id)); |
476 | result = acpi_bus_check_device(device, NULL); | 480 | result = acpi_bus_check_device(device, NULL); |
477 | /* | 481 | /* |
478 | * TBD: We'll need to outsource certain events to non-ACPI | 482 | * TBD: We'll need to outsource certain events to non-ACPI |
479 | * drivers via the device manager (device.c). | 483 | * drivers via the device manager (device.c). |
480 | */ | 484 | */ |
481 | break; | 485 | break; |
482 | 486 | ||
483 | case ACPI_NOTIFY_DEVICE_WAKE: | 487 | case ACPI_NOTIFY_DEVICE_WAKE: |
484 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 488 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
485 | "Received DEVICE WAKE notification for device [%s]\n", | 489 | "Received DEVICE WAKE notification for device [%s]\n", |
486 | device->pnp.bus_id)); | 490 | device->pnp.bus_id)); |
487 | /* TBD */ | 491 | /* TBD */ |
488 | break; | 492 | break; |
489 | 493 | ||
490 | case ACPI_NOTIFY_EJECT_REQUEST: | 494 | case ACPI_NOTIFY_EJECT_REQUEST: |
491 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 495 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
492 | "Received EJECT REQUEST notification for device [%s]\n", | 496 | "Received EJECT REQUEST notification for device [%s]\n", |
493 | device->pnp.bus_id)); | 497 | device->pnp.bus_id)); |
494 | /* TBD */ | 498 | /* TBD */ |
495 | break; | 499 | break; |
496 | 500 | ||
497 | case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: | 501 | case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: |
498 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 502 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
499 | "Received DEVICE CHECK LIGHT notification for device [%s]\n", | 503 | "Received DEVICE CHECK LIGHT notification for device [%s]\n", |
500 | device->pnp.bus_id)); | 504 | device->pnp.bus_id)); |
501 | /* TBD: Exactly what does 'light' mean? */ | 505 | /* TBD: Exactly what does 'light' mean? */ |
502 | break; | 506 | break; |
503 | 507 | ||
504 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | 508 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: |
505 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 509 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
506 | "Received FREQUENCY MISMATCH notification for device [%s]\n", | 510 | "Received FREQUENCY MISMATCH notification for device [%s]\n", |
507 | device->pnp.bus_id)); | 511 | device->pnp.bus_id)); |
508 | /* TBD */ | 512 | /* TBD */ |
509 | break; | 513 | break; |
510 | 514 | ||
511 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | 515 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: |
512 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 516 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
513 | "Received BUS MODE MISMATCH notification for device [%s]\n", | 517 | "Received BUS MODE MISMATCH notification for device [%s]\n", |
514 | device->pnp.bus_id)); | 518 | device->pnp.bus_id)); |
515 | /* TBD */ | 519 | /* TBD */ |
516 | break; | 520 | break; |
517 | 521 | ||
518 | case ACPI_NOTIFY_POWER_FAULT: | 522 | case ACPI_NOTIFY_POWER_FAULT: |
519 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 523 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
520 | "Received POWER FAULT notification for device [%s]\n", | 524 | "Received POWER FAULT notification for device [%s]\n", |
521 | device->pnp.bus_id)); | 525 | device->pnp.bus_id)); |
522 | /* TBD */ | 526 | /* TBD */ |
523 | break; | 527 | break; |
524 | 528 | ||
525 | default: | 529 | default: |
526 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 530 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
527 | "Received unknown/unsupported notification [%08x]\n", | 531 | "Received unknown/unsupported notification [%08x]\n", |
528 | type)); | 532 | type)); |
529 | break; | 533 | break; |
530 | } | 534 | } |
531 | 535 | ||
532 | return; | 536 | return; |
533 | } | 537 | } |
534 | 538 | ||
535 | /* -------------------------------------------------------------------------- | 539 | /* -------------------------------------------------------------------------- |
536 | Initialization/Cleanup | 540 | Initialization/Cleanup |
537 | -------------------------------------------------------------------------- */ | 541 | -------------------------------------------------------------------------- */ |
538 | 542 | ||
539 | static int __init acpi_bus_init_irq(void) | 543 | static int __init acpi_bus_init_irq(void) |
540 | { | 544 | { |
541 | acpi_status status = AE_OK; | 545 | acpi_status status = AE_OK; |
542 | union acpi_object arg = { ACPI_TYPE_INTEGER }; | 546 | union acpi_object arg = { ACPI_TYPE_INTEGER }; |
543 | struct acpi_object_list arg_list = { 1, &arg }; | 547 | struct acpi_object_list arg_list = { 1, &arg }; |
544 | char *message = NULL; | 548 | char *message = NULL; |
545 | 549 | ||
546 | 550 | ||
547 | /* | 551 | /* |
548 | * Let the system know what interrupt model we are using by | 552 | * Let the system know what interrupt model we are using by |
549 | * evaluating the \_PIC object, if exists. | 553 | * evaluating the \_PIC object, if exists. |
550 | */ | 554 | */ |
551 | 555 | ||
552 | switch (acpi_irq_model) { | 556 | switch (acpi_irq_model) { |
553 | case ACPI_IRQ_MODEL_PIC: | 557 | case ACPI_IRQ_MODEL_PIC: |
554 | message = "PIC"; | 558 | message = "PIC"; |
555 | break; | 559 | break; |
556 | case ACPI_IRQ_MODEL_IOAPIC: | 560 | case ACPI_IRQ_MODEL_IOAPIC: |
557 | message = "IOAPIC"; | 561 | message = "IOAPIC"; |
558 | break; | 562 | break; |
559 | case ACPI_IRQ_MODEL_IOSAPIC: | 563 | case ACPI_IRQ_MODEL_IOSAPIC: |
560 | message = "IOSAPIC"; | 564 | message = "IOSAPIC"; |
561 | break; | 565 | break; |
562 | case ACPI_IRQ_MODEL_PLATFORM: | 566 | case ACPI_IRQ_MODEL_PLATFORM: |
563 | message = "platform specific model"; | 567 | message = "platform specific model"; |
564 | break; | 568 | break; |
565 | default: | 569 | default: |
566 | printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n"); | 570 | printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n"); |
567 | return -ENODEV; | 571 | return -ENODEV; |
568 | } | 572 | } |
569 | 573 | ||
570 | printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message); | 574 | printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message); |
571 | 575 | ||
572 | arg.integer.value = acpi_irq_model; | 576 | arg.integer.value = acpi_irq_model; |
573 | 577 | ||
574 | status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL); | 578 | status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL); |
575 | if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { | 579 | if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { |
576 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC")); | 580 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC")); |
577 | return -ENODEV; | 581 | return -ENODEV; |
578 | } | 582 | } |
579 | 583 | ||
580 | return 0; | 584 | return 0; |
581 | } | 585 | } |
582 | 586 | ||
583 | acpi_native_uint acpi_gbl_permanent_mmap; | 587 | acpi_native_uint acpi_gbl_permanent_mmap; |
584 | 588 | ||
585 | 589 | ||
586 | void __init acpi_early_init(void) | 590 | void __init acpi_early_init(void) |
587 | { | 591 | { |
588 | acpi_status status = AE_OK; | 592 | acpi_status status = AE_OK; |
589 | 593 | ||
590 | if (acpi_disabled) | 594 | if (acpi_disabled) |
591 | return; | 595 | return; |
592 | 596 | ||
593 | printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); | 597 | printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); |
594 | 598 | ||
595 | /* enable workarounds, unless strict ACPI spec. compliance */ | 599 | /* enable workarounds, unless strict ACPI spec. compliance */ |
596 | if (!acpi_strict) | 600 | if (!acpi_strict) |
597 | acpi_gbl_enable_interpreter_slack = TRUE; | 601 | acpi_gbl_enable_interpreter_slack = TRUE; |
598 | 602 | ||
599 | acpi_gbl_permanent_mmap = 1; | 603 | acpi_gbl_permanent_mmap = 1; |
600 | 604 | ||
601 | status = acpi_reallocate_root_table(); | 605 | status = acpi_reallocate_root_table(); |
602 | if (ACPI_FAILURE(status)) { | 606 | if (ACPI_FAILURE(status)) { |
603 | printk(KERN_ERR PREFIX | 607 | printk(KERN_ERR PREFIX |
604 | "Unable to reallocate ACPI tables\n"); | 608 | "Unable to reallocate ACPI tables\n"); |
605 | goto error0; | 609 | goto error0; |
606 | } | 610 | } |
607 | 611 | ||
608 | status = acpi_initialize_subsystem(); | 612 | status = acpi_initialize_subsystem(); |
609 | if (ACPI_FAILURE(status)) { | 613 | if (ACPI_FAILURE(status)) { |
610 | printk(KERN_ERR PREFIX | 614 | printk(KERN_ERR PREFIX |
611 | "Unable to initialize the ACPI Interpreter\n"); | 615 | "Unable to initialize the ACPI Interpreter\n"); |
612 | goto error0; | 616 | goto error0; |
613 | } | 617 | } |
614 | 618 | ||
615 | status = acpi_load_tables(); | 619 | status = acpi_load_tables(); |
616 | if (ACPI_FAILURE(status)) { | 620 | if (ACPI_FAILURE(status)) { |
617 | printk(KERN_ERR PREFIX | 621 | printk(KERN_ERR PREFIX |
618 | "Unable to load the System Description Tables\n"); | 622 | "Unable to load the System Description Tables\n"); |
619 | goto error0; | 623 | goto error0; |
620 | } | 624 | } |
621 | 625 | ||
622 | #ifdef CONFIG_X86 | 626 | #ifdef CONFIG_X86 |
623 | if (!acpi_ioapic) { | 627 | if (!acpi_ioapic) { |
624 | extern u8 acpi_sci_flags; | 628 | extern u8 acpi_sci_flags; |
625 | 629 | ||
626 | /* compatible (0) means level (3) */ | 630 | /* compatible (0) means level (3) */ |
627 | if (!(acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)) { | 631 | if (!(acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)) { |
628 | acpi_sci_flags &= ~ACPI_MADT_TRIGGER_MASK; | 632 | acpi_sci_flags &= ~ACPI_MADT_TRIGGER_MASK; |
629 | acpi_sci_flags |= ACPI_MADT_TRIGGER_LEVEL; | 633 | acpi_sci_flags |= ACPI_MADT_TRIGGER_LEVEL; |
630 | } | 634 | } |
631 | /* Set PIC-mode SCI trigger type */ | 635 | /* Set PIC-mode SCI trigger type */ |
632 | acpi_pic_sci_set_trigger(acpi_gbl_FADT.sci_interrupt, | 636 | acpi_pic_sci_set_trigger(acpi_gbl_FADT.sci_interrupt, |
633 | (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2); | 637 | (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2); |
634 | } else { | 638 | } else { |
635 | extern int acpi_sci_override_gsi; | 639 | extern int acpi_sci_override_gsi; |
636 | /* | 640 | /* |
637 | * now that acpi_gbl_FADT is initialized, | 641 | * now that acpi_gbl_FADT is initialized, |
638 | * update it with result from INT_SRC_OVR parsing | 642 | * update it with result from INT_SRC_OVR parsing |
639 | */ | 643 | */ |
640 | acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi; | 644 | acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi; |
641 | } | 645 | } |
642 | #endif | 646 | #endif |
643 | 647 | ||
644 | status = | 648 | status = |
645 | acpi_enable_subsystem(~ | 649 | acpi_enable_subsystem(~ |
646 | (ACPI_NO_HARDWARE_INIT | | 650 | (ACPI_NO_HARDWARE_INIT | |
647 | ACPI_NO_ACPI_ENABLE)); | 651 | ACPI_NO_ACPI_ENABLE)); |
648 | if (ACPI_FAILURE(status)) { | 652 | if (ACPI_FAILURE(status)) { |
649 | printk(KERN_ERR PREFIX "Unable to enable ACPI\n"); | 653 | printk(KERN_ERR PREFIX "Unable to enable ACPI\n"); |
650 | goto error0; | 654 | goto error0; |
651 | } | 655 | } |
652 | 656 | ||
653 | return; | 657 | return; |
654 | 658 | ||
655 | error0: | 659 | error0: |
656 | disable_acpi(); | 660 | disable_acpi(); |
657 | return; | 661 | return; |
658 | } | 662 | } |
659 | 663 | ||
660 | static int __init acpi_bus_init(void) | 664 | static int __init acpi_bus_init(void) |
661 | { | 665 | { |
662 | int result = 0; | 666 | int result = 0; |
663 | acpi_status status = AE_OK; | 667 | acpi_status status = AE_OK; |
664 | extern acpi_status acpi_os_initialize1(void); | 668 | extern acpi_status acpi_os_initialize1(void); |
665 | 669 | ||
666 | 670 | ||
667 | status = acpi_os_initialize1(); | 671 | status = acpi_os_initialize1(); |
668 | 672 | ||
669 | status = | 673 | status = |
670 | acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE); | 674 | acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE); |
671 | if (ACPI_FAILURE(status)) { | 675 | if (ACPI_FAILURE(status)) { |
672 | printk(KERN_ERR PREFIX | 676 | printk(KERN_ERR PREFIX |
673 | "Unable to start the ACPI Interpreter\n"); | 677 | "Unable to start the ACPI Interpreter\n"); |
674 | goto error1; | 678 | goto error1; |
675 | } | 679 | } |
676 | 680 | ||
677 | if (ACPI_FAILURE(status)) { | 681 | if (ACPI_FAILURE(status)) { |
678 | printk(KERN_ERR PREFIX | 682 | printk(KERN_ERR PREFIX |
679 | "Unable to initialize ACPI OS objects\n"); | 683 | "Unable to initialize ACPI OS objects\n"); |
680 | goto error1; | 684 | goto error1; |
681 | } | 685 | } |
682 | #ifdef CONFIG_ACPI_EC | 686 | #ifdef CONFIG_ACPI_EC |
683 | /* | 687 | /* |
684 | * ACPI 2.0 requires the EC driver to be loaded and work before | 688 | * ACPI 2.0 requires the EC driver to be loaded and work before |
685 | * the EC device is found in the namespace (i.e. before acpi_initialize_objects() | 689 | * the EC device is found in the namespace (i.e. before acpi_initialize_objects() |
686 | * is called). | 690 | * is called). |
687 | * | 691 | * |
688 | * This is accomplished by looking for the ECDT table, and getting | 692 | * This is accomplished by looking for the ECDT table, and getting |
689 | * the EC parameters out of that. | 693 | * the EC parameters out of that. |
690 | */ | 694 | */ |
691 | status = acpi_ec_ecdt_probe(); | 695 | status = acpi_ec_ecdt_probe(); |
692 | /* Ignore result. Not having an ECDT is not fatal. */ | 696 | /* Ignore result. Not having an ECDT is not fatal. */ |
693 | #endif | 697 | #endif |
694 | 698 | ||
695 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); | 699 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); |
696 | if (ACPI_FAILURE(status)) { | 700 | if (ACPI_FAILURE(status)) { |
697 | printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); | 701 | printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); |
698 | goto error1; | 702 | goto error1; |
699 | } | 703 | } |
700 | 704 | ||
701 | printk(KERN_INFO PREFIX "Interpreter enabled\n"); | 705 | printk(KERN_INFO PREFIX "Interpreter enabled\n"); |
702 | 706 | ||
703 | /* Initialize sleep structures */ | 707 | /* Initialize sleep structures */ |
704 | acpi_sleep_init(); | 708 | acpi_sleep_init(); |
705 | 709 | ||
706 | /* | 710 | /* |
707 | * Get the system interrupt model and evaluate \_PIC. | 711 | * Get the system interrupt model and evaluate \_PIC. |
708 | */ | 712 | */ |
709 | result = acpi_bus_init_irq(); | 713 | result = acpi_bus_init_irq(); |
710 | if (result) | 714 | if (result) |
711 | goto error1; | 715 | goto error1; |
712 | 716 | ||
713 | /* | 717 | /* |
714 | * Register the for all standard device notifications. | 718 | * Register the for all standard device notifications. |
715 | */ | 719 | */ |
716 | status = | 720 | status = |
717 | acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, | 721 | acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, |
718 | &acpi_bus_notify, NULL); | 722 | &acpi_bus_notify, NULL); |
719 | if (ACPI_FAILURE(status)) { | 723 | if (ACPI_FAILURE(status)) { |
720 | printk(KERN_ERR PREFIX | 724 | printk(KERN_ERR PREFIX |
721 | "Unable to register for device notifications\n"); | 725 | "Unable to register for device notifications\n"); |
722 | goto error1; | 726 | goto error1; |
723 | } | 727 | } |
724 | 728 | ||
725 | /* | 729 | /* |
726 | * Create the top ACPI proc directory | 730 | * Create the top ACPI proc directory |
727 | */ | 731 | */ |
728 | acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL); | 732 | acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL); |
729 | 733 | ||
730 | return 0; | 734 | return 0; |
731 | 735 | ||
732 | /* Mimic structured exception handling */ | 736 | /* Mimic structured exception handling */ |
733 | error1: | 737 | error1: |
734 | acpi_terminate(); | 738 | acpi_terminate(); |
735 | return -ENODEV; | 739 | return -ENODEV; |
736 | } | 740 | } |
737 | 741 | ||
738 | decl_subsys(acpi, NULL, NULL); | 742 | decl_subsys(acpi, NULL, NULL); |
739 | 743 | ||
740 | static int __init acpi_init(void) | 744 | static int __init acpi_init(void) |
741 | { | 745 | { |
742 | int result = 0; | 746 | int result = 0; |
743 | 747 | ||
744 | 748 | ||
745 | if (acpi_disabled) { | 749 | if (acpi_disabled) { |
746 | printk(KERN_INFO PREFIX "Interpreter disabled.\n"); | 750 | printk(KERN_INFO PREFIX "Interpreter disabled.\n"); |
747 | return -ENODEV; | 751 | return -ENODEV; |
748 | } | 752 | } |
749 | 753 | ||
750 | result = firmware_register(&acpi_subsys); | 754 | result = firmware_register(&acpi_subsys); |
751 | if (result < 0) | 755 | if (result < 0) |
752 | printk(KERN_WARNING "%s: firmware_register error: %d\n", | 756 | printk(KERN_WARNING "%s: firmware_register error: %d\n", |
753 | __FUNCTION__, result); | 757 | __FUNCTION__, result); |
754 | 758 | ||
755 | result = acpi_bus_init(); | 759 | result = acpi_bus_init(); |
756 | 760 | ||
757 | if (!result) { | 761 | if (!result) { |
758 | #ifdef CONFIG_PM_LEGACY | 762 | #ifdef CONFIG_PM_LEGACY |
759 | if (!PM_IS_ACTIVE()) | 763 | if (!PM_IS_ACTIVE()) |
760 | pm_active = 1; | 764 | pm_active = 1; |
761 | else { | 765 | else { |
762 | printk(KERN_INFO PREFIX | 766 | printk(KERN_INFO PREFIX |
763 | "APM is already active, exiting\n"); | 767 | "APM is already active, exiting\n"); |
764 | disable_acpi(); | 768 | disable_acpi(); |
765 | result = -ENODEV; | 769 | result = -ENODEV; |
766 | } | 770 | } |
767 | #endif | 771 | #endif |
768 | } else | 772 | } else |
769 | disable_acpi(); | 773 | disable_acpi(); |
770 | 774 | ||
771 | return result; | 775 | return result; |
772 | } | 776 | } |
773 | 777 | ||
774 | subsys_initcall(acpi_init); | 778 | subsys_initcall(acpi_init); |
775 | 779 |
drivers/acpi/event.c
1 | /* | 1 | /* |
2 | * event.c - exporting ACPI events via procfs | 2 | * event.c - exporting ACPI events via procfs |
3 | * | 3 | * |
4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | 4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | 5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> |
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/spinlock.h> | 9 | #include <linux/spinlock.h> |
10 | #include <linux/proc_fs.h> | 10 | #include <linux/proc_fs.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/poll.h> | 12 | #include <linux/poll.h> |
13 | #include <acpi/acpi_drivers.h> | 13 | #include <acpi/acpi_drivers.h> |
14 | #include <net/netlink.h> | ||
15 | #include <net/genetlink.h> | ||
14 | 16 | ||
15 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | 17 | #define _COMPONENT ACPI_SYSTEM_COMPONENT |
16 | ACPI_MODULE_NAME("event"); | 18 | ACPI_MODULE_NAME("event"); |
17 | 19 | ||
18 | /* Global vars for handling event proc entry */ | 20 | /* Global vars for handling event proc entry */ |
19 | static DEFINE_SPINLOCK(acpi_system_event_lock); | 21 | static DEFINE_SPINLOCK(acpi_system_event_lock); |
20 | int event_is_open = 0; | 22 | int event_is_open = 0; |
21 | extern struct list_head acpi_bus_event_list; | 23 | extern struct list_head acpi_bus_event_list; |
22 | extern wait_queue_head_t acpi_bus_event_queue; | 24 | extern wait_queue_head_t acpi_bus_event_queue; |
23 | 25 | ||
24 | static int acpi_system_open_event(struct inode *inode, struct file *file) | 26 | static int acpi_system_open_event(struct inode *inode, struct file *file) |
25 | { | 27 | { |
26 | spin_lock_irq(&acpi_system_event_lock); | 28 | spin_lock_irq(&acpi_system_event_lock); |
27 | 29 | ||
28 | if (event_is_open) | 30 | if (event_is_open) |
29 | goto out_busy; | 31 | goto out_busy; |
30 | 32 | ||
31 | event_is_open = 1; | 33 | event_is_open = 1; |
32 | 34 | ||
33 | spin_unlock_irq(&acpi_system_event_lock); | 35 | spin_unlock_irq(&acpi_system_event_lock); |
34 | return 0; | 36 | return 0; |
35 | 37 | ||
36 | out_busy: | 38 | out_busy: |
37 | spin_unlock_irq(&acpi_system_event_lock); | 39 | spin_unlock_irq(&acpi_system_event_lock); |
38 | return -EBUSY; | 40 | return -EBUSY; |
39 | } | 41 | } |
40 | 42 | ||
41 | static ssize_t | 43 | static ssize_t |
42 | acpi_system_read_event(struct file *file, char __user * buffer, size_t count, | 44 | acpi_system_read_event(struct file *file, char __user * buffer, size_t count, |
43 | loff_t * ppos) | 45 | loff_t * ppos) |
44 | { | 46 | { |
45 | int result = 0; | 47 | int result = 0; |
46 | struct acpi_bus_event event; | 48 | struct acpi_bus_event event; |
47 | static char str[ACPI_MAX_STRING]; | 49 | static char str[ACPI_MAX_STRING]; |
48 | static int chars_remaining = 0; | 50 | static int chars_remaining = 0; |
49 | static char *ptr; | 51 | static char *ptr; |
50 | 52 | ||
51 | |||
52 | if (!chars_remaining) { | 53 | if (!chars_remaining) { |
53 | memset(&event, 0, sizeof(struct acpi_bus_event)); | 54 | memset(&event, 0, sizeof(struct acpi_bus_event)); |
54 | 55 | ||
55 | if ((file->f_flags & O_NONBLOCK) | 56 | if ((file->f_flags & O_NONBLOCK) |
56 | && (list_empty(&acpi_bus_event_list))) | 57 | && (list_empty(&acpi_bus_event_list))) |
57 | return -EAGAIN; | 58 | return -EAGAIN; |
58 | 59 | ||
59 | result = acpi_bus_receive_event(&event); | 60 | result = acpi_bus_receive_event(&event); |
60 | if (result) | 61 | if (result) |
61 | return result; | 62 | return result; |
62 | 63 | ||
63 | chars_remaining = sprintf(str, "%s %s %08x %08x\n", | 64 | chars_remaining = sprintf(str, "%s %s %08x %08x\n", |
64 | event.device_class ? event. | 65 | event.device_class ? event. |
65 | device_class : "<unknown>", | 66 | device_class : "<unknown>", |
66 | event.bus_id ? event. | 67 | event.bus_id ? event. |
67 | bus_id : "<unknown>", event.type, | 68 | bus_id : "<unknown>", event.type, |
68 | event.data); | 69 | event.data); |
69 | ptr = str; | 70 | ptr = str; |
70 | } | 71 | } |
71 | 72 | ||
72 | if (chars_remaining < count) { | 73 | if (chars_remaining < count) { |
73 | count = chars_remaining; | 74 | count = chars_remaining; |
74 | } | 75 | } |
75 | 76 | ||
76 | if (copy_to_user(buffer, ptr, count)) | 77 | if (copy_to_user(buffer, ptr, count)) |
77 | return -EFAULT; | 78 | return -EFAULT; |
78 | 79 | ||
79 | *ppos += count; | 80 | *ppos += count; |
80 | chars_remaining -= count; | 81 | chars_remaining -= count; |
81 | ptr += count; | 82 | ptr += count; |
82 | 83 | ||
83 | return count; | 84 | return count; |
84 | } | 85 | } |
85 | 86 | ||
86 | static int acpi_system_close_event(struct inode *inode, struct file *file) | 87 | static int acpi_system_close_event(struct inode *inode, struct file *file) |
87 | { | 88 | { |
88 | spin_lock_irq(&acpi_system_event_lock); | 89 | spin_lock_irq(&acpi_system_event_lock); |
89 | event_is_open = 0; | 90 | event_is_open = 0; |
90 | spin_unlock_irq(&acpi_system_event_lock); | 91 | spin_unlock_irq(&acpi_system_event_lock); |
91 | return 0; | 92 | return 0; |
92 | } | 93 | } |
93 | 94 | ||
94 | static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait) | 95 | static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait) |
95 | { | 96 | { |
96 | poll_wait(file, &acpi_bus_event_queue, wait); | 97 | poll_wait(file, &acpi_bus_event_queue, wait); |
97 | if (!list_empty(&acpi_bus_event_list)) | 98 | if (!list_empty(&acpi_bus_event_list)) |
98 | return POLLIN | POLLRDNORM; | 99 | return POLLIN | POLLRDNORM; |
99 | return 0; | 100 | return 0; |
100 | } | 101 | } |
101 | 102 | ||
102 | static const struct file_operations acpi_system_event_ops = { | 103 | static const struct file_operations acpi_system_event_ops = { |
103 | .open = acpi_system_open_event, | 104 | .open = acpi_system_open_event, |
104 | .read = acpi_system_read_event, | 105 | .read = acpi_system_read_event, |
105 | .release = acpi_system_close_event, | 106 | .release = acpi_system_close_event, |
106 | .poll = acpi_system_poll_event, | 107 | .poll = acpi_system_poll_event, |
107 | }; | 108 | }; |
108 | 109 | ||
110 | #ifdef CONFIG_NET | ||
111 | unsigned int acpi_event_seqnum; | ||
112 | struct acpi_genl_event { | ||
113 | acpi_device_class device_class; | ||
114 | char bus_id[15]; | ||
115 | u32 type; | ||
116 | u32 data; | ||
117 | }; | ||
118 | |||
119 | /* attributes of acpi_genl_family */ | ||
120 | enum { | ||
121 | ACPI_GENL_ATTR_UNSPEC, | ||
122 | ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */ | ||
123 | __ACPI_GENL_ATTR_MAX, | ||
124 | }; | ||
125 | #define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1) | ||
126 | |||
127 | /* commands supported by the acpi_genl_family */ | ||
128 | enum { | ||
129 | ACPI_GENL_CMD_UNSPEC, | ||
130 | ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */ | ||
131 | __ACPI_GENL_CMD_MAX, | ||
132 | }; | ||
133 | #define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1) | ||
134 | |||
135 | #define ACPI_GENL_NAME "acpi_event" | ||
136 | #define ACPI_GENL_VERSION 0x01 | ||
137 | |||
138 | static struct genl_family acpi_event_genl_family = { | ||
139 | .id = GENL_ID_GENERATE, | ||
140 | .name = ACPI_GENL_NAME, | ||
141 | .version = ACPI_GENL_VERSION, | ||
142 | .maxattr = ACPI_GENL_ATTR_MAX, | ||
143 | }; | ||
144 | |||
145 | /* .doit: standard command callback */ | ||
146 | static int acpi_genl_cmd_event(struct sk_buff *skb, struct genl_info *info) | ||
147 | { | ||
148 | struct acpi_genl_event *event = info->userhdr; | ||
149 | |||
150 | if (!event) | ||
151 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "ACPI event: NULL\n")); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static struct genl_ops acpi_event_genl_ops = { | ||
157 | .cmd = ACPI_GENL_CMD_EVENT, | ||
158 | .doit = acpi_genl_cmd_event, | ||
159 | }; | ||
160 | |||
161 | int acpi_bus_generate_genetlink_event(struct acpi_device *device, | ||
162 | u8 type, int data) | ||
163 | { | ||
164 | struct sk_buff *skb; | ||
165 | struct nlattr *attr; | ||
166 | struct acpi_genl_event *event; | ||
167 | void *msg_header; | ||
168 | int size; | ||
169 | int result; | ||
170 | |||
171 | /* allocate memory */ | ||
172 | size = nla_total_size(sizeof(struct acpi_genl_event)) + | ||
173 | nla_total_size(0); | ||
174 | |||
175 | skb = genlmsg_new(size, GFP_ATOMIC); | ||
176 | if (!skb) | ||
177 | return -ENOMEM; | ||
178 | |||
179 | /* add the genetlink message header */ | ||
180 | msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++, | ||
181 | &acpi_event_genl_family, 0, | ||
182 | ACPI_GENL_CMD_EVENT); | ||
183 | if (!msg_header) { | ||
184 | nlmsg_free(skb); | ||
185 | return -ENOMEM; | ||
186 | } | ||
187 | |||
188 | /* fill the data */ | ||
189 | attr = | ||
190 | nla_reserve(skb, ACPI_GENL_ATTR_EVENT, | ||
191 | sizeof(struct acpi_genl_event)); | ||
192 | if (!attr) { | ||
193 | nlmsg_free(skb); | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | event = nla_data(attr); | ||
198 | if (!event) { | ||
199 | nlmsg_free(skb); | ||
200 | return -EINVAL; | ||
201 | } | ||
202 | |||
203 | memset(event, 0, sizeof(struct acpi_genl_event)); | ||
204 | |||
205 | strcpy(event->device_class, device->pnp.device_class); | ||
206 | strcpy(event->bus_id, device->dev.bus_id); | ||
207 | event->type = type; | ||
208 | event->data = data; | ||
209 | |||
210 | /* send multicast genetlink message */ | ||
211 | result = genlmsg_end(skb, msg_header); | ||
212 | if (result < 0) { | ||
213 | nlmsg_free(skb); | ||
214 | return result; | ||
215 | } | ||
216 | |||
217 | result = | ||
218 | genlmsg_multicast(skb, 0, acpi_event_genl_family.id, GFP_ATOMIC); | ||
219 | if (result) | ||
220 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
221 | "Failed to send a Genetlink message!\n")); | ||
222 | return 0; | ||
223 | } | ||
224 | EXPORT_SYMBOL(acpi_bus_generate_genetlink_event); | ||
225 | |||
226 | static int acpi_event_genetlink_init(void) | ||
227 | { | ||
228 | int result; | ||
229 | |||
230 | result = genl_register_family(&acpi_event_genl_family); | ||
231 | if (result) | ||
232 | return result; | ||
233 | |||
234 | result = | ||
235 | genl_register_ops(&acpi_event_genl_family, &acpi_event_genl_ops); | ||
236 | if (result) | ||
237 | genl_unregister_family(&acpi_event_genl_family); | ||
238 | |||
239 | return result; | ||
240 | } | ||
241 | |||
242 | #else | ||
243 | int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type, | ||
244 | int data) | ||
245 | { | ||
246 | return 0; | ||
247 | } | ||
248 | EXPORT_SYMBOL(acpi_bus_generate_genetlink_event); | ||
249 | |||
250 | static int acpi_event_genetlink_init(void) | ||
251 | { | ||
252 | return -ENODEV; | ||
253 | } | ||
254 | #endif | ||
255 | |||
109 | static int __init acpi_event_init(void) | 256 | static int __init acpi_event_init(void) |
110 | { | 257 | { |
111 | struct proc_dir_entry *entry; | 258 | struct proc_dir_entry *entry; |
112 | int error = 0; | 259 | int error = 0; |
113 | 260 | ||
114 | |||
115 | if (acpi_disabled) | 261 | if (acpi_disabled) |
116 | return 0; | 262 | return 0; |
117 | 263 | ||
264 | /* create genetlink for acpi event */ | ||
265 | error = acpi_event_genetlink_init(); | ||
266 | if (error) | ||
267 | printk(KERN_WARNING PREFIX | ||
268 | "Failed to create genetlink family for ACPI event\n"); | ||
269 | |||
118 | /* 'event' [R] */ | 270 | /* 'event' [R] */ |
119 | entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); | 271 | entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); |
120 | if (entry) | 272 | if (entry) |
121 | entry->proc_fops = &acpi_system_event_ops; | 273 | entry->proc_fops = &acpi_system_event_ops; |
122 | else { | 274 | else |
123 | error = -ENODEV; | 275 | return -ENODEV; |
124 | } | 276 | |
125 | return error; | 277 | return 0; |
126 | } | 278 | } |
127 | 279 |
include/acpi/acpi_bus.h
1 | /* | 1 | /* |
2 | * acpi_bus.h - ACPI Bus Driver ($Revision: 22 $) | 2 | * acpi_bus.h - ACPI Bus Driver ($Revision: 22 $) |
3 | * | 3 | * |
4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | 4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | 5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> |
6 | * | 6 | * |
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2 of the License, or (at | 11 | * the Free Software Foundation; either version 2 of the License, or (at |
12 | * your option) any later version. | 12 | * your option) any later version. |
13 | * | 13 | * |
14 | * This program is distributed in the hope that it will be useful, but | 14 | * This program is distributed in the hope that it will be useful, but |
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | * General Public License for more details. | 17 | * General Public License for more details. |
18 | * | 18 | * |
19 | * You should have received a copy of the GNU General Public License along | 19 | * You should have received a copy of the GNU General Public License along |
20 | * with this program; if not, write to the Free Software Foundation, Inc., | 20 | * with this program; if not, write to the Free Software Foundation, Inc., |
21 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | 21 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
22 | * | 22 | * |
23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #ifndef __ACPI_BUS_H__ | 26 | #ifndef __ACPI_BUS_H__ |
27 | #define __ACPI_BUS_H__ | 27 | #define __ACPI_BUS_H__ |
28 | 28 | ||
29 | #include <linux/device.h> | 29 | #include <linux/device.h> |
30 | 30 | ||
31 | #include <acpi/acpi.h> | 31 | #include <acpi/acpi.h> |
32 | 32 | ||
33 | #define PREFIX "ACPI: " | 33 | #define PREFIX "ACPI: " |
34 | 34 | ||
35 | /* TBD: Make dynamic */ | 35 | /* TBD: Make dynamic */ |
36 | #define ACPI_MAX_HANDLES 10 | 36 | #define ACPI_MAX_HANDLES 10 |
37 | struct acpi_handle_list { | 37 | struct acpi_handle_list { |
38 | u32 count; | 38 | u32 count; |
39 | acpi_handle handles[ACPI_MAX_HANDLES]; | 39 | acpi_handle handles[ACPI_MAX_HANDLES]; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | /* acpi_utils.h */ | 42 | /* acpi_utils.h */ |
43 | acpi_status | 43 | acpi_status |
44 | acpi_extract_package(union acpi_object *package, | 44 | acpi_extract_package(union acpi_object *package, |
45 | struct acpi_buffer *format, struct acpi_buffer *buffer); | 45 | struct acpi_buffer *format, struct acpi_buffer *buffer); |
46 | acpi_status | 46 | acpi_status |
47 | acpi_evaluate_integer(acpi_handle handle, | 47 | acpi_evaluate_integer(acpi_handle handle, |
48 | acpi_string pathname, | 48 | acpi_string pathname, |
49 | struct acpi_object_list *arguments, unsigned long *data); | 49 | struct acpi_object_list *arguments, unsigned long *data); |
50 | acpi_status | 50 | acpi_status |
51 | acpi_evaluate_reference(acpi_handle handle, | 51 | acpi_evaluate_reference(acpi_handle handle, |
52 | acpi_string pathname, | 52 | acpi_string pathname, |
53 | struct acpi_object_list *arguments, | 53 | struct acpi_object_list *arguments, |
54 | struct acpi_handle_list *list); | 54 | struct acpi_handle_list *list); |
55 | 55 | ||
56 | #ifdef CONFIG_ACPI | 56 | #ifdef CONFIG_ACPI |
57 | 57 | ||
58 | #include <linux/proc_fs.h> | 58 | #include <linux/proc_fs.h> |
59 | 59 | ||
60 | #define ACPI_BUS_FILE_ROOT "acpi" | 60 | #define ACPI_BUS_FILE_ROOT "acpi" |
61 | extern struct proc_dir_entry *acpi_root_dir; | 61 | extern struct proc_dir_entry *acpi_root_dir; |
62 | 62 | ||
63 | enum acpi_bus_removal_type { | 63 | enum acpi_bus_removal_type { |
64 | ACPI_BUS_REMOVAL_NORMAL = 0, | 64 | ACPI_BUS_REMOVAL_NORMAL = 0, |
65 | ACPI_BUS_REMOVAL_EJECT, | 65 | ACPI_BUS_REMOVAL_EJECT, |
66 | ACPI_BUS_REMOVAL_SUPRISE, | 66 | ACPI_BUS_REMOVAL_SUPRISE, |
67 | ACPI_BUS_REMOVAL_TYPE_COUNT | 67 | ACPI_BUS_REMOVAL_TYPE_COUNT |
68 | }; | 68 | }; |
69 | 69 | ||
70 | enum acpi_bus_device_type { | 70 | enum acpi_bus_device_type { |
71 | ACPI_BUS_TYPE_DEVICE = 0, | 71 | ACPI_BUS_TYPE_DEVICE = 0, |
72 | ACPI_BUS_TYPE_POWER, | 72 | ACPI_BUS_TYPE_POWER, |
73 | ACPI_BUS_TYPE_PROCESSOR, | 73 | ACPI_BUS_TYPE_PROCESSOR, |
74 | ACPI_BUS_TYPE_THERMAL, | 74 | ACPI_BUS_TYPE_THERMAL, |
75 | ACPI_BUS_TYPE_SYSTEM, | 75 | ACPI_BUS_TYPE_SYSTEM, |
76 | ACPI_BUS_TYPE_POWER_BUTTON, | 76 | ACPI_BUS_TYPE_POWER_BUTTON, |
77 | ACPI_BUS_TYPE_SLEEP_BUTTON, | 77 | ACPI_BUS_TYPE_SLEEP_BUTTON, |
78 | ACPI_BUS_DEVICE_TYPE_COUNT | 78 | ACPI_BUS_DEVICE_TYPE_COUNT |
79 | }; | 79 | }; |
80 | 80 | ||
81 | struct acpi_driver; | 81 | struct acpi_driver; |
82 | struct acpi_device; | 82 | struct acpi_device; |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * ACPI Driver | 85 | * ACPI Driver |
86 | * ----------- | 86 | * ----------- |
87 | */ | 87 | */ |
88 | 88 | ||
89 | typedef int (*acpi_op_add) (struct acpi_device * device); | 89 | typedef int (*acpi_op_add) (struct acpi_device * device); |
90 | typedef int (*acpi_op_remove) (struct acpi_device * device, int type); | 90 | typedef int (*acpi_op_remove) (struct acpi_device * device, int type); |
91 | typedef int (*acpi_op_lock) (struct acpi_device * device, int type); | 91 | typedef int (*acpi_op_lock) (struct acpi_device * device, int type); |
92 | typedef int (*acpi_op_start) (struct acpi_device * device); | 92 | typedef int (*acpi_op_start) (struct acpi_device * device); |
93 | typedef int (*acpi_op_stop) (struct acpi_device * device, int type); | 93 | typedef int (*acpi_op_stop) (struct acpi_device * device, int type); |
94 | typedef int (*acpi_op_suspend) (struct acpi_device * device, | 94 | typedef int (*acpi_op_suspend) (struct acpi_device * device, |
95 | pm_message_t state); | 95 | pm_message_t state); |
96 | typedef int (*acpi_op_resume) (struct acpi_device * device); | 96 | typedef int (*acpi_op_resume) (struct acpi_device * device); |
97 | typedef int (*acpi_op_scan) (struct acpi_device * device); | 97 | typedef int (*acpi_op_scan) (struct acpi_device * device); |
98 | typedef int (*acpi_op_bind) (struct acpi_device * device); | 98 | typedef int (*acpi_op_bind) (struct acpi_device * device); |
99 | typedef int (*acpi_op_unbind) (struct acpi_device * device); | 99 | typedef int (*acpi_op_unbind) (struct acpi_device * device); |
100 | typedef int (*acpi_op_shutdown) (struct acpi_device * device); | 100 | typedef int (*acpi_op_shutdown) (struct acpi_device * device); |
101 | 101 | ||
102 | struct acpi_bus_ops { | 102 | struct acpi_bus_ops { |
103 | u32 acpi_op_add:1; | 103 | u32 acpi_op_add:1; |
104 | u32 acpi_op_remove:1; | 104 | u32 acpi_op_remove:1; |
105 | u32 acpi_op_lock:1; | 105 | u32 acpi_op_lock:1; |
106 | u32 acpi_op_start:1; | 106 | u32 acpi_op_start:1; |
107 | u32 acpi_op_stop:1; | 107 | u32 acpi_op_stop:1; |
108 | u32 acpi_op_suspend:1; | 108 | u32 acpi_op_suspend:1; |
109 | u32 acpi_op_resume:1; | 109 | u32 acpi_op_resume:1; |
110 | u32 acpi_op_scan:1; | 110 | u32 acpi_op_scan:1; |
111 | u32 acpi_op_bind:1; | 111 | u32 acpi_op_bind:1; |
112 | u32 acpi_op_unbind:1; | 112 | u32 acpi_op_unbind:1; |
113 | u32 acpi_op_shutdown:1; | 113 | u32 acpi_op_shutdown:1; |
114 | u32 reserved:21; | 114 | u32 reserved:21; |
115 | }; | 115 | }; |
116 | 116 | ||
117 | struct acpi_device_ops { | 117 | struct acpi_device_ops { |
118 | acpi_op_add add; | 118 | acpi_op_add add; |
119 | acpi_op_remove remove; | 119 | acpi_op_remove remove; |
120 | acpi_op_lock lock; | 120 | acpi_op_lock lock; |
121 | acpi_op_start start; | 121 | acpi_op_start start; |
122 | acpi_op_stop stop; | 122 | acpi_op_stop stop; |
123 | acpi_op_suspend suspend; | 123 | acpi_op_suspend suspend; |
124 | acpi_op_resume resume; | 124 | acpi_op_resume resume; |
125 | acpi_op_scan scan; | 125 | acpi_op_scan scan; |
126 | acpi_op_bind bind; | 126 | acpi_op_bind bind; |
127 | acpi_op_unbind unbind; | 127 | acpi_op_unbind unbind; |
128 | acpi_op_shutdown shutdown; | 128 | acpi_op_shutdown shutdown; |
129 | }; | 129 | }; |
130 | 130 | ||
131 | struct acpi_driver { | 131 | struct acpi_driver { |
132 | char name[80]; | 132 | char name[80]; |
133 | char class[80]; | 133 | char class[80]; |
134 | char *ids; /* Supported Hardware IDs */ | 134 | char *ids; /* Supported Hardware IDs */ |
135 | struct acpi_device_ops ops; | 135 | struct acpi_device_ops ops; |
136 | struct device_driver drv; | 136 | struct device_driver drv; |
137 | struct module *owner; | 137 | struct module *owner; |
138 | }; | 138 | }; |
139 | 139 | ||
140 | /* | 140 | /* |
141 | * ACPI Device | 141 | * ACPI Device |
142 | * ----------- | 142 | * ----------- |
143 | */ | 143 | */ |
144 | 144 | ||
145 | /* Status (_STA) */ | 145 | /* Status (_STA) */ |
146 | 146 | ||
147 | struct acpi_device_status { | 147 | struct acpi_device_status { |
148 | u32 present:1; | 148 | u32 present:1; |
149 | u32 enabled:1; | 149 | u32 enabled:1; |
150 | u32 show_in_ui:1; | 150 | u32 show_in_ui:1; |
151 | u32 functional:1; | 151 | u32 functional:1; |
152 | u32 battery_present:1; | 152 | u32 battery_present:1; |
153 | u32 reserved:27; | 153 | u32 reserved:27; |
154 | }; | 154 | }; |
155 | 155 | ||
156 | /* Flags */ | 156 | /* Flags */ |
157 | 157 | ||
158 | struct acpi_device_flags { | 158 | struct acpi_device_flags { |
159 | u32 dynamic_status:1; | 159 | u32 dynamic_status:1; |
160 | u32 hardware_id:1; | 160 | u32 hardware_id:1; |
161 | u32 compatible_ids:1; | 161 | u32 compatible_ids:1; |
162 | u32 bus_address:1; | 162 | u32 bus_address:1; |
163 | u32 unique_id:1; | 163 | u32 unique_id:1; |
164 | u32 removable:1; | 164 | u32 removable:1; |
165 | u32 ejectable:1; | 165 | u32 ejectable:1; |
166 | u32 lockable:1; | 166 | u32 lockable:1; |
167 | u32 suprise_removal_ok:1; | 167 | u32 suprise_removal_ok:1; |
168 | u32 power_manageable:1; | 168 | u32 power_manageable:1; |
169 | u32 performance_manageable:1; | 169 | u32 performance_manageable:1; |
170 | u32 wake_capable:1; /* Wakeup(_PRW) supported? */ | 170 | u32 wake_capable:1; /* Wakeup(_PRW) supported? */ |
171 | u32 force_power_state:1; | 171 | u32 force_power_state:1; |
172 | u32 reserved:19; | 172 | u32 reserved:19; |
173 | }; | 173 | }; |
174 | 174 | ||
175 | /* File System */ | 175 | /* File System */ |
176 | 176 | ||
177 | struct acpi_device_dir { | 177 | struct acpi_device_dir { |
178 | struct proc_dir_entry *entry; | 178 | struct proc_dir_entry *entry; |
179 | }; | 179 | }; |
180 | 180 | ||
181 | #define acpi_device_dir(d) ((d)->dir.entry) | 181 | #define acpi_device_dir(d) ((d)->dir.entry) |
182 | 182 | ||
183 | /* Plug and Play */ | 183 | /* Plug and Play */ |
184 | 184 | ||
185 | typedef char acpi_bus_id[5]; | 185 | typedef char acpi_bus_id[5]; |
186 | typedef unsigned long acpi_bus_address; | 186 | typedef unsigned long acpi_bus_address; |
187 | typedef char acpi_hardware_id[15]; | 187 | typedef char acpi_hardware_id[15]; |
188 | typedef char acpi_unique_id[9]; | 188 | typedef char acpi_unique_id[9]; |
189 | typedef char acpi_device_name[40]; | 189 | typedef char acpi_device_name[40]; |
190 | typedef char acpi_device_class[20]; | 190 | typedef char acpi_device_class[20]; |
191 | 191 | ||
192 | struct acpi_device_pnp { | 192 | struct acpi_device_pnp { |
193 | acpi_bus_id bus_id; /* Object name */ | 193 | acpi_bus_id bus_id; /* Object name */ |
194 | acpi_bus_address bus_address; /* _ADR */ | 194 | acpi_bus_address bus_address; /* _ADR */ |
195 | acpi_hardware_id hardware_id; /* _HID */ | 195 | acpi_hardware_id hardware_id; /* _HID */ |
196 | struct acpi_compatible_id_list *cid_list; /* _CIDs */ | 196 | struct acpi_compatible_id_list *cid_list; /* _CIDs */ |
197 | acpi_unique_id unique_id; /* _UID */ | 197 | acpi_unique_id unique_id; /* _UID */ |
198 | acpi_device_name device_name; /* Driver-determined */ | 198 | acpi_device_name device_name; /* Driver-determined */ |
199 | acpi_device_class device_class; /* " */ | 199 | acpi_device_class device_class; /* " */ |
200 | }; | 200 | }; |
201 | 201 | ||
202 | #define acpi_device_bid(d) ((d)->pnp.bus_id) | 202 | #define acpi_device_bid(d) ((d)->pnp.bus_id) |
203 | #define acpi_device_adr(d) ((d)->pnp.bus_address) | 203 | #define acpi_device_adr(d) ((d)->pnp.bus_address) |
204 | #define acpi_device_hid(d) ((d)->pnp.hardware_id) | 204 | #define acpi_device_hid(d) ((d)->pnp.hardware_id) |
205 | #define acpi_device_uid(d) ((d)->pnp.unique_id) | 205 | #define acpi_device_uid(d) ((d)->pnp.unique_id) |
206 | #define acpi_device_name(d) ((d)->pnp.device_name) | 206 | #define acpi_device_name(d) ((d)->pnp.device_name) |
207 | #define acpi_device_class(d) ((d)->pnp.device_class) | 207 | #define acpi_device_class(d) ((d)->pnp.device_class) |
208 | 208 | ||
209 | /* Power Management */ | 209 | /* Power Management */ |
210 | 210 | ||
211 | struct acpi_device_power_flags { | 211 | struct acpi_device_power_flags { |
212 | u32 explicit_get:1; /* _PSC present? */ | 212 | u32 explicit_get:1; /* _PSC present? */ |
213 | u32 power_resources:1; /* Power resources */ | 213 | u32 power_resources:1; /* Power resources */ |
214 | u32 inrush_current:1; /* Serialize Dx->D0 */ | 214 | u32 inrush_current:1; /* Serialize Dx->D0 */ |
215 | u32 power_removed:1; /* Optimize Dx->D0 */ | 215 | u32 power_removed:1; /* Optimize Dx->D0 */ |
216 | u32 reserved:28; | 216 | u32 reserved:28; |
217 | }; | 217 | }; |
218 | 218 | ||
219 | struct acpi_device_power_state { | 219 | struct acpi_device_power_state { |
220 | struct { | 220 | struct { |
221 | u8 valid:1; | 221 | u8 valid:1; |
222 | u8 explicit_set:1; /* _PSx present? */ | 222 | u8 explicit_set:1; /* _PSx present? */ |
223 | u8 reserved:6; | 223 | u8 reserved:6; |
224 | } flags; | 224 | } flags; |
225 | int power; /* % Power (compared to D0) */ | 225 | int power; /* % Power (compared to D0) */ |
226 | int latency; /* Dx->D0 time (microseconds) */ | 226 | int latency; /* Dx->D0 time (microseconds) */ |
227 | struct acpi_handle_list resources; /* Power resources referenced */ | 227 | struct acpi_handle_list resources; /* Power resources referenced */ |
228 | }; | 228 | }; |
229 | 229 | ||
230 | struct acpi_device_power { | 230 | struct acpi_device_power { |
231 | int state; /* Current state */ | 231 | int state; /* Current state */ |
232 | struct acpi_device_power_flags flags; | 232 | struct acpi_device_power_flags flags; |
233 | struct acpi_device_power_state states[4]; /* Power states (D0-D3) */ | 233 | struct acpi_device_power_state states[4]; /* Power states (D0-D3) */ |
234 | }; | 234 | }; |
235 | 235 | ||
236 | /* Performance Management */ | 236 | /* Performance Management */ |
237 | 237 | ||
238 | struct acpi_device_perf_flags { | 238 | struct acpi_device_perf_flags { |
239 | u8 reserved:8; | 239 | u8 reserved:8; |
240 | }; | 240 | }; |
241 | 241 | ||
242 | struct acpi_device_perf_state { | 242 | struct acpi_device_perf_state { |
243 | struct { | 243 | struct { |
244 | u8 valid:1; | 244 | u8 valid:1; |
245 | u8 reserved:7; | 245 | u8 reserved:7; |
246 | } flags; | 246 | } flags; |
247 | u8 power; /* % Power (compared to P0) */ | 247 | u8 power; /* % Power (compared to P0) */ |
248 | u8 performance; /* % Performance ( " ) */ | 248 | u8 performance; /* % Performance ( " ) */ |
249 | int latency; /* Px->P0 time (microseconds) */ | 249 | int latency; /* Px->P0 time (microseconds) */ |
250 | }; | 250 | }; |
251 | 251 | ||
252 | struct acpi_device_perf { | 252 | struct acpi_device_perf { |
253 | int state; | 253 | int state; |
254 | struct acpi_device_perf_flags flags; | 254 | struct acpi_device_perf_flags flags; |
255 | int state_count; | 255 | int state_count; |
256 | struct acpi_device_perf_state *states; | 256 | struct acpi_device_perf_state *states; |
257 | }; | 257 | }; |
258 | 258 | ||
259 | /* Wakeup Management */ | 259 | /* Wakeup Management */ |
260 | struct acpi_device_wakeup_flags { | 260 | struct acpi_device_wakeup_flags { |
261 | u8 valid:1; /* Can successfully enable wakeup? */ | 261 | u8 valid:1; /* Can successfully enable wakeup? */ |
262 | u8 run_wake:1; /* Run-Wake GPE devices */ | 262 | u8 run_wake:1; /* Run-Wake GPE devices */ |
263 | }; | 263 | }; |
264 | 264 | ||
265 | struct acpi_device_wakeup_state { | 265 | struct acpi_device_wakeup_state { |
266 | u8 enabled:1; | 266 | u8 enabled:1; |
267 | u8 active:1; | 267 | u8 active:1; |
268 | }; | 268 | }; |
269 | 269 | ||
270 | struct acpi_device_wakeup { | 270 | struct acpi_device_wakeup { |
271 | acpi_handle gpe_device; | 271 | acpi_handle gpe_device; |
272 | acpi_integer gpe_number; | 272 | acpi_integer gpe_number; |
273 | acpi_integer sleep_state; | 273 | acpi_integer sleep_state; |
274 | struct acpi_handle_list resources; | 274 | struct acpi_handle_list resources; |
275 | struct acpi_device_wakeup_state state; | 275 | struct acpi_device_wakeup_state state; |
276 | struct acpi_device_wakeup_flags flags; | 276 | struct acpi_device_wakeup_flags flags; |
277 | }; | 277 | }; |
278 | 278 | ||
279 | /* Device */ | 279 | /* Device */ |
280 | 280 | ||
281 | struct acpi_device { | 281 | struct acpi_device { |
282 | acpi_handle handle; | 282 | acpi_handle handle; |
283 | struct acpi_device *parent; | 283 | struct acpi_device *parent; |
284 | struct list_head children; | 284 | struct list_head children; |
285 | struct list_head node; | 285 | struct list_head node; |
286 | struct list_head wakeup_list; | 286 | struct list_head wakeup_list; |
287 | struct list_head g_list; | 287 | struct list_head g_list; |
288 | struct acpi_device_status status; | 288 | struct acpi_device_status status; |
289 | struct acpi_device_flags flags; | 289 | struct acpi_device_flags flags; |
290 | struct acpi_device_pnp pnp; | 290 | struct acpi_device_pnp pnp; |
291 | struct acpi_device_power power; | 291 | struct acpi_device_power power; |
292 | struct acpi_device_wakeup wakeup; | 292 | struct acpi_device_wakeup wakeup; |
293 | struct acpi_device_perf performance; | 293 | struct acpi_device_perf performance; |
294 | struct acpi_device_dir dir; | 294 | struct acpi_device_dir dir; |
295 | struct acpi_device_ops ops; | 295 | struct acpi_device_ops ops; |
296 | struct acpi_driver *driver; | 296 | struct acpi_driver *driver; |
297 | void *driver_data; | 297 | void *driver_data; |
298 | struct device dev; | 298 | struct device dev; |
299 | struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ | 299 | struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ |
300 | enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ | 300 | enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ |
301 | }; | 301 | }; |
302 | 302 | ||
303 | #define acpi_driver_data(d) ((d)->driver_data) | 303 | #define acpi_driver_data(d) ((d)->driver_data) |
304 | #define to_acpi_device(d) container_of(d, struct acpi_device, dev) | 304 | #define to_acpi_device(d) container_of(d, struct acpi_device, dev) |
305 | #define to_acpi_driver(d) container_of(d, struct acpi_driver, drv) | 305 | #define to_acpi_driver(d) container_of(d, struct acpi_driver, drv) |
306 | 306 | ||
307 | /* acpi_device.dev.bus == &acpi_bus_type */ | 307 | /* acpi_device.dev.bus == &acpi_bus_type */ |
308 | extern struct bus_type acpi_bus_type; | 308 | extern struct bus_type acpi_bus_type; |
309 | 309 | ||
310 | /* | 310 | /* |
311 | * Events | 311 | * Events |
312 | * ------ | 312 | * ------ |
313 | */ | 313 | */ |
314 | 314 | ||
315 | struct acpi_bus_event { | 315 | struct acpi_bus_event { |
316 | struct list_head node; | 316 | struct list_head node; |
317 | acpi_device_class device_class; | 317 | acpi_device_class device_class; |
318 | acpi_bus_id bus_id; | 318 | acpi_bus_id bus_id; |
319 | u32 type; | 319 | u32 type; |
320 | u32 data; | 320 | u32 data; |
321 | }; | 321 | }; |
322 | 322 | ||
323 | extern struct kset acpi_subsys; | 323 | extern struct kset acpi_subsys; |
324 | 324 | extern int acpi_bus_generate_genetlink_event(struct acpi_device *device, | |
325 | u8 type, int data); | ||
325 | /* | 326 | /* |
326 | * External Functions | 327 | * External Functions |
327 | */ | 328 | */ |
328 | 329 | ||
329 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device); | 330 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device); |
330 | void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context); | 331 | void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context); |
331 | int acpi_bus_get_status(struct acpi_device *device); | 332 | int acpi_bus_get_status(struct acpi_device *device); |
332 | int acpi_bus_get_power(acpi_handle handle, int *state); | 333 | int acpi_bus_get_power(acpi_handle handle, int *state); |
333 | int acpi_bus_set_power(acpi_handle handle, int state); | 334 | int acpi_bus_set_power(acpi_handle handle, int state); |
334 | int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data); | 335 | int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data); |
335 | int acpi_bus_receive_event(struct acpi_bus_event *event); | 336 | int acpi_bus_receive_event(struct acpi_bus_event *event); |
336 | int acpi_bus_register_driver(struct acpi_driver *driver); | 337 | int acpi_bus_register_driver(struct acpi_driver *driver); |
337 | void acpi_bus_unregister_driver(struct acpi_driver *driver); | 338 | void acpi_bus_unregister_driver(struct acpi_driver *driver); |
338 | int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, | 339 | int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, |
339 | acpi_handle handle, int type); | 340 | acpi_handle handle, int type); |
340 | int acpi_bus_trim(struct acpi_device *start, int rmdevice); | 341 | int acpi_bus_trim(struct acpi_device *start, int rmdevice); |
341 | int acpi_bus_start(struct acpi_device *device); | 342 | int acpi_bus_start(struct acpi_device *device); |
342 | acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); | 343 | acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); |
343 | int acpi_match_ids(struct acpi_device *device, char *ids); | 344 | int acpi_match_ids(struct acpi_device *device, char *ids); |
344 | int acpi_create_dir(struct acpi_device *); | 345 | int acpi_create_dir(struct acpi_device *); |
345 | void acpi_remove_dir(struct acpi_device *); | 346 | void acpi_remove_dir(struct acpi_device *); |
346 | 347 | ||
347 | /* | 348 | /* |
348 | * Bind physical devices with ACPI devices | 349 | * Bind physical devices with ACPI devices |
349 | */ | 350 | */ |
350 | #include <linux/device.h> | 351 | #include <linux/device.h> |
351 | struct acpi_bus_type { | 352 | struct acpi_bus_type { |
352 | struct list_head list; | 353 | struct list_head list; |
353 | struct bus_type *bus; | 354 | struct bus_type *bus; |
354 | /* For general devices under the bus */ | 355 | /* For general devices under the bus */ |
355 | int (*find_device) (struct device *, acpi_handle *); | 356 | int (*find_device) (struct device *, acpi_handle *); |
356 | /* For bridges, such as PCI root bridge, IDE controller */ | 357 | /* For bridges, such as PCI root bridge, IDE controller */ |
357 | int (*find_bridge) (struct device *, acpi_handle *); | 358 | int (*find_bridge) (struct device *, acpi_handle *); |
358 | }; | 359 | }; |
359 | int register_acpi_bus_type(struct acpi_bus_type *); | 360 | int register_acpi_bus_type(struct acpi_bus_type *); |
360 | int unregister_acpi_bus_type(struct acpi_bus_type *); | 361 | int unregister_acpi_bus_type(struct acpi_bus_type *); |
361 | struct device *acpi_get_physical_device(acpi_handle); | 362 | struct device *acpi_get_physical_device(acpi_handle); |
362 | /* helper */ | 363 | /* helper */ |
363 | acpi_handle acpi_get_child(acpi_handle, acpi_integer); | 364 | acpi_handle acpi_get_child(acpi_handle, acpi_integer); |
364 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); | 365 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); |
365 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) | 366 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) |
366 | 367 | ||
367 | #endif /* CONFIG_ACPI */ | 368 | #endif /* CONFIG_ACPI */ |
368 | 369 | ||
369 | #endif /*__ACPI_BUS_H__*/ | 370 | #endif /*__ACPI_BUS_H__*/ |
370 | 371 |