Blame view

drivers/acpi/battery.c 31.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
2
   *  battery.c - ACPI Battery Driver (Revision: 2.0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
   *
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
4
5
   *  Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
   *  Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   *  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.
   *
   *  You should have received a copy of the GNU General Public License along
   *  with this program; if not, write to the Free Software Foundation, Inc.,
   *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/types.h>
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
32
  #include <linux/jiffies.h>
0f66af530   Arjan van de Ven   ACPI: battery: as...
33
  #include <linux/async.h>
bc76f90b8   Hector Martin   ACPI battery: wor...
34
  #include <linux/dmi.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
35
  #include <linux/slab.h>
25be58215   Kyle McMartin   ACPI battery: fri...
36
  #include <linux/suspend.h>
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
37

fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
38
  #ifdef CONFIG_ACPI_PROCFS_POWER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #include <asm/uaccess.h>
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
42
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
  
  #include <acpi/acpi_bus.h>
  #include <acpi/acpi_drivers.h>
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
46
  #include <linux/power_supply.h>
a192a9580   Len Brown   ACPI: Move defini...
47
  #define PREFIX "ACPI: "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  #define ACPI_BATTERY_CLASS		"battery"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  #define ACPI_BATTERY_DEVICE_NAME	"Battery"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  #define ACPI_BATTERY_NOTIFY_STATUS	0x80
  #define ACPI_BATTERY_NOTIFY_INFO	0x81
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
53
  #define ACPI_BATTERY_NOTIFY_THRESHOLD   0x82
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54

ae6f61870   Lan Tianyu   ACPI / Battery: A...
55
56
  /* Battery power unit: 0 means mW, 1 means mA */
  #define ACPI_BATTERY_POWER_UNIT_MA	1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  #define _COMPONENT		ACPI_BATTERY_COMPONENT
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
58

f52fd66d2   Len Brown   ACPI: clean up AC...
59
  ACPI_MODULE_NAME("battery");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60

f52fd66d2   Len Brown   ACPI: clean up AC...
61
  MODULE_AUTHOR("Paul Diefenbaugh");
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
62
  MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
7cda93e00   Len Brown   ACPI: delete extr...
63
  MODULE_DESCRIPTION("ACPI Battery Driver");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  MODULE_LICENSE("GPL");
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
65
66
67
  static unsigned int cache_time = 1000;
  module_param(cache_time, uint, 0644);
  MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
68

fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
69
  #ifdef CONFIG_ACPI_PROCFS_POWER
3f86b8324   Rich Townsend   ACPI: add support...
70
71
  extern struct proc_dir_entry *acpi_lock_battery_dir(void);
  extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
72
73
74
75
76
77
78
79
  enum acpi_battery_files {
  	info_tag = 0,
  	state_tag,
  	alarm_tag,
  	ACPI_BATTERY_NUMFILES,
  };
  
  #endif
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
80
81
82
83
  static const struct acpi_device_id battery_device_ids[] = {
  	{"PNP0C0A", 0},
  	{"", 0},
  };
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
84

aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
85
  MODULE_DEVICE_TABLE(acpi, battery_device_ids);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86

7b3bcc4a1   Alexey Starikovskiy   ACPI: Battery: Ad...
87
88
  enum {
  	ACPI_BATTERY_ALARM_PRESENT,
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
89
  	ACPI_BATTERY_XINFO_PRESENT,
557d58687   Zhang Rui   ACPI battery: sup...
90
  	ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
7b3bcc4a1   Alexey Starikovskiy   ACPI: Battery: Ad...
91
  };
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
92

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
  struct acpi_battery {
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
94
  	struct mutex lock;
69d94ec6d   Sergey Senozhatsky   Battery: sysfs_re...
95
  	struct mutex sysfs_lock;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
96
  	struct power_supply bat;
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
97
  	struct acpi_device *device;
25be58215   Kyle McMartin   ACPI battery: fri...
98
  	struct notifier_block pm_nb;
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
99
  	unsigned long update_time;
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
100
  	int rate_now;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
101
102
  	int capacity_now;
  	int voltage_now;
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
103
  	int design_capacity;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
104
  	int full_charge_capacity;
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
105
106
107
108
  	int technology;
  	int design_voltage;
  	int design_capacity_warning;
  	int design_capacity_low;
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
109
110
111
112
113
114
  	int cycle_count;
  	int measurement_accuracy;
  	int max_sampling_time;
  	int min_sampling_time;
  	int max_averaging_interval;
  	int min_averaging_interval;
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
115
116
  	int capacity_granularity_1;
  	int capacity_granularity_2;
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
117
  	int alarm;
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
118
119
120
121
  	char model_number[32];
  	char serial_number[32];
  	char type[32];
  	char oem_info[32];
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
122
123
  	int state;
  	int power_unit;
7b3bcc4a1   Alexey Starikovskiy   ACPI: Battery: Ad...
124
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  };
497888cf6   Phil Carmody   treewide: fix pot...
126
  #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
127

78490d821   Alexey Starikovskiy   ACPI: battery: sy...
128
  inline int acpi_battery_present(struct acpi_battery *battery)
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
129
  {
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
130
131
  	return battery->device->status.battery_present;
  }
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
132

d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
133
134
135
136
137
138
139
140
  static int acpi_battery_technology(struct acpi_battery *battery)
  {
  	if (!strcasecmp("NiCd", battery->type))
  		return POWER_SUPPLY_TECHNOLOGY_NiCd;
  	if (!strcasecmp("NiMH", battery->type))
  		return POWER_SUPPLY_TECHNOLOGY_NiMH;
  	if (!strcasecmp("LION", battery->type))
  		return POWER_SUPPLY_TECHNOLOGY_LION;
ad40e68bf   Andrey Borzenkov   ACPI: battery: fi...
141
  	if (!strncasecmp("LI-ION", battery->type, 6))
0bde7eee9   Alexey Starikovskiy   ACPI: battery: Su...
142
  		return POWER_SUPPLY_TECHNOLOGY_LION;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
143
144
145
146
  	if (!strcasecmp("LiP", battery->type))
  		return POWER_SUPPLY_TECHNOLOGY_LIPO;
  	return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
  }
9104476e4   Alexey Starikovskiy   ACPI: Battery: re...
147
  static int acpi_battery_get_state(struct acpi_battery *battery);
b19073a0b   Alexey Starikovskiy   ACPI: battery: Up...
148

56f382a08   Richard Hughes   battery: don't as...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  static int acpi_battery_is_charged(struct acpi_battery *battery)
  {
  	/* either charging or discharging */
  	if (battery->state != 0)
  		return 0;
  
  	/* battery not reporting charge */
  	if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
  	    battery->capacity_now == 0)
  		return 0;
  
  	/* good batteries update full_charge as the batteries degrade */
  	if (battery->full_charge_capacity == battery->capacity_now)
  		return 1;
  
  	/* fallback to using design values for broken batteries */
  	if (battery->design_capacity == battery->capacity_now)
  		return 1;
  
  	/* we don't do any sort of metric based on percentages */
  	return 0;
  }
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
171
172
173
174
  static int acpi_battery_get_property(struct power_supply *psy,
  				     enum power_supply_property psp,
  				     union power_supply_propval *val)
  {
a1b4bd694   Rafael J. Wysocki   ACPI / Battery: R...
175
  	int ret = 0;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
176
  	struct acpi_battery *battery = to_acpi_battery(psy);
9104476e4   Alexey Starikovskiy   ACPI: Battery: re...
177
178
179
180
  	if (acpi_battery_present(battery)) {
  		/* run battery update only if it is present */
  		acpi_battery_get_state(battery);
  	} else if (psp != POWER_SUPPLY_PROP_PRESENT)
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
181
182
183
184
185
186
187
  		return -ENODEV;
  	switch (psp) {
  	case POWER_SUPPLY_PROP_STATUS:
  		if (battery->state & 0x01)
  			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
  		else if (battery->state & 0x02)
  			val->intval = POWER_SUPPLY_STATUS_CHARGING;
56f382a08   Richard Hughes   battery: don't as...
188
  		else if (acpi_battery_is_charged(battery))
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
189
  			val->intval = POWER_SUPPLY_STATUS_FULL;
4c41d3ad6   Roland Dreier   ACPI: Always retu...
190
191
  		else
  			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
192
193
194
195
196
197
198
  		break;
  	case POWER_SUPPLY_PROP_PRESENT:
  		val->intval = acpi_battery_present(battery);
  		break;
  	case POWER_SUPPLY_PROP_TECHNOLOGY:
  		val->intval = acpi_battery_technology(battery);
  		break;
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
199
200
201
  	case POWER_SUPPLY_PROP_CYCLE_COUNT:
  		val->intval = battery->cycle_count;
  		break;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
202
  	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
a1b4bd694   Rafael J. Wysocki   ACPI / Battery: R...
203
204
205
206
  		if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
  			ret = -ENODEV;
  		else
  			val->intval = battery->design_voltage * 1000;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
207
208
  		break;
  	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
a1b4bd694   Rafael J. Wysocki   ACPI / Battery: R...
209
210
211
212
  		if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
  			ret = -ENODEV;
  		else
  			val->intval = battery->voltage_now * 1000;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
213
214
  		break;
  	case POWER_SUPPLY_PROP_CURRENT_NOW:
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
215
  	case POWER_SUPPLY_PROP_POWER_NOW:
a1b4bd694   Rafael J. Wysocki   ACPI / Battery: R...
216
217
218
219
  		if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
  			ret = -ENODEV;
  		else
  			val->intval = battery->rate_now * 1000;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
220
221
222
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
  	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
a1b4bd694   Rafael J. Wysocki   ACPI / Battery: R...
223
224
225
226
  		if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
  			ret = -ENODEV;
  		else
  			val->intval = battery->design_capacity * 1000;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
227
228
229
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_FULL:
  	case POWER_SUPPLY_PROP_ENERGY_FULL:
a1b4bd694   Rafael J. Wysocki   ACPI / Battery: R...
230
231
232
233
  		if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
  			ret = -ENODEV;
  		else
  			val->intval = battery->full_charge_capacity * 1000;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
234
235
236
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_NOW:
  	case POWER_SUPPLY_PROP_ENERGY_NOW:
a1b4bd694   Rafael J. Wysocki   ACPI / Battery: R...
237
238
239
240
  		if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
  			ret = -ENODEV;
  		else
  			val->intval = battery->capacity_now * 1000;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
241
242
243
244
245
246
247
  		break;
  	case POWER_SUPPLY_PROP_MODEL_NAME:
  		val->strval = battery->model_number;
  		break;
  	case POWER_SUPPLY_PROP_MANUFACTURER:
  		val->strval = battery->oem_info;
  		break;
7c2670bbb   maximilian attems   ACPI: battery: ad...
248
249
250
  	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
  		val->strval = battery->serial_number;
  		break;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
251
  	default:
a1b4bd694   Rafael J. Wysocki   ACPI / Battery: R...
252
  		ret = -EINVAL;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
253
  	}
a1b4bd694   Rafael J. Wysocki   ACPI / Battery: R...
254
  	return ret;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
255
256
257
258
259
260
  }
  
  static enum power_supply_property charge_battery_props[] = {
  	POWER_SUPPLY_PROP_STATUS,
  	POWER_SUPPLY_PROP_PRESENT,
  	POWER_SUPPLY_PROP_TECHNOLOGY,
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
261
  	POWER_SUPPLY_PROP_CYCLE_COUNT,
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
262
263
264
265
266
267
268
269
  	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
  	POWER_SUPPLY_PROP_CURRENT_NOW,
  	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
  	POWER_SUPPLY_PROP_CHARGE_FULL,
  	POWER_SUPPLY_PROP_CHARGE_NOW,
  	POWER_SUPPLY_PROP_MODEL_NAME,
  	POWER_SUPPLY_PROP_MANUFACTURER,
7c2670bbb   maximilian attems   ACPI: battery: ad...
270
  	POWER_SUPPLY_PROP_SERIAL_NUMBER,
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
271
272
273
274
275
276
  };
  
  static enum power_supply_property energy_battery_props[] = {
  	POWER_SUPPLY_PROP_STATUS,
  	POWER_SUPPLY_PROP_PRESENT,
  	POWER_SUPPLY_PROP_TECHNOLOGY,
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
277
  	POWER_SUPPLY_PROP_CYCLE_COUNT,
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
278
279
  	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
280
  	POWER_SUPPLY_PROP_POWER_NOW,
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
281
282
283
284
285
  	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
  	POWER_SUPPLY_PROP_ENERGY_FULL,
  	POWER_SUPPLY_PROP_ENERGY_NOW,
  	POWER_SUPPLY_PROP_MODEL_NAME,
  	POWER_SUPPLY_PROP_MANUFACTURER,
7c2670bbb   maximilian attems   ACPI: battery: ad...
286
  	POWER_SUPPLY_PROP_SERIAL_NUMBER,
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
287
  };
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
288
  #ifdef CONFIG_ACPI_PROCFS_POWER
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
289
  inline char *acpi_battery_units(struct acpi_battery *battery)
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
290
  {
ae6f61870   Lan Tianyu   ACPI / Battery: A...
291
292
  	return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
  		"mA" : "mW";
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
293
  }
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
294
  #endif
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
295

