mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 14:44:10 +08:00
ACPI and power management fixes for 3.15-rc6
- ACPICA fix for a stale pointer access introduced by a recent commit in the XSDT validation code from Lv Zheng. - ACPICA fix for the default value of the command line switch to favor 32-bit FADT addresses (in case there's a conflict between a 64-bit and a 32-bit address). The previous default was that the 32-bit version would take precedence and we tried to change it to the other way around and it didn't work. From Lv Zheng. - A TPM commit related to ACPI _DSM in 3.14 caused the driver to refuse to load if a specific _DSM was missing and that broke resume from system suspend on Chromebooks that require the TPM hardware to be restored to a working state during resume by the OS. Restore the old behavior to load the driver if the _DSM in question is not present, but prevent it from using the feature the _DSM is for. - ACPI AC driver conversion in 3.13 broke thermal management on at least one machine and has to be reverted. From Guenter Roeck. - Two reverts of 3.13 commits that attempted to remove the old ACPI battery interface in /proc, but turned out to break some utilities still using that interface. From Lan Tianyu. - ACPI processor driver fix to prevent acpi_processor_add() from modifying the CPU device's .offline field which leads to breakage if the initial online of the CPU fails. From Igor Mammedov. - Two intel_pstate fixes, one to take a BayTrail documentation update into account and one to avoid forcing the maximum P-state on init which causes CPU PM trouble on systems with P-states coordination when one of the CPU cores is initialized after an offline/online cycle triggered by user space. Both stable candidates, from Dirk Brandewie. - Fix for the ACPI video DMI blacklist entry for Dell Inspiron 7520 from Aaron Lu. - Two new ACPI video blacklist entries for machines shipping with Win8 that need to use native backlight so that it can be controlled in a usual way (which doesn't work otherwise due bugs in the ACPI tables) from Hans de Goede. - Two ACPI _OSI quirks for systems that need them to work correctly with Linux from Edward Lin and Hans de Goede. / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCAAGBQJTdow6AAoJEILEb/54YlRxUWcP/0nczFCxZ7C1c7l7Ya8r9iRZ HXT+AAbakanPs6Ms4VRxao65v1AcdlruWHPhJ6JiEoiO60yKxIIzy7f3mO5gVesr tcaxaFaCTNdUDFdRDhyN6y+RzO/ohYSKdOJng2tcz2IvcsRD93hXk+095BlVzfJV EFycqXPb3nmP6oZo1KjPebk4cmlC8Sw9aWcBxK0O1aRoIrAdObf3+rCXfc2/FvC0 vAquOI2OaJ0bwNl7QhGHMLMnvoDvq+/y2mDQ+BvxPERbtDBDS66tkhjsxEx89kpi ow6WKX1vgfsWYGa5tCxFDZvYIYP5x4+YWPwvYfOFmCO520PUIojT81qT+P6hLHMy jf2G7QWvL/3qn89qKsR26YNE/fadNDZq0IHh3KD8kOaKtXBV30fIh2rLG3XZfB8q lhWAcx5ot2ZoQy5ppAuKNG+zA6MniWbN/a5acUIS6zsvVRFkGeZE5ORyEUgkWMjk QiiL3kcx/Fe528A1cMVXR2fb4kzKBpnVXxWQlzptKCX/3JAOxe6ElZqHMDff983b LHJjMfVUX9m1yGUZHqbH6CiK9kuQv2fQXSESLrkUDItVs9VFskYQb6AZE5Ow+k+A QKnDg7n81YlYiau997g0+yA7EqwQmQZx+EwfVtOIfppOlp4LFbCKC6Ytu9pcgbZB GuYsd/bPvEVswylJMu6U =v+oA -----END PGP SIGNATURE----- Merge tag 'pm+acpi-3.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull ACPI and power management fixes from Rafael Wysocki: "Still fixing regressions (partly by reverting commits that broke things for people), fixing other stable-candidate bugs and adding some blacklist entries for ACPI video and _OSI. Two ACPICA regression fixes (one recent and one for a 3.14 commit), a fix for an ACPI-related regression in TPM (introduced in 3.14), a revert of the ACPI AC driver conversion in 3.13 that went wrong for an unknown reason, two reverts of commits that attempted to remove an old user space interface in /proc and broke some utilities, in 3.13 too, a fix for a CPU hotplug bug in the ACPI processor driver (stable material), two (stable candidate) fixes for intel_pstate and a few new blacklist entries, mostly for systems that shipped with Windows 8. Specifics: - ACPICA fix for a stale pointer access introduced by a recent commit in the XSDT validation code from Lv Zheng. - ACPICA fix for the default value of the command line switch to favor 32-bit FADT addresses (in case there's a conflict between a 64-bit and a 32-bit address). The previous default was that the 32-bit version would take precedence and we tried to change it to the other way around and it didn't work. From Lv Zheng. - A TPM commit related to ACPI _DSM in 3.14 caused the driver to refuse to load if a specific _DSM was missing and that broke resume from system suspend on Chromebooks that require the TPM hardware to be restored to a working state during resume by the OS. Restore the old behavior to load the driver if the _DSM in question is not present, but prevent it from using the feature the _DSM is for. - ACPI AC driver conversion in 3.13 broke thermal management on at least one machine and has to be reverted. From Guenter Roeck. - Two reverts of 3.13 commits that attempted to remove the old ACPI battery interface in /proc, but turned out to break some utilities still using that interface. From Lan Tianyu. - ACPI processor driver fix to prevent acpi_processor_add() from modifying the CPU device's .offline field which leads to breakage if the initial online of the CPU fails. From Igor Mammedov. - Two intel_pstate fixes, one to take a BayTrail documentation update into account and one to avoid forcing the maximum P-state on init which causes CPU PM trouble on systems with P-states coordination when one of the CPU cores is initialized after an offline/online cycle triggered by user space. Both stable candidates, from Dirk Brandewie. - Fix for the ACPI video DMI blacklist entry for Dell Inspiron 7520 from Aaron Lu. - Two new ACPI video blacklist entries for machines shipping with Win8 that need to use native backlight so that it can be controlled in a usual way (which doesn't work otherwise due bugs in the ACPI tables) from Hans de Goede. - Two ACPI _OSI quirks for systems that need them to work correctly with Linux from Edward Lin and Hans de Goede" * tag 'pm+acpi-3.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI / video: Revert native brightness quirk for ThinkPad T530 intel_pstate: remove setting P state to MAX on init ACPICA: Tables: Restore old behavor to favor 32-bit FADT addresses. ACPI / video: correct DMI tag for Dell Inspiron 7520 intel_pstate: Set turbo VID for BayTrail ACPI / TPM: Fix resume regression on Chromebooks ACPI / proc: Do not say when /proc interfaces will be deleted in Kconfig ACPI / processor: do not mark present at boot but not onlined CPU as onlined ACPI: Revert "ACPI / AC: convert ACPI ac driver to platform bus" ACPI / blacklist: Add dmi_enable_osi_linux quirk for Asus EEE PC 1015PX ACPI: blacklist win8 OSI for Dell Inspiron 7737 ACPI / video: Add use_native_backlight quirks for more systems ACPI: Revert "ACPI / Battery: Remove battery's proc directory" ACPI: Revert "ACPI: Remove CONFIG_ACPI_PROCFS_POWER and cm_sbsc.c" ACPICA: Tables: Fix invalid pointer accesses in acpi_tb_parse_root_table().
This commit is contained in:
commit
478c7cf7a8
@ -47,6 +47,23 @@ config ACPI_SLEEP
|
|||||||
depends on SUSPEND || HIBERNATION
|
depends on SUSPEND || HIBERNATION
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config ACPI_PROCFS_POWER
|
||||||
|
bool "Deprecated power /proc/acpi directories"
|
||||||
|
depends on PROC_FS
|
||||||
|
help
|
||||||
|
For backwards compatibility, this option allows
|
||||||
|
deprecated power /proc/acpi/ directories to exist, even when
|
||||||
|
they have been replaced by functions in /sys.
|
||||||
|
The deprecated directories (and their replacements) include:
|
||||||
|
/proc/acpi/battery/* (/sys/class/power_supply/*)
|
||||||
|
/proc/acpi/ac_adapter/* (sys/class/power_supply/*)
|
||||||
|
This option has no effect on /proc/acpi/ directories
|
||||||
|
and functions, which do not yet exist in /sys
|
||||||
|
This option, together with the proc directories, will be
|
||||||
|
deleted in the future.
|
||||||
|
|
||||||
|
Say N to delete power /proc/acpi/ directories that have moved to /sys/
|
||||||
|
|
||||||
config ACPI_EC_DEBUGFS
|
config ACPI_EC_DEBUGFS
|
||||||
tristate "EC read/write access through /sys/kernel/debug/ec"
|
tristate "EC read/write access through /sys/kernel/debug/ec"
|
||||||
default n
|
default n
|
||||||
|
@ -47,6 +47,7 @@ acpi-y += sysfs.o
|
|||||||
acpi-$(CONFIG_X86) += acpi_cmos_rtc.o
|
acpi-$(CONFIG_X86) += acpi_cmos_rtc.o
|
||||||
acpi-$(CONFIG_DEBUG_FS) += debugfs.o
|
acpi-$(CONFIG_DEBUG_FS) += debugfs.o
|
||||||
acpi-$(CONFIG_ACPI_NUMA) += numa.o
|
acpi-$(CONFIG_ACPI_NUMA) += numa.o
|
||||||
|
acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
|
||||||
ifdef CONFIG_ACPI_VIDEO
|
ifdef CONFIG_ACPI_VIDEO
|
||||||
acpi-y += video_detect.o
|
acpi-y += video_detect.o
|
||||||
endif
|
endif
|
||||||
|
@ -52,11 +52,39 @@ MODULE_AUTHOR("Paul Diefenbaugh");
|
|||||||
MODULE_DESCRIPTION("ACPI AC Adapter Driver");
|
MODULE_DESCRIPTION("ACPI AC Adapter Driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
static int acpi_ac_add(struct acpi_device *device);
|
||||||
|
static int acpi_ac_remove(struct acpi_device *device);
|
||||||
|
static void acpi_ac_notify(struct acpi_device *device, u32 event);
|
||||||
|
|
||||||
|
static const struct acpi_device_id ac_device_ids[] = {
|
||||||
|
{"ACPI0003", 0},
|
||||||
|
{"", 0},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(acpi, ac_device_ids);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int acpi_ac_resume(struct device *dev);
|
||||||
|
#endif
|
||||||
|
static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
|
||||||
|
|
||||||
static int ac_sleep_before_get_state_ms;
|
static int ac_sleep_before_get_state_ms;
|
||||||
|
|
||||||
|
static struct acpi_driver acpi_ac_driver = {
|
||||||
|
.name = "ac",
|
||||||
|
.class = ACPI_AC_CLASS,
|
||||||
|
.ids = ac_device_ids,
|
||||||
|
.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
|
||||||
|
.ops = {
|
||||||
|
.add = acpi_ac_add,
|
||||||
|
.remove = acpi_ac_remove,
|
||||||
|
.notify = acpi_ac_notify,
|
||||||
|
},
|
||||||
|
.drv.pm = &acpi_ac_pm,
|
||||||
|
};
|
||||||
|
|
||||||
struct acpi_ac {
|
struct acpi_ac {
|
||||||
struct power_supply charger;
|
struct power_supply charger;
|
||||||
struct platform_device *pdev;
|
struct acpi_device * device;
|
||||||
unsigned long long state;
|
unsigned long long state;
|
||||||
struct notifier_block battery_nb;
|
struct notifier_block battery_nb;
|
||||||
};
|
};
|
||||||
@ -69,10 +97,12 @@ struct acpi_ac {
|
|||||||
|
|
||||||
static int acpi_ac_get_state(struct acpi_ac *ac)
|
static int acpi_ac_get_state(struct acpi_ac *ac)
|
||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status = AE_OK;
|
||||||
acpi_handle handle = ACPI_HANDLE(&ac->pdev->dev);
|
|
||||||
|
|
||||||
status = acpi_evaluate_integer(handle, "_PSR", NULL,
|
if (!ac)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL,
|
||||||
&ac->state);
|
&ac->state);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
ACPI_EXCEPTION((AE_INFO, status,
|
ACPI_EXCEPTION((AE_INFO, status,
|
||||||
@ -117,10 +147,9 @@ static enum power_supply_property ac_props[] = {
|
|||||||
Driver Model
|
Driver Model
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data)
|
static void acpi_ac_notify(struct acpi_device *device, u32 event)
|
||||||
{
|
{
|
||||||
struct acpi_ac *ac = data;
|
struct acpi_ac *ac = acpi_driver_data(device);
|
||||||
struct acpi_device *adev;
|
|
||||||
|
|
||||||
if (!ac)
|
if (!ac)
|
||||||
return;
|
return;
|
||||||
@ -143,11 +172,10 @@ static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data)
|
|||||||
msleep(ac_sleep_before_get_state_ms);
|
msleep(ac_sleep_before_get_state_ms);
|
||||||
|
|
||||||
acpi_ac_get_state(ac);
|
acpi_ac_get_state(ac);
|
||||||
adev = ACPI_COMPANION(&ac->pdev->dev);
|
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
||||||
acpi_bus_generate_netlink_event(adev->pnp.device_class,
|
dev_name(&device->dev), event,
|
||||||
dev_name(&ac->pdev->dev),
|
(u32) ac->state);
|
||||||
event, (u32) ac->state);
|
acpi_notifier_call_chain(device, event, (u32) ac->state);
|
||||||
acpi_notifier_call_chain(adev, event, (u32) ac->state);
|
|
||||||
kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
|
kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,49 +220,39 @@ static struct dmi_system_id ac_dmi_table[] = {
|
|||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int acpi_ac_probe(struct platform_device *pdev)
|
static int acpi_ac_add(struct acpi_device *device)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
struct acpi_ac *ac = NULL;
|
struct acpi_ac *ac = NULL;
|
||||||
struct acpi_device *adev;
|
|
||||||
|
|
||||||
if (!pdev)
|
|
||||||
|
if (!device)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
adev = ACPI_COMPANION(&pdev->dev);
|
|
||||||
if (!adev)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
|
ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
|
||||||
if (!ac)
|
if (!ac)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME);
|
ac->device = device;
|
||||||
strcpy(acpi_device_class(adev), ACPI_AC_CLASS);
|
strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
|
||||||
ac->pdev = pdev;
|
strcpy(acpi_device_class(device), ACPI_AC_CLASS);
|
||||||
platform_set_drvdata(pdev, ac);
|
device->driver_data = ac;
|
||||||
|
|
||||||
result = acpi_ac_get_state(ac);
|
result = acpi_ac_get_state(ac);
|
||||||
if (result)
|
if (result)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
ac->charger.name = acpi_device_bid(adev);
|
ac->charger.name = acpi_device_bid(device);
|
||||||
ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
|
ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
|
||||||
ac->charger.properties = ac_props;
|
ac->charger.properties = ac_props;
|
||||||
ac->charger.num_properties = ARRAY_SIZE(ac_props);
|
ac->charger.num_properties = ARRAY_SIZE(ac_props);
|
||||||
ac->charger.get_property = get_ac_property;
|
ac->charger.get_property = get_ac_property;
|
||||||
result = power_supply_register(&pdev->dev, &ac->charger);
|
result = power_supply_register(&ac->device->dev, &ac->charger);
|
||||||
if (result)
|
if (result)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
|
|
||||||
ACPI_ALL_NOTIFY, acpi_ac_notify_handler, ac);
|
|
||||||
if (result) {
|
|
||||||
power_supply_unregister(&ac->charger);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
|
printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
|
||||||
acpi_device_name(adev), acpi_device_bid(adev),
|
acpi_device_name(device), acpi_device_bid(device),
|
||||||
ac->state ? "on-line" : "off-line");
|
ac->state ? "on-line" : "off-line");
|
||||||
|
|
||||||
ac->battery_nb.notifier_call = acpi_ac_battery_notify;
|
ac->battery_nb.notifier_call = acpi_ac_battery_notify;
|
||||||
@ -256,7 +274,7 @@ static int acpi_ac_resume(struct device *dev)
|
|||||||
if (!dev)
|
if (!dev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ac = platform_get_drvdata(to_platform_device(dev));
|
ac = acpi_driver_data(to_acpi_device(dev));
|
||||||
if (!ac)
|
if (!ac)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -270,19 +288,17 @@ static int acpi_ac_resume(struct device *dev)
|
|||||||
#else
|
#else
|
||||||
#define acpi_ac_resume NULL
|
#define acpi_ac_resume NULL
|
||||||
#endif
|
#endif
|
||||||
static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume);
|
|
||||||
|
|
||||||
static int acpi_ac_remove(struct platform_device *pdev)
|
static int acpi_ac_remove(struct acpi_device *device)
|
||||||
{
|
{
|
||||||
struct acpi_ac *ac;
|
struct acpi_ac *ac = NULL;
|
||||||
|
|
||||||
if (!pdev)
|
|
||||||
|
if (!device || !acpi_driver_data(device))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
|
ac = acpi_driver_data(device);
|
||||||
ACPI_ALL_NOTIFY, acpi_ac_notify_handler);
|
|
||||||
|
|
||||||
ac = platform_get_drvdata(pdev);
|
|
||||||
if (ac->charger.dev)
|
if (ac->charger.dev)
|
||||||
power_supply_unregister(&ac->charger);
|
power_supply_unregister(&ac->charger);
|
||||||
unregister_acpi_notifier(&ac->battery_nb);
|
unregister_acpi_notifier(&ac->battery_nb);
|
||||||
@ -292,23 +308,6 @@ static int acpi_ac_remove(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct acpi_device_id acpi_ac_match[] = {
|
|
||||||
{ "ACPI0003", 0 },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(acpi, acpi_ac_match);
|
|
||||||
|
|
||||||
static struct platform_driver acpi_ac_driver = {
|
|
||||||
.probe = acpi_ac_probe,
|
|
||||||
.remove = acpi_ac_remove,
|
|
||||||
.driver = {
|
|
||||||
.name = "acpi-ac",
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.pm = &acpi_ac_pm_ops,
|
|
||||||
.acpi_match_table = ACPI_PTR(acpi_ac_match),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init acpi_ac_init(void)
|
static int __init acpi_ac_init(void)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
@ -316,7 +315,7 @@ static int __init acpi_ac_init(void)
|
|||||||
if (acpi_disabled)
|
if (acpi_disabled)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
result = platform_driver_register(&acpi_ac_driver);
|
result = acpi_bus_register_driver(&acpi_ac_driver);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
@ -325,7 +324,7 @@ static int __init acpi_ac_init(void)
|
|||||||
|
|
||||||
static void __exit acpi_ac_exit(void)
|
static void __exit acpi_ac_exit(void)
|
||||||
{
|
{
|
||||||
platform_driver_unregister(&acpi_ac_driver);
|
acpi_bus_unregister_driver(&acpi_ac_driver);
|
||||||
}
|
}
|
||||||
module_init(acpi_ac_init);
|
module_init(acpi_ac_init);
|
||||||
module_exit(acpi_ac_exit);
|
module_exit(acpi_ac_exit);
|
||||||
|
@ -29,7 +29,6 @@ ACPI_MODULE_NAME("platform");
|
|||||||
static const struct acpi_device_id acpi_platform_device_ids[] = {
|
static const struct acpi_device_id acpi_platform_device_ids[] = {
|
||||||
|
|
||||||
{ "PNP0D40" },
|
{ "PNP0D40" },
|
||||||
{ "ACPI0003" },
|
|
||||||
{ "VPC2004" },
|
{ "VPC2004" },
|
||||||
{ "BCM4752" },
|
{ "BCM4752" },
|
||||||
|
|
||||||
|
@ -405,7 +405,6 @@ static int acpi_processor_add(struct acpi_device *device,
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
pr->dev = dev;
|
pr->dev = dev;
|
||||||
dev->offline = pr->flags.need_hotplug_init;
|
|
||||||
|
|
||||||
/* Trigger the processor driver's .probe() if present. */
|
/* Trigger the processor driver's .probe() if present. */
|
||||||
if (device_attach(dev) >= 0)
|
if (device_attach(dev) >= 0)
|
||||||
|
@ -141,9 +141,9 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);
|
|||||||
* address. Although ACPICA adheres to the ACPI specification which
|
* address. Although ACPICA adheres to the ACPI specification which
|
||||||
* requires the use of the corresponding 64-bit address if it is non-zero,
|
* requires the use of the corresponding 64-bit address if it is non-zero,
|
||||||
* some machines have been found to have a corrupted non-zero 64-bit
|
* some machines have been found to have a corrupted non-zero 64-bit
|
||||||
* address. Default is FALSE, do not favor the 32-bit addresses.
|
* address. Default is TRUE, favor the 32-bit addresses.
|
||||||
*/
|
*/
|
||||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_use32_bit_fadt_addresses, FALSE);
|
ACPI_INIT_GLOBAL(u8, acpi_gbl_use32_bit_fadt_addresses, TRUE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Optionally truncate I/O addresses to 16 bits. Provides compatibility
|
* Optionally truncate I/O addresses to 16 bits. Provides compatibility
|
||||||
|
@ -461,6 +461,7 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
|
|||||||
u32 table_count;
|
u32 table_count;
|
||||||
struct acpi_table_header *table;
|
struct acpi_table_header *table;
|
||||||
acpi_physical_address address;
|
acpi_physical_address address;
|
||||||
|
acpi_physical_address rsdt_address;
|
||||||
u32 length;
|
u32 length;
|
||||||
u8 *table_entry;
|
u8 *table_entry;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
@ -488,11 +489,14 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
|
|||||||
* as per the ACPI specification.
|
* as per the ACPI specification.
|
||||||
*/
|
*/
|
||||||
address = (acpi_physical_address) rsdp->xsdt_physical_address;
|
address = (acpi_physical_address) rsdp->xsdt_physical_address;
|
||||||
|
rsdt_address =
|
||||||
|
(acpi_physical_address) rsdp->rsdt_physical_address;
|
||||||
table_entry_size = ACPI_XSDT_ENTRY_SIZE;
|
table_entry_size = ACPI_XSDT_ENTRY_SIZE;
|
||||||
} else {
|
} else {
|
||||||
/* Root table is an RSDT (32-bit physical addresses) */
|
/* Root table is an RSDT (32-bit physical addresses) */
|
||||||
|
|
||||||
address = (acpi_physical_address) rsdp->rsdt_physical_address;
|
address = (acpi_physical_address) rsdp->rsdt_physical_address;
|
||||||
|
rsdt_address = address;
|
||||||
table_entry_size = ACPI_RSDT_ENTRY_SIZE;
|
table_entry_size = ACPI_RSDT_ENTRY_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,8 +519,7 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
|
|||||||
|
|
||||||
/* Fall back to the RSDT */
|
/* Fall back to the RSDT */
|
||||||
|
|
||||||
address =
|
address = rsdt_address;
|
||||||
(acpi_physical_address) rsdp->rsdt_physical_address;
|
|
||||||
table_entry_size = ACPI_RSDT_ENTRY_SIZE;
|
table_entry_size = ACPI_RSDT_ENTRY_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,12 @@
|
|||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
#include <linux/proc_fs.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/power_supply.h>
|
#include <linux/power_supply.h>
|
||||||
|
|
||||||
@ -64,6 +70,19 @@ static unsigned int cache_time = 1000;
|
|||||||
module_param(cache_time, uint, 0644);
|
module_param(cache_time, uint, 0644);
|
||||||
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
|
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
extern struct proc_dir_entry *acpi_lock_battery_dir(void);
|
||||||
|
extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
|
||||||
|
|
||||||
|
enum acpi_battery_files {
|
||||||
|
info_tag = 0,
|
||||||
|
state_tag,
|
||||||
|
alarm_tag,
|
||||||
|
ACPI_BATTERY_NUMFILES,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct acpi_device_id battery_device_ids[] = {
|
static const struct acpi_device_id battery_device_ids[] = {
|
||||||
{"PNP0C0A", 0},
|
{"PNP0C0A", 0},
|
||||||
{"", 0},
|
{"", 0},
|
||||||
@ -299,6 +318,14 @@ static enum power_supply_property energy_battery_props[] = {
|
|||||||
POWER_SUPPLY_PROP_SERIAL_NUMBER,
|
POWER_SUPPLY_PROP_SERIAL_NUMBER,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
inline char *acpi_battery_units(struct acpi_battery *battery)
|
||||||
|
{
|
||||||
|
return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
|
||||||
|
"mA" : "mW";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
Battery Management
|
Battery Management
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
@ -716,6 +743,279 @@ static void acpi_battery_refresh(struct acpi_battery *battery)
|
|||||||
sysfs_add_battery(battery);
|
sysfs_add_battery(battery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
FS Interface (/proc)
|
||||||
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
static struct proc_dir_entry *acpi_battery_dir;
|
||||||
|
|
||||||
|
static int acpi_battery_print_info(struct seq_file *seq, int result)
|
||||||
|
{
|
||||||
|
struct acpi_battery *battery = seq->private;
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
seq_printf(seq, "present: %s\n",
|
||||||
|
acpi_battery_present(battery) ? "yes" : "no");
|
||||||
|
if (!acpi_battery_present(battery))
|
||||||
|
goto end;
|
||||||
|
if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
|
||||||
|
seq_printf(seq, "design capacity: unknown\n");
|
||||||
|
else
|
||||||
|
seq_printf(seq, "design capacity: %d %sh\n",
|
||||||
|
battery->design_capacity,
|
||||||
|
acpi_battery_units(battery));
|
||||||
|
|
||||||
|
if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
|
||||||
|
seq_printf(seq, "last full capacity: unknown\n");
|
||||||
|
else
|
||||||
|
seq_printf(seq, "last full capacity: %d %sh\n",
|
||||||
|
battery->full_charge_capacity,
|
||||||
|
acpi_battery_units(battery));
|
||||||
|
|
||||||
|
seq_printf(seq, "battery technology: %srechargeable\n",
|
||||||
|
(!battery->technology)?"non-":"");
|
||||||
|
|
||||||
|
if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
|
||||||
|
seq_printf(seq, "design voltage: unknown\n");
|
||||||
|
else
|
||||||
|
seq_printf(seq, "design voltage: %d mV\n",
|
||||||
|
battery->design_voltage);
|
||||||
|
seq_printf(seq, "design capacity warning: %d %sh\n",
|
||||||
|
battery->design_capacity_warning,
|
||||||
|
acpi_battery_units(battery));
|
||||||
|
seq_printf(seq, "design capacity low: %d %sh\n",
|
||||||
|
battery->design_capacity_low,
|
||||||
|
acpi_battery_units(battery));
|
||||||
|
seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
|
||||||
|
seq_printf(seq, "capacity granularity 1: %d %sh\n",
|
||||||
|
battery->capacity_granularity_1,
|
||||||
|
acpi_battery_units(battery));
|
||||||
|
seq_printf(seq, "capacity granularity 2: %d %sh\n",
|
||||||
|
battery->capacity_granularity_2,
|
||||||
|
acpi_battery_units(battery));
|
||||||
|
seq_printf(seq, "model number: %s\n", battery->model_number);
|
||||||
|
seq_printf(seq, "serial number: %s\n", battery->serial_number);
|
||||||
|
seq_printf(seq, "battery type: %s\n", battery->type);
|
||||||
|
seq_printf(seq, "OEM info: %s\n", battery->oem_info);
|
||||||
|
end:
|
||||||
|
if (result)
|
||||||
|
seq_printf(seq, "ERROR: Unable to read battery info\n");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int acpi_battery_print_state(struct seq_file *seq, int result)
|
||||||
|
{
|
||||||
|
struct acpi_battery *battery = seq->private;
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
seq_printf(seq, "present: %s\n",
|
||||||
|
acpi_battery_present(battery) ? "yes" : "no");
|
||||||
|
if (!acpi_battery_present(battery))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
seq_printf(seq, "capacity state: %s\n",
|
||||||
|
(battery->state & 0x04) ? "critical" : "ok");
|
||||||
|
if ((battery->state & 0x01) && (battery->state & 0x02))
|
||||||
|
seq_printf(seq,
|
||||||
|
"charging state: charging/discharging\n");
|
||||||
|
else if (battery->state & 0x01)
|
||||||
|
seq_printf(seq, "charging state: discharging\n");
|
||||||
|
else if (battery->state & 0x02)
|
||||||
|
seq_printf(seq, "charging state: charging\n");
|
||||||
|
else
|
||||||
|
seq_printf(seq, "charging state: charged\n");
|
||||||
|
|
||||||
|
if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
|
||||||
|
seq_printf(seq, "present rate: unknown\n");
|
||||||
|
else
|
||||||
|
seq_printf(seq, "present rate: %d %s\n",
|
||||||
|
battery->rate_now, acpi_battery_units(battery));
|
||||||
|
|
||||||
|
if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
|
||||||
|
seq_printf(seq, "remaining capacity: unknown\n");
|
||||||
|
else
|
||||||
|
seq_printf(seq, "remaining capacity: %d %sh\n",
|
||||||
|
battery->capacity_now, acpi_battery_units(battery));
|
||||||
|
if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
|
||||||
|
seq_printf(seq, "present voltage: unknown\n");
|
||||||
|
else
|
||||||
|
seq_printf(seq, "present voltage: %d mV\n",
|
||||||
|
battery->voltage_now);
|
||||||
|
end:
|
||||||
|
if (result)
|
||||||
|
seq_printf(seq, "ERROR: Unable to read battery state\n");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int acpi_battery_print_alarm(struct seq_file *seq, int result)
|
||||||
|
{
|
||||||
|
struct acpi_battery *battery = seq->private;
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!acpi_battery_present(battery)) {
|
||||||
|
seq_printf(seq, "present: no\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
seq_printf(seq, "alarm: ");
|
||||||
|
if (!battery->alarm)
|
||||||
|
seq_printf(seq, "unsupported\n");
|
||||||
|
else
|
||||||
|
seq_printf(seq, "%u %sh\n", battery->alarm,
|
||||||
|
acpi_battery_units(battery));
|
||||||
|
end:
|
||||||
|
if (result)
|
||||||
|
seq_printf(seq, "ERROR: Unable to read battery alarm\n");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t acpi_battery_write_alarm(struct file *file,
|
||||||
|
const char __user * buffer,
|
||||||
|
size_t count, loff_t * ppos)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
char alarm_string[12] = { '\0' };
|
||||||
|
struct seq_file *m = file->private_data;
|
||||||
|
struct acpi_battery *battery = m->private;
|
||||||
|
|
||||||
|
if (!battery || (count > sizeof(alarm_string) - 1))
|
||||||
|
return -EINVAL;
|
||||||
|
if (!acpi_battery_present(battery)) {
|
||||||
|
result = -ENODEV;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (copy_from_user(alarm_string, buffer, count)) {
|
||||||
|
result = -EFAULT;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
alarm_string[count] = '\0';
|
||||||
|
battery->alarm = simple_strtol(alarm_string, NULL, 0);
|
||||||
|
result = acpi_battery_set_alarm(battery);
|
||||||
|
end:
|
||||||
|
if (!result)
|
||||||
|
return count;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int(*print_func)(struct seq_file *seq, int result);
|
||||||
|
|
||||||
|
static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
|
||||||
|
acpi_battery_print_info,
|
||||||
|
acpi_battery_print_state,
|
||||||
|
acpi_battery_print_alarm,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int acpi_battery_read(int fid, struct seq_file *seq)
|
||||||
|
{
|
||||||
|
struct acpi_battery *battery = seq->private;
|
||||||
|
int result = acpi_battery_update(battery);
|
||||||
|
return acpi_print_funcs[fid](seq, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DECLARE_FILE_FUNCTIONS(_name) \
|
||||||
|
static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
|
||||||
|
{ \
|
||||||
|
return acpi_battery_read(_name##_tag, seq); \
|
||||||
|
} \
|
||||||
|
static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
|
||||||
|
{ \
|
||||||
|
return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_FILE_FUNCTIONS(info);
|
||||||
|
DECLARE_FILE_FUNCTIONS(state);
|
||||||
|
DECLARE_FILE_FUNCTIONS(alarm);
|
||||||
|
|
||||||
|
#undef DECLARE_FILE_FUNCTIONS
|
||||||
|
|
||||||
|
#define FILE_DESCRIPTION_RO(_name) \
|
||||||
|
{ \
|
||||||
|
.name = __stringify(_name), \
|
||||||
|
.mode = S_IRUGO, \
|
||||||
|
.ops = { \
|
||||||
|
.open = acpi_battery_##_name##_open_fs, \
|
||||||
|
.read = seq_read, \
|
||||||
|
.llseek = seq_lseek, \
|
||||||
|
.release = single_release, \
|
||||||
|
.owner = THIS_MODULE, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FILE_DESCRIPTION_RW(_name) \
|
||||||
|
{ \
|
||||||
|
.name = __stringify(_name), \
|
||||||
|
.mode = S_IFREG | S_IRUGO | S_IWUSR, \
|
||||||
|
.ops = { \
|
||||||
|
.open = acpi_battery_##_name##_open_fs, \
|
||||||
|
.read = seq_read, \
|
||||||
|
.llseek = seq_lseek, \
|
||||||
|
.write = acpi_battery_write_##_name, \
|
||||||
|
.release = single_release, \
|
||||||
|
.owner = THIS_MODULE, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct battery_file {
|
||||||
|
struct file_operations ops;
|
||||||
|
umode_t mode;
|
||||||
|
const char *name;
|
||||||
|
} acpi_battery_file[] = {
|
||||||
|
FILE_DESCRIPTION_RO(info),
|
||||||
|
FILE_DESCRIPTION_RO(state),
|
||||||
|
FILE_DESCRIPTION_RW(alarm),
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef FILE_DESCRIPTION_RO
|
||||||
|
#undef FILE_DESCRIPTION_RW
|
||||||
|
|
||||||
|
static int acpi_battery_add_fs(struct acpi_device *device)
|
||||||
|
{
|
||||||
|
struct proc_dir_entry *entry = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
|
||||||
|
" please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
|
||||||
|
if (!acpi_device_dir(device)) {
|
||||||
|
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
|
||||||
|
acpi_battery_dir);
|
||||||
|
if (!acpi_device_dir(device))
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
|
||||||
|
entry = proc_create_data(acpi_battery_file[i].name,
|
||||||
|
acpi_battery_file[i].mode,
|
||||||
|
acpi_device_dir(device),
|
||||||
|
&acpi_battery_file[i].ops,
|
||||||
|
acpi_driver_data(device));
|
||||||
|
if (!entry)
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void acpi_battery_remove_fs(struct acpi_device *device)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (!acpi_device_dir(device))
|
||||||
|
return;
|
||||||
|
for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
|
||||||
|
remove_proc_entry(acpi_battery_file[i].name,
|
||||||
|
acpi_device_dir(device));
|
||||||
|
|
||||||
|
remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
|
||||||
|
acpi_device_dir(device) = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
Driver Interface
|
Driver Interface
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
@ -790,6 +1090,15 @@ static int acpi_battery_add(struct acpi_device *device)
|
|||||||
result = acpi_battery_update(battery);
|
result = acpi_battery_update(battery);
|
||||||
if (result)
|
if (result)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
result = acpi_battery_add_fs(device);
|
||||||
|
#endif
|
||||||
|
if (result) {
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
acpi_battery_remove_fs(device);
|
||||||
|
#endif
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
|
printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
|
||||||
ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
|
ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
|
||||||
@ -816,6 +1125,9 @@ static int acpi_battery_remove(struct acpi_device *device)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
battery = acpi_driver_data(device);
|
battery = acpi_driver_data(device);
|
||||||
unregister_pm_notifier(&battery->pm_nb);
|
unregister_pm_notifier(&battery->pm_nb);
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
acpi_battery_remove_fs(device);
|
||||||
|
#endif
|
||||||
sysfs_remove_battery(battery);
|
sysfs_remove_battery(battery);
|
||||||
mutex_destroy(&battery->lock);
|
mutex_destroy(&battery->lock);
|
||||||
mutex_destroy(&battery->sysfs_lock);
|
mutex_destroy(&battery->sysfs_lock);
|
||||||
@ -866,7 +1178,19 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
|
|||||||
|
|
||||||
if (dmi_check_system(bat_dmi_table))
|
if (dmi_check_system(bat_dmi_table))
|
||||||
battery_bix_broken_package = 1;
|
battery_bix_broken_package = 1;
|
||||||
acpi_bus_register_driver(&acpi_battery_driver);
|
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
acpi_battery_dir = acpi_lock_battery_dir();
|
||||||
|
if (!acpi_battery_dir)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
acpi_unlock_battery_dir(acpi_battery_dir);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init acpi_battery_init(void)
|
static int __init acpi_battery_init(void)
|
||||||
@ -878,6 +1202,9 @@ static int __init acpi_battery_init(void)
|
|||||||
static void __exit acpi_battery_exit(void)
|
static void __exit acpi_battery_exit(void)
|
||||||
{
|
{
|
||||||
acpi_bus_unregister_driver(&acpi_battery_driver);
|
acpi_bus_unregister_driver(&acpi_battery_driver);
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
acpi_unlock_battery_dir(acpi_battery_dir);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(acpi_battery_init);
|
module_init(acpi_battery_init);
|
||||||
|
@ -314,6 +314,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
|
|||||||
DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
|
DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.callback = dmi_disable_osi_win8,
|
||||||
|
.ident = "Dell Inspiron 7737",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
|
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
|
||||||
@ -374,6 +382,19 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
|
|||||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T500"),
|
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T500"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
|
* Without this this EEEpc exports a non working WMI interface, with
|
||||||
|
* this it exports a working "good old" eeepc_laptop interface, fixing
|
||||||
|
* both brightness control, and rfkill not working.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
.callback = dmi_enable_osi_linux,
|
||||||
|
.ident = "Asus EEE PC 1015PX",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
105
drivers/acpi/cm_sbs.c
Normal file
105
drivers/acpi/cm_sbs.c
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/proc_fs.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
#include <acpi/acpi_bus.h>
|
||||||
|
#include <acpi/acpi_drivers.h>
|
||||||
|
|
||||||
|
#define PREFIX "ACPI: "
|
||||||
|
|
||||||
|
ACPI_MODULE_NAME("cm_sbs");
|
||||||
|
#define ACPI_AC_CLASS "ac_adapter"
|
||||||
|
#define ACPI_BATTERY_CLASS "battery"
|
||||||
|
#define _COMPONENT ACPI_SBS_COMPONENT
|
||||||
|
static struct proc_dir_entry *acpi_ac_dir;
|
||||||
|
static struct proc_dir_entry *acpi_battery_dir;
|
||||||
|
|
||||||
|
static DEFINE_MUTEX(cm_sbs_mutex);
|
||||||
|
|
||||||
|
static int lock_ac_dir_cnt;
|
||||||
|
static int lock_battery_dir_cnt;
|
||||||
|
|
||||||
|
struct proc_dir_entry *acpi_lock_ac_dir(void)
|
||||||
|
{
|
||||||
|
mutex_lock(&cm_sbs_mutex);
|
||||||
|
if (!acpi_ac_dir)
|
||||||
|
acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
|
||||||
|
if (acpi_ac_dir) {
|
||||||
|
lock_ac_dir_cnt++;
|
||||||
|
} else {
|
||||||
|
printk(KERN_ERR PREFIX
|
||||||
|
"Cannot create %s\n", ACPI_AC_CLASS);
|
||||||
|
}
|
||||||
|
mutex_unlock(&cm_sbs_mutex);
|
||||||
|
return acpi_ac_dir;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(acpi_lock_ac_dir);
|
||||||
|
|
||||||
|
void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param)
|
||||||
|
{
|
||||||
|
mutex_lock(&cm_sbs_mutex);
|
||||||
|
if (acpi_ac_dir_param)
|
||||||
|
lock_ac_dir_cnt--;
|
||||||
|
if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) {
|
||||||
|
remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
|
||||||
|
acpi_ac_dir = NULL;
|
||||||
|
}
|
||||||
|
mutex_unlock(&cm_sbs_mutex);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(acpi_unlock_ac_dir);
|
||||||
|
|
||||||
|
struct proc_dir_entry *acpi_lock_battery_dir(void)
|
||||||
|
{
|
||||||
|
mutex_lock(&cm_sbs_mutex);
|
||||||
|
if (!acpi_battery_dir) {
|
||||||
|
acpi_battery_dir =
|
||||||
|
proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
|
||||||
|
}
|
||||||
|
if (acpi_battery_dir) {
|
||||||
|
lock_battery_dir_cnt++;
|
||||||
|
} else {
|
||||||
|
printk(KERN_ERR PREFIX
|
||||||
|
"Cannot create %s\n", ACPI_BATTERY_CLASS);
|
||||||
|
}
|
||||||
|
mutex_unlock(&cm_sbs_mutex);
|
||||||
|
return acpi_battery_dir;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(acpi_lock_battery_dir);
|
||||||
|
|
||||||
|
void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param)
|
||||||
|
{
|
||||||
|
mutex_lock(&cm_sbs_mutex);
|
||||||
|
if (acpi_battery_dir_param)
|
||||||
|
lock_battery_dir_cnt--;
|
||||||
|
if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param
|
||||||
|
&& acpi_battery_dir) {
|
||||||
|
remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
|
||||||
|
acpi_battery_dir = NULL;
|
||||||
|
}
|
||||||
|
mutex_unlock(&cm_sbs_mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(acpi_unlock_battery_dir);
|
@ -457,10 +457,10 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.callback = video_set_use_native_backlight,
|
.callback = video_set_use_native_backlight,
|
||||||
.ident = "ThinkPad T430s",
|
.ident = "ThinkPad T430 and T430s",
|
||||||
.matches = {
|
.matches = {
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"),
|
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -472,7 +472,7 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.callback = video_set_use_native_backlight,
|
.callback = video_set_use_native_backlight,
|
||||||
.ident = "ThinkPad X1 Carbon",
|
.ident = "ThinkPad X1 Carbon",
|
||||||
.matches = {
|
.matches = {
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||||
@ -500,7 +500,7 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
|
|||||||
.ident = "Dell Inspiron 7520",
|
.ident = "Dell Inspiron 7520",
|
||||||
.matches = {
|
.matches = {
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Inspiron 7520"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -511,6 +511,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
|
|||||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.callback = video_set_use_native_backlight,
|
||||||
|
.ident = "Acer Aspire 5742G",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5742G"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.callback = video_set_use_native_backlight,
|
.callback = video_set_use_native_backlight,
|
||||||
.ident = "Acer Aspire V5-431",
|
.ident = "Acer Aspire V5-431",
|
||||||
|
@ -328,13 +328,11 @@ int tpm_add_ppi(struct kobject *parent)
|
|||||||
/* Cache TPM ACPI handle and version string */
|
/* Cache TPM ACPI handle and version string */
|
||||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
|
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
|
||||||
ppi_callback, NULL, NULL, &tpm_ppi_handle);
|
ppi_callback, NULL, NULL, &tpm_ppi_handle);
|
||||||
if (tpm_ppi_handle == NULL)
|
return tpm_ppi_handle ? sysfs_create_group(parent, &ppi_attr_grp) : 0;
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
return sysfs_create_group(parent, &ppi_attr_grp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tpm_remove_ppi(struct kobject *parent)
|
void tpm_remove_ppi(struct kobject *parent)
|
||||||
{
|
{
|
||||||
sysfs_remove_group(parent, &ppi_attr_grp);
|
if (tpm_ppi_handle)
|
||||||
|
sysfs_remove_group(parent, &ppi_attr_grp);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#define BYT_RATIOS 0x66a
|
#define BYT_RATIOS 0x66a
|
||||||
#define BYT_VIDS 0x66b
|
#define BYT_VIDS 0x66b
|
||||||
#define BYT_TURBO_RATIOS 0x66c
|
#define BYT_TURBO_RATIOS 0x66c
|
||||||
|
#define BYT_TURBO_VIDS 0x66d
|
||||||
|
|
||||||
|
|
||||||
#define FRAC_BITS 6
|
#define FRAC_BITS 6
|
||||||
@ -70,8 +71,9 @@ struct pstate_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct vid_data {
|
struct vid_data {
|
||||||
int32_t min;
|
int min;
|
||||||
int32_t max;
|
int max;
|
||||||
|
int turbo;
|
||||||
int32_t ratio;
|
int32_t ratio;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -359,14 +361,14 @@ static int byt_get_min_pstate(void)
|
|||||||
{
|
{
|
||||||
u64 value;
|
u64 value;
|
||||||
rdmsrl(BYT_RATIOS, value);
|
rdmsrl(BYT_RATIOS, value);
|
||||||
return (value >> 8) & 0xFF;
|
return (value >> 8) & 0x3F;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int byt_get_max_pstate(void)
|
static int byt_get_max_pstate(void)
|
||||||
{
|
{
|
||||||
u64 value;
|
u64 value;
|
||||||
rdmsrl(BYT_RATIOS, value);
|
rdmsrl(BYT_RATIOS, value);
|
||||||
return (value >> 16) & 0xFF;
|
return (value >> 16) & 0x3F;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int byt_get_turbo_pstate(void)
|
static int byt_get_turbo_pstate(void)
|
||||||
@ -393,6 +395,9 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
|
|||||||
vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max);
|
vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max);
|
||||||
vid = fp_toint(vid_fp);
|
vid = fp_toint(vid_fp);
|
||||||
|
|
||||||
|
if (pstate > cpudata->pstate.max_pstate)
|
||||||
|
vid = cpudata->vid.turbo;
|
||||||
|
|
||||||
val |= vid;
|
val |= vid;
|
||||||
|
|
||||||
wrmsrl(MSR_IA32_PERF_CTL, val);
|
wrmsrl(MSR_IA32_PERF_CTL, val);
|
||||||
@ -402,13 +407,17 @@ static void byt_get_vid(struct cpudata *cpudata)
|
|||||||
{
|
{
|
||||||
u64 value;
|
u64 value;
|
||||||
|
|
||||||
|
|
||||||
rdmsrl(BYT_VIDS, value);
|
rdmsrl(BYT_VIDS, value);
|
||||||
cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
|
cpudata->vid.min = int_tofp((value >> 8) & 0x3f);
|
||||||
cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
|
cpudata->vid.max = int_tofp((value >> 16) & 0x3f);
|
||||||
cpudata->vid.ratio = div_fp(
|
cpudata->vid.ratio = div_fp(
|
||||||
cpudata->vid.max - cpudata->vid.min,
|
cpudata->vid.max - cpudata->vid.min,
|
||||||
int_tofp(cpudata->pstate.max_pstate -
|
int_tofp(cpudata->pstate.max_pstate -
|
||||||
cpudata->pstate.min_pstate));
|
cpudata->pstate.min_pstate));
|
||||||
|
|
||||||
|
rdmsrl(BYT_TURBO_VIDS, value);
|
||||||
|
cpudata->vid.turbo = value & 0x7f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -545,12 +554,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
|
|||||||
|
|
||||||
if (pstate_funcs.get_vid)
|
if (pstate_funcs.get_vid)
|
||||||
pstate_funcs.get_vid(cpu);
|
pstate_funcs.get_vid(cpu);
|
||||||
|
intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
|
||||||
/*
|
|
||||||
* goto max pstate so we don't slow up boot if we are built-in if we are
|
|
||||||
* a module we will take care of it during normal operation
|
|
||||||
*/
|
|
||||||
intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void intel_pstate_calc_busy(struct cpudata *cpu,
|
static inline void intel_pstate_calc_busy(struct cpudata *cpu,
|
||||||
@ -695,11 +699,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
|
|||||||
cpu = all_cpu_data[cpunum];
|
cpu = all_cpu_data[cpunum];
|
||||||
|
|
||||||
intel_pstate_get_cpu_pstates(cpu);
|
intel_pstate_get_cpu_pstates(cpu);
|
||||||
if (!cpu->pstate.current_pstate) {
|
|
||||||
all_cpu_data[cpunum] = NULL;
|
|
||||||
kfree(cpu);
|
|
||||||
return -ENODATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu->cpu = cpunum;
|
cpu->cpu = cpunum;
|
||||||
|
|
||||||
@ -710,7 +709,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
|
|||||||
cpu->timer.expires = jiffies + HZ/100;
|
cpu->timer.expires = jiffies + HZ/100;
|
||||||
intel_pstate_busy_pid_reset(cpu);
|
intel_pstate_busy_pid_reset(cpu);
|
||||||
intel_pstate_sample(cpu);
|
intel_pstate_sample(cpu);
|
||||||
intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
|
|
||||||
|
|
||||||
add_timer_on(&cpu->timer, cpunum);
|
add_timer_on(&cpu->timer, cpunum);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user