aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt12
-rw-r--r--arch/x86/Kconfig.debug79
-rw-r--r--arch/x86/kernel/io_delay.c106
-rw-r--r--include/asm-x86/io_32.h10
-rw-r--r--include/asm-x86/io_64.h10
-rw-r--r--kernel/sysctl.c9
6 files changed, 143 insertions, 83 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 9e6056058425..b427b7c0e5d0 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
795 then look in the higher range. 795 then look in the higher range.
796 796
797 io_delay= [X86-32,X86-64] I/O delay method 797 io_delay= [X86-32,X86-64] I/O delay method
798 standard 798 0x80
799 Standard port 0x80 delay 799 Standard port 0x80 based delay
800 alternate 800 0xed
801 Alternate port 0xed delay 801 Alternate port 0xed based delay (needed on some systems)
802 udelay 802 udelay
803 Simple two microsecond delay 803 Simple two microseconds delay
804 none
805 No delay
804 806
805 io7= [HW] IO7 for Marvel based alpha systems 807 io7= [HW] IO7 for Marvel based alpha systems
806 See comment before marvel_specify_io7 in 808 See comment before marvel_specify_io7 in
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 40aba670fb37..77eda46f97b8 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -112,13 +112,78 @@ config IOMMU_LEAK
112 Add a simple leak tracer to the IOMMU code. This is useful when you 112 Add a simple leak tracer to the IOMMU code. This is useful when you
113 are debugging a buggy device driver that leaks IOMMU mappings. 113 are debugging a buggy device driver that leaks IOMMU mappings.
114 114
115config UDELAY_IO_DELAY 115#
116 bool "Delay I/O through udelay instead of outb" 116# IO delay types:
117 depends on DEBUG_KERNEL 117#
118
119config IO_DELAY_TYPE_0X80
120 int
121 default "0"
122
123config IO_DELAY_TYPE_0XED
124 int
125 default "1"
126
127config IO_DELAY_TYPE_UDELAY
128 int
129 default "2"
130
131config IO_DELAY_TYPE_NONE
132 int
133 default "3"
134
135choice
136 prompt "IO delay type"
137 default IO_DELAY_0X80
138
139config IO_DELAY_0X80
140 bool "port 0x80 based port-IO delay [recommended]"
141 help
142 This is the traditional Linux IO delay used for in/out_p.
143 It is the most tested hence safest selection here.
144
145config IO_DELAY_0XED
146 bool "port 0xed based port-IO delay"
147 help
148 Use port 0xed as the IO delay. This frees up port 0x80 which is
149 often used as a hardware-debug port.
150
151config IO_DELAY_UDELAY
152 bool "udelay based port-IO delay"
153 help
154 Use udelay(2) as the IO delay method. This provides the delay
155 while not having any side-effect on the IO port space.
156
157config IO_DELAY_NONE
158 bool "no port-IO delay"
118 help 159 help
119 Make inb_p/outb_p use udelay() based delays by default. Please note 160 No port-IO delay. Will break on old boxes that require port-IO
120 that udelay() does not have the same bus-level side-effects that 161 delay for certain operations. Should work on most new machines.
121 the normal outb based delay does meaning this could cause drivers 162
122 to change behaviour and/or bugs to surface. 163endchoice
164
165if IO_DELAY_0X80
166config DEFAULT_IO_DELAY_TYPE
167 int
168 default IO_DELAY_TYPE_0X80
169endif
170
171if IO_DELAY_0XED
172config DEFAULT_IO_DELAY_TYPE
173 int
174 default IO_DELAY_TYPE_0XED
175endif
176
177if IO_DELAY_UDELAY
178config DEFAULT_IO_DELAY_TYPE
179 int
180 default IO_DELAY_TYPE_UDELAY
181endif
182
183if IO_DELAY_NONE
184config DEFAULT_IO_DELAY_TYPE
185 int
186 default IO_DELAY_TYPE_NONE
187endif
123 188
124endmenu 189endmenu
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
index 4d955e74b974..f052e34dc94c 100644
--- a/arch/x86/kernel/io_delay.c
+++ b/arch/x86/kernel/io_delay.c
@@ -1,5 +1,9 @@
1/* 1/*
2 * I/O delay strategies for inb_p/outb_p 2 * I/O delay strategies for inb_p/outb_p
3 *
4 * Allow for a DMI based override of port 0x80, needed for certain HP laptops
5 * and possibly other systems. Also allow for the gradual elimination of
6 * outb_p/inb_p API uses.
3 */ 7 */
4#include <linux/kernel.h> 8#include <linux/kernel.h>
5#include <linux/module.h> 9#include <linux/module.h>
@@ -8,98 +12,86 @@
8#include <linux/dmi.h> 12#include <linux/dmi.h>
9#include <asm/io.h> 13#include <asm/io.h>
10 14
11/* 15int io_delay_type __read_mostly = CONFIG_DEFAULT_IO_DELAY_TYPE;
12 * Allow for a DMI based override of port 0x80 needed for certain HP laptops 16EXPORT_SYMBOL_GPL(io_delay_type);
13 */
14#define IO_DELAY_PORT_STD 0x80
15#define IO_DELAY_PORT_ALT 0xed
16
17static void standard_io_delay(void)
18{
19 asm volatile ("outb %%al, %0" : : "N" (IO_DELAY_PORT_STD));
20}
21
22static void alternate_io_delay(void)
23{
24 asm volatile ("outb %%al, %0" : : "N" (IO_DELAY_PORT_ALT));
25}
26
27/*
28 * 2 usecs is an upper-bound for the outb delay but note that udelay doesn't
29 * have the bus-level side-effects that outb does
30 */
31#define IO_DELAY_USECS 2
32
33/*
34 * High on a hill was a lonely goatherd
35 */
36static void udelay_io_delay(void)
37{
38 udelay(IO_DELAY_USECS);
39}
40 17
41#ifndef CONFIG_UDELAY_IO_DELAY 18static int __initdata io_delay_override;
42static void (*io_delay)(void) = standard_io_delay;
43#else
44static void (*io_delay)(void) = udelay_io_delay;
45#endif
46 19
47/* 20/*
48 * Paravirt wants native_io_delay to be a constant. 21 * Paravirt wants native_io_delay to be a constant.
49 */ 22 */
50void native_io_delay(void) 23void native_io_delay(void)
51{ 24{
52 io_delay(); 25 switch (io_delay_type) {
26 default:
27 case CONFIG_IO_DELAY_TYPE_0X80:
28 asm volatile ("outb %al, $0x80");
29 break;
30 case CONFIG_IO_DELAY_TYPE_0XED:
31 asm volatile ("outb %al, $0xed");
32 break;
33 case CONFIG_IO_DELAY_TYPE_UDELAY:
34 /*
35 * 2 usecs is an upper-bound for the outb delay but
36 * note that udelay doesn't have the bus-level
37 * side-effects that outb does, nor does udelay() have
38 * precise timings during very early bootup (the delays
39 * are shorter until calibrated):
40 */
41 udelay(2);
42 case CONFIG_IO_DELAY_TYPE_NONE:
43 break;
44 }
53} 45}
54EXPORT_SYMBOL(native_io_delay); 46EXPORT_SYMBOL(native_io_delay);
55 47
56#ifndef CONFIG_UDELAY_IO_DELAY 48static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id)
57static int __init dmi_alternate_io_delay_port(const struct dmi_system_id *id)
58{ 49{
59 printk(KERN_NOTICE "%s: using alternate I/O delay port\n", id->ident); 50 if (io_delay_type == CONFIG_IO_DELAY_TYPE_0X80) {
60 io_delay = alternate_io_delay; 51 printk(KERN_NOTICE "%s: using 0xed I/O delay port\n",
52 id->ident);
53 io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
54 }
55
61 return 0; 56 return 0;
62} 57}
63 58
64static struct dmi_system_id __initdata alternate_io_delay_port_dmi_table[] = { 59/*
60 * Quirk table for systems that misbehave (lock up, etc.) if port
61 * 0x80 is used:
62 */
63static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = {
65 { 64 {
66 .callback = dmi_alternate_io_delay_port, 65 .callback = dmi_io_delay_0xed_port,
67 .ident = "HP Pavilion dv9000z", 66 .ident = "HP Pavilion dv9000z",
68 .matches = { 67 .matches = {
69 DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), 68 DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
70 DMI_MATCH(DMI_BOARD_NAME, "30B9") 69 DMI_MATCH(DMI_BOARD_NAME, "30B9")
71 } 70 }
72 }, 71 },
73 { 72 { }
74 }
75}; 73};
76 74
77static int __initdata io_delay_override;
78
79void __init io_delay_init(void) 75void __init io_delay_init(void)
80{ 76{
81 if (!io_delay_override) 77 if (!io_delay_override)
82 dmi_check_system(alternate_io_delay_port_dmi_table); 78 dmi_check_system(io_delay_0xed_port_dmi_table);
83} 79}
84#endif
85 80
86static int __init io_delay_param(char *s) 81static int __init io_delay_param(char *s)
87{ 82{
88 if (!s) 83 if (!strcmp(s, "0x80"))
89 return -EINVAL; 84 io_delay_type = CONFIG_IO_DELAY_TYPE_0X80;
90 85 else if (!strcmp(s, "0xed"))
91 if (!strcmp(s, "standard")) 86 io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
92 io_delay = standard_io_delay;
93 else if (!strcmp(s, "alternate"))
94 io_delay = alternate_io_delay;
95 else if (!strcmp(s, "udelay")) 87 else if (!strcmp(s, "udelay"))
96 io_delay = udelay_io_delay; 88 io_delay_type = CONFIG_IO_DELAY_TYPE_UDELAY;
89 else if (!strcmp(s, "none"))
90 io_delay_type = CONFIG_IO_DELAY_TYPE_NONE;
97 else 91 else
98 return -EINVAL; 92 return -EINVAL;
99 93
100#ifndef CONFIG_UDELAY_IO_DELAY
101 io_delay_override = 1; 94 io_delay_override = 1;
102#endif
103 return 0; 95 return 0;
104} 96}
105 97
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index a8d25c38b91c..2a04bd17eac5 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)
250 250
251#endif /* __KERNEL__ */ 251#endif /* __KERNEL__ */
252 252
253#ifndef CONFIG_UDELAY_IO_DELAY
254extern void io_delay_init(void);
255#else
256static inline void io_delay_init(void)
257{
258}
259#endif
260extern void native_io_delay(void); 253extern void native_io_delay(void);
261 254
255extern int io_delay_type;
256extern void io_delay_init(void);
257
262#if defined(CONFIG_PARAVIRT) 258#if defined(CONFIG_PARAVIRT)
263#include <asm/paravirt.h> 259#include <asm/paravirt.h>
264#else 260#else
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index 5bebaf961692..dbcc03aa1c6a 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -35,15 +35,11 @@
35 * - Arnaldo Carvalho de Melo <acme@conectiva.com.br> 35 * - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
36 */ 36 */
37 37
38#ifndef CONFIG_UDELAY_IO_DELAY
39extern void io_delay_init(void);
40#else
41static inline void io_delay_init(void)
42{
43}
44#endif
45extern void native_io_delay(void); 38extern void native_io_delay(void);
46 39
40extern int io_delay_type;
41extern void io_delay_init(void);
42
47static inline void slow_down_io(void) 43static inline void slow_down_io(void)
48{ 44{
49 native_io_delay(); 45 native_io_delay();
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 4bc8e48434a7..357b68ba23ec 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -53,6 +53,7 @@
53#ifdef CONFIG_X86 53#ifdef CONFIG_X86
54#include <asm/nmi.h> 54#include <asm/nmi.h>
55#include <asm/stacktrace.h> 55#include <asm/stacktrace.h>
56#include <asm/io.h>
56#endif 57#endif
57 58
58static int deprecated_sysctl_warning(struct __sysctl_args *args); 59static int deprecated_sysctl_warning(struct __sysctl_args *args);
@@ -727,6 +728,14 @@ static struct ctl_table kern_table[] = {
727 .mode = 0644, 728 .mode = 0644,
728 .proc_handler = &proc_dointvec, 729 .proc_handler = &proc_dointvec,
729 }, 730 },
731 {
732 .ctl_name = CTL_UNNUMBERED,
733 .procname = "io_delay_type",
734 .data = &io_delay_type,
735 .maxlen = sizeof(int),
736 .mode = 0644,
737 .proc_handler = &proc_dointvec,
738 },
730#endif 739#endif
731#if defined(CONFIG_MMU) 740#if defined(CONFIG_MMU)
732 { 741 {