Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1d4661a authored by Alexey Starikovskiy's avatar Alexey Starikovskiy Committed by Len Brown
Browse files

ACPI: Battery: simplify update scheme

parent 038fdea2
Loading
Loading
Loading
Loading
+57 −223
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/jiffies.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
@@ -41,27 +42,18 @@
#define ACPI_BATTERY_DEVICE_NAME	"Battery"
#define ACPI_BATTERY_NOTIFY_STATUS	0x80
#define ACPI_BATTERY_NOTIFY_INFO	0x81
#define ACPI_BATTERY_UNITS_WATTS	"mW"
#define ACPI_BATTERY_UNITS_AMPS		"mA"

#define _COMPONENT		ACPI_BATTERY_COMPONENT

#define ACPI_BATTERY_UPDATE_TIME	0

#define ACPI_BATTERY_NONE_UPDATE	0
#define ACPI_BATTERY_EASY_UPDATE	1
#define ACPI_BATTERY_INIT_UPDATE	2

ACPI_MODULE_NAME("battery");

MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION("ACPI Battery Driver");
MODULE_LICENSE("GPL");

static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME;

/* 0 - every time, > 0 - by update_time */
module_param(update_time, uint, 0644);
static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");

extern struct proc_dir_entry *acpi_lock_battery_dir(void);
extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
@@ -95,15 +87,12 @@ enum acpi_battery_files {
};

struct acpi_battery {
	struct acpi_device *device;
	struct mutex lock;
	unsigned long alarm;
	unsigned long update_time[ACPI_BATTERY_NUMFILES];
	int state;
	struct acpi_device *device;
	unsigned long update_time;
	int present_rate;
	int remaining_capacity;
	int present_voltage;
	int power_unit;
	int design_capacity;
	int last_full_capacity;
	int technology;
@@ -112,14 +101,14 @@ struct acpi_battery {
	int design_capacity_low;
	int capacity_granularity_1;
	int capacity_granularity_2;
	int alarm;
	char model_number[32];
	char serial_number[32];
	char type[32];
	char oem_info[32];
	u8 present_prev;
	int state;
	int power_unit;
	u8 alarm_present;
	u8 init_update;
	u8 update[ACPI_BATTERY_NUMFILES];
};

inline int acpi_battery_present(struct acpi_battery *battery)
@@ -127,33 +116,15 @@ inline int acpi_battery_present(struct acpi_battery *battery)
	return battery->device->status.battery_present;
}

inline char *acpi_battery_power_units(struct acpi_battery *battery)
{
	if (battery->power_unit)
		return ACPI_BATTERY_UNITS_AMPS;
	else
		return ACPI_BATTERY_UNITS_WATTS;
}

inline acpi_handle acpi_battery_handle(struct acpi_battery *battery)
inline char *acpi_battery_units(struct acpi_battery *battery)
{
	return battery->device->handle;
	return (battery->power_unit)?"mA":"mW";
}

/* --------------------------------------------------------------------------
                               Battery Management
   -------------------------------------------------------------------------- */

static void acpi_battery_check_result(struct acpi_battery *battery, int result)
{
	if (!battery)
		return;

	if (result) {
		battery->init_update = 1;
	}
}

struct acpi_offsets {
	size_t offset;		/* offset inside struct acpi_sbs_battery */
	u8 mode;		/* int or string? */
@@ -228,11 +199,10 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
	acpi_status status = 0;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };

	battery->update_time[ACPI_BATTERY_INFO] = get_seconds();
	if (!acpi_battery_present(battery))
		return 0;
	mutex_lock(&battery->lock);
	status = acpi_evaluate_object(acpi_battery_handle(battery), "_BIF",
	status = acpi_evaluate_object(battery->device->handle, "_BIF",
				      NULL, &buffer);
	mutex_unlock(&battery->lock);
	if (ACPI_FAILURE(status)) {
@@ -251,13 +221,16 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
	acpi_status status = 0;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };

	battery->update_time[ACPI_BATTERY_STATE] = get_seconds();

	if (!acpi_battery_present(battery))
		return 0;

	if (battery->update_time &&
	    time_before(jiffies, battery->update_time +
			msecs_to_jiffies(cache_time)))
		return 0;

	mutex_lock(&battery->lock);
	status = acpi_evaluate_object(acpi_battery_handle(battery), "_BST",
	status = acpi_evaluate_object(battery->device->handle, "_BST",
				      NULL, &buffer);
	mutex_unlock(&battery->lock);

@@ -267,14 +240,13 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
	}
	result = extract_package(battery, buffer.pointer,
				 state_offsets, ARRAY_SIZE(state_offsets));
	battery->update_time = jiffies;
	kfree(buffer.pointer);
	return result;
}

