예제 #1
0
static int acpi_power_meter_remove(struct acpi_device *device, int type)
{
	struct acpi_power_meter_resource *resource;

	if (!device || !acpi_driver_data(device))
		return -EINVAL;

	resource = acpi_driver_data(device);
	hwmon_device_unregister(resource->hwmon_dev);

	free_capabilities(resource);
	remove_attrs(resource);

	kfree(resource);
	return 0;
}
예제 #2
0
static int acpi_power_meter_add(struct acpi_device *device)
{
	int res;
	struct acpi_power_meter_resource *resource;

	if (!device)
		return -EINVAL;

	resource = kzalloc(sizeof(struct acpi_power_meter_resource),
			   GFP_KERNEL);
	if (!resource)
		return -ENOMEM;

	resource->sensors_valid = 0;
	resource->acpi_dev = device;
	mutex_init(&resource->lock);
	strcpy(acpi_device_name(device), ACPI_POWER_METER_DEVICE_NAME);
	strcpy(acpi_device_class(device), ACPI_POWER_METER_CLASS);
	device->driver_data = resource;

	free_capabilities(resource);
	res = read_capabilities(resource);
	if (res)
		goto exit_free;

	resource->trip[0] = resource->trip[1] = -1;

	res = setup_attrs(resource);
	if (res)
		goto exit_free;

	resource->hwmon_dev = hwmon_device_register(&device->dev);
	if (IS_ERR(resource->hwmon_dev)) {
		res = PTR_ERR(resource->hwmon_dev);
		goto exit_remove;
	}

	res = 0;
	goto exit;

exit_remove:
	remove_attrs(resource);
exit_free:
	kfree(resource);
exit:
	return res;
}
예제 #3
0
/* Handle ACPI event notifications */
static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
{
	struct acpi_power_meter_resource *resource;
	int res;

	if (!device || !acpi_driver_data(device))
		return;

	resource = acpi_driver_data(device);

	mutex_lock(&resource->lock);
	switch (event) {
	case METER_NOTIFY_CONFIG:
		free_capabilities(resource);
		res = read_capabilities(resource);
		if (res)
			break;

		remove_attrs(resource);
		setup_attrs(resource);
		break;
	case METER_NOTIFY_TRIP:
		sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME);
		update_meter(resource);
		break;
	case METER_NOTIFY_CAP:
		sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME);
		update_cap(resource);
		break;
	case METER_NOTIFY_INTERVAL:
		sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME);
		update_avg_interval(resource);
		break;
	case METER_NOTIFY_CAPPING:
		sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME);
		dev_info(&device->dev, "Capping in progress.\n");
		break;
	default:
		WARN(1, "Unexpected event %d\n", event);
		break;
	}
	mutex_unlock(&resource->lock);

	acpi_bus_generate_netlink_event(ACPI_POWER_METER_CLASS,
					dev_name(&device->dev), event, 0);
}