aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/button.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/button.c')
-rw-r--r--drivers/acpi/button.c183
1 files changed, 74 insertions, 109 deletions
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 1575a9b51f1d..d27d072472f9 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -78,8 +78,6 @@ static int acpi_button_add(struct acpi_device *device);
78static int acpi_button_remove(struct acpi_device *device, int type); 78static int acpi_button_remove(struct acpi_device *device, int type);
79static int acpi_button_resume(struct acpi_device *device); 79static int acpi_button_resume(struct acpi_device *device);
80static void acpi_button_notify(struct acpi_device *device, u32 event); 80static void acpi_button_notify(struct acpi_device *device, u32 event);
81static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
82static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
83 81
84static struct acpi_driver acpi_button_driver = { 82static 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
103static 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
111static 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
119static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); 102static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
@@ -124,20 +107,7 @@ static struct acpi_device *lid_device;
124 -------------------------------------------------------------------------- */ 107 -------------------------------------------------------------------------- */
125 108
126static struct proc_dir_entry *acpi_button_dir; 109static struct proc_dir_entry *acpi_button_dir;
127 110static struct proc_dir_entry *acpi_lid_dir;
128static 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
137static 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
142static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) 112static 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
160static struct proc_dir_entry *acpi_power_dir; 130static const struct file_operations acpi_button_state_fops = {
161static struct proc_dir_entry *acpi_sleep_dir; 131 .owner = THIS_MODULE,
162static 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
164static int acpi_button_add_fs(struct acpi_device *device) 138static 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; 181done:
182 return ret;
183
184remove_dev_dir:
185 remove_proc_entry(acpi_device_bid(device),
186 acpi_lid_dir);
187 acpi_device_dir(device) = NULL;
188remove_lid_dir:
189 remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
190remove_button_dir:
191 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
192 goto done;
214} 193}
215 194
216static int acpi_button_remove_fs(struct acpi_device *device) 195static 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}
@@ -279,6 +257,9 @@ static int acpi_lid_send_state(struct acpi_device *device)
279 input_report_switch(button->input, SW_LID, !state); 257 input_report_switch(button->input, SW_LID, !state);
280 input_sync(button->input); 258 input_sync(button->input);
281 259
260 if (state)
261 pm_wakeup_event(&device->dev, 0);
262
282 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); 263 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
283 if (ret == NOTIFY_DONE) 264 if (ret == NOTIFY_DONE)
284 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, 265 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
@@ -314,6 +295,8 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
314 input_sync(input); 295 input_sync(input);
315 input_report_key(input, keycode, 0); 296 input_report_key(input, keycode, 0);
316 input_sync(input); 297 input_sync(input);
298
299 pm_wakeup_event(&device->dev, 0);
317 } 300 }
318 301
319 acpi_bus_generate_proc_event(device, event, ++button->pushed); 302 acpi_bus_generate_proc_event(device, event, ++button->pushed);
@@ -338,7 +321,8 @@ static int acpi_button_add(struct acpi_device *device)
338{ 321{
339 struct acpi_button *button; 322 struct acpi_button *button;
340 struct input_dev *input; 323 struct input_dev *input;
341 char *hid, *name, *class; 324 const char *hid = acpi_device_hid(device);
325 char *name, *class;
342 int error; 326 int error;
343 327
344 button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL); 328 button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
@@ -353,7 +337,6 @@ static int acpi_button_add(struct acpi_device *device)
353 goto err_free_button; 337 goto err_free_button;
354 } 338 }
355 339
356 hid = acpi_device_hid(device);
357 name = acpi_device_name(device); 340 name = acpi_device_name(device);
358 class = acpi_device_class(device); 341 class = acpi_device_class(device);
359 342
@@ -425,8 +408,10 @@ static int acpi_button_add(struct acpi_device *device)
425 /* Button's GPE is run-wake GPE */ 408 /* Button's GPE is run-wake GPE */
426 acpi_enable_gpe(device->wakeup.gpe_device, 409 acpi_enable_gpe(device->wakeup.gpe_device,
427 device->wakeup.gpe_number); 410 device->wakeup.gpe_number);
428 device->wakeup.run_wake_count++; 411 if (!device_may_wakeup(&device->dev)) {
429 device->wakeup.state.enabled = 1; 412 device_set_wakeup_enable(&device->dev, true);
413 button->wakeup_enabled = true;
414 }
430 } 415 }
431 416
432 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));
@@ -448,8 +433,8 @@ static int acpi_button_remove(struct acpi_device *device, int type)
448 if (device->wakeup.flags.valid) { 433 if (device->wakeup.flags.valid) {
449 acpi_disable_gpe(device->wakeup.gpe_device, 434 acpi_disable_gpe(device->wakeup.gpe_device,
450 device->wakeup.gpe_number); 435 device->wakeup.gpe_number);
451 device->wakeup.run_wake_count--; 436 if (button->wakeup_enabled)
452 device->wakeup.state.enabled = 0; 437 device_set_wakeup_enable(&device->dev, false);
453 } 438 }
454 439
455 acpi_button_remove_fs(device); 440 acpi_button_remove_fs(device);
@@ -460,32 +445,12 @@ static int acpi_button_remove(struct acpi_device *device, int type)
460 445
461static int __init acpi_button_init(void) 446static int __init acpi_button_init(void)
462{ 447{
463 int result; 448 return acpi_bus_register_driver(&acpi_button_driver);
464
465 acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
466 if (!acpi_button_dir)
467 return -ENODEV;
468
469 result = acpi_bus_register_driver(&acpi_button_driver);
470 if (result < 0) {
471 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
472 return -ENODEV;
473 }
474
475 return 0;
476} 449}
477 450
478static void __exit acpi_button_exit(void) 451static void __exit acpi_button_exit(void)
479{ 452{
480 acpi_bus_unregister_driver(&acpi_button_driver); 453 acpi_bus_unregister_driver(&acpi_button_driver);
481
482 if (acpi_power_dir)
483 remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir);
484 if (acpi_sleep_dir)
485 remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir);
486 if (acpi_lid_dir)
487 remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
488 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
489} 454}
490 455
491module_init(acpi_button_init); 456module_init(acpi_button_init);