78490d821   Alexey Starikovskiy   ACPI: battery: sy...
296
297
298
  /* --------------------------------------------------------------------------
                                 Battery Management
     -------------------------------------------------------------------------- */
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
299
300
301
302
  struct acpi_offsets {
  	size_t offset;		/* offset inside struct acpi_sbs_battery */
  	u8 mode;		/* int or string? */
  };
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
303

038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
304
305
  static struct acpi_offsets state_offsets[] = {
  	{offsetof(struct acpi_battery, state), 0},
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
306
  	{offsetof(struct acpi_battery, rate_now), 0},
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
307
308
  	{offsetof(struct acpi_battery, capacity_now), 0},
  	{offsetof(struct acpi_battery, voltage_now), 0},
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
309
  };
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
310

038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
311
312
313
  static struct acpi_offsets info_offsets[] = {
  	{offsetof(struct acpi_battery, power_unit), 0},
  	{offsetof(struct acpi_battery, design_capacity), 0},
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
314
  	{offsetof(struct acpi_battery, full_charge_capacity), 0},
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
315
316
317
318
319
320
321
322
323
324
325
  	{offsetof(struct acpi_battery, technology), 0},
  	{offsetof(struct acpi_battery, design_voltage), 0},
  	{offsetof(struct acpi_battery, design_capacity_warning), 0},
  	{offsetof(struct acpi_battery, design_capacity_low), 0},
  	{offsetof(struct acpi_battery, capacity_granularity_1), 0},
  	{offsetof(struct acpi_battery, capacity_granularity_2), 0},
  	{offsetof(struct acpi_battery, model_number), 1},
  	{offsetof(struct acpi_battery, serial_number), 1},
  	{offsetof(struct acpi_battery, type), 1},
  	{offsetof(struct acpi_battery, oem_info), 1},
  };
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
326

