Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 79707
b: refs/heads/master
c: b02aae9
h: refs/heads/master
i:
  79705: ce7ee98
  79703: 93ff2e0
v: v3
  • Loading branch information
Rene Herman authored and Ingo Molnar committed Jan 30, 2008
1 parent 8b6051a commit a861994
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 24 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4c6b8b4d62fb4cb843c32db71e0a8301039908f3
refs/heads/master: b02aae9cf52956dfe1bec73f77f81a3d05d3902b
8 changes: 8 additions & 0 deletions trunk/Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,14 @@ and is between 256 and 4096 characters. It is defined in the file
for translation below 32 bit and if not available
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
udelay
Simple two microsecond delay

io7= [HW] IO7 for Marvel based alpha systems
See comment before marvel_specify_io7 in
arch/alpha/kernel/core_marvel.c.
Expand Down
9 changes: 9 additions & 0 deletions trunk/arch/x86/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,13 @@ 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
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.

endmenu
8 changes: 4 additions & 4 deletions trunk/arch/x86/boot/compressed/misc_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,10 @@ static void putstr(const char *s)
RM_SCREEN_INFO.orig_y = y;

pos = (x + cols * y) * 2; /* Update cursor position */
outb_p(14, vidport);
outb_p(0xff & (pos >> 9), vidport+1);
outb_p(15, vidport);
outb_p(0xff & (pos >> 1), vidport+1);
outb(14, vidport);
outb(0xff & (pos >> 9), vidport+1);
outb(15, vidport);
outb(0xff & (pos >> 1), vidport+1);
}

static void* memset(void* s, int c, unsigned n)
Expand Down
8 changes: 4 additions & 4 deletions trunk/arch/x86/boot/compressed/misc_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,10 @@ static void putstr(const char *s)
RM_SCREEN_INFO.orig_y = y;

pos = (x + cols * y) * 2; /* Update cursor position */
outb_p(14, vidport);
outb_p(0xff & (pos >> 9), vidport+1);
outb_p(15, vidport);
outb_p(0xff & (pos >> 1), vidport+1);
outb(14, vidport);
outb(0xff & (pos >> 9), vidport+1);
outb(15, vidport);
outb(0xff & (pos >> 1), vidport+1);
}

static void* memset(void* s, int c, unsigned n)
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/x86/kernel/Makefile_32
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ CPPFLAGS_vmlinux.lds += -Ui386
obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \
ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \
pci-dma_32.o i386_ksyms_32.o i387_32.o bootflag.o e820_32.o\
quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o
quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o io_delay.o

obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += cpu/
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/x86/kernel/Makefile_64
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \
x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \
setup64.o bootflag.o e820_64.o reboot_64.o quirks.o i8237.o \
pci-dma_64.o pci-nommu_64.o alternative.o hpet.o tsc_64.o bugs_64.o \
i8253.o
i8253.o io_delay.o

obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += cpu/
Expand Down
106 changes: 106 additions & 0 deletions trunk/arch/x86/kernel/io_delay.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* 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);
2 changes: 2 additions & 0 deletions trunk/arch/x86/kernel/setup_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,8 @@ void __init setup_arch(char **cmdline_p)

dmi_scan_machine();

io_delay_init();;

#ifdef CONFIG_X86_GENERICARCH
generic_apic_probe();
#endif
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/x86/kernel/setup_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ void __init setup_arch(char **cmdline_p)

dmi_scan_machine();

io_delay_init();

#ifdef CONFIG_SMP
/* setup to use the static apicid table during kernel startup */
x86_cpu_to_apicid_ptr = (void *)&x86_cpu_to_apicid_init;
Expand Down
8 changes: 6 additions & 2 deletions trunk/include/asm-x86/io_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,14 @@ static inline void flush_write_buffers(void)

#endif /* __KERNEL__ */

static inline void native_io_delay(void)
#ifndef CONFIG_UDELAY_IO_DELAY
extern void io_delay_init(void);
#else
static inline void io_delay_init(void)
{
asm volatile("outb %%al,$0x80" : : : "memory");
}
#endif
extern void native_io_delay(void);

#if defined(CONFIG_PARAVIRT)
#include <asm/paravirt.h>
Expand Down
33 changes: 22 additions & 11 deletions trunk/include/asm-x86/io_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,24 @@
* - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/

#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
#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);

static inline void slow_down_io(void)
{
native_io_delay();
#ifdef REALLY_SLOW_IO
#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
#else
#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
native_io_delay();
native_io_delay();
native_io_delay();
#endif
}

/*
* Talk about misusing macros..
Expand All @@ -50,21 +61,21 @@
static inline void out##s(unsigned x value, unsigned short port) {

#define __OUT2(s,s1,s2) \
__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" : : "a" (value), "Nd" (port))

#define __OUT(s,s1,x) \
__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
__OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \
__OUT1(s,x) __OUT2(s,s1,"w"); } \
__OUT1(s##_p,x) __OUT2(s,s1,"w"); slow_down_io(); }

#define __IN1(s) \
static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;

#define __IN2(s,s1,s2) \
__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" : "=a" (_v) : "Nd" (port))

#define __IN(s,s1,i...) \
__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
__IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
#define __IN(s,s1) \
__IN1(s) __IN2(s,s1,"w"); return _v; } \
__IN1(s##_p) __IN2(s,s1,"w"); slow_down_io(); return _v; }

#define __INS(s) \
static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
Expand Down

0 comments on commit a861994

Please sign in to comment.