diff options
Diffstat (limited to 'drivers/acpi/button.c')
-rw-r--r-- | drivers/acpi/button.c | 174 |
1 files changed, 67 insertions, 107 deletions
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 76bbb78a5ad..d27d072472f 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -78,8 +78,6 @@ static int acpi_button_add(struct acpi_device *device); | |||
78 | static int acpi_button_remove(struct acpi_device *device, int type); | 78 | static int acpi_button_remove(struct acpi_device *device, int type); |
79 | static int acpi_button_resume(struct acpi_device *device); | 79 | static int acpi_button_resume(struct acpi_device *device); |
80 | static void acpi_button_notify(struct acpi_device *device, u32 event); | 80 | static void acpi_button_notify(struct acpi_device *device, u32 event); |
81 | static int acpi_button_info_open_fs(struct inode *inode, struct file *file); | ||
82 | static int acpi_button_state_open_fs(struct inode *inode, struct file *file); | ||
83 | 81 | ||
84 | static struct acpi_driver acpi_button_driver = { | 82 | static struct acpi_driver acpi_button_driver = { |
85 | .name = "button", | 83 | .name = "button", |
@@ -98,22 +96,7 @@ struct acpi_button { | |||
98 | struct input_dev *input; | 96 | struct input_dev *input; |
99 | char phys[32]; /* for input device */ | 97 | char phys[32]; /* for input device */ |
100 | unsigned long pushed; | 98 | unsigned long pushed; |
101 | }; | 99 | bool wakeup_enabled; |
102 | |||
103 | static const struct file_operations acpi_button_info_fops = { | ||
104 | .owner = THIS_MODULE, | ||
105 | .open = acpi_button_info_open_fs, | ||
106 | .read = seq_read, | ||
107 | .llseek = seq_lseek, | ||
108 | .release = single_release, | ||
109 | }; | ||
110 | |||
111 | static const struct file_operations acpi_button_state_fops = { | ||
112 | .owner = THIS_MODULE, | ||
113 | .open = acpi_button_state_open_fs, | ||
114 | .read = seq_read, | ||
115 | .llseek = seq_lseek, | ||
116 | .release = single_release, | ||
117 | }; | 100 | }; |
118 | 101 | ||
119 | static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); | 102 | static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); |
@@ -124,20 +107,7 @@ static struct acpi_device *lid_device; | |||
124 | -------------------------------------------------------------------------- */ | 107 | -------------------------------------------------------------------------- */ |
125 | 108 | ||
126 | static struct proc_dir_entry *acpi_button_dir; | 109 | static struct proc_dir_entry *acpi_button_dir; |
127 | 110 | static struct proc_dir_entry *acpi_lid_dir; | |
128 | static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) | ||
129 | { | ||
130 | struct acpi_device *device = seq->private; | ||
131 | |||
132 | seq_printf(seq, "type: %s\n", | ||
133 | acpi_device_name(device)); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int acpi_button_info_open_fs(struct inode *inode, struct file *file) | ||
138 | { | ||
139 | return single_open(file, acpi_button_info_seq_show, PDE(inode)->data); | ||
140 | } | ||
141 | 111 | ||
142 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) | 112 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) |
143 | { | 113 | { |
@@ -157,77 +127,85 @@ static int acpi_button_state_open_fs(struct inode *inode, struct file *file) | |||
157 | return single_open(file, acpi_button_state_seq_show, PDE(inode)->data); | 127 | return single_open(file, acpi_button_state_seq_show, PDE(inode)->data); |
158 | } | 128 | } |
159 | 129 | ||
160 | static struct proc_dir_entry *acpi_power_dir; | 130 | static const struct file_operations acpi_button_state_fops = { |
161 | static struct proc_dir_entry *acpi_sleep_dir; | 131 | .owner = THIS_MODULE, |
162 | static struct proc_dir_entry *acpi_lid_dir; | 132 | .open = acpi_button_state_open_fs, |
133 | .read = seq_read, | ||
134 | .llseek = seq_lseek, | ||
135 | .release = single_release, | ||
136 | }; | ||
163 | 137 | ||
164 | static int acpi_button_add_fs(struct acpi_device *device) | 138 | static int acpi_button_add_fs(struct acpi_device *device) |
165 | { | 139 | { |
166 | struct acpi_button *button = acpi_driver_data(device); | 140 | struct acpi_button *button = acpi_driver_data(device); |
167 | struct proc_dir_entry *entry = NULL; | 141 | struct proc_dir_entry *entry = NULL; |
142 | int ret = 0; | ||
168 | 143 | ||
169 | switch (button->type) { | 144 | /* procfs I/F for ACPI lid device only */ |
170 | case ACPI_BUTTON_TYPE_POWER: | 145 | if (button->type != ACPI_BUTTON_TYPE_LID) |
171 | if (!acpi_power_dir) | 146 | return 0; |
172 | acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, | 147 | |
173 | acpi_button_dir); | 148 | if (acpi_button_dir || acpi_lid_dir) { |
174 | entry = acpi_power_dir; | 149 | printk(KERN_ERR PREFIX "More than one Lid device found!\n"); |
175 | break; | 150 | return -EEXIST; |
176 | case ACPI_BUTTON_TYPE_SLEEP: | ||
177 | if (!acpi_sleep_dir) | ||
178 | acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, | ||
179 | acpi_button_dir); | ||
180 | entry = acpi_sleep_dir; | ||
181 | break; | ||
182 | case ACPI_BUTTON_TYPE_LID: | ||
183 | if (!acpi_lid_dir) | ||
184 | acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, | ||
185 | acpi_button_dir); | ||
186 | entry = acpi_lid_dir; | ||
187 | break; | ||
188 | } | 151 | } |
189 | 152 | ||
190 | if (!entry) | 153 | /* create /proc/acpi/button */ |
154 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
155 | if (!acpi_button_dir) | ||
191 | return -ENODEV; | 156 | return -ENODEV; |
192 | 157 | ||
193 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); | 158 | /* create /proc/acpi/button/lid */ |
194 | if (!acpi_device_dir(device)) | 159 | acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); |
195 | return -ENODEV; | 160 | if (!acpi_lid_dir) { |
161 | ret = -ENODEV; | ||
162 | goto remove_button_dir; | ||
163 | } | ||
196 | 164 | ||
197 | /* 'info' [R] */ | 165 | /* create /proc/acpi/button/lid/LID/ */ |
198 | entry = proc_create_data(ACPI_BUTTON_FILE_INFO, | 166 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir); |
199 | S_IRUGO, acpi_device_dir(device), | 167 | if (!acpi_device_dir(device)) { |
200 | &acpi_button_info_fops, device); | 168 | ret = -ENODEV; |
201 | if (!entry) | 169 | goto remove_lid_dir; |
202 | return -ENODEV; | 170 | } |
203 | 171 | ||
204 | /* show lid state [R] */ | 172 | /* create /proc/acpi/button/lid/LID/state */ |
205 | if (button->type == ACPI_BUTTON_TYPE_LID) { | 173 | entry = proc_create_data(ACPI_BUTTON_FILE_STATE, |
206 | entry = proc_create_data(ACPI_BUTTON_FILE_STATE, | 174 | S_IRUGO, acpi_device_dir(device), |
207 | S_IRUGO, acpi_device_dir(device), | 175 | &acpi_button_state_fops, device); |
208 | &acpi_button_state_fops, device); | 176 | if (!entry) { |
209 | if (!entry) | 177 | ret = -ENODEV; |
210 | return -ENODEV; | 178 | goto remove_dev_dir; |
211 | } | 179 | } |
212 | 180 | ||
213 | return 0; | 181 | done: |
182 | return ret; | ||
183 | |||
184 | remove_dev_dir: | ||
185 | remove_proc_entry(acpi_device_bid(device), | ||
186 | acpi_lid_dir); | ||
187 | acpi_device_dir(device) = NULL; | ||
188 | remove_lid_dir: | ||
189 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); | ||
190 | remove_button_dir: | ||
191 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
192 | goto done; | ||
214 | } | 193 | } |
215 | 194 | ||
216 | static int acpi_button_remove_fs(struct acpi_device *device) | 195 | static int acpi_button_remove_fs(struct acpi_device *device) |
217 | { | 196 | { |
218 | struct acpi_button *button = acpi_driver_data(device); | 197 | struct acpi_button *button = acpi_driver_data(device); |
219 | 198 | ||
220 | if (acpi_device_dir(device)) { | 199 | if (button->type != ACPI_BUTTON_TYPE_LID) |
221 | if (button->type == ACPI_BUTTON_TYPE_LID) | 200 | return 0; |
222 | remove_proc_entry(ACPI_BUTTON_FILE_STATE, | ||
223 | acpi_device_dir(device)); | ||
224 | remove_proc_entry(ACPI_BUTTON_FILE_INFO, | ||
225 | acpi_device_dir(device)); | ||
226 | 201 | ||
227 | remove_proc_entry(acpi_device_bid(device), | 202 | remove_proc_entry(ACPI_BUTTON_FILE_STATE, |
228 | acpi_device_dir(device)->parent); | 203 | acpi_device_dir(device)); |
229 | acpi_device_dir(device) = NULL; | 204 | remove_proc_entry(acpi_device_bid(device), |
230 | } | 205 | acpi_lid_dir); |
206 | acpi_device_dir(device) = NULL; | ||
207 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); | ||
208 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
231 | 209 | ||
232 | return 0; | 210 | return 0; |
233 | } | 211 | } |
@@ -430,8 +408,10 @@ static int acpi_button_add(struct acpi_device *device) | |||
430 | /* Button's GPE is run-wake GPE */ | 408 | /* Button's GPE is run-wake GPE */ |
431 | acpi_enable_gpe(device->wakeup.gpe_device, | 409 | acpi_enable_gpe(device->wakeup.gpe_device, |
432 | device->wakeup.gpe_number); | 410 | device->wakeup.gpe_number); |
433 | device->wakeup.run_wake_count++; | 411 | if (!device_may_wakeup(&device->dev)) { |
434 | device_set_wakeup_enable(&device->dev, true); | 412 | device_set_wakeup_enable(&device->dev, true); |
413 | button->wakeup_enabled = true; | ||
414 | } | ||
435 | } | 415 | } |
436 | 416 | ||
437 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); | 417 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); |
@@ -453,8 +433,8 @@ static int acpi_button_remove(struct acpi_device *device, int type) | |||
453 | if (device->wakeup.flags.valid) { | 433 | if (device->wakeup.flags.valid) { |
454 | acpi_disable_gpe(device->wakeup.gpe_device, | 434 | acpi_disable_gpe(device->wakeup.gpe_device, |
455 | device->wakeup.gpe_number); | 435 | device->wakeup.gpe_number); |
456 | device->wakeup.run_wake_count--; | 436 | if (button->wakeup_enabled) |
457 | device_set_wakeup_enable(&device->dev, false); | 437 | device_set_wakeup_enable(&device->dev, false); |
458 | } | 438 | } |
459 | 439 | ||
460 | acpi_button_remove_fs(device); | 440 | acpi_button_remove_fs(device); |
@@ -465,32 +445,12 @@ static int acpi_button_remove(struct acpi_device *device, int type) | |||
465 | 445 | ||
466 | static int __init acpi_button_init(void) | 446 | static int __init acpi_button_init(void) |
467 | { | 447 | { |
468 | int result; | 448 | return acpi_bus_register_driver(&acpi_button_driver); |
469 | |||
470 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
471 | if (!acpi_button_dir) | ||
472 | return -ENODEV; | ||
473 | |||
474 | result = acpi_bus_register_driver(&acpi_button_driver); | ||
475 | if (result < 0) { | ||
476 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
477 | return -ENODEV; | ||
478 | } | ||
479 | |||
480 | return 0; | ||
481 | } | 449 | } |
482 | 450 | ||
483 | static void __exit acpi_button_exit(void) | 451 | static void __exit acpi_button_exit(void) |
484 | { | 452 | { |
485 | acpi_bus_unregister_driver(&acpi_button_driver); | 453 | acpi_bus_unregister_driver(&acpi_button_driver); |
486 | |||
487 | if (acpi_power_dir) | ||
488 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir); | ||
489 | if (acpi_sleep_dir) | ||
490 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir); | ||
491 | if (acpi_lid_dir) | ||
492 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); | ||
493 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | ||
494 | } | 454 | } |
495 | 455 | ||
496 | module_init(acpi_button_init); | 456 | module_init(acpi_button_init); |