forked from Minki/linux
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 <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: "David P. Reed" <dpreed@reed.com>
This commit is contained in:
parent
b02aae9cf5
commit
6e7c402590
@ -795,12 +795,14 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||||||
then look in the higher range.
|
then look in the higher range.
|
||||||
|
|
||||||
io_delay= [X86-32,X86-64] I/O delay method
|
io_delay= [X86-32,X86-64] I/O delay method
|
||||||
standard
|
0x80
|
||||||
Standard port 0x80 delay
|
Standard port 0x80 based delay
|
||||||
alternate
|
0xed
|
||||||
Alternate port 0xed delay
|
Alternate port 0xed based delay (needed on some systems)
|
||||||
udelay
|
udelay
|
||||||
Simple two microsecond delay
|
Simple two microseconds delay
|
||||||
|
none
|
||||||
|
No delay
|
||||||
|
|
||||||
io7= [HW] IO7 for Marvel based alpha systems
|
io7= [HW] IO7 for Marvel based alpha systems
|
||||||
See comment before marvel_specify_io7 in
|
See comment before marvel_specify_io7 in
|
||||||
|
@ -112,13 +112,78 @@ config IOMMU_LEAK
|
|||||||
Add a simple leak tracer to the IOMMU code. This is useful when you
|
Add a simple leak tracer to the IOMMU code. This is useful when you
|
||||||
are debugging a buggy device driver that leaks IOMMU mappings.
|
are debugging a buggy device driver that leaks IOMMU mappings.
|
||||||
|
|
||||||
config UDELAY_IO_DELAY
|
#
|
||||||
bool "Delay I/O through udelay instead of outb"
|
# IO delay types:
|
||||||
depends on DEBUG_KERNEL
|
#
|
||||||
|
|
||||||
|
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
|
help
|
||||||
Make inb_p/outb_p use udelay() based delays by default. Please note
|
This is the traditional Linux IO delay used for in/out_p.
|
||||||
that udelay() does not have the same bus-level side-effects that
|
It is the most tested hence safest selection here.
|
||||||
the normal outb based delay does meaning this could cause drivers
|
|
||||||
to change behaviour and/or bugs to surface.
|
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
|
||||||
|
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
|
endmenu
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* I/O delay strategies for inb_p/outb_p
|
* 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/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -8,98 +12,86 @@
|
|||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
/*
|
int io_delay_type __read_mostly = CONFIG_DEFAULT_IO_DELAY_TYPE;
|
||||||
* Allow for a DMI based override of port 0x80 needed for certain HP laptops
|
EXPORT_SYMBOL_GPL(io_delay_type);
|
||||||
*/
|
|
||||||
#define IO_DELAY_PORT_STD 0x80
|
|
||||||
#define IO_DELAY_PORT_ALT 0xed
|
|
||||||
|
|
||||||
static void standard_io_delay(void)
|
static int __initdata io_delay_override;
|
||||||
{
|
|
||||||
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.
|
* Paravirt wants native_io_delay to be a constant.
|
||||||
*/
|
*/
|
||||||
void native_io_delay(void)
|
void native_io_delay(void)
|
||||||
{
|
{
|
||||||
io_delay();
|
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);
|
EXPORT_SYMBOL(native_io_delay);
|
||||||
|
|
||||||
#ifndef CONFIG_UDELAY_IO_DELAY
|
static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id)
|
||||||
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);
|
if (io_delay_type == CONFIG_IO_DELAY_TYPE_0X80) {
|
||||||
io_delay = alternate_io_delay;
|
printk(KERN_NOTICE "%s: using 0xed I/O delay port\n",
|
||||||
|
id->ident);
|
||||||
|
io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dmi_system_id __initdata alternate_io_delay_port_dmi_table[] = {
|
/*
|
||||||
|
* 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_alternate_io_delay_port,
|
.callback = dmi_io_delay_0xed_port,
|
||||||
.ident = "HP Pavilion dv9000z",
|
.ident = "HP Pavilion dv9000z",
|
||||||
.matches = {
|
.matches = {
|
||||||
DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
|
DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
|
||||||
DMI_MATCH(DMI_BOARD_NAME, "30B9")
|
DMI_MATCH(DMI_BOARD_NAME, "30B9")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{ }
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __initdata io_delay_override;
|
|
||||||
|
|
||||||
void __init io_delay_init(void)
|
void __init io_delay_init(void)
|
||||||
{
|
{
|
||||||
if (!io_delay_override)
|
if (!io_delay_override)
|
||||||
dmi_check_system(alternate_io_delay_port_dmi_table);
|
dmi_check_system(io_delay_0xed_port_dmi_table);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static int __init io_delay_param(char *s)
|
static int __init io_delay_param(char *s)
|
||||||
{
|
{
|
||||||
if (!s)
|
if (!strcmp(s, "0x80"))
|
||||||
return -EINVAL;
|
io_delay_type = CONFIG_IO_DELAY_TYPE_0X80;
|
||||||
|
else if (!strcmp(s, "0xed"))
|
||||||
if (!strcmp(s, "standard"))
|
io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
|
||||||
io_delay = standard_io_delay;
|
|
||||||
else if (!strcmp(s, "alternate"))
|
|
||||||
io_delay = alternate_io_delay;
|
|
||||||
else if (!strcmp(s, "udelay"))
|
else if (!strcmp(s, "udelay"))
|
||||||
io_delay = udelay_io_delay;
|
io_delay_type = CONFIG_IO_DELAY_TYPE_UDELAY;
|
||||||
|
else if (!strcmp(s, "none"))
|
||||||
|
io_delay_type = CONFIG_IO_DELAY_TYPE_NONE;
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
#ifndef CONFIG_UDELAY_IO_DELAY
|
|
||||||
io_delay_override = 1;
|
io_delay_override = 1;
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,15 +250,11 @@ static inline void flush_write_buffers(void)
|
|||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#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 void native_io_delay(void);
|
||||||
|
|
||||||
|
extern int io_delay_type;
|
||||||
|
extern void io_delay_init(void);
|
||||||
|
|
||||||
#if defined(CONFIG_PARAVIRT)
|
#if defined(CONFIG_PARAVIRT)
|
||||||
#include <asm/paravirt.h>
|
#include <asm/paravirt.h>
|
||||||
#else
|
#else
|
||||||
|
@ -35,15 +35,11 @@
|
|||||||
* - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
* - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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 void native_io_delay(void);
|
||||||
|
|
||||||
|
extern int io_delay_type;
|
||||||
|
extern void io_delay_init(void);
|
||||||
|
|
||||||
static inline void slow_down_io(void)
|
static inline void slow_down_io(void)
|
||||||
{
|
{
|
||||||
native_io_delay();
|
native_io_delay();
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#ifdef CONFIG_X86
|
#ifdef CONFIG_X86
|
||||||
#include <asm/nmi.h>
|
#include <asm/nmi.h>
|
||||||
#include <asm/stacktrace.h>
|
#include <asm/stacktrace.h>
|
||||||
|
#include <asm/io.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int deprecated_sysctl_warning(struct __sysctl_args *args);
|
static int deprecated_sysctl_warning(struct __sysctl_args *args);
|
||||||
@ -727,6 +728,14 @@ static struct ctl_table kern_table[] = {
|
|||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = &proc_dointvec,
|
.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
|
#endif
|
||||||
#if defined(CONFIG_MMU)
|
#if defined(CONFIG_MMU)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user