c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  static struct acpi_offsets extended_info_offsets[] = {
  	{offsetof(struct acpi_battery, power_unit), 0},
  	{offsetof(struct acpi_battery, design_capacity), 0},
  	{offsetof(struct acpi_battery, full_charge_capacity), 0},
  	{offsetof(struct acpi_battery, technology), 0},
  	{offsetof(struct acpi_battery, design_voltage), 0},
  	{offsetof(struct acpi_battery, design_capacity_warning), 0},
  	{offsetof(struct acpi_battery, design_capacity_low), 0},
  	{offsetof(struct acpi_battery, cycle_count), 0},
  	{offsetof(struct acpi_battery, measurement_accuracy), 0},
  	{offsetof(struct acpi_battery, max_sampling_time), 0},
  	{offsetof(struct acpi_battery, min_sampling_time), 0},
  	{offsetof(struct acpi_battery, max_averaging_interval), 0},
  	{offsetof(struct acpi_battery, min_averaging_interval), 0},
  	{offsetof(struct acpi_battery, capacity_granularity_1), 0},
  	{offsetof(struct acpi_battery, capacity_granularity_2), 0},
  	{offsetof(struct acpi_battery, model_number), 1},
  	{offsetof(struct acpi_battery, serial_number), 1},
  	{offsetof(struct acpi_battery, type), 1},
  	{offsetof(struct acpi_battery, oem_info), 1},
  };
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
348
349
350
351
  static int extract_package(struct acpi_battery *battery,
  			   union acpi_object *package,
  			   struct acpi_offsets *offsets, int num)
  {
106449e87   Alexey Starikovskiy   ACPI: Battery: Al...
352
  	int i;
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
353
354
355
356
357
358
359
360
  	union acpi_object *element;
  	if (package->type != ACPI_TYPE_PACKAGE)
  		return -EFAULT;
  	for (i = 0; i < num; ++i) {
  		if (package->package.count <= i)
  			return -EFAULT;
  		element = &package->package.elements[i];
  		if (offsets[i].mode) {
106449e87   Alexey Starikovskiy   ACPI: Battery: Al...
361
362
363
364
365
366
  			u8 *ptr = (u8 *)battery + offsets[i].offset;
  			if (element->type == ACPI_TYPE_STRING ||
  			    element->type == ACPI_TYPE_BUFFER)
  				strncpy(ptr, element->string.pointer, 32);
  			else if (element->type == ACPI_TYPE_INTEGER) {
  				strncpy(ptr, (u8 *)&element->integer.value,
439913fff   Lin Ming   ACPI: replace acp...
367
368
  					sizeof(u64));
  				ptr[sizeof(u64)] = 0;
b8a1bdb14   Alexey Starikovskiy   ACPI: battery: Do...
369
370
  			} else
  				*ptr = 0; /* don't have value */
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
371
  		} else {
b8a1bdb14   Alexey Starikovskiy   ACPI: battery: Do...
372
373
374
  			int *x = (int *)((u8 *)battery + offsets[i].offset);
  			*x = (element->type == ACPI_TYPE_INTEGER) ?
  				element->integer.value : -1;
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
375
  		}
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
376
  	}
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
377
378
379
380
381
  	return 0;
  }
  
  static int acpi_battery_get_status(struct acpi_battery *battery)
  {
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
382
  	if (acpi_bus_get_status(battery->device)) {
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
383
384
385
  		ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
  		return -ENODEV;
  	}
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
386
  	return 0;
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
387
388
389
  }
  
  static int acpi_battery_get_info(struct acpi_battery *battery)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
  {
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
391
  	int result = -EFAULT;
4be44fcd3   Len Brown   [ACPI] Lindent al...
392
  	acpi_status status = 0;
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
393
394
  	char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)?
  			"_BIX" : "_BIF";
4be44fcd3   Len Brown   [ACPI] Lindent al...
395
  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396

b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
397
398
  	if (!acpi_battery_present(battery))
  		return 0;
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
399
  	mutex_lock(&battery->lock);
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
400
401
  	status = acpi_evaluate_object(battery->device->handle, name,
  						NULL, &buffer);
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
402
  	mutex_unlock(&battery->lock);
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
403

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  	if (ACPI_FAILURE(status)) {
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
405
  		ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
d550d98d3   Patrick Mochel   ACPI: delete trac...
406
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
  	}
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
408
409
410
411
412
413
414
  	if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
  		result = extract_package(battery, buffer.pointer,
  				extended_info_offsets,
  				ARRAY_SIZE(extended_info_offsets));
  	else
  		result = extract_package(battery, buffer.pointer,
  				info_offsets, ARRAY_SIZE(info_offsets));
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
415
  	kfree(buffer.pointer);
557d58687   Zhang Rui   ACPI battery: sup...
416
417
  	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
  		battery->full_charge_capacity = battery->design_capacity;
