lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 24 Mar 2020 17:36:15 +0100
From:   Enric Balletbo i Serra <enric.balletbo@...labora.com>
To:     Srinivas Pandruvada <srinivas.pandruvada@...ux.intel.com>,
        linux-kernel@...r.kernel.org
Cc:     vbendeb@...omium.org, groeck@...omium.org, bleung@...omium.org,
        dtor@...omium.org, gwendal@...omium.org, andy@...radead.org,
        Collabora Kernel ML <kernel@...labora.com>,
        Ayman Bagabas <ayman.bagabas@...il.com>,
        Darren Hart <dvhart@...radead.org>,
        Dmitry Torokhov <dmitry.torokhov@...il.com>,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        Jeremy Soller <jeremy@...tem76.com>,
        Mattias Jacobsson <2pi@....nu>,
        Mauro Carvalho Chehab <mchehab+samsung@...nel.org>,
        Rajat Jain <rajatja@...gle.com>,
        Yauhen Kharuzhy <jekhor@...il.com>,
        platform-driver-x86@...r.kernel.org
Subject: Re: [PATCH v2] platform: x86: Add ACPI driver for ChromeOS

Hi Srinivas,

Thanks for your quick answer.

On 22/3/20 16:21, Srinivas Pandruvada wrote:
> On Sun, 2020-03-22 at 10:43 +0100, Enric Balletbo i Serra wrote:
>> This driver attaches to the ChromeOS ACPI device and then exports the
>> values
>> reported by the ACPI in a sysfs directory. The ACPI values are
>> presented in
>> the string form (numbers as decimal values) or binary blobs, and can
>> be
>> accessed as the contents of the appropriate read only files in the
>> sysfs
>> directory tree originating in /sys/devices/platform/chromeos_acpi.
>>
>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@...labora.com>
>> ---
>>
> 
> [...]
> 
>>  /sys/devices/platform/chromeos_acpi/BINF.2 : 1
> Just wondering why don't you create additional attributes under ACPI
> device itself, like in your case:
> /sys/bus/acpi/devices/GGL0001/*
> 

As I commented in my previous email, it was to no not break current ChromeOS
userspace. But I assume we will need to break it, so I'll investigate how hard
is to do that change on the userspace side.

Thanks,
Enric B.S.


> Additional attributes are added for ACPI device objects at such
> location in other cases also for some PNP* and INT3* objects.
> 
> This will make your driver simple with one attr group.
> 
> Thanks,
> Srinivas 
> 
> 
>>  /sys/devices/platform/chromeos_acpi/FMAP : -2031616
>>  /sys/devices/platform/chromeos_acpi/HWID : SAMUS E25-G7R-W35
>>  /sys/devices/platform/chromeos_acpi/BINF.0 : 0
>>  /sys/devices/platform/chromeos_acpi/GPIO.0/GPIO.2 : -1
>>  /sys/devices/platform/chromeos_acpi/GPIO.0/GPIO.0 : 1
>>  /sys/devices/platform/chromeos_acpi/GPIO.0/GPIO.3 : INT3437:00
>>  /sys/devices/platform/chromeos_acpi/GPIO.0/GPIO.1 : 0
>>  /sys/devices/platform/chromeos_acpi/FRID : Google_Samus.6300.102.0
>>  /sys/devices/platform/chromeos_acpi/VBNV.0 : 38
>>  /sys/devices/platform/chromeos_acpi/BINF.3 : 2
>>  /sys/devices/platform/chromeos_acpi/BINF.1 : 1
>>  /sys/devices/platform/chromeos_acpi/GPIO.1/GPIO.2 : 16
>>  /sys/devices/platform/chromeos_acpi/GPIO.1/GPIO.0 : 3
>>  /sys/devices/platform/chromeos_acpi/GPIO.1/GPIO.3 : INT3437:00
>>  /sys/devices/platform/chromeos_acpi/GPIO.1/GPIO.1 : 1
>>  /sys/devices/platform/chromeos_acpi/CHSW : 0
>>  /sys/devices/platform/chromeos_acpi/FWID : Google_Samus.6300.330.0
>>  /sys/devices/platform/chromeos_acpi/VBNV.1 : 16
>>  /sys/devices/platform/chromeos_acpi/BINF.4 : 0
>>
>> And for binary packages:
>>
>> cat /sys/devices/platform/chromeos_acpi/MECK | hexdump
>>  0000000 02fb 8e72 a025 0a73 0f13 095e 9e07 41e6
>>  0000010 f9e6 bb4e 76cc bef9 cca7 70e2 8f6d 863d
>>  0000020
>>
>> cat /sys/devices/platform/chromeos_acpi/VDAT | hexdump
>>  0000000 6256 4453 0002 0000 0448 0000 0000 0000
>>  0000010 0c00 0000 0000 0000 0850 0000 0000 0000
>>  0000020 7c54 0003 0000 0000 0420 0000 0000 0000
>>  0000030 0408 0000 0000 0000 0007 0000 0000 0000
>>  0000040 0003 0000 0000 0000 0448 0000 0000 0000
>>  0000050 0408 0000 0000 0000 9335 1f80 0000 0000
>>  0000060 69a8 21f3 0000 0000 1d02 21f9 0000 0000
>>  0000070 ba55 371b 0000 0000 0000 0000 0000 0000
>>  0000080 bcae 001d 0000 0000 0003 0001 0001 0003
>>  0000090 000c 0000 0003 0001 0003 0001 0001 0000
>>  00000a0 0001 0000 0000 0000 cc00 01da 0000 0000
>>  00000b0 0200 0000 0204 0000 0001 0000 0000 0000
>>  00000c0 0800 0000 0000 0000 0000 0001 0000 0000
>>  00000d0 0001 0001 1301 0000 0000 0000 0000 0000
>>  00000e0 0000 0000 0000 0000 0000 0000 0000 0000
>>  *
>>
>> Thanks,
>>  Enric
>>
>> [1] https://lkml.org/lkml/2017/7/31/378
>>
>> Changes in v2:
>> - Note that this version is a total rework, with those major changes:
>>   - Use lists to track dinamically allocated attributes and groups.
>>   - Use sysfs binary attributes to store the ACPI contents.
>>   - Remove all the functionalities except the one that creates the
>> sysfs files.
>>
>>  drivers/platform/x86/Kconfig         |  12 +
>>  drivers/platform/x86/Makefile        |   1 +
>>  drivers/platform/x86/chromeos_acpi.c | 489
>> +++++++++++++++++++++++++++
>>  3 files changed, 502 insertions(+)
>>  create mode 100644 drivers/platform/x86/chromeos_acpi.c
>>
>> diff --git a/drivers/platform/x86/Kconfig
>> b/drivers/platform/x86/Kconfig
>> index 587403c44598..917a1c1a0758 100644
>> --- a/drivers/platform/x86/Kconfig
>> +++ b/drivers/platform/x86/Kconfig
>> @@ -72,6 +72,18 @@ config ACERHDF
>>  	  If you have an Acer Aspire One netbook, say Y or M
>>  	  here.
>>  
>> +config ACPI_CHROMEOS
>> +	tristate "ChromeOS specific ACPI extensions"
>> +	depends on ACPI
>> +	depends on CHROME_PLATFORMS
>> +	help
>> +	  This driver provides the firmware interface for the services
>> +	  exported through the ChromeOS interfaces when using ChromeOS
>> +	  ACPI firmware.
>> +
>> +	  If you have an ACPI-compatible Chromebook, say Y or M
>> +	  here.
>> +
>>  config ALIENWARE_WMI
>>  	tristate "Alienware Special feature control"
>>  	depends on ACPI
>> diff --git a/drivers/platform/x86/Makefile
>> b/drivers/platform/x86/Makefile
>> index 3747b1f07cf1..222e2e88ccb8 100644
>> --- a/drivers/platform/x86/Makefile
>> +++ b/drivers/platform/x86/Makefile
>> @@ -83,6 +83,7 @@ obj-$(CONFIG_SAMSUNG_Q10)	+= samsung-q10.o
>>  obj-$(CONFIG_APPLE_GMUX)	+= apple-gmux.o
>>  obj-$(CONFIG_INTEL_RST)		+= intel-rst.o
>>  obj-$(CONFIG_INTEL_SMARTCONNECT)	+= intel-smartconnect.o
>> +obj-$(CONFIG_ACPI_CHROMEOS)	+= chromeos_acpi.o
>>  
>>  obj-$(CONFIG_ALIENWARE_WMI)	+= alienware-wmi.o
>>  obj-$(CONFIG_INTEL_PMC_IPC)	+= intel_pmc_ipc.o
>> diff --git a/drivers/platform/x86/chromeos_acpi.c
>> b/drivers/platform/x86/chromeos_acpi.c
>> new file mode 100644
>> index 000000000000..4d9addee2473
>> --- /dev/null
>> +++ b/drivers/platform/x86/chromeos_acpi.c
>> @@ -0,0 +1,489 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * ChromeOS specific ACPI extensions
>> + *
>> + * Copyright 2011 Google, Inc.
>> + * Copyright 2020 Google LLC
>> + *
>> + * This file is a rework and part of the code is ported from
>> + * drivers/platform/x86/chromeos_acpi.c of the chromeos-3.18 kernel
>> and
>> + * was originally written by Vadim Bendebury <vbendeb@...omium.org>.
>> + *
>> + * This driver attaches to the ChromeOS ACPI device and then exports
>> the
>> + * values reported by the ACPI in a sysfs directory. All values are
>> + * presented in the string form (numbers as decimal values) and can
>> be
>> + * accessed as the contents of the appropriate read only files in
>> the
>> + * sysfs directory tree originating in
>> /sys/devices/platform/chromeos_acpi.
>> + */
>> +
>> +#include <linux/acpi.h>
>> +#include <linux/kernel.h>
>> +#include <linux/list.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +
>> +/*
>> + * ACPI method name for MLST; the response for this method is a
>> package of
>> + * strings listing the methods which should be reflected in sysfs.
>> + */
>> +#define MLST "MLST"
>> +
>> +/*
>> + * The default list of methods the ChromeOS ACPI device is supposed
>> to export,
>> + * if the MLST method is not present or is poorly formed.  The MLST
>> method
>> + * itself is included, to aid in debugging.
>> + */
>> +static char *chromeos_acpi_default_methods[] = {
>> +	"CHSW", "HWID", "BINF", "GPIO", "CHNV", "FWID", "FRID", MLST
>> +};
>> +
>> +/*
>> + * Representation of a single sysfs attribute. In addition to the
>> standard
>> + * bin_attribute structure has a list of these structures (to keep
>> track for
>> + * de-allocation when removing the driver) and a pointer to the
>> actual
>> + * attribute name and value, reported when accessing the appropriate
>> sysfs
>> + * file.
>> + */
>> +struct chromeos_acpi_attribute {
>> +	struct bin_attribute bin_attr;
>> +	struct list_head list;
>> +	char *name;
>> +	char *data;
>> +};
>> +
>> +/*
>> + * Representation of a sysfs attribute group (a sub directory in the
>> device's
>> + * sysfs directory). In addition to the standard structure has lists
>> to allow
>> + * to keep track of the allocated structures.
>> + */
>> +struct chromeos_acpi_attribute_group {
>> +	struct list_head attribs;
>> +	struct list_head list;
>> +	struct kobject *kobj;	/* chromeos_acpi/name directory */
>> +	char *name;
>> +};
>> +
>> +/*
>> + * This is the main structure, we use it to store data and adds
>> links pointing
>> + * at lists of allocated attributes and attribute groups.
>> + */
>> +struct chromeos_acpi_dev {
>> +	struct platform_device *pdev;
>> +
>> +	struct chromeos_acpi_attribute_group root;
>> +	struct list_head groups;
>> +};
>> +
>> +static struct chromeos_acpi_dev chromeos_acpi;
>> +
>> +static ssize_t chromeos_acpi_read_bin_attribute(struct file *filp,
>> +						struct kobject *kobj,
>> +						struct bin_attribute
>> *bin_attr,
>> +						char *buffer, loff_t
>> pos,
>> +						size_t count)
>> +{
>> +	struct chromeos_acpi_attribute *info = bin_attr->private;
>> +
>> +	return memory_read_from_buffer(buffer, count, &pos, info->data,
>> +				       info->bin_attr.size);
>> +}
>> +
>> +static char *chromeos_acpi_alloc_name(char *name, int count, int
>> index)
>> +{
>> +	char *str;
>> +
>> +	if (count == 1)
>> +		str = kstrdup(name, GFP_KERNEL);
>> +	else
>> +		str = kasprintf(GFP_KERNEL, "%s.%d", name, index);
>> +
>> +	return str;
>> +}
>> +
>> +static int
>> +chromeos_acpi_add_attr(struct chromeos_acpi_attribute_group *aag,
>> +		       union acpi_object *element, char *name,
>> +		       int count, int index)
>> +{
>> +	struct chromeos_acpi_attribute *info;
>> +	char buffer[24]; /* enough to store a u64 and "\n\0" */
>> +	int length;
>> +	int ret;
>> +
>> +	info = kzalloc(sizeof(*info), GFP_KERNEL);
>> +	if (!info)
>> +		return -ENOMEM;
>> +
>> +	info->name = chromeos_acpi_alloc_name(name, count, index);
>> +	if (!info->name) {
>> +		ret = -ENOMEM;
>> +		goto free_attribute;
>> +	}
>> +
>> +	sysfs_bin_attr_init(&info->bin_attr);
>> +	info->bin_attr.attr.name = info->name;
>> +	info->bin_attr.attr.mode = 0444;
>> +
>> +	switch (element->type) {
>> +	case ACPI_TYPE_BUFFER:
>> +		length = element->buffer.length;
>> +		info->data = kmemdup(element->buffer.pointer,
>> +				     length, GFP_KERNEL);
>> +		break;
>> +	case ACPI_TYPE_INTEGER:
>> +		length = snprintf(buffer, sizeof(buffer), "%d",
>> +				  (int)element->integer.value);
>> +		info->data = kmemdup(buffer, length, GFP_KERNEL);
>> +		break;
>> +	case ACPI_TYPE_STRING:
>> +		length = element->string.length + 1;
>> +		info->data = kstrdup(element->string.pointer,
>> GFP_KERNEL);
>> +		break;
>> +	default:
>> +		ret = -EINVAL;
>> +		goto free_attr_name;
>> +	}
>> +
>> +	if (!info->data) {
>> +		ret = -ENOMEM;
>> +		goto free_attr_name;
>> +	}
>> +
>> +	info->bin_attr.size = length;
>> +	info->bin_attr.read = chromeos_acpi_read_bin_attribute;
>> +	info->bin_attr.private = info;
>> +
>> +	INIT_LIST_HEAD(&info->list);
>> +
>> +	ret = sysfs_create_bin_file(aag->kobj, &info->bin_attr);
>> +	if (ret)
>> +		goto free_attr_data;
>> +
>> +	list_add(&info->list, &aag->attribs);
>> +
>> +	return 0;
>> +
>> +free_attr_data:
>> +	kfree(info->data);
>> +free_attr_name:
>> +	kfree(info->name);
>> +free_attribute:
>> +	kfree(info);
>> +	return ret;
>> +}
>> +
>> +static void
>> +chromeos_acpi_remove_attribs(struct chromeos_acpi_attribute_group
>> *aag)
>> +{
>> +	struct chromeos_acpi_attribute *attr, *tmp_attr;
>> +
>> +	list_for_each_entry_safe(attr, tmp_attr, &aag->attribs, list) {
>> +		sysfs_remove_bin_file(aag->kobj, &attr->bin_attr);
>> +		kfree(attr->name);
>> +		kfree(attr->data);
>> +		kfree(attr);
>> +	}
>> +}
>> +
>> +/**
>> + * chromeos_acpi_add_group() - Create a sysfs group including
>> attributes
>> + *			       representing a nested ACPI package.
>> + *
>> + * @obj: Package contents as returned by ACPI.
>> + * @name: Name of the group.
>> + * @num_attrs: Number of attributes of this package.
>> + * @index: Index number of this particular group.
>> + *
>> + * The created group is called @name in case there is a single
>> instance, or
>> + * @name.@...ex otherwise.
>> + *
>> + * All group and attribute storage allocations are included in the
>> lists for
>> + * tracking of allocated memory.
>> + *
>> + * Return: 0 on success, negative errno on failure.
>> + */
>> +static int chromeos_acpi_add_group(union acpi_object *obj, char
>> *name,
>> +				   int num_attrs, int index)
>> +{
>> +	struct device *dev = &chromeos_acpi.pdev->dev;
>> +	struct chromeos_acpi_attribute_group *aag;
>> +	union acpi_object *element;
>> +	int i, count, ret;
>> +
>> +	aag = kzalloc(sizeof(*aag), GFP_KERNEL);
>> +	if (!aag)
>> +		return -ENOMEM;
>> +
>> +	aag->name = chromeos_acpi_alloc_name(name, num_attrs, index);
>> +	if (!aag->name) {
>> +		ret = -ENOMEM;
>> +		goto free_group;
>> +	}
>> +
>> +	aag->kobj = kobject_create_and_add(aag->name, &dev->kobj);
>> +	if (!aag->kobj) {
>> +		ret = -EINVAL;
>> +		goto free_group_name;
>> +	}
>> +
>> +	INIT_LIST_HEAD(&aag->attribs);
>> +	INIT_LIST_HEAD(&aag->list);
>> +
>> +	count = obj->package.count;
>> +	element = obj->package.elements;
>> +	for (i = 0; i < count; i++, element++) {
>> +		ret = chromeos_acpi_add_attr(aag, element, name, count,
>> i);
>> +		if (ret)
>> +			goto free_group_attr;
>> +	}
>> +
>> +	list_add(&aag->list, &chromeos_acpi.groups);
>> +
>> +	return 0;
>> +
>> +free_group_attr:
>> +	chromeos_acpi_remove_attribs(aag);
>> +	kobject_put(aag->kobj);
>> +free_group_name:
>> +	kfree(aag->name);
>> +free_group:
>> +	kfree(aag);
>> +	return ret;
>> +}
>> +
>> +static void chromeos_acpi_remove_groups(void)
>> +{
>> +	struct chromeos_acpi_attribute_group *aag, *tmp_aag;
>> +
>> +	list_for_each_entry_safe(aag, tmp_aag, &chromeos_acpi.groups,
>> list) {
>> +		chromeos_acpi_remove_attribs(aag);
>> +		kfree(aag->name);
>> +		kobject_put(aag->kobj);
>> +		kfree(aag);
>> +	}
>> +}
>> +
>> +/**
>> + * chromeos_acpi_handle_package() - Create sysfs group including
>> attributes
>> + *				    representing an ACPI package.
>> + *
>> + * @obj: Package contents as returned by ACPI.
>> + * @name: Name of the group.
>> + *
>> + * Scalar objects included in the package get sysfs attributes
>> created for
>> + * them. Nested packages are passed to a function creating a sysfs
>> group per
>> + * package.
>> + *
>> + * Return: 0 on success, negative errno on failure.
>> + */
>> +static int chromeos_acpi_handle_package(union acpi_object *obj, char
>> *name)
>> +{
>> +	struct device *dev = &chromeos_acpi.pdev->dev;
>> +	int count = obj->package.count;
>> +	union acpi_object *element;
>> +	int i, ret = 0;
>> +
>> +	element = obj->package.elements;
>> +	for (i = 0; i < count; i++, element++) {
>> +		if (element->type == ACPI_TYPE_BUFFER ||
>> +		    element->type == ACPI_TYPE_STRING ||
>> +		    element->type == ACPI_TYPE_INTEGER)
>> +			/* Create a single attribute in the root
>> directory */
>> +			ret =
>> chromeos_acpi_add_attr(&chromeos_acpi.root,
>> +						     element, name,
>> +						     count, i);
>> +		else if (element->type == ACPI_TYPE_PACKAGE)
>> +			/* Create a group of attributes */
>> +			ret = chromeos_acpi_add_group(element, name,
>> +						      count, i);
>> +		else
>> +			ret = -EINVAL;
>> +		if (ret)
>> +			dev_err(dev,
>> +				"failed to create group attributes
>> (%d)\n",
>> +				ret);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +/**
>> + * chromeos_acpi_add_method() - Evaluate an ACPI method and create
>> sysfs
>> + *				attributes.
>> + *
>> + * @adev: ACPI device
>> + * @name: Name of the method to evaluate
>> + *
>> + * Return: 0 on success, non-zero on failure
>> + */
>> +static int chromeos_acpi_add_method(struct acpi_device *adev, char
>> *name)
>> +{
>> +	struct device *dev = &chromeos_acpi.pdev->dev;
>> +	struct acpi_buffer output;
>> +	union acpi_object *obj;
>> +	acpi_status status;
>> +	int ret = 0;
>> +
>> +	output.length = ACPI_ALLOCATE_BUFFER;
>> +
>> +	status = acpi_evaluate_object(adev->handle, name, NULL,
>> &output);
>> +	if (ACPI_FAILURE(status)) {
>> +		dev_err(dev, "failed to retrieve %s (%d)\n", name,
>> status);
>> +		return status;
>> +	}
>> +
>> +	obj = output.pointer;
>> +	if (obj->type == ACPI_TYPE_PACKAGE)
>> +		ret = chromeos_acpi_handle_package(obj, name);
>> +
>> +	kfree(output.pointer);
>> +
>> +	return ret;
>> +}
>> +
>> +/**
>> + * chromeos_acpi_process_mlst() - Evaluate the MLST method and add
>> methods
>> + *				  listed in the response.
>> + *
>> + * @adev: ACPI device
>> + *
>> + * Returns: 0 if successful, non-zero if error.
>> + */
>> +static int chromeos_acpi_process_mlst(struct acpi_device *adev)
>> +{
>> +	char name[ACPI_NAMESEG_SIZE + 1];
>> +	union acpi_object *element, *obj;
>> +	struct acpi_buffer output;
>> +	acpi_status status;
>> +	int ret = 0;
>> +	int size;
>> +	int i;
>> +
>> +	output.length = ACPI_ALLOCATE_BUFFER;
>> +	status = acpi_evaluate_object(adev->handle, MLST, NULL,
>> +				      &output);
>> +	if (ACPI_FAILURE(status))
>> +		return status;
>> +
>> +	obj = output.pointer;
>> +	if (obj->type != ACPI_TYPE_PACKAGE) {
>> +		ret = -EINVAL;
>> +		goto free_acpi_buffer;
>> +	}
>> +
>> +	element = obj->package.elements;
>> +	for (i = 0; i < obj->package.count; i++, element++) {
>> +		if (element->type == ACPI_TYPE_STRING) {
>> +			size = min(element->string.length + 1,
>> +				   (u32)ACPI_NAMESEG_SIZE + 1);
>> +			strlcpy(name, element->string.pointer, size);
>> +			ret = chromeos_acpi_add_method(adev, name);
>> +			if (ret) {
>> +				chromeos_acpi_remove_groups();
>> +				break;
>> +			}
>> +		}
>> +	}
>> +
>> +free_acpi_buffer:
>> +	kfree(output.pointer);
>> +
>> +	return ret;
>> +}
>> +
>> +static int chromeos_acpi_device_add(struct acpi_device *adev)
>> +{
>> +	struct chromeos_acpi_attribute_group *aag =
>> &chromeos_acpi.root;
>> +	struct device *dev = &chromeos_acpi.pdev->dev;
>> +	int i, ret;
>> +
>> +	INIT_LIST_HEAD(&aag->attribs);
>> +	INIT_LIST_HEAD(&aag->list);
>> +
>> +	aag->kobj = &dev->kobj;
>> +
>> +	/*
>> +	 * Attempt to add methods by querying the device's MLST method
>> +	 * for the list of methods.
>> +	 */
>> +	if (!chromeos_acpi_process_mlst(adev))
>> +		return 0;
>> +
>> +	dev_info(dev, "falling back to default list of methods\n");
>> +
>> +	for (i = 0; i < ARRAY_SIZE(chromeos_acpi_default_methods); i++)
>> {
>> +		ret = chromeos_acpi_add_method(adev,
>> +					     chromeos_acpi_default_meth
>> ods[i]);
>> +		if (ret) {
>> +			dev_err(dev, "failed to add default methods
>> (%d)\n",
>> +				ret);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int chromeos_acpi_device_remove(struct acpi_device *adev)
>> +{
>> +	/* Remove dinamically allocated sysfs groups and attributes */
>> +	chromeos_acpi_remove_groups();
>> +	/* Remove attributes from the root group */
>> +	chromeos_acpi_remove_attribs(&chromeos_acpi.root);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct acpi_device_id chromeos_device_ids[] = {
>> +	{ "GGL0001", 0 },
>> +	{ }
>> +};
>> +MODULE_DEVICE_TABLE(acpi, chromeos_device_ids);
>> +
>> +static struct acpi_driver chromeos_acpi_driver = {
>> +	.name = "ChromeOS ACPI driver",
>> +	.class = "chromeos-acpi",
>> +	.ids = chromeos_device_ids,
>> +	.ops = {
>> +		.add = chromeos_acpi_device_add,
>> +		.remove = chromeos_acpi_device_remove,
>> +	},
>> +	.owner = THIS_MODULE,
>> +};
>> +
>> +static int __init chromeos_acpi_init(void)
>> +{
>> +	int ret;
>> +
>> +	chromeos_acpi.pdev =
>> platform_device_register_simple("chromeos_acpi",
>> +						PLATFORM_DEVID_NONE,
>> NULL, 0);
>> +	if (IS_ERR(chromeos_acpi.pdev)) {
>> +		pr_err("unable to register chromeos_acpi platform
>> device\n");
>> +		return PTR_ERR(chromeos_acpi.pdev);
>> +	}
>> +
>> +	INIT_LIST_HEAD(&chromeos_acpi.groups);
>> +
>> +	ret = acpi_bus_register_driver(&chromeos_acpi_driver);
>> +	if (ret < 0) {
>> +		pr_err("failed to register chromeos_acpi driver
>> (%d)\n", ret);
>> +		platform_device_unregister(chromeos_acpi.pdev);
>> +		chromeos_acpi.pdev = NULL;
>> +		return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void __exit chromeos_acpi_exit(void)
>> +{
>> +	acpi_bus_unregister_driver(&chromeos_acpi_driver);
>> +	platform_device_unregister(chromeos_acpi.pdev);
>> +}
>> +
>> +module_init(chromeos_acpi_init);
>> +module_exit(chromeos_acpi_exit);
>> +
>> +MODULE_AUTHOR("Enric Balletbo i Serra <enric.balletbo@...labora.com>
>> ");
>> +MODULE_LICENSE("GPL");
>> +MODULE_DESCRIPTION("ChromeOS specific ACPI extensions");
> 
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