Blame view

drivers/acpi/ac.c 11 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   *  acpi_ac.c - ACPI AC Adapter Driver ($Revision: 27 $)
   *
   *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
   *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or (at
   *  your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful, but
   *  WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   *  General Public License for more details.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
23
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
24
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
  #include <linux/init.h>
  #include <linux/types.h>
0ab5bb649   Lan Tianyu   ACPI / AC: Add sl...
27
28
  #include <linux/dmi.h>
  #include <linux/delay.h>
e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
29
30
31
32
  #ifdef CONFIG_ACPI_PROCFS_POWER
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #endif
cc8ef5270   Zhang Rui   ACPI / AC: conver...
33
  #include <linux/platform_device.h>
d5b4a3d0e   Alexey Starikovskiy   ACPI: AC: Add sys...
34
  #include <linux/power_supply.h>
8b48463f8   Lv Zheng   ACPI: Clean up in...
35
  #include <linux/acpi.h>
4eee4f03c   Alexander Mezin   ACPI / AC: rechec...
36
  #include "battery.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

a192a9580   Len Brown   ACPI: Move defini...
38
  #define PREFIX "ACPI: "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  #define ACPI_AC_CLASS			"ac_adapter"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
46
47
  #define ACPI_AC_DEVICE_NAME		"AC Adapter"
  #define ACPI_AC_FILE_STATE		"state"
  #define ACPI_AC_NOTIFY_STATUS		0x80
  #define ACPI_AC_STATUS_OFFLINE		0x00
  #define ACPI_AC_STATUS_ONLINE		0x01
  #define ACPI_AC_STATUS_UNKNOWN		0xFF
  
  #define _COMPONENT		ACPI_AC_COMPONENT
f52fd66d2   Len Brown   ACPI: clean up AC...
48
  ACPI_MODULE_NAME("ac");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49

f52fd66d2   Len Brown   ACPI: clean up AC...
50
  MODULE_AUTHOR("Paul Diefenbaugh");
7cda93e00   Len Brown   ACPI: delete extr...
51
  MODULE_DESCRIPTION("ACPI AC Adapter Driver");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  MODULE_LICENSE("GPL");
e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
53

98012849e   Guenter Roeck   ACPI: Revert "ACP...
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  static int acpi_ac_add(struct acpi_device *device);
  static int acpi_ac_remove(struct acpi_device *device);
  static void acpi_ac_notify(struct acpi_device *device, u32 event);
  
  static const struct acpi_device_id ac_device_ids[] = {
  	{"ACPI0003", 0},
  	{"", 0},
  };
  MODULE_DEVICE_TABLE(acpi, ac_device_ids);
  
  #ifdef CONFIG_PM_SLEEP
  static int acpi_ac_resume(struct device *dev);
  #endif
  static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
68
69
70
71
72
  #ifdef CONFIG_ACPI_PROCFS_POWER
  extern struct proc_dir_entry *acpi_lock_ac_dir(void);
  extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
  static int acpi_ac_open_fs(struct inode *inode, struct file *file);
  #endif
0ab5bb649   Lan Tianyu   ACPI / AC: Add sl...
73
  static int ac_sleep_before_get_state_ms;
98012849e   Guenter Roeck   ACPI: Revert "ACP...
74
75
76
77
78
79
80
81
82
83
84
85
  static struct acpi_driver acpi_ac_driver = {
  	.name = "ac",
  	.class = ACPI_AC_CLASS,
  	.ids = ac_device_ids,
  	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
  	.ops = {
  		.add = acpi_ac_add,
  		.remove = acpi_ac_remove,
  		.notify = acpi_ac_notify,
  		},
  	.drv.pm = &acpi_ac_pm,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  struct acpi_ac {
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
87
88
  	struct power_supply *charger;
  	struct power_supply_desc charger_desc;
98012849e   Guenter Roeck   ACPI: Revert "ACP...
89
  	struct acpi_device * device;
27663c585   Matthew Wilcox   ACPI: Change acpi...
90
  	unsigned long long state;
4eee4f03c   Alexander Mezin   ACPI / AC: rechec...
91
  	struct notifier_block battery_nb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  };
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
93
  #define to_acpi_ac(x) power_supply_get_drvdata(x)
d5b4a3d0e   Alexey Starikovskiy   ACPI: AC: Add sys...
94

e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
95
96
97
98
99
100
101
102
103
  #ifdef CONFIG_ACPI_PROCFS_POWER
  static const struct file_operations acpi_ac_fops = {
  	.owner = THIS_MODULE,
  	.open = acpi_ac_open_fs,
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.release = single_release,
  };
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
  /* --------------------------------------------------------------------------
                                 AC Adapter Management
     -------------------------------------------------------------------------- */
4be44fcd3   Len Brown   [ACPI] Lindent al...
107
  static int acpi_ac_get_state(struct acpi_ac *ac)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  {
98012849e   Guenter Roeck   ACPI: Revert "ACP...
109
110
111
112
  	acpi_status status = AE_OK;
  
  	if (!ac)
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113

98012849e   Guenter Roeck   ACPI: Revert "ACP...
114
  	status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL,
cc8ef5270   Zhang Rui   ACPI / AC: conver...
115
  				       &ac->state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  	if (ACPI_FAILURE(status)) {
cc8ef5270   Zhang Rui   ACPI / AC: conver...
117
118
  		ACPI_EXCEPTION((AE_INFO, status,
  				"Error reading AC Adapter state"));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  		ac->state = ACPI_AC_STATUS_UNKNOWN;
d550d98d3   Patrick Mochel   ACPI: delete trac...
120
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
122

d550d98d3   Patrick Mochel   ACPI: delete trac...
123
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  }
3151dbb04   Zhang Rui   ACPI ac: update A...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  /* --------------------------------------------------------------------------
                              sysfs I/F
     -------------------------------------------------------------------------- */
  static int get_ac_property(struct power_supply *psy,
  			   enum power_supply_property psp,
  			   union power_supply_propval *val)
  {
  	struct acpi_ac *ac = to_acpi_ac(psy);
  
  	if (!ac)
  		return -ENODEV;
  
  	if (acpi_ac_get_state(ac))
  		return -ENODEV;
  
  	switch (psp) {
  	case POWER_SUPPLY_PROP_ONLINE:
  		val->intval = ac->state;
  		break;
  	default:
  		return -EINVAL;
  	}
  	return 0;
  }
  
  static enum power_supply_property ac_props[] = {
  	POWER_SUPPLY_PROP_ONLINE,
  };
e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  #ifdef CONFIG_ACPI_PROCFS_POWER
  /* --------------------------------------------------------------------------
                                FS Interface (/proc)
     -------------------------------------------------------------------------- */
  
  static struct proc_dir_entry *acpi_ac_dir;
  
  static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
  {
  	struct acpi_ac *ac = seq->private;
  
  
  	if (!ac)
  		return 0;
  
  	if (acpi_ac_get_state(ac)) {
  		seq_puts(seq, "ERROR: Unable to read AC Adapter state
  ");
  		return 0;
  	}
  
  	seq_puts(seq, "state:                   ");
  	switch (ac->state) {
  	case ACPI_AC_STATUS_OFFLINE:
  		seq_puts(seq, "off-line
  ");
  		break;
  	case ACPI_AC_STATUS_ONLINE:
  		seq_puts(seq, "on-line
  ");
  		break;
  	default:
  		seq_puts(seq, "unknown
  ");
  		break;
  	}
  
  	return 0;
  }
  
  static int acpi_ac_open_fs(struct inode *inode, struct file *file)
  {
  	return single_open(file, acpi_ac_seq_show, PDE_DATA(inode));
  }
  
  static int acpi_ac_add_fs(struct acpi_ac *ac)
  {
  	struct proc_dir_entry *entry = NULL;
  
  	printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded,"
  			" please retry with CONFIG_ACPI_PROCFS_POWER cleared
  ");
  	if (!acpi_device_dir(ac->device)) {
  		acpi_device_dir(ac->device) =
  			proc_mkdir(acpi_device_bid(ac->device), acpi_ac_dir);
  		if (!acpi_device_dir(ac->device))
  			return -ENODEV;
  	}
  
  	/* 'state' [R] */
  	entry = proc_create_data(ACPI_AC_FILE_STATE,
  				 S_IRUGO, acpi_device_dir(ac->device),
  				 &acpi_ac_fops, ac);
  	if (!entry)
  		return -ENODEV;
  	return 0;
  }
  
  static int acpi_ac_remove_fs(struct acpi_ac *ac)
  {
  
  	if (acpi_device_dir(ac->device)) {
  		remove_proc_entry(ACPI_AC_FILE_STATE,
  				  acpi_device_dir(ac->device));
  		remove_proc_entry(acpi_device_bid(ac->device), acpi_ac_dir);
  		acpi_device_dir(ac->device) = NULL;
  	}
  
  	return 0;
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
  /* --------------------------------------------------------------------------
                                     Driver Model
     -------------------------------------------------------------------------- */
98012849e   Guenter Roeck   ACPI: Revert "ACP...
237
  static void acpi_ac_notify(struct acpi_device *device, u32 event)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  {
98012849e   Guenter Roeck   ACPI: Revert "ACP...
239
  	struct acpi_ac *ac = acpi_driver_data(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
  
  	if (!ac)
d550d98d3   Patrick Mochel   ACPI: delete trac...
242
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
  	switch (event) {
f163ff517   Len Brown   ACPI: no AC statu...
245
246
247
248
  	default:
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  				  "Unsupported event [0x%x]
  ", event));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  	case ACPI_AC_NOTIFY_STATUS:
03d782524   Christian Lupien   ACPI: handle AC n...
250
251
  	case ACPI_NOTIFY_BUS_CHECK:
  	case ACPI_NOTIFY_DEVICE_CHECK:
0ab5bb649   Lan Tianyu   ACPI / AC: Add sl...
252
253
254
255
256
257
258
259
260
  		/*
  		 * A buggy BIOS may notify AC first and then sleep for
  		 * a specific time before doing actual operations in the
  		 * EC event handler (_Qxx). This will cause the AC state
  		 * reported by the ACPI event to be incorrect, so wait for a
  		 * specific time for the EC event handler to make progress.
  		 */
  		if (ac_sleep_before_get_state_ms > 0)
  			msleep(ac_sleep_before_get_state_ms);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
  		acpi_ac_get_state(ac);
98012849e   Guenter Roeck   ACPI: Revert "ACP...
262
263
264
265
  		acpi_bus_generate_netlink_event(device->pnp.device_class,
  						  dev_name(&device->dev), event,
  						  (u32) ac->state);
  		acpi_notifier_call_chain(device, event, (u32) ac->state);
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
266
  		kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  	}
d550d98d3   Patrick Mochel   ACPI: delete trac...
268
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  }
4eee4f03c   Alexander Mezin   ACPI / AC: rechec...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  static int acpi_ac_battery_notify(struct notifier_block *nb,
  				  unsigned long action, void *data)
  {
  	struct acpi_ac *ac = container_of(nb, struct acpi_ac, battery_nb);
  	struct acpi_bus_event *event = (struct acpi_bus_event *)data;
  
  	/*
  	 * On HP Pavilion dv6-6179er AC status notifications aren't triggered
  	 * when adapter is plugged/unplugged. However, battery status
  	 * notifcations are triggered when battery starts charging or
  	 * discharging. Re-reading AC status triggers lost AC notifications,
  	 * if AC status has changed.
  	 */
  	if (strcmp(event->device_class, ACPI_BATTERY_CLASS) == 0 &&
  	    event->type == ACPI_BATTERY_NOTIFY_STATUS)
  		acpi_ac_get_state(ac);
  
  	return NOTIFY_OK;
  }
0ab5bb649   Lan Tianyu   ACPI / AC: Add sl...
289
290
291
292
293
  static int thinkpad_e530_quirk(const struct dmi_system_id *d)
  {
  	ac_sleep_before_get_state_ms = 1000;
  	return 0;
  }
44f610cdf   Mathias Krause   ACPI / AC: consti...
294
  static const struct dmi_system_id ac_dmi_table[] = {
0ab5bb649   Lan Tianyu   ACPI / AC: Add sl...
295
296
297
298
299
300
301
302
303
304
  	{
  	.callback = thinkpad_e530_quirk,
  	.ident = "thinkpad e530",
  	.matches = {
  		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  		DMI_MATCH(DMI_PRODUCT_NAME, "32597CG"),
  		},
  	},
  	{},
  };
98012849e   Guenter Roeck   ACPI: Revert "ACP...
305
  static int acpi_ac_add(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  {
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
307
  	struct power_supply_config psy_cfg = {};
4be44fcd3   Len Brown   [ACPI] Lindent al...
308
  	int result = 0;
4be44fcd3   Len Brown   [ACPI] Lindent al...
309
  	struct acpi_ac *ac = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311

98012849e   Guenter Roeck   ACPI: Revert "ACP...
312
313
  	if (!device)
  		return -EINVAL;
cc8ef5270   Zhang Rui   ACPI / AC: conver...
314

36bcbec7c   Burman Yan   ACPI: replace kma...
315
  	ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  	if (!ac)
d550d98d3   Patrick Mochel   ACPI: delete trac...
317
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318

98012849e   Guenter Roeck   ACPI: Revert "ACP...
319
320
321
322
  	ac->device = device;
  	strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
  	strcpy(acpi_device_class(device), ACPI_AC_CLASS);
  	device->driver_data = ac;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
326
  
  	result = acpi_ac_get_state(ac);
  	if (result)
  		goto end;
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
327
328
329
  	psy_cfg.drv_data = ac;
  
  	ac->charger_desc.name = acpi_device_bid(device);
e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
330
331
332
333
334
  #ifdef CONFIG_ACPI_PROCFS_POWER
  	result = acpi_ac_add_fs(ac);
  	if (result)
  		goto end;
  #endif
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
335
336
337
338
339
340
341
342
  	ac->charger_desc.type = POWER_SUPPLY_TYPE_MAINS;
  	ac->charger_desc.properties = ac_props;
  	ac->charger_desc.num_properties = ARRAY_SIZE(ac_props);
  	ac->charger_desc.get_property = get_ac_property;
  	ac->charger = power_supply_register(&ac->device->dev,
  					    &ac->charger_desc, &psy_cfg);
  	if (IS_ERR(ac->charger)) {
  		result = PTR_ERR(ac->charger);
f197ac13f   Lan Tianyu   ACPI/AC: prevent ...
343
  		goto end;
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
344
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345

4be44fcd3   Len Brown   [ACPI] Lindent al...
346
347
  	printk(KERN_INFO PREFIX "%s [%s] (%s)
  ",
98012849e   Guenter Roeck   ACPI: Revert "ACP...
348
  	       acpi_device_name(device), acpi_device_bid(device),
4be44fcd3   Len Brown   [ACPI] Lindent al...
349
  	       ac->state ? "on-line" : "off-line");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350

4eee4f03c   Alexander Mezin   ACPI / AC: rechec...
351
352
  	ac->battery_nb.notifier_call = acpi_ac_battery_notify;
  	register_acpi_notifier(&ac->battery_nb);
ab0fd674d   Lan Tianyu   ACPI / AC: Remove...
353
  end:
e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
354
355
356
357
  	if (result) {
  #ifdef CONFIG_ACPI_PROCFS_POWER
  		acpi_ac_remove_fs(ac);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
  		kfree(ac);
e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
359
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360

0ab5bb649   Lan Tianyu   ACPI / AC: Add sl...
361
  	dmi_check_system(ac_dmi_table);
d550d98d3   Patrick Mochel   ACPI: delete trac...
362
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
  }
906924048   Rafael J. Wysocki   ACPI / PM: Fix un...
364
  #ifdef CONFIG_PM_SLEEP
ccda70698   Rafael J. Wysocki   ACPI: Use struct ...
365
  static int acpi_ac_resume(struct device *dev)
5bfeca313   Alexey Starikovskiy   ACPI: AC: Update ...
366
367
368
  {
  	struct acpi_ac *ac;
  	unsigned old_state;
ccda70698   Rafael J. Wysocki   ACPI: Use struct ...
369
370
371
  
  	if (!dev)
  		return -EINVAL;
98012849e   Guenter Roeck   ACPI: Revert "ACP...
372
  	ac = acpi_driver_data(to_acpi_device(dev));
ccda70698   Rafael J. Wysocki   ACPI: Use struct ...
373
  	if (!ac)
5bfeca313   Alexey Starikovskiy   ACPI: AC: Update ...
374
  		return -EINVAL;
ccda70698   Rafael J. Wysocki   ACPI: Use struct ...
375

5bfeca313   Alexey Starikovskiy   ACPI: AC: Update ...
376
377
378
379
  	old_state = ac->state;
  	if (acpi_ac_get_state(ac))
  		return 0;
  	if (old_state != ac->state)
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
380
  		kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE);
5bfeca313   Alexey Starikovskiy   ACPI: AC: Update ...
381
382
  	return 0;
  }
06521c2e4   Shuah Khan   ACPI / AC: fix AC...
383
384
  #else
  #define acpi_ac_resume NULL
906924048   Rafael J. Wysocki   ACPI / PM: Fix un...
385
  #endif
5bfeca313   Alexey Starikovskiy   ACPI: AC: Update ...
386

98012849e   Guenter Roeck   ACPI: Revert "ACP...
387
  static int acpi_ac_remove(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
  {
98012849e   Guenter Roeck   ACPI: Revert "ACP...
389
  	struct acpi_ac *ac = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390

98012849e   Guenter Roeck   ACPI: Revert "ACP...
391
  	if (!device || !acpi_driver_data(device))
d550d98d3   Patrick Mochel   ACPI: delete trac...
392
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393

98012849e   Guenter Roeck   ACPI: Revert "ACP...
394
  	ac = acpi_driver_data(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395

297d716f6   Krzysztof Kozlowski   power_supply: Cha...
396
  	power_supply_unregister(ac->charger);
4eee4f03c   Alexander Mezin   ACPI / AC: rechec...
397
  	unregister_acpi_notifier(&ac->battery_nb);
cc8ef5270   Zhang Rui   ACPI / AC: conver...
398

e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
399
400
401
  #ifdef CONFIG_ACPI_PROCFS_POWER
  	acpi_ac_remove_fs(ac);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
  	kfree(ac);
d550d98d3   Patrick Mochel   ACPI: delete trac...
403
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
405
  static int __init acpi_ac_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  {
3f86b8324   Rich Townsend   ACPI: add support...
407
  	int result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408

4d8316d5e   Pavel Machek   ACPI: fix boot wi...
409
410
  	if (acpi_disabled)
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411

e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
412
413
414
415
416
  #ifdef CONFIG_ACPI_PROCFS_POWER
  	acpi_ac_dir = acpi_lock_ac_dir();
  	if (!acpi_ac_dir)
  		return -ENODEV;
  #endif
98012849e   Guenter Roeck   ACPI: Revert "ACP...
417
  	result = acpi_bus_register_driver(&acpi_ac_driver);
e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
418
419
420
421
  	if (result < 0) {
  #ifdef CONFIG_ACPI_PROCFS_POWER
  		acpi_unlock_ac_dir(acpi_ac_dir);
  #endif
d550d98d3   Patrick Mochel   ACPI: delete trac...
422
  		return -ENODEV;
e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
423
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424

d550d98d3   Patrick Mochel   ACPI: delete trac...
425
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
427
  static void __exit acpi_ac_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
  {
98012849e   Guenter Roeck   ACPI: Revert "ACP...
429
  	acpi_bus_unregister_driver(&acpi_ac_driver);
e63f6e28d   Lan Tianyu   Revert "ACPI / AC...
430
431
432
  #ifdef CONFIG_ACPI_PROCFS_POWER
  	acpi_unlock_ac_dir(acpi_ac_dir);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
  module_init(acpi_ac_init);
  module_exit(acpi_ac_exit);