cregit-Linux how code gets into the kernel

Release 4.14 drivers/acpi/osi.c

Directory: drivers/acpi
/*
 *  osi.c - _OSI implementation
 *
 *  Copyright (C) 2016 Intel Corporation
 *    Author: Lv Zheng <lv.zheng@intel.com>
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *  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.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

/* Uncomment next line to get verbose printout */
/* #define DEBUG */

#define pr_fmt(fmt) "ACPI: " fmt

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/platform_data/x86/apple.h>

#include "internal.h"



#define OSI_STRING_LENGTH_MAX	64

#define OSI_STRING_ENTRIES_MAX	16


struct acpi_osi_entry {
	
char string[OSI_STRING_LENGTH_MAX];
	
bool enable;
};


static struct acpi_osi_config {
	
u8		default_disabling;
	
unsigned int	linux_enable:1;
	
unsigned int	linux_dmi:1;
	
unsigned int	linux_cmdline:1;
	
unsigned int	darwin_enable:1;
	
unsigned int	darwin_dmi:1;
	
unsigned int	darwin_cmdline:1;

} osi_config;


static struct acpi_osi_config osi_config;
static struct acpi_osi_entry

osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
	{"Module Device", true},
	{"Processor Device", true},
	{"3.0 _SCP Extensions", true},
	{"Processor Aggregator Device", true},
};


static u32 acpi_osi_handler(acpi_string interface, u32 supported) { if (!strcmp("Linux", interface)) { pr_notice_once(FW_BUG "BIOS _OSI(Linux) query %s%s\n", osi_config.linux_enable ? "honored" : "ignored", osi_config.linux_cmdline ? " via cmdline" : osi_config.linux_dmi ? " via DMI" : ""); } if (!strcmp("Darwin", interface)) { pr_notice_once( "BIOS _OSI(Darwin) query %s%s\n", osi_config.darwin_enable ? "honored" : "ignored", osi_config.darwin_cmdline ? " via cmdline" : osi_config.darwin_dmi ? " via DMI" : ""); } return supported; }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng94100.00%1100.00%
Total94100.00%1100.00%


void __init acpi_osi_setup(char *str) { struct acpi_osi_entry *osi; bool enable = true; int i; if (!acpi_gbl_create_osi_method) return; if (str == NULL || *str == '\0') { pr_info("_OSI method disabled\n"); acpi_gbl_create_osi_method = FALSE; return; } if (*str == '!') { str++; if (*str == '\0') { /* Do not override acpi_osi=!* */ if (!osi_config.default_disabling) osi_config.default_disabling = ACPI_DISABLE_ALL_VENDOR_STRINGS; return; } else if (*str == '*') { osi_config.default_disabling = ACPI_DISABLE_ALL_STRINGS; for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { osi = &osi_setup_entries[i]; osi->enable = false; } return; } else if (*str == '!') { osi_config.default_disabling = 0; return; } enable = false; } for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { osi = &osi_setup_entries[i]; if (!strcmp(osi->string, str)) { osi->enable = enable; break; } else if (osi->string[0] == '\0') { osi->enable = enable; strncpy(osi->string, str, OSI_STRING_LENGTH_MAX); break; } } }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng231100.00%1100.00%
Total231100.00%1100.00%


static void __init __acpi_osi_setup_darwin(bool enable) { osi_config.darwin_enable = !!enable; if (enable) { acpi_osi_setup("!"); acpi_osi_setup("Darwin"); } else { acpi_osi_setup("!!"); acpi_osi_setup("!Darwin"); } }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng47100.00%1100.00%
Total47100.00%1100.00%


static void __init acpi_osi_setup_darwin(bool enable) { /* Override acpi_osi_dmi_blacklisted() */ osi_config.darwin_dmi = 0; osi_config.darwin_cmdline = 1; __acpi_osi_setup_darwin(enable); }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng28100.00%1100.00%
Total28100.00%1100.00%