d550d98d3   Patrick Mochel   ACPI: delete trac...
418
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  }
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
420
  static int acpi_battery_get_state(struct acpi_battery *battery)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
422
423
424
  	int result = 0;
  	acpi_status status = 0;
  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425

b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
426
427
  	if (!acpi_battery_present(battery))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428

f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
429
430
431
432
  	if (battery->update_time &&
  	    time_before(jiffies, battery->update_time +
  			msecs_to_jiffies(cache_time)))
  		return 0;
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
433
  	mutex_lock(&battery->lock);
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
434
  	status = acpi_evaluate_object(battery->device->handle, "_BST",
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
435
436
  				      NULL, &buffer);
  	mutex_unlock(&battery->lock);
5b31d8958   Len Brown   Revert "ACPI: Bat...
437

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  	if (ACPI_FAILURE(status)) {
a6fc67202   Thomas Renninger   ACPI: Enable ACPI...
439
  		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
d550d98d3   Patrick Mochel   ACPI: delete trac...
440
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  	}
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
442

038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
443
444
  	result = extract_package(battery, buffer.pointer,
  				 state_offsets, ARRAY_SIZE(state_offsets));
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
445
  	battery->update_time = jiffies;
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
446
  	kfree(buffer.pointer);
bc76f90b8   Hector Martin   ACPI battery: wor...
447

55003b210   Lan Tianyu   ACPI / Battery: C...
448
449
450
451
452
453
454
  	/* For buggy DSDTs that report negative 16-bit values for either
  	 * charging or discharging current and/or report 0 as 65536
  	 * due to bad math.
  	 */
  	if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
  		battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
  		(s16)(battery->rate_now) < 0) {
bc76f90b8   Hector Martin   ACPI battery: wor...
455
  		battery->rate_now = abs((s16)battery->rate_now);
55003b210   Lan Tianyu   ACPI / Battery: C...
456
457
458
459
  		printk_once(KERN_WARNING FW_BUG "battery: (dis)charge rate"
  			" invalid.
  ");
  	}
bc76f90b8   Hector Martin   ACPI battery: wor...
460

557d58687   Zhang Rui   ACPI battery: sup...
461
462
463
464
  	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
  	    && battery->capacity_now >= 0 && battery->capacity_now <= 100)
  		battery->capacity_now = (battery->capacity_now *
  				battery->full_charge_capacity) / 100;
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
465
466
  	return result;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467

aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
468
  static int acpi_battery_set_alarm(struct acpi_battery *battery)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
470
  	acpi_status status = 0;
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
471
  	union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER };
