mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
Power management and ACPI updates for 3.10-rc1
- ARM big.LITTLE cpufreq driver from Viresh Kumar.
- exynos5440 cpufreq driver from Amit Daniel Kachhap.
- cpufreq core cleanup and code consolidation from Viresh Kumar and
Stratos Karafotis.
- cpufreq scalability improvement from Nathan Zimmer.
- AMD "frequency sensitivity feedback" powersave bias for the ondemand
cpufreq governor from Jacob Shin.
- cpuidle code consolidation and cleanups from Daniel Lezcano.
- ARM OMAP cpuidle fixes from Santosh Shilimkar and Daniel Lezcano.
- ACPICA fixes and other improvements from Bob Moore, Jung-uk Kim,
Lv Zheng, Yinghai Lu, Tang Chen, Colin Ian King, and Linn Crosetto.
- ACPI core updates related to hotplug from Toshi Kani, Paul Bolle,
Yasuaki Ishimatsu, and Rafael J. Wysocki.
- Intel Lynxpoint LPSS (Low-Power Subsystem) support improvements
from Rafael J. Wysocki and Andy Shevchenko.
/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
iQIcBAABAgAGBQJRf8M8AAoJEKhOf7ml8uNsud4P/3cabXP5lDipzibRrpOiONse
puuvIdhtNdMRMc3t1oSDjNH/w/JA51Gc+ICGFAORiyVmqxBc85mpT6J5ibqV7hNd
pCqbKJceoB5PajHZSx22e4wG9O7YN1k3r80p38IfFzA+Ct0KNSuE0ixMEfHKYjiq
p5pXswk6TY3gtBReH9agrafHqDtXw4IMTE0asMuJ+BorPW7vQeiNlrkuA+0qmDuu
26O0Pm2TVkx1ryfTjdM9zSZ9X2G4JuM8rm1/VFZWQJTExwlv3bA2Za1nvQNJlJ99
6JZ0JXfAehcEW2Ye0sqsZ8HSEabDVHM29QvvOszJ5RpBXERiOCHOkhvFleCoTpn0
Xq0rtXPrLMH1G28Ej+cxmsAjfzOLV2Byg30CAoI/GCLuQ+xh+VMCpuNYQuld25CG
9rtYd0fWESeYsAebhDcX0E3xyzJtbrHtOb9PyGwNkbAJ8YQfhVSMCOPi2SX2wa+Q
qXLXi2VaHvjBSUKcAv5BmM+Ya57Be+88D0LxbgXbUeOnYefUK1ljldKDDshkMjgG
P4LPdm4JpoB5ncXSOO1Dz9w9QnNcFexSUySd/TtKLNMha1vEHV8ISzNPYY+9IdXf
XN0VZbFnUDzdj+Fwna7zyFb1cGihDYJKAtpXvRd8Y6RGUxKx9uGLAFJZw/xZB/cR
KZKuML5O8MgJuef37F38
=H/se
-----END PGP SIGNATURE-----
Merge tag 'pm+acpi-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management and ACPI updates from Rafael J Wysocki:
- ARM big.LITTLE cpufreq driver from Viresh Kumar.
- exynos5440 cpufreq driver from Amit Daniel Kachhap.
- cpufreq core cleanup and code consolidation from Viresh Kumar and
Stratos Karafotis.
- cpufreq scalability improvement from Nathan Zimmer.
- AMD "frequency sensitivity feedback" powersave bias for the ondemand
cpufreq governor from Jacob Shin.
- cpuidle code consolidation and cleanups from Daniel Lezcano.
- ARM OMAP cpuidle fixes from Santosh Shilimkar and Daniel Lezcano.
- ACPICA fixes and other improvements from Bob Moore, Jung-uk Kim, Lv
Zheng, Yinghai Lu, Tang Chen, Colin Ian King, and Linn Crosetto.
- ACPI core updates related to hotplug from Toshi Kani, Paul Bolle,
Yasuaki Ishimatsu, and Rafael J Wysocki.
- Intel Lynxpoint LPSS (Low-Power Subsystem) support improvements from
Rafael J Wysocki and Andy Shevchenko.
* tag 'pm+acpi-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (192 commits)
cpufreq: Revert incorrect commit 5800043
cpufreq: MAINTAINERS: Add co-maintainer
cpuidle: add maintainer entry
ACPI / thermal: do not always return THERMAL_TREND_RAISING for active trip points
ARM: s3c64xx: cpuidle: use init/exit common routine
cpufreq: pxa2xx: initialize variables
ACPI: video: correct acpi_video_bus_add error processing
SH: cpuidle: use init/exit common routine
ARM: S5pv210: compiling issue, ARM_S5PV210_CPUFREQ needs CONFIG_CPU_FREQ_TABLE=y
ACPI: Fix wrong parameter passed to memblock_reserve
cpuidle: fix comment format
pnp: use %*phC to dump small buffers
isapnp: remove debug leftovers
ARM: imx: cpuidle: use init/exit common routine
ARM: davinci: cpuidle: use init/exit common routine
ARM: kirkwood: cpuidle: use init/exit common routine
ARM: calxeda: cpuidle: use init/exit common routine
ARM: tegra: cpuidle: use init/exit common routine for tegra3
ARM: tegra: cpuidle: use init/exit common routine for tegra2
ARM: OMAP4: cpuidle: use init/exit common routine
...
This commit is contained in:
commit
3ed1c478ef
253 changed files with 6938 additions and 4145 deletions
|
|
@ -298,14 +298,6 @@ config ACPI_DEBUG
|
|||
Documentation/kernel-parameters.txt to control the type and
|
||||
amount of debug output.
|
||||
|
||||
config ACPI_DEBUG_FUNC_TRACE
|
||||
bool "Additionally enable ACPI function tracing"
|
||||
default n
|
||||
depends on ACPI_DEBUG
|
||||
help
|
||||
ACPI Debug Statements slow down ACPI processing. Function trace
|
||||
is about half of the penalty and is rarely useful.
|
||||
|
||||
config ACPI_PCI_SLOT
|
||||
bool "PCI slot detection driver"
|
||||
depends on SYSFS
|
||||
|
|
@ -334,7 +326,7 @@ config X86_PM_TIMER
|
|||
|
||||
config ACPI_CONTAINER
|
||||
bool "Container and Module Devices"
|
||||
default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
|
||||
default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU)
|
||||
help
|
||||
This driver supports ACPI Container and Module devices (IDs
|
||||
ACPI0004, PNP0A05, and PNP0A06).
|
||||
|
|
@ -345,9 +337,8 @@ config ACPI_CONTAINER
|
|||
the module will be called container.
|
||||
|
||||
config ACPI_HOTPLUG_MEMORY
|
||||
tristate "Memory Hotplug"
|
||||
bool "Memory Hotplug"
|
||||
depends on MEMORY_HOTPLUG
|
||||
default n
|
||||
help
|
||||
This driver supports ACPI memory hotplug. The driver
|
||||
fields notifications on ACPI memory devices (PNP0C80),
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ acpi-y += ec.o
|
|||
acpi-$(CONFIG_ACPI_DOCK) += dock.o
|
||||
acpi-y += pci_root.o pci_link.o pci_irq.o
|
||||
acpi-y += csrt.o
|
||||
acpi-$(CONFIG_X86_INTEL_LPSS) += acpi_lpss.o
|
||||
acpi-y += acpi_platform.o
|
||||
acpi-y += power.o
|
||||
acpi-y += event.o
|
||||
|
|
|
|||
292
drivers/acpi/acpi_lpss.c
Normal file
292
drivers/acpi/acpi_lpss.c
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* ACPI support for Intel Lynxpoint LPSS.
|
||||
*
|
||||
* Copyright (C) 2013, Intel Corporation
|
||||
* Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
* Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/clk-lpss.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
ACPI_MODULE_NAME("acpi_lpss");
|
||||
|
||||
#define LPSS_CLK_SIZE 0x04
|
||||
#define LPSS_LTR_SIZE 0x18
|
||||
|
||||
/* Offsets relative to LPSS_PRIVATE_OFFSET */
|
||||
#define LPSS_GENERAL 0x08
|
||||
#define LPSS_GENERAL_LTR_MODE_SW BIT(2)
|
||||
#define LPSS_SW_LTR 0x10
|
||||
#define LPSS_AUTO_LTR 0x14
|
||||
|
||||
struct lpss_device_desc {
|
||||
bool clk_required;
|
||||
const char *clk_parent;
|
||||
bool ltr_required;
|
||||
unsigned int prv_offset;
|
||||
};
|
||||
|
||||
struct lpss_private_data {
|
||||
void __iomem *mmio_base;
|
||||
resource_size_t mmio_size;
|
||||
struct clk *clk;
|
||||
const struct lpss_device_desc *dev_desc;
|
||||
};
|
||||
|
||||
static struct lpss_device_desc lpt_dev_desc = {
|
||||
.clk_required = true,
|
||||
.clk_parent = "lpss_clk",
|
||||
.prv_offset = 0x800,
|
||||
.ltr_required = true,
|
||||
};
|
||||
|
||||
static struct lpss_device_desc lpt_sdio_dev_desc = {
|
||||
.prv_offset = 0x1000,
|
||||
.ltr_required = true,
|
||||
};
|
||||
|
||||
static const struct acpi_device_id acpi_lpss_device_ids[] = {
|
||||
/* Lynxpoint LPSS devices */
|
||||
{ "INT33C0", (unsigned long)&lpt_dev_desc },
|
||||
{ "INT33C1", (unsigned long)&lpt_dev_desc },
|
||||
{ "INT33C2", (unsigned long)&lpt_dev_desc },
|
||||
{ "INT33C3", (unsigned long)&lpt_dev_desc },
|
||||
{ "INT33C4", (unsigned long)&lpt_dev_desc },
|
||||
{ "INT33C5", (unsigned long)&lpt_dev_desc },
|
||||
{ "INT33C6", (unsigned long)&lpt_sdio_dev_desc },
|
||||
{ "INT33C7", },
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
static int is_memory(struct acpi_resource *res, void *not_used)
|
||||
{
|
||||
struct resource r;
|
||||
return !acpi_dev_resource_memory(res, &r);
|
||||
}
|
||||
|
||||
/* LPSS main clock device. */
|
||||
static struct platform_device *lpss_clk_dev;
|
||||
|
||||
static inline void lpt_register_clock_device(void)
|
||||
{
|
||||
lpss_clk_dev = platform_device_register_simple("clk-lpt", -1, NULL, 0);
|
||||
}
|
||||
|
||||
static int register_device_clock(struct acpi_device *adev,
|
||||
struct lpss_private_data *pdata)
|
||||
{
|
||||
const struct lpss_device_desc *dev_desc = pdata->dev_desc;
|
||||
|
||||
if (!lpss_clk_dev)
|
||||
lpt_register_clock_device();
|
||||
|
||||
if (!dev_desc->clk_parent || !pdata->mmio_base
|
||||
|| pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE)
|
||||
return -ENODATA;
|
||||
|
||||
pdata->clk = clk_register_gate(NULL, dev_name(&adev->dev),
|
||||
dev_desc->clk_parent, 0,
|
||||
pdata->mmio_base + dev_desc->prv_offset,
|
||||
0, 0, NULL);
|
||||
if (IS_ERR(pdata->clk))
|
||||
return PTR_ERR(pdata->clk);
|
||||
|
||||
clk_register_clkdev(pdata->clk, NULL, dev_name(&adev->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_lpss_create_device(struct acpi_device *adev,
|
||||
const struct acpi_device_id *id)
|
||||
{
|
||||
struct lpss_device_desc *dev_desc;
|
||||
struct lpss_private_data *pdata;
|
||||
struct resource_list_entry *rentry;
|
||||
struct list_head resource_list;
|
||||
int ret;
|
||||
|
||||
dev_desc = (struct lpss_device_desc *)id->driver_data;
|
||||
if (!dev_desc)
|
||||
return acpi_create_platform_device(adev, id);
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&resource_list);
|
||||
ret = acpi_dev_get_resources(adev, &resource_list, is_memory, NULL);
|
||||
if (ret < 0)
|
||||
goto err_out;
|
||||
|
||||
list_for_each_entry(rentry, &resource_list, node)
|
||||
if (resource_type(&rentry->res) == IORESOURCE_MEM) {
|
||||
pdata->mmio_size = resource_size(&rentry->res);
|
||||
pdata->mmio_base = ioremap(rentry->res.start,
|
||||
pdata->mmio_size);
|
||||
pdata->dev_desc = dev_desc;
|
||||
break;
|
||||
}
|
||||
|
||||
acpi_dev_free_resource_list(&resource_list);
|
||||
|
||||
if (dev_desc->clk_required) {
|
||||
ret = register_device_clock(adev, pdata);
|
||||
if (ret) {
|
||||
/*
|
||||
* Skip the device, but don't terminate the namespace
|
||||
* scan.
|
||||
*/
|
||||
kfree(pdata);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
adev->driver_data = pdata;
|
||||
ret = acpi_create_platform_device(adev, id);
|
||||
if (ret > 0)
|
||||
return ret;
|
||||
|
||||
adev->driver_data = NULL;
|
||||
|
||||
err_out:
|
||||
kfree(pdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
struct lpss_private_data *pdata;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ret = acpi_bus_get_device(ACPI_HANDLE(dev), &adev);
|
||||
if (WARN_ON(ret))
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&dev->power.lock, flags);
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
pdata = acpi_driver_data(adev);
|
||||
if (WARN_ON(!pdata || !pdata->mmio_base)) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
*val = readl(pdata->mmio_base + pdata->dev_desc->prv_offset + reg);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&dev->power.lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t lpss_ltr_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
u32 ltr_value = 0;
|
||||
unsigned int reg;
|
||||
int ret;
|
||||
|
||||
reg = strcmp(attr->attr.name, "auto_ltr") ? LPSS_SW_LTR : LPSS_AUTO_LTR;
|
||||
ret = lpss_reg_read(dev, reg, <r_value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%08x\n", ltr_value);
|
||||
}
|
||||
|
||||
static ssize_t lpss_ltr_mode_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
u32 ltr_mode = 0;
|
||||
char *outstr;
|
||||
int ret;
|
||||
|
||||
ret = lpss_reg_read(dev, LPSS_GENERAL, <r_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
outstr = (ltr_mode & LPSS_GENERAL_LTR_MODE_SW) ? "sw" : "auto";
|
||||
return sprintf(buf, "%s\n", outstr);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(auto_ltr, S_IRUSR, lpss_ltr_show, NULL);
|
||||
static DEVICE_ATTR(sw_ltr, S_IRUSR, lpss_ltr_show, NULL);
|
||||
static DEVICE_ATTR(ltr_mode, S_IRUSR, lpss_ltr_mode_show, NULL);
|
||||
|
||||
static struct attribute *lpss_attrs[] = {
|
||||
&dev_attr_auto_ltr.attr,
|
||||
&dev_attr_sw_ltr.attr,
|
||||
&dev_attr_ltr_mode.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group lpss_attr_group = {
|
||||
.attrs = lpss_attrs,
|
||||
.name = "lpss_ltr",
|
||||
};
|
||||
|
||||
static int acpi_lpss_platform_notify(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(data);
|
||||
struct lpss_private_data *pdata;
|
||||
struct acpi_device *adev;
|
||||
const struct acpi_device_id *id;
|
||||
int ret = 0;
|
||||
|
||||
id = acpi_match_device(acpi_lpss_device_ids, &pdev->dev);
|
||||
if (!id || !id->driver_data)
|
||||
return 0;
|
||||
|
||||
if (acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
|
||||
return 0;
|
||||
|
||||
pdata = acpi_driver_data(adev);
|
||||
if (!pdata || !pdata->mmio_base || !pdata->dev_desc->ltr_required)
|
||||
return 0;
|
||||
|
||||
if (pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) {
|
||||
dev_err(&pdev->dev, "MMIO size insufficient to access LTR\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (action == BUS_NOTIFY_ADD_DEVICE)
|
||||
ret = sysfs_create_group(&pdev->dev.kobj, &lpss_attr_group);
|
||||
else if (action == BUS_NOTIFY_DEL_DEVICE)
|
||||
sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct notifier_block acpi_lpss_nb = {
|
||||
.notifier_call = acpi_lpss_platform_notify,
|
||||
};
|
||||
|
||||
static struct acpi_scan_handler lpss_handler = {
|
||||
.ids = acpi_lpss_device_ids,
|
||||
.attach = acpi_lpss_create_device,
|
||||
};
|
||||
|
||||
void __init acpi_lpss_init(void)
|
||||
{
|
||||
if (!lpt_clk_init()) {
|
||||
bus_register_notifier(&platform_bus_type, &acpi_lpss_nb);
|
||||
acpi_scan_add_handler(&lpss_handler);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com>
|
||||
* Copyright (C) 2004, 2013 Intel Corporation
|
||||
* Author: Naveen B S <naveen.b.s@intel.com>
|
||||
* Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
|
|
@ -25,14 +27,10 @@
|
|||
* ranges.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/memory_hotplug.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <linux/memory_hotplug.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define ACPI_MEMORY_DEVICE_CLASS "memory"
|
||||
#define ACPI_MEMORY_DEVICE_HID "PNP0C80"
|
||||
|
|
@ -44,32 +42,28 @@
|
|||
#define PREFIX "ACPI:memory_hp:"
|
||||
|
||||
ACPI_MODULE_NAME("acpi_memhotplug");
|
||||
MODULE_AUTHOR("Naveen B S <[email protected]>");
|
||||
MODULE_DESCRIPTION("Hotplug Mem Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* Memory Device States */
|
||||
#define MEMORY_INVALID_STATE 0
|
||||
#define MEMORY_POWER_ON_STATE 1
|
||||
#define MEMORY_POWER_OFF_STATE 2
|
||||
|
||||
static int acpi_memory_device_add(struct acpi_device *device);
|
||||
static int acpi_memory_device_remove(struct acpi_device *device);
|
||||
static int acpi_memory_device_add(struct acpi_device *device,
|
||||
const struct acpi_device_id *not_used);
|
||||
static void acpi_memory_device_remove(struct acpi_device *device);
|
||||
|
||||
static const struct acpi_device_id memory_device_ids[] = {
|
||||
{ACPI_MEMORY_DEVICE_HID, 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, memory_device_ids);
|
||||
|
||||
static struct acpi_driver acpi_memory_device_driver = {
|
||||
.name = "acpi_memhotplug",
|
||||
.class = ACPI_MEMORY_DEVICE_CLASS,
|
||||
static struct acpi_scan_handler memory_device_handler = {
|
||||
.ids = memory_device_ids,
|
||||
.ops = {
|
||||
.add = acpi_memory_device_add,
|
||||
.remove = acpi_memory_device_remove,
|
||||
},
|
||||
.attach = acpi_memory_device_add,
|
||||
.detach = acpi_memory_device_remove,
|
||||
.hotplug = {
|
||||
.enabled = true,
|
||||
},
|
||||
};
|
||||
|
||||
struct acpi_memory_info {
|
||||
|
|
@ -79,7 +73,6 @@ struct acpi_memory_info {
|
|||
unsigned short caching; /* memory cache attribute */
|
||||
unsigned short write_protect; /* memory read/write attribute */
|
||||
unsigned int enabled:1;
|
||||
unsigned int failed:1;
|
||||
};
|
||||
|
||||
struct acpi_memory_device {
|
||||
|
|
@ -153,48 +146,6 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_memory_get_device(acpi_handle handle,
|
||||
struct acpi_memory_device **mem_device)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
int result = 0;
|
||||
|
||||
acpi_scan_lock_acquire();
|
||||
|
||||
acpi_bus_get_device(handle, &device);
|
||||
if (device)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Now add the notified device. This creates the acpi_device
|
||||
* and invokes .add function
|
||||
*/
|
||||
result = acpi_bus_scan(handle);
|
||||
if (result) {
|
||||
acpi_handle_warn(handle, "ACPI namespace scan failed\n");
|
||||
result = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
result = acpi_bus_get_device(handle, &device);
|
||||
if (result) {
|
||||
acpi_handle_warn(handle, "Missing device object\n");
|
||||
result = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
end:
|
||||
*mem_device = acpi_driver_data(device);
|
||||
if (!(*mem_device)) {
|
||||
dev_err(&device->dev, "driver data not found\n");
|
||||
result = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
acpi_scan_lock_release();
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
|
||||
{
|
||||
unsigned long long current_status;
|
||||
|
|
@ -249,13 +200,11 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
|
|||
* returns -EEXIST. If add_memory() returns the other error, it
|
||||
* means that this memory block is not used by the kernel.
|
||||
*/
|
||||
if (result && result != -EEXIST) {
|
||||
info->failed = 1;
|
||||
if (result && result != -EEXIST)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!result)
|
||||
info->enabled = 1;
|
||||
info->enabled = 1;
|
||||
|
||||
/*
|
||||
* Add num_enable even if add_memory() returns -EEXIST, so the
|
||||
* device is bound to this driver.
|
||||
|
|
@ -286,16 +235,8 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
|
|||
nid = acpi_get_node(mem_device->device->handle);
|
||||
|
||||
list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
|
||||
if (info->failed)
|
||||
/* The kernel does not use this memory block */
|
||||
continue;
|
||||
|
||||
if (!info->enabled)
|
||||
/*
|
||||
* The kernel uses this memory block, but it may be not
|
||||
* managed by us.
|
||||
*/
|
||||
return -EBUSY;
|
||||
continue;
|
||||
|
||||
if (nid < 0)
|
||||
nid = memory_add_physaddr_to_nid(info->start_addr);
|
||||
|
|
@ -310,95 +251,21 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct acpi_memory_device *mem_device;
|
||||
struct acpi_device *device;
|
||||
struct acpi_eject_event *ej_event = NULL;
|
||||
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
|
||||
acpi_status status;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"\nReceived BUS CHECK notification for device\n"));
|
||||
/* Fall Through */
|
||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||
if (event == ACPI_NOTIFY_DEVICE_CHECK)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"\nReceived DEVICE CHECK notification for device\n"));
|
||||
if (acpi_memory_get_device(handle, &mem_device)) {
|
||||
acpi_handle_err(handle, "Cannot find driver data\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ost_code = ACPI_OST_SC_SUCCESS;
|
||||
break;
|
||||
|
||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"\nReceived EJECT REQUEST notification for device\n"));
|
||||
|
||||
status = AE_ERROR;
|
||||
acpi_scan_lock_acquire();
|
||||
|
||||
if (acpi_bus_get_device(handle, &device)) {
|
||||
acpi_handle_err(handle, "Device doesn't exist\n");
|
||||
goto unlock;
|
||||
}
|
||||
mem_device = acpi_driver_data(device);
|
||||
if (!mem_device) {
|
||||
acpi_handle_err(handle, "Driver Data is NULL\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
|
||||
if (!ej_event) {
|
||||
pr_err(PREFIX "No memory, dropping EJECT\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
get_device(&device->dev);
|
||||
ej_event->device = device;
|
||||
ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
|
||||
/* The eject is carried out asynchronously. */
|
||||
status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
|
||||
ej_event);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
put_device(&device->dev);
|
||||
kfree(ej_event);
|
||||
}
|
||||
|
||||
unlock:
|
||||
acpi_scan_lock_release();
|
||||
if (ACPI_SUCCESS(status))
|
||||
return;
|
||||
default:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Unsupported event [0x%x]\n", event));
|
||||
|
||||
/* non-hotplug event; possibly handled by other handler */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Inform firmware that the hotplug operation has completed */
|
||||
(void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
|
||||
}
|
||||
|
||||
static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
|
||||
{
|
||||
if (!mem_device)
|
||||
return;
|
||||
|
||||
acpi_memory_free_device_resources(mem_device);
|
||||
mem_device->device->driver_data = NULL;
|
||||
kfree(mem_device);
|
||||
}
|
||||
|
||||
static int acpi_memory_device_add(struct acpi_device *device)
|
||||
static int acpi_memory_device_add(struct acpi_device *device,
|
||||
const struct acpi_device_id *not_used)
|
||||
{
|
||||
struct acpi_memory_device *mem_device;
|
||||
int result;
|
||||
struct acpi_memory_device *mem_device = NULL;
|
||||
|
||||
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
|
@ -423,147 +290,36 @@ static int acpi_memory_device_add(struct acpi_device *device)
|
|||
/* Set the device state */
|
||||
mem_device->state = MEMORY_POWER_ON_STATE;
|
||||
|
||||
pr_debug("%s\n", acpi_device_name(device));
|
||||
|
||||
if (!acpi_memory_check_device(mem_device)) {
|
||||
/* call add_memory func */
|
||||
result = acpi_memory_enable_device(mem_device);
|
||||
if (result) {
|
||||
dev_err(&device->dev,
|
||||
"Error in acpi_memory_enable_device\n");
|
||||
acpi_memory_device_free(mem_device);
|
||||
}
|
||||
result = acpi_memory_check_device(mem_device);
|
||||
if (result) {
|
||||
acpi_memory_device_free(mem_device);
|
||||
return 0;
|
||||
}
|
||||
return result;
|
||||
|
||||
result = acpi_memory_enable_device(mem_device);
|
||||
if (result) {
|
||||
dev_err(&device->dev, "acpi_memory_enable_device() error\n");
|
||||
acpi_memory_device_free(mem_device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_dbg(&device->dev, "Memory device configured by ACPI\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int acpi_memory_device_remove(struct acpi_device *device)
|
||||
static void acpi_memory_device_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_memory_device *mem_device = NULL;
|
||||
int result;
|
||||
struct acpi_memory_device *mem_device;
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
mem_device = acpi_driver_data(device);
|
||||
|
||||
result = acpi_memory_remove_memory(mem_device);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
acpi_memory_remove_memory(mem_device);
|
||||
acpi_memory_device_free(mem_device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to check for memory device
|
||||
*/
|
||||
static acpi_status is_memory_device(acpi_handle handle)
|
||||
void __init acpi_memory_hotplug_init(void)
|
||||
{
|
||||
char *hardware_id;
|
||||
acpi_status status;
|
||||
struct acpi_device_info *info;
|
||||
|
||||
status = acpi_get_object_info(handle, &info);
|
||||
if (ACPI_FAILURE(status))
|
||||
return status;
|
||||
|
||||
if (!(info->valid & ACPI_VALID_HID)) {
|
||||
kfree(info);
|
||||
return AE_ERROR;
|
||||
}
|
||||
|
||||
hardware_id = info->hardware_id.string;
|
||||
if ((hardware_id == NULL) ||
|
||||
(strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
|
||||
status = AE_ERROR;
|
||||
|
||||
kfree(info);
|
||||
return status;
|
||||
acpi_scan_add_handler_with_hotplug(&memory_device_handler, "memory");
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
acpi_memory_register_notify_handler(acpi_handle handle,
|
||||
u32 level, void *ctxt, void **retv)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
||||
status = is_memory_device(handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
return AE_OK; /* continue */
|
||||
|
||||
status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||
acpi_memory_device_notify, NULL);
|
||||
/* continue */
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
acpi_memory_deregister_notify_handler(acpi_handle handle,
|
||||
u32 level, void *ctxt, void **retv)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
||||
status = is_memory_device(handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
return AE_OK; /* continue */
|
||||
|
||||
status = acpi_remove_notify_handler(handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
acpi_memory_device_notify);
|
||||
|
||||
return AE_OK; /* continue */
|
||||
}
|
||||
|
||||
static int __init acpi_memory_device_init(void)
|
||||
{
|
||||
int result;
|
||||
acpi_status status;
|
||||
|
||||
|
||||
result = acpi_bus_register_driver(&acpi_memory_device_driver);
|
||||
|
||||
if (result < 0)
|
||||
return -ENODEV;
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
acpi_memory_register_notify_handler, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
|
||||
acpi_bus_unregister_driver(&acpi_memory_device_driver);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit acpi_memory_device_exit(void)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
||||
/*
|
||||
* Adding this to un-install notification handlers for all the device
|
||||
* handles.
|
||||
*/
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
acpi_memory_deregister_notify_handler, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
|
||||
|
||||
acpi_bus_unregister_driver(&acpi_memory_device_driver);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(acpi_memory_device_init);
|
||||
module_exit(acpi_memory_device_exit);
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ static int create_power_saving_task(void)
|
|||
ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread,
|
||||
(void *)(unsigned long)ps_tsk_num,
|
||||
"acpi_pad/%d", ps_tsk_num);
|
||||
rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0;
|
||||
rc = PTR_RET(ps_tsks[ps_tsk_num]);
|
||||
if (!rc)
|
||||
ps_tsk_num++;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -22,9 +22,6 @@
|
|||
|
||||
ACPI_MODULE_NAME("platform");
|
||||
|
||||
/* Flags for acpi_create_platform_device */
|
||||
#define ACPI_PLATFORM_CLK BIT(0)
|
||||
|
||||
/*
|
||||
* The following ACPI IDs are known to be suitable for representing as
|
||||
* platform devices.
|
||||
|
|
@ -33,33 +30,9 @@ static const struct acpi_device_id acpi_platform_device_ids[] = {
|
|||
|
||||
{ "PNP0D40" },
|
||||
|
||||
/* Haswell LPSS devices */
|
||||
{ "INT33C0", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C1", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C2", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C3", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C4", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C5", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C6", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C7", ACPI_PLATFORM_CLK },
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
static int acpi_create_platform_clks(struct acpi_device *adev)
|
||||
{
|
||||
static struct platform_device *pdev;
|
||||
|
||||
/* Create Lynxpoint LPSS clocks */
|
||||
if (!pdev && !strncmp(acpi_device_hid(adev), "INT33C", 6)) {
|
||||
pdev = platform_device_register_simple("clk-lpt", -1, NULL, 0);
|
||||
if (IS_ERR(pdev))
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_create_platform_device - Create platform device for ACPI device node
|
||||
* @adev: ACPI device node to create a platform device for.
|
||||
|
|
@ -71,10 +44,9 @@ static int acpi_create_platform_clks(struct acpi_device *adev)
|
|||
*
|
||||
* Name of the platform device will be the same as @adev's.
|
||||
*/
|
||||
static int acpi_create_platform_device(struct acpi_device *adev,
|
||||
const struct acpi_device_id *id)
|
||||
int acpi_create_platform_device(struct acpi_device *adev,
|
||||
const struct acpi_device_id *id)
|
||||
{
|
||||
unsigned long flags = id->driver_data;
|
||||
struct platform_device *pdev = NULL;
|
||||
struct acpi_device *acpi_parent;
|
||||
struct platform_device_info pdevinfo;
|
||||
|
|
@ -83,14 +55,6 @@ static int acpi_create_platform_device(struct acpi_device *adev,
|
|||
struct resource *resources;
|
||||
int count;
|
||||
|
||||
if (flags & ACPI_PLATFORM_CLK) {
|
||||
int ret = acpi_create_platform_clks(adev);
|
||||
if (ret) {
|
||||
dev_err(&adev->dev, "failed to create clocks\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the ACPI node already has a physical device attached, skip it. */
|
||||
if (adev->physical_node_count)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
|
|||
acpi-y += \
|
||||
nsaccess.o \
|
||||
nsalloc.o \
|
||||
nsconvert.o \
|
||||
nsdump.o \
|
||||
nseval.o \
|
||||
nsinit.o \
|
||||
|
|
@ -160,6 +161,7 @@ acpi-y += \
|
|||
utobject.o \
|
||||
utosi.o \
|
||||
utownerid.o \
|
||||
utpredef.o \
|
||||
utresrc.o \
|
||||
utstate.o \
|
||||
utstring.o \
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ ACPI_EXTERN u8 acpi_gbl_global_lock_pending;
|
|||
*/
|
||||
ACPI_EXTERN acpi_spinlock acpi_gbl_gpe_lock; /* For GPE data structs and registers */
|
||||
ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock; /* For ACPI H/W except GPE registers */
|
||||
ACPI_EXTERN acpi_spinlock acpi_gbl_reference_count_lock;
|
||||
|
||||
/* Mutex for _OSI support */
|
||||
|
||||
|
|
@ -413,10 +414,12 @@ ACPI_EXTERN u8 acpi_gbl_db_output_flags;
|
|||
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
|
||||
u8 ACPI_INIT_GLOBAL(acpi_gbl_ignore_noop_operator, FALSE);
|
||||
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_ignore_noop_operator, FALSE);
|
||||
|
||||
ACPI_EXTERN u8 acpi_gbl_db_opt_disasm;
|
||||
ACPI_EXTERN u8 acpi_gbl_db_opt_verbose;
|
||||
ACPI_EXTERN u8 acpi_gbl_num_external_methods;
|
||||
ACPI_EXTERN u32 acpi_gbl_resolved_external_methods;
|
||||
ACPI_EXTERN struct acpi_external_list *acpi_gbl_external_list;
|
||||
ACPI_EXTERN struct acpi_external_file *acpi_gbl_external_file_list;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -294,6 +294,8 @@ acpi_status(*acpi_internal_method) (struct acpi_walk_state * walk_state);
|
|||
#define ACPI_BTYPE_OBJECTS_AND_REFS 0x0001FFFF /* ARG or LOCAL */
|
||||
#define ACPI_BTYPE_ALL_OBJECTS 0x0000FFFF
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/*
|
||||
* Information structure for ACPI predefined names.
|
||||
* Each entry in the table contains the following items:
|
||||
|
|
@ -304,7 +306,7 @@ acpi_status(*acpi_internal_method) (struct acpi_walk_state * walk_state);
|
|||
*/
|
||||
struct acpi_name_info {
|
||||
char name[ACPI_NAME_SIZE];
|
||||
u8 param_count;
|
||||
u16 argument_list;
|
||||
u8 expected_btypes;
|
||||
};
|
||||
|
||||
|
|
@ -327,7 +329,7 @@ struct acpi_package_info {
|
|||
u8 count1;
|
||||
u8 object_type2;
|
||||
u8 count2;
|
||||
u8 reserved;
|
||||
u16 reserved;
|
||||
};
|
||||
|
||||
/* Used for ACPI_PTYPE2_FIXED */
|
||||
|
|
@ -336,6 +338,7 @@ struct acpi_package_info2 {
|
|||
u8 type;
|
||||
u8 count;
|
||||
u8 object_type[4];
|
||||
u8 reserved;
|
||||
};
|
||||
|
||||
/* Used for ACPI_PTYPE1_OPTION */
|
||||
|
|
@ -345,7 +348,7 @@ struct acpi_package_info3 {
|
|||
u8 count;
|
||||
u8 object_type[2];
|
||||
u8 tail_object_type;
|
||||
u8 reserved;
|
||||
u16 reserved;
|
||||
};
|
||||
|
||||
union acpi_predefined_info {
|
||||
|
|
@ -355,6 +358,10 @@ union acpi_predefined_info {
|
|||
struct acpi_package_info3 ret_info3;
|
||||
};
|
||||
|
||||
/* Reset to default packing */
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/* Data block used during object validation */
|
||||
|
||||
struct acpi_predefined_data {
|
||||
|
|
@ -363,6 +370,7 @@ struct acpi_predefined_data {
|
|||
union acpi_operand_object *parent_package;
|
||||
struct acpi_namespace_node *node;
|
||||
u32 flags;
|
||||
u32 return_btype;
|
||||
u8 node_flags;
|
||||
};
|
||||
|
||||
|
|
@ -371,6 +379,20 @@ struct acpi_predefined_data {
|
|||
#define ACPI_OBJECT_REPAIRED 1
|
||||
#define ACPI_OBJECT_WRAPPED 2
|
||||
|
||||
/* Return object auto-repair info */
|
||||
|
||||
typedef acpi_status(*acpi_object_converter) (union acpi_operand_object
|
||||
*original_object,
|
||||
union acpi_operand_object
|
||||
**converted_object);
|
||||
|
||||
struct acpi_simple_repair_info {
|
||||
char name[ACPI_NAME_SIZE];
|
||||
u32 unexpected_btypes;
|
||||
u32 package_index;
|
||||
acpi_object_converter object_converter;
|
||||
};
|
||||
|
||||
/*
|
||||
* Bitmapped return value types
|
||||
* Note: the actual data types must be contiguous, a loop in nspredef.c
|
||||
|
|
@ -1037,6 +1059,7 @@ struct acpi_external_list {
|
|||
u16 length;
|
||||
u8 type;
|
||||
u8 flags;
|
||||
u8 resolved;
|
||||
};
|
||||
|
||||
/* Values for Flags field above */
|
||||
|
|
|
|||
|
|
@ -322,10 +322,12 @@
|
|||
* where a pointer to an object of type union acpi_operand_object can also
|
||||
* appear. This macro is used to distinguish them.
|
||||
*
|
||||
* The "Descriptor" field is the first field in both structures.
|
||||
* The "DescriptorType" field is the second field in both structures.
|
||||
*/
|
||||
#define ACPI_GET_DESCRIPTOR_PTR(d) (((union acpi_descriptor *)(void *)(d))->common.common_pointer)
|
||||
#define ACPI_SET_DESCRIPTOR_PTR(d, p) (((union acpi_descriptor *)(void *)(d))->common.common_pointer = (p))
|
||||
#define ACPI_GET_DESCRIPTOR_TYPE(d) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type)
|
||||
#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = t)
|
||||
#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = (t))
|
||||
|
||||
/*
|
||||
* Macros for the master AML opcode table
|
||||
|
|
|
|||
|
|
@ -166,6 +166,29 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent);
|
|||
|
||||
int acpi_ns_compare_names(char *name1, char *name2);
|
||||
|
||||
/*
|
||||
* nsconvert - Dynamic object conversion routines
|
||||
*/
|
||||
acpi_status
|
||||
acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object);
|
||||
|
||||
acpi_status
|
||||
acpi_ns_convert_to_string(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object);
|
||||
|
||||
acpi_status
|
||||
acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object);
|
||||
|
||||
acpi_status
|
||||
acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object);
|
||||
|
||||
acpi_status
|
||||
acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object);
|
||||
|
||||
/*
|
||||
* nsdump - Namespace dump/print utilities
|
||||
*/
|
||||
|
|
@ -208,10 +231,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
|||
acpi_status return_status,
|
||||
union acpi_operand_object **return_object);
|
||||
|
||||
const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
|
||||
acpi_namespace_node
|
||||
*node);
|
||||
|
||||
void
|
||||
acpi_ns_check_parameter_count(char *pathname,
|
||||
struct acpi_namespace_node *node,
|
||||
|
|
@ -289,7 +308,7 @@ acpi_ns_get_attached_data(struct acpi_namespace_node *node,
|
|||
* predefined methods/objects
|
||||
*/
|
||||
acpi_status
|
||||
acpi_ns_repair_object(struct acpi_predefined_data *data,
|
||||
acpi_ns_simple_repair(struct acpi_predefined_data *data,
|
||||
u32 expected_btypes,
|
||||
u32 package_index,
|
||||
union acpi_operand_object **return_object_ptr);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -113,9 +113,10 @@ struct acpi_pkg_info {
|
|||
u32 num_packages;
|
||||
};
|
||||
|
||||
/* Object reference counts */
|
||||
|
||||
#define REF_INCREMENT (u16) 0
|
||||
#define REF_DECREMENT (u16) 1
|
||||
#define REF_FORCE_DELETE (u16) 2
|
||||
|
||||
/* acpi_ut_dump_buffer */
|
||||
|
||||
|
|
@ -421,7 +422,7 @@ acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length);
|
|||
*/
|
||||
acpi_status acpi_ut_initialize_interfaces(void);
|
||||
|
||||
void acpi_ut_interface_terminate(void);
|
||||
acpi_status acpi_ut_interface_terminate(void);
|
||||
|
||||
acpi_status acpi_ut_install_interface(acpi_string interface_name);
|
||||
|
||||
|
|
@ -431,6 +432,26 @@ struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name);
|
|||
|
||||
acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
|
||||
|
||||
/*
|
||||
* utpredef - support for predefined names
|
||||
*/
|
||||
const union acpi_predefined_info *acpi_ut_get_next_predefined_method(const union
|
||||
acpi_predefined_info
|
||||
*this_name);
|
||||
|
||||
const union acpi_predefined_info *acpi_ut_match_predefined_method(char *name);
|
||||
|
||||
const union acpi_predefined_info *acpi_ut_match_resource_name(char *name);
|
||||
|
||||
void
|
||||
acpi_ut_display_predefined_method(char *buffer,
|
||||
const union acpi_predefined_info *this_name,
|
||||
u8 multi_line);
|
||||
|
||||
void acpi_ut_get_expected_return_types(char *buffer, u32 expected_btypes);
|
||||
|
||||
u32 acpi_ut_get_resource_bit_width(char *buffer, u16 types);
|
||||
|
||||
/*
|
||||
* utstate - Generic state creation/cache routines
|
||||
*/
|
||||
|
|
@ -483,7 +504,8 @@ acpi_ut_short_divide(u64 in_dividend,
|
|||
/*
|
||||
* utmisc
|
||||
*/
|
||||
const char *acpi_ut_validate_exception(acpi_status status);
|
||||
const struct acpi_exception_info *acpi_ut_validate_exception(acpi_status
|
||||
status);
|
||||
|
||||
u8 acpi_ut_is_pci_root_bridge(char *id);
|
||||
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
|
|||
|
||||
if (!op) {
|
||||
ACPI_ERROR((AE_INFO, "Null Op"));
|
||||
return_VALUE(TRUE);
|
||||
return_UINT8(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -210,7 +210,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
|
|||
"At Method level, result of [%s] not used\n",
|
||||
acpi_ps_get_opcode_name(op->common.
|
||||
aml_opcode)));
|
||||
return_VALUE(FALSE);
|
||||
return_UINT8(FALSE);
|
||||
}
|
||||
|
||||
/* Get info on the parent. The root_op is AML_SCOPE */
|
||||
|
|
@ -219,7 +219,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
|
|||
acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
|
||||
if (parent_info->class == AML_CLASS_UNKNOWN) {
|
||||
ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
|
||||
return_VALUE(FALSE);
|
||||
return_UINT8(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -307,7 +307,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
|
|||
acpi_ps_get_opcode_name(op->common.parent->common.
|
||||
aml_opcode), op));
|
||||
|
||||
return_VALUE(TRUE);
|
||||
return_UINT8(TRUE);
|
||||
|
||||
result_not_used:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
|
|
@ -316,7 +316,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
|
|||
acpi_ps_get_opcode_name(op->common.parent->common.
|
||||
aml_opcode), op));
|
||||
|
||||
return_VALUE(FALSE);
|
||||
return_UINT8(FALSE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
|
|
@ -693,7 +693,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
|
|||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Unimplemented opcode, class=0x%X type=0x%X Opcode=-0x%X Op=%p",
|
||||
"Unimplemented opcode, class=0x%X type=0x%X Opcode=0x%X Op=%p",
|
||||
op_class, op_type, op->common.aml_opcode,
|
||||
op));
|
||||
|
||||
|
|
|
|||
|
|
@ -257,6 +257,8 @@ u32 acpi_ev_fixed_event_detect(void)
|
|||
*
|
||||
* DESCRIPTION: Clears the status bit for the requested event, calls the
|
||||
* handler that previously registered for the event.
|
||||
* NOTE: If there is no handler for the event, the event is
|
||||
* disabled to prevent further interrupts.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
|
@ -271,17 +273,17 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
|
|||
status_register_id, ACPI_CLEAR_STATUS);
|
||||
|
||||
/*
|
||||
* Make sure we've got a handler. If not, report an error. The event is
|
||||
* disabled to prevent further interrupts.
|
||||
* Make sure that a handler exists. If not, report an error
|
||||
* and disable the event to prevent further interrupts.
|
||||
*/
|
||||
if (NULL == acpi_gbl_fixed_event_handlers[event].handler) {
|
||||
if (!acpi_gbl_fixed_event_handlers[event].handler) {
|
||||
(void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
|
||||
enable_register_id,
|
||||
ACPI_DISABLE_EVENT);
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"No installed handler for fixed event [0x%08X]",
|
||||
event));
|
||||
"No installed handler for fixed event - %s (%u), disabling",
|
||||
acpi_ut_get_event_name(event), event));
|
||||
|
||||
return (ACPI_INTERRUPT_NOT_HANDLED);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -707,7 +707,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
|
|||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"Unable to clear GPE%02X", gpe_number));
|
||||
return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
|
||||
return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -724,7 +724,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
|
|||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"Unable to disable GPE%02X", gpe_number));
|
||||
return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
|
||||
return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -784,7 +784,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
|
|||
break;
|
||||
}
|
||||
|
||||
return_VALUE(ACPI_INTERRUPT_HANDLED);
|
||||
return_UINT32(ACPI_INTERRUPT_HANDLED);
|
||||
}
|
||||
|
||||
#endif /* !ACPI_REDUCED_HARDWARE */
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
|
|||
*/
|
||||
interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
|
||||
|
||||
return_VALUE(interrupt_handled);
|
||||
return_UINT32(interrupt_handled);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
@ -120,7 +120,7 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
|
|||
|
||||
interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
|
||||
|
||||
return_VALUE(interrupt_handled);
|
||||
return_UINT32(interrupt_handled);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
|||
|
|
@ -467,9 +467,9 @@ acpi_install_fixed_event_handler(u32 event,
|
|||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Don't allow two handlers. */
|
||||
/* Do not allow multiple handlers */
|
||||
|
||||
if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
|
||||
if (acpi_gbl_fixed_event_handlers[event].handler) {
|
||||
status = AE_ALREADY_EXISTS;
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -483,8 +483,9 @@ acpi_install_fixed_event_handler(u32 event,
|
|||
if (ACPI_SUCCESS(status))
|
||||
status = acpi_enable_event(event, 0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_WARNING((AE_INFO, "Could not enable fixed event 0x%X",
|
||||
event));
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Could not enable fixed event - %s (%u)",
|
||||
acpi_ut_get_event_name(event), event));
|
||||
|
||||
/* Remove the handler */
|
||||
|
||||
|
|
@ -492,7 +493,8 @@ acpi_install_fixed_event_handler(u32 event,
|
|||
acpi_gbl_fixed_event_handlers[event].context = NULL;
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Enabled fixed event %X, Handler=%p\n", event,
|
||||
"Enabled fixed event %s (%X), Handler=%p\n",
|
||||
acpi_ut_get_event_name(event), event,
|
||||
handler));
|
||||
}
|
||||
|
||||
|
|
@ -544,11 +546,12 @@ acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
|
|||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Could not write to fixed event enable register 0x%X",
|
||||
event));
|
||||
"Could not disable fixed event - %s (%u)",
|
||||
acpi_ut_get_event_name(event), event));
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",
|
||||
event));
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Disabled fixed event - %s (%X)\n",
|
||||
acpi_ut_get_event_name(event), event));
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,12 @@ acpi_status acpi_enable(void)
|
|||
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
|
||||
}
|
||||
|
||||
/* If the Hardware Reduced flag is set, machine is always in acpi mode */
|
||||
|
||||
if (acpi_gbl_reduced_hardware) {
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/* Check current mode */
|
||||
|
||||
if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
|
||||
|
|
@ -126,6 +132,12 @@ acpi_status acpi_disable(void)
|
|||
|
||||
ACPI_FUNCTION_TRACE(acpi_disable);
|
||||
|
||||
/* If the Hardware Reduced flag is set, machine is always in acpi mode */
|
||||
|
||||
if (acpi_gbl_reduced_hardware) {
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
|
||||
"System is already in legacy (non-ACPI) mode\n"));
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
|
|||
union acpi_operand_object *return_desc = NULL;
|
||||
u64 index;
|
||||
acpi_status status = AE_OK;
|
||||
acpi_size length;
|
||||
acpi_size length = 0;
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R,
|
||||
acpi_ps_get_opcode_name(walk_state->opcode));
|
||||
|
|
@ -320,7 +320,6 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
|
|||
* NOTE: A length of zero is ok, and will create a zero-length, null
|
||||
* terminated string.
|
||||
*/
|
||||
length = 0;
|
||||
while ((length < operand[0]->buffer.length) &&
|
||||
(length < operand[1]->integer.value) &&
|
||||
(operand[0]->buffer.pointer[length])) {
|
||||
|
|
@ -376,6 +375,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
|
|||
case ACPI_TYPE_STRING:
|
||||
|
||||
if (index >= operand[0]->string.length) {
|
||||
length = operand[0]->string.length;
|
||||
status = AE_AML_STRING_LIMIT;
|
||||
}
|
||||
|
||||
|
|
@ -386,6 +386,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
|
|||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
if (index >= operand[0]->buffer.length) {
|
||||
length = operand[0]->buffer.length;
|
||||
status = AE_AML_BUFFER_LIMIT;
|
||||
}
|
||||
|
||||
|
|
@ -396,6 +397,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
|
|||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
if (index >= operand[0]->package.count) {
|
||||
length = operand[0]->package.count;
|
||||
status = AE_AML_PACKAGE_LIMIT;
|
||||
}
|
||||
|
||||
|
|
@ -414,8 +416,9 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
|
|||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"Index (0x%8.8X%8.8X) is beyond end of object",
|
||||
ACPI_FORMAT_UINT64(index)));
|
||||
"Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
|
||||
ACPI_FORMAT_UINT64(index),
|
||||
(u32)length));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
|
|||
/* Invalid field access type */
|
||||
|
||||
ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access));
|
||||
return_VALUE(0);
|
||||
return_UINT32(0);
|
||||
}
|
||||
|
||||
if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
|
||||
|
|
@ -289,7 +289,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
|
|||
}
|
||||
|
||||
*return_byte_alignment = byte_alignment;
|
||||
return_VALUE(bit_length);
|
||||
return_UINT32(bit_length);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ static u32 acpi_ex_digits_needed(u64 value, u32 base)
|
|||
/* u64 is unsigned, so we don't worry about a '-' prefix */
|
||||
|
||||
if (value == 0) {
|
||||
return_VALUE(1);
|
||||
return_UINT32(1);
|
||||
}
|
||||
|
||||
current_value = value;
|
||||
|
|
@ -354,7 +354,7 @@ static u32 acpi_ex_digits_needed(u64 value, u32 base)
|
|||
num_digits++;
|
||||
}
|
||||
|
||||
return_VALUE(num_digits);
|
||||
return_UINT32(num_digits);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
|
|
@ -66,6 +66,12 @@ acpi_status acpi_hw_set_mode(u32 mode)
|
|||
|
||||
ACPI_FUNCTION_TRACE(hw_set_mode);
|
||||
|
||||
/* If the Hardware Reduced flag is set, machine is always in acpi mode */
|
||||
|
||||
if (acpi_gbl_reduced_hardware) {
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
|
||||
* system does not support mode transition.
|
||||
|
|
@ -146,23 +152,29 @@ u32 acpi_hw_get_mode(void)
|
|||
|
||||
ACPI_FUNCTION_TRACE(hw_get_mode);
|
||||
|
||||
/* If the Hardware Reduced flag is set, machine is always in acpi mode */
|
||||
|
||||
if (acpi_gbl_reduced_hardware) {
|
||||
return_UINT32(ACPI_SYS_MODE_ACPI);
|
||||
}
|
||||
|
||||
/*
|
||||
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
|
||||
* system does not support mode transition.
|
||||
*/
|
||||
if (!acpi_gbl_FADT.smi_command) {
|
||||
return_VALUE(ACPI_SYS_MODE_ACPI);
|
||||
return_UINT32(ACPI_SYS_MODE_ACPI);
|
||||
}
|
||||
|
||||
status = acpi_read_bit_register(ACPI_BITREG_SCI_ENABLE, &value);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_VALUE(ACPI_SYS_MODE_LEGACY);
|
||||
return_UINT32(ACPI_SYS_MODE_LEGACY);
|
||||
}
|
||||
|
||||
if (value) {
|
||||
return_VALUE(ACPI_SYS_MODE_ACPI);
|
||||
return_UINT32(ACPI_SYS_MODE_ACPI);
|
||||
} else {
|
||||
return_VALUE(ACPI_SYS_MODE_LEGACY);
|
||||
return_UINT32(ACPI_SYS_MODE_LEGACY);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
443
drivers/acpi/acpica/nsconvert.c
Normal file
443
drivers/acpi/acpica/nsconvert.c
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Module Name: nsconvert - Object conversions for objects returned by
|
||||
* predefined methods
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2013, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acnamesp.h"
|
||||
#include "acinterp.h"
|
||||
#include "acpredef.h"
|
||||
#include "amlresrc.h"
|
||||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
ACPI_MODULE_NAME("nsconvert")
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_convert_to_integer
|
||||
*
|
||||
* PARAMETERS: original_object - Object to be converted
|
||||
* return_object - Where the new converted object is returned
|
||||
*
|
||||
* RETURN: Status. AE_OK if conversion was successful.
|
||||
*
|
||||
* DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object)
|
||||
{
|
||||
union acpi_operand_object *new_object;
|
||||
acpi_status status;
|
||||
u64 value = 0;
|
||||
u32 i;
|
||||
|
||||
switch (original_object->common.type) {
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
/* String-to-Integer conversion */
|
||||
|
||||
status = acpi_ut_strtoul64(original_object->string.pointer,
|
||||
ACPI_ANY_BASE, &value);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
|
||||
|
||||
if (original_object->buffer.length > 8) {
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/* Extract each buffer byte to create the integer */
|
||||
|
||||
for (i = 0; i < original_object->buffer.length; i++) {
|
||||
value |=
|
||||
((u64)original_object->buffer.
|
||||
pointer[i] << (i * 8));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
new_object = acpi_ut_create_integer_object(value);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
*return_object = new_object;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_convert_to_string
|
||||
*
|
||||
* PARAMETERS: original_object - Object to be converted
|
||||
* return_object - Where the new converted object is returned
|
||||
*
|
||||
* RETURN: Status. AE_OK if conversion was successful.
|
||||
*
|
||||
* DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ns_convert_to_string(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object)
|
||||
{
|
||||
union acpi_operand_object *new_object;
|
||||
acpi_size length;
|
||||
acpi_status status;
|
||||
|
||||
switch (original_object->common.type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
/*
|
||||
* Integer-to-String conversion. Commonly, convert
|
||||
* an integer of value 0 to a NULL string. The last element of
|
||||
* _BIF and _BIX packages occasionally need this fix.
|
||||
*/
|
||||
if (original_object->integer.value == 0) {
|
||||
|
||||
/* Allocate a new NULL string object */
|
||||
|
||||
new_object = acpi_ut_create_string_object(0);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
} else {
|
||||
status =
|
||||
acpi_ex_convert_to_string(original_object,
|
||||
&new_object,
|
||||
ACPI_IMPLICIT_CONVERT_HEX);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
/*
|
||||
* Buffer-to-String conversion. Use a to_string
|
||||
* conversion, no transform performed on the buffer data. The best
|
||||
* example of this is the _BIF method, where the string data from
|
||||
* the battery is often (incorrectly) returned as buffer object(s).
|
||||
*/
|
||||
length = 0;
|
||||
while ((length < original_object->buffer.length) &&
|
||||
(original_object->buffer.pointer[length])) {
|
||||
length++;
|
||||
}
|
||||
|
||||
/* Allocate a new string object */
|
||||
|
||||
new_object = acpi_ut_create_string_object(length);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the raw buffer data with no transform. String is already NULL
|
||||
* terminated at Length+1.
|
||||
*/
|
||||
ACPI_MEMCPY(new_object->string.pointer,
|
||||
original_object->buffer.pointer, length);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
*return_object = new_object;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_convert_to_buffer
|
||||
*
|
||||
* PARAMETERS: original_object - Object to be converted
|
||||
* return_object - Where the new converted object is returned
|
||||
*
|
||||
* RETURN: Status. AE_OK if conversion was successful.
|
||||
*
|
||||
* DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object)
|
||||
{
|
||||
union acpi_operand_object *new_object;
|
||||
acpi_status status;
|
||||
union acpi_operand_object **elements;
|
||||
u32 *dword_buffer;
|
||||
u32 count;
|
||||
u32 i;
|
||||
|
||||
switch (original_object->common.type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
/*
|
||||
* Integer-to-Buffer conversion.
|
||||
* Convert the Integer to a packed-byte buffer. _MAT and other
|
||||
* objects need this sometimes, if a read has been performed on a
|
||||
* Field object that is less than or equal to the global integer
|
||||
* size (32 or 64 bits).
|
||||
*/
|
||||
status =
|
||||
acpi_ex_convert_to_buffer(original_object, &new_object);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
/* String-to-Buffer conversion. Simple data copy */
|
||||
|
||||
new_object =
|
||||
acpi_ut_create_buffer_object(original_object->string.
|
||||
length);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
ACPI_MEMCPY(new_object->buffer.pointer,
|
||||
original_object->string.pointer,
|
||||
original_object->string.length);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
/*
|
||||
* This case is often seen for predefined names that must return a
|
||||
* Buffer object with multiple DWORD integers within. For example,
|
||||
* _FDE and _GTM. The Package can be converted to a Buffer.
|
||||
*/
|
||||
|
||||
/* All elements of the Package must be integers */
|
||||
|
||||
elements = original_object->package.elements;
|
||||
count = original_object->package.count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if ((!*elements) ||
|
||||
((*elements)->common.type != ACPI_TYPE_INTEGER)) {
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
elements++;
|
||||
}
|
||||
|
||||
/* Create the new buffer object to replace the Package */
|
||||
|
||||
new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Copy the package elements (integers) to the buffer as DWORDs */
|
||||
|
||||
elements = original_object->package.elements;
|
||||
dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
*dword_buffer = (u32)(*elements)->integer.value;
|
||||
dword_buffer++;
|
||||
elements++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
*return_object = new_object;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_convert_to_unicode
|
||||
*
|
||||
* PARAMETERS: original_object - ASCII String Object to be converted
|
||||
* return_object - Where the new converted object is returned
|
||||
*
|
||||
* RETURN: Status. AE_OK if conversion was successful.
|
||||
*
|
||||
* DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object)
|
||||
{
|
||||
union acpi_operand_object *new_object;
|
||||
char *ascii_string;
|
||||
u16 *unicode_buffer;
|
||||
u32 unicode_length;
|
||||
u32 i;
|
||||
|
||||
if (!original_object) {
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/* If a Buffer was returned, it must be at least two bytes long */
|
||||
|
||||
if (original_object->common.type == ACPI_TYPE_BUFFER) {
|
||||
if (original_object->buffer.length < 2) {
|
||||
return (AE_AML_OPERAND_VALUE);
|
||||
}
|
||||
|
||||
*return_object = NULL;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* The original object is an ASCII string. Convert this string to
|
||||
* a unicode buffer.
|
||||
*/
|
||||
ascii_string = original_object->string.pointer;
|
||||
unicode_length = (original_object->string.length * 2) + 2;
|
||||
|
||||
/* Create a new buffer object for the Unicode data */
|
||||
|
||||
new_object = acpi_ut_create_buffer_object(unicode_length);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
|
||||
|
||||
/* Convert ASCII to Unicode */
|
||||
|
||||
for (i = 0; i < original_object->string.length; i++) {
|
||||
unicode_buffer[i] = (u16)ascii_string[i];
|
||||
}
|
||||
|
||||
*return_object = new_object;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_convert_to_resource
|
||||
*
|
||||
* PARAMETERS: original_object - Object to be converted
|
||||
* return_object - Where the new converted object is returned
|
||||
*
|
||||
* RETURN: Status. AE_OK if conversion was successful
|
||||
*
|
||||
* DESCRIPTION: Attempt to convert a Integer object to a resource_template
|
||||
* Buffer.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object)
|
||||
{
|
||||
union acpi_operand_object *new_object;
|
||||
u8 *buffer;
|
||||
|
||||
/*
|
||||
* We can fix the following cases for an expected resource template:
|
||||
* 1. No return value (interpreter slack mode is disabled)
|
||||
* 2. A "Return (Zero)" statement
|
||||
* 3. A "Return empty buffer" statement
|
||||
*
|
||||
* We will return a buffer containing a single end_tag
|
||||
* resource descriptor.
|
||||
*/
|
||||
if (original_object) {
|
||||
switch (original_object->common.type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
/* We can only repair an Integer==0 */
|
||||
|
||||
if (original_object->integer.value) {
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
if (original_object->buffer.length) {
|
||||
|
||||
/* Additional checks can be added in the future */
|
||||
|
||||
*return_object = NULL;
|
||||
return (AE_OK);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
default:
|
||||
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the new buffer object for the resource descriptor */
|
||||
|
||||
new_object = acpi_ut_create_buffer_object(2);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
|
||||
|
||||
/* Initialize the Buffer with a single end_tag descriptor */
|
||||
|
||||
buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
|
||||
buffer[1] = 0x00;
|
||||
|
||||
*return_object = new_object;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
|
@ -98,17 +98,21 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
|
|||
info->return_object = NULL;
|
||||
info->param_count = 0;
|
||||
|
||||
/*
|
||||
* Get the actual namespace node for the target object. Handles these cases:
|
||||
*
|
||||
* 1) Null node, Pathname (absolute path)
|
||||
* 2) Node, Pathname (path relative to Node)
|
||||
* 3) Node, Null Pathname
|
||||
*/
|
||||
status = acpi_ns_get_node(info->prefix_node, info->pathname,
|
||||
ACPI_NS_NO_UPSEARCH, &info->resolved_node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
if (!info->resolved_node) {
|
||||
/*
|
||||
* Get the actual namespace node for the target object if we need to.
|
||||
* Handles these cases:
|
||||
*
|
||||
* 1) Null node, Pathname (absolute path)
|
||||
* 2) Node, Pathname (path relative to Node)
|
||||
* 3) Node, Null Pathname
|
||||
*/
|
||||
status = acpi_ns_get_node(info->prefix_node, info->pathname,
|
||||
ACPI_NS_NO_UPSEARCH,
|
||||
&info->resolved_node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -76,19 +76,7 @@ static acpi_status
|
|||
acpi_ns_check_reference(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object *return_object);
|
||||
|
||||
static void acpi_ns_get_expected_types(char *buffer, u32 expected_btypes);
|
||||
|
||||
/*
|
||||
* Names for the types that can be returned by the predefined objects.
|
||||
* Used for warning messages. Must be in the same order as the ACPI_RTYPEs
|
||||
*/
|
||||
static const char *acpi_rtype_names[] = {
|
||||
"/Integer",
|
||||
"/String",
|
||||
"/Buffer",
|
||||
"/Package",
|
||||
"/Reference",
|
||||
};
|
||||
static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
|
|
@ -112,7 +100,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
|||
acpi_status return_status,
|
||||
union acpi_operand_object **return_object_ptr)
|
||||
{
|
||||
union acpi_operand_object *return_object = *return_object_ptr;
|
||||
acpi_status status = AE_OK;
|
||||
const union acpi_predefined_info *predefined;
|
||||
char *pathname;
|
||||
|
|
@ -120,7 +107,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
|||
|
||||
/* Match the name for this method/object against the predefined list */
|
||||
|
||||
predefined = acpi_ns_check_for_predefined_name(node);
|
||||
predefined = acpi_ut_match_predefined_method(node->name.ascii);
|
||||
|
||||
/* Get the full pathname to the object, for use in warning messages */
|
||||
|
||||
|
|
@ -151,25 +138,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no return value, check if we require a return value for
|
||||
* this predefined name. Either one return value is expected, or none,
|
||||
* for both methods and other objects.
|
||||
*
|
||||
* Exit now if there is no return object. Warning if one was expected.
|
||||
*/
|
||||
if (!return_object) {
|
||||
if ((predefined->info.expected_btypes) &&
|
||||
(!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) {
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, pathname,
|
||||
ACPI_WARN_ALWAYS,
|
||||
"Missing expected return value"));
|
||||
|
||||
status = AE_AML_NO_RETURN_VALUE;
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return value validation and possible repair.
|
||||
*
|
||||
|
|
@ -310,8 +278,10 @@ acpi_ns_check_parameter_count(char *pathname,
|
|||
* Validate the user-supplied parameter count.
|
||||
* Allow two different legal argument counts (_SCP, etc.)
|
||||
*/
|
||||
required_params_current = predefined->info.param_count & 0x0F;
|
||||
required_params_old = predefined->info.param_count >> 4;
|
||||
required_params_current =
|
||||
predefined->info.argument_list & METHOD_ARG_MASK;
|
||||
required_params_old =
|
||||
predefined->info.argument_list >> METHOD_ARG_BIT_WIDTH;
|
||||
|
||||
if (user_param_count != ACPI_UINT32_MAX) {
|
||||
if ((user_param_count != required_params_current) &&
|
||||
|
|
@ -338,52 +308,6 @@ acpi_ns_check_parameter_count(char *pathname,
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_check_for_predefined_name
|
||||
*
|
||||
* PARAMETERS: node - Namespace node for the method/object
|
||||
*
|
||||
* RETURN: Pointer to entry in predefined table. NULL indicates not found.
|
||||
*
|
||||
* DESCRIPTION: Check an object name against the predefined object list.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
|
||||
acpi_namespace_node
|
||||
*node)
|
||||
{
|
||||
const union acpi_predefined_info *this_name;
|
||||
|
||||
/* Quick check for a predefined name, first character must be underscore */
|
||||
|
||||
if (node->name.ascii[0] != '_') {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Search info table for a predefined method/object name */
|
||||
|
||||
this_name = predefined_names;
|
||||
while (this_name->info.name[0]) {
|
||||
if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) {
|
||||
return (this_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip next entry in the table if this name returns a Package
|
||||
* (next entry contains the package info)
|
||||
*/
|
||||
if (this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) {
|
||||
this_name++;
|
||||
}
|
||||
|
||||
this_name++;
|
||||
}
|
||||
|
||||
return (NULL); /* Not found */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_check_object_type
|
||||
|
|
@ -410,28 +334,12 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data,
|
|||
{
|
||||
union acpi_operand_object *return_object = *return_object_ptr;
|
||||
acpi_status status = AE_OK;
|
||||
u32 return_btype;
|
||||
char type_buffer[48]; /* Room for 5 types */
|
||||
|
||||
/*
|
||||
* If we get a NULL return_object here, it is a NULL package element.
|
||||
* Since all extraneous NULL package elements were removed earlier by a
|
||||
* call to acpi_ns_remove_null_elements, this is an unexpected NULL element.
|
||||
* We will attempt to repair it.
|
||||
*/
|
||||
if (!return_object) {
|
||||
status = acpi_ns_repair_null_element(data, expected_btypes,
|
||||
package_index,
|
||||
return_object_ptr);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
return (AE_OK); /* Repair was successful */
|
||||
}
|
||||
goto type_error_exit;
|
||||
}
|
||||
|
||||
/* A Namespace node should not get here, but make sure */
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) {
|
||||
if (return_object &&
|
||||
ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) {
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
|
||||
"Invalid return type - Found a Namespace node [%4.4s] type %s",
|
||||
return_object->node.name.ascii,
|
||||
|
|
@ -448,59 +356,31 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data,
|
|||
* from all of the predefined names (including elements of returned
|
||||
* packages)
|
||||
*/
|
||||
switch (return_object->common.type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
return_btype = ACPI_RTYPE_INTEGER;
|
||||
break;
|
||||
data->return_btype = acpi_ns_get_bitmapped_type(return_object);
|
||||
if (data->return_btype == ACPI_RTYPE_ANY) {
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
return_btype = ACPI_RTYPE_BUFFER;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
return_btype = ACPI_RTYPE_STRING;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
return_btype = ACPI_RTYPE_PACKAGE;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
return_btype = ACPI_RTYPE_REFERENCE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not one of the supported objects, must be incorrect */
|
||||
|
||||
goto type_error_exit;
|
||||
}
|
||||
|
||||
/* Is the object one of the expected types? */
|
||||
|
||||
if (return_btype & expected_btypes) {
|
||||
|
||||
/* For reference objects, check that the reference type is correct */
|
||||
|
||||
if (return_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
status = acpi_ns_check_reference(data, return_object);
|
||||
}
|
||||
/* For reference objects, check that the reference type is correct */
|
||||
|
||||
if ((data->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) {
|
||||
status = acpi_ns_check_reference(data, return_object);
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* Type mismatch -- attempt repair of the returned object */
|
||||
/* Attempt simple repair of the returned object if necessary */
|
||||
|
||||
status = acpi_ns_repair_object(data, expected_btypes,
|
||||
status = acpi_ns_simple_repair(data, expected_btypes,
|
||||
package_index, return_object_ptr);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
return (AE_OK); /* Repair was successful */
|
||||
}
|
||||
return (status);
|
||||
|
||||
type_error_exit:
|
||||
|
||||
/* Create a string with all expected types for this predefined object */
|
||||
|
||||
acpi_ns_get_expected_types(type_buffer, expected_btypes);
|
||||
acpi_ut_get_expected_return_types(type_buffer, expected_btypes);
|
||||
|
||||
if (package_index == ACPI_NOT_PACKAGE_ELEMENT) {
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
|
||||
|
|
@ -558,36 +438,55 @@ acpi_ns_check_reference(struct acpi_predefined_data *data,
|
|||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_get_expected_types
|
||||
* FUNCTION: acpi_ns_get_bitmapped_type
|
||||
*
|
||||
* PARAMETERS: buffer - Pointer to where the string is returned
|
||||
* expected_btypes - Bitmap of expected return type(s)
|
||||
* PARAMETERS: return_object - Object returned from method/obj evaluation
|
||||
*
|
||||
* RETURN: Buffer is populated with type names.
|
||||
* RETURN: Object return type. ACPI_RTYPE_ANY indicates that the object
|
||||
* type is not supported. ACPI_RTYPE_NONE indicates that no
|
||||
* object was returned (return_object is NULL).
|
||||
*
|
||||
* DESCRIPTION: Translate the expected types bitmap into a string of ascii
|
||||
* names of expected types, for use in warning messages.
|
||||
* DESCRIPTION: Convert object type into a bitmapped object return type.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void acpi_ns_get_expected_types(char *buffer, u32 expected_btypes)
|
||||
static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object)
|
||||
{
|
||||
u32 this_rtype;
|
||||
u32 i;
|
||||
u32 j;
|
||||
u32 return_btype;
|
||||
|
||||
j = 1;
|
||||
buffer[0] = 0;
|
||||
this_rtype = ACPI_RTYPE_INTEGER;
|
||||
|
||||
for (i = 0; i < ACPI_NUM_RTYPES; i++) {
|
||||
|
||||
/* If one of the expected types, concatenate the name of this type */
|
||||
|
||||
if (expected_btypes & this_rtype) {
|
||||
ACPI_STRCAT(buffer, &acpi_rtype_names[i][j]);
|
||||
j = 0; /* Use name separator from now on */
|
||||
}
|
||||
this_rtype <<= 1; /* Next Rtype */
|
||||
if (!return_object) {
|
||||
return (ACPI_RTYPE_NONE);
|
||||
}
|
||||
|
||||
/* Map acpi_object_type to internal bitmapped type */
|
||||
|
||||
switch (return_object->common.type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
return_btype = ACPI_RTYPE_INTEGER;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
return_btype = ACPI_RTYPE_BUFFER;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
return_btype = ACPI_RTYPE_STRING;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
return_btype = ACPI_RTYPE_PACKAGE;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
return_btype = ACPI_RTYPE_REFERENCE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not one of the supported objects, must be incorrect */
|
||||
|
||||
return_btype = ACPI_RTYPE_ANY;
|
||||
break;
|
||||
}
|
||||
|
||||
return (return_btype);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,9 +112,15 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
|
|||
elements = return_object->package.elements;
|
||||
count = return_object->package.count;
|
||||
|
||||
/* The package must have at least one element, else invalid */
|
||||
|
||||
/*
|
||||
* Most packages must have at least one element. The only exception
|
||||
* is the variable-length package (ACPI_PTYPE1_VAR).
|
||||
*/
|
||||
if (!count) {
|
||||
if (package->ret_info.type == ACPI_PTYPE1_VAR) {
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
|
||||
"Return Package has no elements (empty)"));
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "acnamesp.h"
|
||||
#include "acinterp.h"
|
||||
#include "acpredef.h"
|
||||
#include "amlresrc.h"
|
||||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
ACPI_MODULE_NAME("nsrepair")
|
||||
|
|
@ -71,6 +72,11 @@ ACPI_MODULE_NAME("nsrepair")
|
|||
* Buffer -> String
|
||||
* Buffer -> Package of Integers
|
||||
* Package -> Package of one Package
|
||||
*
|
||||
* Additional conversions that are available:
|
||||
* Convert a null return or zero return value to an end_tag descriptor
|
||||
* Convert an ASCII string to a Unicode buffer
|
||||
*
|
||||
* An incorrect standalone object is wrapped with required outer package
|
||||
*
|
||||
* Additional possible repairs:
|
||||
|
|
@ -78,21 +84,51 @@ ACPI_MODULE_NAME("nsrepair")
|
|||
*
|
||||
******************************************************************************/
|
||||
/* Local prototypes */
|
||||
static acpi_status
|
||||
acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object);
|
||||
static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
|
||||
acpi_namespace_node
|
||||
*node,
|
||||
u32
|
||||
return_btype,
|
||||
u32
|
||||
package_index);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_convert_to_string(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object);
|
||||
/*
|
||||
* Special but simple repairs for some names.
|
||||
*
|
||||
* 2nd argument: Unexpected types that can be repaired
|
||||
*/
|
||||
static const struct acpi_simple_repair_info acpi_object_repair_info[] = {
|
||||
/* Resource descriptor conversions */
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object);
|
||||
{"_CRS",
|
||||
ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
|
||||
ACPI_RTYPE_NONE,
|
||||
ACPI_NOT_PACKAGE_ELEMENT,
|
||||
acpi_ns_convert_to_resource},
|
||||
{"_DMA",
|
||||
ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
|
||||
ACPI_RTYPE_NONE,
|
||||
ACPI_NOT_PACKAGE_ELEMENT,
|
||||
acpi_ns_convert_to_resource},
|
||||
{"_PRS",
|
||||
ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
|
||||
ACPI_RTYPE_NONE,
|
||||
ACPI_NOT_PACKAGE_ELEMENT,
|
||||
acpi_ns_convert_to_resource},
|
||||
|
||||
/* Unicode conversions */
|
||||
|
||||
{"_MLS", ACPI_RTYPE_STRING, 1,
|
||||
acpi_ns_convert_to_unicode},
|
||||
{"_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER,
|
||||
ACPI_NOT_PACKAGE_ELEMENT,
|
||||
acpi_ns_convert_to_unicode},
|
||||
{{0, 0, 0, 0}, 0, 0, NULL} /* Table terminator */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_repair_object
|
||||
* FUNCTION: acpi_ns_simple_repair
|
||||
*
|
||||
* PARAMETERS: data - Pointer to validation data structure
|
||||
* expected_btypes - Object types expected
|
||||
|
|
@ -110,16 +146,54 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
|
|||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ns_repair_object(struct acpi_predefined_data *data,
|
||||
acpi_ns_simple_repair(struct acpi_predefined_data *data,
|
||||
u32 expected_btypes,
|
||||
u32 package_index,
|
||||
union acpi_operand_object **return_object_ptr)
|
||||
{
|
||||
union acpi_operand_object *return_object = *return_object_ptr;
|
||||
union acpi_operand_object *new_object;
|
||||
union acpi_operand_object *new_object = NULL;
|
||||
acpi_status status;
|
||||
const struct acpi_simple_repair_info *predefined;
|
||||
|
||||
ACPI_FUNCTION_NAME(ns_repair_object);
|
||||
ACPI_FUNCTION_NAME(ns_simple_repair);
|
||||
|
||||
/*
|
||||
* Special repairs for certain names that are in the repair table.
|
||||
* Check if this name is in the list of repairable names.
|
||||
*/
|
||||
predefined = acpi_ns_match_simple_repair(data->node,
|
||||
data->return_btype,
|
||||
package_index);
|
||||
if (predefined) {
|
||||
if (!return_object) {
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
|
||||
ACPI_WARN_ALWAYS,
|
||||
"Missing expected return value"));
|
||||
}
|
||||
|
||||
status =
|
||||
predefined->object_converter(return_object, &new_object);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
/* A fatal error occurred during a conversion */
|
||||
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"During return object analysis"));
|
||||
return (status);
|
||||
}
|
||||
if (new_object) {
|
||||
goto object_repaired;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not perform simple object repair unless the return type is not
|
||||
* expected.
|
||||
*/
|
||||
if (data->return_btype & expected_btypes) {
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, we know that the type of the returned object was not
|
||||
|
|
@ -127,6 +201,24 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
|
|||
* repair the object by converting it to one of the expected object
|
||||
* types for this predefined name.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If there is no return value, check if we require a return value for
|
||||
* this predefined name. Either one return value is expected, or none,
|
||||
* for both methods and other objects.
|
||||
*
|
||||
* Exit now if there is no return object. Warning if one was expected.
|
||||
*/
|
||||
if (!return_object) {
|
||||
if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) {
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
|
||||
ACPI_WARN_ALWAYS,
|
||||
"Missing expected return value"));
|
||||
|
||||
return (AE_AML_NO_RETURN_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (expected_btypes & ACPI_RTYPE_INTEGER) {
|
||||
status = acpi_ns_convert_to_integer(return_object, &new_object);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
|
|
@ -216,254 +308,51 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
|
|||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_convert_to_integer
|
||||
* FUNCTION: acpi_ns_match_simple_repair
|
||||
*
|
||||
* PARAMETERS: original_object - Object to be converted
|
||||
* return_object - Where the new converted object is returned
|
||||
* PARAMETERS: node - Namespace node for the method/object
|
||||
* return_btype - Object type that was returned
|
||||
* package_index - Index of object within parent package (if
|
||||
* applicable - ACPI_NOT_PACKAGE_ELEMENT
|
||||
* otherwise)
|
||||
*
|
||||
* RETURN: Status. AE_OK if conversion was successful.
|
||||
* RETURN: Pointer to entry in repair table. NULL indicates not found.
|
||||
*
|
||||
* DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
|
||||
* DESCRIPTION: Check an object name against the repairable object list.
|
||||
*
|
||||
******************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object)
|
||||
static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
|
||||
acpi_namespace_node
|
||||
*node,
|
||||
u32
|
||||
return_btype,
|
||||
u32
|
||||
package_index)
|
||||
{
|
||||
union acpi_operand_object *new_object;
|
||||
acpi_status status;
|
||||
u64 value = 0;
|
||||
u32 i;
|
||||
const struct acpi_simple_repair_info *this_name;
|
||||
|
||||
switch (original_object->common.type) {
|
||||
case ACPI_TYPE_STRING:
|
||||
/* Search info table for a repairable predefined method/object name */
|
||||
|
||||
/* String-to-Integer conversion */
|
||||
this_name = acpi_object_repair_info;
|
||||
while (this_name->object_converter) {
|
||||
if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) {
|
||||
|
||||
status = acpi_ut_strtoul64(original_object->string.pointer,
|
||||
ACPI_ANY_BASE, &value);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
break;
|
||||
/* Check if we can actually repair this name/type combination */
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
|
||||
|
||||
if (original_object->buffer.length > 8) {
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/* Extract each buffer byte to create the integer */
|
||||
|
||||
for (i = 0; i < original_object->buffer.length; i++) {
|
||||
value |=
|
||||
((u64) original_object->buffer.
|
||||
pointer[i] << (i * 8));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
new_object = acpi_ut_create_integer_object(value);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
*return_object = new_object;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_convert_to_string
|
||||
*
|
||||
* PARAMETERS: original_object - Object to be converted
|
||||
* return_object - Where the new converted object is returned
|
||||
*
|
||||
* RETURN: Status. AE_OK if conversion was successful.
|
||||
*
|
||||
* DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_convert_to_string(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object)
|
||||
{
|
||||
union acpi_operand_object *new_object;
|
||||
acpi_size length;
|
||||
acpi_status status;
|
||||
|
||||
switch (original_object->common.type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
/*
|
||||
* Integer-to-String conversion. Commonly, convert
|
||||
* an integer of value 0 to a NULL string. The last element of
|
||||
* _BIF and _BIX packages occasionally need this fix.
|
||||
*/
|
||||
if (original_object->integer.value == 0) {
|
||||
|
||||
/* Allocate a new NULL string object */
|
||||
|
||||
new_object = acpi_ut_create_string_object(0);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
} else {
|
||||
status =
|
||||
acpi_ex_convert_to_string(original_object,
|
||||
&new_object,
|
||||
ACPI_IMPLICIT_CONVERT_HEX);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
if ((return_btype & this_name->unexpected_btypes) &&
|
||||
(package_index == this_name->package_index)) {
|
||||
return (this_name);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
/*
|
||||
* Buffer-to-String conversion. Use a to_string
|
||||
* conversion, no transform performed on the buffer data. The best
|
||||
* example of this is the _BIF method, where the string data from
|
||||
* the battery is often (incorrectly) returned as buffer object(s).
|
||||
*/
|
||||
length = 0;
|
||||
while ((length < original_object->buffer.length) &&
|
||||
(original_object->buffer.pointer[length])) {
|
||||
length++;
|
||||
}
|
||||
|
||||
/* Allocate a new string object */
|
||||
|
||||
new_object = acpi_ut_create_string_object(length);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the raw buffer data with no transform. String is already NULL
|
||||
* terminated at Length+1.
|
||||
*/
|
||||
ACPI_MEMCPY(new_object->string.pointer,
|
||||
original_object->buffer.pointer, length);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
this_name++;
|
||||
}
|
||||
|
||||
*return_object = new_object;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_convert_to_buffer
|
||||
*
|
||||
* PARAMETERS: original_object - Object to be converted
|
||||
* return_object - Where the new converted object is returned
|
||||
*
|
||||
* RETURN: Status. AE_OK if conversion was successful.
|
||||
*
|
||||
* DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
|
||||
union acpi_operand_object **return_object)
|
||||
{
|
||||
union acpi_operand_object *new_object;
|
||||
acpi_status status;
|
||||
union acpi_operand_object **elements;
|
||||
u32 *dword_buffer;
|
||||
u32 count;
|
||||
u32 i;
|
||||
|
||||
switch (original_object->common.type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
/*
|
||||
* Integer-to-Buffer conversion.
|
||||
* Convert the Integer to a packed-byte buffer. _MAT and other
|
||||
* objects need this sometimes, if a read has been performed on a
|
||||
* Field object that is less than or equal to the global integer
|
||||
* size (32 or 64 bits).
|
||||
*/
|
||||
status =
|
||||
acpi_ex_convert_to_buffer(original_object, &new_object);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
/* String-to-Buffer conversion. Simple data copy */
|
||||
|
||||
new_object =
|
||||
acpi_ut_create_buffer_object(original_object->string.
|
||||
length);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
ACPI_MEMCPY(new_object->buffer.pointer,
|
||||
original_object->string.pointer,
|
||||
original_object->string.length);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
/*
|
||||
* This case is often seen for predefined names that must return a
|
||||
* Buffer object with multiple DWORD integers within. For example,
|
||||
* _FDE and _GTM. The Package can be converted to a Buffer.
|
||||
*/
|
||||
|
||||
/* All elements of the Package must be integers */
|
||||
|
||||
elements = original_object->package.elements;
|
||||
count = original_object->package.count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if ((!*elements) ||
|
||||
((*elements)->common.type != ACPI_TYPE_INTEGER)) {
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
elements++;
|
||||
}
|
||||
|
||||
/* Create the new buffer object to replace the Package */
|
||||
|
||||
new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Copy the package elements (integers) to the buffer as DWORDs */
|
||||
|
||||
elements = original_object->package.elements;
|
||||
dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
*dword_buffer = (u32) (*elements)->integer.value;
|
||||
dword_buffer++;
|
||||
elements++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
*return_object = new_object;
|
||||
return (AE_OK);
|
||||
return (NULL); /* Name was not found in the repair table */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
|
|
@ -66,9 +66,9 @@ typedef struct acpi_repair_info {
|
|||
|
||||
/* Local prototypes */
|
||||
|
||||
static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct
|
||||
acpi_namespace_node
|
||||
*node);
|
||||
static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
|
||||
acpi_namespace_node
|
||||
*node);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_repair_ALR(struct acpi_predefined_data *data,
|
||||
|
|
@ -175,7 +175,7 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
|
|||
|
||||
/* Check if this name is in the list of repairable names */
|
||||
|
||||
predefined = acpi_ns_match_repairable_name(node);
|
||||
predefined = acpi_ns_match_complex_repair(node);
|
||||
if (!predefined) {
|
||||
return (validate_status);
|
||||
}
|
||||
|
|
@ -186,7 +186,7 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
|
|||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_match_repairable_name
|
||||
* FUNCTION: acpi_ns_match_complex_repair
|
||||
*
|
||||
* PARAMETERS: node - Namespace node for the method/object
|
||||
*
|
||||
|
|
@ -196,9 +196,9 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct
|
||||
acpi_namespace_node
|
||||
*node)
|
||||
static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
|
||||
acpi_namespace_node
|
||||
*node)
|
||||
{
|
||||
const struct acpi_repair_info *this_name;
|
||||
|
||||
|
|
|
|||
|
|
@ -112,10 +112,10 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
|
|||
|
||||
if (!node) {
|
||||
ACPI_WARNING((AE_INFO, "Null Node parameter"));
|
||||
return_VALUE(ACPI_TYPE_ANY);
|
||||
return_UINT8(ACPI_TYPE_ANY);
|
||||
}
|
||||
|
||||
return_VALUE(node->type);
|
||||
return_UINT8(node->type);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
@ -140,10 +140,10 @@ u32 acpi_ns_local(acpi_object_type type)
|
|||
/* Type code out of range */
|
||||
|
||||
ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
|
||||
return_VALUE(ACPI_NS_NORMAL);
|
||||
return_UINT32(ACPI_NS_NORMAL);
|
||||
}
|
||||
|
||||
return_VALUE(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
|
||||
return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
|
|||
/* Byte 0 is a special case, either bits [0:3] or [0:5] are used */
|
||||
|
||||
package_length |= (aml[0] & byte_zero_mask);
|
||||
return_VALUE(package_length);
|
||||
return_UINT32(package_length);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
|
|
@ -202,6 +202,12 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
|
|||
return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
|
||||
}
|
||||
|
||||
/* Sanity check the length. It must not be zero, or we loop forever */
|
||||
|
||||
if (!resource->length) {
|
||||
return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
|
||||
}
|
||||
|
||||
/* Get the base size of the (external stream) resource descriptor */
|
||||
|
||||
total_size = acpi_gbl_aml_resource_sizes[resource->type];
|
||||
|
|
|
|||
|
|
@ -385,6 +385,14 @@ void acpi_rs_dump_resource_list(struct acpi_resource *resource_list)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Sanity check the length. It must not be zero, or we loop forever */
|
||||
|
||||
if (!resource_list->length) {
|
||||
acpi_os_printf
|
||||
("Invalid zero length descriptor in resource list\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dump the resource descriptor */
|
||||
|
||||
if (type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
|
||||
|
|
|
|||
|
|
@ -178,6 +178,14 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
|
|||
return_ACPI_STATUS(AE_BAD_DATA);
|
||||
}
|
||||
|
||||
/* Sanity check the length. It must not be zero, or we loop forever */
|
||||
|
||||
if (!resource->length) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Invalid zero length descriptor in resource list\n"));
|
||||
return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
|
||||
}
|
||||
|
||||
/* Perform the conversion */
|
||||
|
||||
if (resource->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
|
||||
|
|
|
|||
|
|
@ -563,13 +563,19 @@ acpi_walk_resource_buffer(struct acpi_buffer * buffer,
|
|||
|
||||
while (resource < resource_end) {
|
||||
|
||||
/* Sanity check the resource */
|
||||
/* Sanity check the resource type */
|
||||
|
||||
if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
|
||||
status = AE_AML_INVALID_RESOURCE_TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Sanity check the length. It must not be zero, or we loop forever */
|
||||
|
||||
if (!resource->length) {
|
||||
return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
|
||||
}
|
||||
|
||||
/* Invoke the user function, abort on any error returned */
|
||||
|
||||
status = user_function(resource, context);
|
||||
|
|
|
|||
|
|
@ -559,8 +559,12 @@ static void acpi_tb_validate_fadt(void)
|
|||
/*
|
||||
* For each extended field, check for length mismatch between the
|
||||
* legacy length field and the corresponding 64-bit X length field.
|
||||
* Note: If the legacy length field is > 0xFF bits, ignore this
|
||||
* check. (GPE registers can be larger than the 64-bit GAS structure
|
||||
* can accomodate, 0xFF bits).
|
||||
*/
|
||||
if (address64->address &&
|
||||
(ACPI_MUL_8(length) <= ACPI_UINT8_MAX) &&
|
||||
(address64->bit_width != ACPI_MUL_8(length))) {
|
||||
ACPI_BIOS_WARNING((AE_INFO,
|
||||
"32/64X length mismatch in FADT/%s: %u/%u",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Module Name: tbxface - ACPI table oriented external interfaces
|
||||
* Module Name: tbxface - ACPI table-oriented external interfaces
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ acpi_status acpi_allocate_root_table(u32 initial_table_count)
|
|||
* array is dynamically allocated.
|
||||
* initial_table_count - Size of initial_table_array, in number of
|
||||
* struct acpi_table_desc structures
|
||||
* allow_realloc - Flag to tell Table Manager if resize of
|
||||
* allow_resize - Flag to tell Table Manager if resize of
|
||||
* pre-allocated array is allowed. Ignored
|
||||
* if initial_table_array is NULL.
|
||||
*
|
||||
|
|
@ -107,8 +107,8 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
|
|||
ACPI_FUNCTION_TRACE(acpi_initialize_tables);
|
||||
|
||||
/*
|
||||
* Set up the Root Table Array
|
||||
* Allocate the table array if requested
|
||||
* Setup the Root Table Array and allocate the table array
|
||||
* if requested
|
||||
*/
|
||||
if (!initial_table_array) {
|
||||
status = acpi_allocate_root_table(initial_table_count);
|
||||
|
|
@ -305,9 +305,10 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
|
|||
* instance - Which instance (for SSDTs)
|
||||
* out_table - Where the pointer to the table is returned
|
||||
*
|
||||
* RETURN: Status and pointer to table
|
||||
* RETURN: Status and pointer to the requested table
|
||||
*
|
||||
* DESCRIPTION: Finds and verifies an ACPI table.
|
||||
* DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
|
||||
* RSDT/XSDT.
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
|
|
@ -375,9 +376,10 @@ ACPI_EXPORT_SYMBOL(acpi_get_table)
|
|||
* PARAMETERS: table_index - Table index
|
||||
* table - Where the pointer to the table is returned
|
||||
*
|
||||
* RETURN: Status and pointer to the table
|
||||
* RETURN: Status and pointer to the requested table
|
||||
*
|
||||
* DESCRIPTION: Obtain a table by an index into the global table list.
|
||||
* DESCRIPTION: Obtain a table by an index into the global table list. Used
|
||||
* internally also.
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
|
|
@ -432,7 +434,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
|
|||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Install table event handler
|
||||
* DESCRIPTION: Install a global table event handler.
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
|
|
@ -479,7 +481,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_table_handler)
|
|||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Remove table event handler
|
||||
* DESCRIPTION: Remove a table event handler
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_remove_table_handler(acpi_table_handler handler)
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id,
|
|||
|
||||
if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
|
||||
(space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
|
||||
return_VALUE(0);
|
||||
return_UINT32(0);
|
||||
}
|
||||
|
||||
range_info = acpi_gbl_address_range_list[space_id];
|
||||
|
|
@ -256,7 +256,7 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id,
|
|||
range_info = range_info->next;
|
||||
}
|
||||
|
||||
return_VALUE(overlap_count);
|
||||
return_UINT32(overlap_count);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@ acpi_os_create_cache(char *cache_name,
|
|||
/* Populate the cache object and return it */
|
||||
|
||||
ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
|
||||
cache->link_offset = 8;
|
||||
cache->list_name = cache_name;
|
||||
cache->object_size = object_size;
|
||||
cache->max_depth = max_depth;
|
||||
|
|
@ -108,7 +107,7 @@ acpi_os_create_cache(char *cache_name,
|
|||
|
||||
acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
|
||||
{
|
||||
char *next;
|
||||
void *next;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
|
@ -128,10 +127,7 @@ acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
|
|||
|
||||
/* Delete and unlink one cached state object */
|
||||
|
||||
next = *(ACPI_CAST_INDIRECT_PTR(char,
|
||||
&(((char *)cache->
|
||||
list_head)[cache->
|
||||
link_offset])));
|
||||
next = ACPI_GET_DESCRIPTOR_PTR(cache->list_head);
|
||||
ACPI_FREE(cache->list_head);
|
||||
|
||||
cache->list_head = next;
|
||||
|
|
@ -221,10 +217,7 @@ acpi_os_release_object(struct acpi_memory_list * cache, void *object)
|
|||
|
||||
/* Put the object at the head of the cache list */
|
||||
|
||||
*(ACPI_CAST_INDIRECT_PTR(char,
|
||||
&(((char *)object)[cache->
|
||||
link_offset]))) =
|
||||
cache->list_head;
|
||||
ACPI_SET_DESCRIPTOR_PTR(object, cache->list_head);
|
||||
cache->list_head = object;
|
||||
cache->current_depth++;
|
||||
|
||||
|
|
@ -272,10 +265,7 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache)
|
|||
/* There is an object available, use it */
|
||||
|
||||
object = cache->list_head;
|
||||
cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char,
|
||||
&(((char *)
|
||||
object)[cache->
|
||||
link_offset])));
|
||||
cache->list_head = ACPI_GET_DESCRIPTOR_PTR(object);
|
||||
|
||||
cache->current_depth--;
|
||||
|
||||
|
|
|
|||
|
|
@ -359,19 +359,20 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list)
|
|||
* FUNCTION: acpi_ut_update_ref_count
|
||||
*
|
||||
* PARAMETERS: object - Object whose ref count is to be updated
|
||||
* action - What to do
|
||||
* action - What to do (REF_INCREMENT or REF_DECREMENT)
|
||||
*
|
||||
* RETURN: New ref count
|
||||
* RETURN: None. Sets new reference count within the object
|
||||
*
|
||||
* DESCRIPTION: Modify the ref count and return it.
|
||||
* DESCRIPTION: Modify the reference count for an internal acpi object
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void
|
||||
acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
|
||||
{
|
||||
u16 count;
|
||||
u16 new_count;
|
||||
u16 original_count;
|
||||
u16 new_count = 0;
|
||||
acpi_cpu_flags lock_flags;
|
||||
|
||||
ACPI_FUNCTION_NAME(ut_update_ref_count);
|
||||
|
||||
|
|
@ -379,76 +380,79 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
|
|||
return;
|
||||
}
|
||||
|
||||
count = object->common.reference_count;
|
||||
new_count = count;
|
||||
|
||||
/*
|
||||
* Perform the reference count action (increment, decrement, force delete)
|
||||
* Always get the reference count lock. Note: Interpreter and/or
|
||||
* Namespace is not always locked when this function is called.
|
||||
*/
|
||||
lock_flags = acpi_os_acquire_lock(acpi_gbl_reference_count_lock);
|
||||
original_count = object->common.reference_count;
|
||||
|
||||
/* Perform the reference count action (increment, decrement) */
|
||||
|
||||
switch (action) {
|
||||
case REF_INCREMENT:
|
||||
|
||||
new_count++;
|
||||
new_count = original_count + 1;
|
||||
object->common.reference_count = new_count;
|
||||
acpi_os_release_lock(acpi_gbl_reference_count_lock, lock_flags);
|
||||
|
||||
/* The current reference count should never be zero here */
|
||||
|
||||
if (!original_count) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Obj %p, Reference Count was zero before increment\n",
|
||||
object));
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
|
||||
"Obj %p Refs=%X, [Incremented]\n",
|
||||
object, new_count));
|
||||
"Obj %p Type %.2X Refs %.2X [Incremented]\n",
|
||||
object, object->common.type, new_count));
|
||||
break;
|
||||
|
||||
case REF_DECREMENT:
|
||||
|
||||
if (count < 1) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
|
||||
"Obj %p Refs=%X, can't decrement! (Set to 0)\n",
|
||||
object, new_count));
|
||||
/* The current reference count must be non-zero */
|
||||
|
||||
new_count = 0;
|
||||
} else {
|
||||
new_count--;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
|
||||
"Obj %p Refs=%X, [Decremented]\n",
|
||||
object, new_count));
|
||||
if (original_count) {
|
||||
new_count = original_count - 1;
|
||||
object->common.reference_count = new_count;
|
||||
}
|
||||
|
||||
if (object->common.type == ACPI_TYPE_METHOD) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
|
||||
"Method Obj %p Refs=%X, [Decremented]\n",
|
||||
object, new_count));
|
||||
acpi_os_release_lock(acpi_gbl_reference_count_lock, lock_flags);
|
||||
|
||||
if (!original_count) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Obj %p, Reference Count is already zero, cannot decrement\n",
|
||||
object));
|
||||
}
|
||||
|
||||
object->common.reference_count = new_count;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
|
||||
"Obj %p Type %.2X Refs %.2X [Decremented]\n",
|
||||
object, object->common.type, new_count));
|
||||
|
||||
/* Actually delete the object on a reference count of zero */
|
||||
|
||||
if (new_count == 0) {
|
||||
acpi_ut_delete_internal_obj(object);
|
||||
}
|
||||
break;
|
||||
|
||||
case REF_FORCE_DELETE:
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
|
||||
"Obj %p Refs=%X, Force delete! (Set to 0)\n",
|
||||
object, count));
|
||||
|
||||
new_count = 0;
|
||||
object->common.reference_count = new_count;
|
||||
acpi_ut_delete_internal_obj(object);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO, "Unknown action (0x%X)", action));
|
||||
break;
|
||||
acpi_os_release_lock(acpi_gbl_reference_count_lock, lock_flags);
|
||||
ACPI_ERROR((AE_INFO, "Unknown Reference Count action (0x%X)",
|
||||
action));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check the reference count, for debug purposes only.
|
||||
* (A deleted object will have a huge reference count)
|
||||
*/
|
||||
if (count > ACPI_MAX_REFERENCE_COUNT) {
|
||||
if (new_count > ACPI_MAX_REFERENCE_COUNT) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Large Reference Count (0x%X) in object %p",
|
||||
count, object));
|
||||
"Large Reference Count (0x%X) in object %p, Type=0x%.2X",
|
||||
new_count, object, object->common.type));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -458,8 +462,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
|
|||
*
|
||||
* PARAMETERS: object - Increment ref count for this object
|
||||
* and all sub-objects
|
||||
* action - Either REF_INCREMENT or REF_DECREMENT or
|
||||
* REF_FORCE_DELETE
|
||||
* action - Either REF_INCREMENT or REF_DECREMENT
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
|
|
@ -714,7 +717,6 @@ void acpi_ut_remove_reference(union acpi_operand_object *object)
|
|||
/*
|
||||
* Allow a NULL pointer to be passed in, just ignore it. This saves
|
||||
* each caller from having to check. Also, ignore NS nodes.
|
||||
*
|
||||
*/
|
||||
if (!object ||
|
||||
(ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED)) {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ ACPI_MODULE_NAME("utexcep")
|
|||
******************************************************************************/
|
||||
const char *acpi_format_exception(acpi_status status)
|
||||
{
|
||||
const char *exception = NULL;
|
||||
const struct acpi_exception_info *exception;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
|
|
@ -76,10 +76,10 @@ const char *acpi_format_exception(acpi_status status)
|
|||
ACPI_ERROR((AE_INFO,
|
||||
"Unknown exception code: 0x%8.8X", status));
|
||||
|
||||
exception = "UNKNOWN_STATUS_CODE";
|
||||
return ("UNKNOWN_STATUS_CODE");
|
||||
}
|
||||
|
||||
return (ACPI_CAST_PTR(const char, exception));
|
||||
return (exception->name);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_format_exception)
|
||||
|
|
@ -97,10 +97,10 @@ ACPI_EXPORT_SYMBOL(acpi_format_exception)
|
|||
* an ASCII string.
|
||||
*
|
||||
******************************************************************************/
|
||||
const char *acpi_ut_validate_exception(acpi_status status)
|
||||
const struct acpi_exception_info *acpi_ut_validate_exception(acpi_status status)
|
||||
{
|
||||
u32 sub_status;
|
||||
const char *exception = NULL;
|
||||
const struct acpi_exception_info *exception = NULL;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
|
|
@ -113,35 +113,35 @@ const char *acpi_ut_validate_exception(acpi_status status)
|
|||
case AE_CODE_ENVIRONMENTAL:
|
||||
|
||||
if (sub_status <= AE_CODE_ENV_MAX) {
|
||||
exception = acpi_gbl_exception_names_env[sub_status];
|
||||
exception = &acpi_gbl_exception_names_env[sub_status];
|
||||
}
|
||||
break;
|
||||
|
||||
case AE_CODE_PROGRAMMER:
|
||||
|
||||
if (sub_status <= AE_CODE_PGM_MAX) {
|
||||
exception = acpi_gbl_exception_names_pgm[sub_status];
|
||||
exception = &acpi_gbl_exception_names_pgm[sub_status];
|
||||
}
|
||||
break;
|
||||
|
||||
case AE_CODE_ACPI_TABLES:
|
||||
|
||||
if (sub_status <= AE_CODE_TBL_MAX) {
|
||||
exception = acpi_gbl_exception_names_tbl[sub_status];
|
||||
exception = &acpi_gbl_exception_names_tbl[sub_status];
|
||||
}
|
||||
break;
|
||||
|
||||
case AE_CODE_AML:
|
||||
|
||||
if (sub_status <= AE_CODE_AML_MAX) {
|
||||
exception = acpi_gbl_exception_names_aml[sub_status];
|
||||
exception = &acpi_gbl_exception_names_aml[sub_status];
|
||||
}
|
||||
break;
|
||||
|
||||
case AE_CODE_CONTROL:
|
||||
|
||||
if (sub_status <= AE_CODE_CTRL_MAX) {
|
||||
exception = acpi_gbl_exception_names_ctrl[sub_status];
|
||||
exception = &acpi_gbl_exception_names_ctrl[sub_status];
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -149,5 +149,9 @@ const char *acpi_ut_validate_exception(acpi_status status)
|
|||
break;
|
||||
}
|
||||
|
||||
return (ACPI_CAST_PTR(const char, exception));
|
||||
if (!exception || !exception->name) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (exception);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -359,6 +359,8 @@ acpi_status acpi_ut_init_globals(void)
|
|||
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
acpi_gbl_external_list = NULL;
|
||||
acpi_gbl_num_external_methods = 0;
|
||||
acpi_gbl_resolved_external_methods = 0;
|
||||
#endif
|
||||
|
||||
#ifdef ACPI_DEBUG_OUTPUT
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ acpi_status acpi_ut_mutex_initialize(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* Create the spinlocks for use at interrupt level */
|
||||
/* Create the spinlocks for use at interrupt level or for speed */
|
||||
|
||||
status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
|
|
@ -93,7 +93,13 @@ acpi_status acpi_ut_mutex_initialize(void)
|
|||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
status = acpi_os_create_lock(&acpi_gbl_reference_count_lock);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Mutex for _OSI support */
|
||||
|
||||
status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
|
|
@ -136,6 +142,7 @@ void acpi_ut_mutex_terminate(void)
|
|||
|
||||
acpi_os_delete_lock(acpi_gbl_gpe_lock);
|
||||
acpi_os_delete_lock(acpi_gbl_hardware_lock);
|
||||
acpi_os_delete_lock(acpi_gbl_reference_count_lock);
|
||||
|
||||
/* Delete the reader/writer lock */
|
||||
|
||||
|
|
|
|||
|
|
@ -108,9 +108,14 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = {
|
|||
|
||||
acpi_status acpi_ut_initialize_interfaces(void)
|
||||
{
|
||||
acpi_status status;
|
||||
u32 i;
|
||||
|
||||
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
acpi_gbl_supported_interfaces = acpi_default_supported_interfaces;
|
||||
|
||||
/* Link the static list of supported interfaces */
|
||||
|
|
@ -132,20 +137,24 @@ acpi_status acpi_ut_initialize_interfaces(void)
|
|||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: None
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Delete all interfaces in the global list. Sets
|
||||
* acpi_gbl_supported_interfaces to NULL.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_ut_interface_terminate(void)
|
||||
acpi_status acpi_ut_interface_terminate(void)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_interface_info *next_interface;
|
||||
|
||||
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
next_interface = acpi_gbl_supported_interfaces;
|
||||
status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
next_interface = acpi_gbl_supported_interfaces;
|
||||
while (next_interface) {
|
||||
acpi_gbl_supported_interfaces = next_interface->next;
|
||||
|
||||
|
|
@ -160,6 +169,7 @@ void acpi_ut_interface_terminate(void)
|
|||
}
|
||||
|
||||
acpi_os_release_mutex(acpi_gbl_osi_mutex);
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
@ -315,6 +325,7 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state * walk_state)
|
|||
union acpi_operand_object *return_desc;
|
||||
struct acpi_interface_info *interface_info;
|
||||
acpi_interface_handler interface_handler;
|
||||
acpi_status status;
|
||||
u32 return_value;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_osi_implementation);
|
||||
|
|
@ -336,7 +347,10 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state * walk_state)
|
|||
/* Default return value is 0, NOT SUPPORTED */
|
||||
|
||||
return_value = 0;
|
||||
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* Lookup the interface in the global _OSI list */
|
||||
|
||||
|
|
|
|||
399
drivers/acpi/acpica/utpredef.c
Normal file
399
drivers/acpi/acpica/utpredef.c
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Module Name: utpredef - support functions for predefined names
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2013, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acpredef.h"
|
||||
|
||||
#define _COMPONENT ACPI_UTILITIES
|
||||
ACPI_MODULE_NAME("utpredef")
|
||||
|
||||
/*
|
||||
* Names for the types that can be returned by the predefined objects.
|
||||
* Used for warning messages. Must be in the same order as the ACPI_RTYPEs
|
||||
*/
|
||||
static const char *ut_rtype_names[] = {
|
||||
"/Integer",
|
||||
"/String",
|
||||
"/Buffer",
|
||||
"/Package",
|
||||
"/Reference",
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_get_next_predefined_method
|
||||
*
|
||||
* PARAMETERS: this_name - Entry in the predefined method/name table
|
||||
*
|
||||
* RETURN: Pointer to next entry in predefined table.
|
||||
*
|
||||
* DESCRIPTION: Get the next entry in the predefine method table. Handles the
|
||||
* cases where a package info entry follows a method name that
|
||||
* returns a package.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
const union acpi_predefined_info *acpi_ut_get_next_predefined_method(const union
|
||||
acpi_predefined_info
|
||||
*this_name)
|
||||
{
|
||||
|
||||
/*
|
||||
* Skip next entry in the table if this name returns a Package
|
||||
* (next entry contains the package info)
|
||||
*/
|
||||
if ((this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) &&
|
||||
(this_name->info.expected_btypes != ACPI_RTYPE_ALL)) {
|
||||
this_name++;
|
||||
}
|
||||
|
||||
this_name++;
|
||||
return (this_name);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_match_predefined_method
|
||||
*
|
||||
* PARAMETERS: name - Name to find
|
||||
*
|
||||
* RETURN: Pointer to entry in predefined table. NULL indicates not found.
|
||||
*
|
||||
* DESCRIPTION: Check an object name against the predefined object list.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
const union acpi_predefined_info *acpi_ut_match_predefined_method(char *name)
|
||||
{
|
||||
const union acpi_predefined_info *this_name;
|
||||
|
||||
/* Quick check for a predefined name, first character must be underscore */
|
||||
|
||||
if (name[0] != '_') {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Search info table for a predefined method/object name */
|
||||
|
||||
this_name = acpi_gbl_predefined_methods;
|
||||
while (this_name->info.name[0]) {
|
||||
if (ACPI_COMPARE_NAME(name, this_name->info.name)) {
|
||||
return (this_name);
|
||||
}
|
||||
|
||||
this_name = acpi_ut_get_next_predefined_method(this_name);
|
||||
}
|
||||
|
||||
return (NULL); /* Not found */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_get_expected_return_types
|
||||
*
|
||||
* PARAMETERS: buffer - Where the formatted string is returned
|
||||
* expected_Btypes - Bitfield of expected data types
|
||||
*
|
||||
* RETURN: Formatted string in Buffer.
|
||||
*
|
||||
* DESCRIPTION: Format the expected object types into a printable string.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_ut_get_expected_return_types(char *buffer, u32 expected_btypes)
|
||||
{
|
||||
u32 this_rtype;
|
||||
u32 i;
|
||||
u32 j;
|
||||
|
||||
j = 1;
|
||||
buffer[0] = 0;
|
||||
this_rtype = ACPI_RTYPE_INTEGER;
|
||||
|
||||
for (i = 0; i < ACPI_NUM_RTYPES; i++) {
|
||||
|
||||
/* If one of the expected types, concatenate the name of this type */
|
||||
|
||||
if (expected_btypes & this_rtype) {
|
||||
ACPI_STRCAT(buffer, &ut_rtype_names[i][j]);
|
||||
j = 0; /* Use name separator from now on */
|
||||
}
|
||||
|
||||
this_rtype <<= 1; /* Next Rtype */
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* The remaining functions are used by iASL and acpi_help only
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#if (defined ACPI_ASL_COMPILER || defined ACPI_HELP_APP)
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Local prototypes */
|
||||
|
||||
static u32 acpi_ut_get_argument_types(char *buffer, u16 argument_types);
|
||||
|
||||
/* Types that can be returned externally by a predefined name */
|
||||
|
||||
static const char *ut_external_type_names[] = /* Indexed by ACPI_TYPE_* */
|
||||
{
|
||||
", UNSUPPORTED-TYPE",
|
||||
", Integer",
|
||||
", String",
|
||||
", Buffer",
|
||||
", Package"
|
||||
};
|
||||
|
||||
/* Bit widths for resource descriptor predefined names */
|
||||
|
||||
static const char *ut_resource_type_names[] = {
|
||||
"/1",
|
||||
"/2",
|
||||
"/3",
|
||||
"/8",
|
||||
"/16",
|
||||
"/32",
|
||||
"/64",
|
||||
"/variable",
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_match_resource_name
|
||||
*
|
||||
* PARAMETERS: name - Name to find
|
||||
*
|
||||
* RETURN: Pointer to entry in the resource table. NULL indicates not
|
||||
* found.
|
||||
*
|
||||
* DESCRIPTION: Check an object name against the predefined resource
|
||||
* descriptor object list.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
const union acpi_predefined_info *acpi_ut_match_resource_name(char *name)
|
||||
{
|
||||
const union acpi_predefined_info *this_name;
|
||||
|
||||
/* Quick check for a predefined name, first character must be underscore */
|
||||
|
||||
if (name[0] != '_') {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Search info table for a predefined method/object name */
|
||||
|
||||
this_name = acpi_gbl_resource_names;
|
||||
while (this_name->info.name[0]) {
|
||||
if (ACPI_COMPARE_NAME(name, this_name->info.name)) {
|
||||
return (this_name);
|
||||
}
|
||||
|
||||
this_name++;
|
||||
}
|
||||
|
||||
return (NULL); /* Not found */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_display_predefined_method
|
||||
*
|
||||
* PARAMETERS: buffer - Scratch buffer for this function
|
||||
* this_name - Entry in the predefined method/name table
|
||||
* multi_line - TRUE if output should be on >1 line
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Display information about a predefined method. Number and
|
||||
* type of the input arguments, and expected type(s) for the
|
||||
* return value, if any.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ut_display_predefined_method(char *buffer,
|
||||
const union acpi_predefined_info *this_name,
|
||||
u8 multi_line)
|
||||
{
|
||||
u32 arg_count;
|
||||
|
||||
/*
|
||||
* Get the argument count and the string buffer
|
||||
* containing all argument types
|
||||
*/
|
||||
arg_count = acpi_ut_get_argument_types(buffer,
|
||||
this_name->info.argument_list);
|
||||
|
||||
if (multi_line) {
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf("%4.4s Requires %s%u argument%s",
|
||||
this_name->info.name,
|
||||
(this_name->info.argument_list & ARG_COUNT_IS_MINIMUM) ?
|
||||
"(at least) " : "", arg_count, arg_count != 1 ? "s" : "");
|
||||
|
||||
/* Display the types for any arguments */
|
||||
|
||||
if (arg_count > 0) {
|
||||
printf(" (%s)", buffer);
|
||||
}
|
||||
|
||||
if (multi_line) {
|
||||
printf("\n ");
|
||||
}
|
||||
|
||||
/* Get the return value type(s) allowed */
|
||||
|
||||
if (this_name->info.expected_btypes) {
|
||||
acpi_ut_get_expected_return_types(buffer,
|
||||
this_name->info.
|
||||
expected_btypes);
|
||||
printf(" Return value types: %s\n", buffer);
|
||||
} else {
|
||||
printf(" No return value\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_get_argument_types
|
||||
*
|
||||
* PARAMETERS: buffer - Where to return the formatted types
|
||||
* argument_types - Types field for this method
|
||||
*
|
||||
* RETURN: count - the number of arguments required for this method
|
||||
*
|
||||
* DESCRIPTION: Format the required data types for this method (Integer,
|
||||
* String, Buffer, or Package) and return the required argument
|
||||
* count.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static u32 acpi_ut_get_argument_types(char *buffer, u16 argument_types)
|
||||
{
|
||||
u16 this_argument_type;
|
||||
u16 sub_index;
|
||||
u16 arg_count;
|
||||
u32 i;
|
||||
|
||||
*buffer = 0;
|
||||
sub_index = 2;
|
||||
|
||||
/* First field in the types list is the count of args to follow */
|
||||
|
||||
arg_count = (argument_types & METHOD_ARG_MASK);
|
||||
argument_types >>= METHOD_ARG_BIT_WIDTH;
|
||||
|
||||
if (arg_count > METHOD_PREDEF_ARGS_MAX) {
|
||||
printf("**** Invalid argument count (%u) "
|
||||
"in predefined info structure\n", arg_count);
|
||||
return (arg_count);
|
||||
}
|
||||
|
||||
/* Get each argument from the list, convert to ascii, store to buffer */
|
||||
|
||||
for (i = 0; i < arg_count; i++) {
|
||||
this_argument_type = (argument_types & METHOD_ARG_MASK);
|
||||
if (!this_argument_type
|
||||
|| (this_argument_type > METHOD_MAX_ARG_TYPE)) {
|
||||
printf("**** Invalid argument type (%u) "
|
||||
"in predefined info structure\n",
|
||||
this_argument_type);
|
||||
return (arg_count);
|
||||
}
|
||||
|
||||
strcat(buffer,
|
||||
ut_external_type_names[this_argument_type] + sub_index);
|
||||
|
||||
/* Shift to next argument type field */
|
||||
|
||||
argument_types >>= METHOD_ARG_BIT_WIDTH;
|
||||
sub_index = 0;
|
||||
}
|
||||
|
||||
return (arg_count);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_get_resource_bit_width
|
||||
*
|
||||
* PARAMETERS: buffer - Where the formatted string is returned
|
||||
* types - Bitfield of expected data types
|
||||
*
|
||||
* RETURN: Count of return types. Formatted string in Buffer.
|
||||
*
|
||||
* DESCRIPTION: Format the resource bit widths into a printable string.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u32 acpi_ut_get_resource_bit_width(char *buffer, u16 types)
|
||||
{
|
||||
u32 i;
|
||||
u16 sub_index;
|
||||
u32 found;
|
||||
|
||||
*buffer = 0;
|
||||
sub_index = 1;
|
||||
found = 0;
|
||||
|
||||
for (i = 0; i < NUM_RESOURCE_WIDTHS; i++) {
|
||||
if (types & 1) {
|
||||
strcat(buffer, &(ut_resource_type_names[i][sub_index]));
|
||||
sub_index = 0;
|
||||
found++;
|
||||
}
|
||||
|
||||
types >>= 1;
|
||||
}
|
||||
|
||||
return (found);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -287,7 +287,10 @@ acpi_status acpi_install_interface(acpi_string interface_name)
|
|||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* Check if the interface name is already in the global list */
|
||||
|
||||
|
|
@ -336,7 +339,10 @@ acpi_status acpi_remove_interface(acpi_string interface_name)
|
|||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
status = acpi_ut_remove_interface(interface_name);
|
||||
|
||||
|
|
@ -362,9 +368,12 @@ ACPI_EXPORT_SYMBOL(acpi_remove_interface)
|
|||
****************************************************************************/
|
||||
acpi_status acpi_install_interface_handler(acpi_interface_handler handler)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
acpi_status status;
|
||||
|
||||
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
if (handler && acpi_gbl_interface_handler) {
|
||||
status = AE_ALREADY_EXISTS;
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ struct acpi_battery {
|
|||
|
||||
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
|
||||
|
||||
inline int acpi_battery_present(struct acpi_battery *battery)
|
||||
static inline int acpi_battery_present(struct acpi_battery *battery)
|
||||
{
|
||||
return battery->device->status.battery_present;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,13 +288,12 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
|
|||
}
|
||||
out_success:
|
||||
context->ret.length = out_obj->buffer.length;
|
||||
context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL);
|
||||
context->ret.pointer = kmemdup(out_obj->buffer.pointer,
|
||||
context->ret.length, GFP_KERNEL);
|
||||
if (!context->ret.pointer) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto out_kfree;
|
||||
}
|
||||
memcpy(context->ret.pointer, out_obj->buffer.pointer,
|
||||
context->ret.length);
|
||||
status = AE_OK;
|
||||
|
||||
out_kfree:
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <acpi/button.h>
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* acpi_container.c - ACPI Generic Container Driver
|
||||
* ($Revision: )
|
||||
* container.c - ACPI Generic Container Driver
|
||||
*
|
||||
* Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
|
||||
* Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
|
||||
* Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
|
||||
* Copyright (C) 2004 Intel Corp.
|
||||
* Copyright (C) 2004 FUJITSU LIMITED
|
||||
* Copyright (C) 2004, 2013 Intel Corp.
|
||||
* Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
|
|
@ -26,14 +26,11 @@
|
|||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
|
|
@ -50,141 +47,20 @@ static const struct acpi_device_id container_device_ids[] = {
|
|||
static int container_device_attach(struct acpi_device *device,
|
||||
const struct acpi_device_id *not_used)
|
||||
{
|
||||
/*
|
||||
* FIXME: This is necessary, so that acpi_eject_store() doesn't return
|
||||
* -ENODEV for containers.
|
||||
*/
|
||||
/* This is necessary for container hotplug to work. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct acpi_scan_handler container_device_handler = {
|
||||
static struct acpi_scan_handler container_handler = {
|
||||
.ids = container_device_ids,
|
||||
.attach = container_device_attach,
|
||||
.hotplug = {
|
||||
.enabled = true,
|
||||
.mode = AHM_CONTAINER,
|
||||
},
|
||||
};
|
||||
|
||||
static int is_device_present(acpi_handle handle)
|
||||
{
|
||||
acpi_handle temp;
|
||||
acpi_status status;
|
||||
unsigned long long sta;
|
||||
|
||||
|
||||
status = acpi_get_handle(handle, "_STA", &temp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return 1; /* _STA not found, assume device present */
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
|
||||
if (ACPI_FAILURE(status))
|
||||
return 0; /* Firmware error */
|
||||
|
||||
return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
|
||||
}
|
||||
|
||||
static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
int result;
|
||||
int present;
|
||||
acpi_status status;
|
||||
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
|
||||
|
||||
acpi_scan_lock_acquire();
|
||||
|
||||
switch (type) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
/* Fall through */
|
||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||
pr_debug("Container driver received %s event\n",
|
||||
(type == ACPI_NOTIFY_BUS_CHECK) ?
|
||||
"ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
|
||||
|
||||
present = is_device_present(handle);
|
||||
status = acpi_bus_get_device(handle, &device);
|
||||
if (!present) {
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
/* device exist and this is a remove request */
|
||||
device->flags.eject_pending = 1;
|
||||
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ACPI_FAILURE(status) || device)
|
||||
break;
|
||||
|
||||
result = acpi_bus_scan(handle);
|
||||
if (result) {
|
||||
acpi_handle_warn(handle, "Failed to add container\n");
|
||||
break;
|
||||
}
|
||||
result = acpi_bus_get_device(handle, &device);
|
||||
if (result) {
|
||||
acpi_handle_warn(handle, "Missing device object\n");
|
||||
break;
|
||||
}
|
||||
|
||||
kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
|
||||
ost_code = ACPI_OST_SC_SUCCESS;
|
||||
break;
|
||||
|
||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||
if (!acpi_bus_get_device(handle, &device) && device) {
|
||||
device->flags.eject_pending = 1;
|
||||
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* non-hotplug event; possibly handled by other handler */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Inform firmware that the hotplug operation has completed */
|
||||
(void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
|
||||
|
||||
out:
|
||||
acpi_scan_lock_release();
|
||||
}
|
||||
|
||||
static bool is_container(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device_info *info;
|
||||
bool ret = false;
|
||||
|
||||
if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
|
||||
return false;
|
||||
|
||||
if (info->valid & ACPI_VALID_HID) {
|
||||
const struct acpi_device_id *id;
|
||||
|
||||
for (id = container_device_ids; id->id[0]; id++) {
|
||||
ret = !strcmp((char *)id->id, info->hardware_id.string);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
kfree(info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
|
||||
u32 lvl, void *ctxt,
|
||||
void **retv)
|
||||
{
|
||||
if (is_container(handle))
|
||||
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||
container_notify_cb, NULL);
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
void __init acpi_container_init(void)
|
||||
{
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
|
||||
acpi_container_register_notify_handler, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
acpi_scan_add_handler(&container_device_handler);
|
||||
acpi_scan_add_handler_with_hotplug(&container_handler, "container");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,27 +145,36 @@ int acpi_device_get_power(struct acpi_device *device, int *state)
|
|||
}
|
||||
|
||||
/*
|
||||
* Get the device's power state either directly (via _PSC) or
|
||||
* indirectly (via power resources).
|
||||
* Get the device's power state from power resources settings and _PSC,
|
||||
* if available.
|
||||
*/
|
||||
if (device->power.flags.explicit_get) {
|
||||
unsigned long long psc;
|
||||
acpi_status status = acpi_evaluate_integer(device->handle,
|
||||
"_PSC", NULL, &psc);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
result = psc;
|
||||
}
|
||||
/* The test below covers ACPI_STATE_UNKNOWN too. */
|
||||
if (result <= ACPI_STATE_D2) {
|
||||
; /* Do nothing. */
|
||||
} else if (device->power.flags.power_resources) {
|
||||
if (device->power.flags.power_resources) {
|
||||
int error = acpi_power_get_inferred_state(device, &result);
|
||||
if (error)
|
||||
return error;
|
||||
} else if (result == ACPI_STATE_D3_HOT) {
|
||||
result = ACPI_STATE_D3;
|
||||
}
|
||||
if (device->power.flags.explicit_get) {
|
||||
acpi_handle handle = device->handle;
|
||||
unsigned long long psc;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_PSC", NULL, &psc);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* The power resources settings may indicate a power state
|
||||
* shallower than the actual power state of the device.
|
||||
*
|
||||
* Moreover, on systems predating ACPI 4.0, if the device
|
||||
* doesn't depend on any power resources and _PSC returns 3,
|
||||
* that means "power off". We need to maintain compatibility
|
||||
* with those systems.
|
||||
*/
|
||||
if (psc > result && psc < ACPI_STATE_D3_COLD)
|
||||
result = psc;
|
||||
else if (result == ACPI_STATE_UNKNOWN)
|
||||
result = psc > ACPI_STATE_D2 ? ACPI_STATE_D3_COLD : psc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -174,9 +174,13 @@ static int acpi_fan_add(struct acpi_device *device)
|
|||
|
||||
static int acpi_fan_remove(struct acpi_device *device)
|
||||
{
|
||||
struct thermal_cooling_device *cdev = acpi_driver_data(device);
|
||||
struct thermal_cooling_device *cdev;
|
||||
|
||||
if (!device || !cdev)
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
cdev = acpi_driver_data(device);
|
||||
if (!cdev)
|
||||
return -EINVAL;
|
||||
|
||||
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
|
||||
|
|
|
|||
|
|
@ -41,6 +41,17 @@ void acpi_container_init(void);
|
|||
#else
|
||||
static inline void acpi_container_init(void) {}
|
||||
#endif
|
||||
#ifdef CONFIG_ACPI_HOTPLUG_MEMORY
|
||||
void acpi_memory_hotplug_init(void);
|
||||
#else
|
||||
static inline void acpi_memory_hotplug_init(void) {}
|
||||
#endif
|
||||
|
||||
void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
|
||||
const char *name);
|
||||
int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
|
||||
const char *hotplug_profile_name);
|
||||
void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern struct dentry *acpi_debugfs_dir;
|
||||
|
|
@ -48,6 +59,11 @@ int acpi_debugfs_init(void);
|
|||
#else
|
||||
static inline void acpi_debugfs_init(void) { return; }
|
||||
#endif
|
||||
#ifdef CONFIG_X86_INTEL_LPSS
|
||||
void acpi_lpss_init(void);
|
||||
#else
|
||||
static inline void acpi_lpss_init(void) {}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Device Node Initialization / Removal
|
||||
|
|
@ -60,7 +76,7 @@ int acpi_device_add(struct acpi_device *device,
|
|||
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
|
||||
int type, unsigned long long sta);
|
||||
void acpi_device_add_finalize(struct acpi_device *device);
|
||||
void acpi_free_ids(struct acpi_device *device);
|
||||
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Power Resource
|
||||
|
|
@ -131,4 +147,7 @@ static inline void suspend_nvs_restore(void) {}
|
|||
-------------------------------------------------------------------------- */
|
||||
struct platform_device;
|
||||
|
||||
int acpi_create_platform_device(struct acpi_device *adev,
|
||||
const struct acpi_device_id *id);
|
||||
|
||||
#endif /* _ACPI_INTERNAL_H_ */
|
||||
|
|
|
|||
|
|
@ -641,7 +641,7 @@ void __init acpi_initrd_override(void *data, size_t size)
|
|||
* Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
|
||||
* works fine.
|
||||
*/
|
||||
memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size);
|
||||
memblock_reserve(acpi_tables_addr, all_tables_size);
|
||||
arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
|
||||
|
||||
p = early_ioremap(acpi_tables_addr, all_tables_size);
|
||||
|
|
@ -1555,7 +1555,7 @@ int acpi_check_resource_conflict(const struct resource *res)
|
|||
else
|
||||
space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY;
|
||||
|
||||
length = res->end - res->start + 1;
|
||||
length = resource_size(res);
|
||||
if (acpi_enforce_resources != ENFORCE_RESOURCES_NO)
|
||||
warn = 1;
|
||||
clash = acpi_check_address_range(space_id, res->start, length, warn);
|
||||
|
|
|
|||
|
|
@ -354,6 +354,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
|
|||
|
||||
}
|
||||
resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
|
||||
resource->end.length = sizeof(struct acpi_resource);
|
||||
|
||||
/* Attempt to set the resource */
|
||||
status = acpi_set_current_resources(link->device->handle, &buffer);
|
||||
|
|
|
|||
|
|
@ -169,8 +169,8 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
|
|||
*control &= OSC_PCI_CONTROL_MASKS;
|
||||
capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set;
|
||||
} else {
|
||||
/* Run _OSC query for all possible controls. */
|
||||
capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
|
||||
/* Run _OSC query only with existing controls. */
|
||||
capbuf[OSC_CONTROL_TYPE] = root->osc_control_set;
|
||||
}
|
||||
|
||||
status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
|
||||
|
|
|
|||
|
|
@ -459,57 +459,79 @@ static struct attribute_group attr_groups[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static void acpi_power_hide_list(struct acpi_device *adev, int state)
|
||||
static struct attribute_group wakeup_attr_group = {
|
||||
.name = "power_resources_wakeup",
|
||||
.attrs = attrs,
|
||||
};
|
||||
|
||||
static void acpi_power_hide_list(struct acpi_device *adev,
|
||||
struct list_head *resources,
|
||||
struct attribute_group *attr_group)
|
||||
{
|
||||
struct acpi_device_power_state *ps = &adev->power.states[state];
|
||||
struct acpi_power_resource_entry *entry;
|
||||
|
||||
if (list_empty(&ps->resources))
|
||||
if (list_empty(resources))
|
||||
return;
|
||||
|
||||
list_for_each_entry_reverse(entry, &ps->resources, node) {
|
||||
list_for_each_entry_reverse(entry, resources, node) {
|
||||
struct acpi_device *res_dev = &entry->resource->device;
|
||||
|
||||
sysfs_remove_link_from_group(&adev->dev.kobj,
|
||||
attr_groups[state].name,
|
||||
attr_group->name,
|
||||
dev_name(&res_dev->dev));
|
||||
}
|
||||
sysfs_remove_group(&adev->dev.kobj, &attr_groups[state]);
|
||||
sysfs_remove_group(&adev->dev.kobj, attr_group);
|
||||
}
|
||||
|
||||
static void acpi_power_expose_list(struct acpi_device *adev, int state)
|
||||
static void acpi_power_expose_list(struct acpi_device *adev,
|
||||
struct list_head *resources,
|
||||
struct attribute_group *attr_group)
|
||||
{
|
||||
struct acpi_device_power_state *ps = &adev->power.states[state];
|
||||
struct acpi_power_resource_entry *entry;
|
||||
int ret;
|
||||
|
||||
if (list_empty(&ps->resources))
|
||||
if (list_empty(resources))
|
||||
return;
|
||||
|
||||
ret = sysfs_create_group(&adev->dev.kobj, &attr_groups[state]);
|
||||
ret = sysfs_create_group(&adev->dev.kobj, attr_group);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
list_for_each_entry(entry, &ps->resources, node) {
|
||||
list_for_each_entry(entry, resources, node) {
|
||||
struct acpi_device *res_dev = &entry->resource->device;
|
||||
|
||||
ret = sysfs_add_link_to_group(&adev->dev.kobj,
|
||||
attr_groups[state].name,
|
||||
attr_group->name,
|
||||
&res_dev->dev.kobj,
|
||||
dev_name(&res_dev->dev));
|
||||
if (ret) {
|
||||
acpi_power_hide_list(adev, state);
|
||||
acpi_power_hide_list(adev, resources, attr_group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_power_expose_hide(struct acpi_device *adev,
|
||||
struct list_head *resources,
|
||||
struct attribute_group *attr_group,
|
||||
bool expose)
|
||||
{
|
||||
if (expose)
|
||||
acpi_power_expose_list(adev, resources, attr_group);
|
||||
else
|
||||
acpi_power_hide_list(adev, resources, attr_group);
|
||||
}
|
||||
|
||||
void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
|
||||
{
|
||||
struct acpi_device_power_state *ps;
|
||||
struct acpi_power_resource_entry *entry;
|
||||
int state;
|
||||
|
||||
if (adev->wakeup.flags.valid)
|
||||
acpi_power_expose_hide(adev, &adev->wakeup.resources,
|
||||
&wakeup_attr_group, add);
|
||||
|
||||
if (!adev->power.flags.power_resources)
|
||||
return;
|
||||
|
||||
|
|
@ -523,12 +545,10 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
|
|||
acpi_power_remove_dependent(resource, adev);
|
||||
}
|
||||
|
||||
for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++) {
|
||||
if (add)
|
||||
acpi_power_expose_list(adev, state);
|
||||
else
|
||||
acpi_power_hide_list(adev, state);
|
||||
}
|
||||
for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++)
|
||||
acpi_power_expose_hide(adev,
|
||||
&adev->power.states[state].resources,
|
||||
&attr_groups[state], add);
|
||||
}
|
||||
|
||||
int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
|
||||
|
|
@ -824,7 +844,7 @@ static void acpi_release_power_resource(struct device *dev)
|
|||
list_del(&resource->list_node);
|
||||
mutex_unlock(&power_resource_list_lock);
|
||||
|
||||
acpi_free_ids(device);
|
||||
acpi_free_pnp_ids(&device->pnp);
|
||||
kfree(resource);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -918,7 +918,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
|
|||
struct cpuidle_driver acpi_idle_driver = {
|
||||
.name = "acpi_idle",
|
||||
.owner = THIS_MODULE,
|
||||
.en_core_tk_irqen = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -218,9 +218,13 @@ processor_get_max_state(struct thermal_cooling_device *cdev,
|
|||
unsigned long *state)
|
||||
{
|
||||
struct acpi_device *device = cdev->devdata;
|
||||
struct acpi_processor *pr = acpi_driver_data(device);
|
||||
struct acpi_processor *pr;
|
||||
|
||||
if (!device || !pr)
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
pr = acpi_driver_data(device);
|
||||
if (!pr)
|
||||
return -EINVAL;
|
||||
|
||||
*state = acpi_processor_max_state(pr);
|
||||
|
|
@ -232,9 +236,13 @@ processor_get_cur_state(struct thermal_cooling_device *cdev,
|
|||
unsigned long *cur_state)
|
||||
{
|
||||
struct acpi_device *device = cdev->devdata;
|
||||
struct acpi_processor *pr = acpi_driver_data(device);
|
||||
struct acpi_processor *pr;
|
||||
|
||||
if (!device || !pr)
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
pr = acpi_driver_data(device);
|
||||
if (!pr)
|
||||
return -EINVAL;
|
||||
|
||||
*cur_state = cpufreq_get_cur_state(pr->id);
|
||||
|
|
@ -248,11 +256,15 @@ processor_set_cur_state(struct thermal_cooling_device *cdev,
|
|||
unsigned long state)
|
||||
{
|
||||
struct acpi_device *device = cdev->devdata;
|
||||
struct acpi_processor *pr = acpi_driver_data(device);
|
||||
struct acpi_processor *pr;
|
||||
int result = 0;
|
||||
int max_pstate;
|
||||
|
||||
if (!device || !pr)
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
pr = acpi_driver_data(device);
|
||||
if (!pr)
|
||||
return -EINVAL;
|
||||
|
||||
max_pstate = cpufreq_get_max_state(pr->id);
|
||||
|
|
|
|||
|
|
@ -211,9 +211,10 @@ err_ret:
|
|||
*/
|
||||
void acpi_processor_throttling_init(void)
|
||||
{
|
||||
if (acpi_processor_update_tsd_coord())
|
||||
if (acpi_processor_update_tsd_coord()) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Assume no T-state coordination\n"));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,19 @@ int acpi_scan_add_handler(struct acpi_scan_handler *handler)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
|
||||
const char *hotplug_profile_name)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = acpi_scan_add_handler(handler);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
acpi_sysfs_add_hotplug_profile(&handler->hotplug, hotplug_profile_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates hid/cid(s) string needed for modalias and uevent
|
||||
* e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
|
||||
|
|
@ -107,32 +120,20 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha
|
|||
}
|
||||
static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
|
||||
|
||||
/**
|
||||
* acpi_bus_hot_remove_device: hot-remove a device and its children
|
||||
* @context: struct acpi_eject_event pointer (freed in this func)
|
||||
*
|
||||
* Hot-remove a device and its children. This function frees up the
|
||||
* memory space passed by arg context, so that the caller may call
|
||||
* this function asynchronously through acpi_os_hotplug_execute().
|
||||
*/
|
||||
void acpi_bus_hot_remove_device(void *context)
|
||||
static int acpi_scan_hot_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_eject_event *ej_event = context;
|
||||
struct acpi_device *device = ej_event->device;
|
||||
acpi_handle handle = device->handle;
|
||||
acpi_handle temp;
|
||||
acpi_handle not_used;
|
||||
struct acpi_object_list arg_list;
|
||||
union acpi_object arg;
|
||||
acpi_status status = AE_OK;
|
||||
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
acpi_status status;
|
||||
unsigned long long sta;
|
||||
|
||||
/* If there is no handle, the device node has been unregistered. */
|
||||
if (!device->handle) {
|
||||
if (!handle) {
|
||||
dev_dbg(&device->dev, "ACPI handle missing\n");
|
||||
put_device(&device->dev);
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
|
|
@ -143,7 +144,7 @@ void acpi_bus_hot_remove_device(void *context)
|
|||
put_device(&device->dev);
|
||||
device = NULL;
|
||||
|
||||
if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
|
||||
if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", ¬_used))) {
|
||||
arg_list.count = 1;
|
||||
arg_list.pointer = &arg;
|
||||
arg.type = ACPI_TYPE_INTEGER;
|
||||
|
|
@ -161,18 +162,205 @@ void acpi_bus_hot_remove_device(void *context)
|
|||
*/
|
||||
status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
if (status != AE_NOT_FOUND)
|
||||
acpi_handle_warn(handle, "Eject failed\n");
|
||||
if (status == AE_NOT_FOUND) {
|
||||
return -ENODEV;
|
||||
} else {
|
||||
acpi_handle_warn(handle, "Eject failed (0x%x)\n",
|
||||
status);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tell the firmware the hot-remove operation has failed. */
|
||||
acpi_evaluate_hotplug_ost(handle, ej_event->event,
|
||||
ost_code, NULL);
|
||||
/*
|
||||
* Verify if eject was indeed successful. If not, log an error
|
||||
* message. No need to call _OST since _EJ0 call was made OK.
|
||||
*/
|
||||
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_handle_warn(handle,
|
||||
"Status check after eject failed (0x%x)\n", status);
|
||||
} else if (sta & ACPI_STA_DEVICE_ENABLED) {
|
||||
acpi_handle_warn(handle,
|
||||
"Eject incomplete - status 0x%llx\n", sta);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_bus_device_eject(void *context)
|
||||
{
|
||||
acpi_handle handle = context;
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_scan_handler *handler;
|
||||
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
|
||||
acpi_bus_get_device(handle, &device);
|
||||
if (!device)
|
||||
goto err_out;
|
||||
|
||||
handler = device->handler;
|
||||
if (!handler || !handler->hotplug.enabled) {
|
||||
ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
|
||||
goto err_out;
|
||||
}
|
||||
acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
|
||||
ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
|
||||
if (handler->hotplug.mode == AHM_CONTAINER) {
|
||||
device->flags.eject_pending = true;
|
||||
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
|
||||
} else {
|
||||
int error;
|
||||
|
||||
get_device(&device->dev);
|
||||
error = acpi_scan_hot_remove(device);
|
||||
if (error)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&acpi_scan_lock);
|
||||
kfree(context);
|
||||
return;
|
||||
|
||||
err_out:
|
||||
acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code,
|
||||
NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
|
||||
int error;
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
|
||||
acpi_bus_get_device(handle, &device);
|
||||
if (device) {
|
||||
dev_warn(&device->dev, "Attempt to re-insert\n");
|
||||
goto out;
|
||||
}
|
||||
acpi_evaluate_hotplug_ost(handle, ost_source,
|
||||
ACPI_OST_SC_INSERT_IN_PROGRESS, NULL);
|
||||
error = acpi_bus_scan(handle);
|
||||
if (error) {
|
||||
acpi_handle_warn(handle, "Namespace scan failure\n");
|
||||
goto out;
|
||||
}
|
||||
error = acpi_bus_get_device(handle, &device);
|
||||
if (error) {
|
||||
acpi_handle_warn(handle, "Missing device node object\n");
|
||||
goto out;
|
||||
}
|
||||
ost_code = ACPI_OST_SC_SUCCESS;
|
||||
if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER)
|
||||
kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
|
||||
|
||||
out:
|
||||
acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL);
|
||||
mutex_unlock(&acpi_scan_lock);
|
||||
}
|
||||
|
||||
static void acpi_scan_bus_check(void *context)
|
||||
{
|
||||
acpi_scan_bus_device_check((acpi_handle)context,
|
||||
ACPI_NOTIFY_BUS_CHECK);
|
||||
}
|
||||
|
||||
static void acpi_scan_device_check(void *context)
|
||||
{
|
||||
acpi_scan_bus_device_check((acpi_handle)context,
|
||||
ACPI_NOTIFY_DEVICE_CHECK);
|
||||
}
|
||||
|
||||
static void acpi_hotplug_unsupported(acpi_handle handle, u32 type)
|
||||
{
|
||||
u32 ost_status;
|
||||
|
||||
switch (type) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
acpi_handle_debug(handle,
|
||||
"ACPI_NOTIFY_BUS_CHECK event: unsupported\n");
|
||||
ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED;
|
||||
break;
|
||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||
acpi_handle_debug(handle,
|
||||
"ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n");
|
||||
ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED;
|
||||
break;
|
||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||
acpi_handle_debug(handle,
|
||||
"ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n");
|
||||
ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
|
||||
break;
|
||||
default:
|
||||
/* non-hotplug event; possibly handled by other handler */
|
||||
return;
|
||||
}
|
||||
|
||||
acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL);
|
||||
}
|
||||
|
||||
static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
|
||||
{
|
||||
acpi_osd_exec_callback callback;
|
||||
struct acpi_scan_handler *handler = data;
|
||||
acpi_status status;
|
||||
|
||||
if (!handler->hotplug.enabled)
|
||||
return acpi_hotplug_unsupported(handle, type);
|
||||
|
||||
switch (type) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
|
||||
callback = acpi_scan_bus_check;
|
||||
break;
|
||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||
acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
|
||||
callback = acpi_scan_device_check;
|
||||
break;
|
||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||
acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
|
||||
callback = acpi_bus_device_eject;
|
||||
break;
|
||||
default:
|
||||
/* non-hotplug event; possibly handled by other handler */
|
||||
return;
|
||||
}
|
||||
status = acpi_os_hotplug_execute(callback, handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
acpi_evaluate_hotplug_ost(handle, type,
|
||||
ACPI_OST_SC_NON_SPECIFIC_FAILURE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_bus_hot_remove_device: hot-remove a device and its children
|
||||
* @context: struct acpi_eject_event pointer (freed in this func)
|
||||
*
|
||||
* Hot-remove a device and its children. This function frees up the
|
||||
* memory space passed by arg context, so that the caller may call
|
||||
* this function asynchronously through acpi_os_hotplug_execute().
|
||||
*/
|
||||
void acpi_bus_hot_remove_device(void *context)
|
||||
{
|
||||
struct acpi_eject_event *ej_event = context;
|
||||
struct acpi_device *device = ej_event->device;
|
||||
acpi_handle handle = device->handle;
|
||||
int error;
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
|
||||
error = acpi_scan_hot_remove(device);
|
||||
if (error && handle)
|
||||
acpi_evaluate_hotplug_ost(handle, ej_event->event,
|
||||
ACPI_OST_SC_NON_SPECIFIC_FAILURE,
|
||||
NULL);
|
||||
|
||||
mutex_unlock(&acpi_scan_lock);
|
||||
kfree(context);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_hot_remove_device);
|
||||
|
||||
|
|
@ -206,51 +394,61 @@ static ssize_t
|
|||
acpi_eject_store(struct device *d, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret = count;
|
||||
acpi_status status;
|
||||
acpi_object_type type = 0;
|
||||
struct acpi_device *acpi_device = to_acpi_device(d);
|
||||
struct acpi_eject_event *ej_event;
|
||||
acpi_object_type not_used;
|
||||
acpi_status status;
|
||||
u32 ost_source;
|
||||
int ret;
|
||||
|
||||
if ((!count) || (buf[0] != '1')) {
|
||||
if (!count || buf[0] != '1')
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!acpi_device->driver && !acpi_device->handler) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
status = acpi_get_type(acpi_device->handle, &type);
|
||||
if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
|
||||
&& !acpi_device->driver)
|
||||
return -ENODEV;
|
||||
|
||||
status = acpi_get_type(acpi_device->handle, ¬_used);
|
||||
if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
|
||||
if (acpi_device->flags.eject_pending) {
|
||||
/* ACPI eject notification event. */
|
||||
ost_source = ACPI_NOTIFY_EJECT_REQUEST;
|
||||
acpi_device->flags.eject_pending = 0;
|
||||
} else {
|
||||
/* Eject initiated by user space. */
|
||||
ost_source = ACPI_OST_EC_OSPM_EJECT;
|
||||
}
|
||||
ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
|
||||
if (!ej_event) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
get_device(&acpi_device->dev);
|
||||
acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source,
|
||||
ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
|
||||
ej_event->device = acpi_device;
|
||||
if (acpi_device->flags.eject_pending) {
|
||||
/* event originated from ACPI eject notification */
|
||||
ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
|
||||
acpi_device->flags.eject_pending = 0;
|
||||
} else {
|
||||
/* event originated from user */
|
||||
ej_event->event = ACPI_OST_EC_OSPM_EJECT;
|
||||
(void) acpi_evaluate_hotplug_ost(acpi_device->handle,
|
||||
ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
|
||||
}
|
||||
|
||||
ej_event->event = ost_source;
|
||||
get_device(&acpi_device->dev);
|
||||
status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
put_device(&acpi_device->dev);
|
||||
kfree(ej_event);
|
||||
ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
|
||||
goto err_out;
|
||||
}
|
||||
err:
|
||||
ret = count;
|
||||
|
||||
out:
|
||||
mutex_unlock(&acpi_scan_lock);
|
||||
return ret;
|
||||
|
||||
err_out:
|
||||
acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source,
|
||||
ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
|
||||
|
|
@ -376,7 +574,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (dev->flags.bus_address)
|
||||
if (dev->pnp.type.bus_address)
|
||||
result = device_create_file(&dev->dev, &dev_attr_adr);
|
||||
if (dev->pnp.unique_id)
|
||||
result = device_create_file(&dev->dev, &dev_attr_uid);
|
||||
|
|
@ -449,7 +647,7 @@ static void acpi_device_remove_files(struct acpi_device *dev)
|
|||
|
||||
if (dev->pnp.unique_id)
|
||||
device_remove_file(&dev->dev, &dev_attr_uid);
|
||||
if (dev->flags.bus_address)
|
||||
if (dev->pnp.type.bus_address)
|
||||
device_remove_file(&dev->dev, &dev_attr_adr);
|
||||
device_remove_file(&dev->dev, &dev_attr_modalias);
|
||||
device_remove_file(&dev->dev, &dev_attr_hid);
|
||||
|
|
@ -512,17 +710,6 @@ int acpi_match_device_ids(struct acpi_device *device,
|
|||
}
|
||||
EXPORT_SYMBOL(acpi_match_device_ids);
|
||||
|
||||
void acpi_free_ids(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_hardware_id *id, *tmp;
|
||||
|
||||
list_for_each_entry_safe(id, tmp, &device->pnp.ids, list) {
|
||||
kfree(id->id);
|
||||
kfree(id);
|
||||
}
|
||||
kfree(device->pnp.unique_id);
|
||||
}
|
||||
|
||||
static void acpi_free_power_resources_lists(struct acpi_device *device)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -543,7 +730,7 @@ static void acpi_device_release(struct device *dev)
|
|||
{
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
|
||||
acpi_free_ids(acpi_dev);
|
||||
acpi_free_pnp_ids(&acpi_dev->pnp);
|
||||
acpi_free_power_resources_lists(acpi_dev);
|
||||
kfree(acpi_dev);
|
||||
}
|
||||
|
|
@ -1256,19 +1443,17 @@ static void acpi_device_get_busid(struct acpi_device *device)
|
|||
}
|
||||
|
||||
/*
|
||||
* acpi_bay_match - see if a device is an ejectable driver bay
|
||||
* acpi_bay_match - see if an acpi object is an ejectable driver bay
|
||||
*
|
||||
* If an acpi object is ejectable and has one of the ACPI ATA methods defined,
|
||||
* then we can safely call it an ejectable drive bay
|
||||
*/
|
||||
static int acpi_bay_match(struct acpi_device *device){
|
||||
static int acpi_bay_match(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
acpi_handle tmp;
|
||||
acpi_handle phandle;
|
||||
|
||||
handle = device->handle;
|
||||
|
||||
status = acpi_get_handle(handle, "_EJ0", &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
|
@ -1292,12 +1477,12 @@ static int acpi_bay_match(struct acpi_device *device){
|
|||
}
|
||||
|
||||
/*
|
||||
* acpi_dock_match - see if a device has a _DCK method
|
||||
* acpi_dock_match - see if an acpi object has a _DCK method
|
||||
*/
|
||||
static int acpi_dock_match(struct acpi_device *device)
|
||||
static int acpi_dock_match(acpi_handle handle)
|
||||
{
|
||||
acpi_handle tmp;
|
||||
return acpi_get_handle(device->handle, "_DCK", &tmp);
|
||||
return acpi_get_handle(handle, "_DCK", &tmp);
|
||||
}
|
||||
|
||||
const char *acpi_device_hid(struct acpi_device *device)
|
||||
|
|
@ -1312,7 +1497,7 @@ const char *acpi_device_hid(struct acpi_device *device)
|
|||
}
|
||||
EXPORT_SYMBOL(acpi_device_hid);
|
||||
|
||||
static void acpi_add_id(struct acpi_device *device, const char *dev_id)
|
||||
static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id)
|
||||
{
|
||||
struct acpi_hardware_id *id;
|
||||
|
||||
|
|
@ -1326,7 +1511,8 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
|
|||
return;
|
||||
}
|
||||
|
||||
list_add_tail(&id->list, &device->pnp.ids);
|
||||
list_add_tail(&id->list, &pnp->ids);
|
||||
pnp->type.hardware_id = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1334,7 +1520,7 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
|
|||
* lacks the SMBUS01 HID and the methods do not have the necessary "_"
|
||||
* prefix. Work around this.
|
||||
*/
|
||||
static int acpi_ibm_smbus_match(struct acpi_device *device)
|
||||
static int acpi_ibm_smbus_match(acpi_handle handle)
|
||||
{
|
||||
acpi_handle h_dummy;
|
||||
struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
|
|
@ -1344,7 +1530,7 @@ static int acpi_ibm_smbus_match(struct acpi_device *device)
|
|||
return -ENODEV;
|
||||
|
||||
/* Look for SMBS object */
|
||||
result = acpi_get_name(device->handle, ACPI_SINGLE_NAME, &path);
|
||||
result = acpi_get_name(handle, ACPI_SINGLE_NAME, &path);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
|
|
@ -1355,48 +1541,50 @@ static int acpi_ibm_smbus_match(struct acpi_device *device)
|
|||
|
||||
/* Does it have the necessary (but misnamed) methods? */
|
||||
result = -ENODEV;
|
||||
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "SBI", &h_dummy)) &&
|
||||
ACPI_SUCCESS(acpi_get_handle(device->handle, "SBR", &h_dummy)) &&
|
||||
ACPI_SUCCESS(acpi_get_handle(device->handle, "SBW", &h_dummy)))
|
||||
if (ACPI_SUCCESS(acpi_get_handle(handle, "SBI", &h_dummy)) &&
|
||||
ACPI_SUCCESS(acpi_get_handle(handle, "SBR", &h_dummy)) &&
|
||||
ACPI_SUCCESS(acpi_get_handle(handle, "SBW", &h_dummy)))
|
||||
result = 0;
|
||||
out:
|
||||
kfree(path.pointer);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void acpi_device_set_id(struct acpi_device *device)
|
||||
static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
|
||||
int device_type)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_device_info *info;
|
||||
struct acpi_pnp_device_id_list *cid_list;
|
||||
int i;
|
||||
|
||||
switch (device->device_type) {
|
||||
switch (device_type) {
|
||||
case ACPI_BUS_TYPE_DEVICE:
|
||||
if (ACPI_IS_ROOT_DEVICE(device)) {
|
||||
acpi_add_id(device, ACPI_SYSTEM_HID);
|
||||
if (handle == ACPI_ROOT_OBJECT) {
|
||||
acpi_add_id(pnp, ACPI_SYSTEM_HID);
|
||||
break;
|
||||
}
|
||||
|
||||
status = acpi_get_object_info(device->handle, &info);
|
||||
status = acpi_get_object_info(handle, &info);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__);
|
||||
pr_err(PREFIX "%s: Error reading device info\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->valid & ACPI_VALID_HID)
|
||||
acpi_add_id(device, info->hardware_id.string);
|
||||
acpi_add_id(pnp, info->hardware_id.string);
|
||||
if (info->valid & ACPI_VALID_CID) {
|
||||
cid_list = &info->compatible_id_list;
|
||||
for (i = 0; i < cid_list->count; i++)
|
||||
acpi_add_id(device, cid_list->ids[i].string);
|
||||
acpi_add_id(pnp, cid_list->ids[i].string);
|
||||
}
|
||||
if (info->valid & ACPI_VALID_ADR) {
|
||||
device->pnp.bus_address = info->address;
|
||||
device->flags.bus_address = 1;
|
||||
pnp->bus_address = info->address;
|
||||
pnp->type.bus_address = 1;
|
||||
}
|
||||
if (info->valid & ACPI_VALID_UID)
|
||||
device->pnp.unique_id = kstrdup(info->unique_id.string,
|
||||
pnp->unique_id = kstrdup(info->unique_id.string,
|
||||
GFP_KERNEL);
|
||||
|
||||
kfree(info);
|
||||
|
|
@ -1405,40 +1593,50 @@ static void acpi_device_set_id(struct acpi_device *device)
|
|||
* Some devices don't reliably have _HIDs & _CIDs, so add
|
||||
* synthetic HIDs to make sure drivers can find them.
|
||||
*/
|
||||
if (acpi_is_video_device(device))
|
||||
acpi_add_id(device, ACPI_VIDEO_HID);
|
||||
else if (ACPI_SUCCESS(acpi_bay_match(device)))
|
||||
acpi_add_id(device, ACPI_BAY_HID);
|
||||
else if (ACPI_SUCCESS(acpi_dock_match(device)))
|
||||
acpi_add_id(device, ACPI_DOCK_HID);
|
||||
else if (!acpi_ibm_smbus_match(device))
|
||||
acpi_add_id(device, ACPI_SMBUS_IBM_HID);
|
||||
else if (list_empty(&device->pnp.ids) &&
|
||||
ACPI_IS_ROOT_DEVICE(device->parent)) {
|
||||
acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
|
||||
strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
|
||||
strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
|
||||
if (acpi_is_video_device(handle))
|
||||
acpi_add_id(pnp, ACPI_VIDEO_HID);
|
||||
else if (ACPI_SUCCESS(acpi_bay_match(handle)))
|
||||
acpi_add_id(pnp, ACPI_BAY_HID);
|
||||
else if (ACPI_SUCCESS(acpi_dock_match(handle)))
|
||||
acpi_add_id(pnp, ACPI_DOCK_HID);
|
||||
else if (!acpi_ibm_smbus_match(handle))
|
||||
acpi_add_id(pnp, ACPI_SMBUS_IBM_HID);
|
||||
else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) {
|
||||
acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
|
||||
strcpy(pnp->device_name, ACPI_BUS_DEVICE_NAME);
|
||||
strcpy(pnp->device_class, ACPI_BUS_CLASS);
|
||||
}
|
||||
|
||||
break;
|
||||
case ACPI_BUS_TYPE_POWER:
|
||||
acpi_add_id(device, ACPI_POWER_HID);
|
||||
acpi_add_id(pnp, ACPI_POWER_HID);
|
||||
break;
|
||||
case ACPI_BUS_TYPE_PROCESSOR:
|
||||
acpi_add_id(device, ACPI_PROCESSOR_OBJECT_HID);
|
||||
acpi_add_id(pnp, ACPI_PROCESSOR_OBJECT_HID);
|
||||
break;
|
||||
case ACPI_BUS_TYPE_THERMAL:
|
||||
acpi_add_id(device, ACPI_THERMAL_HID);
|
||||
acpi_add_id(pnp, ACPI_THERMAL_HID);
|
||||
break;
|
||||
case ACPI_BUS_TYPE_POWER_BUTTON:
|
||||
acpi_add_id(device, ACPI_BUTTON_HID_POWERF);
|
||||
acpi_add_id(pnp, ACPI_BUTTON_HID_POWERF);
|
||||
break;
|
||||
case ACPI_BUS_TYPE_SLEEP_BUTTON:
|
||||
acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF);
|
||||
acpi_add_id(pnp, ACPI_BUTTON_HID_SLEEPF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
|
||||
{
|
||||
struct acpi_hardware_id *id, *tmp;
|
||||
|
||||
list_for_each_entry_safe(id, tmp, &pnp->ids, list) {
|
||||
kfree(id->id);
|
||||
kfree(id);
|
||||
}
|
||||
kfree(pnp->unique_id);
|
||||
}
|
||||
|
||||
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
|
||||
int type, unsigned long long sta)
|
||||
{
|
||||
|
|
@ -1448,7 +1646,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
|
|||
device->parent = acpi_bus_get_parent(handle);
|
||||
STRUCT_TO_INT(device->status) = sta;
|
||||
acpi_device_get_busid(device);
|
||||
acpi_device_set_id(device);
|
||||
acpi_set_pnp_ids(handle, &device->pnp, type);
|
||||
acpi_bus_get_flags(device);
|
||||
device->flags.match_driver = false;
|
||||
device_initialize(&device->dev);
|
||||
|
|
@ -1536,6 +1734,75 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
|
||||
char *idstr,
|
||||
const struct acpi_device_id **matchid)
|
||||
{
|
||||
const struct acpi_device_id *devid;
|
||||
|
||||
for (devid = handler->ids; devid->id[0]; devid++)
|
||||
if (!strcmp((char *)devid->id, idstr)) {
|
||||
if (matchid)
|
||||
*matchid = devid;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct acpi_scan_handler *acpi_scan_match_handler(char *idstr,
|
||||
const struct acpi_device_id **matchid)
|
||||
{
|
||||
struct acpi_scan_handler *handler;
|
||||
|
||||
list_for_each_entry(handler, &acpi_scan_handlers_list, list_node)
|
||||
if (acpi_scan_handler_matching(handler, idstr, matchid))
|
||||
return handler;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val)
|
||||
{
|
||||
if (!!hotplug->enabled == !!val)
|
||||
return;
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
|
||||
hotplug->enabled = val;
|
||||
|
||||
mutex_unlock(&acpi_scan_lock);
|
||||
}
|
||||
|
||||
static void acpi_scan_init_hotplug(acpi_handle handle, int type)
|
||||
{
|
||||
struct acpi_device_pnp pnp = {};
|
||||
struct acpi_hardware_id *hwid;
|
||||
struct acpi_scan_handler *handler;
|
||||
|
||||
INIT_LIST_HEAD(&pnp.ids);
|
||||
acpi_set_pnp_ids(handle, &pnp, type);
|
||||
|
||||
if (!pnp.type.hardware_id)
|
||||
return;
|
||||
|
||||
/*
|
||||
* This relies on the fact that acpi_install_notify_handler() will not
|
||||
* install the same notify handler routine twice for the same handle.
|
||||
*/
|
||||
list_for_each_entry(hwid, &pnp.ids, list) {
|
||||
handler = acpi_scan_match_handler(hwid->id, NULL);
|
||||
if (handler) {
|
||||
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||
acpi_hotplug_notify_cb, handler);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
acpi_free_pnp_ids(&pnp);
|
||||
}
|
||||
|
||||
static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
|
||||
void *not_used, void **return_value)
|
||||
{
|
||||
|
|
@ -1558,6 +1825,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
|
|||
return AE_OK;
|
||||
}
|
||||
|
||||
acpi_scan_init_hotplug(handle, type);
|
||||
|
||||
if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
|
||||
!(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
|
||||
struct acpi_device_wakeup wakeup;
|
||||
|
|
@ -1583,41 +1852,25 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
|
|||
return AE_OK;
|
||||
}
|
||||
|
||||
static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
|
||||
{
|
||||
struct acpi_scan_handler *handler;
|
||||
|
||||
list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
|
||||
const struct acpi_device_id *devid;
|
||||
|
||||
for (devid = handler->ids; devid->id[0]; devid++) {
|
||||
int ret;
|
||||
|
||||
if (strcmp((char *)devid->id, id))
|
||||
continue;
|
||||
|
||||
ret = handler->attach(device, devid);
|
||||
if (ret > 0) {
|
||||
device->handler = handler;
|
||||
return ret;
|
||||
} else if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_scan_attach_handler(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_hardware_id *hwid;
|
||||
int ret = 0;
|
||||
|
||||
list_for_each_entry(hwid, &device->pnp.ids, list) {
|
||||
ret = acpi_scan_do_attach_handler(device, hwid->id);
|
||||
if (ret)
|
||||
break;
|
||||
const struct acpi_device_id *devid;
|
||||
struct acpi_scan_handler *handler;
|
||||
|
||||
handler = acpi_scan_match_handler(hwid->id, &devid);
|
||||
if (handler) {
|
||||
ret = handler->attach(device, devid);
|
||||
if (ret > 0) {
|
||||
device->handler = handler;
|
||||
break;
|
||||
} else if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1788,8 +2041,10 @@ int __init acpi_scan_init(void)
|
|||
acpi_pci_root_init();
|
||||
acpi_pci_link_init();
|
||||
acpi_platform_init();
|
||||
acpi_lpss_init();
|
||||
acpi_csrt_init();
|
||||
acpi_container_init();
|
||||
acpi_memory_hotplug_init();
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#include <linux/moduleparam.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define _COMPONENT ACPI_SYSTEM_COMPONENT
|
||||
ACPI_MODULE_NAME("sysfs");
|
||||
|
||||
|
|
@ -249,6 +251,7 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
|
|||
static LIST_HEAD(acpi_table_attr_list);
|
||||
static struct kobject *tables_kobj;
|
||||
static struct kobject *dynamic_tables_kobj;
|
||||
static struct kobject *hotplug_kobj;
|
||||
|
||||
struct acpi_table_attr {
|
||||
struct bin_attribute attr;
|
||||
|
|
@ -716,6 +719,67 @@ acpi_show_profile(struct device *dev, struct device_attribute *attr,
|
|||
static const struct device_attribute pm_profile_attr =
|
||||
__ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL);
|
||||
|
||||
static ssize_t hotplug_enabled_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
|
||||
|
||||
return sprintf(buf, "%d\n", hotplug->enabled);
|
||||
}
|
||||
|
||||
static ssize_t hotplug_enabled_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
|
||||
unsigned int val;
|
||||
|
||||
if (kstrtouint(buf, 10, &val) || val > 1)
|
||||
return -EINVAL;
|
||||
|
||||
acpi_scan_hotplug_enabled(hotplug, val);
|
||||
return size;
|
||||
}
|
||||
|
||||
static struct kobj_attribute hotplug_enabled_attr =
|
||||
__ATTR(enabled, S_IRUGO | S_IWUSR, hotplug_enabled_show,
|
||||
hotplug_enabled_store);
|
||||
|
||||
static struct attribute *hotplug_profile_attrs[] = {
|
||||
&hotplug_enabled_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct kobj_type acpi_hotplug_profile_ktype = {
|
||||
.sysfs_ops = &kobj_sysfs_ops,
|
||||
.default_attrs = hotplug_profile_attrs,
|
||||
};
|
||||
|
||||
void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
|
||||
const char *name)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!hotplug_kobj)
|
||||
goto err_out;
|
||||
|
||||
kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype);
|
||||
error = kobject_set_name(&hotplug->kobj, "%s", name);
|
||||
if (error)
|
||||
goto err_out;
|
||||
|
||||
hotplug->kobj.parent = hotplug_kobj;
|
||||
error = kobject_add(&hotplug->kobj, hotplug_kobj, NULL);
|
||||
if (error)
|
||||
goto err_out;
|
||||
|
||||
kobject_uevent(&hotplug->kobj, KOBJ_ADD);
|
||||
return;
|
||||
|
||||
err_out:
|
||||
pr_err(PREFIX "Unable to add hotplug profile '%s'\n", name);
|
||||
}
|
||||
|
||||
int __init acpi_sysfs_init(void)
|
||||
{
|
||||
int result;
|
||||
|
|
@ -723,6 +787,8 @@ int __init acpi_sysfs_init(void)
|
|||
result = acpi_tables_sysfs_init();
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
hotplug_kobj = kobject_create_and_add("hotplug", acpi_kobj);
|
||||
result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -723,9 +723,19 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
|
|||
return -EINVAL;
|
||||
|
||||
if (type == THERMAL_TRIP_ACTIVE) {
|
||||
/* aggressive active cooling */
|
||||
*trend = THERMAL_TREND_RAISING;
|
||||
return 0;
|
||||
unsigned long trip_temp;
|
||||
unsigned long temp = KELVIN_TO_MILLICELSIUS(tz->temperature,
|
||||
tz->kelvin_offset);
|
||||
if (thermal_get_trip_temp(thermal, trip, &trip_temp))
|
||||
return -EINVAL;
|
||||
|
||||
if (temp > trip_temp) {
|
||||
*trend = THERMAL_TREND_RAISING;
|
||||
return 0;
|
||||
} else {
|
||||
/* Fall back on default trend */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -167,7 +167,8 @@ struct acpi_video_device_flags {
|
|||
u8 dvi:1;
|
||||
u8 bios:1;
|
||||
u8 unknown:1;
|
||||
u8 reserved:2;
|
||||
u8 notify:1;
|
||||
u8 reserved:1;
|
||||
};
|
||||
|
||||
struct acpi_video_device_cap {
|
||||
|
|
@ -222,7 +223,7 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
|
|||
int level);
|
||||
static int acpi_video_device_lcd_get_level_current(
|
||||
struct acpi_video_device *device,
|
||||
unsigned long long *level, int init);
|
||||
unsigned long long *level, bool raw);
|
||||
static int acpi_video_get_next_level(struct acpi_video_device *device,
|
||||
u32 level_current, u32 event);
|
||||
static int acpi_video_switch_brightness(struct acpi_video_device *device,
|
||||
|
|
@ -236,7 +237,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
|
|||
struct acpi_video_device *vd =
|
||||
(struct acpi_video_device *)bl_get_data(bd);
|
||||
|
||||
if (acpi_video_device_lcd_get_level_current(vd, &cur_level, 0))
|
||||
if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false))
|
||||
return -EINVAL;
|
||||
for (i = 2; i < vd->brightness->count; i++) {
|
||||
if (vd->brightness->levels[i] == cur_level)
|
||||
|
|
@ -281,7 +282,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig
|
|||
unsigned long long level;
|
||||
int offset;
|
||||
|
||||
if (acpi_video_device_lcd_get_level_current(video, &level, 0))
|
||||
if (acpi_video_device_lcd_get_level_current(video, &level, false))
|
||||
return -EINVAL;
|
||||
for (offset = 2; offset < video->brightness->count; offset++)
|
||||
if (level == video->brightness->levels[offset]) {
|
||||
|
|
@ -447,12 +448,45 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_ignore_initial_backlight,
|
||||
.ident = "HP Pavilion dm4",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dm4 Notebook PC"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static unsigned long long
|
||||
acpi_video_bqc_value_to_level(struct acpi_video_device *device,
|
||||
unsigned long long bqc_value)
|
||||
{
|
||||
unsigned long long level;
|
||||
|
||||
if (device->brightness->flags._BQC_use_index) {
|
||||
/*
|
||||
* _BQC returns an index that doesn't account for
|
||||
* the first 2 items with special meaning, so we need
|
||||
* to compensate for that by offsetting ourselves
|
||||
*/
|
||||
if (device->brightness->flags._BCL_reversed)
|
||||
bqc_value = device->brightness->count - 3 - bqc_value;
|
||||
|
||||
level = device->brightness->levels[bqc_value + 2];
|
||||
} else {
|
||||
level = bqc_value;
|
||||
}
|
||||
|
||||
level += bqc_offset_aml_bug_workaround;
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
|
||||
unsigned long long *level, int init)
|
||||
unsigned long long *level, bool raw)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
int i;
|
||||
|
|
@ -463,29 +497,30 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
|
|||
status = acpi_evaluate_integer(device->dev->handle, buf,
|
||||
NULL, level);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
if (device->brightness->flags._BQC_use_index) {
|
||||
if (device->brightness->flags._BCL_reversed)
|
||||
*level = device->brightness->count
|
||||
- 3 - (*level);
|
||||
*level = device->brightness->levels[*level + 2];
|
||||
|
||||
if (raw) {
|
||||
/*
|
||||
* Caller has indicated he wants the raw
|
||||
* value returned by _BQC, so don't furtherly
|
||||
* mess with the value.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
*level += bqc_offset_aml_bug_workaround;
|
||||
|
||||
*level = acpi_video_bqc_value_to_level(device, *level);
|
||||
|
||||
for (i = 2; i < device->brightness->count; i++)
|
||||
if (device->brightness->levels[i] == *level) {
|
||||
device->brightness->curr = *level;
|
||||
return 0;
|
||||
}
|
||||
if (!init) {
|
||||
/*
|
||||
* BQC returned an invalid level.
|
||||
* Stop using it.
|
||||
*/
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s returned an invalid level",
|
||||
buf));
|
||||
device->cap._BQC = device->cap._BCQ = 0;
|
||||
}
|
||||
/*
|
||||
* BQC returned an invalid level.
|
||||
* Stop using it.
|
||||
*/
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s returned an invalid level",
|
||||
buf));
|
||||
device->cap._BQC = device->cap._BCQ = 0;
|
||||
} else {
|
||||
/* Fixme:
|
||||
* should we return an error or ignore this failure?
|
||||
|
|
@ -597,6 +632,56 @@ acpi_video_cmp_level(const void *a, const void *b)
|
|||
return *(int *)a - *(int *)b;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decides if _BQC/_BCQ for this system is usable
|
||||
*
|
||||
* We do this by changing the level first and then read out the current
|
||||
* brightness level, if the value does not match, find out if it is using
|
||||
* index. If not, clear the _BQC/_BCQ capability.
|
||||
*/
|
||||
static int acpi_video_bqc_quirk(struct acpi_video_device *device,
|
||||
int max_level, int current_level)
|
||||
{
|
||||
struct acpi_video_device_brightness *br = device->brightness;
|
||||
int result;
|
||||
unsigned long long level;
|
||||
int test_level;
|
||||
|
||||
/* don't mess with existing known broken systems */
|
||||
if (bqc_offset_aml_bug_workaround)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Some systems always report current brightness level as maximum
|
||||
* through _BQC, we need to test another value for them.
|
||||
*/
|
||||
test_level = current_level == max_level ? br->levels[2] : max_level;
|
||||
|
||||
result = acpi_video_device_lcd_set_level(device, test_level);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = acpi_video_device_lcd_get_level_current(device, &level, true);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (level != test_level) {
|
||||
/* buggy _BQC found, need to find out if it uses index */
|
||||
if (level < br->count) {
|
||||
if (br->flags._BCL_reversed)
|
||||
level = br->count - 3 - level;
|
||||
if (br->levels[level + 2] == test_level)
|
||||
br->flags._BQC_use_index = 1;
|
||||
}
|
||||
|
||||
if (!br->flags._BQC_use_index)
|
||||
device->cap._BQC = device->cap._BCQ = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Arg:
|
||||
* device : video output device (LCD, CRT, ..)
|
||||
|
|
@ -703,41 +788,35 @@ acpi_video_init_brightness(struct acpi_video_device *device)
|
|||
if (!device->cap._BQC)
|
||||
goto set_level;
|
||||
|
||||
result = acpi_video_device_lcd_get_level_current(device, &level_old, 1);
|
||||
result = acpi_video_device_lcd_get_level_current(device,
|
||||
&level_old, true);
|
||||
if (result)
|
||||
goto out_free_levels;
|
||||
|
||||
result = acpi_video_bqc_quirk(device, max_level, level_old);
|
||||
if (result)
|
||||
goto out_free_levels;
|
||||
/*
|
||||
* Set the level to maximum and check if _BQC uses indexed value
|
||||
* cap._BQC may get cleared due to _BQC is found to be broken
|
||||
* in acpi_video_bqc_quirk, so check again here.
|
||||
*/
|
||||
result = acpi_video_device_lcd_set_level(device, max_level);
|
||||
if (result)
|
||||
goto out_free_levels;
|
||||
|
||||
result = acpi_video_device_lcd_get_level_current(device, &level, 0);
|
||||
if (result)
|
||||
goto out_free_levels;
|
||||
|
||||
br->flags._BQC_use_index = (level == max_level ? 0 : 1);
|
||||
|
||||
if (!br->flags._BQC_use_index) {
|
||||
/*
|
||||
* Set the backlight to the initial state.
|
||||
* On some buggy laptops, _BQC returns an uninitialized value
|
||||
* when invoked for the first time, i.e. level_old is invalid.
|
||||
* set the backlight to max_level in this case
|
||||
*/
|
||||
if (use_bios_initial_backlight) {
|
||||
for (i = 2; i < br->count; i++)
|
||||
if (level_old == br->levels[i])
|
||||
level = level_old;
|
||||
}
|
||||
if (!device->cap._BQC)
|
||||
goto set_level;
|
||||
}
|
||||
|
||||
if (br->flags._BCL_reversed)
|
||||
level_old = (br->count - 1) - level_old;
|
||||
level = br->levels[level_old];
|
||||
if (use_bios_initial_backlight) {
|
||||
level = acpi_video_bqc_value_to_level(device, level_old);
|
||||
/*
|
||||
* On some buggy laptops, _BQC returns an uninitialized
|
||||
* value when invoked for the first time, i.e.
|
||||
* level_old is invalid (no matter whether it's a level
|
||||
* or an index). Set the backlight to max_level in this case.
|
||||
*/
|
||||
for (i = 2; i < br->count; i++)
|
||||
if (level_old == br->levels[i])
|
||||
break;
|
||||
if (i == br->count)
|
||||
level = max_level;
|
||||
}
|
||||
|
||||
set_level:
|
||||
result = acpi_video_device_lcd_set_level(device, level);
|
||||
|
|
@ -996,53 +1075,51 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
|
|||
struct acpi_video_device *data;
|
||||
struct acpi_video_device_attrib* attribute;
|
||||
|
||||
if (!device || !video)
|
||||
return -EINVAL;
|
||||
|
||||
status =
|
||||
acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
/* Some device omits _ADR, we skip them instead of fail */
|
||||
if (ACPI_FAILURE(status))
|
||||
return 0;
|
||||
|
||||
data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
|
||||
device->driver_data = data;
|
||||
strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
|
||||
device->driver_data = data;
|
||||
|
||||
data->device_id = device_id;
|
||||
data->video = video;
|
||||
data->dev = device;
|
||||
data->device_id = device_id;
|
||||
data->video = video;
|
||||
data->dev = device;
|
||||
|
||||
attribute = acpi_video_get_device_attr(video, device_id);
|
||||
attribute = acpi_video_get_device_attr(video, device_id);
|
||||
|
||||
if((attribute != NULL) && attribute->device_id_scheme) {
|
||||
switch (attribute->display_type) {
|
||||
case ACPI_VIDEO_DISPLAY_CRT:
|
||||
data->flags.crt = 1;
|
||||
break;
|
||||
case ACPI_VIDEO_DISPLAY_TV:
|
||||
data->flags.tvout = 1;
|
||||
break;
|
||||
case ACPI_VIDEO_DISPLAY_DVI:
|
||||
data->flags.dvi = 1;
|
||||
break;
|
||||
case ACPI_VIDEO_DISPLAY_LCD:
|
||||
data->flags.lcd = 1;
|
||||
break;
|
||||
default:
|
||||
data->flags.unknown = 1;
|
||||
break;
|
||||
}
|
||||
if(attribute->bios_can_detect)
|
||||
data->flags.bios = 1;
|
||||
} else {
|
||||
/* Check for legacy IDs */
|
||||
device_type = acpi_video_get_device_type(video,
|
||||
device_id);
|
||||
/* Ignore bits 16 and 18-20 */
|
||||
switch (device_type & 0xffe2ffff) {
|
||||
if((attribute != NULL) && attribute->device_id_scheme) {
|
||||
switch (attribute->display_type) {
|
||||
case ACPI_VIDEO_DISPLAY_CRT:
|
||||
data->flags.crt = 1;
|
||||
break;
|
||||
case ACPI_VIDEO_DISPLAY_TV:
|
||||
data->flags.tvout = 1;
|
||||
break;
|
||||
case ACPI_VIDEO_DISPLAY_DVI:
|
||||
data->flags.dvi = 1;
|
||||
break;
|
||||
case ACPI_VIDEO_DISPLAY_LCD:
|
||||
data->flags.lcd = 1;
|
||||
break;
|
||||
default:
|
||||
data->flags.unknown = 1;
|
||||
break;
|
||||
}
|
||||
if(attribute->bios_can_detect)
|
||||
data->flags.bios = 1;
|
||||
} else {
|
||||
/* Check for legacy IDs */
|
||||
device_type = acpi_video_get_device_type(video, device_id);
|
||||
/* Ignore bits 16 and 18-20 */
|
||||
switch (device_type & 0xffe2ffff) {
|
||||
case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR:
|
||||
data->flags.crt = 1;
|
||||
break;
|
||||
|
|
@ -1054,34 +1131,24 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
|
|||
break;
|
||||
default:
|
||||
data->flags.unknown = 1;
|
||||
}
|
||||
}
|
||||
|
||||
acpi_video_device_bind(video, data);
|
||||
acpi_video_device_find_cap(data);
|
||||
|
||||
status = acpi_install_notify_handler(device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_device_notify,
|
||||
data);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_ERR PREFIX
|
||||
"Error installing notify handler\n");
|
||||
if(data->brightness)
|
||||
kfree(data->brightness->levels);
|
||||
kfree(data->brightness);
|
||||
kfree(data);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&video->device_list_lock);
|
||||
list_add_tail(&data->entry, &video->video_device_list);
|
||||
mutex_unlock(&video->device_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
acpi_video_device_bind(video, data);
|
||||
acpi_video_device_find_cap(data);
|
||||
|
||||
status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_device_notify, data);
|
||||
if (ACPI_FAILURE(status))
|
||||
dev_err(&device->dev, "Error installing notify handler\n");
|
||||
else
|
||||
data->flags.notify = 1;
|
||||
|
||||
mutex_lock(&video->device_list_lock);
|
||||
list_add_tail(&data->entry, &video->video_device_list);
|
||||
mutex_unlock(&video->device_list_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1268,7 +1335,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
|
|||
goto out;
|
||||
|
||||
result = acpi_video_device_lcd_get_level_current(device,
|
||||
&level_current, 0);
|
||||
&level_current,
|
||||
false);
|
||||
if (result)
|
||||
goto out;
|
||||
|
||||
|
|
@ -1373,9 +1441,8 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
|
|||
|
||||
status = acpi_video_bus_get_one_device(dev, video);
|
||||
if (status) {
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Can't attach device\n");
|
||||
continue;
|
||||
dev_err(&dev->dev, "Can't attach device\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
|
|
@ -1388,13 +1455,14 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
|
|||
if (!device || !device->video)
|
||||
return -ENOENT;
|
||||
|
||||
status = acpi_remove_notify_handler(device->dev->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_device_notify);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Can't remove video notify handler\n");
|
||||
if (device->flags.notify) {
|
||||
status = acpi_remove_notify_handler(device->dev->handle,
|
||||
ACPI_DEVICE_NOTIFY, acpi_video_device_notify);
|
||||
if (ACPI_FAILURE(status))
|
||||
dev_err(&device->dev->dev,
|
||||
"Can't remove video notify handler\n");
|
||||
}
|
||||
|
||||
if (device->backlight) {
|
||||
backlight_device_unregister(device->backlight);
|
||||
device->backlight = NULL;
|
||||
|
|
@ -1676,7 +1744,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
|||
|
||||
error = acpi_video_bus_get_devices(video, device);
|
||||
if (error)
|
||||
goto err_free_video;
|
||||
goto err_put_video;
|
||||
|
||||
video->input = input = input_allocate_device();
|
||||
if (!input) {
|
||||
|
|
|
|||
|
|
@ -67,40 +67,37 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Returns true if the device is a video device which can be handled by
|
||||
* video.ko.
|
||||
/* Returns true if the ACPI object is a video device which can be
|
||||
* handled by video.ko.
|
||||
* The device will get a Linux specific CID added in scan.c to
|
||||
* identify the device as an ACPI graphics device
|
||||
* Be aware that the graphics device may not be physically present
|
||||
* Use acpi_video_get_capabilities() to detect general ACPI video
|
||||
* capabilities of present cards
|
||||
*/
|
||||
long acpi_is_video_device(struct acpi_device *device)
|
||||
long acpi_is_video_device(acpi_handle handle)
|
||||
{
|
||||
acpi_handle h_dummy;
|
||||
long video_caps = 0;
|
||||
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
/* Is this device able to support video switching ? */
|
||||
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) ||
|
||||
ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy)))
|
||||
if (ACPI_SUCCESS(acpi_get_handle(handle, "_DOD", &h_dummy)) ||
|
||||
ACPI_SUCCESS(acpi_get_handle(handle, "_DOS", &h_dummy)))
|
||||
video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
|
||||
|
||||
/* Is this device able to retrieve a video ROM ? */
|
||||
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy)))
|
||||
if (ACPI_SUCCESS(acpi_get_handle(handle, "_ROM", &h_dummy)))
|
||||
video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
|
||||
|
||||
/* Is this device able to configure which video head to be POSTed ? */
|
||||
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) &&
|
||||
ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) &&
|
||||
ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy)))
|
||||
if (ACPI_SUCCESS(acpi_get_handle(handle, "_VPO", &h_dummy)) &&
|
||||
ACPI_SUCCESS(acpi_get_handle(handle, "_GPD", &h_dummy)) &&
|
||||
ACPI_SUCCESS(acpi_get_handle(handle, "_SPD", &h_dummy)))
|
||||
video_caps |= ACPI_VIDEO_DEVICE_POSTING;
|
||||
|
||||
/* Only check for backlight functionality if one of the above hit. */
|
||||
if (video_caps)
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle,
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
|
||||
ACPI_UINT32_MAX, acpi_backlight_cap_match, NULL,
|
||||
&video_caps, NULL);
|
||||
|
||||
|
|
@ -127,7 +124,7 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
|
|||
if (!dev)
|
||||
return AE_OK;
|
||||
pci_dev_put(dev);
|
||||
*cap |= acpi_is_video_device(acpi_dev);
|
||||
*cap |= acpi_is_video_device(handle);
|
||||
}
|
||||
return AE_OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue