- this file.
ABI/
- info on kernel <-> userspace ABI and relative interface stability.
++ +++++++++++
BUG-HUNTING
- brute force method of doing binary search of patches to find bug.
Changes
- how to change your VGA cursor from a blinking underscore.
accounting/
- documentation on accounting and taskstats.
++ +++++++++++acpi/
++ +++++++++++ - info on ACPI-specific hooks in the kernel.
aoe/
- description of AoE (ATA over Ethernet) along with config examples.
applying-patches.txt
- request_firmware() hotplug interface info.
floppy.txt
- notes and driver options for the floppy disk driver.
-------------fujitsu/
+++++++++++++frv/
- Fujitsu FR-V Linux documentation.
gpio.txt
- overview of GPIO (General Purpose Input/Output) access conventions.
- how to use PPro Memory Type Range Registers to increase performance.
mutex-design.txt
- info on the generic mutex subsystem.
++ + + namespaces/
++ + + - directory with various information about namespaces
nbd.txt
- info on a TCP implementation of a network block device.
netlabel/
- a description of shared subtrees for namespaces.
smart-config.txt
- description of the Smart Config makefile feature.
-------------smp.txt
------------- - a few notes on symmetric multi-processing.
sony-laptop.txt
- Sony Notebook Control Driver (SNC) Readme.
sonypi.txt
unsigned long acpi_wakeup_address = 0;
++++++++++ +++#ifdef CONFIG_IA64_GENERIC
++++++++++ +++static unsigned long __init acpi_find_rsdp(void)
++++++++++ +++{
++++++++++ +++ unsigned long rsdp_phys = 0;
++++++++++ +++
++++++++++ +++ if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
++++++++++ +++ rsdp_phys = efi.acpi20;
++++++++++ +++ else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
++++++++++ +++ printk(KERN_WARNING PREFIX
++++++++++ +++ "v1.0/r0.71 tables no longer supported\n");
++++++++++ +++ return rsdp_phys;
++++++++++ +++}
++++++++++ +++#endif
++++++++++ +++
const char __init *
acpi_get_sysname(void)
{
return 0;
}
---------- ---unsigned long __init acpi_find_rsdp(void)
---------- ---{
---------- --- unsigned long rsdp_phys = 0;
---------- ---
---------- --- if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
---------- --- rsdp_phys = efi.acpi20;
---------- --- else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
---------- --- printk(KERN_WARNING PREFIX
---------- --- "v1.0/r0.71 tables no longer supported\n");
---------- --- return rsdp_phys;
---------- ---}
---------- ---
int __init acpi_boot_init(void)
{
lsapic = (struct acpi_madt_local_sapic *)obj->buffer.pointer;
if ((lsapic->header.type != ACPI_MADT_TYPE_LOCAL_SAPIC) ||
-- - - - (!lsapic->lapic_flags & ACPI_MADT_ENABLED)) {
++ + + + (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))) {
kfree(buffer.pointer);
return -EINVAL;
}
* ACPI based hotplug support for CPU
*/
#ifdef CONFIG_ACPI_HOTPLUG_CPU
------- -- --int acpi_map_lsapic(acpi_handle handle, int *pcpu)
+++++++ ++ ++
+++++++ ++ ++static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
return 0;
}
+++++++ ++ ++/* wrapper to silence section mismatch warning */
+++++++ ++ ++int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
+++++++ ++ ++{
+++++++ ++ ++ return _acpi_map_lsapic(handle, pcpu);
+++++++ ++ ++}
EXPORT_SYMBOL(acpi_map_lsapic);
int acpi_unmap_lsapic(int cpu)
EXPORT_SYMBOL(acpi_unregister_ioapic);
---------- ---static unsigned long __init
---------- ---acpi_scan_rsdp(unsigned long start, unsigned long length)
---------- ---{
---------- --- unsigned long offset = 0;
---------- --- unsigned long sig_len = sizeof("RSD PTR ") - 1;
---------- ---
---------- --- /*
---------- --- * Scan all 16-byte boundaries of the physical memory region for the
---------- --- * RSDP signature.
---------- --- */
---------- --- for (offset = 0; offset < length; offset += 16) {
---------- --- if (strncmp((char *)(phys_to_virt(start) + offset), "RSD PTR ", sig_len))
---------- --- continue;
---------- --- return (start + offset);
---------- --- }
---------- ---
---------- --- return 0;
---------- ---}
---------- ---
static int __init acpi_parse_sbf(struct acpi_table_header *table)
{
struct acpi_table_boot *sb;
return 0;
}
---------- ---unsigned long __init acpi_find_rsdp(void)
---------- ---{
---------- --- unsigned long rsdp_phys = 0;
---------- ---
---------- --- if (efi_enabled) {
---------- --- if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
---------- --- return efi.acpi20;
---------- --- else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
---------- --- return efi.acpi;
---------- --- }
---------- --- /*
---------- --- * Scan memory looking for the RSDP signature. First search EBDA (low
---------- --- * memory) paragraphs and then search upper memory (E0000-FFFFF).
---------- --- */
---------- --- rsdp_phys = acpi_scan_rsdp(0, 0x400);
---------- --- if (!rsdp_phys)
---------- --- rsdp_phys = acpi_scan_rsdp(0xE0000, 0x20000);
---------- ---
---------- --- return rsdp_phys;
---------- ---}
---------- ---
#ifdef CONFIG_X86_LOCAL_APIC
/*
* Parse LAPIC entries in MADT
static int num_memory_chunks; /* total number of memory chunks */
static u8 __initdata apicid_to_pxm[MAX_APICID];
------- -- --extern void * boot_ioremap(unsigned long, unsigned long);
------- -- --
/* Identify CPU proximity domains */
static void __init parse_cpu_affinity_structure(char *p)
{
int tables = 0;
int i = 0;
---------- --- rsdp_address = acpi_find_rsdp();
++++++++++ +++ rsdp_address = acpi_os_get_root_pointer();
if (!rsdp_address) {
printk("%s: System description tables not found\n",
__FUNCTION__);
}
rsdt = (struct acpi_table_rsdt *)
------- -- -- boot_ioremap(rsdp->rsdt_physical_address, sizeof(struct acpi_table_rsdt));
+++++++ ++ ++ early_ioremap(rsdp->rsdt_physical_address, sizeof(struct acpi_table_rsdt));
if (!rsdt) {
printk(KERN_WARNING
for (i = 0; i < tables; i++) {
/* Map in header, then map in full table length. */
header = (struct acpi_table_header *)
------- -- -- boot_ioremap(saved_rsdt.table.table_offset_entry[i], sizeof(struct acpi_table_header));
+++++++ ++ ++ early_ioremap(saved_rsdt.table.table_offset_entry[i], sizeof(struct acpi_table_header));
if (!header)
break;
header = (struct acpi_table_header *)
------- -- -- boot_ioremap(saved_rsdt.table.table_offset_entry[i], header->length);
+++++++ ++ ++ early_ioremap(saved_rsdt.table.table_offset_entry[i], header->length);
if (!header)
break;
*
* Check to see if the given machine has a known bad ACPI BIOS
* or if the BIOS is too old.
+++++++ ++ ++ * Check given machine against acpi_osi_dmi_table[].
*
u32 is_critical_error;
};
+++++++ ++ ++static struct dmi_system_id acpi_osi_dmi_table[] __initdata;
+++++++ ++ ++
/*
* POLICY: If *anything* doesn't work, put it on the blacklist.
* If they are critical errors, mark it critical, and abort driver load.
/* IBM 600E - _ADR should return 7, but it returns 1 */
{"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal,
"Incorrect _ADR", 1},
--- ---------- {"ASUS\0\0", "P2B-S ", 0, ACPI_SIG_DSDT, all_versions,
--- ---------- "Bogus PCI routing", 1},
{""}
};
blacklisted += blacklist_by_year();
+++++++ ++ ++ dmi_check_system(acpi_osi_dmi_table);
+++++++ ++ ++
return blacklisted;
}
+++++++ ++ ++#ifdef CONFIG_DMI
+++++++ ++ ++static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
+++++++ ++ ++{
+++++++ ++ ++ acpi_dmi_osi_linux(1, d); /* enable */
+++++++ ++ ++ return 0;
+++++++ ++ ++}
+++++++ ++ ++static int __init dmi_disable_osi_linux(const struct dmi_system_id *d)
+++++++ ++ ++{
+++++++ ++ ++ acpi_dmi_osi_linux(0, d); /* disable */
+++++++ ++ ++ return 0;
+++++++ ++ ++}
+++++++ ++ ++static int __init dmi_unknown_osi_linux(const struct dmi_system_id *d)
+++++++ ++ ++{
+++++++ ++ ++ acpi_dmi_osi_linux(-1, d); /* unknown */
+++++++ ++ ++ return 0;
+++++++ ++ ++}
+++++++ ++ ++
+++++++ ++ ++/*
+++++++ ++ ++ * Most BIOS that invoke OSI(Linux) do nothing with it.
+++++++ ++ ++ * But some cause Linux to break.
+++++++ ++ ++ * Only a couple use it to make Linux run better.
+++++++ ++ ++ *
+++++++ ++ ++ * Thus, Linux should continue to disable OSI(Linux) by default,
+++++++ ++ ++ * should continue to discourage BIOS writers from using it, and
+++++++ ++ ++ * should whitelist the few existing systems that require it.
+++++++ ++ ++ *
+++++++ ++ ++ * If it appears clear a vendor isn't using OSI(Linux)
+++++++ ++ ++ * for anything constructive, blacklist them by name to disable
+++++++ ++ ++ * unnecessary dmesg warnings on all of their products.
+++++++ ++ ++ */
+++++++ ++ ++
+++++++ ++ ++static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "Acer, inc."
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) disables the latest Windows BIOS code:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"),
+++++++ ++ ++ * _OSI(Linux) effect unknown:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Acer, inc.",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Acer, inc."),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "Acer"
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) effect unknown:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_unknown_osi_linux,
+++++++ ++ ++ .ident = "Acer",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "Apple Computer, Inc."
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) confirmed to be a NOP:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"),
+++++++ ++ ++ * _OSI(Linux) effect unknown:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Apple",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "BenQ"
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) confirmed to be a NOP:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Joybook S31"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "BenQ",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "BenQ"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "Clevo Co."
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) confirmed to be a NOP:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "M570RU"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Clevo",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Clevo Co."),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "COMPAL"
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) confirmed to be a NOP:
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "HEL8X"),
+++++++ ++ ++ * _OSI(Linux) unknown effect:
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "IFL91"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_unknown_osi_linux,
+++++++ ++ ++ .ident = "Compal",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ { /* OSI(Linux) touches USB, breaks suspend to disk */
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Dell Dimension 5150",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM051"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ { /* OSI(Linux) is a NOP */
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Dell",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ { /* OSI(Linux) effect unknown */
+++++++ ++ ++ .callback = dmi_unknown_osi_linux,
+++++++ ++ ++ .ident = "Dell",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ { /* OSI(Linux) effect unknown */
+++++++ ++ ++ .callback = dmi_unknown_osi_linux,
+++++++ ++ ++ .ident = "Dell",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ { /* OSI(Linux) effect unknown */
+++++++ ++ ++ .callback = dmi_unknown_osi_linux,
+++++++ ++ ++ .ident = "Dell",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ { /* OSI(Linux) touches USB */
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Dell",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ { /* OSI(Linux) is a NOP */
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Dell Vostro 1000",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1000"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ { /* OSI(Linux) effect unknown */
+++++++ ++ ++ .callback = dmi_unknown_osi_linux,
+++++++ ++ ++ .ident = "Dell",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ { /* OSI(Linux) effect unknown */
+++++++ ++ ++ .callback = dmi_unknown_osi_linux,
+++++++ ++ ++ .ident = "Dialogue Flybook V5",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Dialogue Technology Corporation"),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_NAME, "Flybook V5"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "FUJITSU SIEMENS"
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) disables latest Windows BIOS code:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2510"),
+++++++ ++ ++ * _OSI(Linux) confirmed to be a NOP:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1536"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1556"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 1546"),
+++++++ ++ ++ * _OSI(Linux) unknown effect:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo M1425"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo Si 1520"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Fujitsu Siemens",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "Hewlett-Packard"
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) confirmed to be a NOP:
+++++++ ++ ++ * .ident = "HP Pavilion tx 1000"
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30BF"),
+++++++ ++ ++ * .ident = "HP Pavilion dv2000"
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30B5"),
+++++++ ++ ++ * .ident = "HP Pavilion dv5000",
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30A7"),
+++++++ ++ ++ * .ident = "HP Pavilion dv6300 30BC",
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30BC"),
+++++++ ++ ++ * .ident = "HP Pavilion dv6000",
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30B7"),
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30B8"),
+++++++ ++ ++ * .ident = "HP Pavilion dv9000",
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30B9"),
+++++++ ++ ++ * .ident = "HP Pavilion dv9500",
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30CB"),
+++++++ ++ ++ * .ident = "HP/Compaq Presario C500",
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30C6"),
+++++++ ++ ++ * .ident = "HP/Compaq Presario F500",
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30D3"),
+++++++ ++ ++ * _OSI(Linux) unknown effect:
+++++++ ++ ++ * .ident = "HP Pavilion dv6500",
+++++++ ++ ++ * DMI_MATCH(DMI_BOARD_NAME, "30D0"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Hewlett-Packard",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Lenovo has a mix of systems OSI(Linux) situations
+++++++ ++ ++ * and thus we can not wildcard the vendor.
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) helps sound
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"),
+++++++ ++ ++ * _OSI(Linux) is a NOP:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_enable_osi_linux,
+++++++ ++ ++ .ident = "Lenovo ThinkPad R61",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_enable_osi_linux,
+++++++ ++ ++ .ident = "Lenovo ThinkPad T61",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_unknown_osi_linux,
+++++++ ++ ++ .ident = "Lenovo 3000 V100",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Lenovo 3000 N100",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "LG Electronics"
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) confirmed to be a NOP:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "LG",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /* NEC - OSI(Linux) effect unknown */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_unknown_osi_linux,
+++++++ ++ ++ .ident = "NEC VERSA M360",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "NEC Computers SAS"),
+++++++ ++ ++ DMI_MATCH(DMI_PRODUCT_NAME, "NEC VERSA M360"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "Samsung Electronics"
+++++++ ++ ++ *
+++++++ ++ ++ * OSI(Linux) disables PNP0C32 and other BIOS code for Windows:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "R40P/R41P"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "R59P/R60P/R61P"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Samsung",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "Sony Corporation"
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) is a NOP:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ650N"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ38GP_C"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-TZ21MN_N"),
+++++++ ++ ++ * _OSI(Linux) unknown effect:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_unknown_osi_linux,
+++++++ ++ ++ .ident = "Sony",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ /*
+++++++ ++ ++ * Disable OSI(Linux) warnings on all "TOSHIBA"
+++++++ ++ ++ *
+++++++ ++ ++ * _OSI(Linux) breaks sound (bugzilla 7787):
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P100"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P105"),
+++++++ ++ ++ * _OSI(Linux) is a NOP:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A100"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A210"),
+++++++ ++ ++ * _OSI(Linux) unknown effect:
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A135"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A200"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P205"),
+++++++ ++ ++ * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U305"),
+++++++ ++ ++ */
+++++++ ++ ++ {
+++++++ ++ ++ .callback = dmi_disable_osi_linux,
+++++++ ++ ++ .ident = "Toshiba",
+++++++ ++ ++ .matches = {
+++++++ ++ ++ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+++++++ ++ ++ },
+++++++ ++ ++ },
+++++++ ++ ++ {}
+++++++ ++ ++};
+++++++ ++ ++
+++++++ ++ ++#endif /* CONFIG_DMI */
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
+++++++ ++ ++/* Uncomment next line to get verbose print outs*/
+++++++ ++ ++/* #define DEBUG */
+++++++ ++ ++
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#undef PREFIX
#define PREFIX "ACPI: EC: "
- --- - --/* Uncomment next line to get verbose print outs*/
- --- - --/* #define DEBUG */
- --- - --
/* EC status register */
#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */
EC_FLAGS_QUERY_PENDING, /* Query is pending */
EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */
-- - - EC_FLAGS_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */
++ + + EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */
++ + + EC_FLAGS_ADDRESS, /* Address is being written */
++ + + EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */
++ + + EC_FLAGS_WDATA, /* Data is being written */
+++++++ ++ ++ EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */
};
static int acpi_ec_remove(struct acpi_device *device, int type);
static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
{
-- - - return inb(ec->command_addr);
++ + + u8 x = inb(ec->command_addr);
- --- - -- pr_debug(PREFIX "---> status = 0x%2x\n", x);
+++++++ ++ ++ pr_debug(PREFIX "---> status = 0x%2.2x\n", x);
++ + + return x;
}
static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
{
- --- - -- pr_debug(PREFIX "---> data = 0x%2x\n", x);
++ + + u8 x = inb(ec->data_addr);
+++++++ ++ ++ pr_debug(PREFIX "---> data = 0x%2.2x\n", x);
return inb(ec->data_addr);
}
static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
{
- --- - -- pr_debug(PREFIX "<--- command = 0x%2x\n", command);
+++++++ ++ ++ pr_debug(PREFIX "<--- command = 0x%2.2x\n", command);
outb(command, ec->command_addr);
}
static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
{
- --- - -- pr_debug(PREFIX "<--- data = 0x%2x\n", data);
+++++++ ++ ++ pr_debug(PREFIX "<--- data = 0x%2.2x\n", data);
outb(data, ec->data_addr);
}
static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
{
++ + + int ret = 0;
+++++++ ++ ++
+++++++ ++ ++ if (unlikely(event == ACPI_EC_EVENT_OBF_1 &&
+++++++ ++ ++ test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags)))
+++++++ ++ ++ force_poll = 1;
++ + + if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) &&
++ + + test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags)))
++ + + force_poll = 1;
++ + + if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) &&
++ + + test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags)))
++ + + force_poll = 1;
if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
likely(!force_poll)) {
if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
msecs_to_jiffies(ACPI_EC_DELAY)))
-- - - return 0;
++ + + goto end;
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
if (acpi_ec_check_status(ec, event)) {
- --- - -- if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) {
+ +++ + ++ if (event == ACPI_EC_EVENT_OBF_1) {
-- - - /* miss OBF = 1 GPE, don't expect it anymore */
-- - - printk(KERN_INFO PREFIX "missing OBF_1 confirmation,"
-- - - "switching to degraded mode.\n");
-- - - set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags);
+++++++ ++ ++ /* miss OBF_1 GPE, don't expect it */
+++++++ ++ ++ pr_info(PREFIX "missing OBF confirmation, "
+++++++ ++ ++ "don't expect it any longer.\n");
+++++++ ++ ++ set_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags);
+++++++ ++ ++ } else if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) {
++ + + /* miss address GPE, don't expect it anymore */
++ + + pr_info(PREFIX "missing address confirmation, "
++ + + "don't expect it any longer.\n");
++ + + set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags);
++ + + } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) {
++ + + /* miss write data GPE, don't expect it */
++ + + pr_info(PREFIX "missing write data confirmation, "
++ + + "don't expect it any longer.\n");
++ + + set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags);
} else {
/* missing GPEs, switch back to poll mode */
-- - - printk(KERN_INFO PREFIX "missing IBF_1 confirmations,"
-- - - "switch off interrupt mode.\n");
++ + + if (printk_ratelimit())
++ + + pr_info(PREFIX "missing confirmations, "
++ + + "switch off interrupt mode.\n");
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
}
-- - - return 0;
++ + + goto end;
}
} else {
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
while (time_before(jiffies, delay)) {
if (acpi_ec_check_status(ec, event))
-- - - return 0;
++ + + goto end;
}
}
-- - - printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
++ + + pr_err(PREFIX "acpi_ec_wait timeout,"
" status = %d, expect_event = %d\n",
acpi_ec_read_status(ec), event);
-- - - return -ETIME;
++ + + ret = -ETIME;
++ + + end:
++ + + clear_bit(EC_FLAGS_ADDRESS, &ec->flags);
++ + + return ret;
}
static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
int result = 0;
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
acpi_ec_write_cmd(ec, command);
-- - -
++ + + pr_debug(PREFIX "transaction start\n");
for (; wdata_len > 0; --wdata_len) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
if (result) {
-- - - printk(KERN_ERR PREFIX
++ + + pr_err(PREFIX
"write_cmd timeout, command = %d\n", command);
goto end;
}
++ + + /* mark the address byte written to EC */
++ + + if (rdata_len + wdata_len > 1)
++ + + set_bit(EC_FLAGS_ADDRESS, &ec->flags);
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
acpi_ec_write_data(ec, *(wdata++));
}
if (!rdata_len) {
++ + + set_bit(EC_FLAGS_WDATA, &ec->flags);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
if (result) {
-- - - printk(KERN_ERR PREFIX
++ + + pr_err(PREFIX
"finish-write timeout, command = %d\n", command);
goto end;
}
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
for (; rdata_len > 0; --rdata_len) {
-- - - if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags))
-- - - force_poll = 1;
result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
if (result) {
-- - - printk(KERN_ERR PREFIX "read timeout, command = %d\n",
-- - - command);
++ + + pr_err(PREFIX "read timeout, command = %d\n", command);
goto end;
}
/* Don't expect GPE after last read */
*(rdata++) = acpi_ec_read_data(ec);
}
end:
++ + + pr_debug(PREFIX "transaction end\n");
return result;
}
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
if (status) {
-- - - printk(KERN_ERR PREFIX
-- - - "input buffer is not empty, aborting transaction\n");
++ + + pr_err(PREFIX "input buffer is not empty, "
++ + + "aborting transaction\n");
goto end;
}
acpi_status status = AE_OK;
struct acpi_ec *ec = data;
++ + + pr_debug(PREFIX "~~~> interrupt\n");
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
wake_up(&ec->wait);
acpi_ec_gpe_query, ec);
} else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) {
/* this is non-query, must be confirmation */
-- - - printk(KERN_INFO PREFIX "non-query interrupt received,"
-- - - " switching to interrupt mode\n");
++ + + if (printk_ratelimit())
++ + + pr_info(PREFIX "non-query interrupt received,"
++ + + " switching to interrupt mode\n");
set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
}
void *handler_context, void *region_context)
{
struct acpi_ec *ec = handler_context;
--------- ---- int result = 0, i = 0;
+++++++++ ++++ int result = 0, i;
u8 temp = 0;
if ((address > 0xFF) || !value || !handler_context)
if (bits != 8 && acpi_strict)
return AE_BAD_PARAMETER;
--------- ---- while (bits - i > 0) {
+++++++++ ++++ acpi_ec_burst_enable(ec);
+++++++++ ++++
+++++++++ ++++ if (function == ACPI_READ) {
+++++++++ ++++ result = acpi_ec_read(ec, address, &temp);
+++++++++ ++++ *value = temp;
+++++++++ ++++ } else {
+++++++++ ++++ temp = 0xff & (*value);
+++++++++ ++++ result = acpi_ec_write(ec, address, temp);
+++++++++ ++++ }
+++++++++ ++++
+++++++++ ++++ for (i = 8; unlikely(bits - i > 0); i += 8) {
+++++++++ ++++ ++address;
if (function == ACPI_READ) {
result = acpi_ec_read(ec, address, &temp);
(*value) |= ((acpi_integer)temp) << i;
temp = 0xff & ((*value) >> i);
result = acpi_ec_write(ec, address, temp);
}
--------- ---- i += 8;
--------- ---- ++address;
}
+++++++++ ++++ acpi_ec_burst_disable(ec);
+++++++++ ++++
switch (result) {
case -EINVAL:
return AE_BAD_PARAMETER;
{
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
-- - - printk(KERN_ERR PREFIX "failed to remove space handler\n");
++ + + pr_err(PREFIX "failed to remove space handler\n");
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler)))
-- - - printk(KERN_ERR PREFIX "failed to remove gpe handler\n");
++ + + pr_err(PREFIX "failed to remove gpe handler\n");
ec->handlers_installed = 0;
}
first_ec = ec;
acpi_driver_data(device) = ec;
acpi_ec_add_fs(device);
-- - - printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
++ + + pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr);
-- - - printk(KERN_INFO PREFIX "driver started in %s mode\n",
++ + + pr_info(PREFIX "driver started in %s mode\n",
(test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll");
return 0;
}
return 0;
}
+++++++ ++ ++int __init acpi_boot_ec_enable(void)
+++++++ ++ ++{
+++++++ ++ ++ if (!boot_ec || boot_ec->handlers_installed)
+++++++ ++ ++ return 0;
+++++++ ++ ++ if (!ec_install_handlers(boot_ec)) {
+++++++ ++ ++ first_ec = boot_ec;
+++++++ ++ ++ return 0;
+++++++ ++ ++ }
+++++++ ++ ++ return -EFAULT;
+++++++ ++ ++}
+++++++ ++ ++
int __init acpi_ec_ecdt_probe(void)
{
int ret;
status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr);
if (ACPI_SUCCESS(status)) {
-- - - printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n");
++ + + pr_info(PREFIX "EC description table is found, configuring boot EC\n");
boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address;
boot_ec->gpe = ecdt_ptr->gpe;
boot_ec->handle = ACPI_ROOT_OBJECT;
} else {
++ + + /* This workaround is needed only on some broken machines,
++ + + * which require early EC, but fail to provide ECDT */
++ + + acpi_handle x;
printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
boot_ec, NULL);
/* Check that acpi_get_devices actually find something */
if (ACPI_FAILURE(status) || !boot_ec->handle)
goto error;
- --- - -- goto error;
++ + + /* We really need to limit this workaround, the only ASUS,
++ + + * which needs it, has fake EC._INI method, so use it as flag.
+++++++ ++ ++ * Keep boot_ec struct as it will be needed soon.
++ + + */
++ + + if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x)))
+++++++ ++ ++ return -ENODEV;
}
ret = ec_install_handlers(boot_ec);
#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
static char osi_additional_string[OSI_STRING_LENGTH_MAX];
------- -- --static int osi_linux; /* disable _OSI(Linux) by default */
+++++++ ++ ++/*
+++++++ ++ ++ * "Ode to _OSI(Linux)"
+++++++ ++ ++ *
+++++++ ++ ++ * osi_linux -- Control response to BIOS _OSI(Linux) query.
+++++++ ++ ++ *
+++++++ ++ ++ * As Linux evolves, the features that it supports change.
+++++++ ++ ++ * So an OSI string such as "Linux" is not specific enough
+++++++ ++ ++ * to be useful across multiple versions of Linux. It
+++++++ ++ ++ * doesn't identify any particular feature, interface,
+++++++ ++ ++ * or even any particular version of Linux...
+++++++ ++ ++ *
+++++++ ++ ++ * Unfortunately, Linux-2.6.22 and earlier responded "yes"
+++++++ ++ ++ * to a BIOS _OSI(Linux) query. When
+++++++ ++ ++ * a reference mobile BIOS started using it, its use
+++++++ ++ ++ * started to spread to many vendor platforms.
+++++++ ++ ++ * As it is not supportable, we need to halt that spread.
+++++++ ++ ++ *
+++++++ ++ ++ * Today, most BIOS references to _OSI(Linux) are noise --
+++++++ ++ ++ * they have no functional effect and are just dead code
+++++++ ++ ++ * carried over from the reference BIOS.
+++++++ ++ ++ *
+++++++ ++ ++ * The next most common case is that _OSI(Linux) harms Linux,
+++++++ ++ ++ * usually by causing the BIOS to follow paths that are
+++++++ ++ ++ * not tested during Windows validation.
+++++++ ++ ++ *
+++++++ ++ ++ * Finally, there is a short list of platforms
+++++++ ++ ++ * where OSI(Linux) benefits Linux.
+++++++ ++ ++ *
+++++++ ++ ++ * In Linux-2.6.23, OSI(Linux) is first disabled by default.
+++++++ ++ ++ * DMI is used to disable the dmesg warning about OSI(Linux)
+++++++ ++ ++ * on platforms where it is known to have no effect.
+++++++ ++ ++ * But a dmesg warning remains for systems where
+++++++ ++ ++ * we do not know if OSI(Linux) is good or bad for the system.
+++++++ ++ ++ * DMI is also used to enable OSI(Linux) for the machines
+++++++ ++ ++ * that are known to need it.
+++++++ ++ ++ *
+++++++ ++ ++ * BIOS writers should NOT query _OSI(Linux) on future systems.
+++++++ ++ ++ * It will be ignored by default, and to get Linux to
+++++++ ++ ++ * not ignore it will require a kernel source update to
+++++++ ++ ++ * add a DMI entry, or a boot-time "acpi_osi=Linux" invocation.
+++++++ ++ ++ */
+++++++ ++ ++#define OSI_LINUX_ENABLE 0
------- -- --#ifdef CONFIG_DMI
------- -- --static struct __initdata dmi_system_id acpi_osl_dmi_table[];
------- -- --#endif
+++++++ ++ ++struct osi_linux {
+++++++ ++ ++ unsigned int enable:1;
+++++++ ++ ++ unsigned int dmi:1;
+++++++ ++ ++ unsigned int cmdline:1;
+++++++ ++ ++ unsigned int known:1;
+++++++ ++ ++} osi_linux = { OSI_LINUX_ENABLE, 0, 0, 0};
static void __init acpi_request_region (struct acpi_generic_address *addr,
unsigned int length, char *desc)
acpi_status __init acpi_os_initialize(void)
{
------- -- -- dmi_check_system(acpi_osl_dmi_table);
return AE_OK;
}
"System description tables not found\n");
return 0;
}
---------- --- } else
---------- --- return acpi_find_rsdp();
++++++++++ +++ } else {
++++++++++ +++ acpi_physical_address pa = 0;
++++++++++ +++
++++++++++ +++ acpi_find_root_pointer(&pa);
++++++++++ +++ return pa;
++++++++++ +++ }
}
void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
if (!value)
value = &dummy;
-- - - switch (width) {
-- - - case 8:
++ + + *value = 0;
++ + + if (width <= 8) {
*(u8 *) value = inb(port);
-- - - break;
-- - - case 16:
++ + + } else if (width <= 16) {
*(u16 *) value = inw(port);
-- - - break;
-- - - case 32:
++ + + } else if (width <= 32) {
*(u32 *) value = inl(port);
-- - - break;
-- - - default:
++ + + } else {
BUG();
}
acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
{
-- - - switch (width) {
-- - - case 8:
++ + + if (width <= 8) {
outb(value, port);
-- - - break;
-- - - case 16:
++ + + } else if (width <= 16) {
outw(value, port);
-- - - break;
-- - - case 32:
++ + + } else if (width <= 32) {
outl(value, port);
-- - - break;
-- - - default:
++ + + } else {
BUG();
}
__setup("acpi_os_name=", acpi_os_name_setup);
------- -- --static void enable_osi_linux(int enable) {
+++++++ ++ ++static void __init set_osi_linux(unsigned int enable)
+++++++ ++ ++{
+++++++ ++ ++ if (osi_linux.enable != enable) {
+++++++ ++ ++ osi_linux.enable = enable;
+++++++ ++ ++ printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
+++++++ ++ ++ enable ? "Add": "Delet");
+++++++ ++ ++ }
+++++++ ++ ++ return;
+++++++ ++ ++}
+++++++ + ++
- if (osi_linux != enable)
- printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n",
- enable ? "En": "Dis");
+++++++ ++ ++static void __init acpi_cmdline_osi_linux(unsigned int enable)
+++++++ ++ ++{
+++++++ ++ ++ osi_linux.cmdline = 1; /* cmdline set the default */
+++++++ ++ ++ set_osi_linux(enable);
+++++++ ++ ++
+++++++ ++ ++ return;
+++++++ ++ ++}
+++++++ ++ ++
+++++++ ++ ++void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
+++++++ ++ ++{
+++++++ ++ ++ osi_linux.dmi = 1; /* DMI knows that this box asks OSI(Linux) */
+ +++ ++ ++
-- - if (osi_linux != enable)
-- - printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n",
-- - enable ? "En": "Dis");
+++++++ ++ ++ printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
+++++++ ++ ++
+++++++ ++ ++ if (enable == -1)
+++++++ ++ ++ return;
+++++++ ++ ++
+++++++ ++ ++ osi_linux.known = 1; /* DMI knows which OSI(Linux) default needed */
++ + +
- --- - -- if (osi_linux != enable)
- --- - -- printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n",
- --- - -- enable ? "En": "Dis");
+++++++ ++ ++ set_osi_linux(enable);
------- -- -- osi_linux = enable;
return;
}
printk(KERN_INFO PREFIX "_OSI method disabled\n");
acpi_gbl_create_osi_method = FALSE;
} else if (!strcmp("!Linux", str)) {
------- -- -- enable_osi_linux(0);
+++++++ ++ ++ acpi_cmdline_osi_linux(0); /* !enable */
} else if (*str == '!') {
if (acpi_osi_invalidate(++str) == AE_OK)
printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
} else if (!strcmp("Linux", str)) {
------- -- -- enable_osi_linux(1);
+++++++ ++ ++ acpi_cmdline_osi_linux(1); /* enable */
} else if (*osi_additional_string == '\0') {
strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX);
printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
return (AE_OK);
}
+++++++ ++ ++/**
+++++++ ++ ++ * acpi_dmi_dump - dump DMI slots needed for blacklist entry
+++++++ ++ ++ *
+++++++ ++ ++ * Returns 0 on success
+++++++ ++ ++ */
+++++++ ++ ++int acpi_dmi_dump(void)
+++++++ ++ ++{
+++++++ ++ ++
+++++++ ++ ++ if (!dmi_available)
+++++++ ++ ++ return -1;
+++++++ ++ ++
+++++++ ++ ++ printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
+++++++ ++ ++ dmi_get_slot(DMI_SYS_VENDOR));
+++++++ ++ ++ printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
+++++++ ++ ++ dmi_get_slot(DMI_PRODUCT_NAME));
+++++++ ++ ++ printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
+++++++ ++ ++ dmi_get_slot(DMI_PRODUCT_VERSION));
+++++++ ++ ++ printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
+++++++ ++ ++ dmi_get_slot(DMI_BOARD_NAME));
+++++++ ++ ++ printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
+++++++ ++ ++ dmi_get_slot(DMI_BIOS_VENDOR));
+++++++ ++ ++ printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
+++++++ ++ ++ dmi_get_slot(DMI_BIOS_DATE));
+++++++ ++ ++
+++++++ ++ ++ return 0;
+++++++ ++ ++}
+++++++ ++ ++
+++++++ ++ ++
/******************************************************************************
*
* FUNCTION: acpi_os_validate_interface
if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX))
return AE_OK;
if (!strcmp("Linux", interface)) {
------- -- -- printk(KERN_WARNING PREFIX
------- -- -- "System BIOS is requesting _OSI(Linux)\n");
------- -- -- printk(KERN_WARNING PREFIX
------- -- -- "If \"acpi_osi=Linux\" works better,\n"
------- -- -- "Please send dmidecode "
------- -- -- if(osi_linux)
+++++++ ++ ++
+++++++ ++ ++ printk(KERN_NOTICE PREFIX
+++++++ ++ ++ "BIOS _OSI(Linux) query %s%s\n",
+++++++ ++ ++ osi_linux.enable ? "honored" : "ignored",
+++++++ ++ ++ osi_linux.cmdline ? " via cmdline" :
+++++++ ++ ++ osi_linux.dmi ? " via DMI" : "");
+++++++ ++ ++
+++++++ ++ ++ if (!osi_linux.dmi) {
+++++++ ++ ++ if (acpi_dmi_dump())
+++++++ ++ ++ printk(KERN_NOTICE PREFIX
+++++++ ++ ++ "[please extract dmidecode output]\n");
+++++++ ++ ++ printk(KERN_NOTICE PREFIX
+++++++ ++ ++ "Please send DMI info above to "
+++++++ ++ ++ }
+++++++ ++ ++ if (!osi_linux.known && !osi_linux.cmdline) {
+++++++ ++ ++ printk(KERN_NOTICE PREFIX
+++++++ ++ ++ "If \"acpi_osi=%sLinux\" works better, "
+++++++ ++ ++ osi_linux.enable ? "!" : "");
+++++++ ++ ++ }
+++++++ ++ ++
+++++++ ++ ++ if (osi_linux.enable)
return AE_OK;
}
return AE_SUPPORT;
return AE_OK;
}
------- -- --#ifdef CONFIG_DMI
------- -- --static int dmi_osi_linux(const struct dmi_system_id *d)
------- -- --{
------- -- -- printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident);
------- -- -- enable_osi_linux(1);
------- -- -- return 0;
------- -- --}
------- -- --
------- -- --static struct dmi_system_id acpi_osl_dmi_table[] __initdata = {
------- -- -- /*
------- -- -- * Boxes that need _OSI(Linux)
------- -- -- */
------- -- -- {
------- -- -- .callback = dmi_osi_linux,
------- -- -- .ident = "Intel Napa CRB",
------- -- -- .matches = {
------- -- -- DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
------- -- -- DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"),
------- -- -- },
------- -- -- },
------- -- -- {}
------- -- --};
------- -- --#endif /* CONFIG_DMI */
------- -- --
#endif
* Try to find delimeter, only to insert null. The end of the
* string won't have one, but is still valid.
*/
++++++++++++ + if (*p == NULL)
++++++++++++ + return result;
++++++++++++ +
next = strpbrk(*p, "- :");
if (next)
*next++ = '\0';
if (next)
*p = next;
++++++++++++ + else
++++++++++++ + *p = NULL;
return result;
}
if ((result = get_date_field(&p, &sec)))
goto end;
------------- if (sec > 59) {
------------- min += 1;
------------- sec -= 60;
------------- }
------------- if (min > 59) {
------------- hr += 1;
------------- min -= 60;
------------- }
------------- if (hr > 23) {
------------- day += 1;
------------- hr -= 24;
------------- }
------------- if (day > 31) {
------------- mo += 1;
------------- day -= 31;
------------- }
------------- if (mo > 12) {
------------- yr += 1;
------------- mo -= 12;
------------- }
-------------
spin_lock_irq(&rtc_lock);
rtc_control = CMOS_READ(RTC_CONTROL);
spin_unlock_irq(&rtc_lock);
if (sec > 59) {
------------- min++;
------------- sec -= 60;
+++++++++++++ min += sec/60;
+++++++++++++ sec = sec%60;
}
if (min > 59) {
------------- hr++;
------------- min -= 60;
+++++++++++++ hr += min/60;
+++++++++++++ min = min%60;
}
if (hr > 23) {
------------- day++;
------------- hr -= 24;
+++++++++++++ day += hr/24;
+++++++++++++ hr = hr%24;
}
if (day > 31) {
------------- mo++;
------------- day -= 31;
+++++++++++++ mo += day/32;
+++++++++++++ day = day%32;
}
if (mo > 12) {
------------- yr++;
------------- mo -= 12;
+++++++++++++ yr += mo/13;
+++++++++++++ mo = mo%13;
}
spin_lock_irq(&rtc_lock);
#include <linux/init.h>
#include <linux/types.h>
#include <linux/list.h>
++ + + #include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/input.h>
u8 attached_count;
struct acpi_video_bus_cap cap;
struct acpi_video_bus_flags flags;
-- - - struct semaphore sem;
struct list_head video_device_list;
++ + + struct mutex device_list_lock; /* protects video_device_list */
struct proc_dir_entry *dir;
struct input_dev *input;
char phys[32]; /* for input device */
static int acpi_video_get_brightness(struct backlight_device *bd)
{
unsigned long cur_level;
++++++++ +++++ int i;
struct acpi_video_device *vd =
(struct acpi_video_device *)bl_get_data(bd);
acpi_video_device_lcd_get_level_current(vd, &cur_level);
-------- ----- return (int) cur_level;
++++++++ +++++ for (i = 2; i < vd->brightness->count; i++) {
++++++++ +++++ if (vd->brightness->levels[i] == cur_level)
++++++++ +++++ /* The first two entries are special - see page 575
++++++++ +++++ of the ACPI spec 3.0 */
++++++++ +++++ return i-2;
++++++++ +++++ }
++++++++ +++++ return 0;
}
static int acpi_video_set_brightness(struct backlight_device *bd)
{
-------- ----- int request_level = bd->props.brightness;
++++++++ +++++ int request_level = bd->props.brightness+2;
struct acpi_video_device *vd =
(struct acpi_video_device *)bl_get_data(bd);
-------- ----- acpi_video_device_lcd_set_level(vd, request_level);
++++++++ +++++ acpi_video_device_lcd_set_level(vd,
++++++++ +++++ vd->brightness->levels[request_level]);
return 0;
}
struct acpi_video_device_brightness *br = NULL;
-- - - - memset(&device->cap, 0, 4);
++ + + + memset(&device->cap, 0, sizeof(device->cap));
if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) {
device->cap._ADR = 1;
kfree(obj);
if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
-------- ----- unsigned long tmp;
static int count = 0;
char *name;
name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
return;
sprintf(name, "acpi_video%d", count++);
-------- ----- acpi_video_device_lcd_get_level_current(device, &tmp);
device->backlight = backlight_device_register(name,
NULL, device, &acpi_backlight_ops);
-------- ----- device->backlight->props.max_brightness = max_level;
-------- ----- device->backlight->props.brightness = (int)tmp;
++++++++ +++++ device->backlight->props.max_brightness = device->brightness->count-3;
++++++++ +++++ device->backlight->props.brightness = acpi_video_get_brightness(device->backlight);
backlight_update_status(device->backlight);
kfree(name);
{
acpi_handle h_dummy1;
-- - - - memset(&video->cap, 0, 4);
++ + + + memset(&video->cap, 0, sizeof(video->cap));
if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) {
video->cap._DOS = 1;
}
{
struct seq_file *m = file->private_data;
struct acpi_video_device *dev = m->private;
-- - - char str[4] = { 0 };
++ + + char str[5] = { 0 };
unsigned int level = 0;
int i;
static int acpi_video_bus_add_fs(struct acpi_device *device)
{
+++++++++++ ++ long device_id;
+++++++++++ ++ int status;
struct proc_dir_entry *entry = NULL;
struct acpi_video_bus *video;
+++++++++++ ++ struct device *dev;
+++++++++++ ++
+++++++++++ ++ status =
+++++++++++ ++ acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
+++++++++++ ++
+++++++++++ ++ if (!ACPI_SUCCESS(status))
+++++++++++ ++ return -ENODEV;
+++++++++++ ++
+++++++++++ ++ /* We need to attempt to determine whether the _ADR refers to a
+++++++++++ ++ PCI device or not. There's no terribly good way to do this,
+++++++++++ ++ so the best we can hope for is to assume that there'll never
+++++++++++ ++ be a video device in the host bridge */
+++++++++++ ++ if (device_id >= 0x10000) {
+++++++++++ ++ /* It looks like a PCI device. Does it exist? */
+++++++++++ ++ dev = acpi_get_physical_device(device->handle);
+++++++++++ ++ } else {
+++++++++++ ++ /* It doesn't look like a PCI device. Does its parent
+++++++++++ ++ exist? */
+++++++++++ ++ acpi_handle phandle;
+++++++++++ ++ if (acpi_get_parent(device->handle, &phandle))
+++++++++++ ++ return -ENODEV;
+++++++++++ ++ dev = acpi_get_physical_device(phandle);
+++++++++++ ++ }
+++++++++++ ++ if (!dev)
+++++++++++ ++ return -ENODEV;
+++++++++++ ++ put_device(dev);
+++++++++++ ++
video = acpi_driver_data(device);
return -ENODEV;
}
-- - - down(&video->sem);
++ + + mutex_lock(&video->device_list_lock);
list_add_tail(&data->entry, &video->video_device_list);
-- - - up(&video->sem);
++ + + mutex_unlock(&video->device_list_lock);
acpi_video_device_add_fs(device);
static void acpi_video_device_rebind(struct acpi_video_bus *video)
{
-- - - struct list_head *node, *next;
-- - - list_for_each_safe(node, next, &video->video_device_list) {
-- - - struct acpi_video_device *dev =
-- - - container_of(node, struct acpi_video_device, entry);
++ + + struct acpi_video_device *dev;
++ + +
++ + + mutex_lock(&video->device_list_lock);
++ + +
++ + + list_for_each_entry(dev, &video->video_device_list, entry)
acpi_video_device_bind(video, dev);
-- - - }
++ + +
++ + + mutex_unlock(&video->device_list_lock);
}
/*
static int acpi_video_switch_output(struct acpi_video_bus *video, int event)
{
-- - - struct list_head *node, *next;
++ + + struct list_head *node;
struct acpi_video_device *dev = NULL;
struct acpi_video_device *dev_next = NULL;
struct acpi_video_device *dev_prev = NULL;
unsigned long state;
int status = 0;
++ + + mutex_lock(&video->device_list_lock);
-- - - list_for_each_safe(node, next, &video->video_device_list) {
++ + + list_for_each(node, &video->video_device_list) {
dev = container_of(node, struct acpi_video_device, entry);
status = acpi_video_device_get_state(dev, &state);
if (state & 0x2) {
-- - - dev_next =
-- - - container_of(node->next, struct acpi_video_device,
-- - - entry);
-- - - dev_prev =
-- - - container_of(node->prev, struct acpi_video_device,
-- - - entry);
++ + + dev_next = container_of(node->next,
++ + + struct acpi_video_device, entry);
++ + + dev_prev = container_of(node->prev,
++ + + struct acpi_video_device, entry);
goto out;
}
}
++ + +
dev_next = container_of(node->next, struct acpi_video_device, entry);
dev_prev = container_of(node->prev, struct acpi_video_device, entry);
-- - - out:
++ + +
++ + + out:
++ + + mutex_unlock(&video->device_list_lock);
++ + +
switch (event) {
case ACPI_VIDEO_NOTIFY_CYCLE:
case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
struct acpi_device *device)
{
int status = 0;
-- - - struct list_head *node, *next;
-- - -
++ + + struct acpi_device *dev;
acpi_video_device_enumerate(video);
-- - - list_for_each_safe(node, next, &device->children) {
-- - - struct acpi_device *dev =
-- - - list_entry(node, struct acpi_device, node);
-- - -
-- - - if (!dev)
-- - - continue;
++ + + list_for_each_entry(dev, &device->children, node) {
status = acpi_video_bus_get_one_device(dev, video);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Cant attach device"));
continue;
}
-- - -
}
return status;
}
video = device->video;
-- - - down(&video->sem);
-- - - list_del(&device->entry);
-- - - up(&video->sem);
acpi_video_device_remove_fs(device->dev);
status = acpi_remove_notify_handler(device->dev->handle,
acpi_video_device_notify);
backlight_device_unregister(device->backlight);
video_output_unregister(device->output_dev);
++ + +
return 0;
}
static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
{
int status;
-- - - struct list_head *node, *next;
++ + + struct acpi_video_device *dev, *next;
++ + + mutex_lock(&video->device_list_lock);
-- - - list_for_each_safe(node, next, &video->video_device_list) {
-- - - struct acpi_video_device *data =
-- - - list_entry(node, struct acpi_video_device, entry);
-- - - if (!data)
-- - - continue;
++ + + list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
-- - - status = acpi_video_bus_put_one_device(data);
++ + + status = acpi_video_bus_put_one_device(dev);
if (ACPI_FAILURE(status))
printk(KERN_WARNING PREFIX
"hhuuhhuu bug in acpi video driver.\n");
-- - - if (data->brightness)
-- - - kfree(data->brightness->levels);
-- - - kfree(data->brightness);
-- - - kfree(data);
++ + + if (dev->brightness) {
++ + + kfree(dev->brightness->levels);
++ + + kfree(dev->brightness);
++ + + }
++ + + list_del(&dev->entry);
++ + + kfree(dev);
}
++ + + mutex_unlock(&video->device_list_lock);
++ + +
return 0;
}
struct input_dev *input;
int keycode;
-- - -
-- - - printk("video bus notify\n");
-- - -
if (!video)
return;
static int instance;
static int acpi_video_bus_add(struct acpi_device *device)
{
-- - - int result = 0;
-- - - acpi_status status = 0;
-- - - struct acpi_video_bus *video = NULL;
++ + + acpi_status status;
++ + + struct acpi_video_bus *video;
struct input_dev *input;
-- - -
-- - -
-- - - if (!device)
-- - - return -EINVAL;
++ + + int error;
video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
if (!video)
acpi_driver_data(device) = video;
acpi_video_bus_find_cap(video);
-- - - result = acpi_video_bus_check(video);
-- - - if (result)
-- - - goto end;
++ + + error = acpi_video_bus_check(video);
++ + + if (error)
++ + + goto err_free_video;
-- - - result = acpi_video_bus_add_fs(device);
-- - - if (result)
-- - - goto end;
++ + + error = acpi_video_bus_add_fs(device);
++ + + if (error)
++ + + goto err_free_video;
-- - - init_MUTEX(&video->sem);
++ + + mutex_init(&video->device_list_lock);
INIT_LIST_HEAD(&video->video_device_list);
acpi_video_bus_get_devices(video, device);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error installing notify handler\n"));
-- - - acpi_video_bus_stop_devices(video);
-- - - acpi_video_bus_put_devices(video);
-- - - kfree(video->attached_array);
-- - - acpi_video_bus_remove_fs(device);
-- - - result = -ENODEV;
-- - - goto end;
++ + + error = -ENODEV;
++ + + goto err_stop_video;
}
-- - -
video->input = input = input_allocate_device();
++ + + if (!input) {
++ + + error = -ENOMEM;
++ + + goto err_uninstall_notify;
++ + + }
snprintf(video->phys, sizeof(video->phys),
"%s/video/input0", acpi_device_hid(video->device));
input->phys = video->phys;
input->id.bustype = BUS_HOST;
input->id.product = 0x06;
++ + + input->dev.parent = &device->dev;
input->evbit[0] = BIT(EV_KEY);
set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
set_bit(KEY_VIDEO_NEXT, input->keybit);
set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
set_bit(KEY_DISPLAY_OFF, input->keybit);
set_bit(KEY_UNKNOWN, input->keybit);
-- - - result = input_register_device(input);
-- - - if (result) {
-- - - acpi_remove_notify_handler(video->device->handle,
-- - - ACPI_DEVICE_NOTIFY,
-- - - acpi_video_bus_notify);
-- - - acpi_video_bus_stop_devices(video);
-- - - acpi_video_bus_put_devices(video);
-- - - kfree(video->attached_array);
-- - - acpi_video_bus_remove_fs(device);
-- - - goto end;
-- - - }
++ + + error = input_register_device(input);
++ + + if (error)
++ + + goto err_free_input_dev;
printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
video->flags.rom ? "yes" : "no",
video->flags.post ? "yes" : "no");
-- - - end:
-- - - if (result)
-- - - kfree(video);
++ + + return 0;
++ + +
++ + + err_free_input_dev:
++ + + input_free_device(input);
++ + + err_uninstall_notify:
++ + + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
++ + + acpi_video_bus_notify);
++ + + err_stop_video:
++ + + acpi_video_bus_stop_devices(video);
++ + + acpi_video_bus_put_devices(video);
++ + + kfree(video->attached_array);
++ + + acpi_video_bus_remove_fs(device);
++ + + err_free_video:
++ + + kfree(video);
++ + + acpi_driver_data(device) = NULL;
-- - - return result;
++ + + return error;
}
static int acpi_video_bus_remove(struct acpi_device *device, int type)
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_numa.h>
#include <asm/acpi.h>
+++++++ ++ ++#include <linux/dmi.h>
#ifdef CONFIG_ACPI
typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
---------- ---unsigned long acpi_find_rsdp (void);
int acpi_boot_init (void);
int acpi_boot_table_init (void);
int acpi_numa_init (void);
int acpi_register_gsi (u32 gsi, int triggering, int polarity);
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
++ + + #ifdef CONFIG_X86_IO_APIC
++ + + extern int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity);
++ + + #else
++ + + #define acpi_get_override_irq(bus, trigger, polarity) (-1)
++ + + #endif
/*
* This function undoes the effect of one call to acpi_register_gsi().
* If this matches the last registration, any IRQ resources for gsi
#endif /*CONFIG_ACPI_EC*/
extern int acpi_blacklisted(void);
------- -- --extern void acpi_bios_year(char *s);
+++++++ ++ ++#ifdef CONFIG_DMI
+++++++ ++ ++extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);
+++++++ ++ ++#endif
#ifdef CONFIG_ACPI_NUMA
int acpi_get_pxm(acpi_handle handle);
return 0;
}
------- -- --#endif /* CONFIG_ACPI */
+++++++ ++ ++#endif /* !CONFIG_ACPI */
#endif /*_LINUX_ACPI_H*/