static int acpi_battery_get_alarm(struct acpi_battery *battery)
{
	battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();

	return 0;
}

@@ -285,8 +257,6 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,
	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
	struct acpi_object_list arg_list = { 1, &arg0 };

	battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();

	if (!acpi_battery_present(battery))
		return -ENODEV;

@@ -296,7 +266,7 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,
	arg0.integer.value = alarm;

	mutex_lock(&battery->lock);
	status = acpi_evaluate_object(acpi_battery_handle(battery), "_BTP",
	status = acpi_evaluate_object(battery->device->handle, "_BTP",
				 &arg_list, NULL);
	mutex_unlock(&battery->lock);
	if (ACPI_FAILURE(status))
@@ -311,112 +281,36 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,

static int acpi_battery_init_alarm(struct acpi_battery *battery)
{
	int result = 0;
	acpi_status status = AE_OK;
	acpi_handle handle = NULL;
	unsigned long alarm = battery->alarm;

	/* See if alarms are supported, and if so, set default */

	status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle);
	if (ACPI_SUCCESS(status)) {
		battery->alarm_present = 1;
		if (!alarm) {
			alarm = battery->design_capacity_warning;
		}
		result = acpi_battery_set_alarm(battery, alarm);
		if (result)
			goto end;
	} else {
	status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
	if (ACPI_FAILURE(status)) {
		battery->alarm_present = 0;
		return 0;
	}

      end:

	return result;
	battery->alarm_present = 1;
	if (!battery->alarm)
		battery->alarm = battery->design_capacity_warning;
	return acpi_battery_set_alarm(battery, battery->alarm);
}

static int acpi_battery_init_update(struct acpi_battery *battery)
static int acpi_battery_update(struct acpi_battery *battery)
{
	int result = 0;

	result = acpi_battery_get_status(battery);
	if (result)
	int saved_present = acpi_battery_present(battery);
	int result = acpi_battery_get_status(battery);
	if (result || !acpi_battery_present(battery))
		return result;

	battery->present_prev = acpi_battery_present(battery);

	if (acpi_battery_present(battery)) {
	if (saved_present != acpi_battery_present(battery) ||
	    !battery->update_time) {
		battery->update_time = 0;
		result = acpi_battery_get_info(battery);
		if (result)
			return result;
		result = acpi_battery_get_state(battery);
		if (result)
			return result;

		acpi_battery_init_alarm(battery);
	}

	return result;
}

static int acpi_battery_update(struct acpi_battery *battery,
			       int update, int *update_result_ptr)
{
	int result = 0;
	int update_result = ACPI_BATTERY_NONE_UPDATE;

	if (!acpi_battery_present(battery)) {
		update = 1;
	}

	if (battery->init_update) {
		result = acpi_battery_init_update(battery);
		if (result)
			goto end;
		update_result = ACPI_BATTERY_INIT_UPDATE;
	} else if (update) {
		result = acpi_battery_get_status(battery);
		if (result)
			goto end;
		if ((!battery->present_prev & acpi_battery_present(battery))
		    || (battery->present_prev & !acpi_battery_present(battery))) {
			result = acpi_battery_init_update(battery);
			if (result)
				goto end;
			update_result = ACPI_BATTERY_INIT_UPDATE;
		} else {
			update_result = ACPI_BATTERY_EASY_UPDATE;
		}
	}

      end:

	battery->init_update = (result != 0);

	*update_result_ptr = update_result;

	return result;
}

static void acpi_battery_notify_update(struct acpi_battery *battery)
{
	acpi_battery_get_status(battery);

	if (battery->init_update) {
		return;
	}

	if ((!battery->present_prev &
	     acpi_battery_present(battery)) ||
	    (battery->present_prev &
	     !acpi_battery_present(battery))) {
		battery->init_update = 1;
	} else {
		battery->update[ACPI_BATTERY_INFO] = 1;
		battery->update[ACPI_BATTERY_STATE] = 1;
		battery->update[ACPI_BATTERY_ALARM] = 1;
	}
	return acpi_battery_get_state(battery);
}

/* --------------------------------------------------------------------------
@@ -442,7 +336,7 @@ static int acpi_battery_print_info(struct seq_file *seq, int result)

	/* Battery Units */

	units = acpi_battery_power_units(battery);
	units = acpi_battery_units(battery);

	if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
		seq_printf(seq, "design capacity:         unknown\n");
@@ -511,7 +405,7 @@ static int acpi_battery_print_state(struct seq_file *seq, int result)

	/* Battery Units */

	units = acpi_battery_power_units(battery);
	units = acpi_battery_units(battery);

	if (!(battery->state & 0x04))
		seq_printf(seq, "capacity state:          ok\n");
@@ -571,13 +465,13 @@ static int acpi_battery_print_alarm(struct seq_file *seq, int result)

	/* Battery Units */

	units = acpi_battery_power_units(battery);
	units = acpi_battery_units(battery);

	seq_printf(seq, "alarm:                   ");
	if (!battery->alarm)
		seq_printf(seq, "unsupported\n");
	else
		seq_printf(seq, "%lu %sh\n", battery->alarm, units);
		seq_printf(seq, "%u %sh\n", battery->alarm, units);

      end:

@@ -587,8 +481,7 @@ static int acpi_battery_print_alarm(struct seq_file *seq, int result)
	return result;
}

static ssize_t
acpi_battery_write_alarm(struct file *file,
static ssize_t acpi_battery_write_alarm(struct file *file,
					const char __user * buffer,
					size_t count, loff_t * ppos)
{
@@ -596,40 +489,27 @@ acpi_battery_write_alarm(struct file *file,
	char alarm_string[12] = { '\0' };
	struct seq_file *m = file->private_data;
	struct acpi_battery *battery = m->private;
	int update_result = ACPI_BATTERY_NONE_UPDATE;

	if (!battery || (count > sizeof(alarm_string) - 1))
		return -EINVAL;

	result = acpi_battery_update(battery, 1, &update_result);
	if (result) {
		result = -ENODEV;
		goto end;
	}

	if (!acpi_battery_present(battery)) {
		result = -ENODEV;
		goto end;
	}

	if (copy_from_user(alarm_string, buffer, count)) {
		result = -EFAULT;
		goto end;
	}

	alarm_string[count] = '\0';

	result = acpi_battery_set_alarm(battery,
					simple_strtoul(alarm_string, NULL, 0));
	if (result)
		goto end;

	battery->alarm = simple_strtol(alarm_string, NULL, 0);
	result = acpi_battery_set_alarm(battery, battery->alarm);
      end:

	acpi_battery_check_result(battery, result);

	if (!result)
		result = count;
		return count;
	return result;
}

@@ -648,28 +528,8 @@ static struct acpi_read_mux {
static int acpi_battery_read(int fid, struct seq_file *seq)
{
	struct acpi_battery *battery = seq->private;
	int result = 0;
	int update_result = ACPI_BATTERY_NONE_UPDATE;
	int update = 0;

	update = (get_seconds() - battery->update_time[fid] >= update_time);
	update = (update | battery->update[fid]);

	result = acpi_battery_update(battery, update, &update_result);
	if (result)
		goto end;

	if (update_result == ACPI_BATTERY_EASY_UPDATE) {
		result = acpi_read_funcs[fid].get(battery);
		if (result)
			goto end;
	}

      end:
	result = acpi_read_funcs[fid].print(seq, result);
	acpi_battery_check_result(battery, result);
	battery->update[fid] = result;
	return result;
	int result = acpi_battery_update(battery);
	return acpi_read_funcs[fid].print(seq, result);
}

static int acpi_battery_read_info(struct seq_file *seq, void *offset)
@@ -793,33 +653,16 @@ static int acpi_battery_remove_fs(struct acpi_device *device)
static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
{
	struct acpi_battery *battery = data;
	struct acpi_device *device = NULL;

	struct acpi_device *device;
	if (!battery)
		return;

	device = battery->device;

	switch (event) {
	case ACPI_BATTERY_NOTIFY_STATUS:
	case ACPI_BATTERY_NOTIFY_INFO:
	case ACPI_NOTIFY_BUS_CHECK:
	case ACPI_NOTIFY_DEVICE_CHECK:
	device = battery->device;
		acpi_battery_notify_update(battery);
	acpi_battery_update(battery);
	acpi_bus_generate_proc_event(device, event,
				     acpi_battery_present(battery));
	acpi_bus_generate_netlink_event(device->pnp.device_class,
					device->dev.bus_id, event,
					acpi_battery_present(battery));
		break;
	default:
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Unsupported event [0x%x]\n", event));
		break;
	}

	return;
}

static int acpi_battery_add(struct acpi_device *device)
@@ -840,12 +683,7 @@ 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);
	result = acpi_battery_get_status(battery);
	if (result)
		goto end;

	battery->init_update = 1;

	acpi_battery_update(battery);
	result = acpi_battery_add_fs(device);
	if (result)
		goto end;
@@ -898,14 +736,10 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
static int acpi_battery_resume(struct acpi_device *device)
{
	struct acpi_battery *battery;

	if (!device)
		return -EINVAL;

	battery = device->driver_data;

	battery->init_update = 1;

	battery = acpi_driver_data(device);
	battery->update_time = 0;
	return 0;
}