Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6e7c402590b75b6b45138792445ee0f0315a8473
Commit:     6e7c402590b75b6b45138792445ee0f0315a8473
Parent:     b02aae9cf52956dfe1bec73f77f81a3d05d3902b
Author:     Ingo Molnar <[EMAIL PROTECTED]>
AuthorDate: Wed Jan 30 13:30:05 2008 +0100
Committer:  Ingo Molnar <[EMAIL PROTECTED]>
CommitDate: Wed Jan 30 13:30:05 2008 +0100

    x86: various changes and cleanups to in_p/out_p delay details
    
    various changes to the in_p/out_p delay details:
    
    - add the io_delay=none method
    - make each method selectable from the kernel config
    - simplify the delay code a bit by getting rid of an indirect function call
    - add the /proc/sys/kernel/io_delay_type sysctl
    - change 'io_delay=standard|alternate' to io_delay=0x80 and io_delay=0xed
    - make the io delay config not depend on CONFIG_DEBUG_KERNEL
    
    Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>
    Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
    Tested-by: "David P. Reed" <[EMAIL PROTECTED]>
---
 Documentation/kernel-parameters.txt |   12 ++-
 arch/x86/Kconfig.debug              |   79 ++++++++++++--
 arch/x86/kernel/io_delay.c          |  204 +++++++++++++++++------------------
 include/asm-x86/io_32.h             |   10 +--
 include/asm-x86/io_64.h             |   10 +--
 kernel/sysctl.c                     |    9 ++
 6 files changed, 192 insertions(+), 132 deletions(-)

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
index 9e60560..b427b7c 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -795,12 +795,14 @@ and is between 256 and 4096 characters. It is defined in 
the file
                        then look in the higher range.
 
        io_delay=       [X86-32,X86-64] I/O delay method
-               standard
-                       Standard port 0x80 delay
-               alternate
-                       Alternate port 0xed delay
+               0x80
+                       Standard port 0x80 based delay
+               0xed
+                       Alternate port 0xed based delay (needed on some systems)
                udelay
-                       Simple two microsecond delay
+                       Simple two microseconds delay
+               none
+                       No delay
 
        io7=            [HW] IO7 for Marvel based alpha systems
                        See comment before marvel_specify_io7 in
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 40aba67..77eda46 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -112,13 +112,78 @@ config IOMMU_LEAK
          Add a simple leak tracer to the IOMMU code. This is useful when you
          are debugging a buggy device driver that leaks IOMMU mappings.
 
-config UDELAY_IO_DELAY
-       bool "Delay I/O through udelay instead of outb"
-       depends on DEBUG_KERNEL
+#
+# IO delay types:
+#
+
+config IO_DELAY_TYPE_0X80
+       int
+       default "0"
+
+config IO_DELAY_TYPE_0XED
+       int
+       default "1"
+
+config IO_DELAY_TYPE_UDELAY
+       int
+       default "2"
+
+config IO_DELAY_TYPE_NONE
+       int
+       default "3"
+
+choice
+       prompt "IO delay type"
+       default IO_DELAY_0X80
+
+config IO_DELAY_0X80
+       bool "port 0x80 based port-IO delay [recommended]"
+       help
+         This is the traditional Linux IO delay used for in/out_p.
+         It is the most tested hence safest selection here.
+
+config IO_DELAY_0XED
+       bool "port 0xed based port-IO delay"
+       help
+         Use port 0xed as the IO delay. This frees up port 0x80 which is
+         often used as a hardware-debug port.
+
+config IO_DELAY_UDELAY
+       bool "udelay based port-IO delay"
+       help
+         Use udelay(2) as the IO delay method. This provides the delay
+         while not having any side-effect on the IO port space.
+
+config IO_DELAY_NONE
+       bool "no port-IO delay"
        help
