linux/drivers/acpi/battery.c
<<
>>
Prefs
   1/*
   2 *  battery.c - ACPI Battery Driver (Revision: 2.0)
   3 *
   4 *  Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
   5 *  Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
   6 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
   7 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
   8 *
   9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  10 *
  11 *  This program is free software; you can redistribute it and/or modify
  12 *  it under the terms of the GNU General Public License as published by
  13 *  the Free Software Foundation; either version 2 of the License, or (at
  14 *  your option) any later version.
  15 *
  16 *  This program is distributed in the hope that it will be useful, but
  17 *  WITHOUT ANY WARRANTY; without even the implied warranty of
  18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19 *  General Public License for more details.
  20 *
  21 *  You should have received a copy of the GNU General Public License along
  22 *  with this program; if not, write to the Free Software Foundation, Inc.,
  23 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  24 *
  25 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  26 */
  27
  28#include <linux/kernel.h>
  29#include <linux/module.h>
  30#include <linux/init.h>
  31#include <linux/types.h>
  32#include <linux/jiffies.h>
  33#include <linux/async.h>
  34#include <linux/dmi.h>
  35#include <linux/slab.h>
  36#include <linux/suspend.h>
  37#include <asm/unaligned.h>
  38
  39#ifdef CONFIG_ACPI_PROCFS_POWER
  40#include <linux/proc_fs.h>
  41#include <linux/seq_file.h>
  42#include <asm/uaccess.h>
  43#endif
  44
  45#include <acpi/acpi_bus.h>
  46#include <acpi/acpi_drivers.h>
  47#include <linux/power_supply.h>
  48
  49#define PREFIX "ACPI: "
  50
  51#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
  52
  53#define ACPI_BATTERY_CLASS              "battery"
  54#define ACPI_BATTERY_DEVICE_NAME        "Battery"
  55#define ACPI_BATTERY_NOTIFY_STATUS      0x80
  56#define ACPI_BATTERY_NOTIFY_INFO        0x81
  57#define ACPI_BATTERY_NOTIFY_THRESHOLD   0x82
  58
  59/* Battery power unit: 0 means mW, 1 means mA */
  60#define ACPI_BATTERY_POWER_UNIT_MA      1
  61
  62#define _COMPONENT              ACPI_BATTERY_COMPONENT
  63
  64ACPI_MODULE_NAME("battery");
  65
  66MODULE_AUTHOR("Paul Diefenbaugh");
  67MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
  68MODULE_DESCRIPTION("ACPI Battery Driver");
  69MODULE_LICENSE("GPL");
  70
  71static unsigned int cache_time = 1000;
  72module_param(cache_time, uint, 0644);
  73MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
  74
  75#ifdef CONFIG_ACPI_PROCFS_POWER
  76extern struct proc_dir_entry *acpi_lock_battery_dir(void);
  77extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
  78
  79enum acpi_battery_files {
  80        info_tag = 0,
  81        state_tag,
  82        alarm_tag,
  83        ACPI_BATTERY_NUMFILES,
  84};
  85
  86#endif
  87
  88static const struct acpi_device_id battery_device_ids[] = {
  89        {"PNP0C0A", 0},
  90        {"", 0},
  91};
  92
  93MODULE_DEVICE_TABLE(acpi, battery_device_ids);
  94
  95enum {
  96        ACPI_BATTERY_ALARM_PRESENT,
  97        ACPI_BATTERY_XINFO_PRESENT,
  98        ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
  99        /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
 100           switches between mWh and mAh depending on whether the system
 101           is running on battery or not.  When mAh is the unit, most
 102           reported values are incorrect and need to be adjusted by
 103           10000/design_voltage.  Verified on x201, t410, t410s, and x220.
 104           Pre-2010 and 2012 models appear to always report in mWh and
 105           are thus unaffected (tested with t42, t61, t500, x200, x300,
 106           and x230).  Also, in mid-2012 Lenovo issued a BIOS update for
 107           the 2011 models that fixes the issue (tested on x220 with a
 108           post-1.29 BIOS), but as of Nov. 2012, no such update is
 109           available for the 2010 models.  */
 110        ACPI_BATTERY_QUIRK_THINKPAD_MAH,
 111};
 112
 113struct acpi_battery {
 114        struct mutex lock;
 115        struct mutex sysfs_lock;
 116        struct power_supply bat;
 117        struct acpi_device *device;
 118        struct notifier_block pm_nb;
 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) container_of(x, struct acpi_battery, bat)
 149
 150static inline int acpi_battery_present(struct acpi_battery *battery)
 151{
 152        return battery->device->status.battery_present;
 153}
 154
 155static int acpi_battery_technology(struct acpi_battery *battery)
 156{
 157        if (!strcasecmp("NiCd", battery->type))
 158                return POWER_SUPPLY_TECHNOLOGY_NiCd;
 159        if (!strcasecmp("NiMH", battery->type))
 160                return POWER_SUPPLY_TECHNOLOGY_NiMH;
 161        if (!strcasecmp("LION", battery->type))
 162                return POWER_SUPPLY_TECHNOLOGY_LION;
 163        if (!strncasecmp("LI-ION", battery->type, 6))
 164                return POWER_SUPPLY_TECHNOLOGY_LION;
 165        if (!strcasecmp("LiP", battery->type))
 166                return POWER_SUPPLY_TECHNOLOGY_LIPO;
 167        return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
 168}
 169
 170static int acpi_battery_get_state(struct acpi_battery *battery);
 171
 172static int acpi_battery_is_charged(struct acpi_battery *battery)
 173{
 174        /* either charging or discharging */
 175        if (battery->state != 0)
 176                return 0;
 177
 178        /* battery not reporting charge */
 179        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        if (battery->full_charge_capacity == battery->capacity_now)
 185                return 1;
 186
 187        /* fallback to using design values for broken batteries */
 188        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
 195static int acpi_battery_get_property(struct power_supply *psy,
 196                                     enum power_supply_property psp,
 197                                     union power_supply_propval *val)
 198{
 199        int ret = 0;
 200        struct acpi_battery *battery = to_acpi_battery(psy);
 201
 202        if (acpi_battery_present(battery)) {
 203                /* run battery update only if it is present */
 204                acpi_battery_get_state(battery);
 205        } else if (psp != POWER_SUPPLY_PROP_PRESENT)
 206                return -ENODEV;
 207        switch (psp) {
 208        case POWER_SUPPLY_PROP_STATUS:
 209                if (battery->state & 0x01)
 210                        val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
 211                else if (battery->state & 0x02)
 212                        val->intval = POWER_SUPPLY_STATUS_CHARGING;
 213                else if (acpi_battery_is_charged(battery))
 214                        val->intval = POWER_SUPPLY_STATUS_FULL;
 215                else
 216                        val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
 217                break;
 218        case POWER_SUPPLY_PROP_PRESENT:
 219                val->intval = acpi_battery_present(battery);
 220                break;
 221        case POWER_SUPPLY_PROP_TECHNOLOGY:
 222                val->intval = acpi_battery_technology(battery);
 223                break;
 224        case POWER_SUPPLY_PROP_CYCLE_COUNT:
 225                val->intval = battery->cycle_count;
 226                break;
 227        case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
 228                if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
 229                        ret = -ENODEV;
 230                else
 231                        val->intval = battery->design_voltage * 1000;
 232                break;
 233        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 234                if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
 235                        ret = -ENODEV;
 236                else
 237                        val->intval = battery->voltage_now * 1000;
 238                break;
 239        case POWER_SUPPLY_PROP_CURRENT_NOW:
 240        case POWER_SUPPLY_PROP_POWER_NOW:
 241                if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
 242                        ret = -ENODEV;
 243                else
 244                        val->intval = battery->rate_now * 1000;
 245                break;
 246        case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 247        case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
 248                if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
 249                        ret = -ENODEV;
 250                else
 251                        val->intval = battery->design_capacity * 1000;
 252                break;
 253        case POWER_SUPPLY_PROP_CHARGE_FULL:
 254        case POWER_SUPPLY_PROP_ENERGY_FULL:
 255                if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
 256                        ret = -ENODEV;
 257                else
 258                        val->intval = battery->full_charge_capacity * 1000;
 259                break;
 260        case POWER_SUPPLY_PROP_CHARGE_NOW:
 261        case POWER_SUPPLY_PROP_ENERGY_NOW:
 262                if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
 263                        ret = -ENODEV;
 264                else
 265                        val->intval = battery->capacity_now * 1000;
 266                break;
 267        case POWER_SUPPLY_PROP_CAPACITY:
 268                if (battery->capacity_now && battery->full_charge_capacity)
 269                        val->intval = battery->capacity_now * 100/
 270                                        battery->full_charge_capacity;
 271                else
 272                        val->intval = 0;
 273                break;
 274        case POWER_SUPPLY_PROP_MODEL_NAME:
 275                val->strval = battery->model_number;
 276                break;
 277        case POWER_SUPPLY_PROP_MANUFACTURER:
 278                val->strval = battery->oem_info;
 279                break;
 280        case POWER_SUPPLY_PROP_SERIAL_NUMBER:
 281                val->strval = battery->serial_number;
 282                break;
 283        default:
 284                ret = -EINVAL;
 285        }
 286        return ret;
 287}
 288
 289static enum power_supply_property charge_battery_props[] = {
 290        POWER_SUPPLY_PROP_STATUS,
 291        POWER_SUPPLY_PROP_PRESENT,
 292        POWER_SUPPLY_PROP_TECHNOLOGY,
 293        POWER_SUPPLY_PROP_CYCLE_COUNT,
 294        POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
 295        POWER_SUPPLY_PROP_VOLTAGE_NOW,
 296        POWER_SUPPLY_PROP_CURRENT_NOW,
 297        POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 298        POWER_SUPPLY_PROP_CHARGE_FULL,
 299        POWER_SUPPLY_PROP_CHARGE_NOW,
 300        POWER_SUPPLY_PROP_CAPACITY,
 301        POWER_SUPPLY_PROP_MODEL_NAME,
 302        POWER_SUPPLY_PROP_MANUFACTURER,
 303        POWER_SUPPLY_PROP_SERIAL_NUMBER,
 304};
 305
 306static enum power_supply_property energy_battery_props[] = {
 307        POWER_SUPPLY_PROP_STATUS,
 308        POWER_SUPPLY_PROP_PRESENT,
 309        POWER_SUPPLY_PROP_TECHNOLOGY,
 310        POWER_SUPPLY_PROP_CYCLE_COUNT,
 311        POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
 312        POWER_SUPPLY_PROP_VOLTAGE_NOW,
 313        POWER_SUPPLY_PROP_POWER_NOW,
 314        POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
 315        POWER_SUPPLY_PROP_ENERGY_FULL,
 316        POWER_SUPPLY_PROP_ENERGY_NOW,
 317        POWER_SUPPLY_PROP_CAPACITY,
 318        POWER_SUPPLY_PROP_MODEL_NAME,
 319        POWER_SUPPLY_PROP_MANUFACTURER,
 320        POWER_SUPPLY_PROP_SERIAL_NUMBER,
 321};
 322
 323#ifdef CONFIG_ACPI_PROCFS_POWER
 324inline char *acpi_battery_units(struct acpi_battery *battery)
 325{
 326        return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
 327                "mA" : "mW";
 328}
 329#endif
 330
 331/* --------------------------------------------------------------------------
 332                               Battery Management
 333   -------------------------------------------------------------------------- */
 334struct acpi_offsets {
 335        size_t offset;          /* offset inside struct acpi_sbs_battery */
 336        u8 mode;                /* int or string? */
 337};
 338
 339static struct acpi_offsets state_offsets[] = {
 340        {offsetof(struct acpi_battery, state), 0},
 341        {offsetof(struct acpi_battery, rate_now), 0},
 342        {offsetof(struct acpi_battery, capacity_now), 0},
 343        {offsetof(struct acpi_battery, voltage_now), 0},
 344};
 345
 346static struct acpi_offsets info_offsets[] = {
 347        {offsetof(struct acpi_battery, power_unit), 0},
 348        {offsetof(struct acpi_battery, design_capacity), 0},
 349        {offsetof(struct acpi_battery, full_charge_capacity), 0},
 350        {offsetof(struct acpi_battery, technology), 0},
 351        {offsetof(struct acpi_battery, design_voltage), 0},
 352        {offsetof(struct acpi_battery, design_capacity_warning), 0},
 353        {offsetof(struct acpi_battery, design_capacity_low), 0},
 354        {offsetof(struct acpi_battery, capacity_granularity_1), 0},
 355        {offsetof(struct acpi_battery, capacity_granularity_2), 0},
 356        {offsetof(struct acpi_battery, model_number), 1},
 357        {offsetof(struct acpi_battery, serial_number), 1},
 358        {offsetof(struct acpi_battery, type), 1},
 359        {offsetof(struct acpi_battery, oem_info), 1},
 360};
 361
 362static struct acpi_offsets extended_info_offsets[] = {
 363        {offsetof(struct acpi_battery, revision), 0},
 364        {offsetof(struct acpi_battery, power_unit), 0},
 365        {offsetof(struct acpi_battery, design_capacity), 0},
 366        {offsetof(struct acpi_battery, full_charge_capacity), 0},
 367        {offsetof(struct acpi_battery, technology), 0},
 368        {offsetof(struct acpi_battery, design_voltage), 0},
 369        {offsetof(struct acpi_battery, design_capacity_warning), 0},
 370        {offsetof(struct acpi_battery, design_capacity_low), 0},
 371        {offsetof(struct acpi_battery, cycle_count), 0},
 372        {offsetof(struct acpi_battery, measurement_accuracy), 0},
 373        {offsetof(struct acpi_battery, max_sampling_time), 0},
 374        {offsetof(struct acpi_battery, min_sampling_time), 0},
 375        {offsetof(struct acpi_battery, max_averaging_interval), 0},
 376        {offsetof(struct acpi_battery, min_averaging_interval), 0},
 377        {offsetof(struct acpi_battery, capacity_granularity_1), 0},
 378        {offsetof(struct acpi_battery, capacity_granularity_2), 0},
 379        {offsetof(struct acpi_battery, model_number), 1},
 380        {offsetof(struct acpi_battery, serial_number), 1},
 381        {offsetof(struct acpi_battery, type), 1},
 382        {offsetof(struct acpi_battery, oem_info), 1},
 383};
 384
 385static int extract_package(struct acpi_battery *battery,
 386                           union acpi_object *package,
 387                           struct acpi_offsets *offsets, int num)
 388{
 389        int i;
 390        union acpi_object *element;
 391        if (package->type != ACPI_TYPE_PACKAGE)
 392                return -EFAULT;
 393        for (i = 0; i < num; ++i) {
 394                if (package->package.count <= i)
 395                        return -EFAULT;
 396                element = &package->package.elements[i];
 397                if (offsets[i].mode) {
 398                        u8 *ptr = (u8 *)battery + offsets[i].offset;
 399                        if (element->type == ACPI_TYPE_STRING ||
 400                            element->type == ACPI_TYPE_BUFFER)
 401                                strncpy(ptr, element->string.pointer, 32);
 402                        else if (element->type == ACPI_TYPE_INTEGER) {
 403                                strncpy(ptr, (u8 *)&element->integer.value,
 404                                        sizeof(u64));
 405                                ptr[sizeof(u64)] = 0;
 406                        } else
 407                                *ptr = 0; /* don't have value */
 408                } else {
 409                        int *x = (int *)((u8 *)battery + offsets[i].offset);
 410                        *x = (element->type == ACPI_TYPE_INTEGER) ?
 411                                element->integer.value : -1;
 412                }
 413        }
 414        return 0;
 415}
 416
 417static int acpi_battery_get_status(struct acpi_battery *battery)
 418{
 419        if (acpi_bus_get_status(battery->device)) {
 420                ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
 421                return -ENODEV;
 422        }
 423        return 0;
 424}
 425
 426static int acpi_battery_get_info(struct acpi_battery *battery)
 427{
 428        int result = -EFAULT;
 429        acpi_status status = 0;
 430        char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ?
 431                        "_BIX" : "_BIF";
 432
 433        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 434
 435        if (!acpi_battery_present(battery))
 436                return 0;
 437        mutex_lock(&battery->lock);
 438        status = acpi_evaluate_object(battery->device->handle, name,
 439                                                NULL, &buffer);
 440        mutex_unlock(&battery->lock);
 441
 442        if (ACPI_FAILURE(status)) {
 443                ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
 444                return -ENODEV;
 445        }
 446        if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
 447                result = extract_package(battery, buffer.pointer,
 448                                extended_info_offsets,
 449                                ARRAY_SIZE(extended_info_offsets));
 450        else
 451                result = extract_package(battery, buffer.pointer,
 452                                info_offsets, ARRAY_SIZE(info_offsets));
 453        kfree(buffer.pointer);
 454        if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
 455                battery->full_charge_capacity = battery->design_capacity;
 456        if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
 457            battery->power_unit && battery->design_voltage) {
 458                battery->design_capacity = battery->design_capacity *
 459                    10000 / battery->design_voltage;
 460                battery->full_charge_capacity = battery->full_charge_capacity *
 461                    10000 / battery->design_voltage;
 462                battery->design_capacity_warning =
 463                    battery->design_capacity_warning *
 464                    10000 / battery->design_voltage;
 465                /* Curiously, design_capacity_low, unlike the rest of them,
 466                   is correct.  */
 467                /* capacity_granularity_* equal 1 on the systems tested, so
 468                   it's impossible to tell if they would need an adjustment
 469                   or not if their values were higher.  */
 470        }
 471        return result;
 472}
 473
 474static int acpi_battery_get_state(struct acpi_battery *battery)
 475{
 476        int result = 0;
 477        acpi_status status = 0;
 478        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 479
 480        if (!acpi_battery_present(battery))
 481                return 0;
 482
 483        if (battery->update_time &&
 484            time_before(jiffies, battery->update_time +
 485                        msecs_to_jiffies(cache_time)))
 486                return 0;
 487
 488        mutex_lock(&battery->lock);
 489        status = acpi_evaluate_object(battery->device->handle, "_BST",
 490                                      NULL, &buffer);
 491        mutex_unlock(&battery->lock);
 492
 493        if (ACPI_FAILURE(status)) {
 494                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
 495                return -ENODEV;
 496        }
 497
 498        result = extract_package(battery, buffer.pointer,
 499                                 state_offsets, ARRAY_SIZE(state_offsets));
 500        battery->update_time = jiffies;
 501        kfree(buffer.pointer);
 502
 503        /* For buggy DSDTs that report negative 16-bit values for either
 504         * charging or discharging current and/or report 0 as 65536
 505         * due to bad math.
 506         */
 507        if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
 508                battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
 509                (s16)(battery->rate_now) < 0) {
 510                battery->rate_now = abs((s16)battery->rate_now);
 511                printk_once(KERN_WARNING FW_BUG "battery: (dis)charge rate"
 512                        " invalid.\n");
 513        }
 514
 515        if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
 516            && battery->capacity_now >= 0 && battery->capacity_now <= 100)
 517                battery->capacity_now = (battery->capacity_now *
 518                                battery->full_charge_capacity) / 100;
 519        if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
 520            battery->power_unit && battery->design_voltage) {
 521                battery->capacity_now = battery->capacity_now *
 522                    10000 / battery->design_voltage;
 523        }
 524        return result;
 525}
 526
 527static int acpi_battery_set_alarm(struct acpi_battery *battery)
 528{
 529        acpi_status status = 0;
 530        union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER };
 531        struct acpi_object_list arg_list = { 1, &arg0 };
 532
 533        if (!acpi_battery_present(battery) ||
 534            !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
 535                return -ENODEV;
 536
 537        arg0.integer.value = battery->alarm;
 538
 539        mutex_lock(&battery->lock);
 540        status = acpi_evaluate_object(battery->device->handle, "_BTP",
 541                                 &arg_list, NULL);
 542        mutex_unlock(&battery->lock);
 543
 544        if (ACPI_FAILURE(status))
 545                return -ENODEV;
 546
 547        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
 548        return 0;
 549}
 550
 551static int acpi_battery_init_alarm(struct acpi_battery *battery)
 552{
 553        acpi_status status = AE_OK;
 554        acpi_handle handle = NULL;
 555
 556        /* See if alarms are supported, and if so, set default */
 557        status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
 558        if (ACPI_FAILURE(status)) {
 559                clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
 560                return 0;
 561        }
 562        set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
 563        if (!battery->alarm)
 564                battery->alarm = battery->design_capacity_warning;
 565        return acpi_battery_set_alarm(battery);
 566}
 567
 568static ssize_t acpi_battery_alarm_show(struct device *dev,
 569                                        struct device_attribute *attr,
 570                                        char *buf)
 571{
 572        struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
 573        return sprintf(buf, "%d\n", battery->alarm * 1000);
 574}
 575
 576static ssize_t acpi_battery_alarm_store(struct device *dev,
 577                                        struct device_attribute *attr,
 578                                        const char *buf, size_t count)
 579{
 580        unsigned long x;
 581        struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
 582        if (sscanf(buf, "%ld\n", &x) == 1)
 583                battery->alarm = x/1000;
 584        if (acpi_battery_present(battery))
 585                acpi_battery_set_alarm(battery);
 586        return count;
 587}
 588
 589static struct device_attribute alarm_attr = {
 590        .attr = {.name = "alarm", .mode = 0644},
 591        .show = acpi_battery_alarm_show,
 592        .store = acpi_battery_alarm_store,
 593};
 594
 595static int sysfs_add_battery(struct acpi_battery *battery)
 596{
 597        int result;
 598
 599        if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
 600                battery->bat.properties = charge_battery_props;
 601                battery->bat.num_properties =
 602                        ARRAY_SIZE(charge_battery_props);
 603        } else {
 604                battery->bat.properties = energy_battery_props;
 605                battery->bat.num_properties =
 606                        ARRAY_SIZE(energy_battery_props);
 607        }
 608
 609        battery->bat.name = acpi_device_bid(battery->device);
 610        battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
 611        battery->bat.get_property = acpi_battery_get_property;
 612
 613        result = power_supply_register(&battery->device->dev, &battery->bat);
 614        if (result)
 615                return result;
 616        return device_create_file(battery->bat.dev, &alarm_attr);
 617}
 618
 619static void sysfs_remove_battery(struct acpi_battery *battery)
 620{
 621        mutex_lock(&battery->sysfs_lock);
 622        if (!battery->bat.dev) {
 623                mutex_unlock(&battery->sysfs_lock);
 624                return;
 625        }
 626
 627        device_remove_file(battery->bat.dev, &alarm_attr);
 628        power_supply_unregister(&battery->bat);
 629        battery->bat.dev = NULL;
 630        mutex_unlock(&battery->sysfs_lock);
 631}
 632
 633static void find_battery(const struct dmi_header *dm, void *private)
 634{
 635        struct acpi_battery *battery = (struct acpi_battery *)private;
 636        /* Note: the hardcoded offsets below have been extracted from
 637           the source code of dmidecode.  */
 638        if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
 639                const u8 *dmi_data = (const u8 *)(dm + 1);
 640                int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
 641                if (dm->length >= 18)
 642                        dmi_capacity *= dmi_data[17];
 643                if (battery->design_capacity * battery->design_voltage / 1000
 644                    != dmi_capacity &&
 645                    battery->design_capacity * 10 == dmi_capacity)
 646                        set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
 647                                &battery->flags);
 648        }
 649}
 650
 651/*
 652 * According to the ACPI spec, some kinds of primary batteries can
 653 * report percentage battery remaining capacity directly to OS.
 654 * In this case, it reports the Last Full Charged Capacity == 100
 655 * and BatteryPresentRate == 0xFFFFFFFF.
 656 *
 657 * Now we found some battery reports percentage remaining capacity
 658 * even if it's rechargeable.
 659 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
 660 *
 661 * Handle this correctly so that they won't break userspace.
 662 */
 663static void acpi_battery_quirks(struct acpi_battery *battery)
 664{
 665        if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
 666                return;
 667
 668        if (battery->full_charge_capacity == 100 &&
 669                battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
 670                battery->capacity_now >= 0 && battery->capacity_now <= 100) {
 671                set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
 672                battery->full_charge_capacity = battery->design_capacity;
 673                battery->capacity_now = (battery->capacity_now *
 674                                battery->full_charge_capacity) / 100;
 675        }
 676
 677        if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
 678                return;
 679
 680        if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
 681                const char *s;
 682                s = dmi_get_system_info(DMI_PRODUCT_VERSION);
 683                if (s && !strnicmp(s, "ThinkPad", 8)) {
 684                        dmi_walk(find_battery, battery);
 685                        if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
 686                                     &battery->flags) &&
 687                            battery->design_voltage) {
 688                                battery->design_capacity =
 689                                    battery->design_capacity *
 690                                    10000 / battery->design_voltage;
 691                                battery->full_charge_capacity =
 692                                    battery->full_charge_capacity *
 693                                    10000 / battery->design_voltage;
 694                                battery->design_capacity_warning =
 695                                    battery->design_capacity_warning *
 696                                    10000 / battery->design_voltage;
 697                                battery->capacity_now = battery->capacity_now *
 698                                    10000 / battery->design_voltage;
 699                        }
 700                }
 701        }
 702}
 703
 704static int acpi_battery_update(struct acpi_battery *battery)
 705{
 706        int result, old_present = acpi_battery_present(battery);
 707        result = acpi_battery_get_status(battery);
 708        if (result)
 709                return result;
 710        if (!acpi_battery_present(battery)) {
 711                sysfs_remove_battery(battery);
 712                battery->update_time = 0;
 713                return 0;
 714        }
 715        if (!battery->update_time ||
 716            old_present != acpi_battery_present(battery)) {
 717                result = acpi_battery_get_info(battery);
 718                if (result)
 719                        return result;
 720                acpi_battery_init_alarm(battery);
 721        }
 722        if (!battery->bat.dev) {
 723                result = sysfs_add_battery(battery);
 724                if (result)
 725                        return result;
 726        }
 727        result = acpi_battery_get_state(battery);
 728        acpi_battery_quirks(battery);
 729        return result;
 730}
 731
 732static void acpi_battery_refresh(struct acpi_battery *battery)
 733{
 734        int power_unit;
 735
 736        if (!battery->bat.dev)
 737                return;
 738
 739        power_unit = battery->power_unit;
 740
 741        acpi_battery_get_info(battery);
 742
 743        if (power_unit == battery->power_unit)
 744                return;
 745
 746        /* The battery has changed its reporting units. */
 747        sysfs_remove_battery(battery);
 748        sysfs_add_battery(battery);
 749}
 750
 751/* --------------------------------------------------------------------------
 752                              FS Interface (/proc)
 753   -------------------------------------------------------------------------- */
 754
 755#ifdef CONFIG_ACPI_PROCFS_POWER
 756static struct proc_dir_entry *acpi_battery_dir;
 757
 758static int acpi_battery_print_info(struct seq_file *seq, int result)
 759{
 760        struct acpi_battery *battery = seq->private;
 761
 762        if (result)
 763                goto end;
 764
 765        seq_printf(seq, "present:                 %s\n",
 766                   acpi_battery_present(battery) ? "yes" : "no");
 767        if (!acpi_battery_present(battery))
 768                goto end;
 769        if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
 770                seq_printf(seq, "design capacity:         unknown\n");
 771        else
 772                seq_printf(seq, "design capacity:         %d %sh\n",
 773                           battery->design_capacity,
 774                           acpi_battery_units(battery));
 775
 776        if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
 777                seq_printf(seq, "last full capacity:      unknown\n");
 778        else
 779                seq_printf(seq, "last full capacity:      %d %sh\n",
 780                           battery->full_charge_capacity,
 781                           acpi_battery_units(battery));
 782
 783        seq_printf(seq, "battery technology:      %srechargeable\n",
 784                   (!battery->technology)?"non-":"");
 785
 786        if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
 787                seq_printf(seq, "design voltage:          unknown\n");
 788        else
 789                seq_printf(seq, "design voltage:          %d mV\n",
 790                           battery->design_voltage);
 791        seq_printf(seq, "design capacity warning: %d %sh\n",
 792                   battery->design_capacity_warning,
 793                   acpi_battery_units(battery));
 794        seq_printf(seq, "design capacity low:     %d %sh\n",
 795                   battery->design_capacity_low,
 796                   acpi_battery_units(battery));
 797        seq_printf(seq, "cycle count:             %i\n", battery->cycle_count);
 798        seq_printf(seq, "capacity granularity 1:  %d %sh\n",
 799                   battery->capacity_granularity_1,
 800                   acpi_battery_units(battery));
 801        seq_printf(seq, "capacity granularity 2:  %d %sh\n",
 802                   battery->capacity_granularity_2,
 803                   acpi_battery_units(battery));
 804        seq_printf(seq, "model number:            %s\n", battery->model_number);
 805        seq_printf(seq, "serial number:           %s\n", battery->serial_number);
 806        seq_printf(seq, "battery type:            %s\n", battery->type);
 807        seq_printf(seq, "OEM info:                %s\n", battery->oem_info);
 808      end:
 809        if (result)
 810                seq_printf(seq, "ERROR: Unable to read battery info\n");
 811        return result;
 812}
 813
 814static int acpi_battery_print_state(struct seq_file *seq, int result)
 815{
 816        struct acpi_battery *battery = seq->private;
 817
 818        if (result)
 819                goto end;
 820
 821        seq_printf(seq, "present:                 %s\n",
 822                   acpi_battery_present(battery) ? "yes" : "no");
 823        if (!acpi_battery_present(battery))
 824                goto end;
 825
 826        seq_printf(seq, "capacity state:          %s\n",
 827                        (battery->state & 0x04) ? "critical" : "ok");
 828        if ((battery->state & 0x01) && (battery->state & 0x02))
 829                seq_printf(seq,
 830                           "charging state:          charging/discharging\n");
 831        else if (battery->state & 0x01)
 832                seq_printf(seq, "charging state:          discharging\n");
 833        else if (battery->state & 0x02)
 834                seq_printf(seq, "charging state:          charging\n");
 835        else
 836                seq_printf(seq, "charging state:          charged\n");
 837
 838        if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
 839                seq_printf(seq, "present rate:            unknown\n");
 840        else
 841                seq_printf(seq, "present rate:            %d %s\n",
 842                           battery->rate_now, acpi_battery_units(battery));
 843
 844        if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
 845                seq_printf(seq, "remaining capacity:      unknown\n");
 846        else
 847                seq_printf(seq, "remaining capacity:      %d %sh\n",
 848                           battery->capacity_now, acpi_battery_units(battery));
 849        if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
 850                seq_printf(seq, "present voltage:         unknown\n");
 851        else
 852                seq_printf(seq, "present voltage:         %d mV\n",
 853                           battery->voltage_now);
 854      end:
 855        if (result)
 856                seq_printf(seq, "ERROR: Unable to read battery state\n");
 857
 858        return result;
 859}
 860
 861static int acpi_battery_print_alarm(struct seq_file *seq, int result)
 862{
 863        struct acpi_battery *battery = seq->private;
 864
 865        if (result)
 866                goto end;
 867
 868        if (!acpi_battery_present(battery)) {
 869                seq_printf(seq, "present:                 no\n");
 870                goto end;
 871        }
 872        seq_printf(seq, "alarm:                   ");
 873        if (!battery->alarm)
 874                seq_printf(seq, "unsupported\n");
 875        else
 876                seq_printf(seq, "%u %sh\n", battery->alarm,
 877                                acpi_battery_units(battery));
 878      end:
 879        if (result)
 880                seq_printf(seq, "ERROR: Unable to read battery alarm\n");
 881        return result;
 882}
 883
 884static ssize_t acpi_battery_write_alarm(struct file *file,
 885                                        const char __user * buffer,
 886                                        size_t count, loff_t * ppos)
 887{
 888        int result = 0;
 889        char alarm_string[12] = { '\0' };
 890        struct seq_file *m = file->private_data;
 891        struct acpi_battery *battery = m->private;
 892
 893        if (!battery || (count > sizeof(alarm_string) - 1))
 894                return -EINVAL;
 895        if (!acpi_battery_present(battery)) {
 896                result = -ENODEV;
 897                goto end;
 898        }
 899        if (copy_from_user(alarm_string, buffer, count)) {
 900                result = -EFAULT;
 901                goto end;
 902        }
 903        alarm_string[count] = '\0';
 904        battery->alarm = simple_strtol(alarm_string, NULL, 0);
 905        result = acpi_battery_set_alarm(battery);
 906      end:
 907        if (!result)
 908                return count;
 909        return result;
 910}
 911
 912typedef int(*print_func)(struct seq_file *seq, int result);
 913
 914static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
 915        acpi_battery_print_info,
 916        acpi_battery_print_state,
 917        acpi_battery_print_alarm,
 918};
 919
 920static int acpi_battery_read(int fid, struct seq_file *seq)
 921{
 922        struct acpi_battery *battery = seq->private;
 923        int result = acpi_battery_update(battery);
 924        return acpi_print_funcs[fid](seq, result);
 925}
 926
 927#define DECLARE_FILE_FUNCTIONS(_name) \
 928static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
 929{ \
 930        return acpi_battery_read(_name##_tag, seq); \
 931} \
 932static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
 933{ \
 934        return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
 935}
 936
 937DECLARE_FILE_FUNCTIONS(info);
 938DECLARE_FILE_FUNCTIONS(state);
 939DECLARE_FILE_FUNCTIONS(alarm);
 940
 941#undef DECLARE_FILE_FUNCTIONS
 942
 943#define FILE_DESCRIPTION_RO(_name) \
 944        { \
 945        .name = __stringify(_name), \
 946        .mode = S_IRUGO, \
 947        .ops = { \
 948                .open = acpi_battery_##_name##_open_fs, \
 949                .read = seq_read, \
 950                .llseek = seq_lseek, \
 951                .release = single_release, \
 952                .owner = THIS_MODULE, \
 953                }, \
 954        }
 955
 956#define FILE_DESCRIPTION_RW(_name) \
 957        { \
 958        .name = __stringify(_name), \
 959        .mode = S_IFREG | S_IRUGO | S_IWUSR, \
 960        .ops = { \
 961                .open = acpi_battery_##_name##_open_fs, \
 962                .read = seq_read, \
 963                .llseek = seq_lseek, \
 964                .write = acpi_battery_write_##_name, \
 965                .release = single_release, \
 966                .owner = THIS_MODULE, \
 967                }, \
 968        }
 969
 970static const struct battery_file {
 971        struct file_operations ops;
 972        umode_t mode;
 973        const char *name;
 974} acpi_battery_file[] = {
 975        FILE_DESCRIPTION_RO(info),
 976        FILE_DESCRIPTION_RO(state),
 977        FILE_DESCRIPTION_RW(alarm),
 978};
 979
 980#undef FILE_DESCRIPTION_RO
 981#undef FILE_DESCRIPTION_RW
 982
 983static int acpi_battery_add_fs(struct acpi_device *device)
 984{
 985        struct proc_dir_entry *entry = NULL;
 986        int i;
 987
 988        printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
 989                        " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
 990        if (!acpi_device_dir(device)) {
 991                acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 992                                                     acpi_battery_dir);
 993                if (!acpi_device_dir(device))
 994                        return -ENODEV;
 995        }
 996
 997        for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
 998                entry = proc_create_data(acpi_battery_file[i].name,
 999                                         acpi_battery_file[i].mode,
1000                                         acpi_device_dir(device),
1001                                         &acpi_battery_file[i].ops,
1002                                         acpi_driver_data(device));
1003                if (!entry)
1004                        return -ENODEV;
1005        }
1006        return 0;
1007}
1008
1009static void acpi_battery_remove_fs(struct acpi_device *device)
1010{
1011        int i;
1012        if (!acpi_device_dir(device))
1013                return;
1014        for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
1015                remove_proc_entry(acpi_battery_file[i].name,
1016                                  acpi_device_dir(device));
1017
1018        remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
1019        acpi_device_dir(device) = NULL;
1020}
1021
1022#endif
1023
1024/* --------------------------------------------------------------------------
1025                                 Driver Interface
1026   -------------------------------------------------------------------------- */
1027
1028static void acpi_battery_notify(struct acpi_device *device, u32 event)
1029{
1030        struct acpi_battery *battery = acpi_driver_data(device);
1031        struct device *old;
1032
1033        if (!battery)
1034                return;
1035        old = battery->bat.dev;
1036        if (event == ACPI_BATTERY_NOTIFY_INFO)
1037                acpi_battery_refresh(battery);
1038        acpi_battery_update(battery);
1039        acpi_bus_generate_proc_event(device, event,
1040                                     acpi_battery_present(battery));
1041        acpi_bus_generate_netlink_event(device->pnp.device_class,
1042                                        dev_name(&device->dev), event,
1043                                        acpi_battery_present(battery));
1044        /* acpi_battery_update could remove power_supply object */
1045        if (old && battery->bat.dev)
1046                power_supply_changed(&battery->bat);
1047}
1048
1049static int battery_notify(struct notifier_block *nb,
1050                               unsigned long mode, void *_unused)
1051{
1052        struct acpi_battery *battery = container_of(nb, struct acpi_battery,
1053                                                    pm_nb);
1054        switch (mode) {
1055        case PM_POST_HIBERNATION:
1056        case PM_POST_SUSPEND:
1057                if (battery->bat.dev) {
1058                        sysfs_remove_battery(battery);
1059                        sysfs_add_battery(battery);
1060                }
1061                break;
1062        }
1063
1064        return 0;
1065}
1066
1067static int acpi_battery_add(struct acpi_device *device)
1068{
1069        int result = 0;
1070        struct acpi_battery *battery = NULL;
1071        acpi_handle handle;
1072        if (!device)
1073                return -EINVAL;
1074        battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
1075        if (!battery)
1076                return -ENOMEM;
1077        battery->device = device;
1078        strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1079        strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
1080        device->driver_data = battery;
1081        mutex_init(&battery->lock);
1082        mutex_init(&battery->sysfs_lock);
1083        if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
1084                        "_BIX", &handle)))
1085                set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
1086        result = acpi_battery_update(battery);
1087        if (result)
1088                goto fail;
1089#ifdef CONFIG_ACPI_PROCFS_POWER
1090        result = acpi_battery_add_fs(device);
1091#endif
1092        if (result) {
1093#ifdef CONFIG_ACPI_PROCFS_POWER
1094                acpi_battery_remove_fs(device);
1095#endif
1096                goto fail;
1097        }
1098
1099        printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
1100                ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
1101                device->status.battery_present ? "present" : "absent");
1102
1103        battery->pm_nb.notifier_call = battery_notify;
1104        register_pm_notifier(&battery->pm_nb);
1105
1106        return result;
1107
1108fail:
1109        sysfs_remove_battery(battery);
1110        mutex_destroy(&battery->lock);
1111        mutex_destroy(&battery->sysfs_lock);
1112        kfree(battery);
1113        return result;
1114}
1115
1116static int acpi_battery_remove(struct acpi_device *device)
1117{
1118        struct acpi_battery *battery = NULL;
1119
1120        if (!device || !acpi_driver_data(device))
1121                return -EINVAL;
1122        battery = acpi_driver_data(device);
1123        unregister_pm_notifier(&battery->pm_nb);
1124#ifdef CONFIG_ACPI_PROCFS_POWER
1125        acpi_battery_remove_fs(device);
1126#endif
1127        sysfs_remove_battery(battery);
1128        mutex_destroy(&battery->lock);
1129        mutex_destroy(&battery->sysfs_lock);
1130        kfree(battery);
1131        return 0;
1132}
1133
1134#ifdef CONFIG_PM_SLEEP
1135/* this is needed to learn about changes made in suspended state */
1136static int acpi_battery_resume(struct device *dev)
1137{
1138        struct acpi_battery *battery;
1139
1140        if (!dev)
1141                return -EINVAL;
1142
1143        battery = acpi_driver_data(to_acpi_device(dev));
1144        if (!battery)
1145                return -EINVAL;
1146
1147        battery->update_time = 0;
1148        acpi_battery_update(battery);
1149        return 0;
1150}
1151#endif
1152
1153static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
1154
1155static struct acpi_driver acpi_battery_driver = {
1156        .name = "battery",
1157        .class = ACPI_BATTERY_CLASS,
1158        .ids = battery_device_ids,
1159        .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1160        .ops = {
1161                .add = acpi_battery_add,
1162                .remove = acpi_battery_remove,
1163                .notify = acpi_battery_notify,
1164                },
1165        .drv.pm = &acpi_battery_pm,
1166};
1167
1168static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
1169{
1170        if (acpi_disabled)
1171                return;
1172#ifdef CONFIG_ACPI_PROCFS_POWER
1173        acpi_battery_dir = acpi_lock_battery_dir();
1174        if (!acpi_battery_dir)
1175                return;
1176#endif
1177        if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
1178#ifdef CONFIG_ACPI_PROCFS_POWER
1179                acpi_unlock_battery_dir(acpi_battery_dir);
1180#endif
1181                return;
1182        }
1183        return;
1184}
1185
1186static int __init acpi_battery_init(void)
1187{
1188        async_schedule(acpi_battery_init_async, NULL);
1189        return 0;
1190}
1191
1192static void __exit acpi_battery_exit(void)
1193{
1194        acpi_bus_unregister_driver(&acpi_battery_driver);
1195#ifdef CONFIG_ACPI_PROCFS_POWER
1196        acpi_unlock_battery_dir(acpi_battery_dir);
1197#endif
1198}
1199
1200module_init(acpi_battery_init);
1201module_exit(acpi_battery_exit);
1202
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.