diff options
Diffstat (limited to 'drivers/acpi/ac.c')
-rw-r--r-- | drivers/acpi/ac.c | 130 |
1 files changed, 128 insertions, 2 deletions
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index c67f6f5ad611..36b0e61f9c09 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
@@ -30,6 +30,10 @@ | |||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/dmi.h> | 31 | #include <linux/dmi.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
34 | #include <linux/proc_fs.h> | ||
35 | #include <linux/seq_file.h> | ||
36 | #endif | ||
33 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
34 | #include <linux/power_supply.h> | 38 | #include <linux/power_supply.h> |
35 | #include <linux/acpi.h> | 39 | #include <linux/acpi.h> |
@@ -52,6 +56,7 @@ MODULE_AUTHOR("Paul Diefenbaugh"); | |||
52 | MODULE_DESCRIPTION("ACPI AC Adapter Driver"); | 56 | MODULE_DESCRIPTION("ACPI AC Adapter Driver"); |
53 | MODULE_LICENSE("GPL"); | 57 | MODULE_LICENSE("GPL"); |
54 | 58 | ||
59 | |||
55 | static int acpi_ac_add(struct acpi_device *device); | 60 | static int acpi_ac_add(struct acpi_device *device); |
56 | static int acpi_ac_remove(struct acpi_device *device); | 61 | static int acpi_ac_remove(struct acpi_device *device); |
57 | static void acpi_ac_notify(struct acpi_device *device, u32 event); | 62 | static void acpi_ac_notify(struct acpi_device *device, u32 event); |
@@ -67,6 +72,13 @@ static int acpi_ac_resume(struct device *dev); | |||
67 | #endif | 72 | #endif |
68 | static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); | 73 | static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); |
69 | 74 | ||
75 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
76 | extern struct proc_dir_entry *acpi_lock_ac_dir(void); | ||
77 | extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); | ||
78 | static int acpi_ac_open_fs(struct inode *inode, struct file *file); | ||
79 | #endif | ||
80 | |||
81 | |||
70 | static int ac_sleep_before_get_state_ms; | 82 | static int ac_sleep_before_get_state_ms; |
71 | 83 | ||
72 | static struct acpi_driver acpi_ac_driver = { | 84 | static struct acpi_driver acpi_ac_driver = { |
@@ -91,6 +103,16 @@ struct acpi_ac { | |||
91 | 103 | ||
92 | #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) | 104 | #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) |
93 | 105 | ||
106 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
107 | static const struct file_operations acpi_ac_fops = { | ||
108 | .owner = THIS_MODULE, | ||
109 | .open = acpi_ac_open_fs, | ||
110 | .read = seq_read, | ||
111 | .llseek = seq_lseek, | ||
112 | .release = single_release, | ||
113 | }; | ||
114 | #endif | ||
115 | |||
94 | /* -------------------------------------------------------------------------- | 116 | /* -------------------------------------------------------------------------- |
95 | AC Adapter Management | 117 | AC Adapter Management |
96 | -------------------------------------------------------------------------- */ | 118 | -------------------------------------------------------------------------- */ |
@@ -143,6 +165,83 @@ static enum power_supply_property ac_props[] = { | |||
143 | POWER_SUPPLY_PROP_ONLINE, | 165 | POWER_SUPPLY_PROP_ONLINE, |
144 | }; | 166 | }; |
145 | 167 | ||
168 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
169 | /* -------------------------------------------------------------------------- | ||
170 | FS Interface (/proc) | ||
171 | -------------------------------------------------------------------------- */ | ||
172 | |||
173 | static struct proc_dir_entry *acpi_ac_dir; | ||
174 | |||
175 | static int acpi_ac_seq_show(struct seq_file *seq, void *offset) | ||
176 | { | ||
177 | struct acpi_ac *ac = seq->private; | ||
178 | |||
179 | |||
180 | if (!ac) | ||
181 | return 0; | ||
182 | |||
183 | if (acpi_ac_get_state(ac)) { | ||
184 | seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | seq_puts(seq, "state: "); | ||
189 | switch (ac->state) { | ||
190 | case ACPI_AC_STATUS_OFFLINE: | ||
191 | seq_puts(seq, "off-line\n"); | ||
192 | break; | ||
193 | case ACPI_AC_STATUS_ONLINE: | ||
194 | seq_puts(seq, "on-line\n"); | ||
195 | break; | ||
196 | default: | ||
197 | seq_puts(seq, "unknown\n"); | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int acpi_ac_open_fs(struct inode *inode, struct file *file) | ||
205 | { | ||
206 | return single_open(file, acpi_ac_seq_show, PDE_DATA(inode)); | ||
207 | } | ||
208 | |||
209 | static int acpi_ac_add_fs(struct acpi_ac *ac) | ||
210 | { | ||
211 | struct proc_dir_entry *entry = NULL; | ||
212 | |||
213 | printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded," | ||
214 | " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); | ||
215 | if (!acpi_device_dir(ac->device)) { | ||
216 | acpi_device_dir(ac->device) = | ||
217 | proc_mkdir(acpi_device_bid(ac->device), acpi_ac_dir); | ||
218 | if (!acpi_device_dir(ac->device)) | ||
219 | return -ENODEV; | ||
220 | } | ||
221 | |||
222 | /* 'state' [R] */ | ||
223 | entry = proc_create_data(ACPI_AC_FILE_STATE, | ||
224 | S_IRUGO, acpi_device_dir(ac->device), | ||
225 | &acpi_ac_fops, ac); | ||
226 | if (!entry) | ||
227 | return -ENODEV; | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int acpi_ac_remove_fs(struct acpi_ac *ac) | ||
232 | { | ||
233 | |||
234 | if (acpi_device_dir(ac->device)) { | ||
235 | remove_proc_entry(ACPI_AC_FILE_STATE, | ||
236 | acpi_device_dir(ac->device)); | ||
237 | remove_proc_entry(acpi_device_bid(ac->device), acpi_ac_dir); | ||
238 | acpi_device_dir(ac->device) = NULL; | ||
239 | } | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | #endif | ||
244 | |||
146 | /* -------------------------------------------------------------------------- | 245 | /* -------------------------------------------------------------------------- |
147 | Driver Model | 246 | Driver Model |
148 | -------------------------------------------------------------------------- */ | 247 | -------------------------------------------------------------------------- */ |
@@ -243,6 +342,11 @@ static int acpi_ac_add(struct acpi_device *device) | |||
243 | goto end; | 342 | goto end; |
244 | 343 | ||
245 | ac->charger.name = acpi_device_bid(device); | 344 | ac->charger.name = acpi_device_bid(device); |
345 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
346 | result = acpi_ac_add_fs(ac); | ||
347 | if (result) | ||
348 | goto end; | ||
349 | #endif | ||
246 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; | 350 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; |
247 | ac->charger.properties = ac_props; | 351 | ac->charger.properties = ac_props; |
248 | ac->charger.num_properties = ARRAY_SIZE(ac_props); | 352 | ac->charger.num_properties = ARRAY_SIZE(ac_props); |
@@ -258,8 +362,12 @@ static int acpi_ac_add(struct acpi_device *device) | |||
258 | ac->battery_nb.notifier_call = acpi_ac_battery_notify; | 362 | ac->battery_nb.notifier_call = acpi_ac_battery_notify; |
259 | register_acpi_notifier(&ac->battery_nb); | 363 | register_acpi_notifier(&ac->battery_nb); |
260 | end: | 364 | end: |
261 | if (result) | 365 | if (result) { |
366 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
367 | acpi_ac_remove_fs(ac); | ||
368 | #endif | ||
262 | kfree(ac); | 369 | kfree(ac); |
370 | } | ||
263 | 371 | ||
264 | dmi_check_system(ac_dmi_table); | 372 | dmi_check_system(ac_dmi_table); |
265 | return result; | 373 | return result; |
@@ -303,6 +411,10 @@ static int acpi_ac_remove(struct acpi_device *device) | |||
303 | power_supply_unregister(&ac->charger); | 411 | power_supply_unregister(&ac->charger); |
304 | unregister_acpi_notifier(&ac->battery_nb); | 412 | unregister_acpi_notifier(&ac->battery_nb); |
305 | 413 | ||
414 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
415 | acpi_ac_remove_fs(ac); | ||
416 | #endif | ||
417 | |||
306 | kfree(ac); | 418 | kfree(ac); |
307 | 419 | ||
308 | return 0; | 420 | return 0; |
@@ -315,9 +427,20 @@ static int __init acpi_ac_init(void) | |||
315 | if (acpi_disabled) | 427 | if (acpi_disabled) |
316 | return -ENODEV; | 428 | return -ENODEV; |
317 | 429 | ||
430 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
431 | acpi_ac_dir = acpi_lock_ac_dir(); | ||
432 | if (!acpi_ac_dir) | ||
433 | return -ENODEV; | ||
434 | #endif | ||
435 | |||
436 | |||
318 | result = acpi_bus_register_driver(&acpi_ac_driver); | 437 | result = acpi_bus_register_driver(&acpi_ac_driver); |
319 | if (result < 0) | 438 | if (result < 0) { |
439 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
440 | acpi_unlock_ac_dir(acpi_ac_dir); | ||
441 | #endif | ||
320 | return -ENODEV; | 442 | return -ENODEV; |
443 | } | ||
321 | 444 | ||
322 | return 0; | 445 | return 0; |
323 | } | 446 | } |
@@ -325,6 +448,9 @@ static int __init acpi_ac_init(void) | |||
325 | static void __exit acpi_ac_exit(void) | 448 | static void __exit acpi_ac_exit(void) |
326 | { | 449 | { |
327 | acpi_bus_unregister_driver(&acpi_ac_driver); | 450 | acpi_bus_unregister_driver(&acpi_ac_driver); |
451 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
452 | acpi_unlock_ac_dir(acpi_ac_dir); | ||
453 | #endif | ||
328 | } | 454 | } |
329 | module_init(acpi_ac_init); | 455 | module_init(acpi_ac_init); |
330 | module_exit(acpi_ac_exit); | 456 | module_exit(acpi_ac_exit); |