From: Len Brown <[EMAIL PROTECTED]>

Allow "acpi_osi=Linux" and "acpi_osi=!Linux" cmdline to override DMI.

If DMI for the system known already, don't ask for it again.

If DMI known, but proper default not known, request just test results.

Signed-off-by: Len Brown <[EMAIL PROTECTED]>
---
 drivers/acpi/osl.c |  136 +++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 114 insertions(+), 22 deletions(-)

diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 3c767e7..5204731 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -77,7 +77,37 @@ static struct workqueue_struct *kacpi_notify_wq;
 #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 */
+/*
+ * osi_linux -- Control response to BIOS _OSI(Linux) query.
+ *
+ * The OS Interface string "Linux" is ill-defined,
+ * as it specifies no particuar feature, and the
+ * features of Linux evolve from release to release.
+ *
+ * It was an error when Linux-2.6.22 and earlier
+ * responded "yes" to a BIOS _OSI(Linux) query.
+ * A reference BIOS started using it and opened Pandora's box:
+ *
+ * OSI(Linux) may:
+ * 1. help
+ * 2. hurt
+ * 3. be a NOP
+ * and only DMI can tell which is which...
+ *
+ * Today, there seems to be more exposure for "hurt" and "NOP"
+ * than "help".  So starting with Linux-2.6.23, OSI(Linux)
+ * is disablbed by default.  #define OSI_LINUX_ENABLE 1 to enable it.
+ *
+ * BIOS writers are asked to NOT query _OSI(Linux) going forward.
+ */
+#define OSI_LINUX_ENABLE 0
+
+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};
 
 #ifdef CONFIG_DMI
 static struct __initdata dmi_system_id acpi_osl_dmi_table[];
@@ -964,13 +994,39 @@ static int __init acpi_os_name_setup(char *str)
 
 __setup("acpi_os_name=", acpi_os_name_setup);
 
-static void enable_osi_linux(int enable) {
+static void set_osi_linux(unsigned int enable)
+{
+       if (osi_linux.enable != enable) {
+               osi_linux.enable = enable;
+               printk(KERN_INFO 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 cmdline_osi_linux(unsigned int enable)
+{
+       osi_linux.cmdline = 1;  /* cmdline set the default */
+       set_osi_linux(enable);
+
+       return;
+}
+
+static void dmi_osi_linux(int enable, const struct dmi_system_id *d)
+{
+       osi_linux.dmi = 1;      /* DMI knows that this box asks OSI(Linux) */
+
+       printk(KERN_NOTICE PREFIX "%s detected\n", d->ident);
+
+       if (enable == -1)
+               return;
+
+       osi_linux.known = 1;    /* DMI knows hich OSI(Linux) default needed */
+
+       /* Set default via DMI only if no cmdline override */
+       if (!osi_linux.cmdline)
+               set_osi_linux(enable);
 
-       osi_linux = enable;
        return;
 }
 
@@ -987,12 +1043,12 @@ static int __init acpi_osi_setup(char *str)
                printk(KERN_INFO PREFIX "_OSI method disabled\n");
                acpi_gbl_create_osi_method = FALSE;
        } else if (!strcmp("!Linux", str)) {
-               enable_osi_linux(0);
+               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);
+               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);
@@ -1172,16 +1228,32 @@ acpi_os_validate_interface (char *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");
-               if (dmi_dump_entries(DMI_INTERESTING_ENTRIES))
-                       printk(KERN_WARNING
-                       "[please extract dmidecode output]\n");
-               printk(KERN_WARNING PREFIX
-                       "If \"acpi_osi=Linux\" works better,\n"
-                       "Please send DMI info above to "
-                       "[EMAIL PROTECTED]");
-               if(osi_linux)
+
+               if (!osi_linux.dmi) {
+                       printk(KERN_WARNING PREFIX
+                               "_OSI(Linux) requested "
+                               "by unknown system BIOS\n");
+                       if (dmi_dump_entries(DMI_INTERESTING_ENTRIES))
+                               printk(KERN_WARNING
+                                       "[please extract dmidecode output]\n");
+                       printk(KERN_WARNING PREFIX
+                               "Please send DMI info above to "
+                               "[EMAIL PROTECTED]");
+               } else {
+                       printk(KERN_WARNING PREFIX
+                               "_OSI(Linux) %sabled %s\n",
+                               osi_linux.enable ? "En" : "Dis",
+                               osi_linux.cmdline ? "via cmdline" :
+                                       "for known system BIOS");
+               }
+               if (!osi_linux.known) {
+                       printk(KERN_WARNING PREFIX
+                               "If \"acpi_osi=%sLinux\" works better,"
+                               "please notify [EMAIL PROTECTED]",
+                               osi_linux.enable ? "!" : "");
+               }
+
+               if (osi_linux.enable)
                        return AE_OK;
        }
        return AE_SUPPORT;
@@ -1214,25 +1286,45 @@ acpi_os_validate_address (
 }
 
 #ifdef CONFIG_DMI
-static int dmi_osi_linux(const struct dmi_system_id *d)
+
+static int dmi_enable_osi_linux(const struct dmi_system_id *d)
+{
+       dmi_osi_linux(1, d);    /* enable */
+       return 0;
+}
+#ifdef ACPI_FUTURE_USAGE
+static int dmi_disable_osi_linux(const struct dmi_system_id *d)
 {
-       printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident);
-       enable_osi_linux(1);
+       dmi_osi_linux(0, d);    /* disable */
        return 0;
 }
+static int dmi_unknown_osi_linux(const struct dmi_system_id *d)
+{
+       dmi_osi_linux(-1, d);   /* unknown */
+       return 0;
+}
+#endif
 
 static struct dmi_system_id acpi_osl_dmi_table[] __initdata = {
        /*
         * Boxes that need _OSI(Linux)
         */
        {
-        .callback = dmi_osi_linux,
+        .callback = dmi_enable_osi_linux,
         .ident = "Intel Napa CRB",
         .matches = {
                     DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
                     DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference 
Boards"),
                     },
         },
+
+       /*
+        * Boxes that need _OSI(Linux) NOT set
+        */
+
+       /*
+        * Boxes that request _OSI(Linux), but proper default is unknown
+        */
        {}
 };
 #endif /* CONFIG_DMI */
-- 
1.5.4.rc3.14.g44397

-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to