/* * The story of _OSI(Linux) * * From pre-history through Linux-2.6.22, Linux responded TRUE upon a BIOS * OSI(Linux) query. * * Unfortunately, reference BIOS writers got wind of this and put * OSI(Linux) in their example code, quickly exposing this string as * ill-conceived and opening the door to an un-bounded number of BIOS * incompatibilities. * * For example, OSI(Linux) was used on resume to re-POST a video card on * one system, because Linux at that time could not do a speedy restore in * its native driver. But then upon gaining quick native restore * capability, Linux has no way to tell the BIOS to skip the time-consuming * POST -- putting Linux at a permanent performance disadvantage. On * another system, the BIOS writer used OSI(Linux) to infer native OS * support for IPMI! On other systems, OSI(Linux) simply got in the way of * Linux claiming to be compatible with other operating systems, exposing * BIOS issues such as skipped device initialization. * * So "Linux" turned out to be a really poor chose of OSI string, and from * Linux-2.6.23 onward we respond FALSE. * * BIOS writers should NOT query _OSI(Linux) on future systems. Linux will * complain on the console when it sees it, and return FALSE. To get Linux * to return TRUE for your system will require a kernel source update to * add a DMI entry, or boot with "acpi_osi=Linux" */
static void __init __acpi_osi_setup_linux(bool enable) { osi_config.linux_enable = !!enable; if (enable) acpi_osi_setup("Linux"); else acpi_osi_setup("!Linux"); }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng33100.00%1100.00%
Total33100.00%1100.00%


static void __init acpi_osi_setup_linux(bool enable) { /* Override acpi_osi_dmi_blacklisted() */ osi_config.linux_dmi = 0; osi_config.linux_cmdline = 1; __acpi_osi_setup_linux(enable); }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng28100.00%1100.00%
Total28100.00%1100.00%

/* * Modify the list of "OS Interfaces" reported to BIOS via _OSI * * empty string disables _OSI * string starting with '!' disables that string * otherwise string is added to list, augmenting built-in strings */
static void __init acpi_osi_setup_late(void) { struct acpi_osi_entry *osi; char *str; int i; acpi_status status; if (osi_config.default_disabling) { status = acpi_update_interfaces(osi_config.default_disabling); if (ACPI_SUCCESS(status)) pr_info("Disabled all _OSI OS vendors%s\n", osi_config.default_disabling == ACPI_DISABLE_ALL_STRINGS ? " and feature groups" : ""); } for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { osi = &osi_setup_entries[i]; str = osi->string; if (*str == '\0') break; if (osi->enable) { status = acpi_install_interface(str); if (ACPI_SUCCESS(status)) pr_info("Added _OSI(%s)\n", str); } else { status = acpi_remove_interface(str); if (ACPI_SUCCESS(status)) pr_info("Deleted _OSI(%s)\n", str); } } }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng153100.00%1100.00%
Total153100.00%1100.00%