-         Make inb_p/outb_p use udelay() based delays by default. Please note
-         that udelay() does not have the same bus-level side-effects that
-         the normal outb based delay does meaning this could cause drivers
-         to change behaviour and/or bugs to surface.
+         No port-IO delay. Will break on old boxes that require port-IO
+         delay for certain operations. Should work on most new machines.
+
+endchoice
+
+if IO_DELAY_0X80
+config DEFAULT_IO_DELAY_TYPE
+       int
+       default IO_DELAY_TYPE_0X80
+endif
+
+if IO_DELAY_0XED
+config DEFAULT_IO_DELAY_TYPE
+       int
+       default IO_DELAY_TYPE_0XED
+endif
+
+if IO_DELAY_UDELAY
+config DEFAULT_IO_DELAY_TYPE
+       int
+       default IO_DELAY_TYPE_UDELAY
+endif
+
+if IO_DELAY_NONE
+config DEFAULT_IO_DELAY_TYPE
+       int
+       default IO_DELAY_TYPE_NONE
+endif
 
 endmenu
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
dissimilarity index 64%
index 4d955e7..f052e34 100644
--- a/arch/x86/kernel/io_delay.c
+++ b/arch/x86/kernel/io_delay.c
@@ -1,106 +1,98 @@
-/*
- * I/O delay strategies for inb_p/outb_p
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/dmi.h>
-#include <asm/io.h>
-
-/*
- * Allow for a DMI based override of port 0x80 needed for certain HP laptops
- */
-#define IO_DELAY_PORT_STD 0x80
-#define IO_DELAY_PORT_ALT 0xed
-
-static void standard_io_delay(void)
-{
-       asm volatile ("outb %%al, %0" : : "N" (IO_DELAY_PORT_STD));
-}
-
-static void alternate_io_delay(void)
-{
-       asm volatile ("outb %%al, %0" : : "N" (IO_DELAY_PORT_ALT));
-}
-
-/*
- * 2 usecs is an upper-bound for the outb delay but note that udelay doesn't
- * have the bus-level side-effects that outb does
- */
-#define IO_DELAY_USECS 2
-
-/*
- * High on a hill was a lonely goatherd
- */
-static void udelay_io_delay(void)
-{
-       udelay(IO_DELAY_USECS);
-}
-
-#ifndef CONFIG_UDELAY_IO_DELAY
-static void (*io_delay)(void) = standard_io_delay;
-#else
-static void (*io_delay)(void) = udelay_io_delay;
-#endif
-
-/*
- * Paravirt wants native_io_delay to be a constant.
- */
-void native_io_delay(void)
-{
-       io_delay();
-}
-EXPORT_SYMBOL(native_io_delay);
-
-#ifndef CONFIG_UDELAY_IO_DELAY
-static int __init dmi_alternate_io_delay_port(const struct dmi_system_id *id)
-{
-       printk(KERN_NOTICE "%s: using alternate I/O delay port\n", id->ident);
-       io_delay = alternate_io_delay;
-       return 0;
-}
-
-static struct dmi_system_id __initdata alternate_io_delay_port_dmi_table[] = {
-       {
-               .callback       = dmi_alternate_io_delay_port,
-               .ident          = "HP Pavilion dv9000z",
-               .matches        = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
-                       DMI_MATCH(DMI_BOARD_NAME, "30B9")
-               }
-       },
-       {
-       }
-};
-
-static int __initdata io_delay_override;
-
-void __init io_delay_init(void)
-{
-       if (!io_delay_override)
-               dmi_check_system(alternate_io_delay_port_dmi_table);
-}
-#endif
-
-static int __init io_delay_param(char *s)
-{
-       if (!s)
-               return -EINVAL;
-
-       if (!strcmp(s, "standard"))
-               io_delay = standard_io_delay;
-       else if (!strcmp(s, "alternate"))
-               io_delay = alternate_io_delay;
-       else if (!strcmp(s, "udelay"))
-               io_delay = udelay_io_delay;
-       else
-               return -EINVAL;
-
-#ifndef CONFIG_UDELAY_IO_DELAY
-       io_delay_override = 1;
-#endif
-       return 0;
-}
-
-early_param("io_delay", io_delay_param);
+/*
+ * I/O delay strategies for inb_p/outb_p
+ *
+ * Allow for a DMI based override of port 0x80, needed for certain HP laptops
+ * and possibly other systems. Also allow for the gradual elimination of
+ * outb_p/inb_p API uses.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+
+int io_delay_type __read_mostly = CONFIG_DEFAULT_IO_DELAY_TYPE;
+EXPORT_SYMBOL_GPL(io_delay_type);
+
+static int __initdata io_delay_override;
+
+/*
+ * Paravirt wants native_io_delay to be a constant.
+ */
+void native_io_delay(void)
+{
+       switch (io_delay_type) {
+       default:
+       case CONFIG_IO_DELAY_TYPE_0X80:
+               asm volatile ("outb %al, $0x80");
+               break;
+       case CONFIG_IO_DELAY_TYPE_0XED:
+               asm volatile ("outb %al, $0xed");
+               break;
+       case CONFIG_IO_DELAY_TYPE_UDELAY:
+               /*
+                * 2 usecs is an upper-bound for the outb delay but
+                * note that udelay doesn't have the bus-level
+                * side-effects that outb does, nor does udelay() have
+                * precise timings during very early bootup (the delays
+                * are shorter until calibrated):
+                */
+               udelay(2);
+       case CONFIG_IO_DELAY_TYPE_NONE:
+               break;
+       }
+}
+EXPORT_SYMBOL(native_io_delay);
+
+static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id)
+{
+       if (io_delay_type == CONFIG_IO_DELAY_TYPE_0X80) {
+               printk(KERN_NOTICE "%s: using 0xed I/O delay port\n",
+                       id->ident);
+               io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
+       }
+
+       return 0;
+}
+
+/*
+ * Quirk table for systems that misbehave (lock up, etc.) if port
+ * 0x80 is used:
+ */
+static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = {
+       {
+               .callback       = dmi_io_delay_0xed_port,
+               .ident          = "HP Pavilion dv9000z",
+               .matches        = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
+                       DMI_MATCH(DMI_BOARD_NAME, "30B9")
+               }
+       },
+       { }
+};
+
+void __init io_delay_init(void)
+{
+       if (!io_delay_override)
+               dmi_check_system(io_delay_0xed_port_dmi_table);
+}
+
+static int __init io_delay_param(char *s)
+{
+       if (!strcmp(s, "0x80"))
+               io_delay_type = CONFIG_IO_DELAY_TYPE_0X80;
+       else if (!strcmp(s, "0xed"))
+               io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
+       else if (!strcmp(s, "udelay"))
+               io_delay_type = CONFIG_IO_DELAY_TYPE_UDELAY;
+       else if (!strcmp(s, "none"))
+               io_delay_type = CONFIG_IO_DELAY_TYPE_NONE;
+       else
+               return -EINVAL;
+
+       io_delay_override = 1;
+       return 0;
+}
+
+early_param("io_delay", io_delay_param);
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index a8d25c3..2a04bd1 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -250,15 +250,11 @@ static inline void flush_write_buffers(void)
 
 #endif /* __KERNEL__ */
 
