Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * battery.c - ACPI Battery Driver (Revision: 2.0)
4 : : *
5 : : * Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
6 : : * Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
7 : : * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
8 : : * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
9 : : */
10 : :
11 : : #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 : :
13 : : #include <linux/async.h>
14 : : #include <linux/delay.h>
15 : : #include <linux/dmi.h>
16 : : #include <linux/jiffies.h>
17 : : #include <linux/kernel.h>
18 : : #include <linux/list.h>
19 : : #include <linux/module.h>
20 : : #include <linux/mutex.h>
21 : : #include <linux/slab.h>
22 : : #include <linux/suspend.h>
23 : : #include <linux/types.h>
24 : :
25 : : #include <asm/unaligned.h>
26 : :
27 : : #ifdef CONFIG_ACPI_PROCFS_POWER
28 : : #include <linux/proc_fs.h>
29 : : #include <linux/seq_file.h>
30 : : #include <linux/uaccess.h>
31 : : #endif
32 : :
33 : : #include <linux/acpi.h>
34 : : #include <linux/power_supply.h>
35 : :
36 : : #include <acpi/battery.h>
37 : :
38 : : #define PREFIX "ACPI: "
39 : :
40 : : #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
41 : : #define ACPI_BATTERY_CAPACITY_VALID(capacity) \
42 : : ((capacity) != 0 && (capacity) != ACPI_BATTERY_VALUE_UNKNOWN)
43 : :
44 : : #define ACPI_BATTERY_DEVICE_NAME "Battery"
45 : :
46 : : /* Battery power unit: 0 means mW, 1 means mA */
47 : : #define ACPI_BATTERY_POWER_UNIT_MA 1
48 : :
49 : : #define ACPI_BATTERY_STATE_DISCHARGING 0x1
50 : : #define ACPI_BATTERY_STATE_CHARGING 0x2
51 : : #define ACPI_BATTERY_STATE_CRITICAL 0x4
52 : :
53 : : #define _COMPONENT ACPI_BATTERY_COMPONENT
54 : :
55 : : ACPI_MODULE_NAME("battery");
56 : :
57 : : MODULE_AUTHOR("Paul Diefenbaugh");
58 : : MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
59 : : MODULE_DESCRIPTION("ACPI Battery Driver");
60 : : MODULE_LICENSE("GPL");
61 : :
62 : : static async_cookie_t async_cookie;
63 : : static bool battery_driver_registered;
64 : : static int battery_bix_broken_package;
65 : : static int battery_notification_delay_ms;
66 : : static int battery_ac_is_broken;
67 : : static int battery_check_pmic = 1;
68 : : static unsigned int cache_time = 1000;
69 : : module_param(cache_time, uint, 0644);
70 : : MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
71 : :
72 : : #ifdef CONFIG_ACPI_PROCFS_POWER
73 : : extern struct proc_dir_entry *acpi_lock_battery_dir(void);
74 : : extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
75 : : #endif
76 : :
77 : : static const struct acpi_device_id battery_device_ids[] = {
78 : : {"PNP0C0A", 0},
79 : : {"", 0},
80 : : };
81 : :
82 : : MODULE_DEVICE_TABLE(acpi, battery_device_ids);
83 : :
84 : : /* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
85 : : static const char * const acpi_battery_blacklist[] = {
86 : : "INT33F4", /* X-Powers AXP288 PMIC */
87 : : };
88 : :
89 : : enum {
90 : : ACPI_BATTERY_ALARM_PRESENT,
91 : : ACPI_BATTERY_XINFO_PRESENT,
92 : : ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
93 : : /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
94 : : switches between mWh and mAh depending on whether the system
95 : : is running on battery or not. When mAh is the unit, most
96 : : reported values are incorrect and need to be adjusted by
97 : : 10000/design_voltage. Verified on x201, t410, t410s, and x220.
98 : : Pre-2010 and 2012 models appear to always report in mWh and
99 : : are thus unaffected (tested with t42, t61, t500, x200, x300,
100 : : and x230). Also, in mid-2012 Lenovo issued a BIOS update for
101 : : the 2011 models that fixes the issue (tested on x220 with a
102 : : post-1.29 BIOS), but as of Nov. 2012, no such update is
103 : : available for the 2010 models. */
104 : : ACPI_BATTERY_QUIRK_THINKPAD_MAH,
105 : : /* for batteries reporting current capacity with design capacity
106 : : * on a full charge, but showing degradation in full charge cap.
107 : : */
108 : : ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE,
109 : : };
110 : :
111 : : struct acpi_battery {
112 : : struct mutex lock;
113 : : struct mutex sysfs_lock;
114 : : struct power_supply *bat;
115 : : struct power_supply_desc bat_desc;
116 : : struct acpi_device *device;
117 : : struct notifier_block pm_nb;
118 : : struct list_head list;
119 : : unsigned long update_time;
120 : : int revision;
121 : : int rate_now;
122 : : int capacity_now;
123 : : int voltage_now;
124 : : int design_capacity;
125 : : int full_charge_capacity;
126 : : int technology;
127 : : int design_voltage;
128 : : int design_capacity_warning;
129 : : int design_capacity_low;
130 : : int cycle_count;
131 : : int measurement_accuracy;
132 : : int max_sampling_time;
133 : : int min_sampling_time;
134 : : int max_averaging_interval;
135 : : int min_averaging_interval;
136 : : int capacity_granularity_1;
137 : : int capacity_granularity_2;
138 : : int alarm;
139 : : char model_number[32];
140 : : char serial_number[32];
141 : : char type[32];
142 : : char oem_info[32];
143 : : int state;
144 : : int power_unit;
145 : : unsigned long flags;
146 : : };
147 : :
148 : : #define to_acpi_battery(x) power_supply_get_drvdata(x)
149 : :
150 : 0 : static inline int acpi_battery_present(struct acpi_battery *battery)
151 : : {
152 : 0 : return battery->device->status.battery_present;
153 : : }
154 : :
155 : 0 : static int acpi_battery_technology(struct acpi_battery *battery)
156 : : {
157 [ # # ]: 0 : if (!strcasecmp("NiCd", battery->type))
158 : : return POWER_SUPPLY_TECHNOLOGY_NiCd;
159 [ # # ]: 0 : if (!strcasecmp("NiMH", battery->type))
160 : : return POWER_SUPPLY_TECHNOLOGY_NiMH;
161 [ # # ]: 0 : if (!strcasecmp("LION", battery->type))
162 : : return POWER_SUPPLY_TECHNOLOGY_LION;
163 [ # # ]: 0 : if (!strncasecmp("LI-ION", battery->type, 6))
164 : : return POWER_SUPPLY_TECHNOLOGY_LION;
165 [ # # ]: 0 : if (!strcasecmp("LiP", battery->type))
166 : 0 : return POWER_SUPPLY_TECHNOLOGY_LIPO;
167 : : return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
168 : : }
169 : :
170 : : static int acpi_battery_get_state(struct acpi_battery *battery);
171 : :
172 : 0 : static int acpi_battery_is_charged(struct acpi_battery *battery)
173 : : {
174 : : /* charging, discharging or critical low */
175 : 0 : if (battery->state != 0)
176 : : return 0;
177 : :
178 : : /* battery not reporting charge */
179 [ # # # # ]: 0 : if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
180 : : battery->capacity_now == 0)
181 : : return 0;
182 : :
183 : : /* good batteries update full_charge as the batteries degrade */
184 [ # # # # ]: 0 : if (battery->full_charge_capacity == battery->capacity_now)
185 : : return 1;
186 : :
187 : : /* fallback to using design values for broken batteries */
188 [ # # # # ]: 0 : if (battery->design_capacity == battery->capacity_now)
189 : : return 1;
190 : :
191 : : /* we don't do any sort of metric based on percentages */
192 : : return 0;
193 : : }
194 : :
195 : 0 : static bool acpi_battery_is_degraded(struct acpi_battery *battery)
196 : : {
197 : 0 : return ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
198 [ # # # # ]: 0 : ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity) &&
199 : : battery->full_charge_capacity < battery->design_capacity;
200 : : }
201 : :
202 : 0 : static int acpi_battery_handle_discharging(struct acpi_battery *battery)
203 : : {
204 : : /*
205 : : * Some devices wrongly report discharging if the battery's charge level
206 : : * was above the device's start charging threshold atm the AC adapter
207 : : * was plugged in and the device thus did not start a new charge cycle.
208 : : */
209 [ # # ]: 0 : if ((battery_ac_is_broken || power_supply_is_system_supplied()) &&
210 [ # # ]: 0 : battery->rate_now == 0)
211 : 0 : return POWER_SUPPLY_STATUS_NOT_CHARGING;
212 : :
213 : : return POWER_SUPPLY_STATUS_DISCHARGING;
214 : : }
215 : :
216 : 0 : static int acpi_battery_get_property(struct power_supply *psy,
217 : : enum power_supply_property psp,
218 : : union power_supply_propval *val)
219 : : {
220 : 0 : int full_capacity = ACPI_BATTERY_VALUE_UNKNOWN, ret = 0;
221 : 0 : struct acpi_battery *battery = to_acpi_battery(psy);
222 : :
223 [ # # ]: 0 : if (acpi_battery_present(battery)) {
224 : : /* run battery update only if it is present */
225 : 0 : acpi_battery_get_state(battery);
226 [ # # ]: 0 : } else if (psp != POWER_SUPPLY_PROP_PRESENT)
227 : : return -ENODEV;
228 [ # # # # : 0 : switch (psp) {
# # # # #
# # # # #
# # ]
229 : 0 : case POWER_SUPPLY_PROP_STATUS:
230 [ # # ]: 0 : if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
231 [ # # ]: 0 : val->intval = acpi_battery_handle_discharging(battery);
232 [ # # ]: 0 : else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
233 : 0 : val->intval = POWER_SUPPLY_STATUS_CHARGING;
234 [ # # ]: 0 : else if (acpi_battery_is_charged(battery))
235 : 0 : val->intval = POWER_SUPPLY_STATUS_FULL;
236 : : else
237 : 0 : val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
238 : : break;
239 : 0 : case POWER_SUPPLY_PROP_PRESENT:
240 : 0 : val->intval = acpi_battery_present(battery);
241 : 0 : break;
242 : 0 : case POWER_SUPPLY_PROP_TECHNOLOGY:
243 : 0 : val->intval = acpi_battery_technology(battery);
244 : 0 : break;
245 : 0 : case POWER_SUPPLY_PROP_CYCLE_COUNT:
246 : 0 : val->intval = battery->cycle_count;
247 : 0 : break;
248 : 0 : case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
249 [ # # ]: 0 : if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
250 : : ret = -ENODEV;
251 : : else
252 : 0 : val->intval = battery->design_voltage * 1000;
253 : : break;
254 : 0 : case POWER_SUPPLY_PROP_VOLTAGE_NOW:
255 [ # # ]: 0 : if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
256 : : ret = -ENODEV;
257 : : else
258 : 0 : val->intval = battery->voltage_now * 1000;
259 : : break;
260 : 0 : case POWER_SUPPLY_PROP_CURRENT_NOW:
261 : : case POWER_SUPPLY_PROP_POWER_NOW:
262 [ # # ]: 0 : if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
263 : : ret = -ENODEV;
264 : : else
265 : 0 : val->intval = battery->rate_now * 1000;
266 : : break;
267 : 0 : case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
268 : : case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
269 [ # # ]: 0 : if (!ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
270 : : ret = -ENODEV;
271 : : else
272 : 0 : val->intval = battery->design_capacity * 1000;
273 : : break;
274 : 0 : case POWER_SUPPLY_PROP_CHARGE_FULL:
275 : : case POWER_SUPPLY_PROP_ENERGY_FULL:
276 [ # # ]: 0 : if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
277 : : ret = -ENODEV;
278 : : else
279 : 0 : val->intval = battery->full_charge_capacity * 1000;
280 : : break;
281 : 0 : case POWER_SUPPLY_PROP_CHARGE_NOW:
282 : : case POWER_SUPPLY_PROP_ENERGY_NOW:
283 [ # # ]: 0 : if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
284 : : ret = -ENODEV;
285 : : else
286 : 0 : val->intval = battery->capacity_now * 1000;
287 : : break;
288 : 0 : case POWER_SUPPLY_PROP_CAPACITY:
289 [ # # ]: 0 : if (ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
290 : : full_capacity = battery->full_charge_capacity;
291 [ # # ]: 0 : else if (ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
292 : 0 : full_capacity = battery->design_capacity;
293 : :
294 [ # # # # ]: 0 : if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
295 : : full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
296 : : ret = -ENODEV;
297 : : else
298 : 0 : val->intval = battery->capacity_now * 100/
299 : : full_capacity;
300 : : break;
301 : 0 : case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
302 [ # # ]: 0 : if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
303 : 0 : val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
304 [ # # ]: 0 : else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
305 [ # # ]: 0 : (battery->capacity_now <= battery->alarm))
306 : 0 : val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
307 [ # # ]: 0 : else if (acpi_battery_is_charged(battery))
308 : 0 : val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
309 : : else
310 : 0 : val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
311 : : break;
312 : 0 : case POWER_SUPPLY_PROP_MODEL_NAME:
313 : 0 : val->strval = battery->model_number;
314 : 0 : break;
315 : 0 : case POWER_SUPPLY_PROP_MANUFACTURER:
316 : 0 : val->strval = battery->oem_info;
317 : 0 : break;
318 : 0 : case POWER_SUPPLY_PROP_SERIAL_NUMBER:
319 : 0 : val->strval = battery->serial_number;
320 : 0 : break;
321 : : default:
322 : : ret = -EINVAL;
323 : : }
324 : : return ret;
325 : : }
326 : :
327 : : static enum power_supply_property charge_battery_props[] = {
328 : : POWER_SUPPLY_PROP_STATUS,
329 : : POWER_SUPPLY_PROP_PRESENT,
330 : : POWER_SUPPLY_PROP_TECHNOLOGY,
331 : : POWER_SUPPLY_PROP_CYCLE_COUNT,
332 : : POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
333 : : POWER_SUPPLY_PROP_VOLTAGE_NOW,
334 : : POWER_SUPPLY_PROP_CURRENT_NOW,
335 : : POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
336 : : POWER_SUPPLY_PROP_CHARGE_FULL,
337 : : POWER_SUPPLY_PROP_CHARGE_NOW,
338 : : POWER_SUPPLY_PROP_CAPACITY,
339 : : POWER_SUPPLY_PROP_CAPACITY_LEVEL,
340 : : POWER_SUPPLY_PROP_MODEL_NAME,
341 : : POWER_SUPPLY_PROP_MANUFACTURER,
342 : : POWER_SUPPLY_PROP_SERIAL_NUMBER,
343 : : };
344 : :
345 : : static enum power_supply_property charge_battery_full_cap_broken_props[] = {
346 : : POWER_SUPPLY_PROP_STATUS,
347 : : POWER_SUPPLY_PROP_PRESENT,
348 : : POWER_SUPPLY_PROP_TECHNOLOGY,
349 : : POWER_SUPPLY_PROP_CYCLE_COUNT,
350 : : POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
351 : : POWER_SUPPLY_PROP_VOLTAGE_NOW,
352 : : POWER_SUPPLY_PROP_CURRENT_NOW,
353 : : POWER_SUPPLY_PROP_CHARGE_NOW,
354 : : POWER_SUPPLY_PROP_MODEL_NAME,
355 : : POWER_SUPPLY_PROP_MANUFACTURER,
356 : : POWER_SUPPLY_PROP_SERIAL_NUMBER,
357 : : };
358 : :
359 : : static enum power_supply_property energy_battery_props[] = {
360 : : POWER_SUPPLY_PROP_STATUS,
361 : : POWER_SUPPLY_PROP_PRESENT,
362 : : POWER_SUPPLY_PROP_TECHNOLOGY,
363 : : POWER_SUPPLY_PROP_CYCLE_COUNT,
364 : : POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
365 : : POWER_SUPPLY_PROP_VOLTAGE_NOW,
366 : : POWER_SUPPLY_PROP_POWER_NOW,
367 : : POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
368 : : POWER_SUPPLY_PROP_ENERGY_FULL,
369 : : POWER_SUPPLY_PROP_ENERGY_NOW,
370 : : POWER_SUPPLY_PROP_CAPACITY,
371 : : POWER_SUPPLY_PROP_CAPACITY_LEVEL,
372 : : POWER_SUPPLY_PROP_MODEL_NAME,
373 : : POWER_SUPPLY_PROP_MANUFACTURER,
374 : : POWER_SUPPLY_PROP_SERIAL_NUMBER,
375 : : };
376 : :
377 : : static enum power_supply_property energy_battery_full_cap_broken_props[] = {
378 : : POWER_SUPPLY_PROP_STATUS,
379 : : POWER_SUPPLY_PROP_PRESENT,
380 : : POWER_SUPPLY_PROP_TECHNOLOGY,
381 : : POWER_SUPPLY_PROP_CYCLE_COUNT,
382 : : POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
383 : : POWER_SUPPLY_PROP_VOLTAGE_NOW,
384 : : POWER_SUPPLY_PROP_POWER_NOW,
385 : : POWER_SUPPLY_PROP_ENERGY_NOW,
386 : : POWER_SUPPLY_PROP_MODEL_NAME,
387 : : POWER_SUPPLY_PROP_MANUFACTURER,
388 : : POWER_SUPPLY_PROP_SERIAL_NUMBER,
389 : : };
390 : :
391 : : /* --------------------------------------------------------------------------
392 : : Battery Management
393 : : -------------------------------------------------------------------------- */
394 : : struct acpi_offsets {
395 : : size_t offset; /* offset inside struct acpi_sbs_battery */
396 : : u8 mode; /* int or string? */
397 : : };
398 : :
399 : : static const struct acpi_offsets state_offsets[] = {
400 : : {offsetof(struct acpi_battery, state), 0},
401 : : {offsetof(struct acpi_battery, rate_now), 0},
402 : : {offsetof(struct acpi_battery, capacity_now), 0},
403 : : {offsetof(struct acpi_battery, voltage_now), 0},
404 : : };
405 : :
406 : : static const struct acpi_offsets info_offsets[] = {
407 : : {offsetof(struct acpi_battery, power_unit), 0},
408 : : {offsetof(struct acpi_battery, design_capacity), 0},
409 : : {offsetof(struct acpi_battery, full_charge_capacity), 0},
410 : : {offsetof(struct acpi_battery, technology), 0},
411 : : {offsetof(struct acpi_battery, design_voltage), 0},
412 : : {offsetof(struct acpi_battery, design_capacity_warning), 0},
413 : : {offsetof(struct acpi_battery, design_capacity_low), 0},
414 : : {offsetof(struct acpi_battery, capacity_granularity_1), 0},
415 : : {offsetof(struct acpi_battery, capacity_granularity_2), 0},
416 : : {offsetof(struct acpi_battery, model_number), 1},
417 : : {offsetof(struct acpi_battery, serial_number), 1},
418 : : {offsetof(struct acpi_battery, type), 1},
419 : : {offsetof(struct acpi_battery, oem_info), 1},
420 : : };
421 : :
422 : : static const struct acpi_offsets extended_info_offsets[] = {
423 : : {offsetof(struct acpi_battery, revision), 0},
424 : : {offsetof(struct acpi_battery, power_unit), 0},
425 : : {offsetof(struct acpi_battery, design_capacity), 0},
426 : : {offsetof(struct acpi_battery, full_charge_capacity), 0},
427 : : {offsetof(struct acpi_battery, technology), 0},
428 : : {offsetof(struct acpi_battery, design_voltage), 0},
429 : : {offsetof(struct acpi_battery, design_capacity_warning), 0},
430 : : {offsetof(struct acpi_battery, design_capacity_low), 0},
431 : : {offsetof(struct acpi_battery, cycle_count), 0},
432 : : {offsetof(struct acpi_battery, measurement_accuracy), 0},
433 : : {offsetof(struct acpi_battery, max_sampling_time), 0},
434 : : {offsetof(struct acpi_battery, min_sampling_time), 0},
435 : : {offsetof(struct acpi_battery, max_averaging_interval), 0},
436 : : {offsetof(struct acpi_battery, min_averaging_interval), 0},
437 : : {offsetof(struct acpi_battery, capacity_granularity_1), 0},
438 : : {offsetof(struct acpi_battery, capacity_granularity_2), 0},
439 : : {offsetof(struct acpi_battery, model_number), 1},
440 : : {offsetof(struct acpi_battery, serial_number), 1},
441 : : {offsetof(struct acpi_battery, type), 1},
442 : : {offsetof(struct acpi_battery, oem_info), 1},
443 : : };
444 : :
445 : 0 : static int extract_package(struct acpi_battery *battery,
446 : : union acpi_object *package,
447 : : const struct acpi_offsets *offsets, int num)
448 : : {
449 : 0 : int i;
450 : 0 : union acpi_object *element;
451 [ # # ]: 0 : if (package->type != ACPI_TYPE_PACKAGE)
452 : : return -EFAULT;
453 [ # # ]: 0 : for (i = 0; i < num; ++i) {
454 [ # # ]: 0 : if (package->package.count <= i)
455 : : return -EFAULT;
456 : 0 : element = &package->package.elements[i];
457 [ # # ]: 0 : if (offsets[i].mode) {
458 : 0 : u8 *ptr = (u8 *)battery + offsets[i].offset;
459 [ # # ]: 0 : if (element->type == ACPI_TYPE_STRING ||
460 : : element->type == ACPI_TYPE_BUFFER)
461 : 0 : strncpy(ptr, element->string.pointer, 32);
462 [ # # ]: 0 : else if (element->type == ACPI_TYPE_INTEGER) {
463 : 0 : strncpy(ptr, (u8 *)&element->integer.value,
464 : : sizeof(u64));
465 : 0 : ptr[sizeof(u64)] = 0;
466 : : } else
467 : 0 : *ptr = 0; /* don't have value */
468 : : } else {
469 : 0 : int *x = (int *)((u8 *)battery + offsets[i].offset);
470 [ # # ]: 0 : *x = (element->type == ACPI_TYPE_INTEGER) ?
471 : 0 : element->integer.value : -1;
472 : : }
473 : : }
474 : : return 0;
475 : : }
476 : :
477 : : static int acpi_battery_get_status(struct acpi_battery *battery)
478 : : {
479 : : if (acpi_bus_get_status(battery->device)) {
480 : : ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
481 : : return -ENODEV;
482 : : }
483 : : return 0;
484 : : }
485 : :
486 : :
487 : : static int extract_battery_info(const int use_bix,
488 : : struct acpi_battery *battery,
489 : : const struct acpi_buffer *buffer)
490 : : {
491 : : int result = -EFAULT;
492 : :
493 : : if (use_bix && battery_bix_broken_package)
494 : : result = extract_package(battery, buffer->pointer,
495 : : extended_info_offsets + 1,
496 : : ARRAY_SIZE(extended_info_offsets) - 1);
497 : : else if (use_bix)
498 : : result = extract_package(battery, buffer->pointer,
499 : : extended_info_offsets,
500 : : ARRAY_SIZE(extended_info_offsets));
501 : : else
502 : : result = extract_package(battery, buffer->pointer,
503 : : info_offsets, ARRAY_SIZE(info_offsets));
504 : : if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
505 : : battery->full_charge_capacity = battery->design_capacity;
506 : : if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
507 : : battery->power_unit && battery->design_voltage) {
508 : : battery->design_capacity = battery->design_capacity *
509 : : 10000 / battery->design_voltage;
510 : : battery->full_charge_capacity = battery->full_charge_capacity *
511 : : 10000 / battery->design_voltage;
512 : : battery->design_capacity_warning =
513 : : battery->design_capacity_warning *
514 : : 10000 / battery->design_voltage;
515 : : /* Curiously, design_capacity_low, unlike the rest of them,
516 : : is correct. */
517 : : /* capacity_granularity_* equal 1 on the systems tested, so
518 : : it's impossible to tell if they would need an adjustment
519 : : or not if their values were higher. */
520 : : }
521 : : if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
522 : : battery->capacity_now > battery->full_charge_capacity)
523 : : battery->capacity_now = battery->full_charge_capacity;
524 : :
525 : : return result;
526 : : }
527 : :
528 : 0 : static int acpi_battery_get_info(struct acpi_battery *battery)
529 : : {
530 : 0 : const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
531 : 0 : int use_bix;
532 : 0 : int result = -ENODEV;
533 : :
534 [ # # ]: 0 : if (!acpi_battery_present(battery))
535 : : return 0;
536 : :
537 : :
538 [ # # ]: 0 : for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
539 : 0 : struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
540 : 0 : acpi_status status = AE_ERROR;
541 : :
542 : 0 : mutex_lock(&battery->lock);
543 [ # # ]: 0 : status = acpi_evaluate_object(battery->device->handle,
544 : : use_bix ? "_BIX":"_BIF",
545 : : NULL, &buffer);
546 : 0 : mutex_unlock(&battery->lock);
547 : :
548 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
549 : 0 : ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
550 : : use_bix ? "_BIX":"_BIF"));
551 : : } else {
552 : 0 : result = extract_battery_info(use_bix,
553 : : battery,
554 : : &buffer);
555 : :
556 : 0 : kfree(buffer.pointer);
557 : 0 : break;
558 : : }
559 : : }
560 : :
561 [ # # # # ]: 0 : if (!result && !use_bix && xinfo)
562 : 0 : pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
563 : :
564 : : return result;
565 : : }
566 : :
567 : 0 : static int acpi_battery_get_state(struct acpi_battery *battery)
568 : : {
569 : 0 : int result = 0;
570 : 0 : acpi_status status = 0;
571 : 0 : struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
572 : :
573 [ # # ]: 0 : if (!acpi_battery_present(battery))
574 : : return 0;
575 : :
576 [ # # ]: 0 : if (battery->update_time &&
577 [ # # # # ]: 0 : time_before(jiffies, battery->update_time +
578 : : msecs_to_jiffies(cache_time)))
579 : : return 0;
580 : :
581 : 0 : mutex_lock(&battery->lock);
582 : 0 : status = acpi_evaluate_object(battery->device->handle, "_BST",
583 : : NULL, &buffer);
584 : 0 : mutex_unlock(&battery->lock);
585 : :
586 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
587 : 0 : ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
588 : 0 : return -ENODEV;
589 : : }
590 : :
591 : 0 : result = extract_package(battery, buffer.pointer,
592 : : state_offsets, ARRAY_SIZE(state_offsets));
593 : 0 : battery->update_time = jiffies;
594 : 0 : kfree(buffer.pointer);
595 : :
596 : : /* For buggy DSDTs that report negative 16-bit values for either
597 : : * charging or discharging current and/or report 0 as 65536
598 : : * due to bad math.
599 : : */
600 [ # # ]: 0 : if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
601 [ # # ]: 0 : battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
602 [ # # ]: 0 : (s16)(battery->rate_now) < 0) {
603 : 0 : battery->rate_now = abs((s16)battery->rate_now);
604 [ # # ]: 0 : pr_warn_once(FW_BUG "battery: (dis)charge rate invalid.\n");
605 : : }
606 : :
607 [ # # ]: 0 : if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
608 [ # # # # ]: 0 : && battery->capacity_now >= 0 && battery->capacity_now <= 100)
609 : 0 : battery->capacity_now = (battery->capacity_now *
610 : 0 : battery->full_charge_capacity) / 100;
611 [ # # ]: 0 : if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
612 [ # # # # ]: 0 : battery->power_unit && battery->design_voltage) {
613 : 0 : battery->capacity_now = battery->capacity_now *
614 : 0 : 10000 / battery->design_voltage;
615 : : }
616 [ # # ]: 0 : if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
617 [ # # ]: 0 : battery->capacity_now > battery->full_charge_capacity)
618 : 0 : battery->capacity_now = battery->full_charge_capacity;
619 : :
620 : : return result;
621 : : }
622 : :
623 : 0 : static int acpi_battery_set_alarm(struct acpi_battery *battery)
624 : : {
625 : 0 : acpi_status status = 0;
626 : :
627 [ # # # # ]: 0 : if (!acpi_battery_present(battery) ||
628 : 0 : !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
629 : 0 : return -ENODEV;
630 : :
631 : 0 : mutex_lock(&battery->lock);
632 : 0 : status = acpi_execute_simple_method(battery->device->handle, "_BTP",
633 : 0 : battery->alarm);
634 : 0 : mutex_unlock(&battery->lock);
635 : :
636 [ # # ]: 0 : if (ACPI_FAILURE(status))
637 : 0 : return -ENODEV;
638 : :
639 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
640 : : return 0;
641 : : }
642 : :
643 : 0 : static int acpi_battery_init_alarm(struct acpi_battery *battery)
644 : : {
645 : : /* See if alarms are supported, and if so, set default */
646 [ # # ]: 0 : if (!acpi_has_method(battery->device->handle, "_BTP")) {
647 : 0 : clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
648 : 0 : return 0;
649 : : }
650 : 0 : set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
651 [ # # ]: 0 : if (!battery->alarm)
652 : 0 : battery->alarm = battery->design_capacity_warning;
653 : 0 : return acpi_battery_set_alarm(battery);
654 : : }
655 : :
656 : 0 : static ssize_t acpi_battery_alarm_show(struct device *dev,
657 : : struct device_attribute *attr,
658 : : char *buf)
659 : : {
660 : 0 : struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
661 : 0 : return sprintf(buf, "%d\n", battery->alarm * 1000);
662 : : }
663 : :
664 : 0 : static ssize_t acpi_battery_alarm_store(struct device *dev,
665 : : struct device_attribute *attr,
666 : : const char *buf, size_t count)
667 : : {
668 : 0 : unsigned long x;
669 : 0 : struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
670 [ # # ]: 0 : if (sscanf(buf, "%lu\n", &x) == 1)
671 : 0 : battery->alarm = x/1000;
672 [ # # ]: 0 : if (acpi_battery_present(battery))
673 : 0 : acpi_battery_set_alarm(battery);
674 : 0 : return count;
675 : : }
676 : :
677 : : static const struct device_attribute alarm_attr = {
678 : : .attr = {.name = "alarm", .mode = 0644},
679 : : .show = acpi_battery_alarm_show,
680 : : .store = acpi_battery_alarm_store,
681 : : };
682 : :
683 : : /*
684 : : * The Battery Hooking API
685 : : *
686 : : * This API is used inside other drivers that need to expose
687 : : * platform-specific behaviour within the generic driver in a
688 : : * generic way.
689 : : *
690 : : */
691 : :
692 : : static LIST_HEAD(acpi_battery_list);
693 : : static LIST_HEAD(battery_hook_list);
694 : : static DEFINE_MUTEX(hook_mutex);
695 : :
696 : 0 : static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock)
697 : : {
698 : 0 : struct acpi_battery *battery;
699 : : /*
700 : : * In order to remove a hook, we first need to
701 : : * de-register all the batteries that are registered.
702 : : */
703 [ # # ]: 0 : if (lock)
704 : 0 : mutex_lock(&hook_mutex);
705 [ # # ]: 0 : list_for_each_entry(battery, &acpi_battery_list, list) {
706 : 0 : hook->remove_battery(battery->bat);
707 : : }
708 [ # # ]: 0 : list_del(&hook->list);
709 [ # # ]: 0 : if (lock)
710 : 0 : mutex_unlock(&hook_mutex);
711 : 0 : pr_info("extension unregistered: %s\n", hook->name);
712 : 0 : }
713 : :
714 : 0 : void battery_hook_unregister(struct acpi_battery_hook *hook)
715 : : {
716 : 0 : __battery_hook_unregister(hook, 1);
717 : 0 : }
718 : : EXPORT_SYMBOL_GPL(battery_hook_unregister);
719 : :
720 : 0 : void battery_hook_register(struct acpi_battery_hook *hook)
721 : : {
722 : 0 : struct acpi_battery *battery;
723 : :
724 : 0 : mutex_lock(&hook_mutex);
725 : 0 : INIT_LIST_HEAD(&hook->list);
726 : 0 : list_add(&hook->list, &battery_hook_list);
727 : : /*
728 : : * Now that the driver is registered, we need
729 : : * to notify the hook that a battery is available
730 : : * for each battery, so that the driver may add
731 : : * its attributes.
732 : : */
733 [ # # ]: 0 : list_for_each_entry(battery, &acpi_battery_list, list) {
734 [ # # ]: 0 : if (hook->add_battery(battery->bat)) {
735 : : /*
736 : : * If a add-battery returns non-zero,
737 : : * the registration of the extension has failed,
738 : : * and we will not add it to the list of loaded
739 : : * hooks.
740 : : */
741 : 0 : pr_err("extension failed to load: %s", hook->name);
742 : 0 : __battery_hook_unregister(hook, 0);
743 : 0 : goto end;
744 : : }
745 : : }
746 : 0 : pr_info("new extension: %s\n", hook->name);
747 : 0 : end:
748 : 0 : mutex_unlock(&hook_mutex);
749 : 0 : }
750 : : EXPORT_SYMBOL_GPL(battery_hook_register);
751 : :
752 : : /*
753 : : * This function gets called right after the battery sysfs
754 : : * attributes have been added, so that the drivers that
755 : : * define custom sysfs attributes can add their own.
756 : : */
757 : 0 : static void battery_hook_add_battery(struct acpi_battery *battery)
758 : : {
759 : 0 : struct acpi_battery_hook *hook_node, *tmp;
760 : :
761 : 0 : mutex_lock(&hook_mutex);
762 : 0 : INIT_LIST_HEAD(&battery->list);
763 : 0 : list_add(&battery->list, &acpi_battery_list);
764 : : /*
765 : : * Since we added a new battery to the list, we need to
766 : : * iterate over the hooks and call add_battery for each
767 : : * hook that was registered. This usually happens
768 : : * when a battery gets hotplugged or initialized
769 : : * during the battery module initialization.
770 : : */
771 [ # # ]: 0 : list_for_each_entry_safe(hook_node, tmp, &battery_hook_list, list) {
772 [ # # ]: 0 : if (hook_node->add_battery(battery->bat)) {
773 : : /*
774 : : * The notification of the extensions has failed, to
775 : : * prevent further errors we will unload the extension.
776 : : */
777 : 0 : pr_err("error in extension, unloading: %s",
778 : : hook_node->name);
779 : 0 : __battery_hook_unregister(hook_node, 0);
780 : : }
781 : : }
782 : 0 : mutex_unlock(&hook_mutex);
783 : 0 : }
784 : :
785 : 0 : static void battery_hook_remove_battery(struct acpi_battery *battery)
786 : : {
787 : 0 : struct acpi_battery_hook *hook;
788 : :
789 : 0 : mutex_lock(&hook_mutex);
790 : : /*
791 : : * Before removing the hook, we need to remove all
792 : : * custom attributes from the battery.
793 : : */
794 [ # # ]: 0 : list_for_each_entry(hook, &battery_hook_list, list) {
795 : 0 : hook->remove_battery(battery->bat);
796 : : }
797 : : /* Then, just remove the battery from the list */
798 : 0 : list_del(&battery->list);
799 : 0 : mutex_unlock(&hook_mutex);
800 : 0 : }
801 : :
802 : 0 : static void __exit battery_hook_exit(void)
803 : : {
804 : 0 : struct acpi_battery_hook *hook;
805 : 0 : struct acpi_battery_hook *ptr;
806 : : /*
807 : : * At this point, the acpi_bus_unregister_driver()
808 : : * has called remove for all batteries. We just
809 : : * need to remove the hooks.
810 : : */
811 [ # # ]: 0 : list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) {
812 : 0 : __battery_hook_unregister(hook, 1);
813 : : }
814 : 0 : mutex_destroy(&hook_mutex);
815 : 0 : }
816 : :
817 : 0 : static int sysfs_add_battery(struct acpi_battery *battery)
818 : : {
819 : 0 : struct power_supply_config psy_cfg = { .drv_data = battery, };
820 : 0 : bool full_cap_broken = false;
821 : :
822 [ # # ]: 0 : if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
823 [ # # ]: 0 : !ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
824 : 0 : full_cap_broken = true;
825 : :
826 [ # # ]: 0 : if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
827 [ # # ]: 0 : if (full_cap_broken) {
828 : 0 : battery->bat_desc.properties =
829 : : charge_battery_full_cap_broken_props;
830 : 0 : battery->bat_desc.num_properties =
831 : : ARRAY_SIZE(charge_battery_full_cap_broken_props);
832 : : } else {
833 : 0 : battery->bat_desc.properties = charge_battery_props;
834 : 0 : battery->bat_desc.num_properties =
835 : : ARRAY_SIZE(charge_battery_props);
836 : : }
837 : : } else {
838 [ # # ]: 0 : if (full_cap_broken) {
839 : 0 : battery->bat_desc.properties =
840 : : energy_battery_full_cap_broken_props;
841 : 0 : battery->bat_desc.num_properties =
842 : : ARRAY_SIZE(energy_battery_full_cap_broken_props);
843 : : } else {
844 : 0 : battery->bat_desc.properties = energy_battery_props;
845 : 0 : battery->bat_desc.num_properties =
846 : : ARRAY_SIZE(energy_battery_props);
847 : : }
848 : : }
849 : :
850 : 0 : battery->bat_desc.name = acpi_device_bid(battery->device);
851 : 0 : battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
852 : 0 : battery->bat_desc.get_property = acpi_battery_get_property;
853 : :
854 : 0 : battery->bat = power_supply_register_no_ws(&battery->device->dev,
855 : 0 : &battery->bat_desc, &psy_cfg);
856 : :
857 [ # # ]: 0 : if (IS_ERR(battery->bat)) {
858 : 0 : int result = PTR_ERR(battery->bat);
859 : :
860 : 0 : battery->bat = NULL;
861 : 0 : return result;
862 : : }
863 : 0 : battery_hook_add_battery(battery);
864 : 0 : return device_create_file(&battery->bat->dev, &alarm_attr);
865 : : }
866 : :
867 : 0 : static void sysfs_remove_battery(struct acpi_battery *battery)
868 : : {
869 : 0 : mutex_lock(&battery->sysfs_lock);
870 [ # # ]: 0 : if (!battery->bat) {
871 : 0 : mutex_unlock(&battery->sysfs_lock);
872 : 0 : return;
873 : : }
874 : 0 : battery_hook_remove_battery(battery);
875 : 0 : device_remove_file(&battery->bat->dev, &alarm_attr);
876 : 0 : power_supply_unregister(battery->bat);
877 : 0 : battery->bat = NULL;
878 : 0 : mutex_unlock(&battery->sysfs_lock);
879 : : }
880 : :
881 : 0 : static void find_battery(const struct dmi_header *dm, void *private)
882 : : {
883 : 0 : struct acpi_battery *battery = (struct acpi_battery *)private;
884 : : /* Note: the hardcoded offsets below have been extracted from
885 : : the source code of dmidecode. */
886 [ # # # # ]: 0 : if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
887 : 0 : const u8 *dmi_data = (const u8 *)(dm + 1);
888 [ # # ]: 0 : int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
889 [ # # ]: 0 : if (dm->length >= 18)
890 : 0 : dmi_capacity *= dmi_data[17];
891 [ # # ]: 0 : if (battery->design_capacity * battery->design_voltage / 1000
892 : 0 : != dmi_capacity &&
893 [ # # ]: 0 : battery->design_capacity * 10 == dmi_capacity)
894 : 0 : set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
895 : 0 : &battery->flags);
896 : : }
897 : 0 : }
898 : :
899 : : /*
900 : : * According to the ACPI spec, some kinds of primary batteries can
901 : : * report percentage battery remaining capacity directly to OS.
902 : : * In this case, it reports the Last Full Charged Capacity == 100
903 : : * and BatteryPresentRate == 0xFFFFFFFF.
904 : : *
905 : : * Now we found some battery reports percentage remaining capacity
906 : : * even if it's rechargeable.
907 : : * https://bugzilla.kernel.org/show_bug.cgi?id=15979
908 : : *
909 : : * Handle this correctly so that they won't break userspace.
910 : : */
911 : 0 : static void acpi_battery_quirks(struct acpi_battery *battery)
912 : : {
913 [ # # ]: 0 : if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
914 : : return;
915 : :
916 [ # # ]: 0 : if (battery->full_charge_capacity == 100 &&
917 [ # # ]: 0 : battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
918 [ # # # # ]: 0 : battery->capacity_now >= 0 && battery->capacity_now <= 100) {
919 : 0 : set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
920 : 0 : battery->full_charge_capacity = battery->design_capacity;
921 : 0 : battery->capacity_now = (battery->capacity_now *
922 : 0 : battery->full_charge_capacity) / 100;
923 : : }
924 : :
925 [ # # ]: 0 : if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
926 : : return;
927 : :
928 [ # # # # ]: 0 : if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
929 : 0 : const char *s;
930 : 0 : s = dmi_get_system_info(DMI_PRODUCT_VERSION);
931 [ # # # # ]: 0 : if (s && !strncasecmp(s, "ThinkPad", 8)) {
932 : 0 : dmi_walk(find_battery, battery);
933 [ # # ]: 0 : if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
934 : 0 : &battery->flags) &&
935 [ # # ]: 0 : battery->design_voltage) {
936 : 0 : battery->design_capacity =
937 : 0 : battery->design_capacity *
938 : 0 : 10000 / battery->design_voltage;
939 : 0 : battery->full_charge_capacity =
940 : 0 : battery->full_charge_capacity *
941 : 0 : 10000 / battery->design_voltage;
942 : 0 : battery->design_capacity_warning =
943 : 0 : battery->design_capacity_warning *
944 : 0 : 10000 / battery->design_voltage;
945 : 0 : battery->capacity_now = battery->capacity_now *
946 : 0 : 10000 / battery->design_voltage;
947 : : }
948 : : }
949 : : }
950 : :
951 [ # # ]: 0 : if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags))
952 : : return;
953 : :
954 [ # # # # ]: 0 : if (acpi_battery_is_degraded(battery) &&
955 [ # # ]: 0 : battery->capacity_now > battery->full_charge_capacity) {
956 : 0 : set_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags);
957 : 0 : battery->capacity_now = battery->full_charge_capacity;
958 : : }
959 : : }
960 : :
961 : 0 : static int acpi_battery_update(struct acpi_battery *battery, bool resume)
962 : : {
963 : 0 : int result = acpi_battery_get_status(battery);
964 : :
965 [ # # ]: 0 : if (result)
966 : : return result;
967 : :
968 [ # # ]: 0 : if (!acpi_battery_present(battery)) {
969 : 0 : sysfs_remove_battery(battery);
970 : 0 : battery->update_time = 0;
971 : 0 : return 0;
972 : : }
973 : :
974 [ # # ]: 0 : if (resume)
975 : : return 0;
976 : :
977 [ # # ]: 0 : if (!battery->update_time) {
978 : 0 : result = acpi_battery_get_info(battery);
979 [ # # ]: 0 : if (result)
980 : : return result;
981 : 0 : acpi_battery_init_alarm(battery);
982 : : }
983 : :
984 : 0 : result = acpi_battery_get_state(battery);
985 [ # # ]: 0 : if (result)
986 : : return result;
987 : 0 : acpi_battery_quirks(battery);
988 : :
989 [ # # ]: 0 : if (!battery->bat) {
990 : 0 : result = sysfs_add_battery(battery);
991 [ # # ]: 0 : if (result)
992 : : return result;
993 : : }
994 : :
995 : : /*
996 : : * Wakeup the system if battery is critical low
997 : : * or lower than the alarm level
998 : : */
999 [ # # # # ]: 0 : if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
1000 : 0 : (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
1001 [ # # ]: 0 : (battery->capacity_now <= battery->alarm)))
1002 : 0 : acpi_pm_wakeup_event(&battery->device->dev);
1003 : :
1004 : : return result;
1005 : : }
1006 : :
1007 : 0 : static void acpi_battery_refresh(struct acpi_battery *battery)
1008 : : {
1009 : 0 : int power_unit;
1010 : :
1011 [ # # ]: 0 : if (!battery->bat)
1012 : : return;
1013 : :
1014 : 0 : power_unit = battery->power_unit;
1015 : :
1016 : 0 : acpi_battery_get_info(battery);
1017 : :
1018 [ # # ]: 0 : if (power_unit == battery->power_unit)
1019 : : return;
1020 : :
1021 : : /* The battery has changed its reporting units. */
1022 : 0 : sysfs_remove_battery(battery);
1023 : 0 : sysfs_add_battery(battery);
1024 : : }
1025 : :
1026 : : /* --------------------------------------------------------------------------
1027 : : FS Interface (/proc)
1028 : : -------------------------------------------------------------------------- */
1029 : :
1030 : : #ifdef CONFIG_ACPI_PROCFS_POWER
1031 : : static struct proc_dir_entry *acpi_battery_dir;
1032 : :
1033 : : static const char *acpi_battery_units(const struct acpi_battery *battery)
1034 : : {
1035 : : return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
1036 : : "mA" : "mW";
1037 : : }
1038 : :
1039 : : static int acpi_battery_info_proc_show(struct seq_file *seq, void *offset)
1040 : : {
1041 : : struct acpi_battery *battery = seq->private;
1042 : : int result = acpi_battery_update(battery, false);
1043 : :
1044 : : if (result)
1045 : : goto end;
1046 : :
1047 : : seq_printf(seq, "present: %s\n",
1048 : : acpi_battery_present(battery) ? "yes" : "no");
1049 : : if (!acpi_battery_present(battery))
1050 : : goto end;
1051 : : if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1052 : : seq_printf(seq, "design capacity: unknown\n");
1053 : : else
1054 : : seq_printf(seq, "design capacity: %d %sh\n",
1055 : : battery->design_capacity,
1056 : : acpi_battery_units(battery));
1057 : :
1058 : : if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1059 : : seq_printf(seq, "last full capacity: unknown\n");
1060 : : else
1061 : : seq_printf(seq, "last full capacity: %d %sh\n",
1062 : : battery->full_charge_capacity,
1063 : : acpi_battery_units(battery));
1064 : :
1065 : : seq_printf(seq, "battery technology: %srechargeable\n",
1066 : : battery->technology ? "" : "non-");
1067 : :
1068 : : if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
1069 : : seq_printf(seq, "design voltage: unknown\n");
1070 : : else
1071 : : seq_printf(seq, "design voltage: %d mV\n",
1072 : : battery->design_voltage);
1073 : : seq_printf(seq, "design capacity warning: %d %sh\n",
1074 : : battery->design_capacity_warning,
1075 : : acpi_battery_units(battery));
1076 : : seq_printf(seq, "design capacity low: %d %sh\n",
1077 : : battery->design_capacity_low,
1078 : : acpi_battery_units(battery));
1079 : : seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
1080 : : seq_printf(seq, "capacity granularity 1: %d %sh\n",
1081 : : battery->capacity_granularity_1,
1082 : : acpi_battery_units(battery));
1083 : : seq_printf(seq, "capacity granularity 2: %d %sh\n",
1084 : : battery->capacity_granularity_2,
1085 : : acpi_battery_units(battery));
1086 : : seq_printf(seq, "model number: %s\n", battery->model_number);
1087 : : seq_printf(seq, "serial number: %s\n", battery->serial_number);
1088 : : seq_printf(seq, "battery type: %s\n", battery->type);
1089 : : seq_printf(seq, "OEM info: %s\n", battery->oem_info);
1090 : : end:
1091 : : if (result)
1092 : : seq_printf(seq, "ERROR: Unable to read battery info\n");
1093 : : return result;
1094 : : }
1095 : :
1096 : : static int acpi_battery_state_proc_show(struct seq_file *seq, void *offset)
1097 : : {
1098 : : struct acpi_battery *battery = seq->private;
1099 : : int result = acpi_battery_update(battery, false);
1100 : :
1101 : : if (result)
1102 : : goto end;
1103 : :
1104 : : seq_printf(seq, "present: %s\n",
1105 : : acpi_battery_present(battery) ? "yes" : "no");
1106 : : if (!acpi_battery_present(battery))
1107 : : goto end;
1108 : :
1109 : : seq_printf(seq, "capacity state: %s\n",
1110 : : (battery->state & 0x04) ? "critical" : "ok");
1111 : : if ((battery->state & 0x01) && (battery->state & 0x02))
1112 : : seq_printf(seq,
1113 : : "charging state: charging/discharging\n");
1114 : : else if (battery->state & 0x01)
1115 : : seq_printf(seq, "charging state: discharging\n");
1116 : : else if (battery->state & 0x02)
1117 : : seq_printf(seq, "charging state: charging\n");
1118 : : else
1119 : : seq_printf(seq, "charging state: charged\n");
1120 : :
1121 : : if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
1122 : : seq_printf(seq, "present rate: unknown\n");
1123 : : else
1124 : : seq_printf(seq, "present rate: %d %s\n",
1125 : : battery->rate_now, acpi_battery_units(battery));
1126 : :
1127 : : if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
1128 : : seq_printf(seq, "remaining capacity: unknown\n");
1129 : : else
1130 : : seq_printf(seq, "remaining capacity: %d %sh\n",
1131 : : battery->capacity_now, acpi_battery_units(battery));
1132 : : if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
1133 : : seq_printf(seq, "present voltage: unknown\n");
1134 : : else
1135 : : seq_printf(seq, "present voltage: %d mV\n",
1136 : : battery->voltage_now);
1137 : : end:
1138 : : if (result)
1139 : : seq_printf(seq, "ERROR: Unable to read battery state\n");
1140 : :
1141 : : return result;
1142 : : }
1143 : :
1144 : : static int acpi_battery_alarm_proc_show(struct seq_file *seq, void *offset)
1145 : : {
1146 : : struct acpi_battery *battery = seq->private;
1147 : : int result = acpi_battery_update(battery, false);
1148 : :
1149 : : if (result)
1150 : : goto end;
1151 : :
1152 : : if (!acpi_battery_present(battery)) {
1153 : : seq_printf(seq, "present: no\n");
1154 : : goto end;
1155 : : }
1156 : : seq_printf(seq, "alarm: ");
1157 : : if (battery->alarm) {
1158 : : seq_printf(seq, "%u %sh\n", battery->alarm,
1159 : : acpi_battery_units(battery));
1160 : : } else {
1161 : : seq_printf(seq, "unsupported\n");
1162 : : }
1163 : : end:
1164 : : if (result)
1165 : : seq_printf(seq, "ERROR: Unable to read battery alarm\n");
1166 : : return result;
1167 : : }
1168 : :
1169 : : static ssize_t acpi_battery_write_alarm(struct file *file,
1170 : : const char __user * buffer,
1171 : : size_t count, loff_t * ppos)
1172 : : {
1173 : : int result = 0;
1174 : : char alarm_string[12] = { '\0' };
1175 : : struct seq_file *m = file->private_data;
1176 : : struct acpi_battery *battery = m->private;
1177 : :
1178 : : if (!battery || (count > sizeof(alarm_string) - 1))
1179 : : return -EINVAL;
1180 : : if (!acpi_battery_present(battery)) {
1181 : : result = -ENODEV;
1182 : : goto end;
1183 : : }
1184 : : if (copy_from_user(alarm_string, buffer, count)) {
1185 : : result = -EFAULT;
1186 : : goto end;
1187 : : }
1188 : : alarm_string[count] = '\0';
1189 : : if (kstrtoint(alarm_string, 0, &battery->alarm)) {
1190 : : result = -EINVAL;
1191 : : goto end;
1192 : : }
1193 : : result = acpi_battery_set_alarm(battery);
1194 : : end:
1195 : : if (result)
1196 : : return result;
1197 : : return count;
1198 : : }
1199 : :
1200 : : static int acpi_battery_alarm_proc_open(struct inode *inode, struct file *file)
1201 : : {
1202 : : return single_open(file, acpi_battery_alarm_proc_show, PDE_DATA(inode));
1203 : : }
1204 : :
1205 : : static const struct proc_ops acpi_battery_alarm_proc_ops = {
1206 : : .proc_open = acpi_battery_alarm_proc_open,
1207 : : .proc_read = seq_read,
1208 : : .proc_write = acpi_battery_write_alarm,
1209 : : .proc_lseek = seq_lseek,
1210 : : .proc_release = single_release,
1211 : : };
1212 : :
1213 : : static int acpi_battery_add_fs(struct acpi_device *device)
1214 : : {
1215 : : pr_warn(PREFIX "Deprecated procfs I/F for battery is loaded, please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
1216 : : if (!acpi_device_dir(device)) {
1217 : : acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1218 : : acpi_battery_dir);
1219 : : if (!acpi_device_dir(device))
1220 : : return -ENODEV;
1221 : : }
1222 : :
1223 : : if (!proc_create_single_data("info", S_IRUGO, acpi_device_dir(device),
1224 : : acpi_battery_info_proc_show, acpi_driver_data(device)))
1225 : : return -ENODEV;
1226 : : if (!proc_create_single_data("state", S_IRUGO, acpi_device_dir(device),
1227 : : acpi_battery_state_proc_show, acpi_driver_data(device)))
1228 : : return -ENODEV;
1229 : : if (!proc_create_data("alarm", S_IFREG | S_IRUGO | S_IWUSR,
1230 : : acpi_device_dir(device), &acpi_battery_alarm_proc_ops,
1231 : : acpi_driver_data(device)))
1232 : : return -ENODEV;
1233 : : return 0;
1234 : : }
1235 : :
1236 : : static void acpi_battery_remove_fs(struct acpi_device *device)
1237 : : {
1238 : : if (!acpi_device_dir(device))
1239 : : return;
1240 : : remove_proc_subtree(acpi_device_bid(device), acpi_battery_dir);
1241 : : acpi_device_dir(device) = NULL;
1242 : : }
1243 : :
1244 : : #endif
1245 : :
1246 : : /* --------------------------------------------------------------------------
1247 : : Driver Interface
1248 : : -------------------------------------------------------------------------- */
1249 : :
1250 : 0 : static void acpi_battery_notify(struct acpi_device *device, u32 event)
1251 : : {
1252 [ # # ]: 0 : struct acpi_battery *battery = acpi_driver_data(device);
1253 : 0 : struct power_supply *old;
1254 : :
1255 [ # # ]: 0 : if (!battery)
1256 : : return;
1257 : 0 : old = battery->bat;
1258 : : /*
1259 : : * On Acer Aspire V5-573G notifications are sometimes triggered too
1260 : : * early. For example, when AC is unplugged and notification is
1261 : : * triggered, battery state is still reported as "Full", and changes to
1262 : : * "Discharging" only after short delay, without any notification.
1263 : : */
1264 [ # # ]: 0 : if (battery_notification_delay_ms > 0)
1265 : 0 : msleep(battery_notification_delay_ms);
1266 [ # # ]: 0 : if (event == ACPI_BATTERY_NOTIFY_INFO)
1267 : 0 : acpi_battery_refresh(battery);
1268 : 0 : acpi_battery_update(battery, false);
1269 [ # # ]: 0 : acpi_bus_generate_netlink_event(device->pnp.device_class,
1270 : : dev_name(&device->dev), event,
1271 : : acpi_battery_present(battery));
1272 : 0 : acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
1273 : : /* acpi_battery_update could remove power_supply object */
1274 [ # # # # ]: 0 : if (old && battery->bat)
1275 : 0 : power_supply_changed(battery->bat);
1276 : : }
1277 : :
1278 : 0 : static int battery_notify(struct notifier_block *nb,
1279 : : unsigned long mode, void *_unused)
1280 : : {
1281 : 0 : struct acpi_battery *battery = container_of(nb, struct acpi_battery,
1282 : : pm_nb);
1283 : 0 : int result;
1284 : :
1285 [ # # ]: 0 : switch (mode) {
1286 : 0 : case PM_POST_HIBERNATION:
1287 : : case PM_POST_SUSPEND:
1288 [ # # ]: 0 : if (!acpi_battery_present(battery))
1289 : : return 0;
1290 : :
1291 [ # # ]: 0 : if (battery->bat) {
1292 : 0 : acpi_battery_refresh(battery);
1293 : : } else {
1294 : 0 : result = acpi_battery_get_info(battery);
1295 [ # # ]: 0 : if (result)
1296 : : return result;
1297 : :
1298 : 0 : result = sysfs_add_battery(battery);
1299 [ # # ]: 0 : if (result)
1300 : : return result;
1301 : : }
1302 : :
1303 : 0 : acpi_battery_init_alarm(battery);
1304 : 0 : acpi_battery_get_state(battery);
1305 : 0 : break;
1306 : : }
1307 : :
1308 : : return 0;
1309 : : }
1310 : :
1311 : : static int __init
1312 : 0 : battery_bix_broken_package_quirk(const struct dmi_system_id *d)
1313 : : {
1314 : 0 : battery_bix_broken_package = 1;
1315 : 0 : return 0;
1316 : : }
1317 : :
1318 : : static int __init
1319 : 0 : battery_notification_delay_quirk(const struct dmi_system_id *d)
1320 : : {
1321 : 0 : battery_notification_delay_ms = 1000;
1322 : 0 : return 0;
1323 : : }
1324 : :
1325 : : static int __init
1326 : 0 : battery_ac_is_broken_quirk(const struct dmi_system_id *d)
1327 : : {
1328 : 0 : battery_ac_is_broken = 1;
1329 : 0 : return 0;
1330 : : }
1331 : :
1332 : : static int __init
1333 : 0 : battery_do_not_check_pmic_quirk(const struct dmi_system_id *d)
1334 : : {
1335 : 0 : battery_check_pmic = 0;
1336 : 0 : return 0;
1337 : : }
1338 : :
1339 : : static const struct dmi_system_id bat_dmi_table[] __initconst = {
1340 : : {
1341 : : /* NEC LZ750/LS */
1342 : : .callback = battery_bix_broken_package_quirk,
1343 : : .matches = {
1344 : : DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
1345 : : DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
1346 : : },
1347 : : },
1348 : : {
1349 : : /* Acer Aspire V5-573G */
1350 : : .callback = battery_notification_delay_quirk,
1351 : : .matches = {
1352 : : DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1353 : : DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
1354 : : },
1355 : : },
1356 : : {
1357 : : /* Point of View mobii wintab p800w */
1358 : : .callback = battery_ac_is_broken_quirk,
1359 : : .matches = {
1360 : : DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
1361 : : DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
1362 : : DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
1363 : : /* Above matches are too generic, add bios-date match */
1364 : : DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
1365 : : },
1366 : : },
1367 : : {
1368 : : /* ECS EF20EA */
1369 : : .callback = battery_do_not_check_pmic_quirk,
1370 : : .matches = {
1371 : : DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
1372 : : },
1373 : : },
1374 : : {
1375 : : /* Lenovo Ideapad Miix 320 */
1376 : : .callback = battery_do_not_check_pmic_quirk,
1377 : : .matches = {
1378 : : DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1379 : : DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80XF"),
1380 : : DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
1381 : : },
1382 : : },
1383 : : {},
1384 : : };
1385 : :
1386 : : /*
1387 : : * Some machines'(E,G Lenovo Z480) ECs are not stable
1388 : : * during boot up and this causes battery driver fails to be
1389 : : * probed due to failure of getting battery information
1390 : : * from EC sometimes. After several retries, the operation
1391 : : * may work. So add retry code here and 20ms sleep between
1392 : : * every retries.
1393 : : */
1394 : 0 : static int acpi_battery_update_retry(struct acpi_battery *battery)
1395 : : {
1396 : 0 : int retry, ret;
1397 : :
1398 [ # # ]: 0 : for (retry = 5; retry; retry--) {
1399 : 0 : ret = acpi_battery_update(battery, false);
1400 [ # # ]: 0 : if (!ret)
1401 : : break;
1402 : :
1403 : 0 : msleep(20);
1404 : : }
1405 : 0 : return ret;
1406 : : }
1407 : :
1408 : 0 : static int acpi_battery_add(struct acpi_device *device)
1409 : : {
1410 : 0 : int result = 0;
1411 : 0 : struct acpi_battery *battery = NULL;
1412 : :
1413 [ # # ]: 0 : if (!device)
1414 : : return -EINVAL;
1415 : :
1416 [ # # ]: 0 : if (device->dep_unmet)
1417 : : return -EPROBE_DEFER;
1418 : :
1419 : 0 : battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
1420 [ # # ]: 0 : if (!battery)
1421 : : return -ENOMEM;
1422 : 0 : battery->device = device;
1423 : 0 : strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1424 : 0 : strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
1425 : 0 : device->driver_data = battery;
1426 : 0 : mutex_init(&battery->lock);
1427 : 0 : mutex_init(&battery->sysfs_lock);
1428 [ # # ]: 0 : if (acpi_has_method(battery->device->handle, "_BIX"))
1429 : 0 : set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
1430 : :
1431 : 0 : result = acpi_battery_update_retry(battery);
1432 [ # # ]: 0 : if (result)
1433 : 0 : goto fail;
1434 : :
1435 : : #ifdef CONFIG_ACPI_PROCFS_POWER
1436 : : result = acpi_battery_add_fs(device);
1437 : : if (result) {
1438 : : acpi_battery_remove_fs(device);
1439 : : goto fail;
1440 : : }
1441 : : #endif
1442 : :
1443 [ # # ]: 0 : pr_info(PREFIX "%s Slot [%s] (battery %s)\n",
1444 : : ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
1445 : : device->status.battery_present ? "present" : "absent");
1446 : :
1447 : 0 : battery->pm_nb.notifier_call = battery_notify;
1448 : 0 : register_pm_notifier(&battery->pm_nb);
1449 : :
1450 : 0 : device_init_wakeup(&device->dev, 1);
1451 : :
1452 : 0 : return result;
1453 : :
1454 : : fail:
1455 : 0 : sysfs_remove_battery(battery);
1456 : 0 : mutex_destroy(&battery->lock);
1457 : 0 : mutex_destroy(&battery->sysfs_lock);
1458 : 0 : kfree(battery);
1459 : 0 : return result;
1460 : : }
1461 : :
1462 : 0 : static int acpi_battery_remove(struct acpi_device *device)
1463 : : {
1464 : 0 : struct acpi_battery *battery = NULL;
1465 : :
1466 [ # # # # ]: 0 : if (!device || !acpi_driver_data(device))
1467 : : return -EINVAL;
1468 : 0 : device_init_wakeup(&device->dev, 0);
1469 : 0 : battery = acpi_driver_data(device);
1470 : 0 : unregister_pm_notifier(&battery->pm_nb);
1471 : : #ifdef CONFIG_ACPI_PROCFS_POWER
1472 : : acpi_battery_remove_fs(device);
1473 : : #endif
1474 : 0 : sysfs_remove_battery(battery);
1475 : 0 : mutex_destroy(&battery->lock);
1476 : 0 : mutex_destroy(&battery->sysfs_lock);
1477 : 0 : kfree(battery);
1478 : 0 : return 0;
1479 : : }
1480 : :
1481 : : #ifdef CONFIG_PM_SLEEP
1482 : : /* this is needed to learn about changes made in suspended state */
1483 : 0 : static int acpi_battery_resume(struct device *dev)
1484 : : {
1485 : 0 : struct acpi_battery *battery;
1486 : :
1487 [ # # ]: 0 : if (!dev)
1488 : : return -EINVAL;
1489 : :
1490 [ # # ]: 0 : battery = acpi_driver_data(to_acpi_device(dev));
1491 [ # # ]: 0 : if (!battery)
1492 : : return -EINVAL;
1493 : :
1494 : 0 : battery->update_time = 0;
1495 : 0 : acpi_battery_update(battery, true);
1496 : 0 : return 0;
1497 : : }
1498 : : #else
1499 : : #define acpi_battery_resume NULL
1500 : : #endif
1501 : :
1502 : : static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
1503 : :
1504 : : static struct acpi_driver acpi_battery_driver = {
1505 : : .name = "battery",
1506 : : .class = ACPI_BATTERY_CLASS,
1507 : : .ids = battery_device_ids,
1508 : : .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1509 : : .ops = {
1510 : : .add = acpi_battery_add,
1511 : : .remove = acpi_battery_remove,
1512 : : .notify = acpi_battery_notify,
1513 : : },
1514 : : .drv.pm = &acpi_battery_pm,
1515 : : };
1516 : :
1517 : 78 : static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
1518 : : {
1519 : 78 : unsigned int i;
1520 : 78 : int result;
1521 : :
1522 : 78 : dmi_check_system(bat_dmi_table);
1523 : :
1524 [ + - ]: 78 : if (battery_check_pmic) {
1525 [ + + ]: 156 : for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
1526 [ - + ]: 78 : if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
1527 : 0 : pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
1528 : : ": found native %s PMIC, not loading\n",
1529 : : acpi_battery_blacklist[i]);
1530 : 0 : return;
1531 : : }
1532 : : }
1533 : :
1534 : : #ifdef CONFIG_ACPI_PROCFS_POWER
1535 : : acpi_battery_dir = acpi_lock_battery_dir();
1536 : : if (!acpi_battery_dir)
1537 : : return;
1538 : : #endif
1539 : 78 : result = acpi_bus_register_driver(&acpi_battery_driver);
1540 : : #ifdef CONFIG_ACPI_PROCFS_POWER
1541 : : if (result < 0)
1542 : : acpi_unlock_battery_dir(acpi_battery_dir);
1543 : : #endif
1544 : 78 : battery_driver_registered = (result == 0);
1545 : : }
1546 : :
1547 : 78 : static int __init acpi_battery_init(void)
1548 : : {
1549 [ + - ]: 78 : if (acpi_disabled)
1550 : : return -ENODEV;
1551 : :
1552 : 78 : async_cookie = async_schedule(acpi_battery_init_async, NULL);
1553 : 78 : return 0;
1554 : : }
1555 : :
1556 : 0 : static void __exit acpi_battery_exit(void)
1557 : : {
1558 : 0 : async_synchronize_cookie(async_cookie + 1);
1559 [ # # ]: 0 : if (battery_driver_registered) {
1560 : 0 : acpi_bus_unregister_driver(&acpi_battery_driver);
1561 : 0 : battery_hook_exit();
1562 : : }
1563 : : #ifdef CONFIG_ACPI_PROCFS_POWER
1564 : : if (acpi_battery_dir)
1565 : : acpi_unlock_battery_dir(acpi_battery_dir);
1566 : : #endif
1567 : 0 : }
1568 : :
1569 : : module_init(acpi_battery_init);
1570 : : module_exit(acpi_battery_exit);
|