static int __init osi_setup(char *str) { if (str && !strcmp("Linux", str)) acpi_osi_setup_linux(true); else if (str && !strcmp("!Linux", str)) acpi_osi_setup_linux(false); else if (str && !strcmp("Darwin", str)) acpi_osi_setup_darwin(true); else if (str && !strcmp("!Darwin", str)) acpi_osi_setup_darwin(false); else acpi_osi_setup(str); return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng91100.00%1100.00%
Total91100.00%1100.00%

__setup("acpi_osi=", osi_setup);
bool acpi_osi_is_win8(void) { return acpi_gbl_osi_data >= ACPI_OSI_WIN_8; }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng12100.00%1100.00%
Total12100.00%1100.00%

EXPORT_SYMBOL(acpi_osi_is_win8);
static void __init acpi_osi_dmi_darwin(void) { pr_notice("DMI detected to setup _OSI(\"Darwin\"): Apple hardware\n"); osi_config.darwin_dmi = 1; __acpi_osi_setup_darwin(true); }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng2288.00%150.00%
Lukas Wunner312.00%150.00%
Total25100.00%2100.00%


static void __init acpi_osi_dmi_linux(bool enable, const struct dmi_system_id *d) { pr_notice("DMI detected to setup _OSI(\"Linux\"): %s\n", d->ident); osi_config.linux_dmi = 1; __acpi_osi_setup_linux(enable); }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng3597.22%150.00%
Colin Ian King12.78%150.00%
Total36100.00%2100.00%


static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) { acpi_osi_dmi_linux(true, d); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng23100.00%1100.00%
Total23100.00%1100.00%


static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) { pr_notice("DMI detected: %s\n", d->ident); acpi_osi_setup("!Windows 2006"); acpi_osi_setup("!Windows 2006 SP1"); acpi_osi_setup("!Windows 2006 SP2"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng40100.00%1100.00%
Total40100.00%1100.00%


static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) { pr_notice("DMI detected: %s\n", d->ident); acpi_osi_setup("!Windows 2009"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng30100.00%1100.00%
Total30100.00%1100.00%


static int __init dmi_disable_osi_win8(const struct dmi_system_id *d) { pr_notice("DMI detected: %s\n", d->ident); acpi_osi_setup("!Windows 2012"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng30100.00%1100.00%
Total30100.00%1100.00%

/* * Linux default _OSI response behavior is determined by this DMI table. * * Note that _OSI("Linux")/_OSI("Darwin") determined here can be overridden * by acpi_osi=!Linux/acpi_osi=!Darwin command line options. */ static const struct dmi_system_id acpi_osi_dmi_table[] __initconst = { { .callback = dmi_disable_osi_vista, .ident = "Fujitsu Siemens", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), }, }, { /* * There have a NVIF method in MSI GX723 DSDT need call by Nvidia * driver (e.g. nouveau) when user press brightness hotkey. * Currently, nouveau driver didn't do the job and it causes there * have a infinite while loop in DSDT when user press hotkey. * We add MSI GX723's dmi information to this table for workaround * this issue. * Will remove MSI GX723 from the table after nouveau grows support. */ .callback = dmi_disable_osi_vista, .ident = "MSI GX723", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), DMI_MATCH(DMI_PRODUCT_NAME, "GX723"), }, }, { .callback = dmi_disable_osi_vista, .ident = "Sony VGN-NS10J_S", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"), }, }, { .callback = dmi_disable_osi_vista, .ident = "Sony VGN-SR290J", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"), }, }, { .callback = dmi_disable_osi_vista, .ident = "VGN-NS50B_L", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"), }, }, { .callback = dmi_disable_osi_vista, .ident = "VGN-SR19XN", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"), }, }, { .callback = dmi_disable_osi_vista, .ident = "Toshiba Satellite L355", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"), }, }, { .callback = dmi_disable_osi_win7, .ident = "ASUS K50IJ", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"), }, }, { .callback = dmi_disable_osi_vista, .ident = "Toshiba P305D", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), }, }, { .callback = dmi_disable_osi_vista, .ident = "Toshiba NB100", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), DMI_MATCH(DMI_PRODUCT_NAME, "NB100"), }, }, /* * The wireless hotkey does not work on those machines when * returning true for _OSI("Windows 2012") */ { .callback = dmi_disable_osi_win8, .ident = "Dell Inspiron 7737", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"), }, }, { .callback = dmi_disable_osi_win8, .ident = "Dell Inspiron 7537", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"), }, }, { .callback = dmi_disable_osi_win8, .ident = "Dell Inspiron 5437", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"), }, }, { .callback = dmi_disable_osi_win8, .ident = "Dell Inspiron 3437", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"), }, }, { .callback = dmi_disable_osi_win8, .ident = "Dell Vostro 3446", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"), }, }, { .callback = dmi_disable_osi_win8, .ident = "Dell Vostro 3546", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"), }, }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. * Linux ignores it, except for the machines enumerated below. */ /* * 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"), }, }, {} };
static __init void acpi_osi_dmi_blacklisted(void) { dmi_check_system(acpi_osi_dmi_table); /* Enable _OSI("Darwin") for Apple platforms. */ if (x86_apple_machine) acpi_osi_dmi_darwin(); }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng1463.64%150.00%
Lukas Wunner836.36%150.00%
Total22100.00%2100.00%


int __init early_acpi_osi_init(void) { acpi_osi_dmi_blacklisted(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng14100.00%1100.00%
Total14100.00%1100.00%


int __init acpi_osi_init(void) { acpi_install_interface_handler(acpi_osi_handler); acpi_osi_setup_late(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng19100.00%1100.00%
Total19100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Lv Zheng163398.97%125.00%
Lukas Wunner140.85%125.00%
Christoph Hellwig20.12%125.00%
Colin Ian King10.06%125.00%
Total1650100.00%4100.00%
Directory: drivers/acpi
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.