-#ifndef CONFIG_UDELAY_IO_DELAY
-extern void io_delay_init(void);
-#else
-static inline void io_delay_init(void)
-{
-}
-#endif
 extern void native_io_delay(void);
 
+extern int io_delay_type;
+extern void io_delay_init(void);
+
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
 #else
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index 5bebaf9..dbcc03a 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -35,15 +35,11 @@
   *  - Arnaldo Carvalho de Melo <[EMAIL PROTECTED]>
   */
 
-#ifndef CONFIG_UDELAY_IO_DELAY
-extern void io_delay_init(void);
-#else
-static inline void io_delay_init(void)
-{
-}
-#endif
 extern void native_io_delay(void);
 
+extern int io_delay_type;
+extern void io_delay_init(void);
+
 static inline void slow_down_io(void)
 {
        native_io_delay();
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 4bc8e48..357b68b 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -53,6 +53,7 @@
 #ifdef CONFIG_X86
 #include <asm/nmi.h>
 #include <asm/stacktrace.h>
+#include <asm/io.h>
 #endif
 
 static int deprecated_sysctl_warning(struct __sysctl_args *args);
@@ -727,6 +728,14 @@ static struct ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "io_delay_type",
+               .data           = &io_delay_type,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
 #endif
 #if defined(CONFIG_MMU)
        {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to