Subject: [PATCH] [2.6.24-rc] ACPI: register power_supply subdevice only when battery is present From: Andrey Borzenkov Make sure no power_supply object is present unless we actualy detect presence of battery. This fixes ghost batteries detected by HAL Signed-off-by: Andrey Borzenkov --- drivers/acpi/battery.c | 98 ++++++++++++++++++++++++++++++------------------ 1 files changed, 61 insertions(+), 37 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index d33cb49..f37e509 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -390,14 +390,64 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) return acpi_battery_set_alarm(battery); } +static ssize_t acpi_battery_alarm_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + return sprintf(buf, "%d\n", battery->alarm * 1000); +} + +static ssize_t acpi_battery_alarm_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long x; + struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + if (sscanf(buf, "%ld\n", &x) == 1) + battery->alarm = x/1000; + if (acpi_battery_present(battery)) + acpi_battery_set_alarm(battery); + return count; +} + +static struct device_attribute alarm_attr = { + .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, + .show = acpi_battery_alarm_show, + .store = acpi_battery_alarm_store, +}; + +static int sysfs_add_battery(struct acpi_battery *battery) +{ + int result = 0; + + result = power_supply_register(&battery->device->dev, &battery->bat); + result = device_create_file(battery->bat.dev, &alarm_attr); + + return result; +} + +static int sysfs_remove_battery(struct acpi_battery *battery) +{ + if (battery->bat.dev) { + device_remove_file(battery->bat.dev, &alarm_attr); + power_supply_unregister(&battery->bat); + battery->bat.dev = NULL; + } + + return 0; +} + static int acpi_battery_update(struct acpi_battery *battery) { - int saved_present = acpi_battery_present(battery); int result = acpi_battery_get_status(battery); - if (result || !acpi_battery_present(battery)) + if (result) return result; - if (saved_present != acpi_battery_present(battery) || - !battery->update_time) { + if (!acpi_battery_present(battery)) { + sysfs_remove_battery(battery); + return 0; + } + if (!battery->bat.dev) { battery->update_time = 0; result = acpi_battery_get_info(battery); if (result) @@ -411,6 +461,7 @@ static int acpi_battery_update(struct acpi_battery *battery) battery->bat.num_properties = ARRAY_SIZE(energy_battery_props); } + sysfs_add_battery(battery); acpi_battery_init_alarm(battery); } return acpi_battery_get_state(battery); @@ -693,33 +744,6 @@ static void acpi_battery_remove_fs(struct acpi_device *device) #endif -static ssize_t acpi_battery_alarm_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); - return sprintf(buf, "%d\n", battery->alarm * 1000); -} - -static ssize_t acpi_battery_alarm_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long x; - struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); - if (sscanf(buf, "%ld\n", &x) == 1) - battery->alarm = x/1000; - if (acpi_battery_present(battery)) - acpi_battery_set_alarm(battery); - return count; -} - -static struct device_attribute alarm_attr = { - .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, - .show = acpi_battery_alarm_show, - .store = acpi_battery_alarm_store, -}; - /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -737,7 +761,9 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) acpi_bus_generate_netlink_event(device->pnp.device_class, device->dev.bus_id, event, acpi_battery_present(battery)); - kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); + /* acpi_batter_update could remove power_supply object */ + if (battery->bat.dev) + kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); } static int acpi_battery_add(struct acpi_device *device) @@ -755,17 +781,15 @@ static int acpi_battery_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); acpi_driver_data(device) = battery; mutex_init(&battery->lock); + battery->bat.name = acpi_device_bid(device); + battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; + battery->bat.get_property = acpi_battery_get_property; acpi_battery_update(battery); #ifdef CONFIG_ACPI_PROCFS result = acpi_battery_add_fs(device); if (result) goto end; #endif - battery->bat.name = acpi_device_bid(device); - battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; - battery->bat.get_property = acpi_battery_get_property; - result = power_supply_register(&battery->device->dev, &battery->bat); - result = device_create_file(battery->bat.dev, &alarm_attr); status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify, battery);