4be44fcd3   Len Brown   [ACPI] Lindent al...
472
  	struct acpi_object_list arg_list = { 1, &arg0 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473

c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
474
  	if (!acpi_battery_present(battery) ||
7b3bcc4a1   Alexey Starikovskiy   ACPI: Battery: Ad...
475
  	    !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
d550d98d3   Patrick Mochel   ACPI: delete trac...
476
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477

aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
478
  	arg0.integer.value = battery->alarm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479

038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
480
  	mutex_lock(&battery->lock);
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
481
482
  	status = acpi_evaluate_object(battery->device->handle, "_BTP",
  				 &arg_list, NULL);
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
483
  	mutex_unlock(&battery->lock);
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
484

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
  	if (ACPI_FAILURE(status))
d550d98d3   Patrick Mochel   ACPI: delete trac...
486
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487

aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
488
489
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d
  ", battery->alarm));
d550d98d3   Patrick Mochel   ACPI: delete trac...
490
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
  }
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
492
  static int acpi_battery_init_alarm(struct acpi_battery *battery)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
494
495
  	acpi_status status = AE_OK;
  	acpi_handle handle = NULL;
4be44fcd3   Len Brown   [ACPI] Lindent al...
496

b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
497
  	/* See if alarms are supported, and if so, set default */
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
498
499
  	status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
  	if (ACPI_FAILURE(status)) {
7b3bcc4a1   Alexey Starikovskiy   ACPI: Battery: Ad...
500
  		clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
501
  		return 0;
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
502
  	}
7b3bcc4a1   Alexey Starikovskiy   ACPI: Battery: Ad...
503
  	set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
504
505
  	if (!battery->alarm)
  		battery->alarm = battery->design_capacity_warning;
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
506
  	return acpi_battery_set_alarm(battery);
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
507
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508

508df92d1   Andrey Borzenkov   ACPI: battery: re...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
  static ssize_t acpi_battery_alarm_show(struct device *dev,
  					struct device_attribute *attr,
  					char *buf)
  {
  	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
  	return sprintf(buf, "%d
  ", battery->alarm * 1000);
  }
  
  static ssize_t acpi_battery_alarm_store(struct device *dev,
  					struct device_attribute *attr,
  					const char *buf, size_t count)
  {
  	unsigned long x;
  	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
  	if (sscanf(buf, "%ld
  ", &x) == 1)
  		battery->alarm = x/1000;
  	if (acpi_battery_present(battery))
  		acpi_battery_set_alarm(battery);
  	return count;
  }
  
  static struct device_attribute alarm_attr = {
01e8ef11b   Parag Warudkar   x86: sysfs: kill ...
533
  	.attr = {.name = "alarm", .mode = 0644},
508df92d1   Andrey Borzenkov   ACPI: battery: re...
534
535
536
537
538
539
540
  	.show = acpi_battery_alarm_show,
  	.store = acpi_battery_alarm_store,
  };
  
  static int sysfs_add_battery(struct acpi_battery *battery)
  {
  	int result;
ae6f61870   Lan Tianyu   ACPI / Battery: A...
541
  	if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
508df92d1   Andrey Borzenkov   ACPI: battery: re...
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
  		battery->bat.properties = charge_battery_props;
  		battery->bat.num_properties =
  			ARRAY_SIZE(charge_battery_props);
  	} else {
  		battery->bat.properties = energy_battery_props;
  		battery->bat.num_properties =
  			ARRAY_SIZE(energy_battery_props);
  	}
  
  	battery->bat.name = acpi_device_bid(battery->device);
  	battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
  	battery->bat.get_property = acpi_battery_get_property;
  
  	result = power_supply_register(&battery->device->dev, &battery->bat);
  	if (result)
  		return result;
  	return device_create_file(battery->bat.dev, &alarm_attr);
  }
  
  static void sysfs_remove_battery(struct acpi_battery *battery)
  {
69d94ec6d   Sergey Senozhatsky   Battery: sysfs_re...
563
  	mutex_lock(&battery->sysfs_lock);
9c921c22a   Lan Tianyu   ACPI / Battery: R...
564
  	if (!battery->bat.dev) {
69d94ec6d   Sergey Senozhatsky   Battery: sysfs_re...
565
  		mutex_unlock(&battery->sysfs_lock);
508df92d1   Andrey Borzenkov   ACPI: battery: re...
566
  		return;
9c921c22a   Lan Tianyu   ACPI / Battery: R...
567
  	}
508df92d1   Andrey Borzenkov   ACPI: battery: re...
568
569
  	device_remove_file(battery->bat.dev, &alarm_attr);
  	power_supply_unregister(&battery->bat);
9104476e4   Alexey Starikovskiy   ACPI: Battery: re...
570
  	battery->bat.dev = NULL;
69d94ec6d   Sergey Senozhatsky   Battery: sysfs_re...
571
  	mutex_unlock(&battery->sysfs_lock);
bc76f90b8   Hector Martin   ACPI battery: wor...
572
  }
557d58687   Zhang Rui   ACPI battery: sup...
573
574
575
576
577
578
579
580
581
582
583
584
  /*
   * According to the ACPI spec, some kinds of primary batteries can
   * report percentage battery remaining capacity directly to OS.
   * In this case, it reports the Last Full Charged Capacity == 100
   * and BatteryPresentRate == 0xFFFFFFFF.
   *
   * Now we found some battery reports percentage remaining capacity
   * even if it's rechargeable.
   * https://bugzilla.kernel.org/show_bug.cgi?id=15979
   *
   * Handle this correctly so that they won't break userspace.
   */
7b78622d0   Lan Tianyu   ACPI / Battery: R...
585
  static void acpi_battery_quirks(struct acpi_battery *battery)
557d58687   Zhang Rui   ACPI battery: sup...
586
587
588
589
590
591
592
593
594
595
596
597
598
  {
  	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
  		return ;
  
          if (battery->full_charge_capacity == 100 &&
              battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
              battery->capacity_now >=0 && battery->capacity_now <= 100) {
  		set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
  		battery->full_charge_capacity = battery->design_capacity;
  		battery->capacity_now = (battery->capacity_now *
  				battery->full_charge_capacity) / 100;
  	}
  }
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
599
  static int acpi_battery_update(struct acpi_battery *battery)
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
600
  {
50b178512   Alexey Starikovskiy   Newly inserted ba...
601
  	int result, old_present = acpi_battery_present(battery);
97749cd9a   Alexey Starikovskiy   ACPI: Make sysfs ...
602
  	result = acpi_battery_get_status(battery);
508df92d1   Andrey Borzenkov   ACPI: battery: re...
603
  	if (result)
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
604
  		return result;
508df92d1   Andrey Borzenkov   ACPI: battery: re...
605
606
  	if (!acpi_battery_present(battery)) {
  		sysfs_remove_battery(battery);
97749cd9a   Alexey Starikovskiy   ACPI: Make sysfs ...
607
  		battery->update_time = 0;
508df92d1   Andrey Borzenkov   ACPI: battery: re...
608
  		return 0;
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
609
  	}
50b178512   Alexey Starikovskiy   Newly inserted ba...
610
611
  	if (!battery->update_time ||
  	    old_present != acpi_battery_present(battery)) {
97749cd9a   Alexey Starikovskiy   ACPI: Make sysfs ...
612
613
614
615
616
  		result = acpi_battery_get_info(battery);
  		if (result)
  			return result;
  		acpi_battery_init_alarm(battery);
  	}
eb03cb02b   Stefan Hajnoczi   ACPI / Battery: p...
617
618
619
620
621
  	if (!battery->bat.dev) {
  		result = sysfs_add_battery(battery);
  		if (result)
  			return result;
  	}
557d58687   Zhang Rui   ACPI battery: sup...
622
  	result = acpi_battery_get_state(battery);
7b78622d0   Lan Tianyu   ACPI / Battery: R...
623
  	acpi_battery_quirks(battery);
557d58687   Zhang Rui   ACPI battery: sup...
624
  	return result;
4bd35cdb1   Vladimir Lebedev   ACPI: battery: ch...
625
  }
da8aeb92d   Rafael J. Wysocki   ACPI / Battery: U...
626
627
628
629
630
631
632
633
634
635
  static void acpi_battery_refresh(struct acpi_battery *battery)
  {
  	if (!battery->bat.dev)
  		return;
  
  	acpi_battery_get_info(battery);
  	/* The battery may have changed its reporting units. */
  	sysfs_remove_battery(battery);
  	sysfs_add_battery(battery);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
637
638
  /* --------------------------------------------------------------------------
                                FS Interface (/proc)
     -------------------------------------------------------------------------- */
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
639
  #ifdef CONFIG_ACPI_PROCFS_POWER
4be44fcd3   Len Brown   [ACPI] Lindent al...
640
  static struct proc_dir_entry *acpi_battery_dir;
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
641

78490d821   Alexey Starikovskiy   ACPI: battery: sy...
642
  static int acpi_battery_print_info(struct seq_file *seq, int result)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
  {
50dd09697   Jan Engelhardt   ACPI: Remove unne...
644
  	struct acpi_battery *battery = seq->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645

b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
646
  	if (result)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
  		goto end;
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
648
649
650
651
  	seq_printf(seq, "present:                 %s
  ",
  		   acpi_battery_present(battery)?"yes":"no");
  	if (!acpi_battery_present(battery))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  		goto end;
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
653
  	if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
656
657
658
  		seq_printf(seq, "design capacity:         unknown
  ");
  	else
  		seq_printf(seq, "design capacity:         %d %sh
  ",
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
659
660
  			   battery->design_capacity,
  			   acpi_battery_units(battery));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661

d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
662
  	if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
664
665
666
667
  		seq_printf(seq, "last full capacity:      unknown
  ");
  	else
  		seq_printf(seq, "last full capacity:      %d %sh
  ",
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
668
  			   battery->full_charge_capacity,
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
669
670
671
672
673
  			   acpi_battery_units(battery));
  
  	seq_printf(seq, "battery technology:      %srechargeable
  ",
  		   (!battery->technology)?"non-":"");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674

038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
675
  	if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
677
678
679
680
  		seq_printf(seq, "design voltage:          unknown
  ");
  	else
  		seq_printf(seq, "design voltage:          %d mV
  ",
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
681
  			   battery->design_voltage);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
  	seq_printf(seq, "design capacity warning: %d %sh
  ",
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
684
685
  		   battery->design_capacity_warning,
  		   acpi_battery_units(battery));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
  	seq_printf(seq, "design capacity low:     %d %sh
  ",
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
688
689
  		   battery->design_capacity_low,
  		   acpi_battery_units(battery));
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
690
691
  	seq_printf(seq, "cycle count:		  %i
  ", battery->cycle_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
  	seq_printf(seq, "capacity granularity 1:  %d %sh
  ",
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
694
695
  		   battery->capacity_granularity_1,
  		   acpi_battery_units(battery));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
  	seq_printf(seq, "capacity granularity 2:  %d %sh
  ",
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
698
699
  		   battery->capacity_granularity_2,
  		   acpi_battery_units(battery));
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
700
701
702
703
704
705
706
707
  	seq_printf(seq, "model number:            %s
  ", battery->model_number);
  	seq_printf(seq, "serial number:           %s
  ", battery->serial_number);
  	seq_printf(seq, "battery type:            %s
  ", battery->type);
  	seq_printf(seq, "OEM info:                %s
  ", battery->oem_info);
4be44fcd3   Len Brown   [ACPI] Lindent al...
708
        end:
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
709
710
711
  	if (result)
  		seq_printf(seq, "ERROR: Unable to read battery info
  ");
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
712
713
  	return result;
  }
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
714
  static int acpi_battery_print_state(struct seq_file *seq, int result)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
  {
50dd09697   Jan Engelhardt   ACPI: Remove unne...
716
  	struct acpi_battery *battery = seq->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717

b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
718
  	if (result)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
  		goto end;
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
720
721
722
723
  	seq_printf(seq, "present:                 %s
  ",
  		   acpi_battery_present(battery)?"yes":"no");
  	if (!acpi_battery_present(battery))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
  		goto end;
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
725

aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
726
727
728
729
  	seq_printf(seq, "capacity state:          %s
  ",
  			(battery->state & 0x04)?"critical":"ok");
  	if ((battery->state & 0x01) && (battery->state & 0x02))
4be44fcd3   Len Brown   [ACPI] Lindent al...
730
731
732
  		seq_printf(seq,
  			   "charging state:          charging/discharging
  ");
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
733
  	else if (battery->state & 0x01)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
  		seq_printf(seq, "charging state:          discharging
  ");
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
736
  	else if (battery->state & 0x02)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
738
  		seq_printf(seq, "charging state:          charging
  ");
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
739
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
741
  		seq_printf(seq, "charging state:          charged
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742

7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
743
  	if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
746
747
748
  		seq_printf(seq, "present rate:            unknown
  ");
  	else
  		seq_printf(seq, "present rate:            %d %s
  ",
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
749
  			   battery->rate_now, acpi_battery_units(battery));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750

d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
751
  	if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
754
755
756
  		seq_printf(seq, "remaining capacity:      unknown
  ");
  	else
  		seq_printf(seq, "remaining capacity:      %d %sh
  ",
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
757
758
  			   battery->capacity_now, acpi_battery_units(battery));
  	if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
760
761
762
763
  		seq_printf(seq, "present voltage:         unknown
  ");
  	else
  		seq_printf(seq, "present voltage:         %d mV
  ",
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
764
  			   battery->voltage_now);
4be44fcd3   Len Brown   [ACPI] Lindent al...
765
        end:
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
766
  	if (result)
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
767
768
  		seq_printf(seq, "ERROR: Unable to read battery state
  ");
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
769
770
771
  
  	return result;
  }
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
772
  static int acpi_battery_print_alarm(struct seq_file *seq, int result)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
773
  {
50dd09697   Jan Engelhardt   ACPI: Remove unne...
774
  	struct acpi_battery *battery = seq->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775

b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
776
  	if (result)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
  		goto end;
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
778
  	if (!acpi_battery_present(battery)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
780
781
782
  		seq_printf(seq, "present:                 no
  ");
  		goto end;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
784
785
786
787
  	seq_printf(seq, "alarm:                   ");
  	if (!battery->alarm)
  		seq_printf(seq, "unsupported
  ");
  	else
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
788
789
790
  		seq_printf(seq, "%u %sh
  ", battery->alarm,
  				acpi_battery_units(battery));
4be44fcd3   Len Brown   [ACPI] Lindent al...
791
        end:
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
792
793
794
  	if (result)
  		seq_printf(seq, "ERROR: Unable to read battery alarm
  ");
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
795
796
  	return result;
  }
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
797
798
799
  static ssize_t acpi_battery_write_alarm(struct file *file,
  					const char __user * buffer,
  					size_t count, loff_t * ppos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
801
802
  	int result = 0;
  	char alarm_string[12] = { '\0' };
50dd09697   Jan Engelhardt   ACPI: Remove unne...
803
804
  	struct seq_file *m = file->private_data;
  	struct acpi_battery *battery = m->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
  	if (!battery || (count > sizeof(alarm_string) - 1))
d550d98d3   Patrick Mochel   ACPI: delete trac...
807
  		return -EINVAL;
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
808
809
810
811
  	if (!acpi_battery_present(battery)) {
  		result = -ENODEV;
  		goto end;
  	}
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
812
813
814
815
  	if (copy_from_user(alarm_string, buffer, count)) {
  		result = -EFAULT;
  		goto end;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816
  	alarm_string[count] = '\0';
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
817
  	battery->alarm = simple_strtol(alarm_string, NULL, 0);
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
818
  	result = acpi_battery_set_alarm(battery);
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
819
        end:
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
820
  	if (!result)
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
821
  		return count;
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
822
823
824
825
  	return result;
  }
  
  typedef int(*print_func)(struct seq_file *seq, int result);
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
826
827
828
829
830
  
  static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
  	acpi_battery_print_info,
  	acpi_battery_print_state,
  	acpi_battery_print_alarm,
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
831
  };
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
832

78490d821   Alexey Starikovskiy   ACPI: battery: sy...
833
834
835
  static int acpi_battery_read(int fid, struct seq_file *seq)
  {
  	struct acpi_battery *battery = seq->private;
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
836
  	int result = acpi_battery_update(battery);
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
837
  	return acpi_print_funcs[fid](seq, result);
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
838
  }
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
839
840
841
842
843
844
845
846
  #define DECLARE_FILE_FUNCTIONS(_name) \
  static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
  { \
  	return acpi_battery_read(_name##_tag, seq); \
  } \
  static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
  { \
  	return single_open(file, acpi_battery_read_##_name, PDE(inode)->data); \
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
847
  }
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
  DECLARE_FILE_FUNCTIONS(info);
  DECLARE_FILE_FUNCTIONS(state);
  DECLARE_FILE_FUNCTIONS(alarm);
  
  #undef DECLARE_FILE_FUNCTIONS
  
  #define FILE_DESCRIPTION_RO(_name) \
  	{ \
  	.name = __stringify(_name), \
  	.mode = S_IRUGO, \
  	.ops = { \
  		.open = acpi_battery_##_name##_open_fs, \
  		.read = seq_read, \
  		.llseek = seq_lseek, \
  		.release = single_release, \
  		.owner = THIS_MODULE, \
  		}, \
  	}
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
866

aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
867
868
869
870
871
872
873
874
875
876
877
878
879
  #define FILE_DESCRIPTION_RW(_name) \
  	{ \
  	.name = __stringify(_name), \
  	.mode = S_IFREG | S_IRUGO | S_IWUSR, \
  	.ops = { \
  		.open = acpi_battery_##_name##_open_fs, \
  		.read = seq_read, \
  		.llseek = seq_lseek, \
  		.write = acpi_battery_write_##_name, \
  		.release = single_release, \
  		.owner = THIS_MODULE, \
  		}, \
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880

9c8b04be4   Vasiliy Kulikov   ACPI: constify op...
881
  static const struct battery_file {
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
882
  	struct file_operations ops;
d161a13f9   Al Viro   switch procfs to ...
883
  	umode_t mode;
070d8eb1f   Jan Engelhardt   ACPI: constify VF...
884
  	const char *name;
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
885
  } acpi_battery_file[] = {
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
886
887
888
  	FILE_DESCRIPTION_RO(info),
  	FILE_DESCRIPTION_RO(state),
  	FILE_DESCRIPTION_RW(alarm),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
  };
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
890
891
  #undef FILE_DESCRIPTION_RO
  #undef FILE_DESCRIPTION_RW
4be44fcd3   Len Brown   [ACPI] Lindent al...
892
  static int acpi_battery_add_fs(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
894
  	struct proc_dir_entry *entry = NULL;
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
895
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896

6d855fcdd   Zhang Rui   ACPI: delete CONF...
897
898
899
  	printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
  			" please retry with CONFIG_ACPI_PROCFS_POWER cleared
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900
901
  	if (!acpi_device_dir(device)) {
  		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
4be44fcd3   Len Brown   [ACPI] Lindent al...
902
  						     acpi_battery_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
  		if (!acpi_device_dir(device))
d550d98d3   Patrick Mochel   ACPI: delete trac...
904
  			return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
  	}
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
906
  	for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
cf7acfab0   Denis V. Lunev   acpi: use non-rac...
907
908
909
910
911
  		entry = proc_create_data(acpi_battery_file[i].name,
  					 acpi_battery_file[i].mode,
  					 acpi_device_dir(device),
  					 &acpi_battery_file[i].ops,
  					 acpi_driver_data(device));
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
912
913
  		if (!entry)
  			return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
  	}
d550d98d3   Patrick Mochel   ACPI: delete trac...
915
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
  }
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
917
  static void acpi_battery_remove_fs(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
  {
78490d821   Alexey Starikovskiy   ACPI: battery: sy...
919
  	int i;
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
920
921
922
923
  	if (!acpi_device_dir(device))
  		return;
  	for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
  		remove_proc_entry(acpi_battery_file[i].name,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
  				  acpi_device_dir(device));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925

aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
926
927
  	remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
  	acpi_device_dir(device) = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
  }
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
929
  #endif
3e58ea0d3   Alexey Starikovskiy   ACPI: Battery: ad...
930

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
932
933
  /* --------------------------------------------------------------------------
                                   Driver Interface
     -------------------------------------------------------------------------- */
d94066910   Bjorn Helgaas   ACPI: battery: us...
934
  static void acpi_battery_notify(struct acpi_device *device, u32 event)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
935
  {
d94066910   Bjorn Helgaas   ACPI: battery: us...
936
  	struct acpi_battery *battery = acpi_driver_data(device);
153e500f5   Zhang Rui   ACPI battery: don...
937
  	struct device *old;
d94066910   Bjorn Helgaas   ACPI: battery: us...
938

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
  	if (!battery)
d550d98d3   Patrick Mochel   ACPI: delete trac...
940
  		return;
153e500f5   Zhang Rui   ACPI battery: don...
941
  	old = battery->bat.dev;
da8aeb92d   Rafael J. Wysocki   ACPI / Battery: U...
942
943
  	if (event == ACPI_BATTERY_NOTIFY_INFO)
  		acpi_battery_refresh(battery);
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
944
945
946
947
  	acpi_battery_update(battery);
  	acpi_bus_generate_proc_event(device, event,
  				     acpi_battery_present(battery));
  	acpi_bus_generate_netlink_event(device->pnp.device_class,
0794469da   Kay Sievers   ACPI: struct devi...
948
  					dev_name(&device->dev), event,
9ea7d5757   Vladimir Lebedev   ACPI: battery: Li...
949
  					acpi_battery_present(battery));
2345baf4a   Justin P. Mattock   battery: fix typo...
950
  	/* acpi_battery_update could remove power_supply object */
153e500f5   Zhang Rui   ACPI battery: don...
951
  	if (old && battery->bat.dev)
f79e1cec8   Alan Jenkins   ACPI: battery dri...
952
  		power_supply_changed(&battery->bat);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
  }
25be58215   Kyle McMartin   ACPI battery: fri...
954
955
956
957
958
959
  static int battery_notify(struct notifier_block *nb,
  			       unsigned long mode, void *_unused)
  {
  	struct acpi_battery *battery = container_of(nb, struct acpi_battery,
  						    pm_nb);
  	switch (mode) {
d5a5911b3   Lan Tianyu   ACPI / Battery: A...
960
  	case PM_POST_HIBERNATION:
25be58215   Kyle McMartin   ACPI battery: fri...
961
  	case PM_POST_SUSPEND:
6e17fb6aa   Lan Tianyu   ACPI / Battery: A...
962
963
964
965
  		if (battery->bat.dev) {
  			sysfs_remove_battery(battery);
  			sysfs_add_battery(battery);
  		}
25be58215   Kyle McMartin   ACPI battery: fri...
966
967
968
969
970
  		break;
  	}
  
  	return 0;
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
971
  static int acpi_battery_add(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
973
  	int result = 0;
4be44fcd3   Len Brown   [ACPI] Lindent al...
974
  	struct acpi_battery *battery = NULL;
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
975
  	acpi_handle handle;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
  	if (!device)
d550d98d3   Patrick Mochel   ACPI: delete trac...
977
  		return -EINVAL;
36bcbec7c   Burman Yan   ACPI: replace kma...
978
  	battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
  	if (!battery)
d550d98d3   Patrick Mochel   ACPI: delete trac...
980
  		return -ENOMEM;
145def84a   Patrick Mochel   ACPI: battery: ad...
981
  	battery->device = device;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
983
  	strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
  	strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
db89b4f0d   Pavel Machek   ACPI: catch calls...
984
  	device->driver_data = battery;
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
985
  	mutex_init(&battery->lock);
69d94ec6d   Sergey Senozhatsky   Battery: sysfs_re...
986
  	mutex_init(&battery->sysfs_lock);
c67fcd670   Alexey Starikovskiy   ACPI: Battery: Ad...
987
988
989
  	if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
  			"_BIX", &handle)))
  		set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
eb03cb02b   Stefan Hajnoczi   ACPI / Battery: p...
990
991
992
  	result = acpi_battery_update(battery);
  	if (result)
  		goto fail;
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
993
  #ifdef CONFIG_ACPI_PROCFS_POWER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
  	result = acpi_battery_add_fs(device);
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
995
  #endif
e80bba4b5   Stefan Hajnoczi   ACPI / Battery: a...
996
  	if (result) {
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
997
  #ifdef CONFIG_ACPI_PROCFS_POWER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
998
  		acpi_battery_remove_fs(device);
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
999
  #endif
e80bba4b5   Stefan Hajnoczi   ACPI / Battery: a...
1000
  		goto fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1001
  	}
25be58215   Kyle McMartin   ACPI battery: fri...
1002

e80bba4b5   Stefan Hajnoczi   ACPI / Battery: a...
1003
1004
1005
1006
  	printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)
  ",
  		ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
  		device->status.battery_present ? "present" : "absent");
25be58215   Kyle McMartin   ACPI battery: fri...
1007
1008
  	battery->pm_nb.notifier_call = battery_notify;
  	register_pm_notifier(&battery->pm_nb);
d550d98d3   Patrick Mochel   ACPI: delete trac...
1009
  	return result;
e80bba4b5   Stefan Hajnoczi   ACPI / Battery: a...
1010
1011
1012
1013
  
  fail:
  	sysfs_remove_battery(battery);
  	mutex_destroy(&battery->lock);
69d94ec6d   Sergey Senozhatsky   Battery: sysfs_re...
1014
  	mutex_destroy(&battery->sysfs_lock);
e80bba4b5   Stefan Hajnoczi   ACPI / Battery: a...
1015
1016
  	kfree(battery);
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
1018
  static int acpi_battery_remove(struct acpi_device *device, int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
1020
  	struct acpi_battery *battery = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
  	if (!device || !acpi_driver_data(device))
d550d98d3   Patrick Mochel   ACPI: delete trac...
1023
  		return -EINVAL;
50dd09697   Jan Engelhardt   ACPI: Remove unne...
1024
  	battery = acpi_driver_data(device);
25be58215   Kyle McMartin   ACPI battery: fri...
1025
  	unregister_pm_notifier(&battery->pm_nb);
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
1026
  #ifdef CONFIG_ACPI_PROCFS_POWER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
  	acpi_battery_remove_fs(device);
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
1028
  #endif
508df92d1   Andrey Borzenkov   ACPI: battery: re...
1029
  	sysfs_remove_battery(battery);
038fdea29   Alexey Starikovskiy   ACPI: Battery: do...
1030
  	mutex_destroy(&battery->lock);
69d94ec6d   Sergey Senozhatsky   Battery: sysfs_re...
1031
  	mutex_destroy(&battery->sysfs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
  	kfree(battery);
d550d98d3   Patrick Mochel   ACPI: delete trac...
1033
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  }
34c4415ab   Jiri Kosina   ACPI: check batte...
1035
  /* this is needed to learn about changes made in suspended state */
5d9464a46   Patrick Mochel   ACPI: add ACPI bu...
1036
  static int acpi_battery_resume(struct acpi_device *device)
34c4415ab   Jiri Kosina   ACPI: check batte...
1037
1038
  {
  	struct acpi_battery *battery;
34c4415ab   Jiri Kosina   ACPI: check batte...
1039
1040
  	if (!device)
  		return -EINVAL;
f1d4661ab   Alexey Starikovskiy   ACPI: Battery: si...
1041
1042
  	battery = acpi_driver_data(device);
  	battery->update_time = 0;
508df92d1   Andrey Borzenkov   ACPI: battery: re...
1043
  	acpi_battery_update(battery);
b6ce4083e   Vladimir Lebedev   ACPI: Cache batte...
1044
  	return 0;
34c4415ab   Jiri Kosina   ACPI: check batte...
1045
  }
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
1046
1047
1048
1049
  static struct acpi_driver acpi_battery_driver = {
  	.name = "battery",
  	.class = ACPI_BATTERY_CLASS,
  	.ids = battery_device_ids,
d94066910   Bjorn Helgaas   ACPI: battery: us...
1050
  	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
1051
1052
1053
1054
  	.ops = {
  		.add = acpi_battery_add,
  		.resume = acpi_battery_resume,
  		.remove = acpi_battery_remove,
d94066910   Bjorn Helgaas   ACPI: battery: us...
1055
  		.notify = acpi_battery_notify,
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
1056
1057
  		},
  };
b0cbc861a   Linus Torvalds   Revert "ACPI batt...
1058
  static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1059
  {
4d8316d5e   Pavel Machek   ACPI: fix boot wi...
1060
  	if (acpi_disabled)
0f66af530   Arjan van de Ven   ACPI: battery: as...
1061
  		return;
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
1062
  #ifdef CONFIG_ACPI_PROCFS_POWER
3f86b8324   Rich Townsend   ACPI: add support...
1063
  	acpi_battery_dir = acpi_lock_battery_dir();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
  	if (!acpi_battery_dir)
0f66af530   Arjan van de Ven   ACPI: battery: as...
1065
  		return;
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
1066
  #endif
aa650bbdc   Alexey Starikovskiy   ACPI: Battery: Mi...
1067
  	if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
1068
  #ifdef CONFIG_ACPI_PROCFS_POWER
3f86b8324   Rich Townsend   ACPI: add support...
1069
  		acpi_unlock_battery_dir(acpi_battery_dir);
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
1070
  #endif
0f66af530   Arjan van de Ven   ACPI: battery: as...
1071
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1072
  	}
0f66af530   Arjan van de Ven   ACPI: battery: as...
1073
1074
1075
1076
1077
1078
  	return;
  }
  
  static int __init acpi_battery_init(void)
  {
  	async_schedule(acpi_battery_init_async, NULL);
d550d98d3   Patrick Mochel   ACPI: delete trac...
1079
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1080
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
1081
  static void __exit acpi_battery_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
  	acpi_bus_unregister_driver(&acpi_battery_driver);
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
1084
  #ifdef CONFIG_ACPI_PROCFS_POWER
3f86b8324   Rich Townsend   ACPI: add support...
1085
  	acpi_unlock_battery_dir(acpi_battery_dir);
d73809657   Alexey Starikovskiy   ACPI: Battery: Ad...
1086
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1088
1089
  module_init(acpi_battery_init);
  module_exit(acpi_battery_exit);