diff options
Diffstat (limited to 'drivers/power/supply/ds2782_battery.c')
-rw-r--r-- | drivers/power/supply/ds2782_battery.c | 89 |
1 files changed, 32 insertions, 57 deletions
diff --git a/drivers/power/supply/ds2782_battery.c b/drivers/power/supply/ds2782_battery.c index 85aa9c465aa4..cae95d35d398 100644 --- a/drivers/power/supply/ds2782_battery.c +++ b/drivers/power/supply/ds2782_battery.c @@ -11,6 +11,7 @@ * UEvent sending added by Evgeny Romanov <romanov@neurosoft.ru> */ +#include <linux/devm-helpers.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/types.h> @@ -57,14 +58,12 @@ struct ds278x_info { struct power_supply_desc battery_desc; const struct ds278x_battery_ops *ops; struct delayed_work bat_work; - int id; int rsns; int capacity; int status; /* State Of Charge */ }; -static DEFINE_IDR(battery_id); -static DEFINE_MUTEX(battery_lock); +static DEFINE_IDA(battery_id); static inline int ds278x_read_reg(struct ds278x_info *info, int reg, u8 *val) { @@ -312,21 +311,6 @@ static void ds278x_power_supply_init(struct power_supply_desc *battery) battery->external_power_changed = NULL; } -static void ds278x_battery_remove(struct i2c_client *client) -{ - struct ds278x_info *info = i2c_get_clientdata(client); - int id = info->id; - - power_supply_unregister(info->battery); - cancel_delayed_work_sync(&info->bat_work); - kfree(info->battery_desc.name); - kfree(info); - - mutex_lock(&battery_lock); - idr_remove(&battery_id, id); - mutex_unlock(&battery_lock); -} - #ifdef CONFIG_PM_SLEEP static int ds278x_suspend(struct device *dev) @@ -368,6 +352,13 @@ static const struct ds278x_battery_ops ds278x_ops[] = { } }; +static void ds278x_free_ida(void *data) +{ + int num = (uintptr_t)data; + + ida_free(&battery_id, num); +} + static int ds278x_battery_probe(struct i2c_client *client) { const struct i2c_device_id *id = i2c_client_get_device_id(client); @@ -387,32 +378,27 @@ static int ds278x_battery_probe(struct i2c_client *client) } /* Get an ID for this battery */ - mutex_lock(&battery_lock); - ret = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL); - mutex_unlock(&battery_lock); - if (ret < 0) - goto fail_id; - num = ret; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) { - ret = -ENOMEM; - goto fail_info; - } + num = ida_alloc(&battery_id, GFP_KERNEL); + if (num < 0) + return num; + ret = devm_add_action_or_reset(&client->dev, ds278x_free_ida, (void *)(uintptr_t)num); + if (ret) + return ret; - info->battery_desc.name = kasprintf(GFP_KERNEL, "%s-%d", - client->name, num); - if (!info->battery_desc.name) { - ret = -ENOMEM; - goto fail_name; - } + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->battery_desc.name = devm_kasprintf(&client->dev, GFP_KERNEL, + "%s-%d", client->name, num); + if (!info->battery_desc.name) + return -ENOMEM; if (id->driver_data == DS2786) info->rsns = pdata->rsns; i2c_set_clientdata(client, info); info->client = client; - info->id = num; info->ops = &ds278x_ops[id->driver_data]; ds278x_power_supply_init(&info->battery_desc); psy_cfg.drv_data = info; @@ -420,30 +406,20 @@ static int ds278x_battery_probe(struct i2c_client *client) info->capacity = 100; info->status = POWER_SUPPLY_STATUS_FULL; - INIT_DELAYED_WORK(&info->bat_work, ds278x_bat_work); - - info->battery = power_supply_register(&client->dev, - &info->battery_desc, &psy_cfg); + info->battery = devm_power_supply_register(&client->dev, + &info->battery_desc, + &psy_cfg); if (IS_ERR(info->battery)) { dev_err(&client->dev, "failed to register battery\n"); - ret = PTR_ERR(info->battery); - goto fail_register; - } else { - schedule_delayed_work(&info->bat_work, DS278x_DELAY); + return PTR_ERR(info->battery); } - return 0; + ret = devm_delayed_work_autocancel(&client->dev, &info->bat_work, ds278x_bat_work); + if (ret) + return ret; + schedule_delayed_work(&info->bat_work, DS278x_DELAY); -fail_register: - kfree(info->battery_desc.name); -fail_name: - kfree(info); -fail_info: - mutex_lock(&battery_lock); - idr_remove(&battery_id, num); - mutex_unlock(&battery_lock); -fail_id: - return ret; + return 0; } static const struct i2c_device_id ds278x_id[] = { @@ -459,7 +435,6 @@ static struct i2c_driver ds278x_battery_driver = { .pm = &ds278x_battery_pm_ops, }, .probe = ds278x_battery_probe, - .remove = ds278x_battery_remove, .id_table = ds278x_id, }; module_i2c_driver(ds278x_battery_driver); |