All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86: fix locking and sync bugs in x86_64 RTC code in time_64.c
       [not found]               ` <1184274754.12353.254.camel@chaos>
@ 2007-11-12 16:55                 ` David P. Reed
  2007-11-14  7:49                   ` Thomas Gleixner
  2007-11-12 17:02                 ` [PATCH] time: fix typo that makes sync_cmos_clock erratic David P. Reed
                                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2007-11-12 16:55 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel; +Cc: Allessandro Zummo

From: David P. Reed

Fix two bugs in arch/x86/kernel/time_64.c that affect the x86_64 kernel. 
1) a repeatable hard freeze due to interrupts when the ntpd service 
calls update_persistent_clock(), 2) potentially unstable PC RTC timer 
values when timer is read.

Signed-off-by: David P. Reed <dpreed@reed.com>
---
More explanation:
1) A repeatable but randomly timed freeze has been happening in Fedora 6 
and 7 for the last year, whenever I run the ntpd service on my AMD64x2 
HP Pavilion dv9000z laptop.  This freeze is due to the use of 
spin_lock(&rtc_lock) under the assumption (per a bad comment) that 
set_rtc_mmss is called only with interrupts disabled.  The call from 
ntp.c to update_persistent_clock is made with interrupts enabled.

2) the use of an incorrect technique for reading the standard PC RTC 
timer, which is documented to "disconnect" time registers from the bus 
while updates are in progress.  The use of UIP flag while interrupts are 
disabled to protect a 244 microsecond window is one of the Motorola spec 
sheet's documented ways to read the RTC time registers reliably.  I 
realize that not all "clones" of the

The patch updates the misleading comments and minimizes the amount of 
time that the kernel disables interrupts.

I have thoroughly tested this patch on a number of x86_64 machines with 
various numbers of cores and chipsets, using 2.6.24rc2 kernel source. 
Note that while testing the ntp code I found another bug in 
kernel/time/ntp.c which is independent of this fix - neither patch 
requires the other.

If possible, I'd love to see the patch merged with 2.6.24, and even with 
2.6.23.

Index: linux-2.6/arch/x86/kernel/time_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/time_64.c
+++ linux-2.6/arch/x86/kernel/time_64.c
@@ -82,13 +82,12 @@ static int set_rtc_mmss(unsigned long no
     int retval = 0;
     int real_seconds, real_minutes, cmos_minutes;
     unsigned char control, freq_select;
+    unsigned long flags;
 
-/*
- * IRQs are disabled when we're called from the timer interrupt,
- * no need for spin_lock_irqsave()
+/*
+ * set_rtc_mmss is called when irqs are enabled, so disable irqs here
  */
-
-    spin_lock(&rtc_lock);
+    spin_lock_irqsave(&rtc_lock, flags);
 
 /*
  * Tell the clock it's being set and stop it.
@@ -138,7 +137,7 @@ static int set_rtc_mmss(unsigned long no
     CMOS_WRITE(control, RTC_CONTROL);
     CMOS_WRITE(freq_select, RTC_FREQ_SELECT);
 
-    spin_unlock(&rtc_lock);
+    spin_unlock_irqrestore(&rtc_lock, flags);
 
     return retval;
 }
@@ -163,22 +162,30 @@ unsigned long read_persistent_clock(void
     unsigned long flags;
     unsigned century = 0;
 
-    spin_lock_irqsave(&rtc_lock, flags);
+ retry:    spin_lock_irqsave(&rtc_lock, flags);
+    /* if UIP is clear, then we have >= 244 microseconds before RTC
+     * registers will be updated.  Spec sheet says that this is the
+     * reliable way to read RTC - registers invalid (off bus) during update
+         */
+    if ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) {
+      spin_unlock_irqrestore(&rtc_lock, flags);
+      cpu_relax();
+      goto retry;
+    }
 
-    do {
-        sec = CMOS_READ(RTC_SECONDS);
-        min = CMOS_READ(RTC_MINUTES);
-        hour = CMOS_READ(RTC_HOURS);
-        day = CMOS_READ(RTC_DAY_OF_MONTH);
-        mon = CMOS_READ(RTC_MONTH);
-        year = CMOS_READ(RTC_YEAR);
+    /* now read all RTC registers while stable with interrupts disabled */
+
+    sec = CMOS_READ(RTC_SECONDS);
+    min = CMOS_READ(RTC_MINUTES);
+    hour = CMOS_READ(RTC_HOURS);
+    day = CMOS_READ(RTC_DAY_OF_MONTH);
+    mon = CMOS_READ(RTC_MONTH);
+    year = CMOS_READ(RTC_YEAR);
 #ifdef CONFIG_ACPI
-        if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
-                    acpi_gbl_FADT.century)
-            century = CMOS_READ(acpi_gbl_FADT.century);
+    if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
+                acpi_gbl_FADT.century)
+        century = CMOS_READ(acpi_gbl_FADT.century);
 #endif
-    } while (sec != CMOS_READ(RTC_SECONDS));
-
     spin_unlock_irqrestore(&rtc_lock, flags);
 
     /*








^ permalink raw reply	[flat|nested] 243+ messages in thread

* [PATCH] time: fix typo that makes sync_cmos_clock erratic
       [not found]               ` <1184274754.12353.254.camel@chaos>
  2007-11-12 16:55                 ` [PATCH] x86: fix locking and sync bugs in x86_64 RTC code in time_64.c David P. Reed
@ 2007-11-12 17:02                 ` David P. Reed
  2007-11-14  7:57                   ` Thomas Gleixner
  2007-11-12 19:19                 ` David P. Reed
                                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2007-11-12 17:02 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel; +Cc: Allessandro Zummo

From: David P. Reed

Fix a typo in ntp.c that has caused updating of the persistent (RTC) 
clock when synced to NTP to behave erratically.

Signed-off-by: David P. Reed

---
When debugging a freeze that arises on my AMD64 machines when I run the 
ntpd service, I added a number of printk's to monitor the 
sync_cmos_clock procedure.  I discovered that it was not syncing to cmos 
RTC every 11 minutes as documented, but instead would keep trying every 
second for hours at a time.   The reason turned out to be a typo in 
sync_cmos_clock, where it attempts to ensure that 
update_persistent_clock is called very close to 500 msec. after a 1 
second boundary (required by the PC RTC's spec). That typo referred to 
"xtime" in one spot, rather than "now", which is derived from "xtime" 
but not equal to it.  This makes the test erratic, creating a 
"coin-flip" that decides when update_persistent_clock is called - when 
it is called, which is rarely, it may be at any time during the one 
second period, rather than close to 500 msec, so the value written is 
needlessly incorrect, too.

I rewrote the code to fix the typo and to be a little more clear about 
the logic that was intended here.  I have thoroughly tested this on 
several x86_64 machines, and also on one 32-bit machine.  I have also 
submitted a patch to fix the freeze cited above, but both patches are 
independent, and should be treated separately.

The patch works in 2.6.24rc2, but it should also work in 2.6.23.

Index: linux-2.6/kernel/time/ntp.c
===================================================================
--- linux-2.6.orig/kernel/time/ntp.c
+++ linux-2.6/kernel/time/ntp.c
@@ -188,6 +188,7 @@ static DEFINE_TIMER(sync_cmos_timer, syn
 static void sync_cmos_clock(unsigned long dummy)
 {
     struct timespec now, next;
+    long delta_from_target_time;
     int fail = 1;
 
     /*
@@ -205,7 +206,10 @@ static void sync_cmos_clock(unsigned lon
         return;
 
     getnstimeofday(&now);
-    if (abs(xtime.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
+    delta_from_target_time = abs(now.tv_nsec - (NSEC_PER_SEC / 2));
+
+    /* set CMOS clock, only if close enough to 500 msec point */
+    if (delta_from_target_time <= tick_nsec / 2)
         fail = update_persistent_clock(now);
 
     next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec;

^ permalink raw reply	[flat|nested] 243+ messages in thread

* [PATCH] time: fix typo that makes sync_cmos_clock erratic
       [not found]               ` <1184274754.12353.254.camel@chaos>
  2007-11-12 16:55                 ` [PATCH] x86: fix locking and sync bugs in x86_64 RTC code in time_64.c David P. Reed
  2007-11-12 17:02                 ` [PATCH] time: fix typo that makes sync_cmos_clock erratic David P. Reed
@ 2007-11-12 19:19                 ` David P. Reed
  2007-11-14 22:47                 ` [PATCH] x86: fix freeze in x86_64 RTC update code in time_64.c David P. Reed
                                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2007-11-12 19:19 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel; +Cc: Allessandro Zummo

From: David P. Reed

Fix a typo in ntp.c that has caused updating of the persistent (RTC)
clock when synced to NTP to behave erratically.

Signed-off-by: David P. Reed

---
When debugging a freeze that arises on my AMD64 machines when I run the
ntpd service, I added a number of printk's to monitor the
sync_cmos_clock procedure.  I discovered that it was not syncing to cmos
RTC every 11 minutes as documented, but instead would keep trying every
second for hours at a time.   The reason turned out to be a typo in
sync_cmos_clock, where it attempts to ensure that
update_persistent_clock is called very close to 500 msec. after a 1
second boundary (required by the PC RTC's spec). That typo referred to
"xtime" in one spot, rather than "now", which is derived from "xtime"
but not equal to it.  This makes the test erratic, creating a
"coin-flip" that decides when update_persistent_clock is called - when
it is called, which is rarely, it may be at any time during the one
second period, rather than close to 500 msec, so the value written is
needlessly incorrect, too.

I rewrote the code to fix the typo and to be a little more clear about
the logic that was intended here.  I have thoroughly tested this on
several x86_64 machines, and also on one 32-bit machine.  I have also
submitted a patch to fix the freeze cited above, but both patches are
independent, and should be treated separately.

The patch works in 2.6.24rc2, but it should also work in 2.6.23.

Index: linux-2.6/kernel/time/ntp.c
===================================================================
--- linux-2.6.orig/kernel/time/ntp.c
+++ linux-2.6/kernel/time/ntp.c
@@ -188,6 +188,7 @@ static DEFINE_TIMER(sync_cmos_timer, syn
static void sync_cmos_clock(unsigned long dummy)
{
     struct timespec now, next;
+    long delta_from_target_time;
     int fail = 1;

     /*
@@ -205,7 +206,10 @@ static void sync_cmos_clock(unsigned lon
         return;

     getnstimeofday(&now);
-    if (abs(xtime.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
+    delta_from_target_time = abs(now.tv_nsec - (NSEC_PER_SEC / 2));
+
+    /* set CMOS clock, only if close enough to 500 msec point */
+    if (delta_from_target_time <= tick_nsec / 2)
         fail = update_persistent_clock(now);

     next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec;


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: fix locking and sync bugs in x86_64 RTC code in time_64.c
  2007-11-12 16:55                 ` [PATCH] x86: fix locking and sync bugs in x86_64 RTC code in time_64.c David P. Reed
@ 2007-11-14  7:49                   ` Thomas Gleixner
  2007-11-14 13:10                     ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: Thomas Gleixner @ 2007-11-14  7:49 UTC (permalink / raw)
  To: David P. Reed; +Cc: linux-kernel, Allessandro Zummo

David,

On Mon, 12 Nov 2007, David P. Reed wrote:

> From: David P. Reed
> 
> Fix two bugs in arch/x86/kernel/time_64.c that affect the x86_64 kernel. 1) a
> repeatable hard freeze due to interrupts when the ntpd service calls
> update_persistent_clock(), 2) potentially unstable PC RTC timer values when
> timer is read.

1) Please send separate patches for separate problems.

2) Your patch is white space damaged and does not apply. Please run it
   through scripts/checkpatch.pl before submitting, maybe send it to
   yourself first and verify that it applies correctly.

> Signed-off-by: David P. Reed <dpreed@reed.com>
> ---
> More explanation:
> 1) A repeatable but randomly timed freeze has been happening in Fedora 6 and 7
> for the last year, whenever I run the ntpd service on my AMD64x2 HP Pavilion
> dv9000z laptop.  This freeze is due to the use of spin_lock(&rtc_lock) under
> the assumption (per a bad comment) that set_rtc_mmss is called only with
> interrupts disabled.  The call from ntp.c to update_persistent_clock is made
> with interrupts enabled.

Good catch.
 
> 2) the use of an incorrect technique for reading the standard PC RTC timer,
> which is documented to "disconnect" time registers from the bus while updates
> are in progress.  The use of UIP flag while interrupts are disabled to protect
> a 244 microsecond window is one of the Motorola spec sheet's documented ways
> to read the RTC time registers reliably.  I realize that not all "clones" of
> the

of the what ?

Also put the detailed description into the patch comment, please.

> The patch updates the misleading comments and minimizes the amount of time
> that the kernel disables interrupts.
> 
> I have thoroughly tested this patch on a number of x86_64 machines with
> various numbers of cores and chipsets, using 2.6.24rc2 kernel source. Note
> that while testing the ntp code I found another bug in kernel/time/ntp.c which
> is independent of this fix - neither patch requires the other.
>
> If possible, I'd love to see the patch merged with 2.6.24, and even with
> 2.6.23.

Care to resend ?

Thanks,

     tglx

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] time: fix typo that makes sync_cmos_clock erratic
  2007-11-12 17:02                 ` [PATCH] time: fix typo that makes sync_cmos_clock erratic David P. Reed
@ 2007-11-14  7:57                   ` Thomas Gleixner
  0 siblings, 0 replies; 243+ messages in thread
From: Thomas Gleixner @ 2007-11-14  7:57 UTC (permalink / raw)
  To: David P. Reed; +Cc: linux-kernel, Allessandro Zummo

David,

On Mon, 12 Nov 2007, David P. Reed wrote:

> From: David P. Reed
> 
> Fix a typo in ntp.c that has caused updating of the persistent (RTC) clock
> when synced to NTP to behave erratically.

Good catch.

> Signed-off-by: David P. Reed

Whitespace damaged as well. Please fix and resend

> ---
> When debugging a freeze that arises on my AMD64 machines when I run the 
> ntpd service, I added a number of printk's to monitor the sync_cmos_clock
> procedure.  I discovered that it was not syncing to cmos RTC every 11 minutes
> as documented, but instead would keep trying every second for hours at a time.
> The reason turned out to be a typo in sync_cmos_clock, where it attempts to
> ensure that update_persistent_clock is called very close to 500 msec. after a
> 1 second boundary (required by the PC RTC's spec). That typo referred to
> "xtime" in one spot, rather than "now", which is derived from "xtime" but not
> equal to it.  This makes the test erratic, creating a "coin-flip" that decides
> when update_persistent_clock is called - when it is called, which is rarely,
> it may be at any time during the one second period, rather than close to 500
> msec, so the value written is needlessly incorrect, too.

Please put the explanation into the changelog.

> The patch works in 2.6.24rc2, but it should also work in 2.6.23.

Yup
 
> @@ -205,7 +206,10 @@ static void sync_cmos_clock(unsigned lon
>         return;
> 
>     getnstimeofday(&now);
> -    if (abs(xtime.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)

Can we just s/xtime/now/ ? There is no value in an extra variable.

Thanks,

	tglx


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: fix locking and sync bugs in x86_64 RTC code in time_64.c
  2007-11-14  7:49                   ` Thomas Gleixner
@ 2007-11-14 13:10                     ` David P. Reed
  2007-11-14 18:26                       ` Matt Mackall
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2007-11-14 13:10 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: linux-kernel, Allessandro Zummo

Will make two patches and resend.

Thomas Gleixner wrote:
> David,
>
> On Mon, 12 Nov 2007, David P. Reed wrote:
>
>   
>> From: David P. Reed
>>
>> Fix two bugs in arch/x86/kernel/time_64.c that affect the x86_64 kernel. 1) a
>> repeatable hard freeze due to interrupts when the ntpd service calls
>> update_persistent_clock(), 2) potentially unstable PC RTC timer values when
>> timer is read.
>>     
>
> 1) Please send separate patches for separate problems.
>
> 2) Your patch is white space damaged and does not apply. Please run it
>    through scripts/checkpatch.pl before submitting, maybe send it to
>    yourself first and verify that it applies correctly.
>
>   
>> Signed-off-by: David P. Reed <dpreed@reed.com>
>> ---
>> More explanation:
>> 1) A repeatable but randomly timed freeze has been happening in Fedora 6 and 7
>> for the last year, whenever I run the ntpd service on my AMD64x2 HP Pavilion
>> dv9000z laptop.  This freeze is due to the use of spin_lock(&rtc_lock) under
>> the assumption (per a bad comment) that set_rtc_mmss is called only with
>> interrupts disabled.  The call from ntp.c to update_persistent_clock is made
>> with interrupts enabled.
>>     
>
> Good catch.
>  
>   
>> 2) the use of an incorrect technique for reading the standard PC RTC timer,
>> which is documented to "disconnect" time registers from the bus while updates
>> are in progress.  The use of UIP flag while interrupts are disabled to protect
>> a 244 microsecond window is one of the Motorola spec sheet's documented ways
>> to read the RTC time registers reliably.  I realize that not all "clones" of
>> the
>>     
>
> of the what ?
>
> Also put the detailed description into the patch comment, please.
>
>   
>> The patch updates the misleading comments and minimizes the amount of time
>> that the kernel disables interrupts.
>>
>> I have thoroughly tested this patch on a number of x86_64 machines with
>> various numbers of cores and chipsets, using 2.6.24rc2 kernel source. Note
>> that while testing the ntp code I found another bug in kernel/time/ntp.c which
>> is independent of this fix - neither patch requires the other.
>>
>> If possible, I'd love to see the patch merged with 2.6.24, and even with
>> 2.6.23.
>>     
>
> Care to resend ?
>
> Thanks,
>
>      tglx
>
>   

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: fix locking and sync bugs in x86_64 RTC code in time_64.c
  2007-11-14 13:10                     ` David P. Reed
@ 2007-11-14 18:26                       ` Matt Mackall
  2007-11-14 21:22                         ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: Matt Mackall @ 2007-11-14 18:26 UTC (permalink / raw)
  To: David P. Reed; +Cc: Thomas Gleixner, linux-kernel, Allessandro Zummo

On Wed, Nov 14, 2007 at 08:10:22AM -0500, David P. Reed wrote:
> Will make two patches and resend.

I've already got a set of patches brewing to fix the UIP problem across all
the affected arches (11+).

-- 
Mathematics is the supreme nostalgia of our time.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: fix locking and sync bugs in x86_64 RTC code in time_64.c
  2007-11-14 18:26                       ` Matt Mackall
@ 2007-11-14 21:22                         ` David P. Reed
  0 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2007-11-14 21:22 UTC (permalink / raw)
  To: Matt Mackall; +Cc: Thomas Gleixner, linux-kernel, Allessandro Zummo

Cool. More reason to separate this into two.

Matt Mackall wrote:
> On Wed, Nov 14, 2007 at 08:10:22AM -0500, David P. Reed wrote:
>   
>> Will make two patches and resend.
>>     
>
> I've already got a set of patches brewing to fix the UIP problem across all
> the affected arches (11+).
>
>   

^ permalink raw reply	[flat|nested] 243+ messages in thread

* [PATCH] x86: fix freeze in x86_64 RTC update code in time_64.c
       [not found]               ` <1184274754.12353.254.camel@chaos>
                                   ` (2 preceding siblings ...)
  2007-11-12 19:19                 ` David P. Reed
@ 2007-11-14 22:47                 ` David P. Reed
  2007-11-14 22:49                 ` [PATCH] time: fix typo that makes sync_cmos_clock erratic David P. Reed
                                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2007-11-14 22:47 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel; +Cc: Allessandro Zummo

Fix hard freeze on x86_64 when the ntpd service calls 
update_persistent_clock()

A repeatable but randomly timed freeze has been happening in Fedora 6
and 7 for the last year, whenever I run the ntpd service on my AMD64x2
HP Pavilion dv9000z laptop.  This freeze is due to the use of
spin_lock(&rtc_lock) under the assumption (per a bad comment) that
set_rtc_mmss is called only with interrupts disabled.  The call from
ntp.c to update_persistent_clock is made with interrupts enabled.

Signed-off-by: David P. Reed <dpreed@reed.com>
---
I have thoroughly tested this patch on a number of x86_64 machines
with various numbers of cores and chipsets, using 2.6.24rc2 kernel
source.

Index: linux-2.6/arch/x86/kernel/time_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/time_64.c
+++ linux-2.6/arch/x86/kernel/time_64.c
@@ -82,18 +82,15 @@ static int set_rtc_mmss(unsigned long no
  	int retval = 0;
  	int real_seconds, real_minutes, cmos_minutes;
  	unsigned char control, freq_select;
+	unsigned long flags;

  /*
- * IRQs are disabled when we're called from the timer interrupt,
- * no need for spin_lock_irqsave()
+ * set_rtc_mmss is called when irqs are enabled, so disable irqs here
   */
-
-	spin_lock(&rtc_lock);
-
+	spin_lock_irqsave(&rtc_lock, flags);
  /*
   * Tell the clock it's being set and stop it.
   */
-
  	control = CMOS_READ(RTC_CONTROL);
  	CMOS_WRITE(control | RTC_SET, RTC_CONTROL);

@@ -138,7 +135,7 @@ static int set_rtc_mmss(unsigned long no
  	CMOS_WRITE(control, RTC_CONTROL);
  	CMOS_WRITE(freq_select, RTC_FREQ_SELECT);

-	spin_unlock(&rtc_lock);
+	spin_unlock_irqrestore(&rtc_lock, flags);

  	return retval;
  }



^ permalink raw reply	[flat|nested] 243+ messages in thread

* [PATCH] time: fix typo that makes sync_cmos_clock erratic
       [not found]               ` <1184274754.12353.254.camel@chaos>
                                   ` (3 preceding siblings ...)
  2007-11-14 22:47                 ` [PATCH] x86: fix freeze in x86_64 RTC update code in time_64.c David P. Reed
@ 2007-11-14 22:49                 ` David P. Reed
  2007-11-15  1:14                 ` [PATCH] x86: on x86_64, correct reading of PC RTC when update in progress in time_64.c David P. Reed
  2007-12-14  2:59                 ` [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
  6 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2007-11-14 22:49 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel; +Cc: Allessandro Zummo

Fix a typo in ntp.c that has caused updating of the persistent (RTC)
clock when synced to NTP to behave erratically.

When debugging a freeze that arises on my AMD64 machines when I
run the ntpd service, I added a number of printk's to monitor the
sync_cmos_clock procedure.  I discovered that it was not syncing to
cmos RTC every 11 minutes as documented, but instead would keep trying
every second for hours at a time.  The reason turned out to be a typo
in sync_cmos_clock, where it attempts to ensure that
update_persistent_clock is called very close to 500 msec. after a 1
second boundary (required by the PC RTC's spec). That typo referred to
"xtime" in one spot, rather than "now", which is derived from "xtime"
but not equal to it.  This makes the test erratic, creating a
"coin-flip" that decides when update_persistent_clock is called - when
it is called, which is rarely, it may be at any time during the one
second period, rather than close to 500 msec, so the value written is
needlessly incorrect, too.

Signed-off-by: David P. Reed

---
I have thoroughly tested this on several x86_64 machines, and also
on one 32-bit machine.  I have also submitted a patch to fix the
freeze cited above, but both patches are independent, and should be
treated separately.

Index: linux-2.6/kernel/time/ntp.c
===================================================================
--- linux-2.6.orig/kernel/time/ntp.c
+++ linux-2.6/kernel/time/ntp.c
@@ -205,7 +205,7 @@ static void sync_cmos_clock(unsigned lon
  		return;

  	getnstimeofday(&now);
-	if (abs(xtime.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
+	if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
  		fail = update_persistent_clock(now);

  	next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec;

^ permalink raw reply	[flat|nested] 243+ messages in thread

* [PATCH] x86: on x86_64, correct reading of PC RTC when update in progress in time_64.c
       [not found]               ` <1184274754.12353.254.camel@chaos>
                                   ` (4 preceding siblings ...)
  2007-11-14 22:49                 ` [PATCH] time: fix typo that makes sync_cmos_clock erratic David P. Reed
@ 2007-11-15  1:14                 ` David P. Reed
  2007-11-15 19:33                   ` Thomas Gleixner
  2007-12-14  2:59                 ` [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
  6 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2007-11-15  1:14 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel; +Cc: Allessandro Zummo, Matt Mackall

Correct potentially unstable PC RTC time register reading in time_64.c

Stop the use of an incorrect technique for reading the standard PC RTC
timer, which is documented to "disconnect" time registers from the bus
while updates are in progress.  The use of UIP flag while interrupts
are disabled to protect a 244 microsecond window is one of the
Motorola spec sheet's documented ways to read the RTC time registers
reliably.

The patch updates the misleading comments and also minimizes the amount of
time that the kernel disables interrupts during the reading.

Signed-off-by: David P. Reed <dpreed@reed.com>
---
Index: linux-2.6/arch/x86/kernel/time_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/time_64.c
+++ linux-2.6/arch/x86/kernel/time_64.c
@@ -160,22 +160,30 @@ unsigned long read_persistent_clock(void
  	unsigned long flags;
  	unsigned century = 0;

-	spin_lock_irqsave(&rtc_lock, flags);
+ retry:	spin_lock_irqsave(&rtc_lock, flags);
+	/* if UIP is clear, then we have >= 244 microseconds before RTC
+	 * registers will be updated.  Spec sheet says that this is the
+	 * reliable way to read RTC - registers invalid (off bus) during update
+	 */
+	if ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) {
+	  spin_unlock_irqrestore(&rtc_lock, flags);
+	  cpu_relax();
+	  goto retry;
+	}

-	do {
-		sec = CMOS_READ(RTC_SECONDS);
-		min = CMOS_READ(RTC_MINUTES);
-		hour = CMOS_READ(RTC_HOURS);
-		day = CMOS_READ(RTC_DAY_OF_MONTH);
-		mon = CMOS_READ(RTC_MONTH);
-		year = CMOS_READ(RTC_YEAR);
+	/* now read all RTC registers while stable with interrupts disabled */
+
+	sec = CMOS_READ(RTC_SECONDS);
+	min = CMOS_READ(RTC_MINUTES);
+	hour = CMOS_READ(RTC_HOURS);
+	day = CMOS_READ(RTC_DAY_OF_MONTH);
+	mon = CMOS_READ(RTC_MONTH);
+	year = CMOS_READ(RTC_YEAR);
  #ifdef CONFIG_ACPI
-		if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
-					acpi_gbl_FADT.century)
-			century = CMOS_READ(acpi_gbl_FADT.century);
+	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
+				acpi_gbl_FADT.century)
+		century = CMOS_READ(acpi_gbl_FADT.century);
  #endif
-	} while (sec != CMOS_READ(RTC_SECONDS));
-
  	spin_unlock_irqrestore(&rtc_lock, flags);

  	/*



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: on x86_64, correct reading of PC RTC when update in progress in time_64.c
  2007-11-15  1:14                 ` [PATCH] x86: on x86_64, correct reading of PC RTC when update in progress in time_64.c David P. Reed
@ 2007-11-15 19:33                   ` Thomas Gleixner
  2007-11-15 20:31                     ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: Thomas Gleixner @ 2007-11-15 19:33 UTC (permalink / raw)
  To: David P. Reed; +Cc: linux-kernel, Allessandro Zummo, Matt Mackall

On Wed, 14 Nov 2007, David P. Reed wrote:

Still whitespace wreckage in your patches. I guess the kernel tree you
made your patches against is already white space wrecked.

I fixed that up manually, but please be more careful about that next
time.

> Correct potentially unstable PC RTC time register reading in time_64.c
> 
> Stop the use of an incorrect technique for reading the standard PC RTC
> timer, which is documented to "disconnect" time registers from the bus
> while updates are in progress.  The use of UIP flag while interrupts
> are disabled to protect a 244 microsecond window is one of the
> Motorola spec sheet's documented ways to read the RTC time registers
> reliably.
> 
> The patch updates the misleading comments and also minimizes the amount of
> time that the kernel disables interrupts during the reading.

While I think that the UIP change is correct and a must have, the
locking change is not really useful. read_persistent_clock is called
from exactly three places:

Right after boot, right before suspend and right after resume. None of
those places is a hot path, where we really care about the interrupt
enable/disable. IIRC, this is even called with interrupts disabled
most of the time, so no real gain here.

Another reason not to do the locking change is the paravirt stuff
which is coming for 64bit. I looked into the existing 32bit code and
doing the same lock thing would introduce a real nasty hackery, which
is definitely not worth the trouble.

Thanks,

	tglx

> Signed-off-by: David P. Reed <dpreed@reed.com>
> ---
> Index: linux-2.6/arch/x86/kernel/time_64.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/time_64.c
> +++ linux-2.6/arch/x86/kernel/time_64.c
> @@ -160,22 +160,30 @@ unsigned long read_persistent_clock(void
>  	unsigned long flags;
>  	unsigned century = 0;
> 
> -	spin_lock_irqsave(&rtc_lock, flags);
> + retry:	spin_lock_irqsave(&rtc_lock, flags);
> +	/* if UIP is clear, then we have >= 244 microseconds before RTC
> +	 * registers will be updated.  Spec sheet says that this is the
> +	 * reliable way to read RTC - registers invalid (off bus) during
> update
> +	 */
> +	if ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) {
> +	  spin_unlock_irqrestore(&rtc_lock, flags);
> +	  cpu_relax();
> +	  goto retry;
> +	}
> 
> -	do {
> -		sec = CMOS_READ(RTC_SECONDS);
> -		min = CMOS_READ(RTC_MINUTES);
> -		hour = CMOS_READ(RTC_HOURS);
> -		day = CMOS_READ(RTC_DAY_OF_MONTH);
> -		mon = CMOS_READ(RTC_MONTH);
> -		year = CMOS_READ(RTC_YEAR);
> +	/* now read all RTC registers while stable with interrupts disabled */
> +
> +	sec = CMOS_READ(RTC_SECONDS);
> +	min = CMOS_READ(RTC_MINUTES);
> +	hour = CMOS_READ(RTC_HOURS);
> +	day = CMOS_READ(RTC_DAY_OF_MONTH);
> +	mon = CMOS_READ(RTC_MONTH);
> +	year = CMOS_READ(RTC_YEAR);
>  #ifdef CONFIG_ACPI
> -		if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
> -					acpi_gbl_FADT.century)
> -			century = CMOS_READ(acpi_gbl_FADT.century);
> +	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
> +				acpi_gbl_FADT.century)
> +		century = CMOS_READ(acpi_gbl_FADT.century);
>  #endif
> -	} while (sec != CMOS_READ(RTC_SECONDS));
> -
>  	spin_unlock_irqrestore(&rtc_lock, flags);
> 
>  	/*
> 
> 

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: on x86_64, correct reading of PC RTC when update in progress in time_64.c
  2007-11-15 19:33                   ` Thomas Gleixner
@ 2007-11-15 20:31                     ` David P. Reed
  2007-11-15 22:17                       ` Thomas Gleixner
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2007-11-15 20:31 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: linux-kernel, Allessandro Zummo, Matt Mackall

There are a couple of things I don't understand on this one.  And I 
presume you thought the other two bug fixing patches I sent before this 
were OK to go, since on my system

Thomas Gleixner wrote:

> Still whitespace wreckage in your patches. I guess the kernel tree you
> made your patches against is already white space wrecked.
>
> I fixed that up manually, but please be more careful about that next
> time.

Um ... I fixed the whitespaces I detected from the first round with 
checkpatch.pl.  Then for good measure
I ran checkpatch.pl on the patches, then pasted the files directly into 
the emails.  No problems detected.
And I also just tried checkpatch.pl on the "sent" folder copy.  No 
problems detected there.
Where was the whitespace?  Was it in the patches? Would you mind showing 
me the output so I can do a better job in the future?
>   
>> Correct potentially unstable PC RTC time register reading in time_64.c
>>
>> Stop the use of an incorrect technique for reading the standard PC RTC
>> timer, which is documented to "disconnect" time registers from the bus
>> while updates are in progress.  The use of UIP flag while interrupts
>> are disabled to protect a 244 microsecond window is one of the
>> Motorola spec sheet's documented ways to read the RTC time registers
>> reliably.
>>
>> The patch updates the misleading comments and also minimizes the amount of
>> time that the kernel disables interrupts during the reading.
>>     
>
> While I think that the UIP change is correct and a must have, the
> locking change is not really useful. read_persistent_clock is called
> from exactly three places:
>   
What locking change?  I didn't change how locking works in 
read_persistent_clock at all.
I did introduce cpu_relax() because if anyone else ever calls from a hot 
path, that would be good practice and its' one line.
> Right after boot, right before suspend and right after resume. None of
> those places is a hot path, where we really care about the interrupt
> enable/disable. IIRC, this is even called with interrupts disabled
> most of the time, so no real gain here.
>
> Another reason not to do the locking change is the paravirt stuff
> which is coming for 64bit. I looked into the existing 32bit code and
> doing the same lock thing would introduce a real nasty hackery, which
> is definitely not worth the trouble.
>   
I presume time_64.c and time_32.c will be unified at some point, 
discarding time_64.c.  There's no arch-specific reason to be separate.  
The current time_32.c depends on a different nmi path (that does some 
weird stuff saving and restoring the CMOS index register!), and I didn't 
dare usurp your long-term plan to unify architectures.  But a simple 
cleanup here makes sense, lest someone copy the bad technique as if it 
were good.
> Thanks,
>
> 	tglx
>
>   
>> Signed-off-by: David P. Reed <dpreed@reed.com>
>> ---
>> Index: linux-2.6/arch/x86/kernel/time_64.c
>> ===================================================================
>> --- linux-2.6.orig/arch/x86/kernel/time_64.c
>> +++ linux-2.6/arch/x86/kernel/time_64.c
>> @@ -160,22 +160,30 @@ unsigned long read_persistent_clock(void
>>  	unsigned long flags;
>>  	unsigned century = 0;
>>
>> -	spin_lock_irqsave(&rtc_lock, flags);
>> + retry:	spin_lock_irqsave(&rtc_lock, flags);
>> +	/* if UIP is clear, then we have >= 244 microseconds before RTC
>> +	 * registers will be updated.  Spec sheet says that this is the
>> +	 * reliable way to read RTC - registers invalid (off bus) during
>> update
>> +	 */
>> +	if ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) {
>> +	  spin_unlock_irqrestore(&rtc_lock, flags);
>> +	  cpu_relax();
>> +	  goto retry;
>> +	}
>>
>> -	do {
>> -		sec = CMOS_READ(RTC_SECONDS);
>> -		min = CMOS_READ(RTC_MINUTES);
>> -		hour = CMOS_READ(RTC_HOURS);
>> -		day = CMOS_READ(RTC_DAY_OF_MONTH);
>> -		mon = CMOS_READ(RTC_MONTH);
>> -		year = CMOS_READ(RTC_YEAR);
>> +	/* now read all RTC registers while stable with interrupts disabled */
>> +
>> +	sec = CMOS_READ(RTC_SECONDS);
>> +	min = CMOS_READ(RTC_MINUTES);
>> +	hour = CMOS_READ(RTC_HOURS);
>> +	day = CMOS_READ(RTC_DAY_OF_MONTH);
>> +	mon = CMOS_READ(RTC_MONTH);
>> +	year = CMOS_READ(RTC_YEAR);
>>  #ifdef CONFIG_ACPI
>> -		if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
>> -					acpi_gbl_FADT.century)
>> -			century = CMOS_READ(acpi_gbl_FADT.century);
>> +	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
>> +				acpi_gbl_FADT.century)
>> +		century = CMOS_READ(acpi_gbl_FADT.century);
>>  #endif
>> -	} while (sec != CMOS_READ(RTC_SECONDS));
>> -
>>  	spin_unlock_irqrestore(&rtc_lock, flags);
>>
>>  	/*
>>
>>
>>     
>
>   

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: on x86_64, correct reading of PC RTC when update in progress in time_64.c
  2007-11-15 20:31                     ` David P. Reed
@ 2007-11-15 22:17                       ` Thomas Gleixner
  0 siblings, 0 replies; 243+ messages in thread
From: Thomas Gleixner @ 2007-11-15 22:17 UTC (permalink / raw)
  To: David P. Reed; +Cc: linux-kernel, Allessandro Zummo, Matt Mackall

On Thu, 15 Nov 2007, David P. Reed wrote:

> There are a couple of things I don't understand on this one.  And I presume
> you thought the other two bug fixing patches I sent before this were OK to go,
> since on my system

I had to fix up all of them.

> Thomas Gleixner wrote:
> 
> > Still whitespace wreckage in your patches. I guess the kernel tree you
> > made your patches against is already white space wrecked.
> > 
> > I fixed that up manually, but please be more careful about that next
> > time.
> 
> Um ... I fixed the whitespaces I detected from the first round with
> checkpatch.pl.  Then for good measure
> I ran checkpatch.pl on the patches, then pasted the files directly into the
> emails.  No problems detected.

Never paste patches into mail. Also I should have checked your mail
client earlier. Thunderbird is famous for this :)
Documentation/email-clients.txt has some info on that.

> And I also just tried checkpatch.pl on the "sent" folder copy.  No problems
> detected there.

Try to apply your own patches right from the sent folder copy. They
will reject.

> Where was the whitespace?  Was it in the patches? Would you mind showing me
> the output so I can do a better job in the future?

Well the output was a simple reject when applying the patch.

Whitespace damage was for example here:

	   unsigned long flags;
20 20 09 75 6e 73  69 67 6e 65 64 20 6c 6f 6e 67 20 66 6c 61 67 73 3b 0a

where the correct patch should read:

20 09 75 6e 73  69 67 6e 65 64 20 6c 6f 6e 67 20 66 6c 61 67 73 3b 0a

Your mailer or the paste added a second blank (0x20) at the beginning
of the line.

> > > Correct potentially unstable PC RTC time register reading in time_64.c
> > > 
> > > Stop the use of an incorrect technique for reading the standard PC RTC
> > > timer, which is documented to "disconnect" time registers from the bus
> > > while updates are in progress.  The use of UIP flag while interrupts
> > > are disabled to protect a 244 microsecond window is one of the
> > > Motorola spec sheet's documented ways to read the RTC time registers
> > > reliably.
> > > 
> > > The patch updates the misleading comments and also minimizes the amount of
> > > time that the kernel disables interrupts during the reading.
> > >     
> > 
> > While I think that the UIP change is correct and a must have, the
> > locking change is not really useful. read_persistent_clock is called
> > from exactly three places:
> >   
> What locking change?  I didn't change how locking works in
> read_persistent_clock at all.
> I did introduce cpu_relax() because if anyone else ever calls from a hot path,
> that would be good practice and its' one line.

Hot path calls to this code would be extremly stupid and are forbidden
by the Penguin Law. :)

cpu_relax is not the problem, but you actuall changed the locking:

Old code:

    spin_lock();
    do {
       ....
    } while (stupid check);
    spin_unlock();

New code:
    while (1) {
        spin_lock();
        if (useful_check) {
             spin_unlock();
             cpu_relax();
        } else
             break;
   }

So with the old code I can take out the inner loop and do what
paravirtualization in the 32 bit code does:

	spin_lock_irqsave(&rtc_lock, flags);
	result = get_wallclock();
	spin_unlock_irqrestore(&rtc_lock, flags);

Where get_wallclock() either resolves to the plain rtc code or to the
paravirtualized function depending on the boot mode of the kernel.

With your change we either would need to put lokck/unlock of rtc_lock
into each incarnation of paravirt or do some nasty hack, where we
convey the flags to the called function. Neither of this makes sense
and is worth the work.

> > Right after boot, right before suspend and right after resume. None of
> > those places is a hot path, where we really care about the interrupt
> > enable/disable. IIRC, this is even called with interrupts disabled
> > most of the time, so no real gain here.
> > 
> > Another reason not to do the locking change is the paravirt stuff
> > which is coming for 64bit. I looked into the existing 32bit code and
> > doing the same lock thing would introduce a real nasty hackery, which
> > is definitely not worth the trouble.
> >   
> I presume time_64.c and time_32.c will be unified at some point, discarding
> time_64.c.  There's no arch-specific reason to be separate.  The current
> time_32.c depends on a different nmi path (that does some weird stuff saving
> and restoring the CMOS index register!), and I didn't dare usurp your
> long-term plan to unify architectures.  But a simple cleanup here makes sense,
> lest someone copy the bad technique as if it were good.

Yeah, those files are on the radar. The cleanup branch of the x86 git
tree has a first go on this already. And I'm currently figuring out
what we can do about this ugly CMOS index hack.

Anyway I keep the locking straight and simple as it is right now, the
cpu_relax() works fine with a lock held, while we are waiting the
bunch of usecs for UIP going away.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 243+ messages in thread

* [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
       [not found]               ` <1184274754.12353.254.camel@chaos>
                                   ` (5 preceding siblings ...)
  2007-11-15  1:14                 ` [PATCH] x86: on x86_64, correct reading of PC RTC when update in progress in time_64.c David P. Reed
@ 2007-12-14  2:59                 ` David P. Reed
  2007-12-14  7:49                   ` Yinghai Lu
                                     ` (4 more replies)
  6 siblings, 5 replies; 243+ messages in thread
From: David P. Reed @ 2007-12-14  2:59 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin
  Cc: Rene Herman, Pavel Machek

Replace use of outb to "unused" diagnostic port 0x80 for time delay
with udelay based time delay on x86_64 architecture machines.  Fix for
bugs 9511 and 6307 in bugzilla, plus bugs reported in
bugzilla.redhat.com.

Derived from suggestion (that didn't compile) by Pavel Machek, and
tested, also based on measurements of typical timings of out's
collated by Rene Herman from many in the community.

This patch fixes a number of bugs known to cause problems on HP
Pavilion dv9000z and dv6000z laptops - in the form of solid freezes
when hwclock is used to show or set the time.  Also, it potentially
improves bus utilization on SMP machines, by using a waiting process
that doesn't tie up the ISA/LPC bus for 1 or 2 microseconds.

i386 family fixes (completely parallel) were not included, considering
that such machines might involve more risk of problems on legacy machines.

Signed-off-by: David P. Reed <dpreed@reed.com>

Index: linux-2.6/arch/x86/boot/compressed/misc_64.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/compressed/misc_64.c
+++ linux-2.6/arch/x86/boot/compressed/misc_64.c
@@ -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)
Index: linux-2.6/include/asm/io_64.h
===================================================================
--- linux-2.6.orig/include/asm/io_64.h
+++ linux-2.6/include/asm/io_64.h
@@ -1,6 +1,7 @@
  #ifndef _ASM_IO_H
  #define _ASM_IO_H

+#include <linux/delay.h>

  /*
   * This file contains the definitions for the x86 IO instructions
@@ -15,19 +16,7 @@
   * mistake somewhere.
   */

-/*
- * Thanks to James van Artsdalen for a better timing-fix than
- * the two short jumps: using outb's to a nonexistent port seems
- * to guarantee better timings even on fast machines.
- *
- * On the other hand, I'd like to be sure of a non-existent port:
- * I feel a bit unsafe about using 0x80 (should be safe, though)
- *
- *             Linus
- */
-
- /*
-  *  Bit simplified and optimized by Jan Hubicka
+/*   Bit simplified and optimized by Jan Hubicka
    *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
    *
    *  isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added,
@@ -35,36 +24,36 @@
    *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
    */

-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-
+/* the following delays are really conservative, at least for modern 
machines */
  #ifdef REALLY_SLOW_IO
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO 
__SLOW_DOWN_IO __SLOW_DOWN_IO
+#define _IOPORT_PAUSE_DELAY 10
  #else
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
+#define _IOPORT_PAUSE_DELAY 2
  #endif

  /*
   * Talk about misusing macros..
   */
-#define __OUT1(s,x) \
+#define __OUT1(s, x) \
  static inline void out##s(unsigned x value, unsigned short port) {

-#define __OUT2(s,s1,s2) \
-__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
-
-#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));} \
+#define __OUT2(s, s1, s2) \
+  __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" : : "a" (value), 
"Nd" \
+(port));
+
+#define __OUT(s, s1, x) \
+__OUT1(s, x) __OUT2(s, s1, "w") } \
+ __OUT1(s##_p, x) __OUT2(s, s1, "w") udelay(_IOPORT_PAUSE_DELAY); } \

  #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"
+#define __IN2(s, s1, s2) \
+__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") udelay(_IOPORT_PAUSE_DELAY); return _v; } \

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


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14  2:59                 ` [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
@ 2007-12-14  7:49                   ` Yinghai Lu
  2007-12-14  9:45                   ` Rene Herman
                                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 243+ messages in thread
From: Yinghai Lu @ 2007-12-14  7:49 UTC (permalink / raw)
  To: David P. Reed
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Rene Herman, Pavel Machek

On Dec 13, 2007 6:59 PM, David P. Reed <dpreed@reed.com> wrote:
> Replace use of outb to "unused" diagnostic port 0x80 for time delay
> with udelay based time delay on x86_64 architecture machines.  Fix for
> bugs 9511 and 6307 in bugzilla, plus bugs reported in
> bugzilla.redhat.com.
>
> Derived from suggestion (that didn't compile) by Pavel Machek, and
> tested, also based on measurements of typical timings of out's
> collated by Rene Herman from many in the community.
>
> This patch fixes a number of bugs known to cause problems on HP
> Pavilion dv9000z and dv6000z laptops - in the form of solid freezes
> when hwclock is used to show or set the time.  Also, it potentially
> improves bus utilization on SMP machines, by using a waiting process
> that doesn't tie up the ISA/LPC bus for 1 or 2 microseconds.
>
> i386 family fixes (completely parallel) were not included, considering
> that such machines might involve more risk of problems on legacy machines.
>
> Signed-off-by: David P. Reed <dpreed@reed.com>
>
> Index: linux-2.6/arch/x86/boot/compressed/misc_64.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/boot/compressed/misc_64.c
> +++ linux-2.6/arch/x86/boot/compressed/misc_64.c
> @@ -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)
> Index: linux-2.6/include/asm/io_64.h
> ===================================================================
> --- linux-2.6.orig/include/asm/io_64.h
> +++ linux-2.6/include/asm/io_64.h

include/asm-x64/io_64.h ?

YH

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14  2:59                 ` [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
  2007-12-14  7:49                   ` Yinghai Lu
@ 2007-12-14  9:45                   ` Rene Herman
  2007-12-14 14:23                     ` Ingo Molnar
  2007-12-14 10:51                   ` Andi Kleen
                                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-14  9:45 UTC (permalink / raw)
  To: David P. Reed, Alan Cox
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Pavel Machek

[-- Attachment #1: Type: text/plain, Size: 2598 bytes --]

On 14-12-07 03:59, David P. Reed wrote:

> Replace use of outb to "unused" diagnostic port 0x80 for time delay
> with udelay based time delay on x86_64 architecture machines.  Fix for
> bugs 9511 and 6307 in bugzilla, plus bugs reported in
> bugzilla.redhat.com.
> 
> Derived from suggestion (that didn't compile) by Pavel Machek, and
> tested, also based on measurements of typical timings of out's
> collated by Rene Herman from many in the community.
> 
> This patch fixes a number of bugs known to cause problems on HP
> Pavilion dv9000z and dv6000z laptops - in the form of solid freezes
> when hwclock is used to show or set the time.  Also, it potentially
> improves bus utilization on SMP machines, by using a waiting process
> that doesn't tie up the ISA/LPC bus for 1 or 2 microseconds.
> 
> i386 family fixes (completely parallel) were not included, considering
> that such machines might involve more risk of problems on legacy machines.

Here's the corresponding 32-bit patch. Applies fine to (and works on) 
v2.6.23.x as well after un-uniting the paths...

I do believe it would be better to do both; x86-64 machines can run 32-bit 
kernels fine and might certainly in the form of generic (installer) kernels 
and the like so if it's a fix lets fix it across the board -- the 2 us delay 
is going to be enough for everything out there, certainly given that _0_ is 
normally enough. With the arches just merged, minimising diferences should 
be a goal in itself I guess.

One thing though -- I believe we want to adjust the loops_per_jiffy default 
to make sure this works, or would work, pre-calibration as well? Not really 
sure how needed it is, but bogomips is defined as

	bogomips = loops_per_jiffy / (500000 / HZ)
			<=>
	loops_per_jiffy = bogomips * (500000 / HZ)

which with assuming any machine above 1G isn't affected by any of this and 
bogomips coming out to 2 * MHz on anything I myself have run linux on might 
suggest that

	loops_per_jiffy = 2 * 1000 * (500000 / HZ) = 1000000000 / HZ

could possibly be a sane if very large default? Alan?

diff --git a/init/main.c b/init/main.c
index 9def935..6d41771 100644
--- a/init/main.c
+++ b/init/main.c
@@ -229,10 +229,9 @@ static int __init obsolete_checksetup(char *line)
  }

  /*
- * This should be approx 2 Bo*oMips to start (note initial shift), and will
- * still work even if initially too large, it will just take slightly longer
+ * Initial value roughly corresponds to a 1 GHz CPU
   */
-unsigned long loops_per_jiffy = (1<<12);
+unsigned long loops_per_jiffy = 1000000000 / HZ;

  EXPORT_SYMBOL(loops_per_jiffy);

[-- Attachment #2: v24-port80.diff --]
[-- Type: text/plain, Size: 1783 bytes --]

From: Pavel Machek <pavel@ucw.cz>

32-bit part of the port 0x80 delay replacement.

diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
index b74d60d..288e162 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc_32.c
@@ -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)
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index fe881cd..9abc215 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -3,6 +3,7 @@
 
 #include <linux/string.h>
 #include <linux/compiler.h>
+#include <linux/delay.h>
 
 /*
  * This file contains the definitions for the x86 IO instructions
@@ -17,17 +18,6 @@
  * mistake somewhere.
  */
 
-/*
- * Thanks to James van Artsdalen for a better timing-fix than
- * the two short jumps: using outb's to a nonexistent port seems
- * to guarantee better timings even on fast machines.
- *
- * On the other hand, I'd like to be sure of a non-existent port:
- * I feel a bit unsafe about using 0x80 (should be safe, though)
- *
- *		Linus
- */
-
  /*
   *  Bit simplified and optimized by Jan Hubicka
   *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
@@ -252,7 +242,7 @@ static inline void flush_write_buffers(void)
 
 static inline void native_io_delay(void)
 {
-	asm volatile("outb %%al,$0x80" : : : "memory");
+	udelay(2);
 }
 
 #if defined(CONFIG_PARAVIRT)

^ permalink raw reply related	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14  2:59                 ` [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
  2007-12-14  7:49                   ` Yinghai Lu
  2007-12-14  9:45                   ` Rene Herman
@ 2007-12-14 10:51                   ` Andi Kleen
  2007-12-14 11:11                     ` David P. Reed
  2007-12-14 13:15                   ` Ingo Molnar
  2007-12-14 16:08                   ` Avi Kivity
  4 siblings, 1 reply; 243+ messages in thread
From: Andi Kleen @ 2007-12-14 10:51 UTC (permalink / raw)
  To: David P. Reed
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Rene Herman, Pavel Machek

"David P. Reed" <dpreed@reed.com> writes:
>
> i386 family fixes (completely parallel) were not included, considering
> that such machines might involve more risk of problems on legacy machines.

They're needed because lots of people fomr some reason still boot 32bit kernels
on 64bit machines.
> +#define __OUT(s, s1, x) \

> +__OUT1(s, x) __OUT2(s, s1, "w") } \
> + __OUT1(s##_p, x) __OUT2(s, s1, "w") udelay(_IOPORT_PAUSE_DELAY); } \

With the additional call this should be completely out of line now to save 
code size. Similar for the in variant.

-Andi


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 10:51                   ` Andi Kleen
@ 2007-12-14 11:11                     ` David P. Reed
  0 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2007-12-14 11:11 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Rene Herman, Pavel Machek



Andi Kleen wrote:
> "
> With the additional call this should be completely out of line now to save 
> code size. Similar for the in variant.
>
>
>   
Sure.  Want me to make a new patch with the _p croutines out-of-line?

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14  2:59                 ` [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
                                     ` (2 preceding siblings ...)
  2007-12-14 10:51                   ` Andi Kleen
@ 2007-12-14 13:15                   ` Ingo Molnar
  2007-12-14 13:24                     ` Ingo Molnar
                                       ` (3 more replies)
  2007-12-14 16:08                   ` Avi Kivity
  4 siblings, 4 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-14 13:15 UTC (permalink / raw)
  To: David P. Reed
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Rene Herman, Pavel Machek


* David P. Reed <dpreed@reed.com> wrote:

> Replace use of outb to "unused" diagnostic port 0x80 for time delay 
> with udelay based time delay on x86_64 architecture machines.  Fix for 
> bugs 9511 and 6307 in bugzilla, plus bugs reported in 
> bugzilla.redhat.com.
>
> Derived from suggestion (that didn't compile) by Pavel Machek, and 
> tested, also based on measurements of typical timings of out's 
> collated by Rene Herman from many in the community.
>
> This patch fixes a number of bugs known to cause problems on HP
> Pavilion dv9000z and dv6000z laptops - in the form of solid freezes
> when hwclock is used to show or set the time.  Also, it potentially
> improves bus utilization on SMP machines, by using a waiting process
> that doesn't tie up the ISA/LPC bus for 1 or 2 microseconds.
>
> i386 family fixes (completely parallel) were not included, considering 
> that such machines might involve more risk of problems on legacy 
> machines.

wow, cool fix! (I remember that there were other systems as well that 
are affected by port 0x80 muckery - i thought we had removed port 0x80 
accesses long ago.)

how about the simpler fix below, as a first-level approach? We can then 
remove the _p in/out sequences after this.

this is also something for v2.6.24 merging.

	Ingo

----------------------------->
Subject: x86: fix in/out_p delays
From: Ingo Molnar <mingo@elte.hu>

Debugged by David P. Reed <dpreed@reed.com>.

Do not use port 0x80, it can cause crashes, see:

 http://bugzilla.kernel.org/show_bug.cgi?id=6307
 http://bugzilla.kernel.org/show_bug.cgi?id=9511

instead of just removing _p postfixes en masse, lets just first
remove the 0x80 port usage, then remove any unnecessary _p io ops
gradually. It's more debuggable this way.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/boot/compressed/misc_32.c |    8 ++++----
 arch/x86/boot/compressed/misc_64.c |    8 ++++----
 arch/x86/kernel/quirks.c           |    9 +++++++++
 include/asm-x86/io_32.h            |    5 +----
 include/asm-x86/io_64.h            |    5 +----
 5 files changed, 19 insertions(+), 16 deletions(-)

Index: linux-x86.q/arch/x86/boot/compressed/misc_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_32.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_32.c
@@ -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)
Index: linux-x86.q/arch/x86/boot/compressed/misc_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_64.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_64.c
@@ -275,10 +275,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)
Index: linux-x86.q/arch/x86/kernel/quirks.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/quirks.c
+++ linux-x86.q/arch/x86/kernel/quirks.c
@@ -6,6 +6,15 @@
 
 #include <asm/hpet.h>
 
+/*
+ * Some legacy devices need delays for IN/OUT sequences. Most are
+ * probably not needed but it's the safest to just do this short delay:
+ */
+void native_io_delay(void)
+{
+	udelay(1);
+}
+
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
 
 static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
Index: linux-x86.q/include/asm-x86/io_32.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_32.h
+++ linux-x86.q/include/asm-x86/io_32.h
@@ -250,10 +250,7 @@ static inline void flush_write_buffers(v
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
Index: linux-x86.q/include/asm-x86/io_64.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_64.h
+++ linux-x86.q/include/asm-x86/io_64.h
@@ -35,10 +35,7 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 13:15                   ` Ingo Molnar
@ 2007-12-14 13:24                     ` Ingo Molnar
  2007-12-14 13:47                       ` Ingo Molnar
  2007-12-14 13:42                     ` Rene Herman
                                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-14 13:24 UTC (permalink / raw)
  To: David P. Reed
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Rene Herman, Pavel Machek


* Ingo Molnar <mingo@elte.hu> wrote:

> wow, cool fix! (I remember that there were other systems as well that 
> are affected by port 0x80 muckery - i thought we had removed port 0x80 
> accesses long ago.)
> 
> how about the simpler fix below, as a first-level approach? We can 
> then remove the _p in/out sequences after this.
> 
> this is also something for v2.6.24 merging.

updated patch attached. (from the MakeItBuild'n'Stuff dept)

	Ingo

-------------->
Subject: x86: fix in/out_p delays
From: Ingo Molnar <mingo@elte.hu>

Debugged by David P. Reed <dpreed@reed.com>.

Do not use port 0x80, it can cause crashes, see:

 http://bugzilla.kernel.org/show_bug.cgi?id=6307
 http://bugzilla.kernel.org/show_bug.cgi?id=9511

instead of just removing _p postfixes en masse, lets just first
remove the 0x80 port usage, then remove any unnecessary _p io ops
gradually. It's more debuggable this way.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/boot/compressed/misc_32.c |    8 ++++----
 arch/x86/boot/compressed/misc_64.c |    8 ++++----
 arch/x86/kernel/quirks.c           |   10 ++++++++++
 include/asm-x86/io_32.h            |    5 +----
 include/asm-x86/io_64.h            |    5 +----
 5 files changed, 20 insertions(+), 16 deletions(-)

Index: linux-x86.q/arch/x86/boot/compressed/misc_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_32.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_32.c
@@ -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)
Index: linux-x86.q/arch/x86/boot/compressed/misc_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_64.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_64.c
@@ -275,10 +275,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)
Index: linux-x86.q/arch/x86/kernel/quirks.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/quirks.c
+++ linux-x86.q/arch/x86/kernel/quirks.c
@@ -3,9 +3,19 @@
  */
 #include <linux/pci.h>
 #include <linux/irq.h>
+#include <linux/delay.h>
 
 #include <asm/hpet.h>
 
+/*
+ * Some legacy devices need delays for IN/OUT sequences. Most are
+ * probably not needed but it's the safest to just do this short delay:
+ */
+void native_io_delay(void)
+{
+	udelay(1);
+}
+
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
 
 static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
Index: linux-x86.q/include/asm-x86/io_32.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_32.h
+++ linux-x86.q/include/asm-x86/io_32.h
@@ -250,10 +250,7 @@ static inline void flush_write_buffers(v
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
Index: linux-x86.q/include/asm-x86/io_64.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_64.h
+++ linux-x86.q/include/asm-x86/io_64.h
@@ -35,10 +35,7 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 13:15                   ` Ingo Molnar
  2007-12-14 13:24                     ` Ingo Molnar
@ 2007-12-14 13:42                     ` Rene Herman
  2007-12-14 14:03                       ` Ingo Molnar
  2007-12-14 18:02                     ` H. Peter Anvin
  2007-12-15 23:00                     ` Pavel Machek
  3 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-14 13:42 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar,
	H. Peter Anvin, Pavel Machek, Alan Cox

On 14-12-07 14:15, Ingo Molnar wrote:

> wow, cool fix! (I remember that there were other systems as well that 
> are affected by port 0x80 muckery - i thought we had removed port 0x80 
> accesses long ago.)
> 
> how about the simpler fix below, as a first-level approach? We can then 
> remove the _p in/out sequences after this.

Your version does the same thing that the version from Pavel/David does for 
32-bit at least.

> +/*
> + * Some legacy devices need delays for IN/OUT sequences. Most are
> + * probably not needed but it's the safest to just do this short delay:
> + */
> +void native_io_delay(void)
> +{
> +	udelay(1);
> +}

Also note the thread(s) on LKML where 2 us was decided to be a nicely 
conservative value:

http://lkml.org/lkml/2007/12/12/309

Also see: http://lkml.org/lkml/2007/12/14/72

And also: http://lkml.org/lkml/2007/12/12/221

As such, please wait a bit for a fuller resolution. We're still discussing this.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 13:24                     ` Ingo Molnar
@ 2007-12-14 13:47                       ` Ingo Molnar
  2007-12-14 14:41                         ` Ingo Molnar
  0 siblings, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-14 13:47 UTC (permalink / raw)
  To: David P. Reed
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Rene Herman, Pavel Machek


* Ingo Molnar <mingo@elte.hu> wrote:

> updated patch attached. (from the MakeItBuild'n'Stuff dept)

the one below is against current upstream. (previous ones were against 
x86.git)

	Ingo

------------------->
Subject: x86: fix in/out_p delays
From: Ingo Molnar <mingo@elte.hu>

Debugged by David P. Reed <dpreed@reed.com>.

Do not use port 0x80, it can cause crashes, see:

 http://bugzilla.kernel.org/show_bug.cgi?id=6307
 http://bugzilla.kernel.org/show_bug.cgi?id=9511

instead of just removing _p postfixes en masse, lets just first
remove the 0x80 port usage, then remove any unnecessary _p io ops
gradually. It's more debuggable this way.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/boot/compressed/misc_32.c |    8 ++++----
 arch/x86/boot/compressed/misc_64.c |    8 ++++----
 arch/x86/kernel/quirks.c           |   10 ++++++++++
 include/asm-x86/io_32.h            |    5 +----
 include/asm-x86/io_64.h            |   14 +++++---------
 5 files changed, 24 insertions(+), 21 deletions(-)

Index: linux-x86.q/arch/x86/boot/compressed/misc_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_32.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_32.c
@@ -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)
Index: linux-x86.q/arch/x86/boot/compressed/misc_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_64.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_64.c
@@ -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)
Index: linux-x86.q/arch/x86/kernel/quirks.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/quirks.c
+++ linux-x86.q/arch/x86/kernel/quirks.c
@@ -3,9 +3,19 @@
  */
 #include <linux/pci.h>
 #include <linux/irq.h>
+#include <linux/delay.h>
 
 #include <asm/hpet.h>
 
+/*
+ * Some legacy devices need delays for IN/OUT sequences. Most are
+ * probably not needed but it's the safest to just do this short delay:
+ */
+void native_io_delay(void)
+{
+	udelay(1);
+}
+
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
 
 static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
Index: linux-x86.q/include/asm-x86/io_32.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_32.h
+++ linux-x86.q/include/asm-x86/io_32.h
@@ -250,10 +250,7 @@ static inline void flush_write_buffers(v
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
Index: linux-x86.q/include/asm-x86/io_64.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_64.h
+++ linux-x86.q/include/asm-x86/io_64.h
@@ -35,13 +35,7 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-
-#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
-#endif
+extern void native_io_delay(void);
 
 /*
  * Talk about misusing macros..
@@ -54,7 +48,8 @@ __asm__ __volatile__ ("out" #s " %" s1 "
 
 #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##_p,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); \
+native_io_delay(); } \
 
 #define __IN1(s) \
 static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
@@ -64,7 +59,8 @@ __asm__ __volatile__ ("in" #s " %" s2 "1
 
 #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; } \
+__IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; \
+native_io_delay(); } \
 
 #define __INS(s) \
 static inline void ins##s(unsigned short port, void * addr, unsigned long count) \

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 13:42                     ` Rene Herman
@ 2007-12-14 14:03                       ` Ingo Molnar
  2007-12-14 14:10                         ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-14 14:03 UTC (permalink / raw)
  To: Rene Herman
  Cc: David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar,
	H. Peter Anvin, Pavel Machek, Alan Cox


* Rene Herman <rene.herman@gmail.com> wrote:

> On 14-12-07 14:15, Ingo Molnar wrote:
>
>> wow, cool fix! (I remember that there were other systems as well that are 
>> affected by port 0x80 muckery - i thought we had removed port 0x80 
>> accesses long ago.)
>>
>> how about the simpler fix below, as a first-level approach? We can 
>> then remove the _p in/out sequences after this.
>
> Your version does the same thing that the version from Pavel/David 
> does for 32-bit at least.

well, if you carefully look at the code it's not the "same" but a 
similar but cleaner thing - it moves this quirk out of a common include 
file. I take back the "simpler" characterisation - my patch indeed ended 
up being almost the same as David's.

>> +/*
>> + * Some legacy devices need delays for IN/OUT sequences. Most are
>> + * probably not needed but it's the safest to just do this short delay:
>> + */
>> +void native_io_delay(void)
>> +{
>> +	udelay(1);
>> +}
>
> Also note the thread(s) on LKML where 2 us was decided to be a nicely 
> conservative value:

yep, i have updated the delay to 2 usecs. The latest patch is below, as 
queued up in x86.git. (not yet queued up for .24 - it's pending testing 
and more feedback, etc.)

	Ingo

----------------->
Subject: x86: fix in_p/out_p crashes
From: David P. Reed <dpreed@reed.com>

Do not use port 0x80, it can cause crashes, see:

 http://bugzilla.kernel.org/show_bug.cgi?id=6307
 http://bugzilla.kernel.org/show_bug.cgi?id=9511

Replace use of outb to "unused" diagnostic port 0x80 for time delay
with udelay based time delay on x86_64 architecture machines.  Fix for
bugs 9511 and 6307 in bugzilla, plus bugs reported in
bugzilla.redhat.com.

Derived from suggestion (that didn't compile) by Pavel Machek, and
tested, also based on measurements of typical timings of out's
collated by Rene Herman from many in the community.

This patch fixes a number of bugs known to cause problems on HP
Pavilion dv9000z and dv6000z laptops - in the form of solid freezes
when hwclock is used to show or set the time.  Also, it potentially
improves bus utilization on SMP machines, by using a waiting process
that doesn't tie up the ISA/LPC bus for 1 or 2 microseconds.

[ mingo@elte.hu: minor restructuring, 32-bit support. ]

Signed-off-by: David P. Reed <dpreed@reed.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/boot/compressed/misc_32.c |    8 ++++----
 arch/x86/boot/compressed/misc_64.c |    8 ++++----
 arch/x86/kernel/quirks.c           |   10 ++++++++++
 include/asm-x86/io_32.h            |    5 +----
 include/asm-x86/io_64.h            |   14 +++++---------
 5 files changed, 24 insertions(+), 21 deletions(-)

Index: linux-x86.q/arch/x86/boot/compressed/misc_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_32.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_32.c
@@ -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)
Index: linux-x86.q/arch/x86/boot/compressed/misc_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_64.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_64.c
@@ -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)
Index: linux-x86.q/arch/x86/kernel/quirks.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/quirks.c
+++ linux-x86.q/arch/x86/kernel/quirks.c
@@ -3,9 +3,19 @@
  */
 #include <linux/pci.h>
 #include <linux/irq.h>
+#include <linux/delay.h>
 
 #include <asm/hpet.h>
 
+/*
+ * Some legacy devices need delays for IN/OUT sequences. Most are
+ * probably not needed but it's the safest to just do this short delay:
+ */
+void native_io_delay(void)
+{
+	udelay(2);
+}
+
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
 
 static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
Index: linux-x86.q/include/asm-x86/io_32.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_32.h
+++ linux-x86.q/include/asm-x86/io_32.h
@@ -250,10 +250,7 @@ static inline void flush_write_buffers(v
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
Index: linux-x86.q/include/asm-x86/io_64.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_64.h
+++ linux-x86.q/include/asm-x86/io_64.h
@@ -35,13 +35,7 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-
-#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
-#endif
+extern void native_io_delay(void);
 
 /*
  * Talk about misusing macros..
@@ -54,7 +48,8 @@ __asm__ __volatile__ ("out" #s " %" s1 "
 
 #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##_p,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); \
+native_io_delay(); } \
 
 #define __IN1(s) \
 static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
@@ -64,7 +59,8 @@ __asm__ __volatile__ ("in" #s " %" s2 "1
 
 #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; } \
+__IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; \
+native_io_delay(); } \
 
 #define __INS(s) \
 static inline void ins##s(unsigned short port, void * addr, unsigned long count) \

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 14:03                       ` Ingo Molnar
@ 2007-12-14 14:10                         ` Rene Herman
  2007-12-14 14:21                           ` Ingo Molnar
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-14 14:10 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar,
	H. Peter Anvin, Pavel Machek, Alan Cox

On 14-12-07 15:03, Ingo Molnar wrote:

> yep, i have updated the delay to 2 usecs. The latest patch is below, as 
> queued up in x86.git. (not yet queued up for .24 - it's pending testing 
> and more feedback, etc.)

Yes, I'd like feedback on the initial value thing:

http://lkml.org/lkml/2007/12/14/72

and Alan's comments here:

http://lkml.org/lkml/2007/12/12/221

And as to testing -- good luck finding a machine that cares at all ;-)

Rene.



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 14:10                         ` Rene Herman
@ 2007-12-14 14:21                           ` Ingo Molnar
  0 siblings, 0 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-14 14:21 UTC (permalink / raw)
  To: Rene Herman
  Cc: David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar,
	H. Peter Anvin, Pavel Machek, Alan Cox


* Rene Herman <rene.herman@gmail.com> wrote:

> And as to testing -- good luck finding a machine that cares at all ;-)

actually, there's a whole lot more testing angle to a change like this 
than ancient boxes.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14  9:45                   ` Rene Herman
@ 2007-12-14 14:23                     ` Ingo Molnar
  2007-12-14 14:36                       ` Rene Herman
  2007-12-15 22:59                       ` Pavel Machek
  0 siblings, 2 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-14 14:23 UTC (permalink / raw)
  To: Rene Herman
  Cc: David P. Reed, Alan Cox, Thomas Gleixner, linux-kernel,
	Ingo Molnar, H. Peter Anvin, Pavel Machek


* Rene Herman <rene.herman@gmail.com> wrote:

> --- a/init/main.c
> +++ b/init/main.c
> @@ -229,10 +229,9 @@ static int __init obsolete_checksetup(char *line)
>  }
>
>  /*
> - * This should be approx 2 Bo*oMips to start (note initial shift), and will
> - * still work even if initially too large, it will just take slightly longer
> + * Initial value roughly corresponds to a 1 GHz CPU
>   */
> -unsigned long loops_per_jiffy = (1<<12);
> +unsigned long loops_per_jiffy = 1000000000 / HZ;
>
>  EXPORT_SYMBOL(loops_per_jiffy);

this is a factor of ~2400 increase - this will take an eternity to boot 
on any older CPU.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 14:23                     ` Ingo Molnar
@ 2007-12-14 14:36                       ` Rene Herman
  2007-12-14 14:46                         ` Ingo Molnar
  2007-12-15 22:59                       ` Pavel Machek
  1 sibling, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-14 14:36 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Rene Herman, David P. Reed, Alan Cox, Thomas Gleixner,
	linux-kernel, Ingo Molnar, H. Peter Anvin, Pavel Machek

On 14-12-07 15:23, Ingo Molnar wrote:

> * Rene Herman <rene.herman@gmail.com> wrote:
> 
>> --- a/init/main.c
>> +++ b/init/main.c
>> @@ -229,10 +229,9 @@ static int __init obsolete_checksetup(char *line)
>>  }
>>
>>  /*
>> - * This should be approx 2 Bo*oMips to start (note initial shift), and will
>> - * still work even if initially too large, it will just take slightly longer
>> + * Initial value roughly corresponds to a 1 GHz CPU
>>   */
>> -unsigned long loops_per_jiffy = (1<<12);
>> +unsigned long loops_per_jiffy = 1000000000 / HZ;
>>
>>  EXPORT_SYMBOL(loops_per_jiffy);
> 
> this is a factor of ~2400 increase - this will take an eternity to boot 
> on any older CPU.

Only any outb_p's used before loops_per_jiffy is calibrated are affected.

This pre-calibation thing is what's historically held this change back (it's 
been discussed dozens of times before). At 4096, not any machine is going to 
have an appreciable delay before calibration when switching from the outb to 
  0x80.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 13:47                       ` Ingo Molnar
@ 2007-12-14 14:41                         ` Ingo Molnar
  0 siblings, 0 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-14 14:41 UTC (permalink / raw)
  To: David P. Reed
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Rene Herman, Pavel Machek


> > updated patch attached. (from the MakeItBuild'n'Stuff dept)
> 
> the one below is against current upstream. (previous ones were against 
> x86.git)

the last version is the one below. Pending further discussion and 
testing. And David, i nominate your fix as the coolest Linux kernel fix 
of 2007 :-)

	Ingo

-------------------------------->

Subject: x86: fix in_p/out_p crashes
From: David P. Reed <dpreed@reed.com>

Do not use port 0x80, it can cause crashes, see:

 http://bugzilla.kernel.org/show_bug.cgi?id=6307
 http://bugzilla.kernel.org/show_bug.cgi?id=9511

Replace use of outb to "unused" diagnostic port 0x80 for time delay
with udelay based time delay on x86_64 architecture machines.  Fix for
bugs 9511 and 6307 in bugzilla, plus bugs reported in
bugzilla.redhat.com.

Derived from suggestion (that didn't compile) by Pavel Machek, and
tested, also based on measurements of typical timings of out's
collated by Rene Herman from many in the community.

This patch fixes a number of bugs known to cause problems on HP
Pavilion dv9000z and dv6000z laptops - in the form of solid freezes
when hwclock is used to show or set the time.  Also, it potentially
improves bus utilization on SMP machines, by using a waiting process
that doesn't tie up the ISA/LPC bus for 1 or 2 microseconds.

[ mingo@elte.hu: minor restructuring, 32-bit support. ]

Signed-off-by: David P. Reed <dpreed@reed.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/boot/compressed/misc_32.c |    8 ++++----
 arch/x86/boot/compressed/misc_64.c |    8 ++++----
 arch/x86/kernel/quirks.c           |   10 ++++++++++
 include/asm-x86/io_32.h            |    5 +----
 include/asm-x86/io_64.h            |   14 +++++---------
 5 files changed, 24 insertions(+), 21 deletions(-)

Index: linux-x86.q/arch/x86/boot/compressed/misc_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_32.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_32.c
@@ -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)
Index: linux-x86.q/arch/x86/boot/compressed/misc_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_64.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_64.c
@@ -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)
Index: linux-x86.q/arch/x86/kernel/quirks.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/quirks.c
+++ linux-x86.q/arch/x86/kernel/quirks.c
@@ -3,9 +3,19 @@
  */
 #include <linux/pci.h>
 #include <linux/irq.h>
+#include <linux/delay.h>
 
 #include <asm/hpet.h>
 
+/*
+ * Some legacy devices need delays for IN/OUT sequences. Most are
+ * probably not needed but it's the safest to just do this short delay:
+ */
+void native_io_delay(void)
+{
+	udelay(2);
+}
+
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
 
 static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
Index: linux-x86.q/include/asm-x86/io_32.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_32.h
+++ linux-x86.q/include/asm-x86/io_32.h
@@ -250,10 +250,7 @@ static inline void flush_write_buffers(v
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
Index: linux-x86.q/include/asm-x86/io_64.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_64.h
+++ linux-x86.q/include/asm-x86/io_64.h
@@ -35,13 +35,7 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-
-#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
-#endif
+extern void native_io_delay(void);
 
 /*
  * Talk about misusing macros..
@@ -54,7 +48,8 @@ __asm__ __volatile__ ("out" #s " %" s1 "
 
 #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##_p,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); \
+native_io_delay(); } \
 
 #define __IN1(s) \
 static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
@@ -64,7 +59,8 @@ __asm__ __volatile__ ("in" #s " %" s2 "1
 
 #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; } \
+__IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; \
+native_io_delay(); } \
 
 #define __INS(s) \
 static inline void ins##s(unsigned short port, void * addr, unsigned long count) \

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 14:36                       ` Rene Herman
@ 2007-12-14 14:46                         ` Ingo Molnar
  2007-12-14 14:56                           ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-14 14:46 UTC (permalink / raw)
  To: Rene Herman
  Cc: David P. Reed, Alan Cox, Thomas Gleixner, linux-kernel,
	Ingo Molnar, H. Peter Anvin, Pavel Machek


* Rene Herman <rene.herman@gmail.com> wrote:

>>>  /*
>>> - * This should be approx 2 Bo*oMips to start (note initial shift), and will
>>> - * still work even if initially too large, it will just take slightly longer
>>> + * Initial value roughly corresponds to a 1 GHz CPU
>>>   */
>>> -unsigned long loops_per_jiffy = (1<<12);
>>> +unsigned long loops_per_jiffy = 1000000000 / HZ;
>>>
>>>  EXPORT_SYMBOL(loops_per_jiffy);
>>
>> this is a factor of ~2400 increase - this will take an eternity to boot on 
>> any older CPU.
>
> Only any outb_p's used before loops_per_jiffy is calibrated are 
> affected.

yes - but there are a couple of early udelays, which would thus be 
affected.

> This pre-calibation thing is what's historically held this change back 
> (it's been discussed dozens of times before). At 4096, not any machine 
> is going to have an appreciable delay before calibration when 
> switching from the outb to 0x80.

i dont think this should matter: old systems that truly _need_ the ISA 
delay will be slow enough to not trip up. (nor are they really affected 
by these early delays - the delays were more for crappy ISA devices that 
get initialized later down, when the delay loop is already calibrated)

modern systems learned to depend on the PCI write posting side-effects 
of port 0x80 activities - those wont be helped by this initialization 
change either. That is a far more serious concern.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 14:46                         ` Ingo Molnar
@ 2007-12-14 14:56                           ` Rene Herman
  2007-12-14 18:36                             ` Alan Cox
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-14 14:56 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Rene Herman, David P. Reed, Alan Cox, Thomas Gleixner,
	linux-kernel, Ingo Molnar, H. Peter Anvin, Pavel Machek

On 14-12-07 15:46, Ingo Molnar wrote:

> * Rene Herman <rene.herman@gmail.com> wrote:
> 
>>>>  /*
>>>> - * This should be approx 2 Bo*oMips to start (note initial shift), and will
>>>> - * still work even if initially too large, it will just take slightly longer
>>>> + * Initial value roughly corresponds to a 1 GHz CPU
>>>>   */
>>>> -unsigned long loops_per_jiffy = (1<<12);
>>>> +unsigned long loops_per_jiffy = 1000000000 / HZ;
>>>>
>>>>  EXPORT_SYMBOL(loops_per_jiffy);
>>> this is a factor of ~2400 increase - this will take an eternity to boot on 
>>> any older CPU.
>> Only any outb_p's used before loops_per_jiffy is calibrated are 
>> affected.
> 
> yes - but there are a couple of early udelays, which would thus be 
> affected.

True. At the moment though they're just always not delaying anywhere close 
the intended amount (on anything with more than 2 bogomips). Pre-calibration 
all this stuff is just broken it seems.

>> This pre-calibation thing is what's historically held this change back 
>> (it's been discussed dozens of times before). At 4096, not any machine 
>> is going to have an appreciable delay before calibration when 
>> switching from the outb to 0x80.
> 
> i dont think this should matter: old systems that truly _need_ the ISA 
> delay will be slow enough to not trip up. (nor are they really affected 
> by these early delays - the delays were more for crappy ISA devices that 
> get initialized later down, when the delay loop is already calibrated)

8253 (DMAC) and 8254 (PIT) have been reported in earlier versions of the 
thread. By Alan, I believe.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14  2:59                 ` [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
                                     ` (3 preceding siblings ...)
  2007-12-14 13:15                   ` Ingo Molnar
@ 2007-12-14 16:08                   ` Avi Kivity
  2007-12-15  2:13                     ` David P. Reed
  4 siblings, 1 reply; 243+ messages in thread
From: Avi Kivity @ 2007-12-14 16:08 UTC (permalink / raw)
  To: David P. Reed
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Rene Herman, Pavel Machek, kvm-devel

David P. Reed wrote:
> Replace use of outb to "unused" diagnostic port 0x80 for time delay
> with udelay based time delay on x86_64 architecture machines.  Fix for
> bugs 9511 and 6307 in bugzilla, plus bugs reported in
> bugzilla.redhat.com.
>
> Derived from suggestion (that didn't compile) by Pavel Machek, and
> tested, also based on measurements of typical timings of out's
> collated by Rene Herman from many in the community.
>
> This patch fixes a number of bugs known to cause problems on HP
> Pavilion dv9000z and dv6000z laptops - in the form of solid freezes
> when hwclock is used to show or set the time.  Also, it potentially
> improves bus utilization on SMP machines, by using a waiting process
> that doesn't tie up the ISA/LPC bus for 1 or 2 microseconds.
>

kvm will forward a virtual machine's writes to port 0x80 to the real 
port.  The reason is that the write is much faster than exiting and 
emulating it; the difference is measurable when compiling kernels.

Now if the cause is simply writing to port 0x80, then we must stop doing 
that.  But if the reason is the back-to-back writes, when we can keep 
it, since the other writes will be trapped by kvm and emulated.  Do you 
which is the case?

-- 
Any sufficiently difficult bug is indistinguishable from a feature.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 13:15                   ` Ingo Molnar
  2007-12-14 13:24                     ` Ingo Molnar
  2007-12-14 13:42                     ` Rene Herman
@ 2007-12-14 18:02                     ` H. Peter Anvin
  2007-12-14 18:23                       ` Rene Herman
                                         ` (2 more replies)
  2007-12-15 23:00                     ` Pavel Machek
  3 siblings, 3 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-14 18:02 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar,
	Rene Herman, Pavel Machek

Ingo Molnar wrote:
> 
> wow, cool fix! (I remember that there were other systems as well that 
> are affected by port 0x80 muckery - i thought we had removed port 0x80 
> accesses long ago.)
> 
> how about the simpler fix below, as a first-level approach? We can then 
> remove the _p in/out sequences after this.
> 

I believe this will suffer from the issue that was raised: this will use 
udelay() long before loop calibration (and no, we can't just "be 
conservative" since there is no "conservative" value we can use.)

Worse, I suspect that at least the PIT, which may need to be used for 
udelay calibration, is one of the devices that may be affected.  I have 
seen the Verilog for a contemporary chipset, and it can only access the 
PIT once per microsecond -- this actually has to do with the definition 
of the PIT; some of the PIT operations are ill-defined if allowed at a 
higher frequency than the PIT clock.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 18:02                     ` H. Peter Anvin
@ 2007-12-14 18:23                       ` Rene Herman
  2007-12-14 21:06                       ` Pavel Machek
  2007-12-15  7:43                       ` Ingo Molnar
  2 siblings, 0 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-14 18:23 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Ingo Molnar, David P. Reed, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Pavel Machek

On 14-12-07 19:02, H. Peter Anvin wrote:

> I believe this will suffer from the issue that was raised: this will use
> udelay() long before loop calibration (and no, we can't just "be 
> conservative" since there is no "conservative" value we can use.)
> 
> Worse, I suspect that at least the PIT, which may need to be used for 
> udelay calibration, is one of the devices that may be affected.  I have 
> seen the Verilog for a contemporary chipset, and it can only access the 
> PIT once per microsecond -- this actually has to do with the definition 
> of the PIT; some of the PIT operations are ill-defined if allowed at a 
> higher frequency than the PIT clock.

Was reported before indeed:

http://linux.derkeiler.com/Mailing-Lists/Kernel/2003-09/5764.html

Rene.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 14:56                           ` Rene Herman
@ 2007-12-14 18:36                             ` Alan Cox
  2007-12-14 18:48                               ` H. Peter Anvin
  2007-12-14 21:05                               ` Pavel Machek
  0 siblings, 2 replies; 243+ messages in thread
From: Alan Cox @ 2007-12-14 18:36 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, Rene Herman, David P. Reed, Thomas Gleixner,
	linux-kernel, Ingo Molnar, H. Peter Anvin, Pavel Machek

> > i dont think this should matter: old systems that truly _need_ the ISA 
> > delay will be slow enough to not trip up. (nor are they really affected 
> > by these early delays - the delays were more for crappy ISA devices that 
> > get initialized later down, when the delay loop is already calibrated)
> 
> 8253 (DMAC) and 8254 (PIT) have been reported in earlier versions of the 
> thread. By Alan, I believe.

They've been seen to be problems up to PII era machines. I'm not aware of
any newer than that with this problem. We also don't need to touch the
DMAC that early anyway that I can see - just the PIT.

In fact if we have a fast processor we have a TSC and APIC so we don't
need the PIT ?

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 18:36                             ` Alan Cox
@ 2007-12-14 18:48                               ` H. Peter Anvin
  2007-12-14 21:05                               ` Pavel Machek
  1 sibling, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-14 18:48 UTC (permalink / raw)
  To: Alan Cox
  Cc: Rene Herman, Ingo Molnar, David P. Reed, Thomas Gleixner,
	linux-kernel, Ingo Molnar, Pavel Machek

Alan Cox wrote:
>>> i dont think this should matter: old systems that truly _need_ the ISA 
>>> delay will be slow enough to not trip up. (nor are they really affected 
>>> by these early delays - the delays were more for crappy ISA devices that 
>>> get initialized later down, when the delay loop is already calibrated)
>> 8253 (DMAC) and 8254 (PIT) have been reported in earlier versions of the 
>> thread. By Alan, I believe.
> 
> They've been seen to be problems up to PII era machines. I'm not aware of
> any newer than that with this problem. We also don't need to touch the
> DMAC that early anyway that I can see - just the PIT.
> 
> In fact if we have a fast processor we have a TSC and APIC so we don't
> need the PIT ?

Well, the TSC may be unstable and the APIC may be disabled.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 18:36                             ` Alan Cox
  2007-12-14 18:48                               ` H. Peter Anvin
@ 2007-12-14 21:05                               ` Pavel Machek
  1 sibling, 0 replies; 243+ messages in thread
From: Pavel Machek @ 2007-12-14 21:05 UTC (permalink / raw)
  To: Alan Cox
  Cc: Rene Herman, Ingo Molnar, David P. Reed, Thomas Gleixner,
	linux-kernel, Ingo Molnar, H. Peter Anvin

On Fri 2007-12-14 18:36:26, Alan Cox wrote:
> > > i dont think this should matter: old systems that truly _need_ the ISA 
> > > delay will be slow enough to not trip up. (nor are they really affected 
> > > by these early delays - the delays were more for crappy ISA devices that 
> > > get initialized later down, when the delay loop is already calibrated)
> > 
> > 8253 (DMAC) and 8254 (PIT) have been reported in earlier versions of the 
> > thread. By Alan, I believe.
> 
> They've been seen to be problems up to PII era machines. I'm not aware of
> any newer than that with this problem. We also don't need to touch the
> DMAC that early anyway that I can see - just the PIT.
> 
> In fact if we have a fast processor we have a TSC and APIC so we don't
> need the PIT ?

It is still good to be able to disable APIC/TSC. Neither are
particulary reliable time sources.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 18:02                     ` H. Peter Anvin
  2007-12-14 18:23                       ` Rene Herman
@ 2007-12-14 21:06                       ` Pavel Machek
  2007-12-14 22:13                         ` H. Peter Anvin
  2007-12-15  7:43                       ` Ingo Molnar
  2 siblings, 1 reply; 243+ messages in thread
From: Pavel Machek @ 2007-12-14 21:06 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Ingo Molnar, David P. Reed, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman

On Fri 2007-12-14 10:02:57, H. Peter Anvin wrote:
> Ingo Molnar wrote:
>> wow, cool fix! (I remember that there were other systems as well that are 
>> affected by port 0x80 muckery - i thought we had removed port 0x80 
>> accesses long ago.)
>> how about the simpler fix below, as a first-level approach? We can then 
>> remove the _p in/out sequences after this.
>
> I believe this will suffer from the issue that was raised: this will use 
> udelay() long before loop calibration (and no, we can't just "be 
> conservative" since there is no "conservative" value we can use.)

?? Just initialize bogomips to 6GHz equivalent... and we are fine
until 6GHz cpus come out.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 21:06                       ` Pavel Machek
@ 2007-12-14 22:13                         ` H. Peter Anvin
  2007-12-14 23:29                           ` Alan Cox
  2007-12-17 22:46                           ` Jan Engelhardt
  0 siblings, 2 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-14 22:13 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Ingo Molnar, David P. Reed, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman

Pavel Machek wrote:
> On Fri 2007-12-14 10:02:57, H. Peter Anvin wrote:
>> Ingo Molnar wrote:
>>> wow, cool fix! (I remember that there were other systems as well that are 
>>> affected by port 0x80 muckery - i thought we had removed port 0x80 
>>> accesses long ago.)
>>> how about the simpler fix below, as a first-level approach? We can then 
>>> remove the _p in/out sequences after this.
>> I believe this will suffer from the issue that was raised: this will use 
>> udelay() long before loop calibration (and no, we can't just "be 
>> conservative" since there is no "conservative" value we can use.)
> 
> ?? Just initialize bogomips to 6GHz equivalent... and we are fine
> until 6GHz cpus come out.

How long will that take to boot on a 386?

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 22:13                         ` H. Peter Anvin
@ 2007-12-14 23:29                           ` Alan Cox
  2007-12-15  3:04                             ` David P. Reed
                                               ` (2 more replies)
  2007-12-17 22:46                           ` Jan Engelhardt
  1 sibling, 3 replies; 243+ messages in thread
From: Alan Cox @ 2007-12-14 23:29 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Pavel Machek, Ingo Molnar, David P. Reed, Thomas Gleixner,
	linux-kernel, Ingo Molnar, Rene Herman

On Fri, 14 Dec 2007 14:13:46 -0800
"H. Peter Anvin" <hpa@zytor.com> wrote:

> Pavel Machek wrote:
> > On Fri 2007-12-14 10:02:57, H. Peter Anvin wrote:
> >> Ingo Molnar wrote:
> >>> wow, cool fix! (I remember that there were other systems as well that are 
> >>> affected by port 0x80 muckery - i thought we had removed port 0x80 
> >>> accesses long ago.)
> >>> how about the simpler fix below, as a first-level approach? We can then 
> >>> remove the _p in/out sequences after this.
> >> I believe this will suffer from the issue that was raised: this will use 
> >> udelay() long before loop calibration (and no, we can't just "be 
> >> conservative" since there is no "conservative" value we can use.)
> > 
> > ?? Just initialize bogomips to 6GHz equivalent... and we are fine
> > until 6GHz cpus come out.
> 
> How long will that take to boot on a 386?

Well the dumb approach to fix that would seem to be to initialise it to

	cpu->family   3 -> 50MHz 4 -> 300Mhz 5-> etc...

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 16:08                   ` Avi Kivity
@ 2007-12-15  2:13                     ` David P. Reed
  2007-12-15  2:20                         ` H. Peter Anvin
                                         ` (2 more replies)
  0 siblings, 3 replies; 243+ messages in thread
From: David P. Reed @ 2007-12-15  2:13 UTC (permalink / raw)
  To: Avi Kivity
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Rene Herman, Pavel Machek, kvm-devel

Avi Kivity wrote:
> kvm will forward a virtual machine's writes to port 0x80 to the real 
> port.  The reason is that the write is much faster than exiting and 
> emulating it; the difference is measurable when compiling kernels.
>
> Now if the cause is simply writing to port 0x80, then we must stop 
> doing that.  But if the reason is the back-to-back writes, when we can 
> keep it, since the other writes will be trapped by kvm and emulated.  
> Do you which is the case?
>
As for kvm, I don't have enough info to know anything about that.  Is 
there a test you'd like me to try?

I think you are also asking if the crash on these laptops is caused only 
by back-to-back writes.  Actually, it doesn't seem to matter if they are 
back to back.  I can cause the crash if the writes to 80 are very much 
spread out in time - it seems only to matter how many of them get 
executed - almost as if there is a buffer overflow.  (And of course if 
you do back to back writes to other ports that are apparently fully 
unused, such as 0xED on my machine, no crash occurs).

I believe (though no one seems to have confirming documentation from the 
chipset or motherboard vendor) that port 80 is actually functional for 
some unknown function on these machines.   (They do respond to "in" 
instructions faster than a bus cycle abort does - more evidence).

I searched the DSDT to see if there is any evidence of an ACPI use for 
this port, but found nothing.





^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
@ 2007-12-15  2:20                         ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-15  2:20 UTC (permalink / raw)
  To: David P. Reed
  Cc: Avi Kivity, Thomas Gleixner, linux-kernel, Ingo Molnar,
	Rene Herman, Pavel Machek, kvm-devel

David P. Reed wrote:
> 
> I believe (though no one seems to have confirming documentation from the 
> chipset or motherboard vendor) that port 80 is actually functional for 
> some unknown function on these machines.   (They do respond to "in" 
> instructions faster than a bus cycle abort does - more evidence).
> 

This is normal.  IN from port 0x80 is used by the DMA address map chip.

As far as I understand, there are other laptops with the same chipset 
which don't have this problem, so it's likely either a motherboard or 
firmware issue.  My guess is that they probably let debugging code out 
in the field (trap port 0x80 in SMM, and then try to output it on some 
debugging bus.)

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
@ 2007-12-15  2:20                         ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-15  2:20 UTC (permalink / raw)
  To: David P. Reed
  Cc: kvm-devel, Rene Herman, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Avi Kivity, Ingo Molnar, Pavel Machek

David P. Reed wrote:
> 
> I believe (though no one seems to have confirming documentation from the 
> chipset or motherboard vendor) that port 80 is actually functional for 
> some unknown function on these machines.   (They do respond to "in" 
> instructions faster than a bus cycle abort does - more evidence).
> 

This is normal.  IN from port 0x80 is used by the DMA address map chip.

As far as I understand, there are other laptops with the same chipset 
which don't have this problem, so it's likely either a motherboard or 
firmware issue.  My guess is that they probably let debugging code out 
in the field (trap port 0x80 in SMM, and then try to output it on some 
debugging bus.)

	-hpa

-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 23:29                           ` Alan Cox
@ 2007-12-15  3:04                             ` David P. Reed
  2007-12-15  5:45                               ` H. Peter Anvin
  2007-12-15  8:08                             ` Paul Rolland
  2007-12-17 21:04                             ` Rene Herman
  2 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2007-12-15  3:04 UTC (permalink / raw)
  To: Alan Cox
  Cc: H. Peter Anvin, Pavel Machek, Ingo Molnar, Thomas Gleixner,
	linux-kernel, Ingo Molnar, Rene Herman

Just a thought for a way to fix the "very early" timing needed to set up 
udelay to work in a way that works on all machines.  Perhaps we haven't 
exploited the BIOS enough:  The PC BIOS since the PC AT (286)  has 
always had a standard "countdown timer" way to delay for n microseconds, 
which as far as I know still works.   This can be used to measure the 
speed of a delay loop, without using ANY in/out instructions directly 
(the ones in the BIOS are presumably correctly delayed...).

So first thing in the boot sequence, one can calibrate a timing loop 
using this technique, and save the value to be used for all the "early" 
stuff.

Here's skeleton code from old ASM code I found lying around in my 
archives to use BIOS to measure how many unrolled short jumps can 
execute in 10 msec.  Note that it can run without knowing anything 
whatsoever about port timing.

haltbyte db 0

calibrate:
    les bx,haltbyte ; address of halt flag into es:bx
    mov ax,8300h
    sub cx,cx
    mov dx,10000 ; 10 msec. in cx:dx
    int 15h
    jc bad
    sub dx,dx
    sub cx,cx ; decrement counter in dx:cx
tloop:
    jmp short $+2 ; 10 short jmps
    jmp short $+2
    jmp short $+2
    jmp short $+2
    jmp short $+2
    jmp short $+2
    jmp short $+2
    jmp short $+2
    jmp short $+2
    test haltbyte
    loopz tloop
    jnz done
    dec dx
    jnz tloop

" overflowed 32 bits ... never happens, cancel BIOS event wait.
    mov ax,8301h
    int 15h
    jmp error
 
done:
    mov ax,cx
    negl
" here dx:ax contains 32 bit loop count corresponding to 10 msec.
    ret ; return 32-bit value


Doc on function 83h of int 15h should be available online.
   

Alan Cox wrote:
> On Fri, 14 Dec 2007 14:13:46 -0800
> "H. Peter Anvin" <hpa@zytor.com> wrote:
>
>   
>> Pavel Machek wrote:
>>     
>>> On Fri 2007-12-14 10:02:57, H. Peter Anvin wrote:
>>>       
>>>> Ingo Molnar wrote:
>>>>         
>>>>> wow, cool fix! (I remember that there were other systems as well that are 
>>>>> affected by port 0x80 muckery - i thought we had removed port 0x80 
>>>>> accesses long ago.)
>>>>> how about the simpler fix below, as a first-level approach? We can then 
>>>>> remove the _p in/out sequences after this.
>>>>>           
>>>> I believe this will suffer from the issue that was raised: this will use 
>>>> udelay() long before loop calibration (and no, we can't just "be 
>>>> conservative" since there is no "conservative" value we can use.)
>>>>         
>>> ?? Just initialize bogomips to 6GHz equivalent... and we are fine
>>> until 6GHz cpus come out.
>>>       
>> How long will that take to boot on a 386?
>>     
>
> Well the dumb approach to fix that would seem to be to initialise it to
>
> 	cpu->family   3 -> 50MHz 4 -> 300Mhz 5-> etc...
>
> Alan
>
>   

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15  3:04                             ` David P. Reed
@ 2007-12-15  5:45                               ` H. Peter Anvin
  2007-12-15 17:17                                 ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-15  5:45 UTC (permalink / raw)
  To: David P. Reed
  Cc: Alan Cox, Pavel Machek, Ingo Molnar, Thomas Gleixner,
	linux-kernel, Ingo Molnar, Rene Herman

David P. Reed wrote:
> Just a thought for a way to fix the "very early" timing needed to set up 
> udelay to work in a way that works on all machines.  Perhaps we haven't 
> exploited the BIOS enough:  The PC BIOS since the PC AT (286)  has 
> always had a standard "countdown timer" way to delay for n microseconds, 
> which as far as I know still works.   This can be used to measure the 
> speed of a delay loop, without using ANY in/out instructions directly 
> (the ones in the BIOS are presumably correctly delayed...).

If we enter from the 32-bit entrypoint, we already don't have access to 
the BIOS, though.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 18:02                     ` H. Peter Anvin
  2007-12-14 18:23                       ` Rene Herman
  2007-12-14 21:06                       ` Pavel Machek
@ 2007-12-15  7:43                       ` Ingo Molnar
  2007-12-15  7:58                         ` Rene Herman
  2 siblings, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-15  7:43 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar,
	Rene Herman, Pavel Machek


* H. Peter Anvin <hpa@zytor.com> wrote:

> I believe this will suffer from the issue that was raised: this will 
> use udelay() long before loop calibration (and no, we can't just "be 
> conservative" since there is no "conservative" value we can use.)
>
> Worse, I suspect that at least the PIT, which may need to be used for 
> udelay calibration, is one of the devices that may be affected.  I 
> have seen the Verilog for a contemporary chipset, and it can only 
> access the PIT once per microsecond -- this actually has to do with 
> the definition of the PIT; some of the PIT operations are ill-defined 
> if allowed at a higher frequency than the PIT clock.

i think the native_io_delay() in quirks.c signals the obvious solution: 
a DMI (or otherwise) driven quirk that activates a port 0x80 based delay 
on such boards. Combined with an iodelay=port80 boot option as well 
perhaps, just in case someone hits a system that is not blacklisted yet. 
This way such crazy broken hardware can be mapped correctly - like we 
map such quirks in every other case. Perhaps even do this workaround on 
the PIT driver level. Instead of perpetuating the superstition of port 
80 forever.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15  7:43                       ` Ingo Molnar
@ 2007-12-15  7:58                         ` Rene Herman
  2007-12-15 13:27                           ` Ingo Molnar
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-15  7:58 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: H. Peter Anvin, David P. Reed, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman, Pavel Machek, Alan Cox

[-- Attachment #1: Type: text/plain, Size: 1624 bytes --]

On 15-12-07 08:43, Ingo Molnar wrote:

> * H. Peter Anvin <hpa@zytor.com> wrote:
> 
>> I believe this will suffer from the issue that was raised: this will 
>> use udelay() long before loop calibration (and no, we can't just "be 
>> conservative" since there is no "conservative" value we can use.)
>>
>> Worse, I suspect that at least the PIT, which may need to be used for 
>> udelay calibration, is one of the devices that may be affected.  I 
>> have seen the Verilog for a contemporary chipset, and it can only 
>> access the PIT once per microsecond -- this actually has to do with 
>> the definition of the PIT; some of the PIT operations are ill-defined 
>> if allowed at a higher frequency than the PIT clock.
> 
> i think the native_io_delay() in quirks.c signals the obvious solution: 
> a DMI (or otherwise) driven quirk that activates a port 0x80 based delay 
> on such boards. Combined with an iodelay=port80 boot option as well 
> perhaps, just in case someone hits a system that is not blacklisted yet. 
> This way such crazy broken hardware can be mapped correctly - like we 
> map such quirks in every other case. Perhaps even do this workaround on 
> the PIT driver level. Instead of perpetuating the superstition of port 
> 80 forever.

The issue is -- how do you safely replace the outb pre-loops_per_jiffy 
calibration? I'm currently running with the attached hack (not submitted, 
only for 32-bit and discussion) the idea of which might be the best we can do?

(And the broken is the hardware that can't take writes to port 0x80, not the 
other way around. It's a well-known legacy PC thing).

Rene.


[-- Attachment #2: native_io_delay-switch.diff --]
[-- Type: text/plain, Size: 1912 bytes --]

diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
index b74d60d..288e162 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc_32.c
@@ -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)
diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c
index 8a322c9..c95d313 100644
--- a/arch/x86/kernel/time_32.c
+++ b/arch/x86/kernel/time_32.c
@@ -222,6 +222,19 @@ void __init hpet_time_init(void)
 	time_init_hook();
 }
 
+static void port_io_delay(void)
+{
+	asm volatile ("outb %%al, $0x80": : : "memory");
+}
+
+static void udelay_io_delay(void)
+{
+	udelay(2);
+}
+
+void (*native_io_delay)(void) = port_io_delay;
+EXPORT_SYMBOL(native_io_delay);
+
 /*
  * This is called directly from init code; we must delay timer setup in the
  * HPET case as we can't make the decision to turn on HPET this early in the
@@ -233,5 +246,7 @@ void __init hpet_time_init(void)
 void __init time_init(void)
 {
 	tsc_init();
+	if (!tsc_disable)
+		native_io_delay = udelay_io_delay;
 	late_time_init = choose_time_init();
 }
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index fe881cd..1b73f49 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -250,10 +250,7 @@ static inline void flush_write_buffers(void)
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void (*native_io_delay)(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>

^ permalink raw reply related	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 23:29                           ` Alan Cox
  2007-12-15  3:04                             ` David P. Reed
@ 2007-12-15  8:08                             ` Paul Rolland
  2007-12-15  8:13                               ` Rene Herman
  2007-12-15 20:26                               ` [PATCH] x86_64: " H. Peter Anvin
  2007-12-17 21:04                             ` Rene Herman
  2 siblings, 2 replies; 243+ messages in thread
From: Paul Rolland @ 2007-12-15  8:08 UTC (permalink / raw)
  To: Alan Cox
  Cc: H. Peter Anvin, Pavel Machek, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman, rol

Hello,

On Fri, 14 Dec 2007 23:29:55 +0000
Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:

> On Fri, 14 Dec 2007 14:13:46 -0800
> "H. Peter Anvin" <hpa@zytor.com> wrote:
> 
> > Pavel Machek wrote:
> > > On Fri 2007-12-14 10:02:57, H. Peter Anvin wrote:
> > 
> > How long will that take to boot on a 386?
> 
> Well the dumb approach to fix that would seem to be to initialise it to
> 
> 	cpu->family   3 -> 50MHz 4 -> 300Mhz 5-> etc...

Just an idea : from what I've read, the problem (port 80 hanging) only occurs
on 'modern' machines... So why not :
 - use port 80 for old CPUs (PII, PIII) where it has never really been
   a problem,
 - use the cpu->family to do a best match for CPU freq
thus we could avoid increasing boot time too much...

Paul



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15  8:08                             ` Paul Rolland
@ 2007-12-15  8:13                               ` Rene Herman
  2007-12-15 20:27                                 ` H. Peter Anvin
  2007-12-15 20:26                               ` [PATCH] x86_64: " H. Peter Anvin
  1 sibling, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-15  8:13 UTC (permalink / raw)
  To: Paul Rolland
  Cc: Alan Cox, H. Peter Anvin, Pavel Machek, Ingo Molnar,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar,
	Rene Herman, rol

On 15-12-07 09:08, Paul Rolland wrote:
> Hello,
> 
> On Fri, 14 Dec 2007 23:29:55 +0000
> Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> 
>> On Fri, 14 Dec 2007 14:13:46 -0800
>> "H. Peter Anvin" <hpa@zytor.com> wrote:
>>
>>> Pavel Machek wrote:
>>>> On Fri 2007-12-14 10:02:57, H. Peter Anvin wrote:
>>> How long will that take to boot on a 386?
>> Well the dumb approach to fix that would seem to be to initialise it to
>>
>> 	cpu->family   3 -> 50MHz 4 -> 300Mhz 5-> etc...
> 
> Just an idea : from what I've read, the problem (port 80 hanging) only occurs
> on 'modern' machines... So why not :
>  - use port 80 for old CPUs (PII, PIII) where it has never really been
>    a problem,
>  - use the cpu->family to do a best match for CPU freq
> thus we could avoid increasing boot time too much...

Yes, just posted a Patch-For-Comments that switches on the availability of a 
TSC (tsc_init sets tsc_disable also for !cpu_has_tsc) which would mean that 
only really old stuff would be using the outb still. A TSC is really all we 
need to have a sensible udelay().

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15  7:58                         ` Rene Herman
@ 2007-12-15 13:27                           ` Ingo Molnar
  2007-12-15 14:01                             ` Rene Herman
  2007-12-15 14:29                             ` Alan Cox
  0 siblings, 2 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-15 13:27 UTC (permalink / raw)
  To: Rene Herman
  Cc: H. Peter Anvin, David P. Reed, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman, Pavel Machek, Alan Cox


* Rene Herman <rene.herman@gmail.com> wrote:

> The issue is -- how do you safely replace the outb pre-loops_per_jiffy 
> calibration? I'm currently running with the attached hack (not 
> submitted, only for 32-bit and discussion) the idea of which might be 
> the best we can do?

how about doing a known-NOP chipset cycle? For example:

  inb(PIC_SLAVE_IMR)

? I.e. instead of trying to find an unused port, lets try to find a 
known-used platform register that has no side-effects if read. Use it 
unconditionally during early bootup and change it to an udelay after 
calibration. (or use it after early bootup too if a boot parameter has 
been specified) Or something like this.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 13:27                           ` Ingo Molnar
@ 2007-12-15 14:01                             ` Rene Herman
  2007-12-15 20:25                               ` H. Peter Anvin
  2007-12-15 14:29                             ` Alan Cox
  1 sibling, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-15 14:01 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: H. Peter Anvin, David P. Reed, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman, Pavel Machek, Alan Cox

On 15-12-07 14:27, Ingo Molnar wrote:

> * Rene Herman <rene.herman@gmail.com> wrote:
> 
>> The issue is -- how do you safely replace the outb pre-loops_per_jiffy 
>> calibration? I'm currently running with the attached hack (not 
>> submitted, only for 32-bit and discussion) the idea of which might be 
>> the best we can do?
> 
> how about doing a known-NOP chipset cycle? For example:
> 
>   inb(PIC_SLAVE_IMR)

An inb is annoying in that it clobbers register al (well, with an inline 
native_io_delay it is at least) and more importantly -- the timing of this 
is going to vary wildly. We really want a register that is effectively 
guaranteed to be unused so that it dies on ISA/LPC or we might get _much_ 
faster PCI only decodes. Even reading port 0x80 itself varies wildly:

http://lkml.org/lkml/2007/12/12/309

> ? I.e. instead of trying to find an unused port, lets try to find a 
> known-used platform register that has no side-effects if read. Use it 
> unconditionally during early bootup and change it to an udelay after 
> calibration. (or use it after early bootup too if a boot parameter has 
> been specified) Or something like this.

It's really going to have to be a known _un_used register and (the write 
direction of) port 0x80 is used exactly for that reason. Port 0xed is a 
known "alternate diagnostic port" used by Phoenix BIOSes at least but Peter 
Anvin reported trouble with that one -- probably for the outb direction but 
assuming that means something was in fact responding, we'd have the same 
timing problem.

I believe we have two "good" options:

1) port 0xed was tested by the current reporter and found to be safe (and 
provide slow enough timing). If DMI  based quirk hacks are available soon 
enough we can switch 0x80 to 0xed based on it. Are they?

2) the thing I posted in the message replied to where immediately after 
tsc_init() (which is before the PIT init) we switch to udelay() if we have a 
TSC which is ofcourse anything modern.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 13:27                           ` Ingo Molnar
  2007-12-15 14:01                             ` Rene Herman
@ 2007-12-15 14:29                             ` Alan Cox
  2007-12-15 16:19                               ` David P. Reed
  1 sibling, 1 reply; 243+ messages in thread
From: Alan Cox @ 2007-12-15 14:29 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Rene Herman, H. Peter Anvin, David P. Reed, Thomas Gleixner,
	linux-kernel, Ingo Molnar, Rene Herman, Pavel Machek

On Sat, 15 Dec 2007 14:27:25 +0100
Ingo Molnar <mingo@elte.hu> wrote:

> 
> * Rene Herman <rene.herman@gmail.com> wrote:
> 
> > The issue is -- how do you safely replace the outb pre-loops_per_jiffy 
> > calibration? I'm currently running with the attached hack (not 
> > submitted, only for 32-bit and discussion) the idea of which might be 
> > the best we can do?
> 
> how about doing a known-NOP chipset cycle? For example:
> 
>   inb(PIC_SLAVE_IMR)

It needs tobe a different chip to the main one (or macrocell anyway) - so
PIC for PIT and vice versa. However since we know 0x80 works for
everything on the planet but this one specifies of laptop which seems to
need a firmware update its a very high risk approach.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 14:29                             ` Alan Cox
@ 2007-12-15 16:19                               ` David P. Reed
  2007-12-15 16:48                                 ` Mark Lord
  2007-12-15 17:51                                 ` Alan Cox
  0 siblings, 2 replies; 243+ messages in thread
From: David P. Reed @ 2007-12-15 16:19 UTC (permalink / raw)
  To: Alan Cox
  Cc: Ingo Molnar, Rene Herman, H. Peter Anvin, Thomas Gleixner,
	linux-kernel, Ingo Molnar, Rene Herman, Pavel Machek

I understand the risks of such a fundamental change, and it may be only 
a minor concern, but I did also point out that using an unused port 
causes the bus to be tied up for a microsecond or two, which matters on 
a fast SMP machine.

Of course all the other concerns you guys are worrying about are really 
important.  I don't want to break anybody's running systems...  I'd like 
to see my machine run smoothly, and all the other machines that may or 
may not have this problem (google "hwclock freeze" to see that I'm far 
from alone - I just have persevered in "bisecting" this problem with 
kernel tweaks for months, whereas the others did not or did not know how).

By the way, this laptop is really nice for Linux in lots of ways.  Dual 
drives, so I set it up with software RAID for reliability, dual 64-bit 
processors, fast 3D graphics, etc.  Great battery life.  Just one last 
kernel issue.

I also note that curent machines like the problem machine have ACPI, and 
maybe those would be the ones that vendors might start to define port 80 
to mean something. As I noted, it /seems/ to be only when ACPI is turned 
on that this problem happens on my machine - that's when the OS starts 
to be involved in servicing various things, so it suggests that maybe 
things change about port 80's unknown function on these machines when 
ACPI is servicing the system management code (that's not something I 
have been able to verify).

My belief is that my machine has some device that is responding to port 
80 by doing something.  And that something requires some other program 
to "service" port 80 in some way.  But it sure would be nice to know.   
I can't personally sand off the top of the chipset to put probes into it 
- so my normal approach of putting a logic analyzer on the bus doesn't work.

PS: If I have time, I may try to build Rene's port 80 test for Windows 
and run it under WinXP on this machine (I still have a crappy little 
partition that boots it).   If it freezes the same way, it's almost 
certain a design "feature", and if it doesn't freeze, we might suspect 
that there is compensating logic in either Windows ACPI code or some way 
that windows "sets up" the machine.

Alan Cox wrote:
> On Sat, 15 Dec 2007 14:27:25 +0100
> Ingo Molnar <mingo@elte.hu> wrote:
>
>   
>> * Rene Herman <rene.herman@gmail.com> wrote:
>>
>>     
>>> The issue is -- how do you safely replace the outb pre-loops_per_jiffy 
>>> calibration? I'm currently running with the attached hack (not 
>>> submitted, only for 32-bit and discussion) the idea of which might be 
>>> the best we can do?
>>>       
>> how about doing a known-NOP chipset cycle? For example:
>>
>>   inb(PIC_SLAVE_IMR)
>>     
>
> It needs tobe a different chip to the main one (or macrocell anyway) - so
> PIC for PIT and vice versa. However since we know 0x80 works for
> everything on the planet but this one specifies of laptop which seems to
> need a firmware update its a very high risk approach.
>
> Alan
>
>   

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 16:19                               ` David P. Reed
@ 2007-12-15 16:48                                 ` Mark Lord
  2007-12-15 17:51                                 ` Alan Cox
  1 sibling, 0 replies; 243+ messages in thread
From: Mark Lord @ 2007-12-15 16:48 UTC (permalink / raw)
  To: David P. Reed
  Cc: Alan Cox, Ingo Molnar, Rene Herman, H. Peter Anvin,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman,
	Pavel Machek

This change seems rather unlikely for 2.6.24 at this point (high risk),
but could be good for 2.6.25.

One thing it should probably have for the early going,
is a simple way to turn it on/off at boot time,
so that we don't have people "stuck" unable to run
the test kernels should something weird happen.

Alan / David / Ingo,

What do you think of the idea of a *temporary* boot flag for this,
something like port80=on/off (pick a suitable name) ?

Cheers

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15  5:45                               ` H. Peter Anvin
@ 2007-12-15 17:17                                 ` David P. Reed
  2007-12-15 17:46                                   ` Alan Cox
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2007-12-15 17:17 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Alan Cox, Pavel Machek, Ingo Molnar, Thomas Gleixner,
	linux-kernel, Ingo Molnar, Rene Herman



H. Peter Anvin wrote:
> David P. Reed wrote:
>> Just a thought for a way to fix the "very early" timing needed to set 
>> up udelay to work in a way that works on all machines.  Perhaps we 
>> haven't exploited the BIOS enough:  The PC BIOS since the PC AT 
>> (286)  has always had a standard "countdown timer" way to delay for n 
>> microseconds, which as far as I know still works.   This can be used 
>> to measure the speed of a delay loop, without using ANY in/out 
>> instructions directly (the ones in the BIOS are presumably correctly 
>> delayed...).
>
> If we enter from the 32-bit entrypoint, we already don't have access 
> to the BIOS, though.
>
My understanding is that the linux starts in real mode, and uses the 
BIOS for such things as reading the very first image.   
arch/x86/boot/main.c seems to use BIOS calls, and one can do what I 
wrote in C or asm.  Good place to measure the appropriate delay timing, 
and pass it on forward.  That's what I was suggesting, which is why I 
copied the ASM routine from my old code listing as I did.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 17:17                                 ` David P. Reed
@ 2007-12-15 17:46                                   ` Alan Cox
  2007-12-17 22:50                                     ` Jan Engelhardt
  0 siblings, 1 reply; 243+ messages in thread
From: Alan Cox @ 2007-12-15 17:46 UTC (permalink / raw)
  To: David P. Reed
  Cc: H. Peter Anvin, Pavel Machek, Ingo Molnar, Thomas Gleixner,
	linux-kernel, Ingo Molnar, Rene Herman

> My understanding is that the linux starts in real mode, and uses the 
> BIOS for such things as reading the very first image.   

Not always. We may enter from 32bit in some cases, and we may also not
have a PC BIOS in the first place.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 16:19                               ` David P. Reed
  2007-12-15 16:48                                 ` Mark Lord
@ 2007-12-15 17:51                                 ` Alan Cox
  1 sibling, 0 replies; 243+ messages in thread
From: Alan Cox @ 2007-12-15 17:51 UTC (permalink / raw)
  To: David P. Reed
  Cc: Ingo Molnar, Rene Herman, H. Peter Anvin, Thomas Gleixner,
	linux-kernel, Ingo Molnar, Rene Herman, Pavel Machek

> a minor concern, but I did also point out that using an unused port 
> causes the bus to be tied up for a microsecond or two, which matters on 
> a fast SMP machine.

And I did point out I'd found locking cases that may be relying upon this

> I also note that curent machines like the problem machine have ACPI, and 
> maybe those would be the ones that vendors might start to define port 80 
> to mean something. As I noted, it /seems/ to be only when ACPI is turned 

Port 0x80 means debug. You appear to have a laptop with some kind of
buggy firmware that wants a BIOS update. Everyone use 0x80 for debug -
its in the chipset hardware quite often.

> My belief is that my machine has some device that is responding to port 
> 80 by doing something.  And that something requires some other program 
> to "service" port 80 in some way.  But it sure would be nice to know.   
> I can't personally sand off the top of the chipset to put probes into it 
> - so my normal approach of putting a logic analyzer on the bus doesn't work.

Almost certainly a SMI trap.

> PS: If I have time, I may try to build Rene's port 80 test for Windows 
> and run it under WinXP on this machine 

That would be very interesting.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 14:01                             ` Rene Herman
@ 2007-12-15 20:25                               ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-15 20:25 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, David P. Reed, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman, Pavel Machek, Alan Cox

Rene Herman wrote:
> 
> It's really going to have to be a known _un_used register and (the write 
> direction of) port 0x80 is used exactly for that reason. Port 0xed is a 
> known "alternate diagnostic port" used by Phoenix BIOSes at least but 
> Peter Anvin reported trouble with that one -- probably for the outb 
> direction but assuming that means something was in fact responding, we'd 
> have the same timing problem.
> 

Yes, for the outbound direction.

> I believe we have two "good" options:
> 
> 1) port 0xed was tested by the current reporter and found to be safe 
> (and provide slow enough timing). If DMI  based quirk hacks are 
> available soon enough we can switch 0x80 to 0xed based on it. Are they?

DMI is just a data structure parked in memory, so it should at least be 
theoretically possible to get to it.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15  8:08                             ` Paul Rolland
  2007-12-15  8:13                               ` Rene Herman
@ 2007-12-15 20:26                               ` H. Peter Anvin
  2007-12-15 22:55                                 ` Pavel Machek
  2007-12-16  9:27                                 ` Ingo Molnar
  1 sibling, 2 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-15 20:26 UTC (permalink / raw)
  To: Paul Rolland
  Cc: Alan Cox, Pavel Machek, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman, rol

Paul Rolland wrote:
> Just an idea : from what I've read, the problem (port 80 hanging) only occurs
> on 'modern' machines...

It happens on *one single* "modern" machine...

Let's keep that in perspective.
	
	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15  8:13                               ` Rene Herman
@ 2007-12-15 20:27                                 ` H. Peter Anvin
  2007-12-15 23:26                                   ` [PATCH] x86: " Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-15 20:27 UTC (permalink / raw)
  To: Rene Herman
  Cc: Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman, rol

Rene Herman wrote:
> 
> Yes, just posted a Patch-For-Comments that switches on the availability 
> of a TSC (tsc_init sets tsc_disable also for !cpu_has_tsc) which would 
> mean that only really old stuff would be using the outb still. A TSC is 
> really all we need to have a sensible udelay().
> 

Uhm, no.  You have no clue what the speed of the TSC is until you have 
been able to calibrate it against a fixed timesource - like the PIT.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 20:26                               ` [PATCH] x86_64: " H. Peter Anvin
@ 2007-12-15 22:55                                 ` Pavel Machek
  2007-12-16  9:27                                 ` Ingo Molnar
  1 sibling, 0 replies; 243+ messages in thread
From: Pavel Machek @ 2007-12-15 22:55 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Paul Rolland, Alan Cox, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman, rol

On Sat 2007-12-15 12:26:26, H. Peter Anvin wrote:
> Paul Rolland wrote:
>> Just an idea : from what I've read, the problem (port 80 hanging) only 
>> occurs
>> on 'modern' machines...
>
> It happens on *one single* "modern" machine...
>
> Let's keep that in perspective.

it hurts on other machines (like debug leds being useless), and it may
be incorrect as soon as you insert leds-on-port-0x80-on-PCI card.

No, it is not critical but yes, I'd like to see it fixed.

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 14:23                     ` Ingo Molnar
  2007-12-14 14:36                       ` Rene Herman
@ 2007-12-15 22:59                       ` Pavel Machek
  1 sibling, 0 replies; 243+ messages in thread
From: Pavel Machek @ 2007-12-15 22:59 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Rene Herman, David P. Reed, Alan Cox, Thomas Gleixner,
	linux-kernel, Ingo Molnar, H. Peter Anvin

On Fri 2007-12-14 15:23:55, Ingo Molnar wrote:
> 
> * Rene Herman <rene.herman@gmail.com> wrote:
> 
> > --- a/init/main.c
> > +++ b/init/main.c
> > @@ -229,10 +229,9 @@ static int __init obsolete_checksetup(char *line)
> >  }
> >
> >  /*
> > - * This should be approx 2 Bo*oMips to start (note initial shift), and will
> > - * still work even if initially too large, it will just take slightly longer
> > + * Initial value roughly corresponds to a 1 GHz CPU
> >   */
> > -unsigned long loops_per_jiffy = (1<<12);
> > +unsigned long loops_per_jiffy = 1000000000 / HZ;
> >
> >  EXPORT_SYMBOL(loops_per_jiffy);
> 
> this is a factor of ~2400 increase - this will take an eternity to boot 
> on any older CPU.

I don't think we are using outb_p before loops_per_jiffy are
initialized -- I believe I'd see oopsen if we did. Factor 2400
increase is bad, but if it only converts 10x 1usec delay into 10x
24msec delay, it is not _that_ bad.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 13:15                   ` Ingo Molnar
                                       ` (2 preceding siblings ...)
  2007-12-14 18:02                     ` H. Peter Anvin
@ 2007-12-15 23:00                     ` Pavel Machek
  2007-12-15 23:04                       ` H. Peter Anvin
  3 siblings, 1 reply; 243+ messages in thread
From: Pavel Machek @ 2007-12-15 23:00 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar,
	H. Peter Anvin, Rene Herman

On Fri 2007-12-14 14:15:03, Ingo Molnar wrote:
> 
> * David P. Reed <dpreed@reed.com> wrote:
> 
> > Replace use of outb to "unused" diagnostic port 0x80 for time delay 
> > with udelay based time delay on x86_64 architecture machines.  Fix for 
> > bugs 9511 and 6307 in bugzilla, plus bugs reported in 
> > bugzilla.redhat.com.
> >
> > Derived from suggestion (that didn't compile) by Pavel Machek, and 
> > tested, also based on measurements of typical timings of out's 
> > collated by Rene Herman from many in the community.
> >
> > This patch fixes a number of bugs known to cause problems on HP
> > Pavilion dv9000z and dv6000z laptops - in the form of solid freezes
> > when hwclock is used to show or set the time.  Also, it potentially
> > improves bus utilization on SMP machines, by using a waiting process
> > that doesn't tie up the ISA/LPC bus for 1 or 2 microseconds.
> >
> > i386 family fixes (completely parallel) were not included, considering 
> > that such machines might involve more risk of problems on legacy 
> > machines.
> 
> wow, cool fix! (I remember that there were other systems as well that 
> are affected by port 0x80 muckery - i thought we had removed port 0x80 
> accesses long ago.)
> 
> how about the simpler fix below, as a first-level approach? We can then 
> remove the _p in/out sequences after this.
> 
> this is also something for v2.6.24 merging.

As much as I like this patch, I do not think it is suitable for
.24. Too risky, I'd say.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 23:00                     ` Pavel Machek
@ 2007-12-15 23:04                       ` H. Peter Anvin
  2007-12-16  9:40                         ` Ingo Molnar
  0 siblings, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-15 23:04 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Ingo Molnar, David P. Reed, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman

Pavel Machek wrote:
>>
>> this is also something for v2.6.24 merging.
> 
> As much as I like this patch, I do not think it is suitable for
> .24. Too risky, I'd say.
> 

No kidding!  We're talking about removing a hack that has been 
successful on thousands of pieces of hardware over 15 years because it 
breaks ONE machine.

If this should be done at all it should be done in the most careful 
manner possible.  2.6.25 would be an aggressive schedule.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* [PATCH] x86: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 20:27                                 ` H. Peter Anvin
@ 2007-12-15 23:26                                   ` Rene Herman
  2007-12-15 23:51                                     ` H. Peter Anvin
  2007-12-16  0:23                                     ` [PATCH] x86: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
  0 siblings, 2 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-15 23:26 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman, rol

[-- Attachment #1: Type: text/plain, Size: 2499 bytes --]

On 15-12-07 21:27, H. Peter Anvin wrote:

> Rene Herman wrote:
>>
>> Yes, just posted a Patch-For-Comments that switches on the 
>> availability of a TSC (tsc_init sets tsc_disable also for 
>> !cpu_has_tsc) which would mean that only really old stuff would be 
>> using the outb still. A TSC is really all we need to have a sensible 
>> udelay().
> 
> Uhm, no.  You have no clue what the speed of the TSC is until you have 
> been able to calibrate it against a fixed timesource - like the PIT.

Yes. Hnng. Okay, this is going nowhere in a hurry, so back to the very first 
suggestion in this thread. How about this? This allows to switch from port 
0x80 to port 0xed based on DMI.

David: I plugged in my own DMI values for testing, but obviously yours are 
needed. The values that are needed are retrieved by the "dmidecode" program 
which you will probably have installed (it might be in an sbin directory) or 
will be able to install through whatever package manager you use.

dmidecode -s baseboard-manufacturer
dmidecode -s baseboard-product-name

are the values you should plug into the .matches field in the dmi_system_id 
struct in this. It would be great if you could do that, test, and post back 
with those values. .ident should be a nice human name.

It's been tested on x86-32 and seems to work fine. It's not been tested on 
x86-64 but seems to stand a fair chance of working similarly.

It ofcourse remains possible to switch to a udelay() based method later on 
anyways but with all the pre-calibratin trouble, this might be the lowest 
risk method in the short run.

This is partly based on previous patches by Pavel Machek and David P. Reed.

I hope this is considered half-way correct/sane (note by the way that it's 
not a good idea to switch a "native_io_delay_port" value since plugging in a 
variable port would clobber register dx for every outb_p, which would then 
have to be reloaded for the next outb again). Comments appreciated.

Signed-off-by: Rene Herman <rene.herman@gmail.com>

  arch/x86/boot/compressed/misc_32.c |    8 ++---
  arch/x86/boot/compressed/misc_64.c |    8 ++---
  arch/x86/kernel/Makefile_32        |    2 -
  arch/x86/kernel/Makefile_64        |    2 -
  arch/x86/kernel/io_delay.c         |   53 
+++++++++++++++++++++++++++++++++++++
  arch/x86/kernel/setup_32.c         |    2 +
  arch/x86/kernel/setup_64.c         |    2 +
  include/asm-x86/io_32.h            |   17 ++---------
  include/asm-x86/io_64.h            |   23 ++++++----------


[-- Attachment #2: dmi-io_delay.diff --]
[-- Type: text/plain, Size: 7133 bytes --]

commit 4a7e75776c648102488a89dbfad516448830ab1a
Author: Rene Herman <rene.herman@gmail.com>
Date:   Sun Dec 16 00:24:32 2007 +0100

    foo

diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
index b74d60d..288e162 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc_32.c
@@ -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)
diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
index 6ea015a..43e5fcc 100644
--- a/arch/x86/boot/compressed/misc_64.c
+++ b/arch/x86/boot/compressed/misc_64.c
@@ -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)
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index a7bc93c..0cc1981 100644
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -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/
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64
index 5a88890..08a68f0 100644
--- a/arch/x86/kernel/Makefile_64
+++ b/arch/x86/kernel/Makefile_64
@@ -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/
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
new file mode 100644
index 0000000..1a2a856
--- /dev/null
+++ b/arch/x86/kernel/io_delay.c
@@ -0,0 +1,53 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+
+#define IO_DELAY(port) asm volatile ("outb %%al, %0" : : "N" ((port)))
+
+static void standard_io_delay(void)
+{
+	IO_DELAY(0x80);
+}
+
+static void alternate_io_delay(void)
+{
+	IO_DELAY(0xed);
+}
+
+void (*native_io_delay)(void) = standard_io_delay;
+
+void slow_down_io(void) {
+	native_io_delay();
+#ifdef REALLY_SLOW_IO
+	native_io_delay();
+	native_io_delay();
+	native_io_delay();
+#endif
+}
+EXPORT_SYMBOL(slow_down_io);
+
+static int __init dmi_alternate_io_delay(const struct dmi_system_id *id)
+{
+	printk(KERN_NOTICE "%s: using alternate I/O delay.\n", id->ident);
+	native_io_delay = alternate_io_delay;
+	return 0;
+}
+
+static struct dmi_system_id __initdata alternate_io_delay_dmi_table[] = {
+	{
+		.callback	= dmi_alternate_io_delay,
+		.ident		= "Gigabyte GA-7IXE4",
+		.matches	= {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
+			DMI_MATCH(DMI_BOARD_NAME, "7IXE4")
+		}
+	},
+	{
+	}
+};
+
+void __init io_delay_init(void)
+{
+	dmi_check_system(alternate_io_delay_dmi_table);
+}
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index e1e18c3..6c3a3b4 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -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	
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 30d94d1..ec976ed 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -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;
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index fe881cd..bf352e3 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -250,24 +250,13 @@ static inline void flush_write_buffers(void)
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void io_delay_init(void);
+extern void (*native_io_delay)(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
 #else
-
-static inline void slow_down_io(void) {
-	native_io_delay();
-#ifdef REALLY_SLOW_IO
-	native_io_delay();
-	native_io_delay();
-	native_io_delay();
-#endif
-}
-
+extern void slow_down_io(void);
 #endif
 
 #ifdef CONFIG_X86_NUMAQ
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index a037b07..486a110 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -35,13 +35,8 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-
-#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
-#endif
+extern void io_delay_init(void);
+extern void slow_down_io(void);
 
 /*
  * Talk about misusing macros..
@@ -50,21 +45,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) \

^ permalink raw reply related	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 23:26                                   ` [PATCH] x86: " Rene Herman
@ 2007-12-15 23:51                                     ` H. Peter Anvin
  2007-12-16  0:05                                       ` H. Peter Anvin
  2007-12-16 13:15                                       ` [PATCH] x86: provide a DMI based port 0x80 I/O delay override Rene Herman
  2007-12-16  0:23                                     ` [PATCH] x86: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
  1 sibling, 2 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-15 23:51 UTC (permalink / raw)
  To: Rene Herman
  Cc: Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman, rol

Rene Herman wrote:
> 
> I hope this is considered half-way correct/sane (note by the way that 
> it's not a good idea to switch a "native_io_delay_port" value since 
> plugging in a variable port would clobber register dx for every outb_p, 
> which would then have to be reloaded for the next outb again). Comments 
> appreciated.
> 

That actually wouldn't be that big of a deal.  Switching values in and 
out of registers is dirt cheap (and MUCH cheaper than an indirect 
function call) -- of course, if there is a reason to do it for 
paravirtualization then that's fine; we're talking about something that 
makes even the slowest CPU operation look speedy anyhow.

If in*_p and out*_p are out-of-lined then %dx would be dead anyway, and 
so there is even less reason to deal with it.

In theory we could use an alternatives section and patch the 
instruction, too; seems like way overkill, though.

Note, however, that your code doesn't deal with io_delay()'s in the boot 
code (arch/x86/boot) at all, nor (obviously) io_delay()'s in boot 
loaders.  In the boot code, access to DMI data is NOT available (we 
can't even use the INT 15h mover if we want to continue to support Loadlin.)

In the boot code, io_delay() is used to slow down accesses to the KBC, 
interrupt controller, INT13h logic, and the NMI gate, and to provide a 
fixed delay during A20 stabilization.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 23:51                                     ` H. Peter Anvin
@ 2007-12-16  0:05                                       ` H. Peter Anvin
  2007-12-16 13:15                                       ` [PATCH] x86: provide a DMI based port 0x80 I/O delay override Rene Herman
  1 sibling, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-16  0:05 UTC (permalink / raw)
  To: Rene Herman
  Cc: Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman, rol

H. Peter Anvin wrote:
> 
> Note, however, that your code doesn't deal with io_delay()'s in the boot 
> code (arch/x86/boot) at all, nor (obviously) io_delay()'s in boot 
> loaders.  In the boot code, access to DMI data is NOT available (we 
> can't even use the INT 15h mover if we want to continue to support 
> Loadlin.)
>

Correction: DMI data are at least supposedly available via the PNPBIOS 
calls specified in the SMBIOS spec.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 23:26                                   ` [PATCH] x86: " Rene Herman
  2007-12-15 23:51                                     ` H. Peter Anvin
@ 2007-12-16  0:23                                     ` David P. Reed
  1 sibling, 0 replies; 243+ messages in thread
From: David P. Reed @ 2007-12-16  0:23 UTC (permalink / raw)
  To: Rene Herman
  Cc: H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman, rol,
	Allen Martin

Here we go.

# dmidecode -s baseboard-manufacturer
Quanta
# dmidecode -s baseboard-product-name
30B9

There do seem to be other systems, besides mine, that have the same 
problem.  I think it's pretty likely that other machines that have this 
problem are Quanta machines, since Quanta is one of the primary ODM's 
that does HP laptops.   Don't know about the product-name being common 
with the HP dv6000z family, which is another one reported to have this 
problem.  We could try to ask all the reporters of hwclock freezes to 
report their results from dmidecode.


Rene Herman wrote:
> On 15-12-07 21:27, H. Peter Anvin wrote:
>
>> Rene Herman wrote:
>>>
>>> Yes, just posted a Patch-For-Comments that switches on the 
>>> availability of a TSC (tsc_init sets tsc_disable also for 
>>> !cpu_has_tsc) which would mean that only really old stuff would be 
>>> using the outb still. A TSC is really all we need to have a sensible 
>>> udelay().
>>
>> Uhm, no.  You have no clue what the speed of the TSC is until you 
>> have been able to calibrate it against a fixed timesource - like the 
>> PIT.
>
> Yes. Hnng. Okay, this is going nowhere in a hurry, so back to the very 
> first suggestion in this thread. How about this? This allows to switch 
> from port 0x80 to port 0xed based on DMI.
>
> David: I plugged in my own DMI values for testing, but obviously yours 
> are needed. The values that are needed are retrieved by the 
> "dmidecode" program which you will probably have installed (it might 
> be in an sbin directory) or will be able to install through whatever 
> package manager you use.
>
> dmidecode -s baseboard-manufacturer
> dmidecode -s baseboard-product-name
>
> are the values you should plug into the .matches field in the 
> dmi_system_id struct in this. It would be great if you could do that, 
> test, and post back with those values. .ident should be a nice human 
> name.
>
> It's been tested on x86-32 and seems to work fine. It's not been 
> tested on x86-64 but seems to stand a fair chance of working similarly.
>
> It ofcourse remains possible to switch to a udelay() based method 
> later on anyways but with all the pre-calibratin trouble, this might 
> be the lowest risk method in the short run.
>
> This is partly based on previous patches by Pavel Machek and David P. 
> Reed.
>
> I hope this is considered half-way correct/sane (note by the way that 
> it's not a good idea to switch a "native_io_delay_port" value since 
> plugging in a variable port would clobber register dx for every 
> outb_p, which would then have to be reloaded for the next outb again). 
> Comments appreciated.
>
> Signed-off-by: Rene Herman <rene.herman@gmail.com>
>
>  arch/x86/boot/compressed/misc_32.c |    8 ++---
>  arch/x86/boot/compressed/misc_64.c |    8 ++---
>  arch/x86/kernel/Makefile_32        |    2 -
>  arch/x86/kernel/Makefile_64        |    2 -
>  arch/x86/kernel/io_delay.c         |   53 
> +++++++++++++++++++++++++++++++++++++
>  arch/x86/kernel/setup_32.c         |    2 +
>  arch/x86/kernel/setup_64.c         |    2 +
>  include/asm-x86/io_32.h            |   17 ++---------
>  include/asm-x86/io_64.h            |   23 ++++++----------
>

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 20:26                               ` [PATCH] x86_64: " H. Peter Anvin
  2007-12-15 22:55                                 ` Pavel Machek
@ 2007-12-16  9:27                                 ` Ingo Molnar
  1 sibling, 0 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-16  9:27 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Paul Rolland, Alan Cox, Pavel Machek, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman, rol


* H. Peter Anvin <hpa@zytor.com> wrote:

> Paul Rolland wrote:
>> Just an idea : from what I've read, the problem (port 80 hanging) only occurs
>> on 'modern' machines...
>
> It happens on *one single* "modern" machine...
>
> Let's keep that in perspective.

two or three i think (and an unknown of others where "random, 
unexplained freezes" were thought to be hw borkage), but yeah, it's 
still a very low proportion.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 23:04                       ` H. Peter Anvin
@ 2007-12-16  9:40                         ` Ingo Molnar
  2007-12-16 21:43                           ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-16  9:40 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Pavel Machek, David P. Reed, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman


* H. Peter Anvin <hpa@zytor.com> wrote:

> Pavel Machek wrote:
>>>
>>> this is also something for v2.6.24 merging.
>>
>> As much as I like this patch, I do not think it is suitable for
>> .24. Too risky, I'd say.
>>
>
> No kidding!  We're talking about removing a hack that has been 
> successful on thousands of pieces of hardware over 15 years because it 
                                                             ^----[*]
> breaks ONE machine.

[*] "- none of which needs it anymore -"

there, fixed it for you ;-)

So lets keep this in perspective: this is a hack that only helps on a 
very low number of systems. (the PIT of one PII era chipset is known to 
be affected)

unfortunately this hack's side-effects are mis-used by an unknown number 
of drivers to mask PCI posting bugs. We want to figure out those bugs 
(safely and carefully) and we want to remove this hack from modern 
machines that dont need it. Doing anything else would be superstition.

anyway, we likely wont be doing anything about this in .24.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-15 23:51                                     ` H. Peter Anvin
  2007-12-16  0:05                                       ` H. Peter Anvin
@ 2007-12-16 13:15                                       ` Rene Herman
  2007-12-16 15:22                                         ` Ingo Molnar
                                                           ` (2 more replies)
  1 sibling, 3 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-16 13:15 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Rene Herman, Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

[-- Attachment #1: Type: text/plain, Size: 2355 bytes --]

On 16-12-07 00:51, H. Peter Anvin wrote:

> Rene Herman wrote:
>>
>> I hope this is considered half-way correct/sane (note by the way that 
>> it's not a good idea to switch a "native_io_delay_port" value since 
>> plugging in a variable port would clobber register dx for every 
>> outb_p, which would then have to be reloaded for the next outb again). 
>> Comments appreciated.
> 
> That actually wouldn't be that big of a deal.  Switching values in and 
> out of registers is dirt cheap (and MUCH cheaper than an indirect 
> function call)

Well, I suppose. With stuff inline, constantly reloading dx also bloats 
things up a bit but yes, out of line who cares. Do you think this version is 
better?

> Note, however, that your code doesn't deal with io_delay()'s in the boot 
> code (arch/x86/boot) at all, nor (obviously) io_delay()'s in boot 
> loaders.  In the boot code, access to DMI data is NOT available (we 
> can't even use the INT 15h mover if we want to continue to support 
> Loadlin.)
> 
> In the boot code, io_delay() is used to slow down accesses to the KBC, 
> interrupt controller, INT13h logic, and the NMI gate, and to provide a 
> fixed delay during A20 stabilization.

Thanks for the heads up (also saw the SMBIOS update to this) but those don't 
seem to be a problem in fact. David Reed has been running with the simple 
udelay(2) version of this and reported no more hangs. He moreover reported 
no trouble after booting with "acpi=off" meaning that things seem to be fine 
pre-acpi which the boot code (and this io_delay_init) is. So I believe we 
get to ignore those.

David: I've plugged in your DMI values in this. Could you perhaps test this 
to confirm that it works for you?

Any ACKs, NAKs or further comments from others in this thread also welcome.

Changelog in the patch.

  arch/x86/boot/compressed/misc_32.c |    8 ++---
  arch/x86/boot/compressed/misc_64.c |    8 ++---
  arch/x86/kernel/Makefile_32        |    2 -
  arch/x86/kernel/Makefile_64        |    2 -
  arch/x86/kernel/io_delay.c         |   54 
+++++++++++++++++++++++++++++++++++++
  arch/x86/kernel/setup_32.c         |    2 +
  arch/x86/kernel/setup_64.c         |    2 +
  include/asm-x86/io_32.h            |   17 ++---------
  include/asm-x86/io_64.h            |   23 ++++++---------
  9 files changed, 80 insertions(+), 38 deletions(-)

Rene.

[-- Attachment #2: dmi-io_delay.diff --]
[-- Type: text/plain, Size: 9858 bytes --]

commit a17ccb1964b53fd4ab00d501b7f229a9a6cf91d1
Author: Rene Herman <rene.herman@gmail.com>
Date:   Sun Dec 16 13:36:39 2007 +0100

    x86: provide a DMI based port 0x80 I/O delay override.
    
    Certain (HP) laptops experience trouble from our port 0x80 I/O delay
    writes. This patch provides for a DMI based switch to the "alternate
    diagnostic port" 0xed (as used by some BIOSes as well) for these.
    
    David P. Reed confirmed that port 0xed works for him and provides a
    proper delay. The symptoms of _not_ working are a hanging machine,
    with "hwclock" use being a direct trigger.
    
    Earlier versions of this attempted to simply use udelay(2), with the
    2 being a value tested to be a nicely conservative upper-bound with
    help from many on the linux-kernel mailinglist, but that approach has
    two problems.
    
    First, pre-loops_per_jiffy calibration (which is post PIT init while
    some implementations of the PIT are actually one of the historically
    problematic devices that need the delay) udelay() isn't particularly
    well-defined. We could initialise loops_per_jiffy conservatively (and
    based on CPU family so as to not unduly delay old machines) which
    would sort of work, but still leaves problem 2.
    
    Second, delaying isn't the only effect that a write to port 0x80 has.
    It's also a PCI posting barrier which some devices may be explicitly
    or implicitly relying on. Alan Cox did a survey and found evidence
    that additionally some drivers may be racy on SMP without the bus
    locking outb.
    
    Switching to an inb() makes the timing too unpredictable and as such,
    this DMI based switch should be the safest approach for now. Any more
    invasive changes should get more rigid testing first. It's moreover
    only very few machines with the problem and a DMI based hack seems
    to fit that situation.
    
    This does not change the io_delay() in the boot code which is using
    the same port 0x80 I/O delay but those do not appear to be a problem
    as David P. Reed reported the problem was already gone after using the
    udelay(2) version of this. He moreover reported that booting with
    "acpi=off" also fixed things and seeing as how ACPI isn't touched
    until after this DMI based I/O port switch I believe it's safe to
    leave the ones in the boot code be.
    
    The DMI strings from David's HP Pavilion dv9000z are in there already
    and we need to get/verify the DMI info from other machines with the
    problem, notably the HP Pavilion dv6000z.
    
    This patch is partly based on earlier patches from Pavel Machek and
    David P. Reed.
    
    Signed-off-by: Rene Herman <rene.herman@gmail.com>

diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
index b74d60d..288e162 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc_32.c
@@ -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)
diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
index 6ea015a..43e5fcc 100644
--- a/arch/x86/boot/compressed/misc_64.c
+++ b/arch/x86/boot/compressed/misc_64.c
@@ -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)
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index a7bc93c..0cc1981 100644
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -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/
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64
index 5a88890..08a68f0 100644
--- a/arch/x86/kernel/Makefile_64
+++ b/arch/x86/kernel/Makefile_64
@@ -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/
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
new file mode 100644
index 0000000..d889c43
--- /dev/null
+++ b/arch/x86/kernel/io_delay.c
@@ -0,0 +1,54 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+
+/*
+ * Some machines get upset at port 0x80 writes which we use as
+ * an I/O delay. Allow for a DMI based override to alternate
+ * port 0xed.
+ */
+#define STANDARD_IO_DELAY_PORT	0x80
+#define ALTERNATE_IO_DELAY_PORT	0xed
+
+static unsigned short io_delay_port = STANDARD_IO_DELAY_PORT;
+
+void native_io_delay(void)
+{
+	asm volatile ("outb %%al, %w0" : : "d" (io_delay_port));
+}
+
+void slow_down_io(void) {
+	native_io_delay();
+#ifdef REALLY_SLOW_IO
+	native_io_delay();
+	native_io_delay();
+	native_io_delay();
+#endif
+}
+EXPORT_SYMBOL(slow_down_io);
+
+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_port = ALTERNATE_IO_DELAY_PORT;
+	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")
+		}
+	},
+	{
+	}
+};
+
+void __init io_delay_init(void)
+{
+	dmi_check_system(alternate_io_delay_port_dmi_table);
+}
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index e1e18c3..6c3a3b4 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -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	
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 30d94d1..ec976ed 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -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;
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index fe881cd..5d4e5e5 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -250,24 +250,13 @@ static inline void flush_write_buffers(void)
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void io_delay_init(void);
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
 #else
-
-static inline void slow_down_io(void) {
-	native_io_delay();
-#ifdef REALLY_SLOW_IO
-	native_io_delay();
-	native_io_delay();
-	native_io_delay();
-#endif
-}
-
+extern void slow_down_io(void);
 #endif
 
 #ifdef CONFIG_X86_NUMAQ
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index a037b07..486a110 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -35,13 +35,8 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-
-#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
-#endif
+extern void io_delay_init(void);
+extern void slow_down_io(void);
 
 /*
  * Talk about misusing macros..
@@ -50,21 +45,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) \

^ permalink raw reply related	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-16 13:15                                       ` [PATCH] x86: provide a DMI based port 0x80 I/O delay override Rene Herman
@ 2007-12-16 15:22                                         ` Ingo Molnar
  2007-12-17  1:43                                           ` Rene Herman
  2007-12-16 21:42                                         ` H. Peter Anvin
  2007-12-16 23:12                                         ` David P. Reed
  2 siblings, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-16 15:22 UTC (permalink / raw)
  To: Rene Herman
  Cc: H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* Rene Herman <rene.herman@gmail.com> wrote:

> Any ACKs, NAKs or further comments from others in this thread also 
> welcome.

looks good to me. Could you please also provide three more controls that 
i suggested earlier:

 - a boot option enabling/disabling the udelay based code
 - a .config method of enabling/disabling the udelay based code
 - a sysctl to toggle it

if we want to clean this all up we'll need as many controls as possible.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-16 13:15                                       ` [PATCH] x86: provide a DMI based port 0x80 I/O delay override Rene Herman
  2007-12-16 15:22                                         ` Ingo Molnar
@ 2007-12-16 21:42                                         ` H. Peter Anvin
  2007-12-17  1:48                                           ` Rene Herman
  2007-12-16 23:12                                         ` David P. Reed
  2 siblings, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-16 21:42 UTC (permalink / raw)
  To: Rene Herman
  Cc: Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> 
> Well, I suppose. With stuff inline, constantly reloading dx also bloats 
> things up a bit but yes, out of line who cares. Do you think this 
> version is better?
> 

It probably comes down to which version is bigger (you probably also 
want to try uninlining.)

>> In the boot code, io_delay() is used to slow down accesses to the KBC, 
>> interrupt controller, INT13h logic, and the NMI gate, and to provide a 
>> fixed delay during A20 stabilization.
> 
> Thanks for the heads up (also saw the SMBIOS update to this) but those 
> don't seem to be a problem in fact. David Reed has been running with the 
> simple udelay(2) version of this and reported no more hangs. He moreover 
> reported no trouble after booting with "acpi=off" meaning that things 
> seem to be fine pre-acpi which the boot code (and this io_delay_init) 
> is. So I believe we get to ignore those.

Okay, so there is something inside ACPI which tickles this.  Which 
brings further credibility that it's activating a debugging hack, 
probably inside the SuperIO/system controller chip.

It would be interesting to know exactly which part of ACPI triggers 
this.  I bet it is a reference to system controller namespace.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-16  9:40                         ` Ingo Molnar
@ 2007-12-16 21:43                           ` H. Peter Anvin
  2007-12-16 23:06                             ` David P. Reed
  2007-12-17  1:51                             ` Rene Herman
  0 siblings, 2 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-16 21:43 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Pavel Machek, David P. Reed, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman

Ingo Molnar wrote:
> * H. Peter Anvin <hpa@zytor.com> wrote:
> 
>> Pavel Machek wrote:
>>>> this is also something for v2.6.24 merging.
>>> As much as I like this patch, I do not think it is suitable for
>>> .24. Too risky, I'd say.
>>>
>> No kidding!  We're talking about removing a hack that has been 
>> successful on thousands of pieces of hardware over 15 years because it 
>                                                              ^----[*]
>> breaks ONE machine.
> 
> [*] "- none of which needs it anymore -"
> 
> there, fixed it for you ;-)
> 
> So lets keep this in perspective: this is a hack that only helps on a 
> very low number of systems. (the PIT of one PII era chipset is known to 
> be affected)

Yes, but the status quo has been *tested* on thousands of systems and is 
known to work.  Thus, changing it puts things into unknown territory, 
even if only a small number of machines actually need the current 
configuration.

Heck, there are only a small number of 386/486 machines still in 
operation and being actively updated.

> unfortunately this hack's side-effects are mis-used by an unknown number 
> of drivers to mask PCI posting bugs. We want to figure out those bugs 
> (safely and carefully) and we want to remove this hack from modern 
> machines that dont need it. Doing anything else would be superstition.
> 
> anyway, we likely wont be doing anything about this in .24.

Again, 24 is "right out".  25 is a "maybe", IMO.  Rene's fix could be an 
exception, since it is a DMI-keyed workaround for a specific machine and 
doesn't change behaviour in general.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-16 21:43                           ` H. Peter Anvin
@ 2007-12-16 23:06                             ` David P. Reed
  2007-12-16 23:23                               ` Pavel Machek
  2007-12-17  1:51                             ` Rene Herman
  1 sibling, 1 reply; 243+ messages in thread
From: David P. Reed @ 2007-12-16 23:06 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Ingo Molnar, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman

The process of safely making delicate changes here is beyond my 
responsibility as just a user - believe me, I'm not suggesting that a 
risky fix be put in .24.   I can patch my own kernels, and I can even 
share an unofficial patch with others for now, or suggest that Fedora 
and Ubuntu add it to their downstream.

May I make a small suggestion, though.   If the decision is a DMI-keyed 
switch from out-80 to udelay(2)  gets put in, perhaps there should also 
be a way for people to test their own configuration for the underlying 
problem made available as a script.   Though it is a "hack", all you 
need to freeze a problem system is to run a loop doing about 1000 "cat 
/dev/nvram > /dev/null"  commands.  If that leads to a freeze, one might 
ask to have the motherboard added to the DMI-key list.

H. Peter Anvin wrote:
> Ingo Molnar wrote:
>> * H. Peter Anvin <hpa@zytor.com> wrote:
>>
>>> Pavel Machek wrote:
>>>>> this is also something for v2.6.24 merging.
>>>> As much as I like this patch, I do not think it is suitable for
>>>> .24. Too risky, I'd say.
>>>>
>>> No kidding!  We're talking about removing a hack that has been 
>>> successful on thousands of pieces of hardware over 15 years because it 
>>                                                              ^----[*]
>>> breaks ONE machine.
>>
>> [*] "- none of which needs it anymore -"
>>
>> there, fixed it for you ;-)
>>
>> So lets keep this in perspective: this is a hack that only helps on a 
>> very low number of systems. (the PIT of one PII era chipset is known 
>> to be affected)
>
> Yes, but the status quo has been *tested* on thousands of systems and 
> is known to work.  Thus, changing it puts things into unknown 
> territory, even if only a small number of machines actually need the 
> current configuration.
>
> Heck, there are only a small number of 386/486 machines still in 
> operation and being actively updated.
>
>> unfortunately this hack's side-effects are mis-used by an unknown 
>> number of drivers to mask PCI posting bugs. We want to figure out 
>> those bugs (safely and carefully) and we want to remove this hack 
>> from modern machines that dont need it. Doing anything else would be 
>> superstition.
>>
>> anyway, we likely wont be doing anything about this in .24.
>
> Again, 24 is "right out".  25 is a "maybe", IMO.  Rene's fix could be 
> an exception, since it is a DMI-keyed workaround for a specific 
> machine and doesn't change behaviour in general.
>
>     -hpa
>

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-16 13:15                                       ` [PATCH] x86: provide a DMI based port 0x80 I/O delay override Rene Herman
  2007-12-16 15:22                                         ` Ingo Molnar
  2007-12-16 21:42                                         ` H. Peter Anvin
@ 2007-12-16 23:12                                         ` David P. Reed
  2007-12-17  1:56                                           ` Rene Herman
  2 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2007-12-16 23:12 UTC (permalink / raw)
  To: Rene Herman
  Cc: H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol



Rene Herman wrote:
> David: I've plugged in your DMI values in this. Could you perhaps test 
> this to confirm that it works for you?
>
Will test it by tomorrow morning.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-16 23:06                             ` David P. Reed
@ 2007-12-16 23:23                               ` Pavel Machek
  2007-12-16 23:34                                 ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: Pavel Machek @ 2007-12-16 23:23 UTC (permalink / raw)
  To: David P. Reed
  Cc: H. Peter Anvin, Ingo Molnar, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman

Hi!

> The process of safely making delicate changes here is beyond my 
> responsibility as just a user - believe me, I'm not suggesting that a risky 
> fix be put in .24.   I can patch my own kernels, and I can even share an 
> unofficial patch with others for now, or suggest that Fedora and Ubuntu add 
> it to their downstream.
>
> May I make a small suggestion, though.   If the decision is a DMI-keyed 
> switch from out-80 to udelay(2)  gets put in, perhaps there should also be 
> a way for people to test their own configuration for the underlying problem 
> made available as a script.   Though it is a "hack", all you need to freeze 
> a problem system is to run a loop doing about 1000 "cat /dev/nvram > 
> /dev/null"  commands.  If that leads to a freeze, one might ask to have the 
> motherboard added to the DMI-key list.

Can you freeze it by catting /dev/rtc, too? That may be significant,
because that is readable for group audio (at least on some
systems)... which would smell like "small security hole" to me.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-16 23:23                               ` Pavel Machek
@ 2007-12-16 23:34                                 ` H. Peter Anvin
  2007-12-26 20:49                                   ` Pavel Machek
  0 siblings, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-16 23:34 UTC (permalink / raw)
  To: Pavel Machek
  Cc: David P. Reed, Ingo Molnar, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman

Pavel Machek wrote:
> Hi!
> 
>> The process of safely making delicate changes here is beyond my 
>> responsibility as just a user - believe me, I'm not suggesting that a risky 
>> fix be put in .24.   I can patch my own kernels, and I can even share an 
>> unofficial patch with others for now, or suggest that Fedora and Ubuntu add 
>> it to their downstream.
>>
>> May I make a small suggestion, though.   If the decision is a DMI-keyed 
>> switch from out-80 to udelay(2)  gets put in, perhaps there should also be 
>> a way for people to test their own configuration for the underlying problem 
>> made available as a script.   Though it is a "hack", all you need to freeze 
>> a problem system is to run a loop doing about 1000 "cat /dev/nvram > 
>> /dev/null"  commands.  If that leads to a freeze, one might ask to have the 
>> motherboard added to the DMI-key list.
> 
> Can you freeze it by catting /dev/rtc, too? That may be significant,
> because that is readable for group audio (at least on some
> systems)... which would smell like "small security hole" to me.
> 									Pavel

Heck, on my system (Fedora 7), it's mode 644...

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-16 15:22                                         ` Ingo Molnar
@ 2007-12-17  1:43                                           ` Rene Herman
  2007-12-17  2:05                                             ` H. Peter Anvin
  2007-12-17 10:57                                             ` Ingo Molnar
  0 siblings, 2 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17  1:43 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

[-- Attachment #1: Type: text/plain, Size: 1427 bytes --]

On 16-12-07 16:22, Ingo Molnar wrote:

> looks good to me. Could you please also provide three more controls that 
> i suggested earlier:
> 
>  - a boot option enabling/disabling the udelay based code
>  - a .config method of enabling/disabling the udelay based code
>  - a sysctl to toggle it
> 
> if we want to clean this all up we'll need as many controls as possible.

This version does the boot and the .config option but not the sysctl. It 
makes for clumsy code and I don't believe it provides for much added value 
as soon as you have the boot option. I am moreover not completely confident 
about things such as paravirt liking the possibility of the native_io_delay 
being changed out from under them at unpredictable times.

So how is this? Also fixes a few problems with the previous version.

  Documentation/kernel-parameters.txt |    8 ++
  arch/x86/Kconfig.debug              |    9 +++
  arch/x86/boot/compressed/misc_32.c  |    8 +-
  arch/x86/boot/compressed/misc_64.c  |    8 +-
  arch/x86/kernel/Makefile_32         |    2
  arch/x86/kernel/Makefile_64         |    2
  arch/x86/kernel/io_delay.c          |  103 
++++++++++++++++++++++++++++++++++++
  arch/x86/kernel/setup_32.c          |    2
  arch/x86/kernel/setup_64.c          |    2
  include/asm-x86/io_32.h             |    6 --
  include/asm-x86/io_64.h             |   27 +++++----
  11 files changed, 152 insertions(+), 25 deletions(-)

Rene.

[-- Attachment #2: dmi-io_delay2.diff --]
[-- Type: text/plain, Size: 12737 bytes --]

commit 5001121e449040aa9cc021f69bfb191662c13004
Author: Rene Herman <rene.herman@gmail.com>
Date:   Sun Dec 16 13:36:39 2007 +0100

    x86: provide a DMI based port 0x80 I/O delay override.
    
    Certain (HP) laptops experience trouble from our port 0x80 I/O delay
    writes. This patch provides for a DMI based switch to the "alternate
    diagnostic port" 0xed (as used by some BIOSes as well) for these.
    
    David P. Reed confirmed that port 0xed works for him and provides a
    proper delay. The symptoms of _not_ working are a hanging machine,
    with "hwclock" use being a direct trigger.
    
    Earlier versions of this attempted to simply use udelay(2), with the
    2 being a value tested to be a nicely conservative upper-bound with
    help from many on the linux-kernel mailinglist but that approach has
    two problems.
    
    First, pre-loops_per_jiffy calibration (which is post PIT init while
    some implementations of the PIT are actually one of the historically
    problematic devices that need the delay) udelay() isn't particularly
    well-defined. We could initialise loops_per_jiffy conservatively (and
    based on CPU family so as to not unduly delay old machines) which
    would sort of work, but...
    
    Second, delaying isn't the only effect that a write to port 0x80 has.
    It's also a PCI posting barrier which some devices may be explicitly
    or implicitly relying on. Alan Cox did a survey and found evidence
    that additionally some drivers may be racy on SMP without the bus
    locking outb.
    
    Switching to an inb() makes the timing too unpredictable and as such,
    this DMI based switch should be the safest approach for now. Any more
    invasive changes should get more rigid testing first. It's moreover
    only very few machines with the problem and a DMI based hack seems
    to fit that situation.
    
    This also introduces a command-line parameter "io_delay" to override
    the DMI based choice again:
    
    	io_delay=<standard|alternate>
    
    where "standard" means using the standard port 0x80 and "alternate"
    port 0xed.
    
    At the request of Ingo Molnar this retains the udelay method as a
    config (CONFIG_UDELAY_IO_DELAY) and command-line ("io_delay=udelay")
    choice for testing purposes as well.
    
    This does not change the io_delay() in the boot code which is using
    the same port 0x80 I/O delay but those do not appear to be a problem
    as David P. Reed reported the problem was already gone after using the
    udelay version. He moreover reported that booting with "acpi=off" also
    fixed things and seeing as how ACPI isn't touched until after this DMI
    based I/O port switch I believe it's safe to leave the ones in the boot
    code be.
    
    The DMI strings from David's HP Pavilion dv9000z are in there already
    and we need to get/verify the DMI info from other machines with the
    problem, notably the HP Pavilion dv6000z.
    
    This patch is partly based on earlier patches from Pavel Machek and
    David P. Reed.
    
    Signed-off-by: Rene Herman <rene.herman@gmail.com>

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 33121d6..9dce154 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -785,6 +785,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.
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 761ca7b..40aba67 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -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
diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
index b74d60d..288e162 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc_32.c
@@ -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)
diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
index 6ea015a..43e5fcc 100644
--- a/arch/x86/boot/compressed/misc_64.c
+++ b/arch/x86/boot/compressed/misc_64.c
@@ -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)
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index a7bc93c..0cc1981 100644
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -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/
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64
index 5a88890..08a68f0 100644
--- a/arch/x86/kernel/Makefile_64
+++ b/arch/x86/kernel/Makefile_64
@@ -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/
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
new file mode 100644
index 0000000..4d955e7
--- /dev/null
+++ b/arch/x86/kernel/io_delay.c
@@ -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);
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index e1e18c3..6c3a3b4 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -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	
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 30d94d1..ec976ed 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -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;
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index fe881cd..a8d25c3 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -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>
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index a037b07..5bebaf9 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -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..
@@ -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) \

^ permalink raw reply related	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-16 21:42                                         ` H. Peter Anvin
@ 2007-12-17  1:48                                           ` Rene Herman
  2007-12-17  1:53                                             ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-17  1:48 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 16-12-07 22:42, H. Peter Anvin wrote:

> It probably comes down to which version is bigger (you probably also 
> want to try uninlining.)

slow_down_io() sort of needs to stay inline due to the REALLY_SLOW_IO thing. 
That stuff could use a cleanup, but that would be a diferent patch.

>> Thanks for the heads up (also saw the SMBIOS update to this) but those 
>> don't seem to be a problem in fact. David Reed has been running with 
>> the simple udelay(2) version of this and reported no more hangs. He 
>> moreover reported no trouble after booting with "acpi=off" meaning 
>> that things seem to be fine pre-acpi which the boot code (and this 
>> io_delay_init) is. So I believe we get to ignore those.
> 
> Okay, so there is something inside ACPI which tickles this.  Which 
> brings further credibility that it's activating a debugging hack, 
> probably inside the SuperIO/system controller chip.
> 
> It would be interesting to know exactly which part of ACPI triggers 
> this.  I bet it is a reference to system controller namespace.

Do you expect a BIOS update to be able to fix it? If so, I guess any DMI 
hack should take BIOS version into account.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-16 21:43                           ` H. Peter Anvin
  2007-12-16 23:06                             ` David P. Reed
@ 2007-12-17  1:51                             ` Rene Herman
  1 sibling, 0 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17  1:51 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Ingo Molnar, Pavel Machek, David P. Reed, Thomas Gleixner,
	linux-kernel, Ingo Molnar

On 16-12-07 22:43, H. Peter Anvin wrote:

> Again, 24 is "right out".  25 is a "maybe", IMO.  Rene's fix could be an 
> exception, since it is a DMI-keyed workaround for a specific machine and 
> doesn't change behaviour in general.

I've not much opinion on the schedule as I've not the problem but yes, it's 
intended as the low risk option.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17  1:48                                           ` Rene Herman
@ 2007-12-17  1:53                                             ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17  1:53 UTC (permalink / raw)
  To: Rene Herman
  Cc: Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> 
> Do you expect a BIOS update to be able to fix it? If so, I guess any DMI 
> hack should take BIOS version into account.
> 

Hard to know without knowing what it is.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-16 23:12                                         ` David P. Reed
@ 2007-12-17  1:56                                           ` Rene Herman
  2007-12-17  2:04                                             ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-17  1:56 UTC (permalink / raw)
  To: David P. Reed
  Cc: H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

[-- Attachment #1: Type: text/plain, Size: 351 bytes --]

On 17-12-07 00:12, David P. Reed wrote:

> Rene Herman wrote:
>> David: I've plugged in your DMI values in this. Could you perhaps test 
>> this to confirm that it works for you?
>>
> Will test it by tomorrow morning.

Might as well test the new version then. Ingo Molnar requested a few changes 
and this fixes a couple of problems as well.

Rene.



[-- Attachment #2: dmi-io_delay2.diff --]
[-- Type: text/plain, Size: 12737 bytes --]

commit 5001121e449040aa9cc021f69bfb191662c13004
Author: Rene Herman <rene.herman@gmail.com>
Date:   Sun Dec 16 13:36:39 2007 +0100

    x86: provide a DMI based port 0x80 I/O delay override.
    
    Certain (HP) laptops experience trouble from our port 0x80 I/O delay
    writes. This patch provides for a DMI based switch to the "alternate
    diagnostic port" 0xed (as used by some BIOSes as well) for these.
    
    David P. Reed confirmed that port 0xed works for him and provides a
    proper delay. The symptoms of _not_ working are a hanging machine,
    with "hwclock" use being a direct trigger.
    
    Earlier versions of this attempted to simply use udelay(2), with the
    2 being a value tested to be a nicely conservative upper-bound with
    help from many on the linux-kernel mailinglist but that approach has
    two problems.
    
    First, pre-loops_per_jiffy calibration (which is post PIT init while
    some implementations of the PIT are actually one of the historically
    problematic devices that need the delay) udelay() isn't particularly
    well-defined. We could initialise loops_per_jiffy conservatively (and
    based on CPU family so as to not unduly delay old machines) which
    would sort of work, but...
    
    Second, delaying isn't the only effect that a write to port 0x80 has.
    It's also a PCI posting barrier which some devices may be explicitly
    or implicitly relying on. Alan Cox did a survey and found evidence
    that additionally some drivers may be racy on SMP without the bus
    locking outb.
    
    Switching to an inb() makes the timing too unpredictable and as such,
    this DMI based switch should be the safest approach for now. Any more
    invasive changes should get more rigid testing first. It's moreover
    only very few machines with the problem and a DMI based hack seems
    to fit that situation.
    
    This also introduces a command-line parameter "io_delay" to override
    the DMI based choice again:
    
    	io_delay=<standard|alternate>
    
    where "standard" means using the standard port 0x80 and "alternate"
    port 0xed.
    
    At the request of Ingo Molnar this retains the udelay method as a
    config (CONFIG_UDELAY_IO_DELAY) and command-line ("io_delay=udelay")
    choice for testing purposes as well.
    
    This does not change the io_delay() in the boot code which is using
    the same port 0x80 I/O delay but those do not appear to be a problem
    as David P. Reed reported the problem was already gone after using the
    udelay version. He moreover reported that booting with "acpi=off" also
    fixed things and seeing as how ACPI isn't touched until after this DMI
    based I/O port switch I believe it's safe to leave the ones in the boot
    code be.
    
    The DMI strings from David's HP Pavilion dv9000z are in there already
    and we need to get/verify the DMI info from other machines with the
    problem, notably the HP Pavilion dv6000z.
    
    This patch is partly based on earlier patches from Pavel Machek and
    David P. Reed.
    
    Signed-off-by: Rene Herman <rene.herman@gmail.com>

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 33121d6..9dce154 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -785,6 +785,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.
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 761ca7b..40aba67 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -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
diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
index b74d60d..288e162 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc_32.c
@@ -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)
diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
index 6ea015a..43e5fcc 100644
--- a/arch/x86/boot/compressed/misc_64.c
+++ b/arch/x86/boot/compressed/misc_64.c
@@ -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)
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index a7bc93c..0cc1981 100644
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -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/
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64
index 5a88890..08a68f0 100644
--- a/arch/x86/kernel/Makefile_64
+++ b/arch/x86/kernel/Makefile_64
@@ -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/
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
new file mode 100644
index 0000000..4d955e7
--- /dev/null
+++ b/arch/x86/kernel/io_delay.c
@@ -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);
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index e1e18c3..6c3a3b4 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -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	
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 30d94d1..ec976ed 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -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;
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index fe881cd..a8d25c3 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -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>
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index a037b07..5bebaf9 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -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..
@@ -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) \

^ permalink raw reply related	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17  1:56                                           ` Rene Herman
@ 2007-12-17  2:04                                             ` H. Peter Anvin
  2007-12-17  2:15                                               ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17  2:04 UTC (permalink / raw)
  To: Rene Herman
  Cc: David P. Reed, Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> On 17-12-07 00:12, David P. Reed wrote:
> 
>> Rene Herman wrote:
>>> David: I've plugged in your DMI values in this. Could you perhaps 
>>> test this to confirm that it works for you?
>>>
>> Will test it by tomorrow morning.
> 
> Might as well test the new version then. Ingo Molnar requested a few 
> changes and this fixes a couple of problems as well.
> 

As far as I can tell, the code still uses udelay() before calibration if 
io_delay=udelay?

Just so we're clear on that...

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17  1:43                                           ` Rene Herman
@ 2007-12-17  2:05                                             ` H. Peter Anvin
  2007-12-17  2:19                                               ` Rene Herman
  2007-12-17 10:57                                             ` Ingo Molnar
  1 sibling, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17  2:05 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, Paul Rolland, Alan Cox, Pavel Machek, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> On 16-12-07 16:22, Ingo Molnar wrote:
> 
>> looks good to me. Could you please also provide three more controls 
>> that i suggested earlier:
>>
>>  - a boot option enabling/disabling the udelay based code
>>  - a .config method of enabling/disabling the udelay based code
>>  - a sysctl to toggle it
>>
>> if we want to clean this all up we'll need as many controls as possible.
> 
> This version does the boot and the .config option but not the sysctl. It 
> makes for clumsy code and I don't believe it provides for much added 
> value as soon as you have the boot option. I am moreover not completely 
> confident about things such as paravirt liking the possibility of the 
> native_io_delay being changed out from under them at unpredictable times.
> 

Incidentally, I had the thought earlier today that port 0xf0 might be a 
suitable delay port.  It is used only by the 387-emulating-a-287 hack 
for IRQ 13, which Linux doesn't use on 486+.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17  2:04                                             ` H. Peter Anvin
@ 2007-12-17  2:15                                               ` Rene Herman
  0 siblings, 0 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17  2:15 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: David P. Reed, Paul Rolland, Alan Cox, Pavel Machek, Ingo Molnar,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 17-12-07 03:04, H. Peter Anvin wrote:

> Rene Herman wrote:
>> On 17-12-07 00:12, David P. Reed wrote:
>>
>>> Rene Herman wrote:
>>>> David: I've plugged in your DMI values in this. Could you perhaps 
>>>> test this to confirm that it works for you?
>>>>
>>> Will test it by tomorrow morning.
>>
>> Might as well test the new version then. Ingo Molnar requested a few 
>> changes and this fixes a couple of problems as well.
>>
> 
> As far as I can tell, the code still uses udelay() before calibration if 
> io_delay=udelay?
> 
> Just so we're clear on that...

Yes. This patch is explicitly about the alternate port and not about udelay. 
  As discussed (and changelogged) the calibration is just one problem with 
PCI posting and possible SMP races the other ones. Ingo Molnar wanted it as 
a debugging thing already though.

Once we start discussing udelay() again I believe we should go with the 
simple per CPU-Family loops_per_jiffy initialization to fix that first 
problem (and I guess I could hack that in now) but then the bigger problem 
remains and will need a fair amount of testing at least and mostly on 
machines that are by now gathering dust in a few basements...

Rene



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17  2:05                                             ` H. Peter Anvin
@ 2007-12-17  2:19                                               ` Rene Herman
  2007-12-17  3:35                                                 ` H. Peter Anvin
  2007-12-17  4:09                                                 ` H. Peter Anvin
  0 siblings, 2 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17  2:19 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Ingo Molnar, Paul Rolland, Alan Cox, Pavel Machek, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 17-12-07 03:05, H. Peter Anvin wrote:

> Incidentally, I had the thought earlier today that port 0xf0 might be a 
> suitable delay port.  It is used only by the 387-emulating-a-287 hack 
> for IRQ 13, which Linux doesn't use on 486+.

rene@7ixe4:~/src/port80$ su -c ./port80
cycles: out 2400, in 2400
rene@7ixe4:~/src/port80$ su -c ./portf0
cycles: out 2400, in 2400

(Duron 1300)

I suppose you mean using it instead of port 0x80 always and not just as an 
alternate port? For the latter 0xed is alright I guess...


Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17  2:19                                               ` Rene Herman
@ 2007-12-17  3:35                                                 ` H. Peter Anvin
  2007-12-17 13:02                                                   ` Rene Herman
  2007-12-17  4:09                                                 ` H. Peter Anvin
  1 sibling, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17  3:35 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, Paul Rolland, Alan Cox, Pavel Machek, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> On 17-12-07 03:05, H. Peter Anvin wrote:
> 
>> Incidentally, I had the thought earlier today that port 0xf0 might be 
>> a suitable delay port.  It is used only by the 387-emulating-a-287 
>> hack for IRQ 13, which Linux doesn't use on 486+.
> 
> rene@7ixe4:~/src/port80$ su -c ./port80
> cycles: out 2400, in 2400
> rene@7ixe4:~/src/port80$ su -c ./portf0
> cycles: out 2400, in 2400
> 
> (Duron 1300)
> 
> I suppose you mean using it instead of port 0x80 always and not just as 
> an alternate port? For the latter 0xed is alright I guess...
> 

Well, we probably should leave the possibility in to use 0x80 -- for one 
thing, we need to use 0x80 on 386, and there is always the possibility 
that the switch will have different timing properties on some or all 
machines.

Note that this doesn't require that a machine actually implements port 
0xf0 for FERR/IGNNE, it just requires that they don't use it for 
something else.

I would be rather inclined to try using port 0xf0 by default as long as 
family > 3[*] (with fallback to port 0x80) at least experimentally (-mm).

We *might* even be able to use port 0xf0 unconditionally in the setup 
code, since we're not using the FPU there (the only FPU instructions in 
the setup code are there to detect the FPU.)

One thing: although I believe most actual implementations of port 0xf0 
implement it as a strobe alone (data is ignored), all documentation I've 
found, including "The Undocumented PC" specifically says "write 0x00 to 
this port."  This *could* mean there are platforms which use other 
values than 0x00 for other hacks.

	-hpa


[*] The following statements are equivalent:
     - family > 3.
     - CR0.NE is settable.
     - EFLAGS.AC is settable.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17  2:19                                               ` Rene Herman
  2007-12-17  3:35                                                 ` H. Peter Anvin
@ 2007-12-17  4:09                                                 ` H. Peter Anvin
  1 sibling, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17  4:09 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, Paul Rolland, Alan Cox, Pavel Machek, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> On 17-12-07 03:05, H. Peter Anvin wrote:
> 
>> Incidentally, I had the thought earlier today that port 0xf0 might be 
>> a suitable delay port.  It is used only by the 387-emulating-a-287 
>> hack for IRQ 13, which Linux doesn't use on 486+.
> 
> rene@7ixe4:~/src/port80$ su -c ./port80
> cycles: out 2400, in 2400
> rene@7ixe4:~/src/port80$ su -c ./portf0
> cycles: out 2400, in 2400
> 
> (Duron 1300)
> 
> I suppose you mean using it instead of port 0x80 always and not just as 
> an alternate port? For the latter 0xed is alright I guess...
> 

FWIW, the criterion used in the kernel for when to use IRQ 13 is:

         /*
          * External FPU? Set up irq13 if so, for
          * original braindamaged IBM FERR coupling.
          */
         if (boot_cpu_data.hard_math && !cpu_has_fpu)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                 setup_irq(FPU_IRQ, &fpu_irq);

In that case we can't actually use port 0xF0 (it is, however, safe to 
use it during setup, specifically before we can take our first FPU 
exception.)

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17  1:43                                           ` Rene Herman
  2007-12-17  2:05                                             ` H. Peter Anvin
@ 2007-12-17 10:57                                             ` Ingo Molnar
  2007-12-17 11:29                                               ` Ingo Molnar
  2007-12-17 12:15                                               ` Rene Herman
  1 sibling, 2 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-17 10:57 UTC (permalink / raw)
  To: Rene Herman
  Cc: H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* Rene Herman <rene.herman@gmail.com> wrote:

> On 16-12-07 16:22, Ingo Molnar wrote:
>
>> looks good to me. Could you please also provide three more controls that i 
>> suggested earlier:
>>
>>  - a boot option enabling/disabling the udelay based code
>>  - a .config method of enabling/disabling the udelay based code
>>  - a sysctl to toggle it
>>
>> if we want to clean this all up we'll need as many controls as possible.
>
> This version does the boot and the .config option but not the sysctl. 
> It makes for clumsy code and I don't believe it provides for much 
> added value as soon as you have the boot option. I am moreover not 
> completely confident about things such as paravirt liking the 
> possibility of the native_io_delay being changed out from under them 
> at unpredictable times.
>
> So how is this? Also fixes a few problems with the previous version.

thanks Rene! I've added your patch to x86.git. I changed a few things 
ontop of it, see the additional changelog and delta patch below.

	Ingo

------------>

- 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 'standard' and 'alternate' to 0x80 and 0xed
- make the io delay config not depend on CONFIG_DEBUG_KERNEL

---
 Documentation/kernel-parameters.txt |   12 ++--
 arch/x86/Kconfig.debug              |   79 +++++++++++++++++++++++++--
 arch/x86/kernel/io_delay.c          |  103 ++++++++++++++++--------------------
 include/asm-x86/io_32.h             |    2 
 include/asm-x86/io_64.h             |    2 
 kernel/sysctl.c                     |    9 +++
 6 files changed, 138 insertions(+), 69 deletions(-)

Index: linux-x86.q/Documentation/kernel-parameters.txt
===================================================================
--- linux-x86.q.orig/Documentation/kernel-parameters.txt
+++ linux-x86.q/Documentation/kernel-parameters.txt
@@ -786,12 +786,14 @@ and is between 256 and 4096 characters. 
 			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
Index: linux-x86.q/arch/x86/Kconfig.debug
===================================================================
--- linux-x86.q.orig/arch/x86/Kconfig.debug
+++ linux-x86.q/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
-	  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.
+	  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
Index: linux-x86.q/arch/x86/kernel/io_delay.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/io_delay.c
+++ linux-x86.q/arch/x86/kernel/io_delay.c
@@ -1,5 +1,9 @@
 /*
  * 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>
@@ -8,98 +12,83 @@
 #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
+int io_delay_type __read_mostly = CONFIG_DEFAULT_IO_DELAY_TYPE;
+EXPORT_SYMBOL_GPL(io_delay_type);
 
-/*
- * 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
+static int __initdata io_delay_override;
 
 /*
  * Paravirt wants native_io_delay to be a constant.
  */
 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);
 
-#ifndef CONFIG_UDELAY_IO_DELAY
-static int __init dmi_alternate_io_delay_port(const struct dmi_system_id *id)
+static int __init dmi_io_delay_0xed_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;
+	printk(KERN_NOTICE "%s: using 0xed I/O delay port\n", id->ident);
+	io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
+
 	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",
 		.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);
+		dmi_check_system(io_delay_0xed_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;
+	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 = 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
 		return -EINVAL;
 
-#ifndef CONFIG_UDELAY_IO_DELAY
 	io_delay_override = 1;
-#endif
 	return 0;
 }
 
Index: linux-x86.q/include/asm-x86/io_32.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_32.h
+++ linux-x86.q/include/asm-x86/io_32.h
@@ -259,6 +259,8 @@ static inline void io_delay_init(void)
 #endif
 extern void native_io_delay(void);
 
+extern int io_delay_type;
+
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
 #else
Index: linux-x86.q/include/asm-x86/io_64.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_64.h
+++ linux-x86.q/include/asm-x86/io_64.h
@@ -44,6 +44,8 @@ static inline void io_delay_init(void)
 #endif
 extern void native_io_delay(void);
 
+extern int io_delay_type;
+
 static inline void slow_down_io(void)
 {
 	native_io_delay();
Index: linux-x86.q/kernel/sysctl.c
===================================================================
--- linux-x86.q.orig/kernel/sysctl.c
+++ linux-x86.q/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);
@@ -683,6 +684,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)
 	{

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 10:57                                             ` Ingo Molnar
@ 2007-12-17 11:29                                               ` Ingo Molnar
  2007-12-17 13:34                                                 ` David P. Reed
  2007-12-17 12:15                                               ` Rene Herman
  1 sibling, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-17 11:29 UTC (permalink / raw)
  To: Rene Herman
  Cc: H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* Ingo Molnar <mingo@elte.hu> wrote:

> > So how is this? Also fixes a few problems with the previous version.
> 
> thanks Rene! I've added your patch to x86.git. I changed a few things 
> ontop of it, see the additional changelog and delta patch below.

here's an updated rollup patch, against 2.6.24-rc4. David, could you 
please try this? This should work out of box on your system, without any 
boot option or other tweak needed.

	Ingo

------------------------->
Subject: x86: provide a DMI based port 0x80 I/O delay override.
From: Rene Herman <rene.herman@gmail.com>

x86: provide a DMI based port 0x80 I/O delay override.

Certain (HP) laptops experience trouble from our port 0x80 I/O delay
writes. This patch provides for a DMI based switch to the "alternate
diagnostic port" 0xed (as used by some BIOSes as well) for these.

David P. Reed confirmed that port 0xed works for him and provides a
proper delay. The symptoms of _not_ working are a hanging machine,
with "hwclock" use being a direct trigger.

Earlier versions of this attempted to simply use udelay(2), with the
2 being a value tested to be a nicely conservative upper-bound with
help from many on the linux-kernel mailinglist but that approach has
two problems.

First, pre-loops_per_jiffy calibration (which is post PIT init while
some implementations of the PIT are actually one of the historically
problematic devices that need the delay) udelay() isn't particularly
well-defined. We could initialise loops_per_jiffy conservatively (and
based on CPU family so as to not unduly delay old machines) which
would sort of work, but...

Second, delaying isn't the only effect that a write to port 0x80 has.
It's also a PCI posting barrier which some devices may be explicitly
or implicitly relying on. Alan Cox did a survey and found evidence
that additionally some drivers may be racy on SMP without the bus
locking outb.

Switching to an inb() makes the timing too unpredictable and as such,
this DMI based switch should be the safest approach for now. Any more
invasive changes should get more rigid testing first. It's moreover
only very few machines with the problem and a DMI based hack seems
to fit that situation.

This also introduces a command-line parameter "io_delay" to override
the DMI based choice again:

	io_delay=<0x80|0xed|udelay|none>

where 0x80 means using the standard port 0x80 and 0xed means the
alternate port 0xed.

All these methods can also be selected via the kernel .config,
and can be runtime tuned via /proc/sys/kernel/io_delay_type (for
debugging purposes).

The DMI strings from David's HP Pavilion dv9000z are in there already
and we need to get/verify the DMI info from other machines with the
problem, notably the HP Pavilion dv6000z.

This patch is partly based on earlier patches from Pavel Machek and
David P. Reed.

[ mingo@elte.hu:
  - add the io_delay=none method
  - make each method selectable from the kernel config
  - eliminate the indirect function calls
  - add the /proc/sys/kernel/io_delay_type sysctl
  - change 'standard' and 'alternate' to 0x80 and 0xed
  - make the io delay config not depend on CONFIG_DEBUG_KERNEL ]

Signed-off-by: Rene Herman <rene.herman@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 Documentation/kernel-parameters.txt |   10 +++
 arch/x86/Kconfig.debug              |   74 ++++++++++++++++++++++++++++
 arch/x86/boot/compressed/misc_32.c  |    8 +--
 arch/x86/boot/compressed/misc_64.c  |    8 +--
 arch/x86/kernel/Makefile_32         |    2 
 arch/x86/kernel/Makefile_64         |    2 
 arch/x86/kernel/io_delay.c          |   95 ++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/setup_32.c          |    2 
 arch/x86/kernel/setup_64.c          |    2 
 include/asm-x86/io_32.h             |    8 +--
 include/asm-x86/io_64.h             |   29 ++++++----
 kernel/sysctl.c                     |    9 +++
 12 files changed, 224 insertions(+), 25 deletions(-)

Index: linux-x86.q/Documentation/kernel-parameters.txt
===================================================================
--- linux-x86.q.orig/Documentation/kernel-parameters.txt
+++ linux-x86.q/Documentation/kernel-parameters.txt
@@ -785,6 +785,16 @@ and is between 256 and 4096 characters. 
 			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
+		0x80
+			Standard port 0x80 based delay
+		0xed
+			Alternate port 0xed based delay (needed on some systems)
+		udelay
+			Simple two microseconds delay
+		none
+			No delay
+
 	io7=		[HW] IO7 for Marvel based alpha systems
 			See comment before marvel_specify_io7 in
 			arch/alpha/kernel/core_marvel.c.
Index: linux-x86.q/arch/x86/Kconfig.debug
===================================================================
--- linux-x86.q.orig/arch/x86/Kconfig.debug
+++ linux-x86.q/arch/x86/Kconfig.debug
@@ -112,4 +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.
 
+#
+# 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
+	  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
Index: linux-x86.q/arch/x86/boot/compressed/misc_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_32.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_32.c
@@ -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)
Index: linux-x86.q/arch/x86/boot/compressed/misc_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_64.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_64.c
@@ -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)
Index: linux-x86.q/arch/x86/kernel/Makefile_32
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/Makefile_32
+++ linux-x86.q/arch/x86/kernel/Makefile_32
@@ -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/
Index: linux-x86.q/arch/x86/kernel/Makefile_64
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/Makefile_64
+++ linux-x86.q/arch/x86/kernel/Makefile_64
@@ -11,7 +11,7 @@ obj-y	:= process_64.o signal_64.o entry_
 		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/
Index: linux-x86.q/arch/x86/kernel/io_delay.c
===================================================================
--- /dev/null
+++ linux-x86.q/arch/x86/kernel/io_delay.c
@@ -0,0 +1,95 @@
+/*
+ * 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)
+{
+	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);
Index: linux-x86.q/arch/x86/kernel/setup_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/setup_32.c
+++ linux-x86.q/arch/x86/kernel/setup_32.c
@@ -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	
Index: linux-x86.q/arch/x86/kernel/setup_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/setup_64.c
+++ linux-x86.q/arch/x86/kernel/setup_64.c
@@ -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;
Index: linux-x86.q/include/asm-x86/io_32.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_32.h
+++ linux-x86.q/include/asm-x86/io_32.h
@@ -250,10 +250,10 @@ static inline void flush_write_buffers(v
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+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>
Index: linux-x86.q/include/asm-x86/io_64.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_64.h
+++ linux-x86.q/include/asm-x86/io_64.h
@@ -35,13 +35,20 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+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();
 #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..
@@ -50,21 +57,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) \
Index: linux-x86.q/kernel/sysctl.c
===================================================================
--- linux-x86.q.orig/kernel/sysctl.c
+++ linux-x86.q/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);
@@ -683,6 +684,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)
 	{

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 10:57                                             ` Ingo Molnar
  2007-12-17 11:29                                               ` Ingo Molnar
@ 2007-12-17 12:15                                               ` Rene Herman
  2007-12-17 13:09                                                 ` Ingo Molnar
  1 sibling, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-17 12:15 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 17-12-07 11:57, Ingo Molnar wrote:

> thanks Rene! I've added your patch to x86.git. I changed a few things 
> ontop of it, see the additional changelog and delta patch below.

"appropriated it", more. Definitely not going to forgive you for deleting 
that comment.

>  void native_io_delay(void)
>  {
> -	io_delay();
> +	switch (io_delay_type) {

That's the clumsy bit. native_io_delay() used to be an inline outb, now it's 
a switch. Yes, sure, versus an indirect call it's not actually worse, except 
  as an uglification.

> -#ifndef CONFIG_UDELAY_IO_DELAY
> -static int __init dmi_alternate_io_delay_port(const struct dmi_system_id *id)
> +static int __init dmi_io_delay_0xed_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;
> +	printk(KERN_NOTICE "%s: using 0xed I/O delay port\n", id->ident);
> +	io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
> +
>  	return 0;
>  }

This isn't correct. DMI shouldn't override the CONFIG choice or someone with 
matching DMI will have a defective CONFIG option. That's why I put all of it 
inside #ifndef.

Rene.



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17  3:35                                                 ` H. Peter Anvin
@ 2007-12-17 13:02                                                   ` Rene Herman
  2007-12-17 17:14                                                     ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-17 13:02 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Ingo Molnar, Paul Rolland, Alan Cox, Pavel Machek, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 17-12-07 04:35, H. Peter Anvin wrote:

> Well, we probably should leave the possibility in to use 0x80 -- for one 
> thing, we need to use 0x80 on 386, and there is always the possibility 
> that the switch will have different timing properties on some or all 
> machines.
> 
> Note that this doesn't require that a machine actually implements port 
> 0xf0 for FERR/IGNNE, it just requires that they don't use it for 
> something else.
> 
> I would be rather inclined to try using port 0xf0 by default as long as 
> family > 3[*] (with fallback to port 0x80) at least experimentally (-mm).

Possible timing differences would be what worry me. 0x80 is well-known for 
its delay purposes, and frankly, I dont believe that one type of machine 
having a problem, which may very well have to be categorized a possibly BIOS 
fixable bug, is enough ground for switching everyone over to a different port

It's enough ground to look at not doing outputs at all AFAIC but that's more 
due to the outb being somewhat cheesy to start with which using a different 
port wouldn't change. But, on the other hand:

> We *might* even be able to use port 0xf0 unconditionally in the setup 
> code, since we're not using the FPU there (the only FPU instructions in 
> the setup code are there to detect the FPU.)
> 
> One thing: although I believe most actual implementations of port 0xf0 
> implement it as a strobe alone (data is ignored), all documentation I've 
> found, including "The Undocumented PC" specifically says "write 0x00 to 
> this port."  This *could* mean there are platforms which use other 
> values than 0x00 for other hacks.

The Intel PIIX/PIIX3 datasheet confirms that the data is of no consequence, 
but yes, most documentation talks about 0.

The PIIX/PIIX3 datasheet also says that both reads and writes flow through 
to the ISA bus, while for port 0x80 only writes do, and reads do not.

I do not know how universal that is, but _reading_ port 0xf0 might in fact 
be sensible then? And should even work on a 386/387 pair? (I have a 386/387 
in fact, although I'd need to dig it up).

Versus the out it has the al clobber disadvantage, but givne that we're by 
now seem to be talking about out of line switch() native_io_delays anyways, 
that's not much of a problem anymore...

> [*] The following statements are equivalent:
>     - family > 3.
>     - CR0.NE is settable.
>     - EFLAGS.AC is settable.

For the boot code, I gather (which could I suppose then also plug in the 
delay port in the zero page or somewhere for use by the kernel proper? I 
don't know how/if these bits communicate).

But, well, _reading_ port 0xf0 sounds promising across the board and low 
risk replacement _if_ teh PIIX/PIIX3 behaviour is as guaranteed as the port 
0x80 behaviour...

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 12:15                                               ` Rene Herman
@ 2007-12-17 13:09                                                 ` Ingo Molnar
  2007-12-17 13:22                                                   ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-17 13:09 UTC (permalink / raw)
  To: Rene Herman
  Cc: H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* Rene Herman <rene.herman@gmail.com> wrote:

> On 17-12-07 11:57, Ingo Molnar wrote:
>
>> thanks Rene! I've added your patch to x86.git. I changed a few things 
>> ontop of it, see the additional changelog and delta patch below.
>
> "appropriated it", more. [...]

huh?

> [...] Definitely not going to forgive you for deleting that comment.

Do you mean:

+/*
+ * High on a hill was a lonely goatherd
+ */

?

>>  void native_io_delay(void)
>>  {
>> -	io_delay();
>> +	switch (io_delay_type) {
>
> That's the clumsy bit. native_io_delay() used to be an inline outb, 
> now it's a switch. Yes, sure, versus an indirect call it's not 
> actually worse, except as an uglification.

the switch enableds the sysctl. I dont see the callback as in any way 
cleaner. (in fact it made things more inflexible.)

>> -#ifndef CONFIG_UDELAY_IO_DELAY
>> -static int __init dmi_alternate_io_delay_port(const struct dmi_system_id *id)
>> +static int __init dmi_io_delay_0xed_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;
>> +	printk(KERN_NOTICE "%s: using 0xed I/O delay port\n", id->ident);
>> +	io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
>> +
>>  	return 0;
>>  }
>
> This isn't correct. DMI shouldn't override the CONFIG choice or 
> someone with matching DMI will have a defective CONFIG option. That's 
> why I put all of it inside #ifndef.

no, the DMI quirk is just that: a quirk that makes boxes work. The DMI 
quirk takes precedence over just about any .config default, except an 
explicit boot-commandline override.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 13:09                                                 ` Ingo Molnar
@ 2007-12-17 13:22                                                   ` Rene Herman
  2007-12-17 13:31                                                     ` Pavel Machek
  2007-12-17 13:32                                                     ` David P. Reed
  0 siblings, 2 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17 13:22 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 17-12-07 14:09, Ingo Molnar wrote:

>>> -#ifndef CONFIG_UDELAY_IO_DELAY
>>> -static int __init dmi_alternate_io_delay_port(const struct dmi_system_id *id)
>>> +static int __init dmi_io_delay_0xed_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;
>>> +	printk(KERN_NOTICE "%s: using 0xed I/O delay port\n", id->ident);
>>> +	io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
>>> +
>>>  	return 0;
>>>  }
>> This isn't correct. DMI shouldn't override the CONFIG choice or 
>> someone with matching DMI will have a defective CONFIG option. That's 
>> why I put all of it inside #ifndef.
> 
> no, the DMI quirk is just that: a quirk that makes boxes work. The DMI 
> quirk takes precedence over just about any .config default, except an 
> explicit boot-commandline override.

No, most definitely not. Having the user select udelay or none through the 
kernel config and then the kernel deciding "ah, you know what, I'll know 
better and use port access anyway" is _utterly_ broken behaviour. Software 
needs to listen to its master.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 13:31                                                     ` Pavel Machek
@ 2007-12-17 13:31                                                       ` Rene Herman
  0 siblings, 0 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17 13:31 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Ingo Molnar, H. Peter Anvin, Paul Rolland, Alan Cox,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 17-12-07 14:31, Pavel Machek wrote:

> On Mon 2007-12-17 14:22:26, Rene Herman wrote:
>> On 17-12-07 14:09, Ingo Molnar wrote:
>>
>>>>> -#ifndef CONFIG_UDELAY_IO_DELAY
>>>>> -static int __init dmi_alternate_io_delay_port(const struct 
>>>>> dmi_system_id *id)
>>>>> +static int __init dmi_io_delay_0xed_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;
>>>>> +	printk(KERN_NOTICE "%s: using 0xed I/O delay port\n", id->ident);
>>>>> +	io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
>>>>> +
>>>>>  	return 0;
>>>>>  }
>>>> This isn't correct. DMI shouldn't override the CONFIG choice or someone 
>>>> with matching DMI will have a defective CONFIG option. That's why I put 
>>>> all of it inside #ifndef.
>>> no, the DMI quirk is just that: a quirk that makes boxes work. The DMI 
>>> quirk takes precedence over just about any .config default, except an 
>>> explicit boot-commandline override.
>> No, most definitely not. Having the user select udelay or none through the 
>> kernel config and then the kernel deciding "ah, you know what, I'll know 
>> better and use port access anyway" is _utterly_ broken behaviour. Software 
>> needs to listen to its master.
> 
> That's what command line is for. Ingo is right here.

No. The kernel shouldn't provide defective config options.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 13:22                                                   ` Rene Herman
@ 2007-12-17 13:31                                                     ` Pavel Machek
  2007-12-17 13:31                                                       ` Rene Herman
  2007-12-17 13:32                                                     ` David P. Reed
  1 sibling, 1 reply; 243+ messages in thread
From: Pavel Machek @ 2007-12-17 13:31 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, H. Peter Anvin, Paul Rolland, Alan Cox,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Mon 2007-12-17 14:22:26, Rene Herman wrote:
> On 17-12-07 14:09, Ingo Molnar wrote:
>
>>>> -#ifndef CONFIG_UDELAY_IO_DELAY
>>>> -static int __init dmi_alternate_io_delay_port(const struct 
>>>> dmi_system_id *id)
>>>> +static int __init dmi_io_delay_0xed_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;
>>>> +	printk(KERN_NOTICE "%s: using 0xed I/O delay port\n", id->ident);
>>>> +	io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
>>>> +
>>>>  	return 0;
>>>>  }
>>> This isn't correct. DMI shouldn't override the CONFIG choice or someone 
>>> with matching DMI will have a defective CONFIG option. That's why I put 
>>> all of it inside #ifndef.
>> no, the DMI quirk is just that: a quirk that makes boxes work. The DMI 
>> quirk takes precedence over just about any .config default, except an 
>> explicit boot-commandline override.
>
> No, most definitely not. Having the user select udelay or none through the 
> kernel config and then the kernel deciding "ah, you know what, I'll know 
> better and use port access anyway" is _utterly_ broken behaviour. Software 
> needs to listen to its master.

That's what command line is for. Ingo is right here.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 13:22                                                   ` Rene Herman
  2007-12-17 13:31                                                     ` Pavel Machek
@ 2007-12-17 13:32                                                     ` David P. Reed
  2007-12-17 13:36                                                       ` Rene Herman
  2007-12-17 14:39                                                       ` Ingo Molnar
  1 sibling, 2 replies; 243+ messages in thread
From: David P. Reed @ 2007-12-17 13:32 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> No, most definitely not. Having the user select udelay or none through 
> the kernel config and then the kernel deciding "ah, you know what, 
> I'll know better and use port access anyway" is _utterly_ broken 
> behaviour. Software needs to listen to its master.
>
When acting as an ordinary user, the .config is beyond my control 
(except on Gentoo).   It is in control of the distro (Fedora, Ubuntu, 
... but perhaps not Gentoo).  I think the distro guys want a default 
behavior that is set in .config, with quirk overrides being done when 
needed.   And of course the user in his/her boot params gets the final say.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 11:29                                               ` Ingo Molnar
@ 2007-12-17 13:34                                                 ` David P. Reed
  0 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2007-12-17 13:34 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Rene Herman, H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

About to start building and testing.  It will take a few hours.

Ingo Molnar wrote:
> here's an updated rollup patch, against 2.6.24-rc4. David, could you 
> please try this? This should work out of box on your system, without any 
> boot option or other tweak needed.
>
>
>   

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 13:32                                                     ` David P. Reed
@ 2007-12-17 13:36                                                       ` Rene Herman
  2007-12-17 14:39                                                       ` Ingo Molnar
  1 sibling, 0 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17 13:36 UTC (permalink / raw)
  To: David P. Reed
  Cc: Ingo Molnar, H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 17-12-07 14:32, David P. Reed wrote:

> Rene Herman wrote:
>> No, most definitely not. Having the user select udelay or none through 
>> the kernel config and then the kernel deciding "ah, you know what, 
>> I'll know better and use port access anyway" is _utterly_ broken 
>> behaviour. Software needs to listen to its master.
>>
> When acting as an ordinary user, the .config is beyond my control 
> (except on Gentoo).   It is in control of the distro (Fedora, Ubuntu, 
> ... but perhaps not Gentoo).  I think the distro guys want a default 
> behavior that is set in .config, with quirk overrides being done when 
> needed.   And of course the user in his/her boot params gets the final say.

Yes, and when the user/distributor specifically selected udelay or none as 
an I/O delay method it makes no sense whatsoever to have the kernel override 
that again -- the DMI hack only fixes something for the default case, when 
_no_ specific choice had been made (which the current setup can't express 
but mine did).

I feel particularly strongly (always) about that "listen to its master" bit. 
The kernel does not know better then whomever configured it, even when it does.

Rene.



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 13:32                                                     ` David P. Reed
  2007-12-17 13:36                                                       ` Rene Herman
@ 2007-12-17 14:39                                                       ` Ingo Molnar
  2007-12-17 16:12                                                         ` Alan Cox
  2007-12-17 19:38                                                         ` David P. Reed
  1 sibling, 2 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-17 14:39 UTC (permalink / raw)
  To: David P. Reed
  Cc: Rene Herman, H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* David P. Reed <dpreed@reed.com> wrote:

> Rene Herman wrote:
>> No, most definitely not. Having the user select udelay or none through the 
>> kernel config and then the kernel deciding "ah, you know what, I'll know 
>> better and use port access anyway" is _utterly_ broken behaviour. Software 
>> needs to listen to its master.
>
> When acting as an ordinary user, the .config is beyond my control 
> (except on Gentoo).  It is in control of the distro (Fedora, Ubuntu, 
> ... but perhaps not Gentoo).  I think the distro guys want a default 
> behavior that is set in .config, with quirk overrides being done when 
> needed.  And of course the user in his/her boot params gets the final 
> say.

yeah, that's exactly the thinking. Distros basically set general policy, 
but a quirk is (almost) always specific and correct enough to override 
that. We could perhaps refine this by directing the quirk to only be 
applied if the current type is 0x80 - because in that case we know that 
it's definitely not going to work. I.e. something like the small patch 
below?

	Ingo

---
 arch/x86/kernel/io_delay.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Index: linux-x86.q/arch/x86/kernel/io_delay.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/io_delay.c
+++ linux-x86.q/arch/x86/kernel/io_delay.c
@@ -47,8 +47,11 @@ EXPORT_SYMBOL(native_io_delay);
 
 static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id)
 {
-	printk(KERN_NOTICE "%s: using 0xed I/O delay port\n", id->ident);
-	io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
+	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;
 }

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 14:39                                                       ` Ingo Molnar
@ 2007-12-17 16:12                                                         ` Alan Cox
  2007-12-17 16:48                                                           ` Ingo Molnar
  2007-12-17 20:48                                                           ` Rene Herman
  2007-12-17 19:38                                                         ` David P. Reed
  1 sibling, 2 replies; 243+ messages in thread
From: Alan Cox @ 2007-12-17 16:12 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: David P. Reed, Rene Herman, H. Peter Anvin, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

I don't think we should be offering udelay based delays at this point.
There are a lot of drivers to fix first. This is just one trivial example

...

--- drivers/watchdog/wdt.c~	2007-12-17 15:58:49.000000000 +0000
+++ drivers/watchdog/wdt.c	2007-12-17 15:58:49.000000000 +0000
@@ -70,6 +70,8 @@
 static int io=0x240;
 static int irq=11;
 
+static DEFINE_SPINLOCK(wdt_lock);
+
 module_param(io, int, 0);
 MODULE_PARM_DESC(io, "WDT io port (default=0x240)");
 module_param(irq, int, 0);
@@ -109,6 +111,8 @@
 
 static int wdt_start(void)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&wdt_lock, flags);
 	inb_p(WDT_DC);			/* Disable watchdog */
 	wdt_ctr_mode(0,3);		/* Program CTR0 for Mode 3:
Square Wave Generator */ wdt_ctr_mode(1,2);		/* Program
CTR1 for Mode 2: Rate Generator */ @@ -117,6 +121,7 @@
 	wdt_ctr_load(1,wd_heartbeat);	/* Heartbeat */
 	wdt_ctr_load(2,65535);		/* Length of reset pulse */
 	outb_p(0, WDT_DC);		/* Enable watchdog */
+	spin_unlock_irqrestore(&wdt_lock, flags);
 	return 0;
 }
 
@@ -128,9 +133,12 @@
 
 static int wdt_stop (void)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&wdt_lock, flags);
 	/* Turn the card off */
 	inb_p(WDT_DC);			/* Disable watchdog */
 	wdt_ctr_load(2,0);		/* 0 length reset pulses now */
+	spin_unlock_irqrestore(&wdt_lock, flags);
 	return 0;
 }
 
@@ -143,11 +151,14 @@
 
 static int wdt_ping(void)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&wdt_lock, flags);
 	/* Write a watchdog value */
 	inb_p(WDT_DC);			/* Disable watchdog */
 	wdt_ctr_mode(1,2);		/* Re-Program CTR1 for Mode 2:
Rate Generator */ wdt_ctr_load(1,wd_heartbeat);	/* Heartbeat */
 	outb_p(0, WDT_DC);		/* Enable watchdog */
+	spin_unlock_irqrestore(&wdt_lock, flags);
 	return 0;
 }
 
@@ -182,7 +193,12 @@
 
 static int wdt_get_status(int *status)
 {
-	unsigned char new_status=inb_p(WDT_SR);
+	unsigned char new_status;
+	unsigned long flags;
+
+	spinlock_irqsave(&wdt_lock, flags);	
+	new_status = inb_p(WDT_SR);
+	spin_unlock_irqrestore(&wdt_lock, flags);
 
 	*status=0;
 	if (new_status & WDC_SR_ISOI0)
@@ -214,8 +230,12 @@
 
 static int wdt_get_temperature(int *temperature)
 {
-	unsigned short c=inb_p(WDT_RT);
+	unsigned short c;
+	unsigned long flags;
 
+	spinlock_irqsave(&wdt_lock, flags);	
+	c=inb_p(WDT_RT);
+	spin_unlock_irqrestore(&wdt_lock, flags);
 	*temperature = (c * 11 / 15) + 7;
 	return 0;
 }
@@ -237,7 +257,10 @@
 	 *	Read the status register see what is up and
 	 *	then printk it.
 	 */
-	unsigned char status=inb_p(WDT_SR);
+	unsigned char status;
+	
+	spin_lock(&wdt_lock);
+	status = inb_p(WDT_SR);
 
 	printk(KERN_CRIT "WDT status %d\n", status);
 
@@ -265,6 +288,7 @@
 		printk(KERN_CRIT "Reset in 5ms.\n");
 #endif
 	}
+	spin_unlock(&wdt_lock);
 	return IRQ_HANDLED;
 }
 

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 16:12                                                         ` Alan Cox
@ 2007-12-17 16:48                                                           ` Ingo Molnar
  2007-12-17 20:48                                                           ` Rene Herman
  1 sibling, 0 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-17 16:48 UTC (permalink / raw)
  To: Alan Cox
  Cc: David P. Reed, Rene Herman, H. Peter Anvin, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:

> I don't think we should be offering udelay based delays at this point. 
> There are a lot of drivers to fix first. This is just one trivial 
> example
> 
> ...
> 
> --- drivers/watchdog/wdt.c~	2007-12-17 15:58:49.000000000 +0000
> +++ drivers/watchdog/wdt.c	2007-12-17 15:58:49.000000000 +0000
> @@ -70,6 +70,8 @@
>  static int io=0x240;
>  static int irq=11;
>  
> +static DEFINE_SPINLOCK(wdt_lock);
> +
>  module_param(io, int, 0);
>  MODULE_PARM_DESC(io, "WDT io port (default=0x240)");
>  module_param(irq, int, 0);
> @@ -109,6 +111,8 @@
>  
>  static int wdt_start(void)
>  {
> +	unsigned long flags;
> +	spin_lock_irqsave(&wdt_lock, flags);
>  	inb_p(WDT_DC);			/* Disable watchdog */
>  	wdt_ctr_mode(0,3);		/* Program CTR0 for Mode 3:

a really stupid question, in what way does:

  inb_p(WDT_DC);

work better than:

  inb(WDT_DC);
  delay(2);

?

(i'm not suggesting you are wrong, this detail just fails to click at 
the moment.)

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 13:02                                                   ` Rene Herman
@ 2007-12-17 17:14                                                     ` H. Peter Anvin
  2007-12-17 19:43                                                       ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17 17:14 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, Paul Rolland, Alan Cox, Pavel Machek, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> 
> I do not know how universal that is, but _reading_ port 0xf0 might in 
> fact be sensible then? And should even work on a 386/387 pair? (I have a 
> 386/387 in fact, although I'd need to dig it up).
> 

No.  Someone might have used 0xf0 as a readonly port for other uses.

	-hpa


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15  2:13                     ` David P. Reed
  2007-12-15  2:20                         ` H. Peter Anvin
@ 2007-12-17 18:14                       ` linux-os (Dick Johnson)
  2007-12-17 18:54                           ` Rene Herman
  2007-12-19 15:03                         ` Avi Kivity
  2 siblings, 1 reply; 243+ messages in thread
From: linux-os (Dick Johnson) @ 2007-12-17 18:14 UTC (permalink / raw)
  To: David P. Reed
  Cc: Avi Kivity, Thomas Gleixner, Linux kernel, Ingo Molnar,
	H. Peter Anvin, Rene Herman, Pavel Machek, kvm-devel

[-- Attachment #1: Type: text/plain, Size: 2814 bytes --]


On Fri, 14 Dec 2007, David P. Reed wrote:

> Avi Kivity wrote:
>> kvm will forward a virtual machine's writes to port 0x80 to the real
>> port.  The reason is that the write is much faster than exiting and
>> emulating it; the difference is measurable when compiling kernels.
>>
>> Now if the cause is simply writing to port 0x80, then we must stop
>> doing that.  But if the reason is the back-to-back writes, when we can
>> keep it, since the other writes will be trapped by kvm and emulated.
>> Do you which is the case?
>>
> As for kvm, I don't have enough info to know anything about that.  Is
> there a test you'd like me to try?
>
> I think you are also asking if the crash on these laptops is caused only
> by back-to-back writes.  Actually, it doesn't seem to matter if they are
> back to back.  I can cause the crash if the writes to 80 are very much
> spread out in time - it seems only to matter how many of them get
> executed - almost as if there is a buffer overflow.  (And of course if
> you do back to back writes to other ports that are apparently fully
> unused, such as 0xED on my machine, no crash occurs).
>
> I believe (though no one seems to have confirming documentation from the
> chipset or motherboard vendor) that port 80 is actually functional for
> some unknown function on these machines.   (They do respond to "in"
> instructions faster than a bus cycle abort does - more evidence).
>
> I searched the DSDT to see if there is any evidence of an ACPI use for
> this port, but found nothing.
>
>

Attached is a patch that changes the outs to ins on port 0x80.
I did NOT let gcc decide what to do about modified registers.
Instead, the code saves/restores EAX itself so that all of the
times (whatever they are) are the same.

The code works and is running here. I also patched a very early
version (2.4.26) running on  a 400 MHz i486 with an real ISA
bus (Adaptec AHA1453). It works too.

David, will you please try it on your machine. Maybe reading
from the port is less harmful than writing.


Cheers,
Dick Johnson
Penguin : Linux version 2.6.22.1 on an i686 machine (5588.27 BogoMips).
My book : http://www.AbominableFirebug.com/
_


****************************************************************
The information transmitted in this message is confidential and may be privileged.  Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited.  If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.

[-- Attachment #2: io.h.patch --]
[-- Type: TEXT/PLAIN, Size: 429 bytes --]

--- linux-2.6.22.1/include/asm-i386/io.h.orig	2007-07-10 14:56:30.000000000 -0400
+++ linux-2.6.22.1/include/asm-i386/io.h	2007-12-17 12:06:10.000000000 -0500
@@ -252,7 +252,10 @@
 
 static inline void native_io_delay(void)
 {
-	asm volatile("outb %%al,$0x80" : : : "memory");
+	asm volatile(	"pushl %%eax\n\t"
+			"inb $0x80, %%al\n\t"
+			"popl %%eax\n\t"
+			 : : : "memory");
 }
 
 #if defined(CONFIG_PARAVIRT)

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
@ 2007-12-17 18:54                           ` Rene Herman
  0 siblings, 0 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17 18:54 UTC (permalink / raw)
  To: linux-os (Dick Johnson)
  Cc: David P. Reed, Avi Kivity, Thomas Gleixner, Linux kernel,
	Ingo Molnar, H. Peter Anvin, Pavel Machek, kvm-devel

On 17-12-07 19:14, linux-os (Dick Johnson) wrote:

> Attached is a patch that changes the outs to ins on port 0x80.

No, that isn't useful. Only a write is "guaranteed" to make ISA/LPC meaning 
the timing for a read varies wildly. See the in/out cycles results posted 
earlier. Was also reading the Intel PIIX(3) chiset datasheet today which 
specifically mentions that only writes flow through to ISA, reads do not.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
@ 2007-12-17 18:54                           ` Rene Herman
  0 siblings, 0 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17 18:54 UTC (permalink / raw)
  To: linux-os (Dick Johnson)
  Cc: kvm-devel, Linux kernel, Avi Kivity, David P. Reed, Ingo Molnar,
	Pavel Machek, H. Peter Anvin

On 17-12-07 19:14, linux-os (Dick Johnson) wrote:

> Attached is a patch that changes the outs to ins on port 0x80.

No, that isn't useful. Only a write is "guaranteed" to make ISA/LPC meaning 
the timing for a read varies wildly. See the in/out cycles results posted 
earlier. Was also reading the Intel PIIX(3) chiset datasheet today which 
specifically mentions that only writes flow through to ISA, reads do not.

Rene.

-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 14:39                                                       ` Ingo Molnar
  2007-12-17 16:12                                                         ` Alan Cox
@ 2007-12-17 19:38                                                         ` David P. Reed
  2007-12-17 19:55                                                           ` H. Peter Anvin
  2007-12-17 21:28                                                           ` Ingo Molnar
  1 sibling, 2 replies; 243+ messages in thread
From: David P. Reed @ 2007-12-17 19:38 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Rene Herman, H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Ingo -

I finished testing the rolled up patch that you provided.  It seems to 
work just fine.  Thank you for putting this all together and persevering 
in this long and complex discussion. 

Here are the results, on the offending laptop, using 2.6.24-rc5 plus 
that one patch.

First: booted with normal boot parameters (no io_delay=):

    According to dmesg, 0xed is used.

    hwclock ran fine, hundreds of times.
    my shell script loop doing "cat /dev/nvram > /dev/null" ran fine, 
several times.
    Running Rene's "port 80" speed test ran fine once, then froze the 
system hard.  (expected)

Second: booted with io_delay=0x80, several tests, rebooting after freezes:

    hwclock froze system hard.  (this is the problem that drove me to 
find this bug).
    my shell script loop froze system hard.

Third: booted with io_delay=none:

    hwclock ran fine, also hundreds of times.
    my shell script loop ran fine several times.
    Running rene's port80 test ran fine twice, froze system hard on 
third try.

Fourth: booted with io_delay=udelay:

    hwclock ran fine, also hundreds of times.
    my shell script loop ran fine several times.
    Running Rene's port80 test ran fine, froze system hard on second try.

Analysis:

    patch works fine, and default to 0xed seems super conservative.
    I will probably use the boot parameter io_delay=none, because I 
don't seem to have any I/O
    devices that require any delays - and this way I can find any that do.

Still wondering:

    what the heck is going on with port 80 on my laptop motherboard.  
Clearly it "does something".
    I will in my spare time continue investigating, though having a 
reliable system is GREAT.




   


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 17:14                                                     ` H. Peter Anvin
@ 2007-12-17 19:43                                                       ` David P. Reed
  2007-12-17 19:55                                                         ` H. Peter Anvin
  2007-12-17 21:25                                                         ` Alan Cox
  0 siblings, 2 replies; 243+ messages in thread
From: David P. Reed @ 2007-12-17 19:43 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Rene Herman, Ingo Molnar, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

H. Peter Anvin wrote:
> Rene Herman wrote:
>>
>> I do not know how universal that is, but _reading_ port 0xf0 might in 
>> fact be sensible then? And should even work on a 386/387 pair? (I 
>> have a 386/387 in fact, although I'd need to dig it up).
>>
>
> No.  Someone might have used 0xf0 as a readonly port for other uses.
>
As support: port 80 on the reporter's (my) HP dv9000z laptop clearly 
responds to reads differently than "unused" ports.  In particular, an 
inb takes 1/2 the elapsed time compared to a read to "known" unused port 
0xed - 792 tsc ticks for port 80 compared to about 1450 tsc ticks for 
port 0xed and other unused ports (tsc at 800 MHz).


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 19:38                                                         ` David P. Reed
@ 2007-12-17 19:55                                                           ` H. Peter Anvin
  2007-12-17 21:28                                                           ` Ingo Molnar
  1 sibling, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17 19:55 UTC (permalink / raw)
  To: David P. Reed
  Cc: Ingo Molnar, Rene Herman, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

David P. Reed wrote:
> 
> Still wondering:
> 
>    what the heck is going on with port 80 on my laptop motherboard.  
> Clearly it "does something".
>    I will in my spare time continue investigating, though having a 
> reliable system is GREAT.
> 

Almost guaranteed to be some kind of debugging hack, probably 
implemented either in the SuperIO chip or in SMM (or both).  When some 
sort of log buffer fills up, the system dies.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 19:43                                                       ` David P. Reed
@ 2007-12-17 19:55                                                         ` H. Peter Anvin
  2007-12-17 21:02                                                           ` David P. Reed
  2007-12-17 21:25                                                         ` Alan Cox
  1 sibling, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17 19:55 UTC (permalink / raw)
  To: David P. Reed
  Cc: Rene Herman, Ingo Molnar, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

David P. Reed wrote:
> H. Peter Anvin wrote:
>> Rene Herman wrote:
>>>
>>> I do not know how universal that is, but _reading_ port 0xf0 might in 
>>> fact be sensible then? And should even work on a 386/387 pair? (I 
>>> have a 386/387 in fact, although I'd need to dig it up).
>>>
>>
>> No.  Someone might have used 0xf0 as a readonly port for other uses.
>>
> As support: port 80 on the reporter's (my) HP dv9000z laptop clearly 
> responds to reads differently than "unused" ports.  In particular, an 
> inb takes 1/2 the elapsed time compared to a read to "known" unused port 
> 0xed - 792 tsc ticks for port 80 compared to about 1450 tsc ticks for 
> port 0xed and other unused ports (tsc at 800 MHz).
> 

Any timings for port 0xf0 (write zero), out of curiosity?

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 16:12                                                         ` Alan Cox
  2007-12-17 16:48                                                           ` Ingo Molnar
@ 2007-12-17 20:48                                                           ` Rene Herman
  2007-12-17 20:57                                                             ` H. Peter Anvin
  2007-12-17 21:41                                                             ` Ingo Molnar
  1 sibling, 2 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17 20:48 UTC (permalink / raw)
  To: Alan Cox
  Cc: Ingo Molnar, David P. Reed, H. Peter Anvin, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

[-- Attachment #1: Type: text/plain, Size: 988 bytes --]

On 17-12-07 17:12, Alan Cox wrote:

> I don't think we should be offering udelay based delays at this point.
> There are a lot of drivers to fix first. This is just one trivial example

I agree. This thread's too full of people calling this outb method a dumb 
hack. It's a well-known legacy PC thing and while in practice the udelay 
might be a functional replacement for a majority of cases (save the races 
you are finding) a delay proportional to the bus speed makes great sense 
certainly when talking to hardware that itself runs proportinal to the bus 
speed for example.

So, really, how about just sticking in this minimal version for now? Only 
switches the port to 0xed based on DMI and is all that is needed to fix the 
actual problem. This should be minimal and no-risk enough that it could also 
go to .24 if people want it to. It'll fix a few HP laptops (I'll try and 
get/verify the dv6000z DMI strings as well).

Ingo?

Signed-off-by: Rene Herman <rene.herman@gmail.com>

[-- Attachment #2: dmi-port80-minimal.diff --]
[-- Type: text/plain, Size: 9464 bytes --]

commit e5f4d11c2470550500e8d8b798d902f2fe07b5c4
Author: Rene Herman <rene.herman@gmail.com>
Date:   Mon Dec 17 21:23:55 2007 +0100

    x86: provide a DMI based port 0x80 I/O delay override.
    
    Certain (HP) laptops experience trouble from our port 0x80 I/O delay
    writes. This patch provides for a DMI based switch to the "alternate
    diagnostic port" 0xed (as used by some BIOSes as well) for these.
    
    David P. Reed confirmed that port 0xed works for him and provides a
    proper delay. The symptoms of _not_ working are a hanging machine,
    with "hwclock" use being a direct trigger.
    
    Earlier versions of this attempted to simply use udelay(2), with the
    2 being a value tested to be a nicely conservative upper-bound with
    help from many on the linux-kernel mailinglist, but that approach has
    two problems.
    
    First, pre-loops_per_jiffy calibration (which is post PIT init while
    some implementations of the PIT are actually one of the historically
    problematic devices that need the delay) udelay() isn't particularly
    well-defined. We could initialise loops_per_jiffy conservatively (and
    based on CPU family so as to not unduly delay old machines) which
    would sort of work, but still leaves:
    
    Second, delaying isn't the only effect that a write to port 0x80 has.
    It's also a PCI posting barrier which some devices may be explicitly
    or implicitly relying on. Alan Cox did a survey and found evidence
    that additionally various drivers are racy on SMP without the bus
    locking outb.
    
    Switching to an inb() makes the timing too unpredictable and as such,
    this DMI based switch should be the safest approach for now. Any more
    invasive changes should get more rigid testing first. It's moreover
    only very few machines with the problem and a DMI based hack seems
    to fit that situation.
    
    This does not change the io_delay() in the boot code which is using
    the same port 0x80 I/O delay but those do not appear to be a problem
    as tested by David P. Reed. He moreover reported that booting with
    "acpi=off" also fixed things and seeing as how ACPI isn't touched
    until after this DMI based I/O port switch leaving the ones in the
    boot code be is safe.
    
    The DMI strings from David's HP Pavilion dv9000z are in there already
    and we need to get/verify the DMI info from other machines with the
    problem, notably the HP Pavilion dv6000z.
    
    This patch is partly based on earlier patches from Pavel Machek and
    David P. Reed.
    
    Signed-off-by: Rene Herman <rene.herman@gmail.com>

diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
index b74d60d..288e162 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc_32.c
@@ -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)
diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
index 6ea015a..43e5fcc 100644
--- a/arch/x86/boot/compressed/misc_64.c
+++ b/arch/x86/boot/compressed/misc_64.c
@@ -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)
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index a7bc93c..0cc1981 100644
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -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/
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64
index 5a88890..08a68f0 100644
--- a/arch/x86/kernel/Makefile_64
+++ b/arch/x86/kernel/Makefile_64
@@ -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/
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
new file mode 100644
index 0000000..e736bab
--- /dev/null
+++ b/arch/x86/kernel/io_delay.c
@@ -0,0 +1,48 @@
+/*
+ * I/O delay strategies for inb_p/outb_p
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+
+/*
+ * Allow for a DMI based override of port 0x80
+ */
+#define IO_DELAY_PORT_STD 0x80
+#define IO_DELAY_PORT_ALT 0xed
+
+static unsigned short io_delay_port __read_mostly = IO_DELAY_PORT_STD;
+
+void native_io_delay(void)
+{
+	asm volatile ("outb %%al, %w0" : : "d" (io_delay_port));
+}
+EXPORT_SYMBOL(native_io_delay);
+
+static int __init dmi_io_delay_port_alt(const struct dmi_system_id *id)
+{
+	printk(KERN_NOTICE "%s: using alternate I/O delay port\n", id->ident);
+	io_delay_port = IO_DELAY_PORT_ALT;
+	return 0;
+}
+
+static struct dmi_system_id __initdata dmi_io_delay_port_alt_table[] = {
+	{
+		.callback	= dmi_io_delay_port_alt,
+		.ident		= "HP Pavilion dv9000z",
+		.matches	= {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME, "30B9")
+		}
+	},
+	{
+	}
+};
+
+void __init io_delay_init(void)
+{
+	dmi_check_system(dmi_io_delay_port_alt_table);
+}
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index e1e18c3..6c3a3b4 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -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	
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 30d94d1..ec976ed 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -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;
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index fe881cd..690b8f4 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -250,10 +250,8 @@ static inline void flush_write_buffers(void)
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void io_delay_init(void);
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index a037b07..b2d4994 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -35,13 +35,18 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+extern void io_delay_init(void);
+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..
@@ -50,21 +55,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) \

^ permalink raw reply related	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 20:48                                                           ` Rene Herman
@ 2007-12-17 20:57                                                             ` H. Peter Anvin
  2007-12-17 21:33                                                               ` Rene Herman
  2007-12-17 21:41                                                             ` Ingo Molnar
  1 sibling, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17 20:57 UTC (permalink / raw)
  To: Rene Herman
  Cc: Alan Cox, Ingo Molnar, David P. Reed, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> On 17-12-07 17:12, Alan Cox wrote:
> 
>> I don't think we should be offering udelay based delays at this point.
>> There are a lot of drivers to fix first. This is just one trivial example
> 
> I agree. This thread's too full of people calling this outb method a 
> dumb hack. It's a well-known legacy PC thing and while in practice the 
> udelay might be a functional replacement for a majority of cases (save 
> the races you are finding) a delay proportional to the bus speed makes 
> great sense certainly when talking to hardware that itself runs 
> proportinal to the bus speed for example.
> 
> So, really, how about just sticking in this minimal version for now? 
> Only switches the port to 0xed based on DMI and is all that is needed to 
> fix the actual problem. This should be minimal and no-risk enough that 
> it could also go to .24 if people want it to. It'll fix a few HP laptops 
> (I'll try and get/verify the dv6000z DMI strings as well).
> 

I think retaining the command-line option available is a good thing, 
though.  If nothing else, it is something very quick we can ask other 
people to try if they seem to have similar problems.

Other than that, this alternate-port patch is a low-impact patch not 
affecting hardware not on the blacklist, which makes it appropriate for 
2.6.24 IMO.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 19:55                                                         ` H. Peter Anvin
@ 2007-12-17 21:02                                                           ` David P. Reed
  2007-12-17 21:17                                                             ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2007-12-17 21:02 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Rene Herman, Ingo Molnar, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol



H. Peter Anvin wrote:
> David P. Reed wrote:
>> As support: port 80 on the reporter's (my) HP dv9000z laptop clearly 
>> responds to reads differently than "unused" ports.  In particular, an 
>> inb takes 1/2 the elapsed time compared to a read to "known" unused 
>> port 0xed - 792 tsc ticks for port 80 compared to about 1450 tsc 
>> ticks for port 0xed and other unused ports (tsc at 800 MHz).
>>
>
> Any timings for port 0xf0 (write zero), out of curiosity?
>

Here's a bunch of data:

port 0xF0: cycles: out 919, in 933
port 0xed: cycles: out 2541, in 2036
port 0x70: cycles: out n/a,  in 934
port 0x80: cycles: out 1424, in 795

AMD Turion 64x2 TL-60 CPU running at 800 MHz, nVidia MCP51 chipset, 
Quanta motherboard.  Running 2.6.24-rc5 with Ingo's patch so inb_p, etc. 
use port 0xed.

Note that I can run the port 80 test once, the second time I get the 
hard freeze.  I didn't try writing to port 70 from userspace - that 
one's dangerous, but the reading of it was included for a timing typical 
of a chipset supported device.  These are all pretty consistent.

I find the "read" timing from 0x80 verrrrry interesting.  The write 
timeing is also interesting, being faster than an unused port. 



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 23:29                           ` Alan Cox
  2007-12-15  3:04                             ` David P. Reed
  2007-12-15  8:08                             ` Paul Rolland
@ 2007-12-17 21:04                             ` Rene Herman
  2007-12-17 23:20                               ` Pavel Machek
  2 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-17 21:04 UTC (permalink / raw)
  To: Alan Cox
  Cc: H. Peter Anvin, Pavel Machek, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar

On 15-12-07 00:29, Alan Cox wrote:

>>> ?? Just initialize bogomips to 6GHz equivalent... and we are fine
>>> until 6GHz cpus come out.
>> How long will that take to boot on a 386?
> 
> Well the dumb approach to fix that would seem to be to initialise it to
> 
> 	cpu->family   3 -> 50MHz 4 -> 300Mhz 5-> etc...

By the way, you have a 300 MHz 486? I believe 3 -> 40, 4 -> 133, 5 -> 233 
would be good? And I'm not really sure about the etc. P6 has a large range 
again...

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 21:02                                                           ` David P. Reed
@ 2007-12-17 21:17                                                             ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17 21:17 UTC (permalink / raw)
  To: David P. Reed
  Cc: Rene Herman, Ingo Molnar, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

David P. Reed wrote:
> 
> Note that I can run the port 80 test once, the second time I get the 
> hard freeze.  I didn't try writing to port 70 from userspace - that 
> one's dangerous, but the reading of it was included for a timing typical 
> of a chipset supported device.  These are all pretty consistent.
> 
> I find the "read" timing from 0x80 verrrrry interesting.  The write 
> timeing is also interesting, being faster than an unused port.
> 

Once again: reading from port 0x80 goes to the DMA page device.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 19:43                                                       ` David P. Reed
  2007-12-17 19:55                                                         ` H. Peter Anvin
@ 2007-12-17 21:25                                                         ` Alan Cox
  2008-01-01 15:57                                                           ` David P. Reed
  2008-01-01 15:59                                                           ` David P. Reed
  1 sibling, 2 replies; 243+ messages in thread
From: Alan Cox @ 2007-12-17 21:25 UTC (permalink / raw)
  To: David P. Reed
  Cc: H. Peter Anvin, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

> responds to reads differently than "unused" ports.  In particular, an 
> inb takes 1/2 the elapsed time compared to a read to "known" unused port 
> 0xed - 792 tsc ticks for port 80 compared to about 1450 tsc ticks for 
> port 0xed and other unused ports (tsc at 800 MHz).

Well at least we know where the port is now - thats too fast for an LPC
bus device, so it must be an SMI trap.

Only easy way to find out is to use the debugging event counters and see
how many instruction cycles are issued as part of the 0x80 port. If its
suprisingly high then you've got a firmware bug and can go spank HP.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 19:38                                                         ` David P. Reed
  2007-12-17 19:55                                                           ` H. Peter Anvin
@ 2007-12-17 21:28                                                           ` Ingo Molnar
  1 sibling, 0 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-17 21:28 UTC (permalink / raw)
  To: David P. Reed
  Cc: Rene Herman, H. Peter Anvin, Paul Rolland, Alan Cox, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* David P. Reed <dpreed@reed.com> wrote:

> Ingo -
>
> I finished testing the rolled up patch that you provided.  It seems to work 
> just fine.  Thank you for putting this all together and persevering in this 
> long and complex discussion. 
> Here are the results, on the offending laptop, using 2.6.24-rc5 plus that 
> one patch.
>
> First: booted with normal boot parameters (no io_delay=):
>
>    According to dmesg, 0xed is used.
>
>    hwclock ran fine, hundreds of times.
>    my shell script loop doing "cat /dev/nvram > /dev/null" ran fine, 
> several times.
>    Running Rene's "port 80" speed test ran fine once, then froze the system 
> hard.  (expected)
>
> Second: booted with io_delay=0x80, several tests, rebooting after freezes:
>
>    hwclock froze system hard.  (this is the problem that drove me to find 
> this bug).
>    my shell script loop froze system hard.
>
> Third: booted with io_delay=none:
>
>    hwclock ran fine, also hundreds of times.
>    my shell script loop ran fine several times.
>    Running rene's port80 test ran fine twice, froze system hard on third 
> try.
>
> Fourth: booted with io_delay=udelay:
>
>    hwclock ran fine, also hundreds of times.
>    my shell script loop ran fine several times.
>    Running Rene's port80 test ran fine, froze system hard on second try.
>
> Analysis:
>
>    patch works fine, and default to 0xed seems super conservative. I 
> will probably use the boot parameter io_delay=none, because I don't 
> seem to have any I/O
>    devices that require any delays - and this way I can find any that 
>    do.

great, and thanks for the extensive testing! I've added this line to the 
patch:

 Tested-by: "David P. Reed" <dpreed@reed.com>

if you dont mind.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 20:57                                                             ` H. Peter Anvin
@ 2007-12-17 21:33                                                               ` Rene Herman
  2007-12-17 21:40                                                                 ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-17 21:33 UTC (permalink / raw)
  To: H. Peter Anvin, Ingo Molnar
  Cc: Rene Herman, Alan Cox, Ingo Molnar, David P. Reed, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, rol

[-- Attachment #1: Type: text/plain, Size: 1695 bytes --]

On 17-12-07 21:57, H. Peter Anvin wrote:

> Rene Herman wrote:
>> On 17-12-07 17:12, Alan Cox wrote:
>>
>>> I don't think we should be offering udelay based delays at this point.
>>> There are a lot of drivers to fix first. This is just one trivial 
>>> example
>>
>> I agree. This thread's too full of people calling this outb method a 
>> dumb hack. It's a well-known legacy PC thing and while in practice the 
>> udelay might be a functional replacement for a majority of cases (save 
>> the races you are finding) a delay proportional to the bus speed makes 
>> great sense certainly when talking to hardware that itself runs 
>> proportinal to the bus speed for example.
>>
>> So, really, how about just sticking in this minimal version for now? 
>> Only switches the port to 0xed based on DMI and is all that is needed 
>> to fix the actual problem. This should be minimal and no-risk enough 
>> that it could also go to .24 if people want it to. It'll fix a few HP 
>> laptops (I'll try and get/verify the dv6000z DMI strings as well).
>>
> 
> I think retaining the command-line option available is a good thing, 
> though.  If nothing else, it is something very quick we can ask other 
> people to try if they seem to have similar problems.

Well, yes, I guess that does make sense. It's back again. Named the choices 
"standard" and "alternate" again as I feel "0x80" and "0xed" suggest they're 
free values a bit too much but if anyone feels strongly about it, so be it.

> Other than that, this alternate-port patch is a low-impact patch not 
> affecting hardware not on the blacklist, which makes it appropriate for 
> 2.6.24 IMO.

Signed-off-by: Rene Herman <rene.herman@gmail.com>

[-- Attachment #2: dmi-port80-minimal-bootparam.diff --]
[-- Type: text/plain, Size: 10720 bytes --]

commit c83008ff40e95f89407807cb122127c5444b3bc4
Author: Rene Herman <rene.herman@gmail.com>
Date:   Mon Dec 17 21:23:55 2007 +0100

    x86: provide a DMI based port 0x80 I/O delay override.
    
    Certain (HP) laptops experience trouble from our port 0x80 I/O delay
    writes. This patch provides for a DMI based switch to the "alternate
    diagnostic port" 0xed (as used by some BIOSes as well) for these.
    
    David P. Reed confirmed that port 0xed works for him and provides a
    proper delay. The symptoms of _not_ working are a hanging machine,
    with "hwclock" use being a direct trigger.
    
    Earlier versions of this attempted to simply use udelay(2), with the
    2 being a value tested to be a nicely conservative upper-bound with
    help from many on the linux-kernel mailinglist, but that approach has
    two problems.
    
    First, pre-loops_per_jiffy calibration (which is post PIT init while
    some implementations of the PIT are actually one of the historically
    problematic devices that need the delay) udelay() isn't particularly
    well-defined. We could initialise loops_per_jiffy conservatively (and
    based on CPU family so as to not unduly delay old machines) which
    would sort of work, but still leaves:
    
    Second, delaying isn't the only effect that a write to port 0x80 has.
    It's also a PCI posting barrier which some devices may be explicitly
    or implicitly relying on. Alan Cox did a survey and found evidence
    that additionally various drivers are racy on SMP without the bus
    locking outb.
    
    Switching to an inb() makes the timing too unpredictable and as such,
    this DMI based switch should be the safest approach for now. Any more
    invasive changes should get more rigid testing first. It's moreover
    only very few machines with the problem and a DMI based hack seems
    to fit that situation.
    
    An early boot parameter to make the choice manually (and override any
    possible DMI based decision) is also provided:
    
    	io_delay=standard|alternate
    
    This does not change the io_delay() in the boot code which is using
    the same port 0x80 I/O delay but those do not appear to be a problem
    as tested by David P. Reed. He moreover reported that booting with
    "acpi=off" also fixed things and seeing as how ACPI isn't touched
    until after this DMI based I/O port switch leaving the ones in the
    boot code be is safe.
    
    The DMI strings from David's HP Pavilion dv9000z are in there already
    and we need to get/verify the DMI info from other machines with the
    problem, notably the HP Pavilion dv6000z.
    
    This patch is partly based on earlier patches from Pavel Machek and
    David P. Reed.
    
    Signed-off-by: Rene Herman <rene.herman@gmail.com>

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 33121d6..ff66cf4 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -785,6 +785,13 @@ 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 port
+		standard
+			Use the 0x80 standard I/O delay port (default)
+		alternate
+			Use the 0xed alternate I/O delay port
+
+			Use the
 	io7=		[HW] IO7 for Marvel based alpha systems
 			See comment before marvel_specify_io7 in
 			arch/alpha/kernel/core_marvel.c.
diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
index b74d60d..288e162 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc_32.c
@@ -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)
diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
index 6ea015a..43e5fcc 100644
--- a/arch/x86/boot/compressed/misc_64.c
+++ b/arch/x86/boot/compressed/misc_64.c
@@ -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)
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index a7bc93c..0cc1981 100644
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -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/
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64
index 5a88890..08a68f0 100644
--- a/arch/x86/kernel/Makefile_64
+++ b/arch/x86/kernel/Makefile_64
@@ -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/
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
new file mode 100644
index 0000000..5029e7a
--- /dev/null
+++ b/arch/x86/kernel/io_delay.c
@@ -0,0 +1,69 @@
+/*
+ * I/O delay strategies for inb_p/outb_p
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+
+/*
+ * Allow for a DMI based override of port 0x80
+ */
+#define IO_DELAY_PORT_STD 0x80
+#define IO_DELAY_PORT_ALT 0xed
+
+static unsigned short io_delay_port __read_mostly = IO_DELAY_PORT_STD;
+
+void native_io_delay(void)
+{
+	asm volatile ("outb %%al, %w0" : : "d" (io_delay_port));
+}
+EXPORT_SYMBOL(native_io_delay);
+
+static int __init dmi_io_delay_port_alt(const struct dmi_system_id *id)
+{
+	printk(KERN_NOTICE "%s: using alternate I/O delay port\n", id->ident);
+	io_delay_port = IO_DELAY_PORT_ALT;
+	return 0;
+}
+
+static struct dmi_system_id __initdata dmi_io_delay_port_alt_table[] = {
+	{
+		.callback	= dmi_io_delay_port_alt,
+		.ident		= "HP Pavilion dv9000z",
+		.matches	= {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME, "30B9")
+		}
+	},
+	{
+	}
+};
+
+static int __initdata io_delay_override;
+
+static int __init io_delay_param(char *s)
+{
+	if (!s)
+		return -EINVAL;
+
+	if (!strcmp(s, "standard"))
+		io_delay_port = IO_DELAY_PORT_STD;
+	else if (!strcmp(s, "alternate"))
+		io_delay_port = IO_DELAY_PORT_ALT;
+	else
+		return -EINVAL;
+
+	io_delay_override = 1;
+	return 0;
+}
+
+early_param("io_delay", io_delay_param);
+
+void __init io_delay_init(void)
+{
+	if (!io_delay_override)
+		dmi_check_system(dmi_io_delay_port_alt_table);
+}
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index e1e18c3..6c3a3b4 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -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	
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 30d94d1..ec976ed 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -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;
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index fe881cd..690b8f4 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -250,10 +250,8 @@ static inline void flush_write_buffers(void)
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void io_delay_init(void);
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index a037b07..b2d4994 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -35,13 +35,18 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+extern void io_delay_init(void);
+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..
@@ -50,21 +55,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) \

^ permalink raw reply related	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 21:33                                                               ` Rene Herman
@ 2007-12-17 21:40                                                                 ` H. Peter Anvin
  2007-12-17 21:46                                                                   ` Ingo Molnar
  2007-12-17 21:50                                                                   ` Rene Herman
  0 siblings, 2 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17 21:40 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, Alan Cox, Ingo Molnar, David P. Reed, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, rol

Rene Herman wrote:
> 
> Well, yes, I guess that does make sense. It's back again. Named the 
> choices "standard" and "alternate" again as I feel "0x80" and "0xed" 
> suggest they're free values a bit too much but if anyone feels strongly 
> about it, so be it.
> 

They ARE -- or really, should be, free values (0xeb and 0xf0 are other 
reasonable values, for example.)

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 20:48                                                           ` Rene Herman
  2007-12-17 20:57                                                             ` H. Peter Anvin
@ 2007-12-17 21:41                                                             ` Ingo Molnar
  2007-12-17 21:47                                                               ` Rene Herman
  1 sibling, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-17 21:41 UTC (permalink / raw)
  To: Rene Herman
  Cc: Alan Cox, David P. Reed, H. Peter Anvin, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* Rene Herman <rene.herman@gmail.com> wrote:

> On 17-12-07 17:12, Alan Cox wrote:
>
>> I don't think we should be offering udelay based delays at this point.
>> There are a lot of drivers to fix first. This is just one trivial example
>
> I agree. This thread's too full of people calling this outb method a 
> dumb hack. It's a well-known legacy PC thing and while in practice the 
> udelay might be a functional replacement for a majority of cases (save 
> the races you are finding) a delay proportional to the bus speed makes 
> great sense certainly when talking to hardware that itself runs 
> proportinal to the bus speed for example.
>
> So, really, how about just sticking in this minimal version for now? 
> Only switches the port to 0xed based on DMI and is all that is needed 
> to fix the actual problem. This should be minimal and no-risk enough 
> that it could also go to .24 if people want it to. It'll fix a few HP 
> laptops (I'll try and get/verify the dv6000z DMI strings as well).
>
> Ingo?
>
> Signed-off-by: Rene Herman <rene.herman@gmail.com>

hm, i see this as a step backwards from the pretty flexible patch that 
David already tested. (and which also passed a few hundred bootup tests 
on my x86 test-grid)

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 21:40                                                                 ` H. Peter Anvin
@ 2007-12-17 21:46                                                                   ` Ingo Molnar
  2007-12-17 21:50                                                                   ` Rene Herman
  1 sibling, 0 replies; 243+ messages in thread
From: Ingo Molnar @ 2007-12-17 21:46 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Rene Herman, Ingo Molnar, Alan Cox, David P. Reed, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, rol


* H. Peter Anvin <hpa@zytor.com> wrote:

> Rene Herman wrote:
>>
>> Well, yes, I guess that does make sense. It's back again. Named the 
>> choices "standard" and "alternate" again as I feel "0x80" and "0xed" 
>> suggest they're free values a bit too much but if anyone feels 
>> strongly about it, so be it.
>
> They ARE -- or really, should be, free values (0xeb and 0xf0 are other 
> reasonable values, for example.)

yeah. We've got the variant below for now, tested by David. We can still 
change things later on if the need arises.

	Ingo

-------------->
Subject: x86: provide a DMI based port 0x80 I/O delay override.
From: Rene Herman <rene.herman@gmail.com>

x86: provide a DMI based port 0x80 I/O delay override.

Certain (HP) laptops experience trouble from our port 0x80 I/O delay
writes. This patch provides for a DMI based switch to the "alternate
diagnostic port" 0xed (as used by some BIOSes as well) for these.

David P. Reed confirmed that port 0xed works for him and provides a
proper delay. The symptoms of _not_ working are a hanging machine,
with "hwclock" use being a direct trigger.

Earlier versions of this attempted to simply use udelay(2), with the
2 being a value tested to be a nicely conservative upper-bound with
help from many on the linux-kernel mailinglist but that approach has
two problems.

First, pre-loops_per_jiffy calibration (which is post PIT init while
some implementations of the PIT are actually one of the historically
problematic devices that need the delay) udelay() isn't particularly
well-defined. We could initialise loops_per_jiffy conservatively (and
based on CPU family so as to not unduly delay old machines) which
would sort of work, but...

Second, delaying isn't the only effect that a write to port 0x80 has.
It's also a PCI posting barrier which some devices may be explicitly
or implicitly relying on. Alan Cox did a survey and found evidence
that additionally some drivers may be racy on SMP without the bus
locking outb.

Switching to an inb() makes the timing too unpredictable and as such,
this DMI based switch should be the safest approach for now. Any more
invasive changes should get more rigid testing first. It's moreover
only very few machines with the problem and a DMI based hack seems
to fit that situation.

This also introduces a command-line parameter "io_delay" to override
the DMI based choice again:

	io_delay=<0x80|0xed|udelay|none>

where 0x80 means using the standard port 0x80 and 0xed means the
alternate port 0xed.

All these methods can also be selected via the kernel .config,
and can be runtime tuned via /proc/sys/kernel/io_delay_type (for
debugging purposes).

The DMI strings from David's HP Pavilion dv9000z are in there already
and we need to get/verify the DMI info from other machines with the
problem, notably the HP Pavilion dv6000z.

This patch is partly based on earlier patches from Pavel Machek and
David P. Reed.

[ mingo@elte.hu:
  - add the io_delay=none method
  - make each method selectable from the kernel config
  - eliminate the indirect function calls
  - add the /proc/sys/kernel/io_delay_type sysctl
  - change 'standard' and 'alternate' to 0x80 and 0xed
  - make the io delay config not depend on CONFIG_DEBUG_KERNEL ]

Signed-off-by: Rene Herman <rene.herman@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: "David P. Reed" <dpreed@reed.com>
---
 Documentation/kernel-parameters.txt |   10 +++
 arch/x86/Kconfig.debug              |   74 +++++++++++++++++++++++++++
 arch/x86/boot/compressed/misc_32.c  |    8 +-
 arch/x86/boot/compressed/misc_64.c  |    8 +-
 arch/x86/kernel/Makefile_32         |    2 
 arch/x86/kernel/Makefile_64         |    2 
 arch/x86/kernel/io_delay.c          |   98 ++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/setup_32.c          |    2 
 arch/x86/kernel/setup_64.c          |    2 
 include/asm-x86/io_32.h             |    8 +-
 include/asm-x86/io_64.h             |   29 ++++++----
 kernel/sysctl.c                     |    9 +++
 12 files changed, 227 insertions(+), 25 deletions(-)

Index: linux-x86.q/Documentation/kernel-parameters.txt
===================================================================
--- linux-x86.q.orig/Documentation/kernel-parameters.txt
+++ linux-x86.q/Documentation/kernel-parameters.txt
@@ -785,6 +785,16 @@ and is between 256 and 4096 characters. 
 			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
+		0x80
+			Standard port 0x80 based delay
+		0xed
+			Alternate port 0xed based delay (needed on some systems)
+		udelay
+			Simple two microseconds delay
+		none
+			No delay
+
 	io7=		[HW] IO7 for Marvel based alpha systems
 			See comment before marvel_specify_io7 in
 			arch/alpha/kernel/core_marvel.c.
Index: linux-x86.q/arch/x86/Kconfig.debug
===================================================================
--- linux-x86.q.orig/arch/x86/Kconfig.debug
+++ linux-x86.q/arch/x86/Kconfig.debug
@@ -112,4 +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.
 
+#
+# 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
+	  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
Index: linux-x86.q/arch/x86/boot/compressed/misc_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_32.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_32.c
@@ -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)
Index: linux-x86.q/arch/x86/boot/compressed/misc_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_64.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_64.c
@@ -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)
Index: linux-x86.q/arch/x86/kernel/Makefile_32
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/Makefile_32
+++ linux-x86.q/arch/x86/kernel/Makefile_32
@@ -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/
Index: linux-x86.q/arch/x86/kernel/Makefile_64
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/Makefile_64
+++ linux-x86.q/arch/x86/kernel/Makefile_64
@@ -11,7 +11,7 @@ obj-y	:= process_64.o signal_64.o entry_
 		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/
Index: linux-x86.q/arch/x86/kernel/io_delay.c
===================================================================
--- /dev/null
+++ linux-x86.q/arch/x86/kernel/io_delay.c
@@ -0,0 +1,98 @@
+/*
+ * 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);
Index: linux-x86.q/arch/x86/kernel/setup_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/setup_32.c
+++ linux-x86.q/arch/x86/kernel/setup_32.c
@@ -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	
Index: linux-x86.q/arch/x86/kernel/setup_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/setup_64.c
+++ linux-x86.q/arch/x86/kernel/setup_64.c
@@ -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;
Index: linux-x86.q/include/asm-x86/io_32.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_32.h
+++ linux-x86.q/include/asm-x86/io_32.h
@@ -250,10 +250,10 @@ static inline void flush_write_buffers(v
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+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>
Index: linux-x86.q/include/asm-x86/io_64.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_64.h
+++ linux-x86.q/include/asm-x86/io_64.h
@@ -35,13 +35,20 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+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();
 #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..
@@ -50,21 +57,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) \
Index: linux-x86.q/kernel/sysctl.c
===================================================================
--- linux-x86.q.orig/kernel/sysctl.c
+++ linux-x86.q/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);
@@ -683,6 +684,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)
 	{

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 21:41                                                             ` Ingo Molnar
@ 2007-12-17 21:47                                                               ` Rene Herman
  2007-12-17 21:56                                                                 ` Ingo Molnar
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-17 21:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Rene Herman, Alan Cox, David P. Reed, H. Peter Anvin,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

[-- Attachment #1: Type: text/plain, Size: 1752 bytes --]

On 17-12-07 22:41, Ingo Molnar wrote:
> * Rene Herman <rene.herman@gmail.com> wrote:
> 
>> On 17-12-07 17:12, Alan Cox wrote:
>>
>>> I don't think we should be offering udelay based delays at this point.
>>> There are a lot of drivers to fix first. This is just one trivial example
>> I agree. This thread's too full of people calling this outb method a 
>> dumb hack. It's a well-known legacy PC thing and while in practice the 
>> udelay might be a functional replacement for a majority of cases (save 
>> the races you are finding) a delay proportional to the bus speed makes 
>> great sense certainly when talking to hardware that itself runs 
>> proportinal to the bus speed for example.
>>
>> So, really, how about just sticking in this minimal version for now? 
>> Only switches the port to 0xed based on DMI and is all that is needed 
>> to fix the actual problem. This should be minimal and no-risk enough 
>> that it could also go to .24 if people want it to. It'll fix a few HP 
>> laptops (I'll try and get/verify the dv6000z DMI strings as well).
>>
>> Ingo?
>>
>> Signed-off-by: Rene Herman <rene.herman@gmail.com>
> 
> hm, i see this as a step backwards from the pretty flexible patch that 
> David already tested. (and which also passed a few hundred bootup tests 
> on my x86 test-grid)

Please see Alan's comment that udelay (and none) shouldn't yet be provided 
as a choice. It opens race windows in drivers even when it works in practice 
on most setups. The version with "udelay" and "none" is not minimal, not low 
risk and certainly not .24 material.

David tested this part of the patch just as well.

Attached again (with the boot param) since I see I left in an extraneous 
'Use the" in the kernel-parameters.txt file.

Rene.

[-- Attachment #2: dmi-port80-minimal-bootparam.diff --]
[-- Type: text/plain, Size: 10708 bytes --]

commit c12c7a47b9af87e8d867d5aa0ca5c6bcdd2463da
Author: Rene Herman <rene.herman@gmail.com>
Date:   Mon Dec 17 21:23:55 2007 +0100

    x86: provide a DMI based port 0x80 I/O delay override.
    
    Certain (HP) laptops experience trouble from our port 0x80 I/O delay
    writes. This patch provides for a DMI based switch to the "alternate
    diagnostic port" 0xed (as used by some BIOSes as well) for these.
    
    David P. Reed confirmed that port 0xed works for him and provides a
    proper delay. The symptoms of _not_ working are a hanging machine,
    with "hwclock" use being a direct trigger.
    
    Earlier versions of this attempted to simply use udelay(2), with the
    2 being a value tested to be a nicely conservative upper-bound with
    help from many on the linux-kernel mailinglist, but that approach has
    two problems.
    
    First, pre-loops_per_jiffy calibration (which is post PIT init while
    some implementations of the PIT are actually one of the historically
    problematic devices that need the delay) udelay() isn't particularly
    well-defined. We could initialise loops_per_jiffy conservatively (and
    based on CPU family so as to not unduly delay old machines) which
    would sort of work, but still leaves:
    
    Second, delaying isn't the only effect that a write to port 0x80 has.
    It's also a PCI posting barrier which some devices may be explicitly
    or implicitly relying on. Alan Cox did a survey and found evidence
    that additionally various drivers are racy on SMP without the bus
    locking outb.
    
    Switching to an inb() makes the timing too unpredictable and as such,
    this DMI based switch should be the safest approach for now. Any more
    invasive changes should get more rigid testing first. It's moreover
    only very few machines with the problem and a DMI based hack seems
    to fit that situation.
    
    An early boot parameter to make the choice manually (and override any
    possible DMI based decision) is also provided:
    
    	io_delay=standard|alternate
    
    This does not change the io_delay() in the boot code which is using
    the same port 0x80 I/O delay but those do not appear to be a problem
    as tested by David P. Reed. He moreover reported that booting with
    "acpi=off" also fixed things and seeing as how ACPI isn't touched
    until after this DMI based I/O port switch leaving the ones in the
    boot code be is safe.
    
    The DMI strings from David's HP Pavilion dv9000z are in there already
    and we need to get/verify the DMI info from other machines with the
    problem, notably the HP Pavilion dv6000z.
    
    This patch is partly based on earlier patches from Pavel Machek and
    David P. Reed.
    
    Signed-off-by: Rene Herman <rene.herman@gmail.com>

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 33121d6..6948e25 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -785,6 +785,12 @@ 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 port
+		standard
+			Use the 0x80 standard I/O delay port (default)
+		alternate
+			Use the 0xed alternate I/O delay port
+
 	io7=		[HW] IO7 for Marvel based alpha systems
 			See comment before marvel_specify_io7 in
 			arch/alpha/kernel/core_marvel.c.
diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
index b74d60d..288e162 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc_32.c
@@ -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)
diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
index 6ea015a..43e5fcc 100644
--- a/arch/x86/boot/compressed/misc_64.c
+++ b/arch/x86/boot/compressed/misc_64.c
@@ -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)
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index a7bc93c..0cc1981 100644
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -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/
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64
index 5a88890..08a68f0 100644
--- a/arch/x86/kernel/Makefile_64
+++ b/arch/x86/kernel/Makefile_64
@@ -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/
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
new file mode 100644
index 0000000..5029e7a
--- /dev/null
+++ b/arch/x86/kernel/io_delay.c
@@ -0,0 +1,69 @@
+/*
+ * I/O delay strategies for inb_p/outb_p
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+
+/*
+ * Allow for a DMI based override of port 0x80
+ */
+#define IO_DELAY_PORT_STD 0x80
+#define IO_DELAY_PORT_ALT 0xed
+
+static unsigned short io_delay_port __read_mostly = IO_DELAY_PORT_STD;
+
+void native_io_delay(void)
+{
+	asm volatile ("outb %%al, %w0" : : "d" (io_delay_port));
+}
+EXPORT_SYMBOL(native_io_delay);
+
+static int __init dmi_io_delay_port_alt(const struct dmi_system_id *id)
+{
+	printk(KERN_NOTICE "%s: using alternate I/O delay port\n", id->ident);
+	io_delay_port = IO_DELAY_PORT_ALT;
+	return 0;
+}
+
+static struct dmi_system_id __initdata dmi_io_delay_port_alt_table[] = {
+	{
+		.callback	= dmi_io_delay_port_alt,
+		.ident		= "HP Pavilion dv9000z",
+		.matches	= {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME, "30B9")
+		}
+	},
+	{
+	}
+};
+
+static int __initdata io_delay_override;
+
+static int __init io_delay_param(char *s)
+{
+	if (!s)
+		return -EINVAL;
+
+	if (!strcmp(s, "standard"))
+		io_delay_port = IO_DELAY_PORT_STD;
+	else if (!strcmp(s, "alternate"))
+		io_delay_port = IO_DELAY_PORT_ALT;
+	else
+		return -EINVAL;
+
+	io_delay_override = 1;
+	return 0;
+}
+
+early_param("io_delay", io_delay_param);
+
+void __init io_delay_init(void)
+{
+	if (!io_delay_override)
+		dmi_check_system(dmi_io_delay_port_alt_table);
+}
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index e1e18c3..6c3a3b4 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -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	
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 30d94d1..ec976ed 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -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;
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index fe881cd..690b8f4 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -250,10 +250,8 @@ static inline void flush_write_buffers(void)
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+extern void io_delay_init(void);
+extern void native_io_delay(void);
 
 #if defined(CONFIG_PARAVIRT)
 #include <asm/paravirt.h>
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index a037b07..b2d4994 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -35,13 +35,18 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+extern void io_delay_init(void);
+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..
@@ -50,21 +55,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) \

^ permalink raw reply related	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 21:40                                                                 ` H. Peter Anvin
  2007-12-17 21:46                                                                   ` Ingo Molnar
@ 2007-12-17 21:50                                                                   ` Rene Herman
  1 sibling, 0 replies; 243+ messages in thread
From: Rene Herman @ 2007-12-17 21:50 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Rene Herman, Ingo Molnar, Alan Cox, Ingo Molnar, David P. Reed,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel, rol

On 17-12-07 22:40, H. Peter Anvin wrote:

> Rene Herman wrote:
>>
>> Well, yes, I guess that does make sense. It's back again. Named the 
>> choices "standard" and "alternate" again as I feel "0x80" and "0xed" 
>> suggest they're free values a bit too much but if anyone feels 
>> strongly about it, so be it.
>>
> 
> They ARE -- or really, should be, free values (0xeb and 0xf0 are other 
> reasonable values, for example.)

I was afraid someone would say that. Making a random port available is fine 
for testing purposes but a failry dangerous thing to do generally. For a 
minimal version at -rc4 time, I believe sticking with 0x80 and 0xed ie best.

Lots of time during .25 to go wild...

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 21:47                                                               ` Rene Herman
@ 2007-12-17 21:56                                                                 ` Ingo Molnar
  2007-12-17 22:01                                                                   ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2007-12-17 21:56 UTC (permalink / raw)
  To: Rene Herman
  Cc: Alan Cox, David P. Reed, H. Peter Anvin, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* Rene Herman <rene.herman@gmail.com> wrote:

>>> Signed-off-by: Rene Herman <rene.herman@gmail.com>
>>
>> hm, i see this as a step backwards from the pretty flexible patch 
>> that David already tested. (and which also passed a few hundred 
>> bootup tests on my x86 test-grid)
>
> Please see Alan's comment that udelay (and none) shouldn't yet be 
> provided as a choice. It opens race windows in drivers even when it 
> works in practice on most setups. The version with "udelay" and "none" 
> is not minimal, not low risk and certainly not .24 material.

huh? By default we still use port 0x80. Any udelay is non-default and 
needs the user to explicitly switch to it. But it enables us to debug 
any suspected drivers by asking testers to: "please try this driver with 
io_delay=udelay, does it still work fine?". So those extra options are 
quite sensible. If you have any real technical arguments against that 
then please let us know.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 21:56                                                                 ` Ingo Molnar
@ 2007-12-17 22:01                                                                   ` Rene Herman
  2007-12-17 22:18                                                                     ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2007-12-17 22:01 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Rene Herman, Alan Cox, David P. Reed, H. Peter Anvin,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On 17-12-07 22:56, Ingo Molnar wrote:

> * Rene Herman <rene.herman@gmail.com> wrote:
> 
>>>> Signed-off-by: Rene Herman <rene.herman@gmail.com>
>>> hm, i see this as a step backwards from the pretty flexible patch 
>>> that David already tested. (and which also passed a few hundred 
>>> bootup tests on my x86 test-grid)
>> Please see Alan's comment that udelay (and none) shouldn't yet be 
>> provided as a choice. It opens race windows in drivers even when it 
>> works in practice on most setups. The version with "udelay" and "none" 
>> is not minimal, not low risk and certainly not .24 material.
> 
> huh? By default we still use port 0x80. Any udelay is non-default and 
> needs the user to explicitly switch to it.  But it enables us to debug
> any suspected drivers by asking testers to: "please try this driver with 
> io_delay=udelay, does it still work fine?". So those extra options are 
> quite sensible. If you have any real technical arguments against that 
> then please let us know.

Ingo, have lots of fun playing with yourself, but remove my sign off from 
anything with the udelay and none methods.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 22:01                                                                   ` Rene Herman
@ 2007-12-17 22:18                                                                     ` David P. Reed
  0 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2007-12-17 22:18 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, Alan Cox, H. Peter Anvin, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Besides the two reports of freezes on bugzilla.kernel.org (9511, 6307), 
the following two bug reports on bugzilla.redhat.com are almost 
certainly due to the same cause (imo, of course): 245834, 227234.

Ubuntu launchpad bug 158849 also seems to report the same problem, for 
an HP dv6258se 64-bit machine.

Also this one: 
http://www.mail-archive.com/linux-acpi@vger.kernel.org/msg10321.html

If you want to collect dmidecode data from these folks, perhaps we might 
get a wider sense of what categories of machines are affected.  They all 
seem to be recemt HP and Compaq AMD64 laptops, probably all Quanta 
motherboards.



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-14 22:13                         ` H. Peter Anvin
  2007-12-14 23:29                           ` Alan Cox
@ 2007-12-17 22:46                           ` Jan Engelhardt
  1 sibling, 0 replies; 243+ messages in thread
From: Jan Engelhardt @ 2007-12-17 22:46 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Pavel Machek, Ingo Molnar, David P. Reed, Thomas Gleixner,
	linux-kernel, Ingo Molnar, Rene Herman


On Dec 14 2007 14:13, H. Peter Anvin wrote:
>> 
>> ?? Just initialize bogomips to 6GHz equivalent... and we are fine
>> until 6GHz cpus come out.
>
> How long will that take to boot on a 386?
>
Load it up in bochs and have look at the wallclock. I think that is a
good estimate when you have no real 386 nearby.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-15 17:46                                   ` Alan Cox
@ 2007-12-17 22:50                                     ` Jan Engelhardt
  2007-12-17 22:52                                       ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: Jan Engelhardt @ 2007-12-17 22:50 UTC (permalink / raw)
  To: Alan Cox
  Cc: David P. Reed, H. Peter Anvin, Pavel Machek, Ingo Molnar,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman


On Dec 15 2007 17:46, Alan Cox wrote:
>
>> My understanding is that the linux starts in real mode, and uses the 
>> BIOS for such things as reading the very first image.   
>
>Not always. We may enter from 32bit in some cases, and we may also not
>have a PC BIOS in the first place.

Computers without a PC BIOS (I'm trying to think of something, e.g.
the typical SUN sparc64 box) should have other means of accessing a
clocksource, no?

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-17 22:50                                     ` Jan Engelhardt
@ 2007-12-17 22:52                                       ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2007-12-17 22:52 UTC (permalink / raw)
  To: Jan Engelhardt
  Cc: Alan Cox, David P. Reed, Pavel Machek, Ingo Molnar,
	Thomas Gleixner, linux-kernel, Ingo Molnar, Rene Herman

Jan Engelhardt wrote:
> On Dec 15 2007 17:46, Alan Cox wrote:
>>> My understanding is that the linux starts in real mode, and uses the 
>>> BIOS for such things as reading the very first image.   
>> Not always. We may enter from 32bit in some cases, and we may also not
>> have a PC BIOS in the first place.
> 
> Computers without a PC BIOS (I'm trying to think of something, e.g.
> the typical SUN sparc64 box) should have other means of accessing a
> clocksource, no?

We were talking about x86 here, though.

Even on x86 we sometimes run from the 32-bit entrypoint.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-17 21:04                             ` Rene Herman
@ 2007-12-17 23:20                               ` Pavel Machek
  2007-12-18  0:06                                 ` Alan Cox
  0 siblings, 1 reply; 243+ messages in thread
From: Pavel Machek @ 2007-12-17 23:20 UTC (permalink / raw)
  To: Rene Herman
  Cc: Alan Cox, H. Peter Anvin, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar

On Mon 2007-12-17 22:04:19, Rene Herman wrote:
> On 15-12-07 00:29, Alan Cox wrote:
>
>>>> ?? Just initialize bogomips to 6GHz equivalent... and we are fine
>>>> until 6GHz cpus come out.
>>> How long will that take to boot on a 386?
>> Well the dumb approach to fix that would seem to be to initialise it to
>> 	cpu->family   3 -> 50MHz 4 -> 300Mhz 5-> etc...
>
> By the way, you have a 300 MHz 486? I believe 3 -> 40, 4 -> 133, 5 -> 233 
> would be good? And I'm not really sure about the etc. P6 has a large range 
> again...

Some nexgen 5x86 boxes were pretty fast, still could not do 486... so
family 3 iirc.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-17 23:20                               ` Pavel Machek
@ 2007-12-18  0:06                                 ` Alan Cox
  2007-12-18 15:49                                   ` Lennart Sorensen
  0 siblings, 1 reply; 243+ messages in thread
From: Alan Cox @ 2007-12-18  0:06 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Rene Herman, H. Peter Anvin, Ingo Molnar, David P. Reed,
	Thomas Gleixner, linux-kernel, Ingo Molnar

> > By the way, you have a 300 MHz 486? I believe 3 -> 40, 4 -> 133, 5 -> 233 
> > would be good? And I'm not really sure about the etc. P6 has a large range 
> > again...
> 
> Some nexgen 5x86 boxes were pretty fast, still could not do 486... so
> family 3 iirc.

300MHz 486 -> Nat Semi Geode.

NextGen as you say are 386 - 586 depending on the BIOS hypercode but I
believe lack WP even in > 386 mode.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-18  0:06                                 ` Alan Cox
@ 2007-12-18 15:49                                   ` Lennart Sorensen
  0 siblings, 0 replies; 243+ messages in thread
From: Lennart Sorensen @ 2007-12-18 15:49 UTC (permalink / raw)
  To: Alan Cox
  Cc: Pavel Machek, Rene Herman, H. Peter Anvin, Ingo Molnar,
	David P. Reed, Thomas Gleixner, linux-kernel, Ingo Molnar

On Tue, Dec 18, 2007 at 12:06:08AM +0000, Alan Cox wrote:
> 300MHz 486 -> Nat Semi Geode.
> 
> NextGen as you say are 386 - 586 depending on the BIOS hypercode but I
> believe lack WP even in > 386 mode.

Geode identifies itself as family 5 though.  It may prefer 486 code but
it's still family 5.  Well Geode GX, SCx200 and LX that is.  I imagine
the Geode NX would be family 6.

--
Len Sorensen

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
@ 2007-12-19 15:03                         ` Avi Kivity
  0 siblings, 0 replies; 243+ messages in thread
From: Avi Kivity @ 2007-12-19 15:03 UTC (permalink / raw)
  To: David P. Reed
  Cc: Thomas Gleixner, linux-kernel, Ingo Molnar, H. Peter Anvin,
	Rene Herman, Pavel Machek, kvm-devel

David P. Reed wrote:
> Avi Kivity wrote:
>> kvm will forward a virtual machine's writes to port 0x80 to the real 
>> port.  The reason is that the write is much faster than exiting and 
>> emulating it; the difference is measurable when compiling kernels.
>>
>> Now if the cause is simply writing to port 0x80, then we must stop 
>> doing that.  But if the reason is the back-to-back writes, when we 
>> can keep it, since the other writes will be trapped by kvm and 
>> emulated.  Do you which is the case?
>>
> As for kvm, I don't have enough info to know anything about that.  Is 
> there a test you'd like me to try?
>

I have a test, but I see that it is broken for mainline.  I'll update it 
eventually, but...

> I think you are also asking if the crash on these laptops is caused 
> only by back-to-back writes.  Actually, it doesn't seem to matter if 
> they are back to back.  I can cause the crash if the writes to 80 are 
> very much spread out in time - it seems only to matter how many of 
> them get executed - almost as if there is a buffer overflow.  (And of 
> course if you do back to back writes to other ports that are 
> apparently fully unused, such as 0xED on my machine, no crash occurs).
>
> I believe (though no one seems to have confirming documentation from 
> the chipset or motherboard vendor) that port 80 is actually functional 
> for some unknown function on these machines.   (They do respond to 
> "in" instructions faster than a bus cycle abort does - more evidence).

That seems to be sufficient evidence for me to remove port 0x80 
pass-through from kvm and emulate it instead.  Given that port 80 writes 
take 1 microsecond, and that an in-kernel exit handler takes a similar 
amount of time, there won't be any significant performance loss.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
@ 2007-12-19 15:03                         ` Avi Kivity
  0 siblings, 0 replies; 243+ messages in thread
From: Avi Kivity @ 2007-12-19 15:03 UTC (permalink / raw)
  To: David P. Reed
  Cc: kvm-devel, Rene Herman, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Ingo Molnar, Pavel Machek, H. Peter Anvin

David P. Reed wrote:
> Avi Kivity wrote:
>> kvm will forward a virtual machine's writes to port 0x80 to the real 
>> port.  The reason is that the write is much faster than exiting and 
>> emulating it; the difference is measurable when compiling kernels.
>>
>> Now if the cause is simply writing to port 0x80, then we must stop 
>> doing that.  But if the reason is the back-to-back writes, when we 
>> can keep it, since the other writes will be trapped by kvm and 
>> emulated.  Do you which is the case?
>>
> As for kvm, I don't have enough info to know anything about that.  Is 
> there a test you'd like me to try?
>

I have a test, but I see that it is broken for mainline.  I'll update it 
eventually, but...

> I think you are also asking if the crash on these laptops is caused 
> only by back-to-back writes.  Actually, it doesn't seem to matter if 
> they are back to back.  I can cause the crash if the writes to 80 are 
> very much spread out in time - it seems only to matter how many of 
> them get executed - almost as if there is a buffer overflow.  (And of 
> course if you do back to back writes to other ports that are 
> apparently fully unused, such as 0xED on my machine, no crash occurs).
>
> I believe (though no one seems to have confirming documentation from 
> the chipset or motherboard vendor) that port 80 is actually functional 
> for some unknown function on these machines.   (They do respond to 
> "in" instructions faster than a bus cycle abort does - more evidence).

That seems to be sufficient evidence for me to remove port 0x80 
pass-through from kvm and emulate it instead.  Given that port 80 writes 
take 1 microsecond, and that an in-kernel exit handler takes a similar 
amount of time, there won't be any significant performance loss.

-- 
error compiling committee.c: too many arguments to function


-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc.
  2007-12-16 23:34                                 ` H. Peter Anvin
@ 2007-12-26 20:49                                   ` Pavel Machek
  0 siblings, 0 replies; 243+ messages in thread
From: Pavel Machek @ 2007-12-26 20:49 UTC (permalink / raw)
  To: H. Peter Anvin, security
  Cc: David P. Reed, Ingo Molnar, Thomas Gleixner, linux-kernel,
	Ingo Molnar, Rene Herman

On Sun 2007-12-16 15:34:58, H. Peter Anvin wrote:
> Pavel Machek wrote:
>> Hi!
>>> The process of safely making delicate changes here is beyond my 
>>> responsibility as just a user - believe me, I'm not suggesting that a 
>>> risky fix be put in .24.   I can patch my own kernels, and I can even 
>>> share an unofficial patch with others for now, or suggest that Fedora and 
>>> Ubuntu add it to their downstream.
>>>
>>> May I make a small suggestion, though.   If the decision is a DMI-keyed 
>>> switch from out-80 to udelay(2)  gets put in, perhaps there should also 
>>> be a way for people to test their own configuration for the underlying 
>>> problem made available as a script.   Though it is a "hack", all you need 
>>> to freeze a problem system is to run a loop doing about 1000 "cat 
>>> /dev/nvram > /dev/null"  commands.  If that leads to a freeze, one might 
>>> ask to have the motherboard added to the DMI-key list.
>> Can you freeze it by catting /dev/rtc, too? That may be significant,
>> because that is readable for group audio (at least on some
>> systems)... which would smell like "small security hole" to me.
>
> Heck, on my system (Fedora 7), it's mode 644...

Ok, time to CC security team, I'd say.

Problem is, that some AMD64x2 nVidia laptops crash on port 0x80
access... which is easily user-triggerable by using /dev/rtc. If it is
644 on Fedora, I guess we have a problem.

Otoh, it is "only" a denial of service, and it can probably be
attributed to "buggy hardware". Is that still relevant for security team?

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 21:25                                                         ` Alan Cox
@ 2008-01-01 15:57                                                           ` David P. Reed
  2008-01-01 21:16                                                             ` H. Peter Anvin
  2008-01-01 15:59                                                           ` David P. Reed
  1 sibling, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-01 15:57 UTC (permalink / raw)
  To: Alan Cox
  Cc: H. Peter Anvin, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Alan Cox wrote:
>> responds to reads differently than "unused" ports.  In particular, an 
>> inb takes 1/2 the elapsed time compared to a read to "known" unused port 
>> 0xed - 792 tsc ticks for port 80 compared to about 1450 tsc ticks for 
>> port 0xed and other unused ports (tsc at 800 MHz).
>>     
>
> Well at least we know where the port is now - thats too fast for an LPC
> bus device, so it must be an SMI trap.
>
> Only easy way to find out is to use the debugging event counters and see
> how many instruction cycles are issued as part of the 0x80 port. If its
> suprisingly high then you've got a firmware bug and can go spank HP.
>
>   
Alan, thank you for the pointers.  I have been doing variations on this 
testing theme for a while - I get intrigued by a good debugging 
challenge, and after all it's my machine...

Two relevant new data points, and then some more suggestions:

1. It appears to be a real port.  SMI traps are not happening in the 
normal outb to 80.  Hundreds of them execute perfectly with the expected 
instruction counts.  If I can trace the particular event that creates 
the hard freeze (getting really creative, here) and stop before the 
freeze disables the entire computer, I will.  That may be an SMI, or 
perhaps any other kind of interrupt or exception.  Maybe someone knows 
how to safely trace through an impending SMI while doing printk's or 
something?

2. It appears to be the standard POST diagnostic port.  On a whim, I 
disassembled my DSDT code, and studied it more closely.   It turns out 
that there are a bunch of "Store(..., DBUG)" instructions scattered 
throughout, and when you look at what DBUG is defined as, it is defined 
as an IO Port at IO address DBGP, which is a 1-byte value = 0x80.  So 
the ACPI BIOS thinks it has something to do with debugging.   There's a 
little strangeness here, however, because the value sent to the port 
occasionally has something to do with arguments to the ACPI operations 
relating to sleep and wakeup ...  could just be that those arguments are 
distinctive.

In thinking about this, I recognize a couple of things.  ACPI is telling 
us something when it declares a reference to port 80 in its code.  It's 
not telling us the function of this port on this machine, but it is 
telling us that it is being used by the BIOS.   This could be a reason 
to put out a printk warning message...   'warning: port 80 is used by 
ACPI BIOS - if you are experiencing problems, you might try an alternate 
means of iodelay.'

Second, it seems likely that there are one of two possible reasons that 
the port 80 writes cause hang/freezes:

1. buffer overflow in such a device.

2. there is some "meaning" to certain byte values being written (the 
_PTS and _WAK use of arguments that come from callers to store into port 
80 makes me suspicious.)   That might mean that the freeze happens only 
when certain values are written, or when they are written closely in 
time to some other action - being used to communicate something to the 
SMM code).   If there is some race in when Linux's port 80 writes happen 
that happen to change the meaning of a request to the hardware or to 
SMM, then we could be rarely stepping on




^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2007-12-17 21:25                                                         ` Alan Cox
  2008-01-01 15:57                                                           ` David P. Reed
@ 2008-01-01 15:59                                                           ` David P. Reed
  2008-01-01 16:15                                                             ` Alan Cox
  2008-01-01 17:31                                                             ` Pavel Machek
  1 sibling, 2 replies; 243+ messages in thread
From: David P. Reed @ 2008-01-01 15:59 UTC (permalink / raw)
  To: Alan Cox
  Cc: H. Peter Anvin, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

[-- Attachment #1: Type: text/plain, Size: 3215 bytes --]

[attached the DSDT.dsl file fyi]

Alan Cox wrote:
>> responds to reads differently than "unused" ports.  In particular, an 
>> inb takes 1/2 the elapsed time compared to a read to "known" unused port 
>> 0xed - 792 tsc ticks for port 80 compared to about 1450 tsc ticks for 
>> port 0xed and other unused ports (tsc at 800 MHz).
>>     
>
> Well at least we know where the port is now - thats too fast for an LPC
> bus device, so it must be an SMI trap.
>
> Only easy way to find out is to use the debugging event counters and see
> how many instruction cycles are issued as part of the 0x80 port. If its
> suprisingly high then you've got a firmware bug and can go spank HP.
>
>   
Alan, thank you for the pointers.  I have been doing variations on this
testing theme for a while - I get intrigued by a good debugging
challenge, and after all it's my machine...

Two relevant new data points, and then some more suggestions:

1. It appears to be a real port.  SMI traps are not happening in the
normal outb to 80.  Hundreds of them execute perfectly with the expected
instruction counts.  If I can trace the particular event that creates
the hard freeze (getting really creative, here) and stop before the
freeze disables the entire computer, I will.  That may be an SMI, or
perhaps any other kind of interrupt or exception.  Maybe someone knows
how to safely trace through an impending SMI while doing printk's or
something?

2. It appears to be the standard POST diagnostic port.  On a whim, I
disassembled my DSDT code, and studied it more closely.   It turns out
that there are a bunch of "Store(..., DBUG)" instructions scattered
throughout, and when you look at what DBUG is defined as, it is defined
as an IO Port at IO address DBGP, which is a 1-byte value = 0x80.  So
the ACPI BIOS thinks it has something to do with debugging.   There's a
little strangeness here, however, because the value sent to the port
occasionally has something to do with arguments to the ACPI operations
relating to sleep and wakeup ...  could just be that those arguments are
distinctive.

In thinking about this, I recognize a couple of things.  ACPI is telling
us something when it declares a reference to port 80 in its code.  It's
not telling us the function of this port on this machine, but it is
telling us that it is being used by the BIOS.   This could be a reason
to put out a printk warning message...   'warning: port 80 is used by
ACPI BIOS - if you are experiencing problems, you might try an alternate
means of iodelay.'

Second, it seems likely that there are one of two possible reasons that
the port 80 writes cause hang/freezes:

1. buffer overflow in such a device.

2. there is some "meaning" to certain byte values being written (the
_PTS and _WAK use of arguments that come from callers to store into port
80 makes me suspicious.)   That might mean that the freeze happens only
when certain values are written, or when they are written closely in
time to some other action - being used to communicate something to the
SMM code).   If there is some race in when Linux's port 80 writes happen
that happen to change the meaning of a request to the hardware or to
SMM, then we could be rarely stepping on





[-- Attachment #2: DSDT.dsl --]
[-- Type: text/x-dsl, Size: 280554 bytes --]

/*
 * Intel ACPI Component Architecture
 * AML Disassembler version 20061109
 *
 * Disassembly of DSDT.dat, Wed Nov 21 17:02:51 2007
 *
 *
 * Original Table Header:
 *     Signature        "DSDT"
 *     Length           0x00008FB0 (36784)
 *     Revision         0x01
 *     OEM ID           "HP    "
 *     OEM Table ID     "MCP51M"
 *     OEM Revision     0x06040000 (100925440)
 *     Creator ID       "MSFT"
 *     Creator Revision 0x03000000 (50331648)
 */
DefinitionBlock ("DSDT.aml", "DSDT", 1, "HP    ", "MCP51M", 0x06040000)
{
    External (\_PR_.CPU0._PPC)

    Name (\_S0, Package (0x04)
    {
        0x00, 
        0x00, 
        0x00, 
        0x00
    })
    Name (\_S3, Package (0x04)
    {
        0x05, 
        0x05, 
        0x00, 
        0x00
    })
    Name (\_S4, Package (0x04)
    {
        0x06, 
        0x06, 
        0x00, 
        0x00
    })
    Name (\_S5, Package (0x04)
    {
        0x07, 
        0x07, 
        0x00, 
        0x00
    })
    Name (SX, 0x00)
    Method (\_PTS, 1, NotSerialized)
    {
        Store (Arg0, DBUG)
        If (LEqual (Arg0, 0x03))
        {
            Store (0x04, GP23)
            Store (0x04, GP24)
        }

        If (LEqual (Arg0, 0x04))
        {
            Store (0x04, GP23)
            Store (0x04, GP24)
            If (LEqual (OSYS, 0x07D6))
            {
                Or (PSMI, 0x01, PSMI)
            }
            Else
            {
                And (PSMI, 0xFE, PSMI)
            }
        }

        If (LEqual (Arg0, 0x05))
        {
            Acquire (\_SB.PCI0.PSMX, 0xFFFF)
            Store (0x8F, \_SB.PCI0.SMIC)
            Store (\_SB.PCI0.SMIS, Local0)
            Release (\_SB.PCI0.PSMX)
        }

        If (LGreater (Arg0, 0x01))
        {
            Store (Zero, LDTC)
            Store (0x04, Z000)
            Store (0x04, Z001)
            Store (0x04, Z002)
        }
    }

    Method (\_WAK, 1, NotSerialized)
    {
        Store (Arg0, DBUG)
        If (LEqual (Arg0, 0x03))
        {
            Acquire (\_SB.PCI0.PSMX, 0xFFFF)
            Store (0x84, \_SB.PCI0.SMIC)
            Store (\_SB.PCI0.SMIS, Local0)
            Release (\_SB.PCI0.PSMX)
            And (GP23, 0x0F, GP26)
            If (LEqual (GP26, 0x05))
            {
                Store (0x01, GP26)
            }
            Else
            {
                Store (0x00, GP26)
            }

            And (GP24, 0x0F, GP25)
            If (LEqual (GP25, 0x05))
            {
                Store (0x01, GP25)
            }
            Else
            {
                Store (0x00, GP25)
            }

            Notify (\_SB.PWRB, 0x02)
            Z003 ()
        }

        If (LEqual (Arg0, 0x04))
        {
            Acquire (\_SB.PCI0.PSMX, 0xFFFF)
            Store (0x85, \_SB.PCI0.SMIC)
            Store (\_SB.PCI0.SMIS, Local0)
            Release (\_SB.PCI0.PSMX)
            And (GP23, 0x0F, GP26)
            If (LEqual (GP26, 0x05))
            {
                Store (0x01, GP26)
            }
            Else
            {
                Store (0x00, GP26)
            }

            And (GP24, 0x0F, GP25)
            If (LEqual (GP25, 0x05))
            {
                Store (0x01, GP25)
            }
            Else
            {
                Store (0x00, GP25)
            }

            Store (Zero, S4FL)
            Store (Zero, S4RT)
            Notify (\_SB.PWRB, 0x02)
            Z003 ()
        }
    }

    Method (Z003, 0, NotSerialized)
    {
        If (LEqual (HOTB, 0x04))
        {
            Notify (\_SB.QBTN, 0x02)
        }

        If (LEqual (HOTB, 0x05))
        {
            Notify (\_SB.DBTN, 0x02)
        }

        If (LEqual (HOTB, 0x03))
        {
            Notify (\_SB.MUBN, 0x02)
        }

        If (LEqual (HOTB, 0x06))
        {
            Notify (\_SB.PIBN, 0x02)
        }

        If (LEqual (HOTB, 0x10))
        {
            Notify (\_SB.WEBN, 0x02)
        }

        If (LEqual (HOTB, 0x11))
        {
            Notify (\_SB.LVBN, 0x02)
        }

        If (LEqual (HOTB, 0x12))
        {
            Notify (\_SB.VOBN, 0x02)
        }

        Store (0x00, HOTB)
    }

    Scope (\_PR)
    {
        Processor (CPU0, 0x00, 0x00001010, 0x06) {}
        Processor (CPU1, 0x01, 0x00001010, 0x06) {}
    }

    Scope (\_SI)
    {
        Method (_SST, 1, NotSerialized)
        {
            Store ("==== SST Working ====", Debug)
        }

        Method (_MSG, 1, NotSerialized)
        {
        }
    }

    Scope (\_GPE)
    {
        Method (_L14, 0, NotSerialized)
        {
            If (PEWS)
            {
                Store (0x01, PEWS)
            }

            Notify (\_SB.PCI0.XVR1, 0x00)
            Notify (\_SB.PCI0.XVR2, 0x01)
        }

        Method (_L0B, 0, NotSerialized)
        {
            Store (0x0B, DBUG)
            Notify (\_SB.PCI0.MAC0, 0x02)
        }
    }

    Scope (\_SB)
    {
        Device (MCFG)
        {
            Name (_HID, EisaId ("PNP0C02"))
            Name (_CRS, ResourceTemplate ()
            {
                DWordMemory (ResourceConsumer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
                    0x00000000,         // Granularity
                    0xE0000000,         // Range Minimum
                    0xEFFFFFFF,         // Range Maximum
                    0x00000000,         // Translation Offset
                    0x10000000,         // Length
                    ,, , AddressRangeMemory, TypeStatic)
            })
        }

        Device (PWRB)
        {
            Name (_HID, EisaId ("PNP0C0C"))
            Method (_STA, 0, NotSerialized)
            {
                Return (0x0B)
            }
        }

        Device (SLPB)
        {
            Name (_HID, EisaId ("PNP0C0E"))
        }

        Device (ACAD)
        {
            Name (_HID, "ACPI0003")
            Name (_PCL, Package (0x01)
            {
                \_SB
            })
            Method (_PSR, 0, NotSerialized)
            {
                If (ECON)
                {
                    Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                    Store (\_SB.PCI0.EC0.ACIN, Local0)
                    Release (\_SB.PCI0.EC0.MUT0)
                    If (RBRF)
                    {
                        \_SB.PCI0.EC0.RSBR ()
                        Store (0x00, RBRF)
                    }

                    If (Local0)
                    {
                        Return (0x01)
                    }
                    Else
                    {
                        Return (0x00)
                    }
                }
                Else
                {
                    Return (0x01)
                }
            }
        }

        Method (VTOB, 1, NotSerialized)
        {
            Store (0x01, Local0)
            ShiftLeft (Local0, Arg0, Local0)
            Return (Local0)
        }

        Method (BTOV, 1, NotSerialized)
        {
            ShiftRight (Arg0, 0x01, Local0)
            Store (0x00, Local1)
            While (Local0)
            {
                Increment (Local1)
                ShiftRight (Local0, 0x01, Local0)
            }

            Return (Local1)
        }

        Method (MKWD, 2, NotSerialized)
        {
            If (And (Arg1, 0x80))
            {
                Store (0xFFFF0000, Local0)
            }
            Else
            {
                Store (Zero, Local0)
            }

            Or (Local0, Arg0, Local0)
            Or (Local0, ShiftLeft (Arg1, 0x08), Local0)
            Return (Local0)
        }

        Method (POSW, 1, NotSerialized)
        {
            If (And (Arg0, 0x8000))
            {
                If (LEqual (Arg0, 0xFFFF))
                {
                    Return (0xFFFFFFFF)
                }
                Else
                {
                    Not (Arg0, Local0)
                    Increment (Local0)
                    And (Local0, 0xFFFF, Local0)
                    Return (Local0)
                }
            }
            Else
            {
                Return (Arg0)
            }
        }

        Method (GBFE, 3, NotSerialized)
        {
            CreateByteField (Arg0, Arg1, TIDX)
            Store (TIDX, Arg2)
        }

        Method (PBFE, 3, NotSerialized)
        {
            CreateByteField (Arg0, Arg1, TIDX)
            Store (Arg2, TIDX)
        }

        Method (ITOS, 1, NotSerialized)
        {
            Store (Buffer (0x05)
                {
                    0x20, 0x20, 0x20, 0x20, 0x20
                }, Local0)
            Store (Buffer (0x11)
                {
                    "0123456789ABCDEF"
                }, Local7)
            Store (0x05, Local1)
            Store (0x00, Local2)
            Store (0x00, Local3)
            While (Local1)
            {
                Decrement (Local1)
                And (ShiftRight (Arg0, ShiftLeft (Local1, 0x02)), 0x0F, Local4)
                GBFE (Local7, Local4, RefOf (Local5))
                PBFE (Local0, Local2, Local5)
                Increment (Local2)
            }

            Return (Local0)
        }

        Device (BAT0)
        {
            Name (_HID, EisaId ("PNP0C0A"))
            Name (_PCL, Package (0x01)
            {
                \_SB
            })
            Name (PBIF, Package (0x0D)
            {
                0x01, 
                0xFFFFFFFF, 
                0xFFFFFFFF, 
                0x01, 
                0xFFFFFFFF, 
                0xFA, 
                0x96, 
                0x0A, 
                0x19, 
                "BAT1", 
                " ", 
                " ", 
                " "
            })
            Name (PBST, Package (0x04)
            {
                0x00, 
                0xFFFFFFFF, 
                0xFFFFFFFF, 
                0x2710
            })
            Name (BAST, 0x00)
            Name (B1ST, 0x0F)
            Name (B1WT, 0x00)
            Method (_STA, 0, NotSerialized)
            {
                If (ECON)
                {
                    If (\_SB.PCI0.EC0.MBTS)
                    {
                        Store (0x1F, B1ST)
                    }
                    Else
                    {
                        Store (0x0F, B1ST)
                    }
                }
                Else
                {
                    Store (0x0F, B1ST)
                }

                Return (B1ST)
            }

            Method (_BIF, 0, NotSerialized)
            {
                If (LEqual (B1ST, 0x1F))
                {
                    UPBI ()
                }
                Else
                {
                    IVBI ()
                }

                Return (PBIF)
            }

            Method (_BST, 0, NotSerialized)
            {
                If (LEqual (B1ST, 0x1F))
                {
                    UPBS ()
                }
                Else
                {
                    IVBS ()
                }

                Return (PBST)
            }

            Method (UPBI, 0, NotSerialized)
            {
                Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                If (LNot (\_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x10, RefOf (Local5))))
                {
                    If (LAnd (Local5, LNot (And (Local5, 0x8000))))
                    {
                        ShiftRight (Local5, 0x05, Local5)
                        ShiftLeft (Local5, 0x05, Local5)
                        Store (Local5, Index (PBIF, 0x02))
                        Divide (Local5, 0x64, , Local2)
                        Add (Local2, 0x01, Local2)
                        Multiply (Local2, 0x05, Local4)
                        Add (Local4, 0x02, Index (PBIF, 0x05))
                        Multiply (Local2, 0x03, Local4)
                        Add (Local4, 0x02, Index (PBIF, 0x06))
                    }
                }

                Store (0x1770, Index (PBIF, 0x01))
                Store (0x39D0, Index (PBIF, 0x04))
                Store ("Primary", Index (PBIF, 0x09))
                Store ("LION", Index (PBIF, 0x0B))
                Store ("Hewlett-Packard", Index (PBIF, 0x0C))
                Store (0x01, Index (PBIF, 0x00))
                Release (\_SB.PCI0.EC0.MUT0)
            }

            Method (UPUM, 0, NotSerialized)
            {
                Store (Buffer (0x0B)
                    {
                        /* 0000 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 
                        /* 0008 */    0x00, 0x00, 0x00
                    }, Local0)
                Store (Buffer (0x05)
                    {
                        0x36, 0x35, 0x35, 0x33, 0x35
                    }, Local6)
                Store (Buffer (0x05)
                    {
                        0x31, 0x32, 0x33, 0x32, 0x31
                    }, Local7)
                If (LNot (\_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x1B, RefOf (Local5))))
                {
                    Divide (Local5, 0x0200, , Local1)
                    Subtract (Local5, Multiply (Local1, 0x0200, Local2), Local5)
                    Multiply (Subtract (Local1, 0x0A, Local1), 0x03E8, Local1)
                    Divide (Local5, 0x20, , Local2)
                    Subtract (Local5, Multiply (Local2, 0x20, Local3), Local3)
                    Add (Multiply (Decrement (Local2), 0x1E, Local5), Local3, Local5)
                    Add (Local1, Local5, Local5)
                    Store (ITOS (ToBCD (Local5)), Local7)
                }

                If (LNot (\_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x1C, RefOf (Local5))))
                {
                    Store (ITOS (ToBCD (Local5)), Local6)
                }

                Store (0x05, Local1)
                Store (0x00, Local2)
                Store (0x00, Local3)
                While (Local1)
                {
                    Decrement (Local1)
                    GBFE (Local6, Local2, RefOf (Local5))
                    PBFE (Local0, Local3, Local5)
                    Increment (Local2)
                    Increment (Local3)
                }

                Increment (Local3)
                Store (0x00, Local2)
                Store (0x05, Local1)
                While (Local1)
                {
                    Decrement (Local1)
                    GBFE (Local7, Local2, RefOf (Local5))
                    PBFE (Local0, Local3, Local5)
                    Increment (Local2)
                    Increment (Local3)
                }

                Store (Local0, Index (PBIF, 0x0A))
                Store ("Hewlett-Packard", Index (PBIF, 0x0C))
            }

            Method (UPBS, 0, NotSerialized)
            {
                Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                Store (\_SB.PCI0.EC0.MBRM, Local5)
                If (LNot (And (Local5, 0x8000)))
                {
                    ShiftRight (Local5, 0x05, Local5)
                    ShiftLeft (Local5, 0x05, Local5)
                    If (LNotEqual (Local5, DerefOf (Index (PBST, 0x02))))
                    {
                        Store (Local5, Index (PBST, 0x02))
                    }
                }

                Store (\_SB.PCI0.EC0.MBCV, Index (PBST, 0x03))
                Sleep (0xFA)
                Store (\_SB.PCI0.EC0.MBST, Local0)
                Release (\_SB.PCI0.EC0.MUT0)
                Store (Local0, Index (PBST, 0x00))
            }

            Method (IVBI, 0, NotSerialized)
            {
                Store (0xFFFFFFFF, Index (PBIF, 0x01))
                Store (0xFFFFFFFF, Index (PBIF, 0x02))
                Store (0xFFFFFFFF, Index (PBIF, 0x04))
                Store ("Bad", Index (PBIF, 0x09))
                Store ("      ", Index (PBIF, 0x0A))
                Store ("Bad", Index (PBIF, 0x0B))
                Store ("Bad", Index (PBIF, 0x0C))
            }

            Method (IVBS, 0, NotSerialized)
            {
                Store (0x00, Index (PBST, 0x00))
                Store (0xFFFFFFFF, Index (PBST, 0x01))
                Store (0xFFFFFFFF, Index (PBST, 0x02))
                Store (0x2710, Index (PBST, 0x03))
            }
        }

        Device (LID)
        {
            Name (_HID, EisaId ("PNP0C0D"))
            Method (_LID, 0, NotSerialized)
            {
                If (ECON)
                {
                    Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                    Store (\_SB.PCI0.EC0.LIDS, Local0)
                    Release (\_SB.PCI0.EC0.MUT0)
                    If (Local0)
                    {
                        Return (0x00)
                    }
                    Else
                    {
                        Return (0x01)
                    }
                }
                Else
                {
                    Return (0x01)
                }
            }
        }

        Device (MEM0)
        {
            Name (_HID, EisaId ("PNP0C01"))
            Method (_CRS, 0, Serialized)
            {
                Name (MEMR, ResourceTemplate ()
                {
                    Memory32Fixed (ReadOnly,
                        0xFFC00000,         // Address Base
                        0x00400000,         // Address Length
                        )
                    Memory32Fixed (ReadWrite,
                        0xFEC00000,         // Address Base
                        0x00001000,         // Address Length
                        )
                    Memory32Fixed (ReadWrite,
                        0xFEE00000,         // Address Base
                        0x00100000,         // Address Length
                        )
                    Memory32Fixed (ReadWrite,
                        0x00000000,         // Address Base
                        0x00000000,         // Address Length
                        _Y00)
                })
                CreateDWordField (MEMR, \_SB.MEM0._CRS._Y00._BAS, MBAS)
                CreateDWordField (MEMR, \_SB.MEM0._CRS._Y00._LEN, MBLE)
                If (\_SB.PCI0.LPC0.MTBA)
                {
                    Store (\_SB.PCI0.LPC0.MTBA, MBAS)
                    Store (0x1000, MBLE)
                }

                Return (MEMR)
            }
        }

        Device (QLBD)
        {
            Name (_HID, "HPQ0006")
            Method (_STA, 0, NotSerialized)
            {
                Return (0x0F)
            }
        }

        Device (WMID)
        {
            Name (Z004, Package (0x0E)
            {
                0x04, 
                0x04, 
                0x04, 
                0x00, 
                0x04, 
                0x04, 
                0x00, 
                0x00, 
                0x04, 
                0x04, 
                0x0C, 
                0x00, 
                0x00, 
                0x00
            })
            Method (Z005, 2, NotSerialized)
            {
                CreateDWordField (Arg1, 0x00, Z006)
                CreateDWordField (Arg1, 0x04, Z007)
                CreateDWordField (Arg1, 0x08, Z008)
                CreateDWordField (Arg1, 0x0C, Z009)
                If (LEqual (Arg0, 0x01))
                {
                    Store (0x00, Local0)
                }

                If (LEqual (Arg0, 0x02))
                {
                    Store (0x04, Local0)
                }

                If (LEqual (Arg0, 0x03))
                {
                    Store (0x80, Local0)
                }

                If (LEqual (Arg0, 0x04))
                {
                    Store (0x0400, Local0)
                }

                If (LEqual (Arg0, 0x05))
                {
                    Store (0x1000, Local0)
                }

                Store (Buffer (Add (0x08, Local0)) {}, Local1)
                CreateDWordField (Local1, 0x00, Z00A)
                CreateDWordField (Local1, 0x04, Z00B)
                Store (0x4C494146, Z00A)
                Store (0x02, Z00B)
                If (LEqual (Z006, 0x55434553))
                {
                    Store (0x03, Z00B)
                    If (LEqual (Z007, 0x01))
                    {
                        Store (0x04, Z00B)
                        If (LEqual (Z008, 0x05))
                        {
                            Store (^Z00C (), Local2)
                            Store (0x00, Z00B)
                        }

                        If (LEqual (Z008, 0x0E))
                        {
                            Store (^Z00D (), Local2)
                            Store (0x00, Z00B)
                        }

                        If (LEqual (Z008, 0x07))
                        {
                            If (Z009)
                            {
                                Store (DerefOf (Index (Arg1, 0x10)), Local3)
                                Store (^Z00E (Local3), Local2)
                                Store (0x00, Z00B)
                            }
                            Else
                            {
                                Store (0x05, Z00B)
                            }
                        }

                        If (LEqual (Z008, 0x01))
                        {
                            Store (^Z00F (), Local2)
                            Store (0x00, Z00B)
                        }

                        If (LEqual (Z008, 0x08))
                        {
                            Store (^Z00G (), Local2)
                            Store (0x00, Z00B)
                        }

                        If (LEqual (Z008, 0x09))
                        {
                            Store (^Z00H (), Local2)
                            Store (0x00, Z00B)
                        }

                        If (LEqual (Z008, 0x0A))
                        {
                            Store (^Z00I (), Local2)
                            Store (0x00, Z00B)
                        }

                        If (LEqual (Z008, 0x0C))
                        {
                            Store (^Z00J (), Local2)
                            Store (0x00, Z00B)
                        }
                    }

                    If (LEqual (Z007, 0x02))
                    {
                        Store (0x04, Z00B)
                        If (LAnd (LGreater (Z008, 0x00), LLessEqual (Z008, 0x0C)))
                        {
                            If (LLess (Z009, DerefOf (Index (Z004, Subtract (Z008, 0x01)
                                ))))
                            {
                                Store (0x05, Z00B)
                            }
                            Else
                            {
                                CreateDWordField (Arg1, 0x10, Z00K)
                                If (LEqual (Z008, 0x05))
                                {
                                    Store (^Z00L (Z00K), Local2)
                                    Store (0x00, Z00B)
                                }

                                If (LEqual (Z008, 0x01))
                                {
                                    Store (^Z00M (Z00K), Local2)
                                    Store (0x00, Z00B)
                                }

                                If (LEqual (Z008, 0x09))
                                {
                                    Store (^Z00N (Z00K), Local2)
                                    Store (0x00, Z00B)
                                }

                                If (LEqual (Z008, 0x0A))
                                {
                                    Store (^Z00O (Z00K), Local2)
                                    Store (0x00, Z00B)
                                }
                            }
                        }
                    }
                }

                If (LEqual (Z00B, 0x00))
                {
                    Store (DerefOf (Index (Local2, 0x00)), Z00B)
                    If (LEqual (Z00B, 0x00))
                    {
                        If (LLessEqual (DerefOf (Index (Local2, 0x01)), Local0))
                        {
                            Store (0x00, Local0)
                            While (LLess (Local0, DerefOf (Index (Local2, 0x01))))
                            {
                                Store (DerefOf (Index (DerefOf (Index (Local2, 0x02)), Local0)), 
                                    Index (Local1, Add (Local0, 0x08)))
                                Increment (Local0)
                            }

                            Store (0x53534150, Z00A)
                        }
                        Else
                        {
                            Store (0x05, Z00B)
                        }
                    }
                }

                Return (Local1)
            }

            Name (_HID, "PNP0C14")
            Name (_UID, 0x00)
            Name (Z00P, 0x00)
            Name (Z00Q, 0x00)
            Name (BUFF, Buffer (0x04)
            {
                0x00, 0x00, 0x00, 0x00
            })
            CreateByteField (BUFF, 0x00, OB0)
            CreateByteField (BUFF, 0x01, OB1)
            CreateByteField (BUFF, 0x02, OB2)
            CreateByteField (BUFF, 0x03, OB3)
            Name (_WDG, Buffer (0x50)
            {
                /* 0000 */    0x34, 0xF0, 0xB7, 0x5F, 0x63, 0x2C, 0xE9, 0x45, 
                /* 0008 */    0xBE, 0x91, 0x3D, 0x44, 0xE2, 0xC7, 0x07, 0xE4, 
                /* 0010 */    0x41, 0x44, 0x01, 0x02, 0x79, 0x42, 0xF2, 0x95, 
                /* 0018 */    0x7B, 0x4D, 0x34, 0x43, 0x93, 0x87, 0xAC, 0xCD, 
                /* 0020 */    0xC6, 0x7E, 0xF6, 0x1C, 0x80, 0x00, 0x01, 0x08, 
                /* 0028 */    0x21, 0x12, 0x90, 0x05, 0x66, 0xD5, 0xD1, 0x11, 
                /* 0030 */    0xB2, 0xF0, 0x00, 0xA0, 0xC9, 0x06, 0x29, 0x10, 
                /* 0038 */    0x41, 0x45, 0x01, 0x00, 0xD4, 0x2B, 0x99, 0xD0, 
                /* 0040 */    0x7C, 0xA4, 0xFE, 0x4E, 0xB0, 0x72, 0x32, 0x4A, 
                /* 0048 */    0xEC, 0x92, 0x29, 0x6C, 0x42, 0x43, 0x01, 0x00
            })
            Method (WQBC, 1, NotSerialized)
            {
                Store ("HP WMI WQBC)", Debug)
                Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                Store (0x88, \_SB.PCI0.SMIC)
                Store (\_SB.PCI0.SMIS, Local0)
                Release (\_SB.PCI0.PSMX)
                Store (Local0, CADL)
                If (ECON)
                {
                    Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                    If (LEqual (\_SB.PCI0.EC0.LIDS, 0x01))
                    {
                        And (Local0, 0xFE, Local0)
                    }

                    Release (\_SB.PCI0.EC0.MUT0)
                }

                Return (Local0)
            }

            Method (WSBC, 2, NotSerialized)
            {
                Store ("HP WMI WSBC)", Debug)
                CreateByteField (Arg1, 0x00, ADA0)
                Store (ADA0, Local0)
                If (LOr (LEqual (\_SB.PCI0.XVR0.VGA.SWIT, 0x00), LEqual (\_SB.PCI0.UVGA.SWIT, 0x00)))
                {
                    Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                    Store (0x87, \_SB.PCI0.SMIC)
                    Store (\_SB.PCI0.SMIS, Local1)
                    Release (\_SB.PCI0.PSMX)
                    If (LEqual (Local0, Local1))
                    {
                        Return (0x02)
                    }
                    Else
                    {
                        Store (0x00, NSTE)
                        If (LEqual (Local0, 0x01))
                        {
                            Store ("LCD", Debug)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                            Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            Store (Zero, \_SB.PCI0.UVGA.CRTA)
                            Store (One, \_SB.PCI0.UVGA.LCDA)
                            Store (Zero, \_SB.PCI0.UVGA.TVAF)
                            Store (Zero, \_SB.PCI0.UVGA.HDTV)
                        }

                        If (LEqual (Local0, 0x02))
                        {
                            Store ("CRT", Debug)
                            Store (One, \_SB.PCI0.XVR0.VGA.CRTA)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.LCDA)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            Store (One, \_SB.PCI0.UVGA.CRTA)
                            Store (Zero, \_SB.PCI0.UVGA.LCDA)
                            Store (Zero, \_SB.PCI0.UVGA.TVAF)
                            Store (Zero, \_SB.PCI0.UVGA.HDTV)
                        }

                        If (LEqual (Local0, 0x03))
                        {
                            Store ("Both", Debug)
                            Store (One, \_SB.PCI0.XVR0.VGA.CRTA)
                            Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            Store (One, \_SB.PCI0.UVGA.CRTA)
                            Store (One, \_SB.PCI0.UVGA.LCDA)
                            Store (Zero, \_SB.PCI0.UVGA.TVAF)
                            Store (Zero, \_SB.PCI0.UVGA.HDTV)
                        }

                        If (LEqual (Local0, 0x04))
                        {
                            Store ("TV", Debug)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.LCDA)
                            Store (One, \_SB.PCI0.XVR0.VGA.TVAF)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            Store (Zero, \_SB.PCI0.UVGA.CRTA)
                            Store (Zero, \_SB.PCI0.UVGA.LCDA)
                            Store (One, \_SB.PCI0.UVGA.TVAF)
                            Store (Zero, \_SB.PCI0.UVGA.HDTV)
                        }

                        If (LEqual (Local0, 0x05))
                        {
                            Store ("TV+LCD", Debug)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                            Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                            Store (One, \_SB.PCI0.XVR0.VGA.TVAF)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            Store (Zero, \_SB.PCI0.UVGA.CRTA)
                            Store (One, \_SB.PCI0.UVGA.LCDA)
                            Store (One, \_SB.PCI0.UVGA.TVAF)
                            Store (Zero, \_SB.PCI0.UVGA.HDTV)
                        }

                        If (LEqual (Local0, 0x06))
                        {
                            Store ("TV+CRT", Debug)
                        }

                        If (LEqual (Local0, 0x08))
                        {
                            Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.LCDA)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                            Store (One, \_SB.PCI0.XVR0.VGA.HDTV)
                            Store (Zero, \_SB.PCI0.UVGA.CRTA)
                            Store (Zero, \_SB.PCI0.UVGA.LCDA)
                            Store (Zero, \_SB.PCI0.UVGA.TVAF)
                            Store (One, \_SB.PCI0.UVGA.HDTV)
                        }

                        If (LEqual (Local0, 0x09))
                        {
                            Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                            Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                            Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                            Store (One, \_SB.PCI0.XVR0.VGA.HDTV)
                            Store (Zero, \_SB.PCI0.UVGA.CRTA)
                            Store (One, \_SB.PCI0.UVGA.LCDA)
                            Store (Zero, \_SB.PCI0.UVGA.TVAF)
                            Store (One, \_SB.PCI0.UVGA.HDTV)
                        }

                        Store (CADL, PADL)
                        If (LGreaterEqual (OSYS, 0x07D1))
                        {
                            Notify (\_SB.PCI0, 0x00)
                        }
                        Else
                        {
                            If (VGAT)
                            {
                                Notify (\_SB.PCI0.XVR0.VGA, 0x00)
                            }
                            Else
                            {
                                Notify (\_SB.PCI0.UVGA, 0x00)
                            }
                        }

                        Sleep (0x02EE)
                        If (VGAT)
                        {
                            Notify (\_SB.PCI0.XVR0.VGA, 0x80)
                        }
                        Else
                        {
                            Notify (\_SB.PCI0.UVGA, 0x80)
                        }

                        Return (0x00)
                    }
                }
                Else
                {
                    Return (0x01)
                }
            }

            Method (WMAD, 3, NotSerialized)
            {
                Return (Z005 (Arg1, Arg2))
            }

            Method (Z00C, 0, NotSerialized)
            {
                Store ("HP WMI Command 0x5 (BIOS Read)", Debug)
                Store (0x01, WIRE)
                And (BTWL, 0x03, Local0)
                Or (Local0, 0x20, OB0)
                Store (WWLS, Local1)
                ShiftLeft (Local1, 0x01, Local1)
                Store (BWLS, Local2)
                ShiftLeft (Local2, 0x01, Local2)
                Store (BTLS, Local3)
                ShiftLeft (Local3, 0x03, Local3)
                Or (Local1, Local3, Local1)
                Or (Local2, Local3, Local2)
                And (GP24, 0x0F, GP25)
                If (LEqual (GP25, 0x05))
                {
                    Store (0x01, GP25)
                }
                Else
                {
                    Store (0x00, GP25)
                }

                And (GP23, 0x0F, GP26)
                If (LEqual (GP26, 0x05))
                {
                    Store (0x01, GP26)
                }
                Else
                {
                    Store (0x00, GP26)
                }

                If (GP26)
                {
                    If (LNot (WWLS))
                    {
                        Store (0x00, GP26)
                        Store (0x04, GP23)
                    }

                    If (LNot (BTLS))
                    {
                        Store (0x00, GP26)
                        Store (0x04, GP23)
                    }
                }

                If (GP25)
                {
                    If (LNot (BWLS))
                    {
                        Store (0x00, GP25)
                        Store (0x04, GP24)
                    }

                    If (LNot (BTLS))
                    {
                        Store (0x00, GP25)
                        Store (0x04, GP24)
                    }
                }

                Or (GP26, Local1, Local1)
                Or (GP25, Local2, Local2)
                Store (0x00, OB2)
                Store (0x00, OB1)
                If (WLSU)
                {
                    Or (Local1, 0x04, Local1)
                }

                If (BTSU)
                {
                    Or (Local2, 0x04, Local2)
                }

                If (GP26)
                {
                    Or (Local1, 0x10, Local1)
                }
                Else
                {
                    And (Local1, 0xEF, Local1)
                }

                If (And (BTWL, 0x01))
                {
                    Store (Local1, OB1)
                }

                If (And (BTWL, 0x02))
                {
                    Store (Local2, OB2)
                }

                Store (0x00, OB3)
                Store (Package (0x03)
                    {
                        0x00, 
                        0x04, 
                        Buffer (0x04)
                        {
                            0x01, 0x02, 0x03, 0x04
                        }
                    }, Local0)
                Store (OB0, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                Store (OB1, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                Store (OB2, Index (DerefOf (Index (Local0, 0x02)), 0x02))
                Store (OB3, Index (DerefOf (Index (Local0, 0x02)), 0x03))
                Return (Local0)
            }

            Method (Z00L, 1, NotSerialized)
            {
                Store ("HP WMI Command 0x5 (BIOS Write)", Debug)
                And (GP24, 0x0F, GP25)
                If (LEqual (GP25, 0x05))
                {
                    Store (0x01, GP25)
                }
                Else
                {
                    Store (0x00, GP25)
                }

                And (GP23, 0x0F, GP26)
                If (LEqual (GP26, 0x05))
                {
                    Store (0x01, GP26)
                }
                Else
                {
                    Store (0x00, GP26)
                }

                If (And (BTWL, 0x03))
                {
                    If (And (Arg0, 0x0800))
                    {
                        If (And (Arg0, 0x08))
                        {
                            Store (0x01, WWLS)
                            Store (0x01, BWLS)
                            If (WLSU)
                            {
                                If (BTLS)
                                {
                                    Store (0x01, GP26)
                                    Store (0x05, GP23)
                                }
                            }
                            Else
                            {
                                Store (0x00, GP26)
                                Store (0x04, GP23)
                            }

                            If (BTSU)
                            {
                                If (BTLS)
                                {
                                    Store (0x01, GP25)
                                    Store (0x05, GP24)
                                }
                            }
                            Else
                            {
                                Store (0x00, GP25)
                                Store (0x04, GP24)
                            }
                        }
                        Else
                        {
                            Store (0x00, WWLS)
                            Store (0x00, GP26)
                            Store (0x04, GP23)
                            Store (0x00, BWLS)
                            Store (0x00, GP25)
                            Store (0x04, GP24)
                        }
                    }

                    If (And (Arg0, 0x0100))
                    {
                        If (And (Arg0, 0x01))
                        {
                            Store (0x01, WWLS)
                            If (WLSU)
                            {
                                If (BTLS)
                                {
                                    Store (0x01, GP26)
                                    Store (0x05, GP23)
                                }
                            }
                            Else
                            {
                                Store (0x00, GP26)
                                Store (0x04, GP23)
                            }
                        }
                        Else
                        {
                            Store (0x00, WWLS)
                            Store (0x00, GP26)
                            Store (0x04, GP23)
                        }
                    }

                    If (And (Arg0, 0x0200))
                    {
                        If (And (Arg0, 0x02))
                        {
                            Store (0x01, BWLS)
                            If (BTSU)
                            {
                                If (BTLS)
                                {
                                    Store (0x01, GP25)
                                    Store (0x05, GP24)
                                }
                            }
                            Else
                            {
                                Store (0x00, GP25)
                                Store (0x04, GP24)
                            }
                        }
                        Else
                        {
                            Store (0x00, BWLS)
                            Store (0x00, GP25)
                            Store (0x04, GP24)
                        }
                    }

                    Return (Package (0x02)
                    {
                        0x00, 
                        0x00
                    })
                }
                Else
                {
                    Return (Package (0x02)
                    {
                        0x0D, 
                        0x00
                    })
                }
            }

            Method (Z00D, 0, NotSerialized)
            {
                Store ("HP WMI Command 0xE (BIOS Read)", Debug)
                Store (0x00, Local0)
                Store (Buffer (0x0A)
                    {
                        /* 0000 */    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                        /* 0008 */    0x00, 0x00
                    }, Local2)
                Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                Store (0x00, \_SB.PCI0.SMIS)
                Store (0x89, \_SB.PCI0.SMIC)
                Store (\_SB.PCI0.SMIS, WLID)
                Release (\_SB.PCI0.PSMX)
                If (LNotEqual (WLID, 0xFF))
                {
                    Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                    Store (0x02, \_SB.PCI0.SMIS)
                    Store (0x89, \_SB.PCI0.SMIC)
                    Store (\_SB.PCI0.SMIS, Index (Local2, 0x02))
                    Store (0x03, \_SB.PCI0.SMIS)
                    Store (0x89, \_SB.PCI0.SMIC)
                    Store (\_SB.PCI0.SMIS, Index (Local2, 0x03))
                    Store (0x04, \_SB.PCI0.SMIS)
                    Store (0x89, \_SB.PCI0.SMIC)
                    Store (\_SB.PCI0.SMIS, Index (Local2, 0x04))
                    Store (0x05, \_SB.PCI0.SMIS)
                    Store (0x89, \_SB.PCI0.SMIC)
                    Store (\_SB.PCI0.SMIS, Index (Local2, 0x05))
                    Store (0x06, \_SB.PCI0.SMIS)
                    Store (0x89, \_SB.PCI0.SMIC)
                    Store (\_SB.PCI0.SMIS, Index (Local2, 0x06))
                    Store (0x07, \_SB.PCI0.SMIS)
                    Store (0x89, \_SB.PCI0.SMIC)
                    Store (\_SB.PCI0.SMIS, Index (Local2, 0x07))
                    Store (0x08, \_SB.PCI0.SMIS)
                    Store (0x89, \_SB.PCI0.SMIC)
                    Store (\_SB.PCI0.SMIS, Index (Local2, 0x08))
                    Store (0x09, \_SB.PCI0.SMIS)
                    Store (0x89, \_SB.PCI0.SMIC)
                    Store (\_SB.PCI0.SMIS, Index (Local2, 0x09))
                    Release (\_SB.PCI0.PSMX)
                    Store (Local2, Local1)
                    Add (Local0, 0x0A, Local0)
                }

                Store (Package (0x03) {}, Local2)
                Store (0x00, Index (Local2, 0x00))
                Store (Local0, Index (Local2, 0x01))
                Store (Local1, Index (Local2, 0x02))
                Return (Local2)
            }

            Method (Z00E, 1, NotSerialized)
            {
                Store ("HP WMI Command 0x7 (BIOS Read)", Debug)
                Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                If (LNot (ECON))
                {
                    Store (Package (0x02)
                        {
                            0x0D, 
                            0x00
                        }, Local0)
                    Sleep (0x96)
                    Release (\_SB.PCI0.EC0.MUT0)
                    Return (Local0)
                }

                If (Arg0)
                {
                    Store (Package (0x02)
                        {
                            0x06, 
                            0x00
                        }, Local0)
                    Sleep (0x96)
                    Release (\_SB.PCI0.EC0.MUT0)
                    Return (Local0)
                }

                If (LNot (\_SB.PCI0.EC0.MBTS))
                {
                    Store (Package (0x02)
                        {
                            0x06, 
                            0x00
                        }, Local0)
                    Sleep (0x96)
                    Release (\_SB.PCI0.EC0.MUT0)
                    Return (Local0)
                }

                Release (\_SB.PCI0.EC0.MUT0)
                Store (Package (0x03)
                    {
                        0x00, 
                        0x80, 
                        Buffer (0x80) {}
                    }, Local0)
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x18, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x01))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x10, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x03))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x02))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x0F, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x05))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x04))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x0C, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x07))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x06))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x17, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x09))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x08))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x08, RefOf (Local1))
                Subtract (Local1, 0x0AAA, Local1)
                Divide (Local1, 0x0A, Local2, Local1)
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x0B))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x0A))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x09, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x0D))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x0C))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x0A, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x0F))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x0E))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x19, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x11))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x10))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x16, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x13))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x12))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x3F, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x15))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x14))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x3E, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x17))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x16))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x3D, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x19))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x18))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x3C, RefOf (Local1))
                Divide (Local1, 0x0100, Local2, Index (DerefOf (Index (Local0, 0x02)), 
                    0x1B))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x1A))
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x1C, RefOf (Local1))
                Store (ITOS (ToBCD (Local1)), Local3)
                Store (0x1C, Local2)
                Store (0x00, Local4)
                Store (SizeOf (Local3), Local1)
                While (Local1)
                {
                    GBFE (Local3, Local4, RefOf (Local5))
                    PBFE (DerefOf (Index (Local0, 0x02)), Local2, Local5)
                    Decrement (Local1)
                    Increment (Local2)
                    Increment (Local4)
                }

                Store (0x20, Index (DerefOf (Index (Local0, 0x02)), Local2))
                Increment (Local2)
                \_SB.PCI0.EC0.SMRD (0x09, 0x16, 0x1B, RefOf (Local1))
                And (Local1, 0x1F, Local7)
                Store (ITOS (ToBCD (Local7)), Local6)
                And (Local1, 0x01E0, Local7)
                ShiftRight (Local7, 0x05, Local7)
                Store (ITOS (ToBCD (Local7)), Local5)
                ShiftRight (Local1, 0x09, Local7)
                Add (Local7, 0x07BC, Local7)
                Store (ITOS (ToBCD (Local7)), Local4)
                Store (0x02, Local1)
                Store (0x03, Local7)
                While (Local1)
                {
                    GBFE (Local5, Local7, RefOf (Local3))
                    PBFE (DerefOf (Index (Local0, 0x02)), Local2, Local3)
                    Decrement (Local1)
                    Increment (Local2)
                    Increment (Local7)
                }

                Store ("/", Index (DerefOf (Index (Local0, 0x02)), Local2))
                Increment (Local2)
                Store (0x02, Local1)
                Store (0x03, Local7)
                While (Local1)
                {
                    GBFE (Local6, Local7, RefOf (Local3))
                    PBFE (DerefOf (Index (Local0, 0x02)), Local2, Local3)
                    Decrement (Local1)
                    Increment (Local2)
                    Increment (Local7)
                }

                Store ("/", Index (DerefOf (Index (Local0, 0x02)), Local2))
                Increment (Local2)
                Store (0x04, Local1)
                Store (0x01, Local7)
                While (Local1)
                {
                    GBFE (Local4, Local7, RefOf (Local3))
                    PBFE (DerefOf (Index (Local0, 0x02)), Local2, Local3)
                    Decrement (Local1)
                    Increment (Local2)
                    Increment (Local7)
                }

                Store (0x00, Index (DerefOf (Index (Local0, 0x02)), Local2))
                \_SB.PCI0.EC0.SMRD (0x0B, 0x16, 0x20, RefOf (Local1))
                Store (SizeOf (Local1), Local3)
                Store (0x2C, Local2)
                Store (0x00, Local4)
                While (Local3)
                {
                    GBFE (Local1, Local4, RefOf (Local5))
                    PBFE (DerefOf (Index (Local0, 0x02)), Local2, Local5)
                    Decrement (Local3)
                    Increment (Local2)
                    Increment (Local4)
                }

                Store (0x00, Index (DerefOf (Index (Local0, 0x02)), Local2))
                Sleep (0x96)
                Return (Local0)
            }

            Method (Z00F, 0, NotSerialized)
            {
                Store ("HP WMI Command 0x1 (BIOS Read)", Debug)
                Store (WQBC (0x00), OB0)
                Or (OB0, 0x01, OB0)
                Store (0x00, OB1)
                Store (0x00, OB2)
                Store (0x00, OB3)
                Store (Package (0x03)
                    {
                        0x00, 
                        0x04, 
                        Buffer (0x04)
                        {
                            0x01, 0x02, 0x03, 0x04
                        }
                    }, Local0)
                Store (OB0, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                Store (OB1, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                Store (OB2, Index (DerefOf (Index (Local0, 0x02)), 0x02))
                Store (OB3, Index (DerefOf (Index (Local0, 0x02)), 0x03))
                Return (Local0)
            }

            Method (Z00M, 1, NotSerialized)
            {
                Store ("HP WMI Command 0x1 (BIOS Write)", Debug)
                And (Arg0, 0x0F, Local0)
                If (VGAT)
                {
                    If (LEqual (\_SB.PCI0.XVR0.VGA.SWIT, 0x00))
                    {
                        Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                        Store (0x87, \_SB.PCI0.SMIC)
                        Store (\_SB.PCI0.SMIS, Local1)
                        Release (\_SB.PCI0.PSMX)
                        If (LEqual (Local0, Local1))
                        {
                            Return (Package (0x02)
                            {
                                0x00, 
                                0x00
                            })
                        }
                        Else
                        {
                            Store (0x00, NSTE)
                            If (LEqual (Local0, 0x01))
                            {
                                Store ("LCD", Debug)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x02))
                            {
                                Store ("CRT", Debug)
                                Store (One, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x03))
                            {
                                Store ("Both", Debug)
                                Store (One, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x04))
                            {
                                Store ("TV", Debug)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (One, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x05))
                            {
                                Store ("TV+LCD", Debug)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (One, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x06))
                            {
                                Store ("TV+CRT", Debug)
                                Return (Package (0x02)
                                {
                                    0x06, 
                                    0x00
                                })
                            }

                            If (LEqual (Local0, 0x07))
                            {
                                Store ("TV+CRT+LCD", Debug)
                                Return (Package (0x02)
                                {
                                    0x06, 
                                    0x00
                                })
                            }

                            If (LEqual (Local0, 0x08))
                            {
                                Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (One, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x09))
                            {
                                Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (One, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LGreaterEqual (Local0, 0x0A))
                            {
                                Return (Package (0x02)
                                {
                                    0x06, 
                                    0x00
                                })
                            }

                            Store (CADL, PADL)
                            Notify (\_SB.PCI0.XVR0.VGA, 0x80)
                            Return (Package (0x02)
                            {
                                0x00, 
                                0x00
                            })
                        }
                    }
                    Else
                    {
                        Return (Package (0x02)
                        {
                            0x00, 
                            0x00
                        })
                    }
                }
                Else
                {
                    If (LEqual (\_SB.PCI0.UVGA.SWIT, 0x00))
                    {
                        Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                        Store (0x87, \_SB.PCI0.SMIC)
                        Store (\_SB.PCI0.SMIS, Local1)
                        Release (\_SB.PCI0.PSMX)
                        If (LEqual (Local0, Local1))
                        {
                            Return (Package (0x02)
                            {
                                0x00, 
                                0x00
                            })
                        }
                        Else
                        {
                            Store (0x00, NSTE)
                            If (LEqual (Local0, 0x01))
                            {
                                Store ("LCD", Debug)
                                Store (Zero, \_SB.PCI0.UVGA.CRTA)
                                Store (One, \_SB.PCI0.UVGA.LCDA)
                                Store (Zero, \_SB.PCI0.UVGA.TVAF)
                                Store (Zero, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x02))
                            {
                                Store ("CRT", Debug)
                                Store (One, \_SB.PCI0.UVGA.CRTA)
                                Store (Zero, \_SB.PCI0.UVGA.LCDA)
                                Store (Zero, \_SB.PCI0.UVGA.TVAF)
                                Store (Zero, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x03))
                            {
                                Store ("Both", Debug)
                                Store (One, \_SB.PCI0.UVGA.CRTA)
                                Store (One, \_SB.PCI0.UVGA.LCDA)
                                Store (Zero, \_SB.PCI0.UVGA.TVAF)
                                Store (Zero, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x04))
                            {
                                Store ("TV", Debug)
                                Store (Zero, \_SB.PCI0.UVGA.CRTA)
                                Store (Zero, \_SB.PCI0.UVGA.LCDA)
                                Store (One, \_SB.PCI0.UVGA.TVAF)
                                Store (Zero, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x05))
                            {
                                Store ("TV+LCD", Debug)
                                Store (Zero, \_SB.PCI0.UVGA.CRTA)
                                Store (One, \_SB.PCI0.UVGA.LCDA)
                                Store (One, \_SB.PCI0.UVGA.TVAF)
                                Store (Zero, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x06))
                            {
                                Store ("TV+CRT", Debug)
                                Return (Package (0x02)
                                {
                                    0x06, 
                                    0x00
                                })
                            }

                            If (LEqual (Local0, 0x07))
                            {
                                Store ("TV+CRT+LCD", Debug)
                                Return (Package (0x02)
                                {
                                    0x06, 
                                    0x00
                                })
                            }

                            If (LEqual (Local0, 0x08))
                            {
                                Store (Zero, \_SB.PCI0.UVGA.CRTA)
                                Store (Zero, \_SB.PCI0.UVGA.LCDA)
                                Store (Zero, \_SB.PCI0.UVGA.TVAF)
                                Store (One, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x09))
                            {
                                Store (Zero, \_SB.PCI0.UVGA.CRTA)
                                Store (One, \_SB.PCI0.UVGA.LCDA)
                                Store (Zero, \_SB.PCI0.UVGA.TVAF)
                                Store (One, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LGreaterEqual (Local0, 0x0A))
                            {
                                Return (Package (0x02)
                                {
                                    0x06, 
                                    0x00
                                })
                            }

                            Store (CADL, PADL)
                            Notify (\_SB.PCI0.UVGA, 0x80)
                            Return (Package (0x02)
                            {
                                0x00, 
                                0x00
                            })
                        }
                    }
                    Else
                    {
                        Return (Package (0x02)
                        {
                            0x00, 
                            0x00
                        })
                    }
                }
            }

            Method (Z00G, 0, NotSerialized)
            {
                Store ("HP WMI Command 0x8 (BIOS Read)", Debug)
                Store (Package (0x03)
                    {
                        0x00, 
                        0x80, 
                        Buffer (0x80)
                        {
                            /* 0000 */    0x31, 0x01, 0x9B, 0x01, 0xFF, 0x01, 0x63, 0x02, 
                            /* 0008 */    0xAE, 0x01, 0x64, 0x02, 0x9D, 0x01, 0xB6, 0x01, 
                            /* 0010 */    0xB7, 0x01, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02, 
                            /* 0018 */    0x68, 0x02, 0xFF, 0xFF, 0xE4, 0x20, 0xE6, 0x20, 
                            /* 0020 */    0x42, 0x21, 0x70, 0x21, 0x00, 0x00
                        }
                    }, Local0)
                Return (Local0)
            }

            Method (Z00H, 0, NotSerialized)
            {
                Store ("HP WMI Command 0x9 (BIOS Read)", Debug)
                Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                Store (Package (0x03)
                    {
                        0x00, 
                        0x04, 
                        Buffer (0x04) {}
                    }, Local0)
                Store (\_SB.PCI0.EC0.Z00R (), Index (DerefOf (Index (Local0, 0x02)), 0x00))
                Release (\_SB.PCI0.EC0.MUT0)
                Return (Local0)
            }

            Method (Z00N, 1, NotSerialized)
            {
                Store ("HP WMI Command 0x9 (BIOS Write)", Debug)
                Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                \_SB.PCI0.EC0.Z00S (Arg0)
                Release (\_SB.PCI0.EC0.MUT0)
                Return (Package (0x02)
                {
                    0x00, 
                    0x00
                })
            }

            Method (Z00T, 0, NotSerialized)
            {
                Store (Package (0x03)
                    {
                        0x00, 
                        0x04, 
                        Buffer (0x04) {}
                    }, Local0)
                If (ECON)
                {
                    Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                    Store (\_SB.PCI0.EC0.QBHK, Local1)
                    Store (0x00, \_SB.PCI0.EC0.QBHK)
                    Release (\_SB.PCI0.EC0.MUT0)
                }

                If (LEqual (Local1, 0x0D))
                {
                    Store ("Fn+ESC Pressed", Debug)
                    Store (0x31, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                    Store (0x01, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                }

                If (LEqual (Local1, 0x01))
                {
                    Store ("Fn+F1 Pressed", Debug)
                    Store (0x9B, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                    Store (0x01, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                }

                If (LEqual (Local1, 0x04))
                {
                    \_SB.PCI0.EC0._Q0D ()
                    Store (0x00, Local3)
                    Store (0x00, Local4)
                    Store (0x00, Local5)
                    Store (0xAE, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                    Store (0x01, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                    ShiftLeft (And (NSTE, 0x01), 0x01, Local3)
                    ShiftLeft (And (NSTE, 0x02), 0x01, Local4)
                    ShiftRight (And (NSTE, 0x08), 0x03, Local5)
                    Or (Local3, Local4, Local3)
                    Or (Local3, Local5, Local3)
                    Store (CSTE, Local3)
                    Store (Local3, Index (DerefOf (Index (Local0, 0x02)), 0x02))
                    ShiftLeft (And (CADL, 0x01), 0x01, Local3)
                    ShiftLeft (And (CADL, 0x02), 0x01, Local4)
                    ShiftRight (And (CADL, 0x08), 0x03, Local5)
                    Or (Local3, Local4, Local3)
                    Or (Local3, Local5, Local3)
                    Store (PSTE, Local3)
                    Store (Local3, Index (DerefOf (Index (Local0, 0x02)), 0x03))
                }

                If (LEqual (Local1, 0x06))
                {
                    Store ("Fn+F6 Pressed", Debug)
                    Store (0x9D, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                    Store (0x01, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                }

                If (LEqual (Local1, 0x07))
                {
                    If (LEqual (OSYS, 0x07D6))
                    {
                        If (LEqual (VGAT, 0x01))
                        {
                            Notify (\_SB.PCI0.XVR0.VGA.LCD, 0x87)
                        }
                        Else
                        {
                            Notify (\_SB.PCI0.UVGA.LCD, 0x87)
                        }
                    }
                    Else
                    {
                        Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                        Store (0x8D, \_SB.PCI0.SMIC)
                        Release (\_SB.PCI0.PSMX)
                    }

                    Sleep (0x32)
                    Store (0xB6, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                    Store (0x01, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                }

                If (LEqual (Local1, 0x08))
                {
                    If (LEqual (OSYS, 0x07D6))
                    {
                        If (LEqual (VGAT, 0x01))
                        {
                            Notify (\_SB.PCI0.XVR0.VGA.LCD, 0x86)
                        }
                        Else
                        {
                            Notify (\_SB.PCI0.UVGA.LCD, 0x86)
                        }
                    }
                    Else
                    {
                        Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                        Store (0x8C, \_SB.PCI0.SMIC)
                        Release (\_SB.PCI0.PSMX)
                    }

                    Sleep (0x32)
                    Store (0xB7, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                    Store (0x01, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                }

                Return (Local0)
            }

            Method (Z00I, 0, NotSerialized)
            {
                Store ("HP WMI Command 0xA (BIOS Read)", Debug)
                Return (Z00T ())
            }

            Method (Z00O, 1, NotSerialized)
            {
                Store ("HP WMI Command 0xA (BIOS Write)", Debug)
                And (Arg0, 0xFF, Local1)
                And (Arg0, 0xFF00, Local3)
                ShiftRight (Local3, 0x08, Local2)
                Store (Package (0x03)
                    {
                        0x00, 
                        0x04, 
                        Buffer (0x04) {}
                    }, Local0)
                Store (Local1, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                Store (Local2, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                If (LEqual (Arg0, 0x01AE))
                {
                    \_SB.PCI0.EC0._Q0D ()
                    Store (CSTE, Index (DerefOf (Index (Local0, 0x02)), 0x02))
                    Store (PSTE, Index (DerefOf (Index (Local0, 0x02)), 0x03))
                }

                Return (Local0)
            }

            Method (Z00J, 0, NotSerialized)
            {
                Store ("HP WMI Command 0xC (BIOS Read)", Debug)
                Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                Store (Package (0x03)
                    {
                        0x00, 
                        0x04, 
                        Buffer (0x04) {}
                    }, Local0)
                If (ECON)
                {
                    Store (\_SB.PCI0.EC0.QBBB, Local1)
                    Store (0x00, \_SB.PCI0.EC0.QBBB)
                }

                If (LEqual (Local1, 0x03))
                {
                    Store (0xE4, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                    Store (0x20, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                }

                If (LEqual (Local1, 0x04))
                {
                    Store (0x42, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                    Store (0x21, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                }

                If (LEqual (Local1, 0x05))
                {
                    Store (0xE6, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                    Store (0x20, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                }

                If (LEqual (Local1, 0x10))
                {
                    Store (0x70, Index (DerefOf (Index (Local0, 0x02)), 0x00))
                    Store (0x21, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                }

                Release (\_SB.PCI0.EC0.MUT0)
                Return (Local0)
            }

            Method (_WED, 1, NotSerialized)
            {
                Concatenate (Z00P, Z00Q, Local0)
                Return (Local0)
            }

            Name (WQAE, Buffer (0x08A9)
            {
                /* 0000 */    0x46, 0x4F, 0x4D, 0x42, 0x01, 0x00, 0x00, 0x00, 
                /* 0008 */    0x99, 0x08, 0x00, 0x00, 0x8A, 0x3A, 0x00, 0x00, 
                /* 0010 */    0x44, 0x53, 0x00, 0x01, 0x1A, 0x7D, 0xDA, 0x54, 
                /* 0018 */    0x98, 0x4B, 0x9C, 0x00, 0x01, 0x06, 0x18, 0x42, 
                /* 0020 */    0x10, 0x13, 0x10, 0x22, 0x21, 0x04, 0x12, 0x01, 
                /* 0028 */    0xA1, 0xC8, 0x2C, 0x0C, 0x86, 0x10, 0x38, 0x2E, 
                /* 0030 */    0x84, 0x1C, 0x40, 0x88, 0x59, 0x50, 0x08, 0x21, 
                /* 0038 */    0x10, 0xEA, 0x4F, 0x20, 0xBF, 0x02, 0x10, 0x3A, 
                /* 0040 */    0x14, 0x20, 0x53, 0x80, 0x41, 0x01, 0x4E, 0x11, 
                /* 0048 */    0x44, 0xD0, 0xAB, 0x00, 0x9B, 0x02, 0x4C, 0x0A, 
                /* 0050 */    0xB0, 0x28, 0x40, 0xBB, 0x00, 0xCB, 0x02, 0x74, 
                /* 0058 */    0x0B, 0x90, 0x0E, 0x4B, 0x44, 0x82, 0xA3, 0xC4, 
                /* 0060 */    0x80, 0xA3, 0x74, 0x62, 0x0B, 0x37, 0x6C, 0xF0, 
                /* 0068 */    0x42, 0x51, 0x34, 0x83, 0x28, 0x09, 0x2A, 0x17, 
                /* 0070 */    0xE0, 0x1B, 0x41, 0xE0, 0xE5, 0x0A, 0x90, 0x3C, 
                /* 0078 */    0x01, 0x69, 0x16, 0x60, 0x58, 0x80, 0x75, 0x01, 
                /* 0080 */    0xB2, 0x87, 0x40, 0xA5, 0x0E, 0x01, 0x25, 0x67, 
                /* 0088 */    0x08, 0xA8, 0x01, 0xB4, 0x3A, 0x01, 0xE1, 0x57, 
                /* 0090 */    0x3A, 0x25, 0x24, 0x41, 0x38, 0x63, 0x15, 0x8F, 
                /* 0098 */    0xAF, 0x59, 0x34, 0x3D, 0x27, 0x39, 0xC7, 0x90, 
                /* 00A0 */    0xE3, 0x71, 0xA1, 0x07, 0xC1, 0x05, 0x78, 0x18, 
                /* 00A8 */    0x06, 0x1D, 0xB2, 0x22, 0x6B, 0x80, 0xC1, 0x58, 
                /* 00B0 */    0x18, 0x0B, 0x75, 0x31, 0x6A, 0xD4, 0x48, 0xD9, 
                /* 00B8 */    0x80, 0x0C, 0x51, 0x12, 0x1C, 0x6A, 0xD4, 0x96, 
                /* 00C0 */    0x28, 0xC0, 0xFC, 0x38, 0x34, 0xBB, 0xB6, 0xC7, 
                /* 00C8 */    0x42, 0x20, 0x99, 0xB4, 0xA1, 0xA0, 0xA4, 0x40, 
                /* 00D0 */    0x68, 0x6C, 0x67, 0xEA, 0x19, 0x45, 0x3C, 0x52, 
                /* 00D8 */    0xC3, 0x24, 0xF0, 0x28, 0x22, 0x1B, 0x8D, 0x43, 
                /* 00E0 */    0x63, 0x87, 0xE1, 0x61, 0x06, 0x3B, 0x88, 0xC3, 
                /* 00E8 */    0x38, 0xE6, 0xC8, 0x09, 0x3C, 0xA1, 0x23, 0x3D, 
                /* 00F0 */    0xF2, 0xC2, 0xE6, 0x29, 0xD4, 0x18, 0xCD, 0x41, 
                /* 00F8 */    0x11, 0xB8, 0xD0, 0x18, 0x19, 0x10, 0xF2, 0x3C, 
                /* 0100 */    0x7E, 0x8D, 0xC4, 0x04, 0x76, 0x2F, 0xC0, 0x1A, 
                /* 0108 */    0xA6, 0x60, 0x1B, 0x9B, 0x98, 0xFE, 0xFF, 0x10, 
                /* 0110 */    0x47, 0x1E, 0xA3, 0xAD, 0xB9, 0x0B, 0x29, 0x4C, 
                /* 0118 */    0x8C, 0x28, 0xC1, 0xE2, 0x55, 0x3C, 0x0D, 0xA1, 
                /* 0120 */    0x3C, 0x29, 0x84, 0x8A, 0x54, 0x19, 0x8A, 0x86, 
                /* 0128 */    0x1E, 0xA5, 0x42, 0x01, 0xCE, 0xE6, 0x21, 0xDC, 
                /* 0130 */    0x1A, 0x41, 0x85, 0x10, 0x2B, 0x52, 0xAC, 0xF6, 
                /* 0138 */    0x07, 0x41, 0x42, 0x2E, 0x5B, 0xC7, 0x07, 0x47, 
                /* 0140 */    0x1A, 0x0D, 0xEA, 0x50, 0xE0, 0xB1, 0x7B, 0xDC, 
                /* 0148 */    0xCF, 0x02, 0x3E, 0x08, 0x9C, 0x5B, 0x90, 0xA3, 
                /* 0150 */    0x3B, 0x8B, 0x47, 0x85, 0x83, 0xF6, 0xF0, 0xD8, 
                /* 0158 */    0x6D, 0xC0, 0x67, 0x08, 0x9F, 0x02, 0xF0, 0xAE, 
                /* 0160 */    0x01, 0x35, 0xFD, 0x83, 0x67, 0x82, 0xE0, 0x50, 
                /* 0168 */    0x43, 0xF4, 0xA8, 0xC3, 0x9D, 0xC0, 0x21, 0x32, 
                /* 0170 */    0x40, 0x4F, 0xEA, 0xB8, 0xB1, 0x83, 0x3B, 0x99, 
                /* 0178 */    0x83, 0x7E, 0x6F, 0x68, 0xF6, 0xC6, 0x40, 0x08, 
                /* 0180 */    0x8E, 0xC7, 0x97, 0x05, 0x36, 0xE1, 0x04, 0x96, 
                /* 0188 */    0x3F, 0x08, 0xD4, 0xC8, 0x0C, 0xED, 0x51, 0x9E, 
                /* 0190 */    0x56, 0xCC, 0x90, 0xCF, 0x0C, 0x26, 0xB0, 0x58, 
                /* 0198 */    0x08, 0x29, 0x80, 0xD0, 0x78, 0xC0, 0x7F, 0x03, 
                /* 01A0 */    0x78, 0xC0, 0xF0, 0xCD, 0xC0, 0xF3, 0x35, 0xC1, 
                /* 01A8 */    0xB0, 0x10, 0x32, 0xB2, 0x0A, 0x8F, 0x87, 0x8E, 
                /* 01B0 */    0xC2, 0xD7, 0x83, 0xC3, 0x39, 0xAD, 0x78, 0x26, 
                /* 01B8 */    0x18, 0x0E, 0x42, 0x27, 0x09, 0x8B, 0x1A, 0x36, 
                /* 01C0 */    0x3D, 0x39, 0xF0, 0x43, 0x03, 0xBB, 0x19, 0x9C, 
                /* 01C8 */    0xC1, 0x23, 0x80, 0x47, 0x72, 0x42, 0xFE, 0x98, 
                /* 01D0 */    0x78, 0x60, 0xF0, 0x01, 0xF1, 0xDE, 0xA7, 0x4C, 
                /* 01D8 */    0x46, 0x70, 0xA6, 0x06, 0xF4, 0x71, 0xC0, 0xFF, 
                /* 01E0 */    0xFF, 0xA1, 0xF0, 0x21, 0x7A, 0x7C, 0xA7, 0x7C, 
                /* 01E8 */    0xBC, 0x96, 0x00, 0x21, 0x59, 0xE3, 0x84, 0x7E, 
                /* 01F0 */    0x87, 0xF0, 0xF1, 0xC3, 0x47, 0x16, 0x47, 0x84, 
                /* 01F8 */    0x90, 0x93, 0x53, 0x00, 0x1A, 0xF8, 0x74, 0xCF, 
                /* 0200 */    0x2E, 0xC2, 0xE9, 0x7A, 0x52, 0x0E, 0x34, 0x0C, 
                /* 0208 */    0x3A, 0x4E, 0x70, 0x9C, 0x07, 0xC0, 0x31, 0x4E, 
                /* 0210 */    0xF8, 0xE7, 0x02, 0xF8, 0x03, 0xE4, 0xA7, 0x8C, 
                /* 0218 */    0x57, 0x8C, 0x04, 0x8E, 0x39, 0x42, 0xF4, 0xB9, 
                /* 0220 */    0xC6, 0x23, 0xC4, 0xC2, 0x3F, 0x55, 0x14, 0x3E, 
                /* 0228 */    0x10, 0x32, 0x46, 0x70, 0x01, 0x7A, 0x8C, 0xC0, 
                /* 0230 */    0x37, 0xE0, 0x18, 0xD1, 0x47, 0x09, 0xAE, 0xFE, 
                /* 0238 */    0xA0, 0x41, 0x07, 0x88, 0xFB, 0xFF, 0x0F, 0x10, 
                /* 0240 */    0x3E, 0xA8, 0x07, 0x08, 0x7C, 0xA3, 0x1F, 0x3D, 
                /* 0248 */    0xD0, 0xE3, 0xB2, 0xE8, 0xF3, 0x80, 0x8C, 0x9F, 
                /* 0250 */    0x68, 0x34, 0x2F, 0x7E, 0x3A, 0xE0, 0x87, 0x0F, 
                /* 0258 */    0xF0, 0x80, 0x7A, 0x48, 0x38, 0x50, 0xCC, 0xB4, 
                /* 0260 */    0x39, 0xE8, 0xB3, 0xCB, 0xA1, 0x63, 0x87, 0x0B, 
                /* 0268 */    0xFE, 0x13, 0x08, 0xB8, 0xE4, 0x1D, 0xC2, 0x40, 
                /* 0270 */    0x31, 0x62, 0xFC, 0x39, 0xC8, 0xA7, 0x30, 0xF0, 
                /* 0278 */    0xFF, 0xFF, 0x4F, 0x61, 0xB8, 0x11, 0xF0, 0x20, 
                /* 0280 */    0xAF, 0x05, 0x9F, 0xB6, 0xA8, 0x74, 0x18, 0xD4, 
                /* 0288 */    0x81, 0x0B, 0x30, 0x09, 0x1A, 0xE1, 0x59, 0xA2, 
                /* 0290 */    0x36, 0x08, 0x01, 0xBF, 0x4D, 0xBC, 0x6D, 0xF9, 
                /* 0298 */    0x16, 0x10, 0xE7, 0xC8, 0x7B, 0x3B, 0x70, 0x11, 
                /* 02A0 */    0x8C, 0x08, 0xA7, 0x1D, 0xCA, 0x63, 0x88, 0x18, 
                /* 02A8 */    0x23, 0xCA, 0xE3, 0x96, 0x51, 0xDE, 0xB6, 0x5E, 
                /* 02B0 */    0x00, 0xE2, 0x9D, 0xE5, 0xF3, 0x96, 0x31, 0x82, 
                /* 02B8 */    0x47, 0x7E, 0xE0, 0x62, 0x62, 0xDF, 0x13, 0xFA, 
                /* 02C0 */    0xB9, 0xF9, 0xC0, 0x05, 0x38, 0xFB, 0xFF, 0x1F, 
                /* 02C8 */    0xB8, 0x00, 0x0E, 0x05, 0x3D, 0x0C, 0xA1, 0x87, 
                /* 02D0 */    0xE1, 0xA9, 0x9C, 0xCB, 0x13, 0xE5, 0xA9, 0x44, 
                /* 02D8 */    0x8C, 0x1A, 0x26, 0xEA, 0x33, 0x94, 0x2F, 0x1A, 
                /* 02E0 */    0x3E, 0x10, 0x81, 0xEF, 0xCC, 0x05, 0xFC, 0xFE, 
                /* 02E8 */    0xFF, 0x07, 0x22, 0x38, 0x02, 0xCF, 0x34, 0xA0, 
                /* 02F0 */    0xF4, 0x39, 0x03, 0x81, 0x9C, 0x8A, 0x0F, 0x35, 
                /* 02F8 */    0xC0, 0x48, 0xF4, 0xAB, 0xC1, 0x27, 0x1A, 0x2A, 
                /* 0300 */    0x13, 0x06, 0x75, 0xA8, 0x01, 0x4C, 0x5E, 0x61, 
                /* 0308 */    0x9E, 0x46, 0xCF, 0xF9, 0x59, 0xC6, 0xA7, 0x1A, 
                /* 0310 */    0x1F, 0x4A, 0x8D, 0x63, 0x88, 0x97, 0x99, 0x87, 
                /* 0318 */    0x1A, 0x1F, 0x0B, 0x5E, 0x49, 0x7D, 0xA8, 0x31, 
                /* 0320 */    0x54, 0x9C, 0x87, 0x1A, 0x9F, 0x48, 0x03, 0x45, 
                /* 0328 */    0x7D, 0xB3, 0x79, 0xB6, 0x31, 0x7A, 0x7C, 0xDF, 
                /* 0330 */    0x50, 0x0D, 0xF1, 0x50, 0xC3, 0x84, 0xBD, 0x23, 
                /* 0338 */    0xF4, 0xC1, 0xF5, 0xA1, 0x06, 0x1C, 0xFF, 0xFF, 
                /* 0340 */    0x43, 0x0D, 0xC0, 0xFF, 0xFF, 0xFF, 0xA1, 0x06, 
                /* 0348 */    0x70, 0x74, 0x34, 0x80, 0x73, 0x64, 0xC4, 0x1D, 
                /* 0350 */    0x0D, 0xC0, 0x75, 0x28, 0x05, 0x0E, 0x47, 0x03, 
                /* 0358 */    0xE0, 0x71, 0x14, 0x02, 0xF3, 0x85, 0xC6, 0x47, 
                /* 0360 */    0x21, 0x60, 0xF1, 0xFF, 0x3F, 0x0A, 0xE1, 0x64, 
                /* 0368 */    0x9F, 0x83, 0x50, 0x42, 0x8F, 0x42, 0x80, 0x54, 
                /* 0370 */    0xC8, 0xA7, 0x88, 0x67, 0x1F, 0x5F, 0x7E, 0x1E, 
                /* 0378 */    0x08, 0x22, 0xBC, 0xE6, 0xFB, 0x14, 0xE4, 0x43, 
                /* 0380 */    0xBE, 0x8F, 0x42, 0x0C, 0xC6, 0x50, 0xBE, 0x06, 
                /* 0388 */    0xF9, 0x28, 0xC4, 0xA0, 0x5E, 0x83, 0x7C, 0xDF, 
                /* 0390 */    0x37, 0xC8, 0x91, 0x18, 0xFB, 0x99, 0xC0, 0x47, 
                /* 0398 */    0x21, 0x26, 0xED, 0x28, 0x04, 0x28, 0xFC, 0xFF, 
                /* 03A0 */    0x1F, 0x85, 0x00, 0xFE, 0xFF, 0xFF, 0x8F, 0x42, 
                /* 03A8 */    0x80, 0xB3, 0x00, 0x47, 0x03, 0xD0, 0x4D, 0xEB, 
                /* 03B0 */    0x51, 0x08, 0xBC, 0x77, 0x96, 0xD3, 0x3E, 0x01, 
                /* 03B8 */    0x9F, 0x85, 0x00, 0xB3, 0xFF, 0xFF, 0xB3, 0x10, 
                /* 03C0 */    0x30, 0x3B, 0x0A, 0x45, 0x3D, 0xE8, 0x57, 0xA1, 
                /* 03C8 */    0x27, 0x80, 0x17, 0x80, 0x18, 0x61, 0xDE, 0x81, 
                /* 03D0 */    0x5E, 0x32, 0xD9, 0x5D, 0xDC, 0x38, 0x4F, 0x2E, 
                /* 03D8 */    0xA7, 0x6D, 0x94, 0x97, 0x20, 0x1F, 0x28, 0x9E, 
                /* 03E0 */    0x85, 0x0C, 0xF5, 0x2E, 0x14, 0xF4, 0x8D, 0xDC, 
                /* 03E8 */    0xA3, 0x8C, 0x19, 0x3F, 0xC4, 0xF3, 0x90, 0x21, 
                /* 03F0 */    0x9E, 0x85, 0x00, 0x76, 0xFD, 0xFF, 0xCF, 0x42, 
                /* 03F8 */    0x00, 0xFF, 0xFF, 0xFF, 0x47, 0x03, 0xF8, 0x2F, 
                /* 0400 */    0x00, 0x9F, 0x85, 0x80, 0xE7, 0x09, 0xE0, 0x41, 
                /* 0408 */    0xDB, 0x67, 0x21, 0x80, 0x33, 0x87, 0xCB, 0xF3, 
                /* 0410 */    0x0F, 0x7A, 0x60, 0xEF, 0x11, 0x9E, 0xF5, 0x71, 
                /* 0418 */    0xBF, 0x5E, 0x7A, 0xE0, 0x0F, 0x05, 0xCF, 0x42, 
                /* 0420 */    0x0C, 0xEB, 0x98, 0x7C, 0x16, 0x62, 0x10, 0x2F, 
                /* 0428 */    0x9A, 0x86, 0x78, 0xE1, 0xF4, 0x61, 0xC0, 0xFF, 
                /* 0430 */    0x7F, 0xBC, 0xC0, 0xAF, 0x9C, 0x06, 0x0A, 0x12, 
                /* 0438 */    0xE8, 0x59, 0x08, 0x60, 0xFC, 0xFF, 0xFF, 0x2C, 
                /* 0440 */    0x04, 0x90, 0x71, 0x8D, 0x3A, 0x0B, 0x01, 0xCB, 
                /* 0448 */    0x63, 0x0C, 0x3B, 0xAD, 0x24, 0xF8, 0xFF, 0x3F, 
                /* 0450 */    0x0B, 0x01, 0x9F, 0x5C, 0x46, 0x0E, 0x42, 0x98, 
                /* 0458 */    0x88, 0x6F, 0x05, 0x1F, 0x33, 0x01, 0xA5, 0xE7, 
                /* 0460 */    0xA0, 0x17, 0x77, 0x63, 0x04, 0x7E, 0x91, 0x78, 
                /* 0468 */    0xCC, 0x64, 0x47, 0x4D, 0xC3, 0x3C, 0x0B, 0x19, 
                /* 0470 */    0xEF, 0x30, 0xCE, 0xE0, 0x09, 0xDE, 0x93, 0x7F, 
                /* 0478 */    0x16, 0x62, 0x60, 0xC7, 0x18, 0xEC, 0x51, 0xC8, 
                /* 0480 */    0xA0, 0x06, 0x8F, 0x1D, 0x22, 0x4C, 0xA0, 0x67, 
                /* 0488 */    0x21, 0x16, 0x6A, 0xDC, 0x3A, 0x7F, 0xF8, 0x2C, 
                /* 0490 */    0x04, 0xBC, 0xFF, 0xFF, 0x67, 0x21, 0xC0, 0xD3, 
                /* 0498 */    0x61, 0xC3, 0x67, 0x0D, 0xF0, 0x0C, 0xDF, 0xA3, 
                /* 04A0 */    0x3A, 0x87, 0xC7, 0x63, 0xE0, 0x92, 0x55, 0xC7, 
                /* 04A8 */    0x09, 0x83, 0xE5, 0x5E, 0xA7, 0x6C, 0x9C, 0x61, 
                /* 04B0 */    0xE8, 0x20, 0xAC, 0x0E, 0x48, 0xC3, 0xC1, 0xDC, 
                /* 04B8 */    0x43, 0x0E, 0xE2, 0x7C, 0xD8, 0x40, 0xAD, 0x08, 
                /* 04C0 */    0x4E, 0xC7, 0x24, 0x0F, 0xDA, 0x5A, 0x28, 0xA4, 
                /* 04C8 */    0x80, 0x46, 0x03, 0x32, 0xBC, 0x33, 0x9F, 0x96, 
                /* 04D0 */    0x28, 0x88, 0x01, 0x7D, 0x02, 0xB2, 0x8D, 0x73, 
                /* 04D8 */    0x00, 0x6A, 0x2F, 0x9A, 0x02, 0x39, 0xDA, 0x60, 
                /* 04E0 */    0xF4, 0x5F, 0x16, 0xE8, 0x6C, 0x7C, 0x0D, 0xE0, 
                /* 04E8 */    0x1A, 0x20, 0x74, 0x30, 0x30, 0xB4, 0xD5, 0xDC, 
                /* 04F0 */    0x62, 0x50, 0x60, 0xC6, 0x7F, 0x70, 0x31, 0x81, 
                /* 04F8 */    0x8F, 0x2E, 0xF8, 0xB3, 0x00, 0xEE, 0xFF, 0x3F, 
                /* 0500 */    0x5C, 0x8F, 0xF6, 0x5D, 0xA0, 0xEA, 0xC9, 0xEA, 
                /* 0508 */    0x8A, 0x60, 0x75, 0x97, 0x17, 0x08, 0x33, 0x32, 
                /* 0510 */    0x41, 0x7D, 0x07, 0x02, 0x50, 0x00, 0xF9, 0x0E, 
                /* 0518 */    0xE0, 0xA3, 0xD3, 0x73, 0x00, 0x9B, 0x48, 0x88, 
                /* 0520 */    0x30, 0xD1, 0x8C, 0x8E, 0x98, 0x30, 0x2A, 0xFA, 
                /* 0528 */    0x84, 0x29, 0x88, 0x27, 0xEC, 0x58, 0x13, 0x46, 
                /* 0530 */    0xCF, 0xC4, 0x77, 0x1B, 0x36, 0x62, 0x4C, 0x88, 
                /* 0538 */    0xDB, 0x06, 0xB4, 0x09, 0x06, 0xF5, 0x3D, 0x08, 
                /* 0540 */    0xD6, 0x90, 0xF9, 0x58, 0x7C, 0x67, 0xC0, 0x4D, 
                /* 0548 */    0x19, 0x8C, 0x73, 0x62, 0xD7, 0x04, 0x0B, 0x9C, 
                /* 0550 */    0x33, 0xC8, 0xE1, 0x31, 0xD7, 0x2F, 0x7E, 0x5B, 
                /* 0558 */    0xF2, 0xE8, 0xF8, 0x41, 0xC1, 0x37, 0x1C, 0x86, 
                /* 0560 */    0xFD, 0x30, 0xE6, 0x19, 0xBD, 0x8A, 0xF9, 0xE6, 
                /* 0568 */    0x86, 0x81, 0xF5, 0x78, 0x39, 0xAC, 0xD1, 0xC2, 
                /* 0570 */    0x1E, 0xDA, 0xAB, 0x87, 0xCF, 0x2D, 0x3E, 0x4F, 
                /* 0578 */    0x18, 0x23, 0xAC, 0x2F, 0x2C, 0xE0, 0x00, 0xFC, 
                /* 0580 */    0xFF, 0xBF, 0x5A, 0xC1, 0xBE, 0x6B, 0x80, 0xE7, 
                /* 0588 */    0x26, 0xE4, 0xBB, 0x06, 0xC0, 0xDA, 0xFF, 0xFF, 
                /* 0590 */    0x5D, 0x03, 0xFE, 0x35, 0xC1, 0x77, 0x0D, 0xE0, 
                /* 0598 */    0x3D, 0x74, 0xDF, 0x35, 0x80, 0x6B, 0xF6, 0xBB, 
                /* 05A0 */    0x06, 0xEA, 0x18, 0x60, 0x85, 0x77, 0x0D, 0x68, 
                /* 05A8 */    0xB7, 0xB4, 0x57, 0xB4, 0x87, 0x2A, 0x6B, 0xBA, 
                /* 05B0 */    0x6C, 0xA0, 0xD4, 0x5C, 0x36, 0x00, 0x6D, 0xFF, 
                /* 05B8 */    0xFF, 0xCB, 0x06, 0xB0, 0x91, 0x32, 0x61, 0x54, 
                /* 05C0 */    0xF8, 0x09, 0x53, 0x10, 0x4F, 0xD8, 0xC1, 0x2E, 
                /* 05C8 */    0x1B, 0xA0, 0x88, 0x71, 0xD9, 0x00, 0xFD, 0xD8, 
                /* 05D0 */    0x5E, 0x36, 0x80, 0xC1, 0x3D, 0x81, 0xDF, 0x36, 
                /* 05D8 */    0x80, 0x37, 0xA4, 0x6F, 0x1B, 0xC0, 0xF4, 0xFF, 
                /* 05E0 */    0x0F, 0x31, 0xFF, 0x6D, 0x03, 0xC5, 0x61, 0x95, 
                /* 05E8 */    0xB7, 0x0D, 0x88, 0x87, 0x77, 0x46, 0x60, 0x55, 
                /* 05F0 */    0xD7, 0x0D, 0x94, 0x9E, 0xEB, 0x06, 0x40, 0x02, 
                /* 05F8 */    0x31, 0x13, 0x46, 0xC5, 0x9F, 0x30, 0x05, 0xF1, 
                /* 0600 */    0x84, 0x1D, 0xED, 0xBA, 0x01, 0x8A, 0x20, 0xD7, 
                /* 0608 */    0x0D, 0xD0, 0xCF, 0xEB, 0x94, 0xC1, 0xFA, 0xFF, 
                /* 0610 */    0xBF, 0x6E, 0x60, 0x2F, 0x0A, 0x98, 0xFB, 0x06, 
                /* 0618 */    0xF0, 0x86, 0xE5, 0xF7, 0x0D, 0xC0, 0xC7, 0xE5, 
                /* 0620 */    0x1B, 0x73, 0xDF, 0x00, 0x6C, 0xFE, 0xFF, 0xEF, 
                /* 0628 */    0x1B, 0x00, 0x13, 0x2E, 0x0A, 0xB8, 0xFB, 0x06, 
                /* 0630 */    0xF0, 0xBE, 0x48, 0xFB, 0xBE, 0x01, 0x5C, 0x83, 
                /* 0638 */    0x49, 0xF8, 0xFF, 0xDF, 0xF5, 0xE8, 0x0B, 0x40, 
                /* 0640 */    0x51, 0x60, 0x50, 0x43, 0xF2, 0x99, 0x00, 0x3F, 
                /* 0648 */    0xBA, 0x83, 0x3B, 0xA6, 0xE0, 0x4C, 0x12, 0x1C, 
                /* 0650 */    0x6A, 0xE0, 0xBE, 0x02, 0x3C, 0xCD, 0x9F, 0xD6, 
                /* 0658 */    0x7B, 0xBD, 0xE7, 0xF1, 0x24, 0x10, 0x92, 0x1D, 
                /* 0660 */    0x61, 0x7C, 0x6C, 0x43, 0x9C, 0x0C, 0xC8, 0x41, 
                /* 0668 */    0xDC, 0x47, 0xF7, 0x88, 0xEF, 0xE1, 0x86, 0x49, 
                /* 0670 */    0xE0, 0x21, 0x33, 0x34, 0x0E, 0x8D, 0x1D, 0x86, 
                /* 0678 */    0xEF, 0x02, 0xC1, 0x0E, 0xE2, 0x30, 0xCE, 0xD7, 
                /* 0680 */    0x04, 0x9E, 0xD0, 0x83, 0xC0, 0x7B, 0xF9, 0xA3, 
                /* 0688 */    0x41, 0xF1, 0x77, 0x03, 0x4A, 0x60, 0xB8, 0xD0, 
                /* 0690 */    0x98, 0x91, 0xFA, 0x6C, 0xFF, 0x8E, 0x70, 0x24, 
                /* 0698 */    0x26, 0xB0, 0x7B, 0x48, 0x59, 0x13, 0xA0, 0xF1, 
                /* 06A0 */    0x96, 0x43, 0x20, 0x7A, 0xC3, 0x91, 0x2D, 0x14, 
                /* 06A8 */    0xCD, 0x2D, 0xCA, 0xFB, 0x42, 0x14, 0x3B, 0x43, 
                /* 06B0 */    0x10, 0x46, 0x94, 0x60, 0x41, 0x9E, 0xD6, 0x62, 
                /* 06B8 */    0x45, 0x79, 0x66, 0x37, 0x42, 0xC4, 0x10, 0xAF, 
                /* 06C0 */    0x0C, 0x81, 0x5E, 0x12, 0xC2, 0x07, 0x79, 0xEC, 
                /* 06C8 */    0x89, 0xD3, 0xFE, 0x20, 0x88, 0xF8, 0x17, 0x82, 
                /* 06D0 */    0x3C, 0x80, 0x28, 0xD2, 0x68, 0x50, 0xE7, 0x06, 
                /* 06D8 */    0x8F, 0xDD, 0x87, 0x10, 0x5F, 0xFE, 0x7D, 0xB8, 
                /* 06E0 */    0xF7, 0xE8, 0x0E, 0xEE, 0x45, 0xFE, 0xA0, 0x3D, 
                /* 06E8 */    0x3C, 0x76, 0xC2, 0xF0, 0x41, 0x03, 0x8E, 0x6B, 
                /* 06F0 */    0x40, 0x4D, 0xFF, 0x19, 0x01, 0x2C, 0x97, 0x7F, 
                /* 06F8 */    0xF8, 0xE3, 0xF1, 0x3D, 0xC1, 0xF3, 0x39, 0xE1, 
                /* 0700 */    0x04, 0x96, 0x3F, 0x08, 0xD4, 0x71, 0x84, 0xCF, 
                /* 0708 */    0xF3, 0x85, 0xC3, 0x90, 0xCF, 0x02, 0x87, 0xC5, 
                /* 0710 */    0xC4, 0x0A, 0xF8, 0xFF, 0x9F, 0x4C, 0xD8, 0x78, 
                /* 0718 */    0xC0, 0x7F, 0x0F, 0x79, 0xFD, 0xF7, 0xCD, 0xC0, 
                /* 0720 */    0xF3, 0x35, 0xC1, 0x88, 0x10, 0x72, 0x32, 0x1E, 
                /* 0728 */    0x34, 0xE8, 0xD9, 0xF8, 0x80, 0xE1, 0xEB, 0x09, 
                /* 0730 */    0x3B, 0x77, 0x70, 0x51, 0xE7, 0x0E, 0xD4, 0xD1, 
                /* 0738 */    0xC1, 0xA7, 0x06, 0x76, 0xB3, 0xC1, 0x1C, 0xB7, 
                /* 0740 */    0xF9, 0x59, 0x03, 0xFC, 0x23, 0x84, 0x7F, 0x7B, 
                /* 0748 */    0xF0, 0xBC, 0x7C, 0x65, 0x78, 0x75, 0x48, 0xE0, 
                /* 0750 */    0x90, 0x23, 0x44, 0x8F, 0xCB, 0x23, 0xC4, 0x9C, 
                /* 0758 */    0x6F, 0x30, 0x43, 0x04, 0xD7, 0x59, 0x00, 0x1C, 
                /* 0760 */    0x43, 0x04, 0x3E, 0x67, 0x4C, 0x9F, 0x71, 0x60, 
                /* 0768 */    0xFE, 0xFF, 0xCF, 0x38, 0xEC, 0xD2, 0xC3, 0x07, 
                /* 0770 */    0x6A, 0x78, 0x13, 0xF8, 0xFE, 0x8C, 0x3B, 0xD2, 
                /* 0778 */    0x18, 0x9C, 0x1F, 0x33, 0x1E, 0x76, 0x18, 0xF8, 
                /* 0780 */    0xFB, 0x8E, 0x67, 0x70, 0x34, 0x3E, 0xA0, 0x18, 
                /* 0788 */    0x21, 0xF8, 0x73, 0xC9, 0x73, 0x8A, 0x35, 0x0F, 
                /* 0790 */    0x52, 0x33, 0x7A, 0x67, 0x38, 0x04, 0x76, 0xB3, 
                /* 0798 */    0xC2, 0x1D, 0x38, 0x3C, 0x04, 0x3E, 0x80, 0x56, 
                /* 07A0 */    0x27, 0x47, 0x4E, 0x3F, 0xA7, 0x84, 0x1B, 0x3E, 
                /* 07A8 */    0xBF, 0x0A, 0x60, 0x0E, 0x41, 0x38, 0x85, 0x36, 
                /* 07B0 */    0x7D, 0x6A, 0x34, 0x6A, 0xD5, 0xA0, 0x4C, 0x8D, 
                /* 07B8 */    0x32, 0x0D, 0x6A, 0xF5, 0xA9, 0xD4, 0x98, 0xB1, 
                /* 07C0 */    0x0B, 0x8B, 0x03, 0xBE, 0x02, 0x74, 0x1C, 0xB0, 
                /* 07C8 */    0x3C, 0x0A, 0x1D, 0xC1, 0xC8, 0x9B, 0x40, 0x20, 
                /* 07D0 */    0x0E, 0x0B, 0x42, 0x23, 0xBD, 0x71, 0x04, 0x62, 
                /* 07D8 */    0xC9, 0xEF, 0x2F, 0x81, 0x58, 0xEE, 0x03, 0x45, 
                /* 07E0 */    0x20, 0x0E, 0x68, 0x02, 0x9C, 0xAA, 0x00, 0xA7, 
                /* 07E8 */    0xAF, 0x01, 0x81, 0x38, 0x32, 0x08, 0x15, 0xFA, 
                /* 07F0 */    0x35, 0x13, 0x88, 0x63, 0x82, 0xD0, 0x50, 0x3E, 
                /* 07F8 */    0x40, 0x98, 0xF4, 0x17, 0x80, 0x00, 0x89, 0x11, 
                /* 0800 */    0x10, 0x16, 0xEE, 0xE5, 0x20, 0x10, 0x4B, 0x7B, 
                /* 0808 */    0x2D, 0x08, 0xC4, 0x42, 0xAC, 0x80, 0xB0, 0xB8, 
                /* 0810 */    0x20, 0x34, 0x9C, 0x16, 0x10, 0x26, 0xC9, 0x0C, 
                /* 0818 */    0x08, 0x0B, 0x04, 0x42, 0xE5, 0x3F, 0xD3, 0x04, 
                /* 0820 */    0x62, 0x91, 0x6E, 0x00, 0xE9, 0xBA, 0x05, 0xE2, 
                /* 0828 */    0x20, 0x7A, 0x40, 0x98, 0x0C, 0x3F, 0x20, 0x2C, 
                /* 0830 */    0x34, 0x08, 0x8D, 0xF6, 0x6C, 0x10, 0x20, 0x31, 
                /* 0838 */    0x04, 0xC2, 0xE2, 0x3B, 0x02, 0x61, 0xE2, 0xDF, 
                /* 0840 */    0x44, 0x02, 0x71, 0x4A, 0x4B, 0x10, 0x37, 0xA5, 
                /* 0848 */    0x01, 0x06, 0x11, 0x90, 0x93, 0x6A, 0x02, 0x62, 
                /* 0850 */    0xB9, 0x41, 0x34, 0x24, 0xF2, 0xB0, 0x10, 0x90, 
                /* 0858 */    0x93, 0x82, 0x68, 0xC0, 0xC4, 0x14, 0x90, 0xFF, 
                /* 0860 */    0xFF, 0x43, 0x13, 0x88, 0x80, 0x9C, 0xCA, 0x15, 
                /* 0868 */    0x10, 0x8B, 0x08, 0x22, 0x20, 0x27, 0x7B, 0x52, 
                /* 0870 */    0x09, 0xC8, 0x39, 0x41, 0x74, 0x04, 0x20, 0xBA, 
                /* 0878 */    0x80, 0x58, 0x3E, 0x10, 0x01, 0x39, 0x96, 0x2F, 
                /* 0880 */    0x20, 0x16, 0x12, 0x44, 0x40, 0x4E, 0xF4, 0xF3, 
                /* 0888 */    0x09, 0x44, 0xE2, 0x81, 0x68, 0x10, 0xE4, 0x3F, 
                /* 0890 */    0x21, 0x20, 0x67, 0x04, 0x11, 0x10, 0x79, 0x12, 
                /* 0898 */    0x05, 0x21, 0x9A, 0x3E, 0x62, 0x02, 0x71, 0x6A, 
                /* 08A0 */    0x10, 0x9A, 0xEC, 0x27, 0x14, 0x84, 0xFC, 0xFF, 
                /* 08A8 */    0x01
            })
        }

        Device (PCI0)
        {
            Name (_ADR, 0x00)
            Name (_HID, EisaId ("PNP0A03"))
            Name (_UID, 0x01)
            Method (_INI, 0, NotSerialized)
            {
                Store (0x07D0, OSYS)
                If (CondRefOf (_OSI, Local0))
                {
                    If (\_OSI ("Linux"))
                    {
                        Store (0x03E8, OSYS)
                    }

                    If (\_OSI ("Windows 2001"))
                    {
                        Store (0x07D1, OSYS)
                    }

                    If (\_OSI ("Windows 2001 SP1"))
                    {
                        Store (0x07D1, OSYS)
                    }

                    If (\_OSI ("Windows 2001 SP2"))
                    {
                        Store (0x07D2, OSYS)
                    }

                    If (\_OSI ("Windows 2006"))
                    {
                        Store (0x07D6, OSYS)
                    }
                }
            }

            Method (_STA, 0, NotSerialized)
            {
                Return (0x0F)
            }

            Scope (\_SB)
            {
                OperationRegion (ASLD, SystemMemory, 0x7FF15DBC, 0x00000100)
                Field (ASLD, AnyAcc, NoLock, Preserve)
                {
                    TOM,    32, 
                    R_ST,   1, 
                        ,   3, 
                    R_P0,   4, 
                    R_S0,   4, 
                    R_S1,   4, 
                    RSS0,   4, 
                    RSS1,   4, 
                    PSTN,   8, 
                    DUAL,   8, 
                    IVIM,   8, 
                    ACBR,   8, 
                    DCBR,   8, 
                    WC01,   8, 
                    SID0,   8, 
                    SID1,   8, 
                    SID2,   8, 
                    SID3,   8, 
                    SID4,   8, 
                    EAX0,   32, 
                    EBX0,   32, 
                    CCBR,   8, 
                    ACST,   8
                }
            }

            Method (_CRS, 0, NotSerialized)
            {
                Name (CBUF, ResourceTemplate ()
                {
                    WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
                        0x0000,             // Granularity
                        0x0000,             // Range Minimum
                        0x00FF,             // Range Maximum
                        0x0000,             // Translation Offset
                        0x0100,             // Length
                        ,, )
                    IO (Decode16,
                        0x0CF8,             // Range Minimum
                        0x0CF8,             // Range Maximum
                        0x01,               // Alignment
                        0x08,               // Length
                        )
                    WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
                        0x0000,             // Granularity
                        0x0000,             // Range Minimum
                        0x0CF7,             // Range Maximum
                        0x0000,             // Translation Offset
                        0x0CF8,             // Length
                        ,, , TypeStatic)
                    WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
                        0x0000,             // Granularity
                        0x0D00,             // Range Minimum
                        0xFFFF,             // Range Maximum
                        0x0000,             // Translation Offset
                        0xF300,             // Length
                        ,, , TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000A0000,         // Range Minimum
                        0x000BFFFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00020000,         // Length
                        ,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000C0000,         // Range Minimum
                        0x000C3FFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000C4000,         // Range Minimum
                        0x000C7FFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000C8000,         // Range Minimum
                        0x000CBFFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000CC000,         // Range Minimum
                        0x000CFFFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000D0000,         // Range Minimum
                        0x000D3FFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000D4000,         // Range Minimum
                        0x000D7FFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000D8000,         // Range Minimum
                        0x000DBFFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000DC000,         // Range Minimum
                        0x000DFFFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000E0000,         // Range Minimum
                        0x000E3FFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000E4000,         // Range Minimum
                        0x000E7FFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000E8000,         // Range Minimum
                        0x000EBFFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000EC000,         // Range Minimum
                        0x000EFFFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00004000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x000F0000,         // Range Minimum
                        0x000FFFFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0x00010000,         // Length
                        0x00,, , AddressRangeMemory, TypeStatic)
                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
                        0x00000000,         // Granularity
                        0x00100000,         // Range Minimum
                        0xFEBFFFFF,         // Range Maximum
                        0x00000000,         // Translation Offset
                        0xFFF00000,         // Length
                        ,, _Y01, AddressRangeMemory, TypeStatic)
                })
                CreateDWordField (CBUF, \_SB.PCI0._CRS._Y01._MIN, PMMN)
                CreateDWordField (CBUF, \_SB.PCI0._CRS._Y01._LEN, PMLN)
                Multiply (\_SB.TOM, 0x00100000, PMMN)
                Subtract (0xFEC00000, PMMN, PMLN)
                Return (CBUF)
            }

            Name (_PRT, Package (0x0D)
            {
                Package (0x04)
                {
                    0x000AFFFF, 
                    0x00, 
                    \_SB.PCI0.LSMB, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x000AFFFF, 
                    0x01, 
                    \_SB.PCI0.LPMU, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x000BFFFF, 
                    0x00, 
                    \_SB.PCI0.LUS0, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x000BFFFF, 
                    0x01, 
                    \_SB.PCI0.LUS2, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x0014FFFF, 
                    0x00, 
                    \_SB.PCI0.LMAC, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x0010FFFF, 
                    0x01, 
                    \_SB.PCI0.LAZA, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x000DFFFF, 
                    0x00, 
                    \_SB.PCI0.LPID, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x000EFFFF, 
                    0x00, 
                    \_SB.PCI0.LTID, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x000FFFFF, 
                    0x00, 
                    \_SB.PCI0.LSI1, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x0005FFFF, 
                    0x00, 
                    \_SB.PCI0.LK3E, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x0005FFFF, 
                    0x01, 
                    \_SB.PCI0.LK4E, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x0005FFFF, 
                    0x02, 
                    \_SB.PCI0.LK1E, 
                    0x00
                }, 

                Package (0x04)
                {
                    0x0005FFFF, 
                    0x03, 
                    \_SB.PCI0.LK2E, 
                    0x00
                }
            })
            Device (LPC0)
            {
                Name (_ADR, 0x000A0000)
                OperationRegion (P44, PCI_Config, 0x44, 0x04)
                Field (P44, AnyAcc, NoLock, Preserve)
                {
                    MTBA,   32
                }

                OperationRegion (P74, PCI_Config, 0x74, 0x04)
                Field (P74, AnyAcc, NoLock, Preserve)
                {
                    HPTF,   16
                }

                Device (MBRD)
                {
                    Name (_HID, EisaId ("PNP0C02"))
                    Name (_UID, 0x1F)
                    Name (RSRC, ResourceTemplate ()
                    {
                        Memory32Fixed (ReadWrite,
                            0xE0000000,         // Address Base
                            0x10000000,         // Address Length
                            )
                    })
                    Method (_CRS, 0, NotSerialized)
                    {
                        Return (RSRC)
                    }
                }

                Device (PMIO)
                {
                    Name (_HID, EisaId ("PNP0C02"))
                    Name (_UID, 0x03)
                    Method (_CRS, 0, NotSerialized)
                    {
                        Name (IODM, ResourceTemplate ()
                        {
                            IO (Decode16,
                                0x0000,             // Range Minimum
                                0x0000,             // Range Maximum
                                0x00,               // Alignment
                                0x00,               // Length
                                )
                        })
                        Name (IORT, ResourceTemplate ()
                        {
                            IO (Decode16,
                                0x0000,             // Range Minimum
                                0x0000,             // Range Maximum
                                0x01,               // Alignment
                                0x80,               // Length
                                _Y02)
                            IO (Decode16,
                                0x0000,             // Range Minimum
                                0x0000,             // Range Maximum
                                0x01,               // Alignment
                                0x80,               // Length
                                _Y03)
                            IO (Decode16,
                                0x0000,             // Range Minimum
                                0x0000,             // Range Maximum
                                0x01,               // Alignment
                                0x80,               // Length
                                _Y04)
                            IO (Decode16,
                                0x0000,             // Range Minimum
                                0x0000,             // Range Maximum
                                0x01,               // Alignment
                                0x80,               // Length
                                _Y05)
                            IO (Decode16,
                                0x0000,             // Range Minimum
                                0x0000,             // Range Maximum
                                0x01,               // Alignment
                                0x80,               // Length
                                _Y06)
                            IO (Decode16,
                                0x0000,             // Range Minimum
                                0x0000,             // Range Maximum
                                0x01,               // Alignment
                                0x80,               // Length
                                _Y07)
                            IO (Decode16,
                                0x0000,             // Range Minimum
                                0x0000,             // Range Maximum
                                0x01,               // Alignment
                                0x40,               // Length
                                _Y08)
                        })
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y02._MIN, I1MN)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y02._MAX, I1MX)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y03._MIN, I2MN)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y03._MAX, I2MX)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y04._MIN, I3MN)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y04._MAX, I3MX)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y05._MIN, I4MN)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y05._MAX, I4MX)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y06._MIN, I5MN)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y06._MAX, I5MX)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y07._MIN, I6MN)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y07._MAX, I6MX)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y08._MIN, I9MN)
                        CreateWordField (IORT, \_SB.PCI0.LPC0.PMIO._CRS._Y08._MAX, I9MX)
                        And (\_SB.PCI0.SMB0.PMBR, 0xFFFC, I1MN)
                        Store (I1MN, I1MX)
                        Add (I1MN, 0x80, Local0)
                        Store (Local0, I2MN)
                        Store (Local0, I2MX)
                        And (\_SB.PCI0.SMB0.NVSB, 0xFFFC, I3MN)
                        Store (I3MN, I3MX)
                        Add (I3MN, 0x80, Local0)
                        Store (Local0, I4MN)
                        Store (Local0, I4MX)
                        And (\_SB.PCI0.SMB0.ANLG, 0xFFFC, I5MN)
                        Store (I5MN, I5MX)
                        Add (I5MN, 0x80, Local0)
                        Store (Local0, I6MN)
                        Store (Local0, I6MX)
                        And (\_SB.PCI0.SMB0.SB7C, 0xFFFC, I9MN)
                        Store (I9MN, I9MX)
                        If (I1MN)
                        {
                            Store (IORT, Local0)
                        }
                        Else
                        {
                            Store (IODM, Local0)
                        }

                        Return (Local0)
                    }
                }
            }

            OperationRegion (SSMI, SystemIO, 0x142E, 0x02)
            Field (SSMI, ByteAcc, NoLock, Preserve)
            {
                SMIC,   8, 
                SMIS,   8
            }

            Mutex (PSMX, 0x00)
            Method (PHSR, 2, NotSerialized)
            {
                Acquire (PSMX, 0xFFFF)
                Store (Arg1, SMIS)
                Store (Arg0, SMIC)
                Store (SMIS, Local0)
                Release (PSMX)
                Return (Local0)
            }

            Device (SYS0)
            {
                Name (_HID, EisaId ("PNP0C02"))
                Name (_UID, 0x01)
                Name (_CRS, ResourceTemplate ()
                {
                    IO (Decode16,
                        0x0010,             // Range Minimum
                        0x0010,             // Range Maximum
                        0x01,               // Alignment
                        0x10,               // Length
                        )
                    IO (Decode16,
                        0x0022,             // Range Minimum
                        0x0022,             // Range Maximum
                        0x01,               // Alignment
                        0x1E,               // Length
                        )
                    IO (Decode16,
                        0x0044,             // Range Minimum
                        0x0044,             // Range Maximum
                        0x01,               // Alignment
                        0x1C,               // Length
                        )
                    IO (Decode16,
                        0x0068,             // Range Minimum
                        0x0068,             // Range Maximum
                        0x01,               // Alignment
                        0x08,               // Length
                        )
                    IO (Decode16,
                        0x0080,             // Range Minimum
                        0x0080,             // Range Maximum
                        0x00,               // Alignment
                        0x01,               // Length
                        )
                    IO (Decode16,
                        0x0091,             // Range Minimum
                        0x0091,             // Range Maximum
                        0x01,               // Alignment
                        0x03,               // Length
                        )
                    IO (Decode16,
                        0x0097,             // Range Minimum
                        0x0097,             // Range Maximum
                        0x01,               // Alignment
                        0x09,               // Length
                        )
                    IO (Decode16,
                        0x00A2,             // Range Minimum
                        0x00A2,             // Range Maximum
                        0x01,               // Alignment
                        0x1E,               // Length
                        )
                    IO (Decode16,
                        0x00E0,             // Range Minimum
                        0x00E0,             // Range Maximum
                        0x01,               // Alignment
                        0x10,               // Length
                        )
                    IO (Decode16,
                        0x0360,             // Range Minimum
                        0x0360,             // Range Maximum
                        0x01,               // Alignment
                        0x02,               // Length
                        )
                    IO (Decode16,
                        0x0380,             // Range Minimum
                        0x0380,             // Range Maximum
                        0x01,               // Alignment
                        0x04,               // Length
                        )
                    IO (Decode16,
                        0x04D0,             // Range Minimum
                        0x04D0,             // Range Maximum
                        0x01,               // Alignment
                        0x02,               // Length
                        )
                })
            }

            Device (PIC0)
            {
                Name (_HID, EisaId ("PNP0000"))
                Name (_CRS, ResourceTemplate ()
                {
                    IO (Decode16,
                        0x0020,             // Range Minimum
                        0x0020,             // Range Maximum
                        0x04,               // Alignment
                        0x02,               // Length
                        )
                    IO (Decode16,
                        0x00A0,             // Range Minimum
                        0x00A0,             // Range Maximum
                        0x04,               // Alignment
                        0x02,               // Length
                        )
                    IRQ (Edge, ActiveHigh, Exclusive, )
                        {2}
                })
            }

            Device (DMA0)
            {
                Name (_HID, EisaId ("PNP0200"))
                Name (_CRS, ResourceTemplate ()
                {
                    IO (Decode16,
                        0x0000,             // Range Minimum
                        0x0000,             // Range Maximum
                        0x01,               // Alignment
                        0x09,               // Length
                        )
                    IO (Decode16,
                        0x000A,             // Range Minimum
                        0x000A,             // Range Maximum
                        0x01,               // Alignment
                        0x06,               // Length
                        )
                    IO (Decode16,
                        0x0081,             // Range Minimum
                        0x0081,             // Range Maximum
                        0x01,               // Alignment
                        0x03,               // Length
                        )
                    IO (Decode16,
                        0x0087,             // Range Minimum
                        0x0087,             // Range Maximum
                        0x01,               // Alignment
                        0x01,               // Length
                        )
                    IO (Decode16,
                        0x0089,             // Range Minimum
                        0x0089,             // Range Maximum
                        0x01,               // Alignment
                        0x03,               // Length
                        )
                    IO (Decode16,
                        0x008F,             // Range Minimum
                        0x008F,             // Range Maximum
                        0x01,               // Alignment
                        0x01,               // Length
                        )
                    IO (Decode16,
                        0x00C0,             // Range Minimum
                        0x00C0,             // Range Maximum
                        0x01,               // Alignment
                        0x12,               // Length
                        )
                    IO (Decode16,
                        0x00D4,             // Range Minimum
                        0x00D4,             // Range Maximum
                        0x01,               // Alignment
                        0x0C,               // Length
                        )
                    DMA (Compatibility, BusMaster, Transfer8, )
                        {4}
                })
            }

            Device (SPK0)
            {
                Name (_HID, EisaId ("PNP0800"))
                Name (_CRS, ResourceTemplate ()
                {
                    IO (Decode16,
                        0x0061,             // Range Minimum
                        0x0061,             // Range Maximum
                        0x01,               // Alignment
                        0x01,               // Length
                        )
                })
            }

            Device (MTH0)
            {
                Name (_HID, EisaId ("PNP0C04"))
                Name (_CRS, ResourceTemplate ()
                {
                    IO (Decode16,
                        0x00F0,             // Range Minimum
                        0x00F0,             // Range Maximum
                        0x01,               // Alignment
                        0x02,               // Length
                        )
                    IRQ (Edge, ActiveHigh, Exclusive, )
                        {13}
                })
            }

            Device (PIT0)
            {
                Name (_HID, EisaId ("PNP0100"))
                Name (BUF0, ResourceTemplate ()
                {
                    IO (Decode16,
                        0x0040,             // Range Minimum
                        0x0040,             // Range Maximum
                        0x00,               // Alignment
                        0x04,               // Length
                        )
                })
                Name (BUF1, ResourceTemplate ()
                {
                    IO (Decode16,
                        0x0040,             // Range Minimum
                        0x0040,             // Range Maximum
                        0x00,               // Alignment
                        0x04,               // Length
                        )
                    IRQ (Edge, ActiveHigh, Exclusive, )
                        {0}
                })
                Method (_CRS, 0, NotSerialized)
                {
                    If (And (\_SB.PCI0.LPC0.HPTF, 0x04))
                    {
                        Return (BUF0)
                    }
                    Else
                    {
                        Return (BUF1)
                    }
                }
            }

            Device (RTC0)
            {
                Name (_HID, EisaId ("PNP0B00"))
                Name (BUF2, ResourceTemplate ()
                {
                    IO (Decode16,
                        0x0070,             // Range Minimum
                        0x0070,             // Range Maximum
                        0x00,               // Alignment
                        0x02,               // Length
                        )
                })
                Name (BUF3, ResourceTemplate ()
                {
                    IO (Decode16,
                        0x0070,             // Range Minimum
                        0x0070,             // Range Maximum
                        0x00,               // Alignment
                        0x02,               // Length
                        )
                    IRQ (Edge, ActiveHigh, Exclusive, )
                        {8}
                })
                Method (_CRS, 0, NotSerialized)
                {
                    If (And (\_SB.PCI0.LPC0.HPTF, 0x04))
                    {
                        Return (BUF2)
                    }
                    Else
                    {
                        Return (BUF3)
                    }
                }
            }

            Device (MMTM)
            {
                Name (_HID, EisaId ("PNP0103"))
                Name (BUF4, ResourceTemplate ()
                {
                    IRQ (Edge, ActiveHigh, Exclusive, )
                        {0}
                    IRQ (Edge, ActiveHigh, Exclusive, )
                        {8}
                    Memory32Fixed (ReadOnly,
                        0x00000000,         // Address Base
                        0x00000400,         // Address Length
                        _Y09)
                })
                Name (BUF5, ResourceTemplate ()
                {
                })
                Method (_STA, 0, NotSerialized)
                {
                    If (And (\_SB.PCI0.LPC0.HPTF, 0x04))
                    {
                        Return (0x0F)
                    }

                    Return (0x00)
                }

                CreateDWordField (BUF4, \_SB.PCI0.MMTM._Y09._BAS, MMBB)
                Method (_CRS, 0, NotSerialized)
                {
                    If (And (\_SB.PCI0.LPC0.HPTF, 0x04))
                    {
                        Store (\_SB.PCI0.LPC0.MTBA, MMBB)
                        Return (BUF4)
                    }
                    Else
                    {
                        Return (BUF5)
                    }
                }
            }

            Device (KBC0)
            {
                Name (_HID, EisaId ("PNP0303"))
                Name (_CRS, ResourceTemplate ()
                {
                    IO (Decode16,
                        0x0060,             // Range Minimum
                        0x0060,             // Range Maximum
                        0x01,               // Alignment
                        0x01,               // Length
                        )
                    IO (Decode16,
                        0x0064,             // Range Minimum
                        0x0064,             // Range Maximum
                        0x01,               // Alignment
                        0x01,               // Length
                        )
                    IRQ (Edge, ActiveHigh, Exclusive, )
                        {1}
                })
            }

            Device (MSE0)
            {
                Method (_HID, 0, NotSerialized)
                {
                    If (LEqual (HPBD, 0x01))
                    {
                        Return ("*SYN012A")
                    }
                    Else
                    {
                        Return ("*SYN0129")
                    }
                }

                Name (_CID, Package (0x03)
                {
                    0x00012E4F, 
                    0x02002E4F, 
                    0x130FD041
                })
                Name (_CRS, ResourceTemplate ()
                {
                    IRQ (Edge, ActiveHigh, Exclusive, )
                        {12}
                })
            }

            Device (EC0)
            {
                Name (_HID, EisaId ("PNP0C09"))
                Name (_UID, 0x01)
                Name (_GPE, 0x10)
                Method (_CRS, 0, NotSerialized)
                {
                    Name (BFFR, ResourceTemplate ()
                    {
                        IO (Decode16,
                            0x0062,             // Range Minimum
                            0x0062,             // Range Maximum
                            0x00,               // Alignment
                            0x01,               // Length
                            )
                        IO (Decode16,
                            0x0066,             // Range Minimum
                            0x0066,             // Range Maximum
                            0x00,               // Alignment
                            0x01,               // Length
                            )
                    })
                    Return (BFFR)
                }

                OperationRegion (ERAM, EmbeddedControl, 0x00, 0xFF)
                Field (ERAM, ByteAcc, Lock, Preserve)
                {
                    SMPR,   8, 
                    SMST,   8, 
                    SMAD,   8, 
                    SMCM,   8, 
                    SMD0,   256, 
                    BCNT,   8, 
                    SMAA,   8, 
                    BATD,   16, 
                            Offset (0x40), 
                    ACIN,   1, 
                            Offset (0x41), 
                        ,   4, 
                    FANC,   1, 
                    BLED,   1, 
                    AADA,   1, 
                            Offset (0x42), 
                        ,   7, 
                    Q8EO,   1, 
                        ,   4, 
                    BANK,   4, 
                            Offset (0x45), 
                    VFAN,   1, 
                    ISEN,   1, 
                    KBEP,   1, 
                    ASCN,   1, 
                    ALIN,   1, 
                            Offset (0x4E), 
                    LIDP,   1, 
                    DT1P,   1, 
                    ODDW,   1, 
                    PRPP,   1, 
                        ,   1, 
                        ,   1, 
                        ,   1, 
                            Offset (0x4F), 
                            Offset (0x52), 
                    LIDS,   1, 
                    DT1I,   1, 
                        ,   1, 
                    PREP,   1, 
                    RBAT,   1, 
                    CRTS,   1, 
                    ABTN,   1, 
                    DBAY,   1, 
                            Offset (0x58), 
                    RTMP,   8, 
                    ECT1,   8, 
                    ECT2,   8, 
                    RG5B,   8, 
                    FSPD,   16, 
                            Offset (0x61), 
                    QPDD,   8, 
                            Offset (0x72), 
                    BFCC,   16, 
                            Offset (0x82), 
                    MBST,   8, 
                    MCUR,   16, 
                    MBRM,   16, 
                    MBCV,   16, 
                            Offset (0xA0), 
                    QBHK,   8, 
                            Offset (0xA2), 
                    QBBB,   8, 
                            Offset (0xA4), 
                    MBTS,   1, 
                    MBTF,   1, 
                    BDES,   1, 
                    BTRK,   1, 
                    BARM,   1, 
                    BLOW,   1, 
                    BDIS,   1, 
                    BDED,   1, 
                        ,   3, 
                    NIMH,   1, 
                            Offset (0xAF), 
                    BATT,   8, 
                            Offset (0xB3), 
                    BACU,   8, 
                            Offset (0xC0), 
                    BRID,   8, 
                            Offset (0xE0), 
                    DTMC,   8, 
                            Offset (0xE2), 
                    BRIC,   8, 
                            Offset (0xE6), 
                    SFHK,   8, 
                    GQKS,   7
                }

                Field (ERAM, ByteAcc, NoLock, Preserve)
                {
                            Offset (0x04), 
                    SMW0,   16
                }

                Field (ERAM, ByteAcc, NoLock, Preserve)
                {
                            Offset (0x04), 
                    SMB0,   8
                }

                Field (ERAM, ByteAcc, NoLock, Preserve)
                {
                            Offset (0x04), 
                    FLD0,   64
                }

                Field (ERAM, ByteAcc, NoLock, Preserve)
                {
                            Offset (0x04), 
                    FLD1,   128
                }

                Field (ERAM, ByteAcc, NoLock, Preserve)
                {
                            Offset (0x04), 
                    FLD2,   192
                }

                Field (ERAM, ByteAcc, NoLock, Preserve)
                {
                            Offset (0x04), 
                    FLD3,   256
                }

                Name (BATO, 0x00)
                Name (BATN, 0x00)
                Name (BATF, 0xC0)
                Mutex (MUT0, 0x00)
                Mutex (MUT1, 0x00)
                Method (_REG, 2, NotSerialized)
                {
                    If (LAnd (LEqual (Arg0, 0x03), LEqual (Arg1, 0x01)))
                    {
                        Store (0x01, ECON)
                    }
                }

                Method (_Q20, 0, NotSerialized)
                {
                    Store (0x20, \DBUG)
                    If (LEqual (OSYS, 0x07D6))
                    {
                        Notify (\_SB.BAT0, 0x81)
                    }

                    Notify (\_SB.ACAD, 0x80)
                    Notify (\_SB.BAT0, 0x80)
                }

                Method (_Q21, 0, NotSerialized)
                {
                    Store (0x21, \DBUG)
                    Notify (\_SB.ACAD, 0x80)
                    Notify (\_SB.BAT0, 0x80)
                    RSBR ()
                }

                Method (_Q09, 0, NotSerialized)
                {
                    If (LEqual (DTCN, 0x02))
                    {
                        Store (0x00, DTCN)
                    }
                    Else
                    {
                        Add (DTCN, 0x01, DTCN)
                        Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                        Store (0x96, \_SB.PCI0.EC0.DTMC)
                        Release (\_SB.PCI0.EC0.MUT0)
                    }

                    Store (0x09, \DBUG)
                    Store (0x05, \_SB.WMID.Z00P)
                    Store (0x00, \_SB.WMID.Z00Q)
                    Notify (\_SB.WMID, 0x80)
                }

                Method (_Q0D, 0, NotSerialized)
                {
                    Store (0x0D, \DBUG)
                    If (VGAT)
                    {
                        VSWT ()
                    }
                    Else
                    {
                        VSWU ()
                    }
                }

                Method (_Q10, 0, NotSerialized)
                {
                    Store (0x10, \DBUG)
                    If (LEqual (OSYS, 0x07D6))
                    {
                        If (LEqual (VGAT, 0x01))
                        {
                            Notify (\_SB.PCI0.XVR0.VGA.LCD, 0x87)
                        }
                        Else
                        {
                            Notify (\_SB.PCI0.UVGA.LCD, 0x87)
                        }
                    }
                    Else
                    {
                        Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                        Store (0x8D, \_SB.PCI0.SMIC)
                        Store (\_SB.PCI0.SMIS, Local0)
                        Release (\_SB.PCI0.PSMX)
                    }
                }

                Method (_Q11, 0, NotSerialized)
                {
                    If (LEqual (OSYS, 0x07D6))
                    {
                        If (LEqual (VGAT, 0x01))
                        {
                            Notify (\_SB.PCI0.XVR0.VGA.LCD, 0x86)
                        }
                        Else
                        {
                            Notify (\_SB.PCI0.UVGA.LCD, 0x86)
                        }
                    }
                    Else
                    {
                        Store (0x11, \DBUG)
                        Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                        Store (0x8C, \_SB.PCI0.SMIC)
                        Store (\_SB.PCI0.SMIS, Local0)
                        Release (\_SB.PCI0.PSMX)
                    }
                }

                Method (_Q15, 0, NotSerialized)
                {
                    Store (0x15, \DBUG)
                    Store ("!!! Wireless Button pressed !!!", Debug)
                    Acquire (M723, 0xFFFF)
                    Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                    If (\_SB.PCI0.EC0.DT1I)
                    {
                        Store (0x00, BTLS)
                    }
                    Else
                    {
                        Store (0x01, BTLS)
                    }

                    Release (\_SB.PCI0.EC0.MUT0)
                    If (LOr (BTSU, WLSU))
                    {
                        If (BTLS)
                        {
                            Store (0x00, BTLS)
                            Store (0x00, GP25)
                            Store (0x04, GP24)
                            Store (0x00, GP26)
                            Store (0x04, GP23)
                        }
                        Else
                        {
                            Store (0x01, BTLS)
                            If (WLSU)
                            {
                                If (WIRE)
                                {
                                    If (WWLS)
                                    {
                                        Store (0x01, GP26)
                                        Store (0x05, GP23)
                                    }
                                }
                                Else
                                {
                                    Store (0x01, GP26)
                                    Store (0x05, GP23)
                                }
                            }

                            If (BTSU)
                            {
                                If (WIRE)
                                {
                                    If (BWLS)
                                    {
                                        Store (0x01, GP25)
                                        Store (0x05, GP24)
                                    }
                                }
                                Else
                                {
                                    Store (0x01, GP25)
                                    Store (0x05, GP24)
                                }
                            }
                        }
                    }
                    Else
                    {
                        Store (0x00, BTLS)
                        Store (0x00, GP25)
                        Store (0x04, GP24)
                        Store (0x00, GP26)
                        Store (0x04, GP23)
                    }

                    Release (M723)
                    Store (0x05, \_SB.WMID.Z00P)
                    Store (0x00, \_SB.WMID.Z00Q)
                    Notify (\_SB.WMID, 0x80)
                }

                Method (_Q16, 0, NotSerialized)
                {
                    Store (QBBB, Local0)
                    If (LEqual (Local0, 0x00))
                    {
                        Store (QPDD, Local0)
                        ShiftRight (Local0, 0x02, Local0)
                        Add (Local0, 0x02, Local0)
                        If (LEqual (Local0, 0x01))
                        {
                            Notify (\_SB.QBTN, 0x80)
                        }

                        If (LEqual (Local0, 0x02))
                        {
                            Notify (\_SB.DBTN, 0x80)
                        }
                    }
                    Else
                    {
                        If (LEqual (OSYS, 0x07D6))
                        {
                            If (LEqual (Local0, 0x04))
                            {
                                Store (0x04, \_SB.WMID.Z00P)
                                Store (0x00, \_SB.WMID.Z00Q)
                                Notify (\_SB.WMID, 0x80)
                                Return (0x00)
                            }

                            If (LEqual (Local0, 0x05))
                            {
                                Store (0x04, \_SB.WMID.Z00P)
                                Store (0x00, \_SB.WMID.Z00Q)
                                Notify (\_SB.WMID, 0x80)
                                Return (0x00)
                            }

                            If (LEqual (Local0, 0x07))
                            {
                                Store (0x04, \_SB.WMID.Z00P)
                                Store (0x00, \_SB.WMID.Z00Q)
                                Notify (\_SB.WMID, 0x80)
                                Return (0x00)
                            }

                            If (LEqual (Local0, 0x08))
                            {
                                Store (0x04, \_SB.WMID.Z00P)
                                Store (0x00, \_SB.WMID.Z00Q)
                                Notify (\_SB.WMID, 0x80)
                                Return (0x00)
                            }

                            If (LEqual (Local0, 0x10))
                            {
                                Store (0x04, \_SB.WMID.Z00P)
                                Store (0x00, \_SB.WMID.Z00Q)
                                Notify (\_SB.WMID, 0x80)
                                Return (0x00)
                            }

                            If (LEqual (Local0, 0x03))
                            {
                                Store (0x04, \_SB.WMID.Z00P)
                                Store (0x00, \_SB.WMID.Z00Q)
                                Notify (\_SB.WMID, 0x80)
                                Return (0x00)
                            }
                        }

                        Store (0x04, \_SB.WMID.Z00P)
                        Store (0x00, \_SB.WMID.Z00Q)
                        Notify (\_SB.WMID, 0x80)
                    }
                }

                Method (_Q80, 0, NotSerialized)
                {
                    Store ("_Q80 : Temperature Up", Debug)
                    Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                    Store (\_SB.PCI0.EC0.RTMP, Local0)
                    Release (\_SB.PCI0.EC0.MUT0)
                    If (LGreater (Local0, 0x57))
                    {
                        Store (\_SB.PSTN, DBUG)
                        Store (\_SB.PSTN, \_PR.CPU0._PPC)
                        Notify (\_PR.CPU0, 0x80)
                    }
                    Else
                    {
                        If (LLess (Local0, 0x4B))
                        {
                            If (LEqual (Q8EO, 0x00))
                            {
                                Store (0x00, \_PR.CPU0._PPC)
                                Notify (\_PR.CPU0, 0x80)
                            }
                        }
                    }
                }

                Method (_Q81, 0, NotSerialized)
                {
                    Store ("_Q81 : Temperature Down", Debug)
                }

                Name (ARG9, 0x00)
                Name (ARG8, 0x00)
                Method (_Q8E, 0, NotSerialized)
                {
                    If (LLess (\_PR.CPU0._PPC, \_SB.PSTN))
                    {
                        Add (\_PR.CPU0._PPC, 0x01, \_PR.CPU0._PPC)
                        If (LGreater (\_PR.CPU0._PPC, \_SB.PSTN))
                        {
                            Store (\_SB.PSTN, \_PR.CPU0._PPC)
                            Notify (\_PR.CPU0, 0x80)
                        }
                        Else
                        {
                            If (LEqual (BACU, 0x01))
                            {
                                If (LGreaterEqual (BATT, 0x3A))
                                {
                                    Subtract (BATT, 0x3A, ARG9)
                                    Divide (ARG9, 0x02, ARG8, ARG9)
                                    Add (ARG9, 0x01, ARG9)
                                    If (LLessEqual (ARG9, \_SB.PSTN))
                                    {
                                        Store (ARG9, \_PR.CPU0._PPC)
                                    }
                                    Else
                                    {
                                        Store (\_SB.PSTN, \_PR.CPU0._PPC)
                                    }
                                }
                            }

                            Notify (\_PR.CPU0, 0x80)
                        }
                    }
                }

                Method (_Q8F, 0, NotSerialized)
                {
                    If (LGreater (\_PR.CPU0._PPC, 0x00))
                    {
                        Subtract (\_PR.CPU0._PPC, 0x01, \_PR.CPU0._PPC)
                        Notify (\_PR.CPU0, 0x80)
                        If (LEqual (\_PR.CPU0._PPC, 0x00))
                        {
                            Store (0x00, Q8EO)
                        }
                        Else
                        {
                            Store (0x01, Q8EO)
                        }
                    }
                    Else
                    {
                        Store (0x00, Q8EO)
                    }
                }

                Method (_Q8A, 0, NotSerialized)
                {
                    If (LIDP)
                    {
                        Store ("_Q8A : Lid Event", Debug)
                        Store (0x00, LIDP)
                    }

                    Notify (\_SB.LID, 0x80)
                }

                Method (VSWT, 0, NotSerialized)
                {
                    Store ("Hot-Keys: ----- _Q0C", Debug)
                    If (LEqual (\_SB.PCI0.XVR0.VGA.SWIT, 0x00))
                    {
                        Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                        Store (0x88, \_SB.PCI0.SMIC)
                        Store (\_SB.PCI0.SMIS, Local0)
                        Release (\_SB.PCI0.PSMX)
                        Store (Local0, CADL)
                        If (LEqual (Local0, 0x10)) {}
                        Else
                        {
                            Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                            Store (0x87, \_SB.PCI0.SMIC)
                            Store (\_SB.PCI0.SMIS, Local1)
                            Release (\_SB.PCI0.PSMX)
                            Store (Local1, PSTE)
                            If (LEqual (Local1, 0x09))
                            {
                                Store (Zero, Local1)
                            }

                            If (LEqual (Local1, 0x05))
                            {
                                Store (0x08, Local1)
                            }

                            Store (Local1, \_SB.PCI0.XVR0.VGA.TOGF)
                            Increment (\_SB.PCI0.XVR0.VGA.TOGF)
                            While (LNotEqual (And (Local0, \_SB.PCI0.XVR0.VGA.TOGF), \_SB.PCI0.XVR0.VGA.TOGF))
                            {
                                Increment (\_SB.PCI0.XVR0.VGA.TOGF)
                                If (LGreater (\_SB.PCI0.XVR0.VGA.TOGF, 0x09))
                                {
                                    Store (One, \_SB.PCI0.XVR0.VGA.TOGF)
                                }
                            }

                            If (LEqual (CADL, 0x0F))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x08, NSTE)
                                }

                                If (LEqual (CSTE, 0x02))
                                {
                                    Store (0x08, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x04, NSTE)
                                }

                                If (LEqual (CSTE, 0x08))
                                {
                                    Store (0x04, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x03, NSTE)
                                }

                                If (LEqual (CSTE, 0x04))
                                {
                                    Store (0x03, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x09, NSTE)
                                }

                                If (LEqual (CSTE, 0x03))
                                {
                                    Store (0x09, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x05, NSTE)
                                }

                                If (LEqual (CSTE, 0x09))
                                {
                                    Store (0x05, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x05))
                                {
                                    Store (0x01, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x02, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x0D))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x08, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x04, NSTE)
                                }

                                If (LEqual (CSTE, 0x08))
                                {
                                    Store (0x04, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x09, NSTE)
                                }

                                If (LEqual (CSTE, 0x04))
                                {
                                    Store (0x09, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x05, NSTE)
                                }

                                If (LEqual (CSTE, 0x09))
                                {
                                    Store (0x05, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x05))
                                {
                                    Store (0x01, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x08, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x0B))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x08, NSTE)
                                }

                                If (LEqual (CSTE, 0x02))
                                {
                                    Store (0x08, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x03, NSTE)
                                }

                                If (LEqual (CSTE, 0x08))
                                {
                                    Store (0x03, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x09, NSTE)
                                }

                                If (LEqual (CSTE, 0x03))
                                {
                                    Store (0x09, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x09))
                                {
                                    Store (0x02, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x09))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x09, NSTE)
                                }

                                If (LEqual (CSTE, 0x08))
                                {
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x09))
                                {
                                    Store (0x08, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x07))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x02, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x04, NSTE)
                                }

                                If (LEqual (CSTE, 0x02))
                                {
                                    Store (0x04, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x03, NSTE)
                                }

                                If (LEqual (CSTE, 0x04))
                                {
                                    Store (0x03, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x05, NSTE)
                                }

                                If (LEqual (CSTE, 0x03))
                                {
                                    Store (0x05, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x05))
                                {
                                    Store (0x01, \_SB.PCI0.XVR0.VGA.TOGF)
                                    Store (0x02, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x03))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x03, NSTE)
                                }

                                If (LEqual (CSTE, 0x02))
                                {
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x03))
                                {
                                    Store (0x02, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x05))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x05, NSTE)
                                }

                                If (LEqual (CSTE, 0x04))
                                {
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x05))
                                {
                                    Store (0x04, NSTE)
                                }
                            }

                            Sleep (0x03E8)
                            Store (\_SB.PCI0.XVR0.VGA.TOGF, Local0)
                            Store (Local0, CSTE)
                            If (LEqual (Local0, 0x01))
                            {
                                Store ("LCD", Debug)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x02))
                            {
                                Store ("CRT", Debug)
                                Store (One, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x03))
                            {
                                Store ("Both", Debug)
                                Store (One, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x04))
                            {
                                Store ("TV", Debug)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (One, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x05))
                            {
                                Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (One, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x08))
                            {
                                Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (One, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            If (LEqual (Local0, 0x09))
                            {
                                Store (Zero, \_SB.PCI0.XVR0.VGA.CRTA)
                                Store (One, \_SB.PCI0.XVR0.VGA.LCDA)
                                Store (Zero, \_SB.PCI0.XVR0.VGA.TVAF)
                                Store (One, \_SB.PCI0.XVR0.VGA.HDTV)
                            }

                            Notify (\_SB.PCI0.XVR0.VGA, 0x80)
                        }
                    }
                    Else
                    {
                    }
                }

                Method (VSWU, 0, NotSerialized)
                {
                    Store ("Hot-Keys: ----- _Q0C", Debug)
                    If (LEqual (\_SB.PCI0.UVGA.SWIT, 0x00))
                    {
                        Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                        Store (0x88, \_SB.PCI0.SMIC)
                        Store (\_SB.PCI0.SMIS, Local0)
                        Release (\_SB.PCI0.PSMX)
                        Store (Local0, CADL)
                        If (LEqual (Local0, 0x10)) {}
                        Else
                        {
                            Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                            Store (0x87, \_SB.PCI0.SMIC)
                            Store (\_SB.PCI0.SMIS, Local1)
                            Release (\_SB.PCI0.PSMX)
                            Store (Local1, PSTE)
                            If (LEqual (Local1, 0x09))
                            {
                                Store (Zero, Local1)
                            }

                            If (LEqual (Local1, 0x05))
                            {
                                Store (0x08, Local1)
                            }

                            Store (Local1, \_SB.PCI0.UVGA.TOGF)
                            Increment (\_SB.PCI0.UVGA.TOGF)
                            While (LNotEqual (And (Local0, \_SB.PCI0.UVGA.TOGF), \_SB.PCI0.UVGA.TOGF))
                            {
                                Increment (\_SB.PCI0.UVGA.TOGF)
                                If (LGreater (\_SB.PCI0.UVGA.TOGF, 0x09))
                                {
                                    Store (One, \_SB.PCI0.UVGA.TOGF)
                                }
                            }

                            If (LEqual (CADL, 0x0F))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x08, NSTE)
                                }

                                If (LEqual (CSTE, 0x02))
                                {
                                    Store (0x08, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x04, NSTE)
                                }

                                If (LEqual (CSTE, 0x08))
                                {
                                    Store (0x04, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x03, NSTE)
                                }

                                If (LEqual (CSTE, 0x04))
                                {
                                    Store (0x03, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x09, NSTE)
                                }

                                If (LEqual (CSTE, 0x03))
                                {
                                    Store (0x09, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x05, NSTE)
                                }

                                If (LEqual (CSTE, 0x09))
                                {
                                    Store (0x05, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x05))
                                {
                                    Store (0x01, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x02, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x0D))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x08, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x04, NSTE)
                                }

                                If (LEqual (CSTE, 0x08))
                                {
                                    Store (0x04, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x09, NSTE)
                                }

                                If (LEqual (CSTE, 0x04))
                                {
                                    Store (0x09, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x05, NSTE)
                                }

                                If (LEqual (CSTE, 0x09))
                                {
                                    Store (0x05, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x05))
                                {
                                    Store (0x01, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x08, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x0B))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x08, NSTE)
                                }

                                If (LEqual (CSTE, 0x02))
                                {
                                    Store (0x08, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x03, NSTE)
                                }

                                If (LEqual (CSTE, 0x08))
                                {
                                    Store (0x03, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x09, NSTE)
                                }

                                If (LEqual (CSTE, 0x03))
                                {
                                    Store (0x09, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x09))
                                {
                                    Store (0x02, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x09))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x09, NSTE)
                                }

                                If (LEqual (CSTE, 0x08))
                                {
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x09))
                                {
                                    Store (0x08, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x07))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x02, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x04, NSTE)
                                }

                                If (LEqual (CSTE, 0x02))
                                {
                                    Store (0x04, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x03, NSTE)
                                }

                                If (LEqual (CSTE, 0x04))
                                {
                                    Store (0x03, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x05, NSTE)
                                }

                                If (LEqual (CSTE, 0x03))
                                {
                                    Store (0x05, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x05))
                                {
                                    Store (0x01, \_SB.PCI0.UVGA.TOGF)
                                    Store (0x02, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x03))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x03, NSTE)
                                }

                                If (LEqual (CSTE, 0x02))
                                {
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x03))
                                {
                                    Store (0x02, NSTE)
                                }
                            }

                            If (LEqual (CADL, 0x05))
                            {
                                If (LEqual (CSTE, 0x01))
                                {
                                    Store (0x05, NSTE)
                                }

                                If (LEqual (CSTE, 0x04))
                                {
                                    Store (0x01, NSTE)
                                }

                                If (LEqual (CSTE, 0x05))
                                {
                                    Store (0x04, NSTE)
                                }
                            }

                            Sleep (0x03E8)
                            Store (\_SB.PCI0.UVGA.TOGF, Local0)
                            Store (Local0, CSTE)
                            If (LEqual (Local0, 0x01))
                            {
                                Store ("LCD", Debug)
                                Store (Zero, \_SB.PCI0.UVGA.CRTA)
                                Store (One, \_SB.PCI0.UVGA.LCDA)
                                Store (Zero, \_SB.PCI0.UVGA.TVAF)
                                Store (Zero, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x02))
                            {
                                Store ("CRT", Debug)
                                Store (One, \_SB.PCI0.UVGA.CRTA)
                                Store (Zero, \_SB.PCI0.UVGA.LCDA)
                                Store (Zero, \_SB.PCI0.UVGA.TVAF)
                                Store (Zero, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x03))
                            {
                                Store ("Both", Debug)
                                Store (One, \_SB.PCI0.UVGA.CRTA)
                                Store (One, \_SB.PCI0.UVGA.LCDA)
                                Store (Zero, \_SB.PCI0.UVGA.TVAF)
                                Store (Zero, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x04))
                            {
                                Store ("TV", Debug)
                                Store (Zero, \_SB.PCI0.UVGA.CRTA)
                                Store (Zero, \_SB.PCI0.UVGA.LCDA)
                                Store (One, \_SB.PCI0.UVGA.TVAF)
                                Store (Zero, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x05))
                            {
                                Store (Zero, \_SB.PCI0.UVGA.CRTA)
                                Store (One, \_SB.PCI0.UVGA.LCDA)
                                Store (One, \_SB.PCI0.UVGA.TVAF)
                                Store (Zero, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x08))
                            {
                                Store (Zero, \_SB.PCI0.UVGA.CRTA)
                                Store (Zero, \_SB.PCI0.UVGA.LCDA)
                                Store (Zero, \_SB.PCI0.UVGA.TVAF)
                                Store (One, \_SB.PCI0.UVGA.HDTV)
                            }

                            If (LEqual (Local0, 0x09))
                            {
                                Store (Zero, \_SB.PCI0.UVGA.CRTA)
                                Store (One, \_SB.PCI0.UVGA.LCDA)
                                Store (Zero, \_SB.PCI0.UVGA.TVAF)
                                Store (One, \_SB.PCI0.UVGA.HDTV)
                            }

                            Notify (\_SB.PCI0.UVGA, 0x80)
                        }
                    }
                    Else
                    {
                    }
                }

                Method (RSBR, 0, NotSerialized)
                {
                    If (LEqual (OSYS, 0x07D6))
                    {
                        Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                        Store (Zero, \_SB.PCI0.SMIS)
                        Store (0x8B, \_SB.PCI0.SMIC)
                        Store (\_SB.PCI0.SMIS, Local0)
                        Release (\_SB.PCI0.PSMX)
                    }
                    Else
                    {
                        Acquire (\_SB.PCI0.PSMX, 0xFFFF)
                        Store (One, \_SB.PCI0.SMIS)
                        Store (0x8B, \_SB.PCI0.SMIC)
                        Store (\_SB.PCI0.SMIS, Local0)
                        Release (\_SB.PCI0.PSMX)
                    }
                }

                Method (PRTH, 0, NotSerialized)
                {
                    Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                    If (\_SB.PCI0.EC0.ACIN)
                    {
                        Acquire (M723, 0xFFFF)
                        Store (ACBN, BRNS)
                        Release (M723)
                    }
                    Else
                    {
                        Acquire (M723, 0xFFFF)
                        Store (BABN, BRNS)
                        Release (M723)
                    }

                    Release (\_SB.PCI0.EC0.MUT0)
                }

                Method (SMRD, 4, NotSerialized)
                {
                    If (LNot (ECON))
                    {
                        Return (0xFF)
                    }

                    If (LNotEqual (Arg0, 0x07))
                    {
                        If (LNotEqual (Arg0, 0x09))
                        {
                            If (LNotEqual (Arg0, 0x0B))
                            {
                                Return (0x19)
                            }
                        }
                    }

                    Acquire (MUT0, 0xFFFF)
                    Store (0x04, Local0)
                    While (LGreater (Local0, 0x01))
                    {
                        And (SMST, 0x40, SMST)
                        Store (Arg2, SMCM)
                        Store (Arg1, SMAD)
                        Store (Arg0, SMPR)
                        Store (0x00, Local3)
                        While (LNot (And (SMST, 0xBF, Local1)))
                        {
                            Sleep (0x02)
                            Increment (Local3)
                            If (LEqual (Local3, 0x32))
                            {
                                And (SMST, 0x40, SMST)
                                Store (Arg2, SMCM)
                                Store (Arg1, SMAD)
                                Store (Arg0, SMPR)
                                Store (0x00, Local3)
                            }
                        }

                        If (LEqual (Local1, 0x80))
                        {
                            Store (0x00, Local0)
                        }
                        Else
                        {
                            Decrement (Local0)
                        }
                    }

                    If (Local0)
                    {
                        Store (And (Local1, 0x1F), Local0)
                    }
                    Else
                    {
                        If (LEqual (Arg0, 0x07))
                        {
                            Store (SMB0, Arg3)
                        }

                        If (LEqual (Arg0, 0x09))
                        {
                            Store (SMW0, Arg3)
                        }

                        If (LEqual (Arg0, 0x0B))
                        {
                            Store (BCNT, Local3)
                            ShiftRight (0x0100, 0x03, Local2)
                            If (LGreater (Local3, Local2))
                            {
                                Store (Local2, Local3)
                            }

                            If (LLess (Local3, 0x09))
                            {
                                Store (FLD0, Local2)
                            }
                            Else
                            {
                                If (LLess (Local3, 0x11))
                                {
                                    Store (FLD1, Local2)
                                }
                                Else
                                {
                                    If (LLess (Local3, 0x19))
                                    {
                                        Store (FLD2, Local2)
                                    }
                                    Else
                                    {
                                        Store (FLD3, Local2)
                                    }
                                }
                            }

                            Increment (Local3)
                            Store (Buffer (Local3) {}, Local4)
                            Decrement (Local3)
                            Store (Zero, Local5)
                            While (LGreater (Local3, Local5))
                            {
                                GBFE (Local2, Local5, RefOf (Local6))
                                PBFE (Local4, Local5, Local6)
                                Increment (Local5)
                            }

                            PBFE (Local4, Local5, 0x00)
                            Store (Local4, Arg3)
                        }
                    }

                    Release (MUT0)
                    Return (Local0)
                }

                Method (Z00R, 0, Serialized)
                {
                    If (ECON)
                    {
                        Store (SFHK, Local0)
                    }

                    Return (Local0)
                }

                Method (Z00S, 1, Serialized)
                {
                    If (ECON)
                    {
                        Store (Arg0, SFHK)
                    }
                }
            }

            Device (SMB0)
            {
                Name (_ADR, 0x000A0001)
                OperationRegion (SMCF, PCI_Config, 0x48, 0x04)
                Field (SMCF, AnyAcc, NoLock, Preserve)
                {
                    SB48,   4
                }

                OperationRegion (SBA0, PCI_Config, 0x20, 0x04)
                Field (SBA0, AnyAcc, NoLock, Preserve)
                {
                    SB20,   16
                }

                OperationRegion (SBA1, PCI_Config, 0x24, 0x04)
                Field (SBA1, AnyAcc, NoLock, Preserve)
                {
                    SB24,   16
                }

                OperationRegion (SBA2, PCI_Config, 0x7C, 0x04)
                Field (SBA2, AnyAcc, NoLock, Preserve)
                {
                    SB7C,   16
                }

                OperationRegion (P60, PCI_Config, 0x60, 0x02)
                Field (P60, AnyAcc, NoLock, Preserve)
                {
                    PMBR,   16
                }

                OperationRegion (P64, PCI_Config, 0x64, 0x02)
                Field (P64, AnyAcc, NoLock, Preserve)
                {
                    NVSB,   16
                }

                OperationRegion (P68, PCI_Config, 0x68, 0x02)
                Field (P68, AnyAcc, NoLock, Preserve)
                {
                    ANLG,   16
                }
            }

            Device (USB0)
            {
                Name (_ADR, 0x000B0000)
                Method (_S1D, 0, NotSerialized)
                {
                    Return (0x01)
                }

                Method (_S3D, 0, NotSerialized)
                {
                    Return (0x02)
                }

                Device (RH00)
                {
                    Name (_ADR, 0x00)
                    Device (PRT0)
                    {
                        Name (_ADR, 0x00)
                    }

                    Device (PRT1)
                    {
                        Name (_ADR, 0x01)
                    }

                    Device (PRT2)
                    {
                        Name (_ADR, 0x02)
                    }

                    Device (PRT3)
                    {
                        Name (_ADR, 0x03)
                    }

                    Device (PRT4)
                    {
                        Name (_ADR, 0x04)
                    }

                    Device (PRT5)
                    {
                        Name (_ADR, 0x05)
                        Name (_EJD, "_SB.PCI0.XVR2.X2S0")
                    }

                    Device (PRT6)
                    {
                        Name (_ADR, 0x06)
                    }

                    Device (PRT7)
                    {
                        Name (_ADR, 0x07)
                    }
                }
            }

            Device (USB2)
            {
                Name (_ADR, 0x000B0001)
            }

            Device (MAC0)
            {
                Name (_ADR, 0x00140000)
                Name (_PRW, Package (0x02)
                {
                    0x0B, 
                    0x05
                })
            }

            Device (AZA0)
            {
                Name (_ADR, 0x00100001)
            }

            Device (P2P0)
            {
                Name (_ADR, 0x00100000)
                Name (_UID, 0x02)
                OperationRegion (A080, PCI_Config, 0x19, 0x01)
                Field (A080, ByteAcc, NoLock, Preserve)
                {
                    SECB,   8
                }

                Method (_BBN, 0, NotSerialized)
                {
                    Return (SECB)
                }

                Method (_STA, 0, NotSerialized)
                {
                    Return (0x0F)
                }

                Name (_PRT, Package (0x02)
                {
                    Package (0x04)
                    {
                        0x0005FFFF, 
                        0x00, 
                        \_SB.PCI0.LNK1, 
                        0x00
                    }, 

                    Package (0x04)
                    {
                        0x0005FFFF, 
                        0x01, 
                        \_SB.PCI0.LNK2, 
                        0x00
                    }
                })
            }

            Name (NATA, Package (0x01)
            {
                0x000D0000
            })
            Scope (\_SB.PCI0)
            {
                Device (NVRB)
                {
                    Name (_HID, "NVRAIDBUS")
                    Name (FNVR, 0xFF)
                    Method (_DIS, 0, NotSerialized)
                    {
                        Store (0x00, FNVR)
                    }

                    Method (_STA, 0, NotSerialized)
                    {
                        If (LEqual (\_SB.R_ST, 0x01))
                        {
                            If (LEqual (FNVR, 0xFF))
                            {
                                Return (0x0F)
                            }
                            Else
                            {
                                Return (0x0D)
                            }
                        }
                        Else
                        {
                            Return (0x00)
                        }
                    }

                    Name (_CRS, ResourceTemplate ()
                    {
                        IO (Decode16,
                            0x04D2,             // Range Minimum
                            0x04D2,             // Range Maximum
                            0x01,               // Alignment
                            0x01,               // Length
                            )
                    })
                }
            }

            Device (IDE0)
            {
                Name (SID4, 0x00)
                Name (SID5, 0x00)
                Name (SFLG, 0x00)
                Name (SID0, 0x00)
                Name (SID1, 0x00)
                Name (SID2, 0x00)
                Name (SID3, 0x00)
                Name (_ADR, 0x000D0000)
                OperationRegion (A090, PCI_Config, 0x50, 0x18)
                Field (A090, DWordAcc, NoLock, Preserve)
                {
                    ID20,   16, 
                            Offset (0x08), 
                    IDTS,   16, 
                    IDTP,   16, 
                    ID22,   32, 
                    UMSS,   16, 
                    UMSP,   16
                }

                Name (IDEP, Buffer (0x14) {})
                Name (IDES, Buffer (0x14) {})
                Method (GTM, 1, NotSerialized)
                {
                    If (LEqual (Arg0, 0x00))
                    {
                        Store (IDTP, Local0)
                        Store (UMSP, Local1)
                        Store (IDEP, Local2)
                    }
                    Else
                    {
                        Store (IDTS, Local0)
                        Store (UMSS, Local1)
                        Store (IDES, Local2)
                    }

                    CreateDWordField (Local2, 0x00, PIO0)
                    CreateDWordField (Local2, 0x04, DMA0)
                    CreateDWordField (Local2, 0x08, PIO1)
                    CreateDWordField (Local2, 0x0C, DMA1)
                    CreateDWordField (Local2, 0x10, FLAG)
                    Store (0x10, FLAG)
                    And (Local0, 0x0F00, Local3)
                    And (Local0, 0xF000, Local4)
                    ShiftRight (Local3, 0x08, Local3)
                    ShiftRight (Local4, 0x0C, Local4)
                    Add (Local3, Local4, Local3)
                    Multiply (Add (Local3, 0x02), 0x1E, PIO0)
                    If (LLessEqual (PIO0, 0xB4))
                    {
                        Or (FLAG, 0x02, FLAG)
                    }

                    If (And (Local1, 0x4000))
                    {
                        Or (FLAG, 0x01, FLAG)
                        And (Local1, 0x0700, Local3)
                        ShiftRight (Local3, 0x08, Local3)
                        Store (U2T (Local3), DMA0)
                    }
                    Else
                    {
                        Store (PIO0, DMA0)
                    }

                    And (Local0, 0x0F, Local3)
                    And (Local0, 0xF0, Local4)
                    ShiftRight (Local4, 0x04, Local4)
                    Add (Local3, Local4, Local3)
                    Multiply (Add (Local3, 0x02), 0x1E, PIO1)
                    If (LLessEqual (PIO1, 0xB4))
                    {
                        Or (FLAG, 0x08, FLAG)
                    }

                    If (And (Local1, 0x40))
                    {
                        Or (FLAG, 0x04, FLAG)
                        And (Local1, 0x07, Local3)
                        Store (U2T (Local3), DMA1)
                    }
                    Else
                    {
                        Store (PIO1, DMA1)
                    }

                    If (LEqual (Arg0, 0x00))
                    {
                        Store (Local2, IDEP)
                        Return (IDEP)
                    }
                    Else
                    {
                        Store (Local2, IDES)
                        Return (IDES)
                    }
                }

                Method (U2T, 1, NotSerialized)
                {
                    If (LEqual (Arg0, 0x00))
                    {
                        Return (0x3C)
                    }

                    If (LEqual (Arg0, 0x01))
                    {
                        Return (0x5A)
                    }

                    If (LEqual (Arg0, 0x02))
                    {
                        Return (0x78)
                    }

                    If (LEqual (Arg0, 0x03))
                    {
                        Return (0x96)
                    }

                    If (LEqual (Arg0, 0x04))
                    {
                        Return (0x2D)
                    }

                    If (LEqual (Arg0, 0x05))
                    {
                        Return (0x1E)
                    }

                    If (LEqual (Arg0, 0x06))
                    {
                        Return (0x14)
                    }

                    Return (0x0F)
                }

                Method (T2U, 1, NotSerialized)
                {
                    If (LGreater (Arg0, 0x78))
                    {
                        Return (0x03)
                    }

                    If (LGreater (Arg0, 0x5A))
                    {
                        Return (0x02)
                    }

                    If (LGreater (Arg0, 0x3C))
                    {
                        Return (0x01)
                    }

                    If (LGreater (Arg0, 0x2D))
                    {
                        Return (0x00)
                    }

                    If (LGreater (Arg0, 0x1E))
                    {
                        Return (0x04)
                    }

                    If (LGreater (Arg0, 0x14))
                    {
                        Return (0x05)
                    }

                    If (LGreater (Arg0, 0x0F))
                    {
                        Return (0x06)
                    }

                    Return (0x07)
                }

                Method (T2D, 1, NotSerialized)
                {
                    If (LGreater (Arg0, 0x01E0))
                    {
                        Return (0xA8)
                    }

                    If (LGreater (Arg0, 0x0186))
                    {
                        Return (0x77)
                    }

                    If (LGreater (Arg0, 0xF0))
                    {
                        Return (0x47)
                    }

                    If (LGreater (Arg0, 0xB4))
                    {
                        Return (0x33)
                    }

                    If (LGreater (Arg0, 0x96))
                    {
                        Return (0x22)
                    }

                    If (LGreater (Arg0, 0x78))
                    {
                        Return (0x21)
                    }

                    Return (0x20)
                }

                Method (STM, 4, NotSerialized)
                {
                    If (SX)
                    {
                        Store (SID0, ID20)
                        Store (SID1, IDTS)
                        Store (SID2, IDTP)
                        Store (SID3, ID22)
                        Store (SID4, UMSS)
                        Store (SID5, UMSP)
                    }
                    Else
                    {
                        Store (ID20, SID0)
                        Store (IDTS, SID1)
                        Store (IDTP, SID2)
                        Store (ID22, SID3)
                        Store (UMSS, SID4)
                        Store (UMSP, SID5)
                    }

                    Store (0x00, SX)
                    CreateDWordField (Arg0, 0x00, PIO0)
                    CreateDWordField (Arg0, 0x04, DMA0)
                    CreateDWordField (Arg0, 0x08, PIO1)
                    CreateDWordField (Arg0, 0x0C, DMA1)
                    CreateDWordField (Arg0, 0x10, FLAG)
                    If (LEqual (Arg3, 0x00))
                    {
                        Store (SID2, Local0)
                        Store (SID5, Local1)
                    }
                    Else
                    {
                        Store (SID1, Local0)
                        Store (SID4, Local1)
                    }

                    If (LNotEqual (PIO0, 0xFFFFFFFF))
                    {
                        And (Local0, 0xFF, Local0)
                        ShiftLeft (T2D (PIO0), 0x08, Local2)
                        Or (Local0, Local2, Local0)
                    }

                    If (LNotEqual (PIO1, 0xFFFFFFFF))
                    {
                        And (Local0, 0xFF00, Local0)
                        Or (Local0, T2D (PIO1), Local0)
                    }

                    If (And (FLAG, 0x01))
                    {
                        And (Local1, 0xFF, Local1)
                        ShiftLeft (T2U (DMA0), 0x08, Local2)
                        Or (0xC000, Local2, Local2)
                        Or (Local2, Local1, Local1)
                    }
                    Else
                    {
                        If (LNotEqual (DMA0, 0xFFFFFFFF))
                        {
                            And (Local0, 0xFF, Local0)
                            ShiftLeft (T2D (DMA0), 0x08, Local2)
                            Or (Local0, Local2, Local0)
                        }
                    }

                    If (And (FLAG, 0x04))
                    {
                        And (Local1, 0xFF00, Local1)
                        Or (0xC0, T2U (DMA1), Local2)
                        Or (Local2, Local1, Local1)
                    }
                    Else
                    {
                        If (LNotEqual (DMA1, 0xFFFFFFFF))
                        {
                            And (Local0, 0xFF00, Local0)
                            Or (Local0, T2D (DMA1), Local0)
                        }
                    }

                    If (LEqual (Arg3, 0x00))
                    {
                        Store (Local0, IDTP)
                        Store (Local1, UMSP)
                    }
                    Else
                    {
                        Store (Local0, IDTS)
                        Store (Local1, UMSS)
                    }
                }

                Method (GTF, 2, NotSerialized)
                {
                    Store (Buffer (0x07)
                        {
                            0x03, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xEF
                        }, Local0)
                    CreateByteField (Local0, 0x01, MODE)
                    CreateByteField (Local0, 0x05, DRIV)
                    Store (Arg1, DRIV)
                    If (LEqual (Arg0, 0x00))
                    {
                        Store (IDEP, Local1)
                    }
                    Else
                    {
                        Store (IDES, Local1)
                    }

                    CreateDWordField (Local1, 0x00, PIO0)
                    CreateDWordField (Local1, 0x04, DMA0)
                    CreateDWordField (Local1, 0x08, PIO1)
                    CreateDWordField (Local1, 0x0C, DMA1)
                    CreateDWordField (Local1, 0x10, FLGX)
                    If (LEqual (Arg1, 0xA0))
                    {
                        Store (PIO0, Local2)
                        Store (DMA0, Local3)
                        And (FLGX, 0x01, FLGX)
                    }
                    Else
                    {
                        Store (PIO1, Local2)
                        Store (DMA1, Local3)
                        And (FLGX, 0x04, FLGX)
                    }

                    Store (FLGX, Local1)
                    If (LGreater (Local2, 0x0186))
                    {
                        Store (0x00, Local2)
                    }
                    Else
                    {
                        If (LGreater (Local2, 0xF0))
                        {
                            Store (0x01, Local2)
                        }
                        Else
                        {
                            If (LGreater (Local2, 0xB4))
                            {
                                Store (0x02, Local2)
                            }
                            Else
                            {
                                If (LGreater (Local2, 0x78))
                                {
                                    Store (0x03, Local2)
                                }
                                Else
                                {
                                    Store (0x04, Local2)
                                }
                            }
                        }
                    }

                    Or (0x08, Local2, MODE)
                    Store (Local0, Local2)
                    If (FLGX)
                    {
                        If (LGreater (Local3, 0x5A))
                        {
                            Store (0x00, Local3)
                        }
                        Else
                        {
                            If (LGreater (Local3, 0x3C))
                            {
                                Store (0x01, Local3)
                            }
                            Else
                            {
                                If (LGreater (Local3, 0x2D))
                                {
                                    Store (0x02, Local3)
                                }
                                Else
                                {
                                    If (LGreater (Local3, 0x1E))
                                    {
                                        Store (0x03, Local3)
                                    }
                                    Else
                                    {
                                        If (LGreater (Local3, 0x14))
                                        {
                                            Store (0x04, Local3)
                                        }
                                        Else
                                        {
                                            If (LGreater (Local3, 0x0F))
                                            {
                                                Store (0x05, Local3)
                                            }
                                            Else
                                            {
                                                Store (0x06, Local3)
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        Or (0x40, Local3, MODE)
                    }
                    Else
                    {
                        If (LEqual (Local3, 0xFFFFFFFF))
                        {
                            Return (Local0)
                        }
                        Else
                        {
                            If (LGreater (Local3, 0x96))
                            {
                                Store (0x00, Local3)
                            }
                            Else
                            {
                                If (LGreater (Local3, 0x78))
                                {
                                    Store (0x01, Local3)
                                }
                                Else
                                {
                                    Store (0x02, Local3)
                                }
                            }

                            Or (0x20, Local3, MODE)
                        }
                    }

                    Concatenate (Local0, Local2, Local1)
                    Return (Local1)
                }

                Device (PRI0)
                {
                    Name (_ADR, 0x00)
                    Method (_GTM, 0, NotSerialized)
                    {
                        Return (GTM (0x00))
                    }

                    Method (_STM, 3, NotSerialized)
                    {
                        STM (Arg0, Arg1, Arg2, 0x00)
                    }

                    Device (MAST)
                    {
                        Name (_ADR, 0x00)
                        Method (_GTF, 0, NotSerialized)
                        {
                            Return (GTF (0x00, 0xA0))
                        }
                    }

                    Device (SLAV)
                    {
                        Name (_ADR, 0x01)
                        Method (_GTF, 0, NotSerialized)
                        {
                            Return (GTF (0x00, 0xB0))
                        }
                    }
                }

                Device (SEC0)
                {
                    Name (_ADR, 0x01)
                    Method (_GTM, 0, NotSerialized)
                    {
                        Return (GTM (0x01))
                    }

                    Method (_STM, 3, NotSerialized)
                    {
                        STM (Arg0, Arg1, Arg2, 0x01)
                    }

                    Device (MAST)
                    {
                        Name (_ADR, 0x00)
                        Method (_GTF, 0, NotSerialized)
                        {
                            Return (GTF (0x01, 0xA0))
                        }
                    }

                    Device (SLAV)
                    {
                        Name (_ADR, 0x01)
                        Method (_GTF, 0, NotSerialized)
                        {
                            Return (GTF (0x01, 0xB0))
                        }
                    }
                }

                Method (DRMP, 0, NotSerialized)
                {
                    Return (\_SB.R_P0)
                }
            }

            Device (SAT1)
            {
                Name (_ADR, 0x000F0000)
                Device (PRI0)
                {
                    Name (_ADR, 0x00)
                    Name (SPTM, Buffer (0x14)
                    {
                        /* 0000 */    0x78, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 
                        /* 0008 */    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
                        /* 0010 */    0x13, 0x00, 0x00, 0x00
                    })
                    Method (_GTM, 0, NotSerialized)
                    {
                        Return (SPTM)
                    }

                    Method (_STM, 3, NotSerialized)
                    {
                        Store (Arg0, SPTM)
                    }

                    Device (MAST)
                    {
                        Name (_ADR, 0x00)
                        Method (_GTF, 0, NotSerialized)
                        {
                            Store (Buffer (0x07)
                                {
                                    0x03, 0x46, 0x00, 0x00, 0x00, 0xA0, 0xEF
                                }, Local0)
                            Return (Local0)
                        }
                    }
                }

                Device (SEC0)
                {
                    Name (_ADR, 0x01)
                    Name (SSTM, Buffer (0x14)
                    {
                        /* 0000 */    0x78, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 
                        /* 0008 */    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
                        /* 0010 */    0x13, 0x00, 0x00, 0x00
                    })
                    Method (_GTM, 0, NotSerialized)
                    {
                        Return (SSTM)
                    }

                    Method (_STM, 3, NotSerialized)
                    {
                        Store (Arg0, SSTM)
                    }

                    Device (MAST)
                    {
                        Name (_ADR, 0x00)
                        Method (_GTF, 0, NotSerialized)
                        {
                            Store (Buffer (0x07)
                                {
                                    0x03, 0x46, 0x00, 0x00, 0x00, 0xA0, 0xEF
                                }, Local0)
                            Return (Local0)
                        }
                    }
                }

                Method (DRMP, 0, NotSerialized)
                {
                    Return (\_SB.R_S0)
                }
            }

            Device (SAT0)
            {
                Name (_ADR, 0x000E0000)
                Device (PRI0)
                {
                    Name (_ADR, 0x00)
                    Name (SPTM, Buffer (0x14)
                    {
                        /* 0000 */    0x78, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 
                        /* 0008 */    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
                        /* 0010 */    0x13, 0x00, 0x00, 0x00
                    })
                    Method (_GTM, 0, NotSerialized)
                    {
                        Return (SPTM)
                    }

                    Method (_STM, 3, NotSerialized)
                    {
                        Store (Arg0, SPTM)
                    }

                    Device (MAST)
                    {
                        Name (_ADR, 0x00)
                        Method (_GTF, 0, NotSerialized)
                        {
                            Store (Buffer (0x07)
                                {
                                    0x03, 0x46, 0x00, 0x00, 0x00, 0xA0, 0xEF
                                }, Local0)
                            Return (Local0)
                        }
                    }
                }

                Device (SEC0)
                {
                    Name (_ADR, 0x01)
                    Name (SSTM, Buffer (0x14)
                    {
                        /* 0000 */    0x78, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 
                        /* 0008 */    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
                        /* 0010 */    0x13, 0x00, 0x00, 0x00
                    })
                    Method (_GTM, 0, NotSerialized)
                    {
                        Return (SSTM)
                    }

                    Method (_STM, 3, NotSerialized)
                    {
                        Store (Arg0, SSTM)
                    }

                    Device (MAST)
                    {
                        Name (_ADR, 0x00)
                        Method (_GTF, 0, NotSerialized)
                        {
                            Store (Buffer (0x07)
                                {
                                    0x03, 0x46, 0x00, 0x00, 0x00, 0xA0, 0xEF
                                }, Local0)
                            Return (Local0)
                        }
                    }
                }

                Method (DRMP, 0, NotSerialized)
                {
                    Return (\_SB.R_S1)
                }
            }

            Device (UVGA)
            {
                Name (_ADR, 0x00050000)
                Name (SWIT, 0x01)
                Name (CRTA, 0x01)
                Name (LCDA, 0x01)
                Name (TVAF, 0x00)
                Name (HDTV, 0x00)
                Name (TOGF, 0x00)
                Name (BRIP, Package (0x0D)
                {
                    0x5C, 
                    0x2A, 
                    0x14, 
                    0x18, 
                    0x1C, 
                    0x21, 
                    0x26, 
                    0x2A, 
                    0x30, 
                    0x38, 
                    0x42, 
                    0x4E, 
                    0x5C
                })
                Name (Z00U, Package (0x0D)
                {
                    0x64, 
                    0x2A, 
                    0x14, 
                    0x18, 
                    0x1C, 
                    0x21, 
                    0x26, 
                    0x2A, 
                    0x34, 
                    0x3D, 
                    0x48, 
                    0x55, 
                    0x64
                })
                Method (_DOS, 1, NotSerialized)
                {
                    Store ("VGA --_DOS Arg0", Debug)
                    Store (Arg0, SWIT)
                }

                Method (_DOD, 0, NotSerialized)
                {
                    Store ("VGA --_DOD", Debug)
                    Return (Package (0x04)
                    {
                        0x00010100, 
                        0x00010118, 
                        0x00010200, 
                        0x00010121
                    })
                }

                Method (_PS0, 0, NotSerialized)
                {
                    Store ("VGA_PS0", Debug)
                }

                Method (_PS2, 0, NotSerialized)
                {
                    Store ("VGA_PS2", Debug)
                }

                Method (_PS3, 0, NotSerialized)
                {
                    Store ("VGA_PS3", Debug)
                }

                Device (CRT)
                {
                    Name (_ADR, 0x0100)
                    Method (_DCS, 0, NotSerialized)
                    {
                        Store ("CRT --_DCS", Debug)
                        If (CRTA)
                        {
                            Return (0x1F)
                        }
                        Else
                        {
                            Return (0x1D)
                        }
                    }

                    Method (_DGS, 0, NotSerialized)
                    {
                        Store ("CRT --_DGS", Debug)
                        Store (CRTA, Local0)
                        If (CRTA)
                        {
                            Return (0x01)
                        }
                        Else
                        {
                            Return (0x00)
                        }
                    }

                    Method (_DSS, 1, NotSerialized)
                    {
                        Store ("CRT --_DSS", Debug)
                        Store (Arg0, Debug)
                    }
                }

                Device (LCD)
                {
                    Name (_ADR, 0x0118)
                    Method (_DCS, 0, NotSerialized)
                    {
                        Store ("LCD --_DCS", Debug)
                        If (LCDA)
                        {
                            Return (0x1F)
                        }
                        Else
                        {
                            Return (0x1D)
                        }
                    }

                    Method (_DGS, 0, NotSerialized)
                    {
                        Store ("LCD --_DGS", Debug)
                        Store (LCDA, Local0)
                        If (LCDA)
                        {
                            Return (0x01)
                        }
                        Else
                        {
                            Return (0x00)
                        }
                    }

                    Method (_DSS, 1, NotSerialized)
                    {
                        Store ("LCD --_DSS", Debug)
                        Store (Arg0, Debug)
                    }

                    Method (_BCL, 0, NotSerialized)
                    {
                        If (LEqual (PTPE, 0x02))
                        {
                            Return (Z00U)
                        }
                        Else
                        {
                            Return (BRIP)
                        }
                    }

                    Method (_BCM, 1, NotSerialized)
                    {
                        Store (Arg0, Local0)
                        Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                        Store (Local0, \_SB.PCI0.EC0.BRIC)
                        Store (\_SB.PCI0.EC0.ACIN, Local1)
                        Release (\_SB.PCI0.EC0.MUT0)
                        Store (_BCL (), Local2)
                        Store (0x02, Local3)
                        While (LLess (Local3, 0x0D))
                        {
                            If (LEqual (Local0, DerefOf (Index (Local2, Local3))))
                            {
                                If (Local1)
                                {
                                    Subtract (Local3, 0x02, ACBR)
                                }
                                Else
                                {
                                    Subtract (Local3, 0x02, DCBR)
                                }

                                Subtract (Local3, 0x02, CCBR)
                                Store (0x0F, Local3)
                            }

                            Increment (Local3)
                        }
                    }

                    Method (_BQC, 0, NotSerialized)
                    {
                        If (ECON)
                        {
                            Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                            Store (\_SB.PCI0.EC0.BRIC, Local0)
                            Release (\_SB.PCI0.EC0.MUT0)
                            Return (Local0)
                        }
                        Else
                        {
                            Store (_BCL (), Local1)
                            Return (DerefOf (Index (Local1, CCBR)))
                        }
                    }
                }

                Device (TV)
                {
                    Name (_ADR, 0x0200)
                    Method (_DCS, 0, NotSerialized)
                    {
                        Store ("TV --_DCS", Debug)
                        If (TVAF)
                        {
                            Return (0x1F)
                        }
                        Else
                        {
                            Return (0x1D)
                        }
                    }

                    Method (_DGS, 0, NotSerialized)
                    {
                        Store ("TV --_DGS", Debug)
                        Store (TVAF, Local0)
                        If (TVAF)
                        {
                            Return (0x01)
                        }
                        Else
                        {
                            Return (0x00)
                        }
                    }

                    Method (_DSS, 1, NotSerialized)
                    {
                        Store ("TV --_DSS", Debug)
                        Store (Arg0, Debug)
                    }
                }

                Device (HDMI)
                {
                    Name (_ADR, 0x0121)
                    Method (_DCS, 0, NotSerialized)
                    {
                        Store ("HDMI TV --_DCS", Debug)
                        If (HDTV)
                        {
                            Return (0x1F)
                        }
                        Else
                        {
                            Return (0x1D)
                        }
                    }

                    Method (_DGS, 0, NotSerialized)
                    {
                        Store ("HDMI TV --_DGS", Debug)
                        Store (HDTV, Local0)
                        If (HDTV)
                        {
                            Return (0x01)
                        }
                        Else
                        {
                            Return (0x00)
                        }
                    }

                    Method (_DSS, 1, NotSerialized)
                    {
                        Store ("HDMI TV --_DSS", Debug)
                        Store (Arg0, Debug)
                    }
                }
            }

            Device (XVR0)
            {
                Name (_ADR, 0x00040000)
                Name (_UID, 0x03)
                OperationRegion (A1E0, PCI_Config, 0x19, 0x01)
                Field (A1E0, ByteAcc, NoLock, Preserve)
                {
                    SECB,   8
                }

                Method (_BBN, 0, NotSerialized)
                {
                    Return (SECB)
                }

                Method (_STA, 0, NotSerialized)
                {
                    Return (0x0F)
                }

                Name (_PRT, Package (0x04)
                {
                    Package (0x04)
                    {
                        0xFFFF, 
                        0x00, 
                        \_SB.PCI0.LK1E, 
                        0x00
                    }, 

                    Package (0x04)
                    {
                        0xFFFF, 
                        0x01, 
                        \_SB.PCI0.LK2E, 
                        0x00
                    }, 

                    Package (0x04)
                    {
                        0xFFFF, 
                        0x02, 
                        \_SB.PCI0.LK3E, 
                        0x00
                    }, 

                    Package (0x04)
                    {
                        0xFFFF, 
                        0x03, 
                        \_SB.PCI0.LK4E, 
                        0x00
                    }
                })
                Device (VGA)
                {
                    Name (_ADR, 0x00)
                    Name (SWIT, 0x01)
                    Name (CRTA, 0x01)
                    Name (LCDA, 0x01)
                    Name (TVAF, 0x00)
                    Name (HDTV, 0x00)
                    Name (TOGF, 0x00)
                    Name (BRIP, Package (0x0D)
                    {
                        0x5C, 
                        0x2A, 
                        0x14, 
                        0x18, 
                        0x1C, 
                        0x21, 
                        0x26, 
                        0x2A, 
                        0x30, 
                        0x38, 
                        0x42, 
                        0x4E, 
                        0x5C
                    })
                    Name (Z00U, Package (0x0D)
                    {
                        0x64, 
                        0x2A, 
                        0x14, 
                        0x18, 
                        0x1C, 
                        0x21, 
                        0x26, 
                        0x2A, 
                        0x34, 
                        0x3D, 
                        0x48, 
                        0x55, 
                        0x64
                    })
                    Method (_DOS, 1, NotSerialized)
                    {
                        Store ("VGA --_DOS Arg0", Debug)
                        Store (Arg0, SWIT)
                    }

                    Method (_DOD, 0, NotSerialized)
                    {
                        Store ("VGA --_DOD", Debug)
                        Return (Package (0x04)
                        {
                            0x00010100, 
                            0x00010118, 
                            0x00010200, 
                            0x00010121
                        })
                    }

                    Method (_PS0, 0, NotSerialized)
                    {
                        Store ("VGA_PS0", Debug)
                    }

                    Method (_PS2, 0, NotSerialized)
                    {
                        Store ("VGA_PS2", Debug)
                    }

                    Method (_PS3, 0, NotSerialized)
                    {
                        Store ("VGA_PS3", Debug)
                    }

                    Device (CRT)
                    {
                        Name (_ADR, 0x0100)
                        Method (_DCS, 0, NotSerialized)
                        {
                            Store ("CRT --_DCS", Debug)
                            If (CRTA)
                            {
                                Return (0x1F)
                            }
                            Else
                            {
                                Return (0x1D)
                            }
                        }

                        Method (_DGS, 0, NotSerialized)
                        {
                            Store ("CRT --_DGS", Debug)
                            Store (CRTA, Local0)
                            If (CRTA)
                            {
                                Return (0x01)
                            }
                            Else
                            {
                                Return (0x00)
                            }
                        }

                        Method (_DSS, 1, NotSerialized)
                        {
                            Store ("CRT --_DSS", Debug)
                            Store (Arg0, Debug)
                        }
                    }

                    Device (LCD)
                    {
                        Name (_ADR, 0x0118)
                        Method (_DCS, 0, NotSerialized)
                        {
                            Store ("LCD --_DCS", Debug)
                            If (LCDA)
                            {
                                Return (0x1F)
                            }
                            Else
                            {
                                Return (0x1D)
                            }
                        }

                        Method (_DGS, 0, NotSerialized)
                        {
                            Store ("LCD --_DGS", Debug)
                            Store (LCDA, Local0)
                            If (LCDA)
                            {
                                Return (0x01)
                            }
                            Else
                            {
                                Return (0x00)
                            }
                        }

                        Method (_DSS, 1, NotSerialized)
                        {
                            Store ("LCD --_DSS", Debug)
                            Store (Arg0, Debug)
                        }

                        Method (_BCL, 0, NotSerialized)
                        {
                            If (LEqual (PTPE, 0x02))
                            {
                                Return (Z00U)
                            }
                            Else
                            {
                                Return (BRIP)
                            }
                        }

                        Method (_BCM, 1, NotSerialized)
                        {
                            Store (Arg0, Local0)
                            Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                            Store (Local0, \_SB.PCI0.EC0.BRIC)
                            Store (\_SB.PCI0.EC0.ACIN, Local1)
                            Release (\_SB.PCI0.EC0.MUT0)
                            Store (_BCL (), Local2)
                            Store (0x02, Local3)
                            While (LLess (Local3, 0x0D))
                            {
                                If (LEqual (Local0, DerefOf (Index (Local2, Local3))))
                                {
                                    If (Local1)
                                    {
                                        Subtract (Local3, 0x02, ACBR)
                                    }
                                    Else
                                    {
                                        Subtract (Local3, 0x02, DCBR)
                                    }

                                    Subtract (Local3, 0x02, CCBR)
                                    Store (0x0F, Local3)
                                }

                                Increment (Local3)
                            }
                        }

                        Method (_BQC, 0, NotSerialized)
                        {
                            If (ECON)
                            {
                                Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                                Store (\_SB.PCI0.EC0.BRIC, Local0)
                                Release (\_SB.PCI0.EC0.MUT0)
                                Return (Local0)
                            }
                            Else
                            {
                                Store (_BCL (), Local1)
                                Return (DerefOf (Index (Local1, CCBR)))
                            }
                        }
                    }

                    Device (TV)
                    {
                        Name (_ADR, 0x0200)
                        Method (_DCS, 0, NotSerialized)
                        {
                            Store ("TV --_DCS", Debug)
                            If (TVAF)
                            {
                                Return (0x1F)
                            }
                            Else
                            {
                                Return (0x1D)
                            }
                        }

                        Method (_DGS, 0, NotSerialized)
                        {
                            Store ("TV --_DGS", Debug)
                            Store (TVAF, Local0)
                            If (TVAF)
                            {
                                Return (0x01)
                            }
                            Else
                            {
                                Return (0x00)
                            }
                        }

                        Method (_DSS, 1, NotSerialized)
                        {
                            Store ("TV --_DSS", Debug)
                            Store (Arg0, Debug)
                        }
                    }

                    Device (HDMI)
                    {
                        Name (_ADR, 0x0121)
                        Method (_DCS, 0, NotSerialized)
                        {
                            Store ("HDMI TV --_DCS", Debug)
                            If (HDTV)
                            {
                                Return (0x1F)
                            }
                            Else
                            {
                                Return (0x1D)
                            }
                        }

                        Method (_DGS, 0, NotSerialized)
                        {
                            Store ("HDMI TV --_DGS", Debug)
                            Store (HDTV, Local0)
                            If (HDTV)
                            {
                                Return (0x01)
                            }
                            Else
                            {
                                Return (0x00)
                            }
                        }

                        Method (_DSS, 1, NotSerialized)
                        {
                            Store ("HDMI TV --_DSS", Debug)
                            Store (Arg0, Debug)
                        }
                    }
                }
            }

            Device (XVR1)
            {
                Name (_ADR, 0x00030000)
                Name (_UID, 0x04)
                OperationRegion (A1E1, PCI_Config, 0x19, 0x01)
                Field (A1E1, ByteAcc, NoLock, Preserve)
                {
                    SECB,   8
                }

                Method (_BBN, 0, NotSerialized)
                {
                    Return (SECB)
                }

                Method (_STA, 0, NotSerialized)
                {
                    Return (0x0F)
                }

                Name (_PRT, Package (0x04)
                {
                    Package (0x04)
                    {
                        0xFFFF, 
                        0x00, 
                        \_SB.PCI0.LK4E, 
                        0x00
                    }, 

                    Package (0x04)
                    {
                        0xFFFF, 
                        0x01, 
                        \_SB.PCI0.LK1E, 
                        0x00
                    }, 

                    Package (0x04)
                    {
                        0xFFFF, 
                        0x02, 
                        \_SB.PCI0.LK2E, 
                        0x00
                    }, 

                    Package (0x04)
                    {
                        0xFFFF, 
                        0x03, 
                        \_SB.PCI0.LK3E, 
                        0x00
                    }
                })
                Device (X1S0)
                {
                    Name (_ADR, 0x00)
                }
            }

            Device (XVR2)
            {
                Name (_ADR, 0x00020000)
                Name (_HPP, Package (0x04)
                {
                    0x10, 
                    0x40, 
                    0x01, 
                    0x00
                })
                Name (_UID, 0x05)
                OperationRegion (A1E2, PCI_Config, 0x19, 0x01)
                Field (A1E2, ByteAcc, NoLock, Preserve)
                {
                    SECB,   8
                }

                Method (_BBN, 0, NotSerialized)
                {
                    Return (SECB)
                }

                Method (_STA, 0, NotSerialized)
                {
                    Return (0x0F)
                }

                Name (_PRT, Package (0x04)
                {
                    Package (0x04)
                    {
                        0xFFFF, 
                        0x00, 
                        \_SB.PCI0.LK2E, 
                        0x00
                    }, 

                    Package (0x04)
                    {
                        0xFFFF, 
                        0x01, 
                        \_SB.PCI0.LK3E, 
                        0x00
                    }, 

                    Package (0x04)
                    {
                        0xFFFF, 
                        0x02, 
                        \_SB.PCI0.LK4E, 
                        0x00
                    }, 

                    Package (0x04)
                    {
                        0xFFFF, 
                        0x03, 
                        \_SB.PCI0.LK1E, 
                        0x00
                    }
                })
                OperationRegion (PCE1, PCI_Config, 0x90, 0x70)
                Field (PCE1, DWordAcc, Lock, Preserve)
                {
                            Offset (0x08), 
                        ,   3, 
                    BS03,   1, 
                        ,   1, 
                    BS05,   1, 
                        ,   13, 
                    BS19,   1, 
                        ,   2, 
                    EPDS,   1
                }

                Device (X2S0)
                {
                    Name (_ADR, 0x00)
                    Method (_STA, 0, NotSerialized)
                    {
                        If (\_SB.PCI0.XVR2.EPDS)
                        {
                            Return (0x0F)
                        }
                        Else
                        {
                            Return (0x00)
                        }
                    }

                    Method (_RMV, 0, NotSerialized)
                    {
                        Return (0x01)
                    }

                    Name (_EJD, "_SB.PCI0.USB0.RH00.Prt5")
                }
            }
        }

        Device (QBTN)
        {
            Name (_HID, EisaId ("PNP0C32"))
            Name (_UID, 0x01)
            Method (_STA, 0, NotSerialized)
            {
                If (LEqual (OSYS, 0x07D6))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (0x00)
                }
            }

            Method (GHID, 0, NotSerialized)
            {
                If (LEqual (HOTB, 0x04))
                {
                    Notify (QBTN, 0x02)
                    Store (0x00, HOTB)
                }

                Return (Buffer (0x01)
                {
                    0x01
                })
            }
        }

        Device (DBTN)
        {
            Name (_HID, EisaId ("PNP0C32"))
            Name (_UID, 0x02)
            Method (_STA, 0, NotSerialized)
            {
                If (LEqual (OSYS, 0x07D6))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (0x00)
                }
            }

            Method (GHID, 0, NotSerialized)
            {
                If (LEqual (HOTB, 0x05))
                {
                    Notify (DBTN, 0x02)
                    Store (0x00, HOTB)
                }

                Return (Buffer (0x01)
                {
                    0x02
                })
            }
        }

        Device (MUBN)
        {
            Name (_HID, EisaId ("PNP0C32"))
            Name (_UID, 0x03)
            Method (_STA, 0, NotSerialized)
            {
                If (LEqual (OSYS, 0x07D6))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (0x00)
                }
            }

            Method (GHID, 0, NotSerialized)
            {
                If (LEqual (HOTB, 0x03))
                {
                    Notify (MUBN, 0x02)
                    Store (0x00, HOTB)
                }

                Return (Buffer (0x01)
                {
                    0x03
                })
            }
        }

        Device (PIBN)
        {
            Name (_HID, EisaId ("PNP0C32"))
            Name (_UID, 0x06)
            Method (_STA, 0, NotSerialized)
            {
                If (LEqual (OSYS, 0x07D6))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (0x00)
                }
            }

            Method (GHID, 0, NotSerialized)
            {
                If (LEqual (HOTB, 0x06))
                {
                    Notify (PIBN, 0x02)
                    Store (0x00, HOTB)
                }

                Return (Buffer (0x01)
                {
                    0x06
                })
            }
        }

        Device (WEBN)
        {
            Name (_HID, EisaId ("PNP0C32"))
            Name (_UID, 0x04)
            Method (_STA, 0, NotSerialized)
            {
                If (LEqual (OSYS, 0x07D6))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (0x00)
                }
            }

            Method (GHID, 0, NotSerialized)
            {
                If (LEqual (HOTB, 0x10))
                {
                    Notify (WEBN, 0x02)
                    Store (0x00, HOTB)
                }

                Return (Buffer (0x01)
                {
                    0x04
                })
            }
        }

        Device (LVBN)
        {
            Name (_HID, EisaId ("PNP0C32"))
            Name (_UID, 0x08)
            Method (_STA, 0, NotSerialized)
            {
                If (LEqual (OSYS, 0x07D6))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (0x00)
                }
            }

            Method (GHID, 0, NotSerialized)
            {
                If (LEqual (HOTB, 0x11))
                {
                    Notify (LVBN, 0x02)
                    Store (0x00, HOTB)
                }

                Return (Buffer (0x01)
                {
                    0x08
                })
            }
        }

        Device (VOBN)
        {
            Name (_HID, EisaId ("PNP0C32"))
            Name (_UID, 0x07)
            Method (_STA, 0, NotSerialized)
            {
                If (LEqual (OSYS, 0x07D6))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (0x00)
                }
            }

            Method (GHID, 0, NotSerialized)
            {
                If (LEqual (HOTB, 0x12))
                {
                    Notify (VOBN, 0x02)
                    Store (0x00, HOTB)
                }

                Return (Buffer (0x01)
                {
                    0x07
                })
            }
        }

        Scope (\)
        {
            Name (PICF, 0x00)
            Method (_PIC, 1, NotSerialized)
            {
                Store (Arg0, PICF)
            }

            OperationRegion (\_SB.PCI0.LPC0.PIRQ, PCI_Config, 0x7C, 0x0C)
            Field (\_SB.PCI0.LPC0.PIRQ, AnyAcc, NoLock, Preserve)
            {
                INTW,   4, 
                INTX,   4, 
                INTY,   4, 
                INTZ,   4, 
                INTA,   4, 
                INTB,   4, 
                INTC,   4, 
                INTD,   4, 
                ISCI,   4, 
                ITCO,   4, 
                ISMB,   4, 
                IUS2,   4, 
                INTU,   4, 
                INTS,   4, 
                PSI1,   4, 
                PSI0,   4, 
                IUS0,   4, 
                IUS1,   4, 
                IMAC,   4, 
                IAZA,   4, 
                IACI,   4, 
                IMCI,   4, 
                IPID,   4, 
                ISID,   4
            }
        }

        Scope (\_SB.PCI0)
        {
            Name (BUFA, ResourceTemplate ()
            {
                IRQ (Level, ActiveLow, Shared, )
                    {5,7,9,10,11,14,15}
            })
            Name (BUFB, ResourceTemplate ()
            {
                IRQ (Level, ActiveLow, Shared, _Y0A)
                    {}
            })
            CreateWordField (BUFB, \_SB.PCI0._Y0A._INT, IRQV)
            Method (CRS, 1, Serialized)
            {
                If (Arg0)
                {
                    ShiftLeft (0x01, Arg0, IRQV)
                }
                Else
                {
                    Store (Zero, IRQV)
                }

                Return (BUFB)
            }

            Method (SRS, 1, Serialized)
            {
                CreateWordField (Arg0, 0x01, IRQ0)
                FindSetRightBit (IRQ0, Local0)
                Decrement (Local0)
                Return (Local0)
            }

            Name (BUFM, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000014,
                }
            })
            Name (BUFI, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000015,
                }
            })
            Name (BUFU, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000016,
                }
            })
            Name (BUFS, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000017,
                }
            })
            Name (BUF1, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000010,
                }
            })
            Name (BUF2, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000011,
                }
            })
            Name (BUF3, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000012,
                }
            })
            Name (BUF4, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000013,
                }
            })
            Name (BUFF, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000005,
                    0x00000007,
                    0x0000000A,
                    0x0000000B,
                    0x0000000E,
                    0x0000000F,
                }
            })
            Name (BUP1, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000005,
                }
            })
            Name (BUP2, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x00000007,
                }
            })
            Name (BUFQ, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x0000000A,
                }
            })
            Name (BUFR, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, )
                {
                    0x0000000B,
                }
            })
            Method (CRSI, 1, Serialized)
            {
                Name (IRZ5, ResourceTemplate ()
                {
                    Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, ,, _Y0B)
                    {
                        0x00000007,
                    }
                })
                CreateWordField (IRZ5, \_SB.PCI0.CRSI._Y0B._INT, INZ5)
                Store (Arg0, Local0)
                If (LEqual (Arg0, 0x03))
                {
                    Store (0x10, Local0)
                }

                If (LEqual (Arg0, 0x04))
                {
                    Store (0x11, Local0)
                }

                If (LEqual (Arg0, 0x06))
                {
                    Store (0x12, Local0)
                }

                If (LEqual (Arg0, 0x0C))
                {
                    Store (0x13, Local0)
                }

                If (LEqual (Arg0, 0x08))
                {
                    Store (0x14, Local0)
                }

                If (LEqual (Arg0, 0x0D))
                {
                    Store (0x15, Local0)
                }

                If (LEqual (Arg0, 0x02))
                {
                    Store (0x16, Local0)
                }

                If (LEqual (Arg0, 0x01))
                {
                    Store (0x17, Local0)
                }

                Store (Local0, INZ5)
                Return (IRZ5)
            }

            Method (SRSI, 1, Serialized)
            {
                CreateWordField (Arg0, 0x05, IRZ6)
                Store (IRZ6, Local0)
                If (LEqual (IRZ6, 0x10))
                {
                    Store (0x03, Local0)
                }

                If (LEqual (IRZ6, 0x11))
                {
                    Store (0x04, Local0)
                }

                If (LEqual (IRZ6, 0x12))
                {
                    Store (0x06, Local0)
                }

                If (LEqual (IRZ6, 0x13))
                {
                    Store (0x0C, Local0)
                }

                If (LEqual (IRZ6, 0x14))
                {
                    Store (0x08, Local0)
                }

                If (LEqual (IRZ6, 0x15))
                {
                    Store (0x0D, Local0)
                }

                If (LEqual (IRZ6, 0x16))
                {
                    Store (0x02, Local0)
                }

                If (LEqual (IRZ6, 0x17))
                {
                    Store (0x01, Local0)
                }

                Return (Local0)
            }

            Device (LNK1)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x01)
                Method (_STA, 0, NotSerialized)
                {
                    If (INTW)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, INTW)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUP1)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (INTW))
                    }
                    Else
                    {
                        Return (CRSI (INTW))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), INTW)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), INTW)
                    }
                }
            }

            Device (LNK2)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x02)
                Method (_STA, 0, NotSerialized)
                {
                    If (INTX)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, INTX)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUP2)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (INTX))
                    }
                    Else
                    {
                        Return (CRSI (INTX))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), INTX)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), INTX)
                    }
                }
            }

            Device (LNK3)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x03)
                Method (_STA, 0, NotSerialized)
                {
                    If (INTY)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, INTY)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFQ)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (INTY))
                    }
                    Else
                    {
                        Return (CRSI (INTY))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), INTY)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), INTY)
                    }
                }
            }

            Device (LNK4)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x04)
                Method (_STA, 0, NotSerialized)
                {
                    If (INTZ)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, INTZ)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFR)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (INTZ))
                    }
                    Else
                    {
                        Return (CRSI (INTZ))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), INTZ)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), INTZ)
                    }
                }
            }

            Device (LK1E)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x05)
                Method (_STA, 0, NotSerialized)
                {
                    If (INTA)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, INTA)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUF1)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (INTA))
                    }
                    Else
                    {
                        Return (CRSI (INTA))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), INTA)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), INTA)
                    }
                }
            }

            Device (LK2E)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x06)
                Method (_STA, 0, NotSerialized)
                {
                    If (INTB)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, INTB)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUF2)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (INTB))
                    }
                    Else
                    {
                        Return (CRSI (INTB))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), INTB)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), INTB)
                    }
                }
            }

            Device (LK3E)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x07)
                Method (_STA, 0, NotSerialized)
                {
                    If (INTC)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, INTC)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUF3)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (INTC))
                    }
                    Else
                    {
                        Return (CRSI (INTC))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), INTC)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), INTC)
                    }
                }
            }

            Device (LK4E)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x08)
                Method (_STA, 0, NotSerialized)
                {
                    If (INTD)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, INTD)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUF4)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (INTD))
                    }
                    Else
                    {
                        Return (CRSI (INTD))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), INTD)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), INTD)
                    }
                }
            }

            Device (LSMB)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x09)
                Method (_STA, 0, NotSerialized)
                {
                    If (ISMB)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, ISMB)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFQ)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (ISMB))
                    }
                    Else
                    {
                        Return (CRSI (ISMB))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), ISMB)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), ISMB)
                    }
                }
            }

            Device (LPMU)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x14)
                Method (_STA, 0, NotSerialized)
                {
                    If (INTS)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, INTS)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFR)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (INTS))
                    }
                    Else
                    {
                        Return (CRSI (INTS))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), INTS)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), INTS)
                    }
                }
            }

            Device (LUS0)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x0A)
                Method (_STA, 0, NotSerialized)
                {
                    If (IUS0)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, IUS0)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFU)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (IUS0))
                    }
                    Else
                    {
                        Return (CRSI (IUS0))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), IUS0)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), IUS0)
                    }
                }
            }

            Device (LUS2)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x0C)
                Method (_STA, 0, NotSerialized)
                {
                    If (IUS2)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, IUS2)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFU)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (IUS2))
                    }
                    Else
                    {
                        Return (CRSI (IUS2))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), IUS2)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), IUS2)
                    }
                }
            }

            Device (LMAC)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x0D)
                Method (_STA, 0, NotSerialized)
                {
                    If (IMAC)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, IMAC)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFM)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (IMAC))
                    }
                    Else
                    {
                        Return (CRSI (IMAC))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), IMAC)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), IMAC)
                    }
                }
            }

            Device (LAZA)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x0E)
                Method (_STA, 0, NotSerialized)
                {
                    If (IAZA)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, IAZA)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFI)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (IAZA))
                    }
                    Else
                    {
                        Return (CRSI (IAZA))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), IAZA)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), IAZA)
                    }
                }
            }

            Device (LACI)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x0F)
                Method (_STA, 0, NotSerialized)
                {
                    If (IACI)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, IACI)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFI)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (IACI))
                    }
                    Else
                    {
                        Return (CRSI (IACI))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), IACI)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), IACI)
                    }
                }
            }

            Device (LMCI)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x10)
                Method (_STA, 0, NotSerialized)
                {
                    If (IMCI)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, IMCI)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFI)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (IMCI))
                    }
                    Else
                    {
                        Return (CRSI (IMCI))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), IMCI)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), IMCI)
                    }
                }
            }

            Device (LPID)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x11)
                Method (_STA, 0, NotSerialized)
                {
                    If (IPID)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, IPID)
                    Store (0x00, ISID)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFI)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (IPID))
                    }
                    Else
                    {
                        Return (CRSI (IPID))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), IPID)
                        Store (SRS (Arg0), ISID)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), IPID)
                        Store (SRSI (Arg0), ISID)
                    }
                }
            }

            Device (LTID)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x12)
                Method (_STA, 0, NotSerialized)
                {
                    If (PSI0)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, PSI0)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFS)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (PSI0))
                    }
                    Else
                    {
                        Return (CRSI (PSI0))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), PSI0)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), PSI0)
                    }
                }
            }

            Device (LSI1)
            {
                Name (_HID, EisaId ("PNP0C0F"))
                Name (_UID, 0x13)
                Method (_STA, 0, NotSerialized)
                {
                    If (PSI0)
                    {
                        Return (0x0B)
                    }
                    Else
                    {
                        Return (0x09)
                    }
                }

                Method (_DIS, 0, NotSerialized)
                {
                    Store (0x00, PSI1)
                }

                Method (_PRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (BUFA)
                    }
                    Else
                    {
                        Return (BUFM)
                    }
                }

                Method (_CRS, 0, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Return (CRS (PSI1))
                    }
                    Else
                    {
                        Return (CRSI (PSI1))
                    }
                }

                Method (_SRS, 1, NotSerialized)
                {
                    If (LNot (PICF))
                    {
                        Store (SRS (Arg0), PSI1)
                    }
                    Else
                    {
                        Store (SRSI (Arg0), PSI1)
                    }
                }
            }
        }

        Scope (\_TZ)
        {
            Name (TPAS, 0x58)
            Name (TPC, 0x5F)
            Name (TPTM, 0x4B)
            ThermalZone (THRM)
            {
                Method (_CRT, 0, Serialized)
                {
                    Return (Add (0x0AAC, Multiply (TPC, 0x0A)))
                }

                Method (_SCP, 1, Serialized)
                {
                    Store (0x00, CTYP)
                }

                Method (_TMP, 0, Serialized)
                {
                    If (ECON)
                    {
                        Acquire (\_SB.PCI0.EC0.MUT0, 0xFFFF)
                        Store (\_SB.PCI0.EC0.RTMP, Local0)
                        Release (\_SB.PCI0.EC0.MUT0)
                        Store ("Current temp is: ", Debug)
                        Return (Add (0x0AAC, Multiply (Local0, 0x0A)))
                    }
                    Else
                    {
                        Return (Add (0x0AAC, Multiply (TPTM, 0x0A)))
                    }
                }

                Method (_PSL, 0, Serialized)
                {
                    Return (Package (0x01)
                    {
                        \_PR.CPU0
                    })
                }

                Method (_PSV, 0, Serialized)
                {
                    Return (Add (0x0AAC, Multiply (TPAS, 0x0A)))
                }

                Method (_TC1, 0, Serialized)
                {
                    Return (0x02)
                }

                Method (_TC2, 0, Serialized)
                {
                    Return (0x03)
                }

                Method (_TSP, 0, Serialized)
                {
                    Return (0x64)
                }
            }
        }
    }

    Scope (\_SB.PCI0.LPC0)
    {
        OperationRegion (RGA0, PCI_Config, 0xA0, 0x04)
        Field (RGA0, AnyAcc, NoLock, Preserve)
        {
            COMP,   8, 
            ADIO,   4, 
            MIDS,   4, 
            MSSS,   4, 
            FDCP,   2, 
            ADLB,   1, 
                    Offset (0x03), 
            LPTP,   3, 
                ,   1, 
            DVR0,   1, 
            DVR1,   1, 
            DVR2,   1, 
            DVR3,   1
        }

        OperationRegion (RGA1, PCI_Config, 0xA4, 0x04)
        Field (RGA1, AnyAcc, NoLock, Preserve)
        {
            GMPS,   16, 
                    Offset (0x04)
        }
    }

    OperationRegion (CS72, SystemIO, 0x72, 0x02)
    Field (CS72, ByteAcc, NoLock, Preserve)
    {
        CI72,   8, 
        CO73,   8
    }

    IndexField (CI72, CO73, ByteAcc, NoLock, Preserve)
    {
                Offset (0x22), 
            ,   3, 
        HPBD,   3, 
                Offset (0x9A), 
        BRNS,   4, 
        ACBN,   4, 
        BABN,   4, 
        WLSU,   1, 
        BTSU,   1, 
        IVIK,   2, 
        BTWL,   2, 
        BTLS,   1, 
        BWLS,   1, 
        WWLS,   1, 
                Offset (0x9D), 
        S4FL,   1, 
        SETF,   1, 
        VGAT,   1, 
        LSHK,   1, 
        S4RT,   2, 
        PTPE,   2, 
        BTNS,   1, 
        BTS3,   1, 
                Offset (0xA2), 
        HOTB,   8
    }

    Mutex (M723, 0x00)
    OperationRegion (DBGP, SystemIO, 0x80, 0x01)
    Field (DBGP, ByteAcc, NoLock, Preserve)
    {
        DBUG,   8
    }

    OperationRegion (ENEP, SystemIO, 0x0380, 0x04)
    Field (ENEP, ByteAcc, NoLock, Preserve)
    {
        P380,   8, 
        P381,   8, 
        P382,   8, 
        P383,   8
    }

    Mutex (M380, 0x00)
    OperationRegion (PM1A, SystemIO, 0x1000, 0x04)
    Field (PM1A, ByteAcc, NoLock, Preserve)
    {
            ,   14, 
        PEWS,   1, 
                Offset (0x02)
    }

    OperationRegion (LDTR, SystemIO, 0x10A6, 0x01)
    Field (LDTR, ByteAcc, NoLock, Preserve)
    {
        LDTC,   1
    }

    OperationRegion (Z00V, SystemIO, 0x1407, 0x01)
    Field (Z00V, ByteAcc, NoLock, Preserve)
    {
        PSMI,   1, 
                Offset (0x01)
    }

    OperationRegion (NVGP, SystemIO, 0x14C4, 0x08)
    Field (NVGP, ByteAcc, NoLock, Preserve)
    {
        Z00W,   8, 
        Z00X,   8, 
        Z00Y,   8, 
        Z000,   8, 
        Z001,   8, 
        Z002,   8, 
        Z00Z,   8, 
        Z010,   8
    }

    OperationRegion (NVG1, SystemIO, 0x14D0, 0x08)
    Field (NVG1, ByteAcc, NoLock, Preserve)
    {
                Offset (0x06), 
        GP23,   8, 
        GP24,   8
    }

    Name (RBRF, 0x01)
    Name (L10F, 0x00)
    Name (SCIC, 0x00)
    Name (SCID, 0x00)
    Name (CADL, 0x01)
    Name (PADL, 0x01)
    Name (PSTE, 0x01)
    Name (CSTE, 0x01)
    Name (NSTE, 0x01)
    Name (SSTE, 0x01)
    Name (WMSF, 0x00)
    Name (JMPF, 0x00)
    Name (WIRE, 0x00)
    Name (WLID, 0xFF)
    Name (GP25, 0x01)
    Name (GP26, 0x01)
    Name (WLSS, 0x01)
    Name (WLS2, 0x00)
    Name (S34F, 0x00)
    Name (S34C, 0x00)
    Name (OSYS, 0x07D6)
    Name (CTYP, 0x00)
    Name (DTCN, 0x00)
    Name (\ECON, 0x00)
    Name (FWSO, "FWSO")
}


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 15:59                                                           ` David P. Reed
@ 2008-01-01 16:15                                                             ` Alan Cox
  2008-01-01 16:43                                                               ` Ingo Molnar
                                                                                 ` (2 more replies)
  2008-01-01 17:31                                                             ` Pavel Machek
  1 sibling, 3 replies; 243+ messages in thread
From: Alan Cox @ 2008-01-01 16:15 UTC (permalink / raw)
  To: David P. Reed
  Cc: H. Peter Anvin, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

> 80 makes me suspicious.)   That might mean that the freeze happens only
> when certain values are written, or when they are written closely in
> time to some other action - being used to communicate something to the
> SMM code).   If there is some race in when Linux's port 80 writes happen
> that happen to change the meaning of a request to the hardware or to
> SMM, then we could be rarely stepping on

That does imply some muppet 'extended' the debug interface for power
management on your laptop. Also pretty much proves that for such systems
we do have to move from port 0x80 to another delay approach.

Ingo - the fact that so many ISA bus devices need _p to mean "ISA bus
clocks" says to me we should keep the _p port 0x80 using variant for old
systems/device combinations (eg ISA ethernet cards) which won't show up
in any problem system (we know this from 15 odd years of testing), but
stop using it for PCI and embedded devices on modern systems.

Alan


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 16:15                                                             ` Alan Cox
@ 2008-01-01 16:43                                                               ` Ingo Molnar
  2008-01-01 17:32                                                                 ` Alan Cox
  2008-01-01 17:32                                                                 ` Christer Weinigel
  2008-01-01 17:32                                                               ` David P. Reed
  2008-01-01 21:15                                                               ` H. Peter Anvin
  2 siblings, 2 replies; 243+ messages in thread
From: Ingo Molnar @ 2008-01-01 16:43 UTC (permalink / raw)
  To: Alan Cox
  Cc: David P. Reed, H. Peter Anvin, Rene Herman, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:

> Ingo - the fact that so many ISA bus devices need _p to mean "ISA bus 
> clocks" says to me we should keep the _p port 0x80 using variant for 
> old systems/device combinations (eg ISA ethernet cards) which won't 
> show up in any problem system (we know this from 15 odd years of 
> testing), but stop using it for PCI and embedded devices on modern 
> systems.

yes, ISA is fragile, and no way do we want to remove the delay, but are 
there strong counter-arguments against doing the clean thing and adding 
an udelay(2) (or udelay(1)) to replace those _p() uses in ISA drivers? 
That removes the global effect once and forever. Initially for 
standalone drivers without early bootup functionality, not platform 
drivers that might need to run before we have calibrated udelay.

if someone runs a fresh new kernel on an ancient device then timings 
_will_ change a bit, no matter what we do. Alignments change, the 
compiler output will change (old compilers get deprecated so a new 
compiler might have to be picked), cache effects change - and this is 
inevitable. The important thing is to not eliminate the delays - but we 
sure dont have to keep them cycle accurate (we couldnt even if we wanted 
to). The only way to get the _exact same_ behavior is to not change the 
kernel at all.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 15:59                                                           ` David P. Reed
  2008-01-01 16:15                                                             ` Alan Cox
@ 2008-01-01 17:31                                                             ` Pavel Machek
  2008-01-01 17:33                                                               ` David P. Reed
  1 sibling, 1 reply; 243+ messages in thread
From: Pavel Machek @ 2008-01-01 17:31 UTC (permalink / raw)
  To: David P. Reed
  Cc: Alan Cox, H. Peter Anvin, Rene Herman, Ingo Molnar, Paul Rolland,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Hi!

> 1. It appears to be a real port.  SMI traps are not happening in the
> normal outb to 80.  Hundreds of them execute perfectly with the expected
> instruction counts.  If I can trace the particular event that creates
> the hard freeze (getting really creative, here) and stop before the
> freeze disables the entire computer, I will.  That may be an SMI, or
> perhaps any other kind of interrupt or exception.  Maybe someone knows
> how to safely trace through an impending SMI while doing printk's or
> something?
> 
> 2. It appears to be the standard POST diagnostic port.  On a whim, I
> disassembled my DSDT code, and studied it more closely.   It turns out
> that there are a bunch of "Store(..., DBUG)" instructions scattered
> throughout, and when you look at what DBUG is defined as, it is defined
> as an IO Port at IO address DBGP, which is a 1-byte value = 0x80.  So
> the ACPI BIOS thinks it has something to do with debugging.   There's a
> little strangeness here, however, because the value sent to the port
> occasionally has something to do with arguments to the ACPI operations
> relating to sleep and wakeup ...  could just be that those arguments are
> distinctive.

Maybe someone just left debugging code in production?

> In thinking about this, I recognize a couple of things.  ACPI is telling
> us something when it declares a reference to port 80 in its code.  It's
> not telling us the function of this port on this machine, but it is
> telling us that it is being used by the BIOS.   This could be a reason
> to put out a printk warning message...   'warning: port 80 is used by
> ACPI BIOS - if you are experiencing problems, you might try an alternate
> means of iodelay.'
> 
> Second, it seems likely that there are one of two possible reasons that
> the port 80 writes cause hang/freezes:
> 
> 1. buffer overflow in such a device.
> 
> 2. there is some "meaning" to certain byte values being written (the
> _PTS and _WAK use of arguments that come from callers to store into port
> 80 makes me suspicious.)   That might mean that the freeze happens only
> when certain values are written, or when they are written closely in
> time to some other action - being used to communicate something to the

There's nothing easier than always writing 0 to the 0x80 to check if
it hangs in such case...?
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 16:43                                                               ` Ingo Molnar
@ 2008-01-01 17:32                                                                 ` Alan Cox
  2008-01-01 18:45                                                                   ` Ingo Molnar
  2008-01-01 17:32                                                                 ` Christer Weinigel
  1 sibling, 1 reply; 243+ messages in thread
From: Alan Cox @ 2008-01-01 17:32 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: David P. Reed, H. Peter Anvin, Rene Herman, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

> there strong counter-arguments against doing the clean thing and adding 
> an udelay(2) (or udelay(1)) to replace those _p() uses in ISA drivers? 

#1 udelay has to be for the worst case bus clock (6MHz) while the device
may be at 10Mhz or even 12MHz ISA. So it slows it down stuff
unneccessarily- and stuff that really really is slow enough as is.

#2 Most of the ancient wind up relics with ISA bus don't have a tsc so
their udelay value is kind of iffy.

#3 Not changing it is the lowest risk for a lot of the old ISA code that
never occurs on newer boxes

If we have an isa_inb_p() as a specific statement of "I am doing an ISA
bus dependant delay on ancient crap hardware" then we can avoid the risk
of breakage. We wouldn't use it for non ISA, and certainly not for stuff
like chipset logic which requires a more thorough fix as it occurs on all
kinds of boxes.

> _will_ change a bit, no matter what we do. Alignments change, the 
> compiler output will change (old compilers get deprecated so a new 
> compiler might have to be picked), cache effects change - and this is 
> inevitable. The important thing is to not eliminate the delays - but we 
> sure dont have to keep them cycle accurate (we couldnt even if we wanted 
> to). The only way to get the _exact same_ behavior is to not change the 
> kernel at all.

ISA bus cycles are *slow*, the subtle processor cache and gcc triggered
timing changes are lost in the noise.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 16:43                                                               ` Ingo Molnar
  2008-01-01 17:32                                                                 ` Alan Cox
@ 2008-01-01 17:32                                                                 ` Christer Weinigel
  2008-01-01 18:46                                                                   ` Ingo Molnar
  1 sibling, 1 reply; 243+ messages in thread
From: Christer Weinigel @ 2008-01-01 17:32 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Alan Cox, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On Tue, 1 Jan 2008 17:43:38 +0100
Ingo Molnar <mingo@elte.hu> wrote:

> if someone runs a fresh new kernel on an ancient device then timings 
> _will_ change a bit, no matter what we do. Alignments change, the 
> compiler output will change (old compilers get deprecated so a new 
> compiler might have to be picked), cache effects change - and this is 
> inevitable. The important thing is to not eliminate the delays - but
> we sure dont have to keep them cycle accurate (we couldnt even if we
> wanted to). The only way to get the _exact same_ behavior is to not
> change the kernel at all.

What I'm afraid is that udelay will be significantly slower, which
might hit anything that does a lot of gettimeofday calls (poking at the
PIT timer)  on embedded 386/486 systems.  On the other hand, those
systems might not want to upgrade to 2.6 anyway.  

And why do people keep buying HP hardware?  HP seem to be quite
Linux-unfriendly on the desktop [1] and on their laptops.  Apparently
HP doesn't even bother to try Linux on any of their non-server systems.

[1] Try running Linux on a HP DC7700 machine, there seems to be a lot
of magic stuff in those machines that doesn't work well with Linux.
They had some ACPI crap that stopped FC7 from booting without a lot of
magic PCI access options and audio still does not work.  

/Christer

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 16:15                                                             ` Alan Cox
  2008-01-01 16:43                                                               ` Ingo Molnar
@ 2008-01-01 17:32                                                               ` David P. Reed
  2008-01-01 17:38                                                                 ` Alan Cox
  2008-01-01 21:15                                                               ` H. Peter Anvin
  2 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-01 17:32 UTC (permalink / raw)
  To: Alan Cox
  Cc: H. Peter Anvin, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


Alan Cox wrote:
> That does imply some muppet 'extended' the debug interface for power
> management on your laptop. Also pretty much proves that for such systems
> we do have to move from port 0x80 to another delay approach.
>   
Alan - in googling around the net yesterday looking for SuperIO chipsets 
that claim to support port 80, I have found that "blade" servers from 
companies like IBM and HP *claim* to have a system for monitoring port 
80 diagnostic codes and sending them to the "drawer" management 
processor through a management backplane.   This is a little puzzling, 
because you'd think they would have noticed port 80 issues, since they 
run Linux in their systems.  Maybe not hangs, but it seems unhelpful to 
have a lot of noise spewing over a bus that is supposed to provide 
"management" diagnostics.  Anyway, what I did not find was whether there 
was a particular chipset that provided that port 80 feature on those 
machines.  However, if it's a common "cell" in a design, it may have 
leaked into the notebook market chipsets too.

Anyone know if the Linux kernels used on blade servers have been patched 
to not do the port 80 things?  I don't think this would break anything 
there, but it might have been a helpful patch for their purposes.  I 
don't do blades personally or at work (I focus on mobile devices these 
days, and my personal servers are discrete), so I have no knowledge.

It could be that the blade servers have BIOSes that don't do POST codes 
over port 80, but send them directly to the "drawer" management bus, of 
course.  

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 17:31                                                             ` Pavel Machek
@ 2008-01-01 17:33                                                               ` David P. Reed
  0 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2008-01-01 17:33 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Alan Cox, H. Peter Anvin, Rene Herman, Ingo Molnar, Paul Rolland,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Pavel Machek wrote:
>> 2. there is some "meaning" to certain byte values being written (the
>> _PTS and _WAK use of arguments that come from callers to store into port
>> 80 makes me suspicious.)   That might mean that the freeze happens only
>> when certain values are written, or when they are written closely in
>> time to some other action - being used to communicate something to the
>>     
>
> There's nothing easier than always writing 0 to the 0x80 to check if
> it hangs in such case...?
> 								Pavel
>
>   
I did try that.  Machine in question does hang when you write 0 to 0x80 
in a loop a few thousand times.  This particular suspicion was that the 
problem was caused by the following sort of thing (it's a multi-cpu 
system...)

First, some ACPI code writes "meaningful value" X to  port 80 that is 
sort of a "parameter" to whatever follows.  Just because the DSDT 
disassembly *calls* it the DBUG port doesn't mean it is *only* used for 
debugging.   We (Linux) use it for timing delays, after all...

 then Linux driver writes some random value (!=X) including zero to port 80.

then ACPI writes some other values that cause SMI or some other thing to 
happen,

There are experiments that are not so simple that could rule this 
particular guess out.   I have them on my queue of experiments I might 
try (locking out ACPI).  Of course if the BIOS were GPL, we could look 
at the comments, etc...

I may today pull the laptop apart to see if I can see what chips are on 
it, besides the nvidia chipset and the processor.  That might give a 
clue as to what SuperIO or other logic chips are there.


 

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 17:32                                                               ` David P. Reed
@ 2008-01-01 17:38                                                                 ` Alan Cox
  0 siblings, 0 replies; 243+ messages in thread
From: Alan Cox @ 2008-01-01 17:38 UTC (permalink / raw)
  To: David P. Reed
  Cc: H. Peter Anvin, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

> 80 diagnostic codes and sending them to the "drawer" management 
> processor through a management backplane.   This is a little puzzling, 
> because you'd think they would have noticed port 80 issues, since they 
> run Linux in their systems.  Maybe not hangs, but it seems unhelpful to 

Most of the chipsets let you turn it on and off so presumably the BIOS
turns it off before running Linux. Thats certainly done by several
chipsets and we recently had a bug where a BIOS forgot to turn them off
which confused someones parallel port devices.

> Anyone know if the Linux kernels used on blade servers have been patched 
> to not do the port 80 things?  I don't think this would break anything 

I'm not aware of such, or requests for them.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 17:32                                                                 ` Alan Cox
@ 2008-01-01 18:45                                                                   ` Ingo Molnar
  2008-01-01 20:14                                                                     ` Christer Weinigel
  2008-01-01 21:07                                                                     ` Alan Cox
  0 siblings, 2 replies; 243+ messages in thread
From: Ingo Molnar @ 2008-01-01 18:45 UTC (permalink / raw)
  To: Alan Cox
  Cc: David P. Reed, H. Peter Anvin, Rene Herman, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:

> > there strong counter-arguments against doing the clean thing and 
> > adding an udelay(2) (or udelay(1)) to replace those _p() uses in ISA 
> > drivers?
> 
> #1 udelay has to be for the worst case bus clock (6MHz) while the 
> #device may be at 10Mhz or even 12MHz ISA. So it slows it down stuff
> unneccessarily- and stuff that really really is slow enough as is.

udelay is supposed to be reliable. If someone runs a new kernel and has 
no TSC (which might happen even on modern hardware or with notsc) _and_ 
finds that udelay is not calibrated well enough then that's a kernel bug 
we want to fix.

> #2 Most of the ancient wind up relics with ISA bus don't have a tsc so
> their udelay value is kind of iffy.

iffy in what way? Again, we might be hiding real udelay bugs.

> #3 Not changing it is the lowest risk for a lot of the old ISA code 
> #that never occurs on newer boxes

Not changing the kernel _at all_ is what is the "lowest risk" option. If 
the kernel is changed, it should be tested - and if we have a buggy 
udelay, that should be fixed - because it could cause many other bugs in 
other drivers.

yes, there are always risks in changing something, but using udelay is a 
common-sense consolidation of code.

> > _will_ change a bit, no matter what we do. Alignments change, the 
> > compiler output will change (old compilers get deprecated so a new 
> > compiler might have to be picked), cache effects change - and this 
> > is inevitable. The important thing is to not eliminate the delays - 
> > but we sure dont have to keep them cycle accurate (we couldnt even 
> > if we wanted to). The only way to get the _exact same_ behavior is 
> > to not change the kernel at all.
> 
> ISA bus cycles are *slow*, the subtle processor cache and gcc 
> triggered timing changes are lost in the noise.

gcc triggered timing changes can easily add up to a LOT more - 
especially if a loop is involved and especially on older hardware. 
Remember, 1 microsecond is just a handful of instructions on real old 
hardware. The kernel's timings are _not_ immutable, never were, never 
will be.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 17:32                                                                 ` Christer Weinigel
@ 2008-01-01 18:46                                                                   ` Ingo Molnar
  2008-01-01 19:35                                                                     ` Christer Weinigel
  0 siblings, 1 reply; 243+ messages in thread
From: Ingo Molnar @ 2008-01-01 18:46 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Alan Cox, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol


* Christer Weinigel <christer@weinigel.se> wrote:

> What I'm afraid is that udelay will be significantly slower, [...]

why should it be significantly slower?

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 18:46                                                                   ` Ingo Molnar
@ 2008-01-01 19:35                                                                     ` Christer Weinigel
  2008-01-01 19:59                                                                       ` Rene Herman
                                                                                         ` (2 more replies)
  0 siblings, 3 replies; 243+ messages in thread
From: Christer Weinigel @ 2008-01-01 19:35 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Alan Cox, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On Tue, 1 Jan 2008 19:46:59 +0100
Ingo Molnar <mingo@elte.hu> wrote:

> 
> * Christer Weinigel <christer@weinigel.se> wrote:
> 
> > What I'm afraid is that udelay will be significantly slower, [...]
> 
> why should it be significantly slower?

out 80h, al is only two bytes.  Any alternative that has been suggested
in this discussion will use more space.  mov dx, alt_port; out dx, al
will be larger, a function call will definitely be a lot larger. People
have been making changes to the kernel to save a couple of hundred
bytes of text size.

On old hardware (or anything with an ISA bus which I'd guess includes
the Geode SCx200 SoC which is basically a MediaGX processor, a
southbridge and an ISA bus with a Super I/O chip on it) an out to 80h
will use exactly one ISA cycle.  A call to udelay will need a margin,
so it will be slightly slower.  And that's assuming that you can find
out the speed of the ISA bus, if you can't you'll have to assume the
slowest possible bus (6 MHz I guess) which will be a lot slower.

I don't know if the difference in code size or the udelay will be
significantly slower, but I think it might be.

And to take the MediaGX as an example, the TSC is not usable on that
CPU, so Linux has to use the PIT timer for gettimeofday.  As I wrote
in a different post, I believe the PIT on the SCx200 needs outb_p to
work reliably.  So if outb_p becomes significantly slower that will
affect a critical path on a very common embedded CPU.

I'm not sure what Alan meant with his comments about locking, but if
changing outb_p to use an udelay means that we have to add locking,
that is also going to affect the code size and speed.

  /Christer






^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 19:35                                                                     ` Christer Weinigel
@ 2008-01-01 19:59                                                                       ` Rene Herman
  2008-01-01 20:55                                                                         ` Christer Weinigel
  2008-01-01 21:01                                                                       ` Ingo Molnar
  2008-01-01 21:21                                                                       ` H. Peter Anvin
  2 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2008-01-01 19:59 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Ingo Molnar, Alan Cox, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On 01-01-08 20:35, Christer Weinigel wrote:

> On Tue, 1 Jan 2008 19:46:59 +0100
> Ingo Molnar <mingo@elte.hu> wrote:
> 
>> * Christer Weinigel <christer@weinigel.se> wrote:
>>
>>> What I'm afraid is that udelay will be significantly slower, [...]
>> why should it be significantly slower?
> 
> out 80h, al is only two bytes.  Any alternative that has been suggested
> in this discussion will use more space.  mov dx, alt_port; out dx, al
> will be larger, a function call will definitely be a lot larger. People
> have been making changes to the kernel to save a couple of hundred
> bytes of text size.
> 
> On old hardware (or anything with an ISA bus which I'd guess includes
> the Geode SCx200 SoC which is basically a MediaGX processor, a
> southbridge and an ISA bus with a Super I/O chip on it) an out to 80h
> will use exactly one ISA cycle.

Not to disagree with the point but more like 8 (1 us at 8 MHz). It's the 
timeout property.

> A call to udelay will need a margin,
> so it will be slightly slower.  And that's assuming that you can find
> out the speed of the ISA bus, if you can't you'll have to assume the
> slowest possible bus (6 MHz I guess) which will be a lot slower.
> 
> I don't know if the difference in code size or the udelay will be
> significantly slower, but I think it might be.

There's also the bit about microseconds being very losely defined pre 
loops_per_jiffy calibration. Per CPU-family init helps somewhat but 
certainly for family 6 (Pentium Pro, II, III -- lots of hardware with ISA 
busses therefore) speeds vary quite a bit still.

> And to take the MediaGX as an example, the TSC is not usable on that
> CPU, so Linux has to use the PIT timer for gettimeofday.  As I wrote
> in a different post, I believe the PIT on the SCx200 needs outb_p to
> work reliably.  So if outb_p becomes significantly slower that will
> affect a critical path on a very common embedded CPU.
> 
> I'm not sure what Alan meant with his comments about locking, but if
> changing outb_p to use an udelay means that we have to add locking,
> that is also going to affect the code size and speed.

Explained here:

http://lkml.org/lkml/2007/12/30/136

However, that's not an argument. Missing locking is a bug, and current outb 
I/O delay use hiding it doesn't change that.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 18:45                                                                   ` Ingo Molnar
@ 2008-01-01 20:14                                                                     ` Christer Weinigel
  2008-01-01 21:13                                                                       ` Alan Cox
  2008-01-01 21:07                                                                     ` Alan Cox
  1 sibling, 1 reply; 243+ messages in thread
From: Christer Weinigel @ 2008-01-01 20:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Alan Cox, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On Tue, 1 Jan 2008 19:45:24 +0100
Ingo Molnar <mingo@elte.hu> wrote:

> 
> * Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> 
> > > there strong counter-arguments against doing the clean thing and 
> > > adding an udelay(2) (or udelay(1)) to replace those _p() uses in
> > > ISA drivers?
> > 
> > #1 udelay has to be for the worst case bus clock (6MHz) while the 
> > #device may be at 10Mhz or even 12MHz ISA. So it slows it down stuff
> > unneccessarily- and stuff that really really is slow enough as is.
> 
> udelay is supposed to be reliable. If someone runs a new kernel and
> has no TSC (which might happen even on modern hardware or with notsc)
> _and_ finds that udelay is not calibrated well enough then that's a
> kernel bug we want to fix.

How do you find out the speed of the ISA bus?  AFAIK there is no
standardized way to do that.  On the Geode SC2200 the ISA bus speed is
usually the PCI clock divided by 4 giving 33MHz/4=8.3MHz or
30/4=7.5MHz, but with no external ISA devices it's possible to
overclock the ISA bus to /3 to run it at 11MHz or so.  But without
poking at some CPU and southbridge specific registers to find out the
PCI bus speed and the ISA bus divisor you can't really tell.

So if you do udelay based on a 6MHz clock (I think you can safely
assume that any 386 based system runs the ISA bus at least that fast)
you'll waste at least 30% and maybe even 100% more time for the delay
after every _p call.

  /Christer

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 19:59                                                                       ` Rene Herman
@ 2008-01-01 20:55                                                                         ` Christer Weinigel
  2008-01-01 21:24                                                                           ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: Christer Weinigel @ 2008-01-01 20:55 UTC (permalink / raw)
  To: Rene Herman
  Cc: Ingo Molnar, Alan Cox, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On Tue, 01 Jan 2008 20:59:20 +0100
Rene Herman <rene.herman@keyaccess.nl> wrote:

> On 01-01-08 20:35, Christer Weinigel wrote:
> 
> > On old hardware (or anything with an ISA bus which I'd guess
> > includes the Geode SCx200 SoC which is basically a MediaGX
> > processor, a southbridge and an ISA bus with a Super I/O chip on
> > it) an out to 80h will use exactly one ISA cycle.
> 
> Not to disagree with the point but more like 8 (1 us at 8 MHz). It's
> the timeout property.

Ah, sorry, you're right of course.

> > I'm not sure what Alan meant with his comments about locking, but if
> > changing outb_p to use an udelay means that we have to add locking,
> > that is also going to affect the code size and speed.
> 
> Explained here:
> 
> http://lkml.org/lkml/2007/12/30/136
> 
> However, that's not an argument. Missing locking is a bug, and
> current outb I/O delay use hiding it doesn't change that.

Thanks, I had missed that one.

Regarding Alan's comment:

>For that matter does anyone actually have video cards old enough for us
>to care actually still in use with Linux today ? 

I'm afraid that some PC104 systems may still use ancient video cards.

  /Christer

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 19:35                                                                     ` Christer Weinigel
  2008-01-01 19:59                                                                       ` Rene Herman
@ 2008-01-01 21:01                                                                       ` Ingo Molnar
  2008-01-01 21:26                                                                         ` Alan Cox
  2008-01-01 21:42                                                                         ` Christer Weinigel
  2008-01-01 21:21                                                                       ` H. Peter Anvin
  2 siblings, 2 replies; 243+ messages in thread
From: Ingo Molnar @ 2008-01-01 21:01 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Alan Cox, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol


* Christer Weinigel <christer@weinigel.se> wrote:

> On Tue, 1 Jan 2008 19:46:59 +0100
> Ingo Molnar <mingo@elte.hu> wrote:
> 
> > 
> > * Christer Weinigel <christer@weinigel.se> wrote:
> > 
> > > What I'm afraid is that udelay will be significantly slower, [...]
> > 
> > why should it be significantly slower?
> 
> out 80h, al is only two bytes.  Any alternative that has been 
> suggested in this discussion will use more space.  mov dx, alt_port; 
> out dx, al will be larger, a function call will definitely be a lot 
> larger. People have been making changes to the kernel to save a couple 
> of hundred bytes of text size.

i've done dozens of patches that saved much less of text size, so yes, i 
very much care about code size. But it has been stated in this thread 
that most of the _p() API uses in the kernel today are bogus. So 
eventually getting rid of the bogus ones will be a net code size 
_reduction_. (But even that is besides the point, we prefer clean and 
easier to maintain code.)

> I don't know if the difference in code size or the udelay will be 
> significantly slower, but I think it might be.

ok, "I dont know but it might be slower" is a perfectly fine statement 
instead of your original "it will be slower".

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 18:45                                                                   ` Ingo Molnar
  2008-01-01 20:14                                                                     ` Christer Weinigel
@ 2008-01-01 21:07                                                                     ` Alan Cox
  2008-01-02 10:04                                                                       ` Ingo Molnar
  1 sibling, 1 reply; 243+ messages in thread
From: Alan Cox @ 2008-01-01 21:07 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: David P. Reed, H. Peter Anvin, Rene Herman, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

> > #1 udelay has to be for the worst case bus clock (6MHz) while the 
> > #device may be at 10Mhz or even 12MHz ISA. So it slows it down stuff
> > unneccessarily- and stuff that really really is slow enough as is.
> 
> udelay is supposed to be reliable. If someone runs a new kernel and has 
> no TSC (which might happen even on modern hardware or with notsc) _and_ 
> finds that udelay is not calibrated well enough then that's a kernel bug 
> we want to fix.

You miss the point entirely. The delay is in bus clocks not CPU clocks,
not tsc clocks not PIT clocks, and it is permitted to vary by a factor of
two. So you'll worst case halve the speed of network packet up/download
even if your udelay is accurate.

> > #2 Most of the ancient wind up relics with ISA bus don't have a tsc so
> > their udelay value is kind of iffy.
> 
> iffy in what way? Again, we might be hiding real udelay bugs.

As you say - its only a few instructions so small udelays tend to be
inaccurate - overlong.

> yes, there are always risks in changing something, but using udelay is a 
> common-sense consolidation of code.

Not for ISA bus hardware. For chipset logic, for PCI yes - for ISA stuff
no. It's all about ISA clocks not wall clocks.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 20:14                                                                     ` Christer Weinigel
@ 2008-01-01 21:13                                                                       ` Alan Cox
  0 siblings, 0 replies; 243+ messages in thread
From: Alan Cox @ 2008-01-01 21:13 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Ingo Molnar, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

> How do you find out the speed of the ISA bus?  AFAIK there is no
> standardized way to do that.  On the Geode SC2200 the ISA bus speed is

It is per chipset magic registers. Fun fun fun

> usually the PCI clock divided by 4 giving 33MHz/4=8.3MHz or
> 30/4=7.5MHz, but with no external ISA devices it's possible to
> overclock the ISA bus to /3 to run it at 11MHz or so.  But without

12MHz is valid for ISA although not a good idea - even IBM issued some
systems with 12MHz ISA before discovering many vendors had assumed 8 was
it.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 16:15                                                             ` Alan Cox
  2008-01-01 16:43                                                               ` Ingo Molnar
  2008-01-01 17:32                                                               ` David P. Reed
@ 2008-01-01 21:15                                                               ` H. Peter Anvin
  2008-01-01 21:35                                                                 ` Rene Herman
  2 siblings, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-01 21:15 UTC (permalink / raw)
  To: Alan Cox
  Cc: David P. Reed, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Alan Cox wrote:
>> 80 makes me suspicious.)   That might mean that the freeze happens only
>> when certain values are written, or when they are written closely in
>> time to some other action - being used to communicate something to the
>> SMM code).   If there is some race in when Linux's port 80 writes happen
>> that happen to change the meaning of a request to the hardware or to
>> SMM, then we could be rarely stepping on
> 
> That does imply some muppet 'extended' the debug interface for power
> management on your laptop. Also pretty much proves that for such systems
> we do have to move from port 0x80 to another delay approach.
> 
> Ingo - the fact that so many ISA bus devices need _p to mean "ISA bus
> clocks" says to me we should keep the _p port 0x80 using variant for old
> systems/device combinations (eg ISA ethernet cards) which won't show up
> in any problem system (we know this from 15 odd years of testing), but
> stop using it for PCI and embedded devices on modern systems.
> 

I have mentioned this before... I think writing zero to port 0xf0 would 
be an acceptable pause interface (to the extent where we need an I/O 
port) except on 386 with 387 present; on those systems we can fall back 
to 0x80.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 15:57                                                           ` David P. Reed
@ 2008-01-01 21:16                                                             ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-01 21:16 UTC (permalink / raw)
  To: David P. Reed
  Cc: Alan Cox, Rene Herman, Ingo Molnar, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

David P. Reed wrote:
> Alan, thank you for the pointers.  I have been doing variations on this 
> testing theme for a while - I get intrigued by a good debugging 
> challenge, and after all it's my machine...
> 
> Two relevant new data points, and then some more suggestions:
> 
> 1. It appears to be a real port.  SMI traps are not happening in the 
> normal outb to 80.  Hundreds of them execute perfectly with the expected 
> instruction counts.  If I can trace the particular event that creates 
> the hard freeze (getting really creative, here) and stop before the 
> freeze disables the entire computer, I will.  That may be an SMI, or 
> perhaps any other kind of interrupt or exception.  Maybe someone knows 
> how to safely trace through an impending SMI while doing printk's or 
> something?
> 
> 2. It appears to be the standard POST diagnostic port.  On a whim, I 
> disassembled my DSDT code, and studied it more closely.   It turns out 
> that there are a bunch of "Store(..., DBUG)" instructions scattered 
> throughout, and when you look at what DBUG is defined as, it is defined 
> as an IO Port at IO address DBGP, which is a 1-byte value = 0x80.  So 
> the ACPI BIOS thinks it has something to do with debugging.   There's a 
> little strangeness here, however, because the value sent to the port 
> occasionally has something to do with arguments to the ACPI operations 
> relating to sleep and wakeup ...  could just be that those arguments are 
> distinctive.
> 

Dumb question: if you change your iodelay function so it always writes 
zero to port 0x80, does it start working?

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 19:35                                                                     ` Christer Weinigel
  2008-01-01 19:59                                                                       ` Rene Herman
  2008-01-01 21:01                                                                       ` Ingo Molnar
@ 2008-01-01 21:21                                                                       ` H. Peter Anvin
  2008-01-01 23:05                                                                         ` Christer Weinigel
  2008-01-02 10:00                                                                         ` Ingo Molnar
  2 siblings, 2 replies; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-01 21:21 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Ingo Molnar, Alan Cox, David P. Reed, Rene Herman, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Christer Weinigel wrote:
> 
> out 80h, al is only two bytes.  Any alternative that has been suggested
> in this discussion will use more space.  mov dx, alt_port; out dx, al
> will be larger, a function call will definitely be a lot larger. People
> have been making changes to the kernel to save a couple of hundred
> bytes of text size.
> 

If text size becomes a problem in this case, then we can use an 
alternatives-like mechanism to fix up the kernel.  However, 
realistically this probably should be a function call *combined with* 
the out and in; that reduces the impact somewhat.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 20:55                                                                         ` Christer Weinigel
@ 2008-01-01 21:24                                                                           ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-01 21:24 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Rene Herman, Ingo Molnar, Alan Cox, David P. Reed, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

Christer Weinigel wrote:
> 
>> For that matter does anyone actually have video cards old enough for us
>> to care actually still in use with Linux today ? 
> 
> I'm afraid that some PC104 systems may still use ancient video cards.
> 

PC/104 is actual ISA, not even LPC...

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:01                                                                       ` Ingo Molnar
@ 2008-01-01 21:26                                                                         ` Alan Cox
  2008-01-01 21:42                                                                         ` Christer Weinigel
  1 sibling, 0 replies; 243+ messages in thread
From: Alan Cox @ 2008-01-01 21:26 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Christer Weinigel, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

> very much care about code size. But it has been stated in this thread 
> that most of the _p() API uses in the kernel today are bogus. So 

You missed a word "wrongly". It has been "wrongly stated"

I've been going through the ISA cases which are the majority. Generally
speaking they are correct. We have a couple of "interesting" PCI users
who most definitely want udelay() or removal of _p. We have various
chipset cases which want looking at in detail. The ISA drivers however
are both the main user and mostly right.

> ok, "I dont know but it might be slower" is a perfectly fine statement 
> instead of your original "it will be slower".

If you use wall clock timings it will be slower.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:15                                                               ` H. Peter Anvin
@ 2008-01-01 21:35                                                                 ` Rene Herman
  2008-01-01 21:44                                                                   ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2008-01-01 21:35 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Alan Cox, David P. Reed, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

[-- Attachment #1: Type: text/plain, Size: 858 bytes --]

On 01-01-08 22:15, H. Peter Anvin wrote:

> I have mentioned this before... I think writing zero to port 0xf0 would 
> be an acceptable pause interface (to the extent where we need an I/O 
> port) except on 386 with 387 present; on those systems we can fall back 
> to 0x80.

PII 400 / Intel 440 BX (PIIX4):

rene@6bap:~/port80$ su -c ./portime
out 0x80: 544 cycles
in  0x80: 254 cycles
in  0x61: 254 cycles
out 0xf0: 544 cycles

The Intel PIIX/PIIX3 datasheet specifically mentions that both reads and 
writes at 0xf0 "flow through to the ISA bus".

However, more complete, it says:

"Writing to this register causes the PIIX/PIIX3 to assert IGNNE#. The 
PIIX/PIIX3 also negates IRQ13 (internal to the PIIX). Note that IGNNE# is 
not asserted unless FERR# is active. Reads/writes flow through to the ISA bus".

We don't want the side-effects, do we?

Rene.

[-- Attachment #2: portime.c --]
[-- Type: text/plain, Size: 1513 bytes --]

/* gcc -W -Wall -O2 -o portime portime.c */

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#include <sys/io.h>

#define LOOPS 10000

inline uint64_t rdtsc(void)
{
	uint32_t hi, lo;

	asm ("rdtsc": "=d" (hi), "=a" (lo));

	return (uint64_t)hi << 32 | lo;
}

inline void serialize(void)
{
	asm ("cpuid": : : "eax", "ebx", "ecx", "edx");
}

int main(void)
{
	uint64_t tsc0, tsc1, tsc2, tsc3, tsc4, tsc5;
	uint64_t out80, in80, in61, outf0;
	int i;

	if (iopl(3) < 0) {
		perror("iopl");
		return EXIT_FAILURE;
	}

	asm ("cli");
	tsc0 = rdtsc();
	for (i = 0; i < LOOPS; i++) {
	 	serialize();	
		serialize();
	}
	tsc1 = rdtsc();
	for (i = 0; i < LOOPS; i++) {
		serialize();
		asm ("outb %al, $0x80");
		serialize();
	}
	tsc2 = rdtsc();
	for (i = 0; i < LOOPS; i++) {
		serialize();
		asm ("inb $0x80, %%al": : : "al");
		serialize();
	}
	tsc3 = rdtsc();
	for (i = 0; i < LOOPS; i++) {
		serialize();
		asm ("inb $0x61, %%al": : : "al");
		serialize();
	}
	tsc4 = rdtsc();
	for (i = 0; i < LOOPS; i++) {
		serialize();
		asm ("outb %b0, $0xf0": : "a" (0));
		serialize();
	}
	tsc5 = rdtsc();
	asm ("sti");

	out80 = ((tsc2 - tsc1) - (tsc1 - tsc0)) / LOOPS;
	in80  = ((tsc3 - tsc2) - (tsc1 - tsc0)) / LOOPS;
	in61  = ((tsc4 - tsc3) - (tsc1 - tsc0)) / LOOPS;
	outf0 = ((tsc5 - tsc4) - (tsc1 - tsc0)) / LOOPS;

	printf("out 0x80: %llu cycles\n", out80);
	printf("in  0x80: %llu cycles\n", in80);
	printf("in  0x61: %llu cycles\n", in61);
	printf("out 0xf0: %llu cycles\n", outf0);

	return EXIT_SUCCESS;
}

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:01                                                                       ` Ingo Molnar
  2008-01-01 21:26                                                                         ` Alan Cox
@ 2008-01-01 21:42                                                                         ` Christer Weinigel
  2008-01-01 21:42                                                                           ` Rene Herman
  2008-01-01 21:50                                                                           ` H. Peter Anvin
  1 sibling, 2 replies; 243+ messages in thread
From: Christer Weinigel @ 2008-01-01 21:42 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Alan Cox, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On Tue, 1 Jan 2008 22:01:43 +0100
Ingo Molnar <mingo@elte.hu> wrote:

> > out 80h, al is only two bytes.  Any alternative that has been 
> > suggested in this discussion will use more space.  mov dx,
> > alt_port; out dx, al will be larger, a function call will
> > definitely be a lot larger. People have been making changes to the
> > kernel to save a couple of hundred bytes of text size.
> 
> i've done dozens of patches that saved much less of text size, so
> yes, i very much care about code size. But it has been stated in this
> thread that most of the _p() API uses in the kernel today are bogus.
> So eventually getting rid of the bogus ones will be a net code size 
> _reduction_. (But even that is besides the point, we prefer clean and 
> easier to maintain code.)

And once again, the _p in the code that talks to the PIT is very much
non-bogus.  And it is a critical path that's called a lot.  The i8253
PIT and the i8259 interrupt controller are probably the only ones that
are relevant on a modern machine, and it seems that even some fairly
modern chipsets have limitations on how fast you can drive them.

BTW, I just checked the Intel M8253 data sheet (dead tree variant), and
it says under A.C Characteristics, READ CYCLE:

    Recovery Time Between /READ and Any Other Control Signal: 1 us

So at least for the original M8253 a udelay(1) might be more
appropriate than outb_p, since the delay is not expressed in clock
cycles but absolute time.

The data sheet for the Intel M8259A says:

    End of /RD to Next Command: 300 ns
    End of /WR to Next Command: 370 ns

On the other hand, I don't know how all the i8253/i8259 clones or the
numerous variants of Super I/O chips behave.  It wouldn't surprise me
if some Super I/O chip uses the ISA bus clock to latch the values
internally so that the delay is dependent on the bus frequency instead.

> > I don't know if the difference in code size or the udelay will be 
> > significantly slower, but I think it might be.
> 
> ok, "I dont know but it might be slower" is a perfectly fine
> statement instead of your original "it will be slower".

I didn't say that, I said I'm afraid it will be slower. :-)

  /Christer

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:42                                                                         ` Christer Weinigel
@ 2008-01-01 21:42                                                                           ` Rene Herman
  2008-01-01 21:50                                                                           ` H. Peter Anvin
  1 sibling, 0 replies; 243+ messages in thread
From: Rene Herman @ 2008-01-01 21:42 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Ingo Molnar, Alan Cox, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On 01-01-08 22:42, Christer Weinigel wrote:

> The data sheet for the Intel M8259A says:
> 
>     End of /RD to Next Command: 300 ns
>     End of /WR to Next Command: 370 ns
> 
> On the other hand, I don't know how all the i8253/i8259 clones or the
> numerous variants of Super I/O chips behave.  It wouldn't surprise me
> if some Super I/O chip uses the ISA bus clock to latch the values
> internally so that the delay is dependent on the bus frequency instead.

I wouldn't even be surprised if most all would...

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:35                                                                 ` Rene Herman
@ 2008-01-01 21:44                                                                   ` H. Peter Anvin
  2008-01-01 22:35                                                                     ` Rene Herman
  2008-01-09 17:27                                                                     ` Maciej W. Rozycki
  0 siblings, 2 replies; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-01 21:44 UTC (permalink / raw)
  To: Rene Herman
  Cc: Alan Cox, David P. Reed, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> On 01-01-08 22:15, H. Peter Anvin wrote:
> 
>> I have mentioned this before... I think writing zero to port 0xf0 
>> would be an acceptable pause interface (to the extent where we need an 
>> I/O port) except on 386 with 387 present; on those systems we can fall 
>> back to 0x80.
> 
> PII 400 / Intel 440 BX (PIIX4):
> 
> rene@6bap:~/port80$ su -c ./portime
> out 0x80: 544 cycles
> in  0x80: 254 cycles
> in  0x61: 254 cycles
> out 0xf0: 544 cycles
> 
> The Intel PIIX/PIIX3 datasheet specifically mentions that both reads and 
> writes at 0xf0 "flow through to the ISA bus".
> 
> However, more complete, it says:
> 
> "Writing to this register causes the PIIX/PIIX3 to assert IGNNE#. The 
> PIIX/PIIX3 also negates IRQ13 (internal to the PIIX). Note that IGNNE# 
> is not asserted unless FERR# is active. Reads/writes flow through to the 
> ISA bus".
> 
> We don't want the side-effects, do we?
> 

Yes, we do.  It's exactly this side effect which makes this safer than 
either 0x80 or 0xED -- it's a port that *guaranteed* can't be reclaimed 
for other purposes without breaking MS-DOS compatibility.

It's specifically a side effect *we don't care about*, except in the 
by-now-somewhat-exotic case of 386+387 (where we indeed can't use it 
once user code has touched the FPU -- but we can fall back to 0x80 on 
those, a very small number of systems.)  486+ doesn't use this interface 
under Linux, since Linux uses the proper exception path on those 
processors.  If Compaq had wired up the proper signals on the first 386 
PC motherboards, we wouldn't have cared about it on the 386 either.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:42                                                                         ` Christer Weinigel
  2008-01-01 21:42                                                                           ` Rene Herman
@ 2008-01-01 21:50                                                                           ` H. Peter Anvin
  1 sibling, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-01 21:50 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Ingo Molnar, Alan Cox, David P. Reed, Rene Herman, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Christer Weinigel wrote:
> 
> And once again, the _p in the code that talks to the PIT is very much
> non-bogus.  And it is a critical path that's called a lot.  The i8253
> PIT and the i8259 interrupt controller are probably the only ones that
> are relevant on a modern machine, and it seems that even some fairly
> modern chipsets have limitations on how fast you can drive them.
> 

I actually analyzed the case of the PIT in the case of the 
implementation of a real chipset.  In our case, running the PIT at 
1.19318 MHz when the rest of the chipset core was running at 100 MHz 
introduced a huge amount of extra complexity and we really wanted to get 
rid of it.  As it turns out, the PIT interface is ill-defined if run at 
a higher frequency; you can get undefined values as a result of a write 
followed by a read if there is no intervening PIT clock, which of course 
in the standard interface never happens.  So in the end, we had to build 
all the synchronizers, backpressure controls and other crap that went 
along with an additional clock domain.

As a result of that experience, I really don't think you will *ever* see 
a PIT that runs at a modern frequency.

Building a 100 MHz PIC, however, was not a problem, and being able to 
sink accesses at full speed meant we didn't have to implement flow control.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:44                                                                   ` H. Peter Anvin
@ 2008-01-01 22:35                                                                     ` Rene Herman
  2008-01-01 22:39                                                                       ` H. Peter Anvin
  2008-01-09 17:27                                                                     ` Maciej W. Rozycki
  1 sibling, 1 reply; 243+ messages in thread
From: Rene Herman @ 2008-01-01 22:35 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Alan Cox, David P. Reed, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

[-- Attachment #1: Type: text/plain, Size: 1633 bytes --]

On 01-01-08 22:44, H. Peter Anvin wrote:

> Rene Herman wrote:
>> On 01-01-08 22:15, H. Peter Anvin wrote:
>>
>>> I have mentioned this before... I think writing zero to port 0xf0 
>>> would be an acceptable pause interface (to the extent where we need 
>>> an I/O port) except on 386 with 387 present; on those systems we can 
>>> fall back to 0x80.
>>
>> PII 400 / Intel 440 BX (PIIX4):
>>
>> rene@6bap:~/port80$ su -c ./portime
>> out 0x80: 544 cycles
>> in  0x80: 254 cycles
>> in  0x61: 254 cycles
>> out 0xf0: 544 cycles
>>
>> The Intel PIIX/PIIX3 datasheet specifically mentions that both reads 
>> and writes at 0xf0 "flow through to the ISA bus".
>>
>> However, more complete, it says:
>>
>> "Writing to this register causes the PIIX/PIIX3 to assert IGNNE#. The 
>> PIIX/PIIX3 also negates IRQ13 (internal to the PIIX). Note that IGNNE# 
>> is not asserted unless FERR# is active. Reads/writes flow through to 
>> the ISA bus".
>>
>> We don't want the side-effects, do we?
>>
> 
> Yes, we do.  It's exactly this side effect which makes this safer than 
> either 0x80 or 0xED -- it's a port that *guaranteed* can't be reclaimed 
> for other purposes without breaking MS-DOS compatibility.

I see that with CR0.NE set (*) we indeed don't care about IGNNE#...

However, I'm worried about this comment in arch/x86/kernel/i8259_32.c

===
/*
  * New motherboards sometimes make IRQ 13 be a PCI interrupt,
  * so allow interrupt sharing.
  */
===

Is it really safe to just blindly negate IRQ13 on everything out there, from 
regular PC through funky embedded thingies?

(*) bit 5:

rene@7ixe4:~/src/local$ ./smsw
msw: 0x3b

Rene.

[-- Attachment #2: smsw.c --]
[-- Type: text/plain, Size: 180 bytes --]

/* gcc -W -Wall -o smsw smsw.c */

#include <stdio.h>
#include <stdint.h>

int main(void)
{
	uint16_t msw;

	asm ("smsw %0": "=r" (msw));
	printf("msw: %#hx\n", msw);
	return 0;
}

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 22:35                                                                     ` Rene Herman
@ 2008-01-01 22:39                                                                       ` H. Peter Anvin
  2008-01-01 23:11                                                                         ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-01 22:39 UTC (permalink / raw)
  To: Rene Herman
  Cc: Alan Cox, David P. Reed, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
>>
>> Yes, we do.  It's exactly this side effect which makes this safer than 
>> either 0x80 or 0xED -- it's a port that *guaranteed* can't be 
>> reclaimed for other purposes without breaking MS-DOS compatibility.
> 
> I see that with CR0.NE set (*) we indeed don't care about IGNNE#...
> 
> However, I'm worried about this comment in arch/x86/kernel/i8259_32.c
> 
> ===
> /*
>  * New motherboards sometimes make IRQ 13 be a PCI interrupt,
>  * so allow interrupt sharing.
>  */
> ===
> 
> Is it really safe to just blindly negate IRQ13 on everything out there, 
> from regular PC through funky embedded thingies?
> 

It's not any IRQ 13, it's IRQ 13 from the FPU.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:21                                                                       ` H. Peter Anvin
@ 2008-01-01 23:05                                                                         ` Christer Weinigel
  2008-01-01 23:12                                                                           ` Alan Cox
  2008-01-02 10:00                                                                         ` Ingo Molnar
  1 sibling, 1 reply; 243+ messages in thread
From: Christer Weinigel @ 2008-01-01 23:05 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Ingo Molnar, Alan Cox, David P. Reed, Rene Herman, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Tue, 01 Jan 2008 13:21:47 -0800
"H. Peter Anvin" <hpa@zytor.com> wrote:

> Christer Weinigel wrote:
> > 
> > out 80h, al is only two bytes.  Any alternative that has been
> > suggested in this discussion will use more space.  mov dx,
> > alt_port; out dx, al will be larger, a function call will
> > definitely be a lot larger. People have been making changes to the
> > kernel to save a couple of hundred bytes of text size.
> 
> If text size becomes a problem in this case, then we can use an 
> alternatives-like mechanism to fix up the kernel.  However, 
> realistically this probably should be a function call *combined with* 
> the out and in; that reduces the impact somewhat.

That's a very good point.  So for the PIT it should be possible to have
two clocksources, one with the _p and one without, that one can switch
between with a kernel command line option.  So there shouldn't be any
slowdown at all due to that.

The i8259 init code is not time critical, so should be able to use a
"reasonable" delay.  

Besides the above there are only a handful of _p uses outside of real
ISA device drivers, and those should not be relevant for a modern PC
unless somebody wants to use an 8390 based PCMCIA card, but we could
tell them "don't do that then".

But I'd better shut up and let Alan continue on his review of the _p
use in the drivers.

  /Christer



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 22:39                                                                       ` H. Peter Anvin
@ 2008-01-01 23:11                                                                         ` Rene Herman
  2008-01-02  0:25                                                                           ` Rene Herman
  2008-01-02  0:55                                                                           ` Christer Weinigel
  0 siblings, 2 replies; 243+ messages in thread
From: Rene Herman @ 2008-01-01 23:11 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Alan Cox, David P. Reed, Rene Herman, Ingo Molnar, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 01-01-08 23:39, H. Peter Anvin wrote:

>>> Yes, we do.  It's exactly this side effect which makes this safer 
>>> than either 0x80 or 0xED -- it's a port that *guaranteed* can't be 
>>> reclaimed for other purposes without breaking MS-DOS compatibility.
>>
>> I see that with CR0.NE set (*) we indeed don't care about IGNNE#...
>>
>> However, I'm worried about this comment in arch/x86/kernel/i8259_32.c
>>
>> ===
>> /*
>>  * New motherboards sometimes make IRQ 13 be a PCI interrupt,
>>  * so allow interrupt sharing.
>>  */
>> ===
>>
>> Is it really safe to just blindly negate IRQ13 on everything out 
>> there, from regular PC through funky embedded thingies?
> 
> It's not any IRQ 13, it's IRQ 13 from the FPU.

Well, on the PIIX it is and I guess on anything where it's _not_ fully 
internal an 0xf0 write wouldn't have any effect on IRQ13...

When you earlier mentioned this it seemed 0xed switched on DMI would be good 
enough, but well.

Alan, do you have an opinion on the port 0xf0 write? It should probably 
still be combined with a replacement/deletion for new machines due to the 
bus-locking "bad for real-time" thing you mentioned earlier but in the short 
run it could be a fairly low-impact replacement on anything except a 386+387

We should do a another timing measurement survey and it makes for sligtly 
worse code if we indeed feel it's not safe enough to write anything other 
than 0, but otherwise it's quite minimal.

Rene.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 23:05                                                                         ` Christer Weinigel
@ 2008-01-01 23:12                                                                           ` Alan Cox
  2008-01-02  0:23                                                                             ` Christer Weinigel
  0 siblings, 1 reply; 243+ messages in thread
From: Alan Cox @ 2008-01-01 23:12 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: H. Peter Anvin, Ingo Molnar, David P. Reed, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

> Besides the above there are only a handful of _p uses outside of real
> ISA device drivers, and those should not be relevant for a modern PC
> unless somebody wants to use an 8390 based PCMCIA card, but we could
> tell them "don't do that then".

We need to build 8390.c twice anyway - once for PCI once for ISA with the
_p changes whichever way it gets done. PCMCIA can use whichever we decide
is right. Anyone know if PCMCIA is guaranteed to be 8MHz ?

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 23:12                                                                           ` Alan Cox
@ 2008-01-02  0:23                                                                             ` Christer Weinigel
  0 siblings, 0 replies; 243+ messages in thread
From: Christer Weinigel @ 2008-01-02  0:23 UTC (permalink / raw)
  To: Alan Cox
  Cc: H. Peter Anvin, Ingo Molnar, David P. Reed, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On Tue, 1 Jan 2008 23:12:50 +0000
Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:

> > Besides the above there are only a handful of _p uses outside of
> > real ISA device drivers, and those should not be relevant for a
> > modern PC unless somebody wants to use an 8390 based PCMCIA card,
> > but we could tell them "don't do that then".
> 
> We need to build 8390.c twice anyway - once for PCI once for ISA with
> the _p changes whichever way it gets done. PCMCIA can use whichever
> we decide is right. Anyone know if PCMCIA is guaranteed to be 8MHz ?

It's not.  It's perfectly ok to drive a PCMCIA bus slower than that,
IIRC we used a much slower clock speed than that on a StrongARM
platform I worked a couple of years ago.  

The PCMCIA CIS (Card information services) allows the following device
speeds: 100, 150, 200 and 250 ns.  The memory card spec also allows 600
and 300 ns.  The standard I/O card cycle speed is 255 ns.  I believe
that is "the shortest access time for a read/write cycle", and I can't
tell if that is comparable to one ISA clock cycles or if it's
comparable to 8 ISA bus cycles.

On the other hand, there is no clock line in a PCMCIA connector, so for
PCMCIA devices any delays should be absolute times, or based on some
clock that is internal to the card.  How that fits with the 8390 data
sheet talking about bus clocks, I don't know.

  /Christer

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 23:11                                                                         ` Rene Herman
@ 2008-01-02  0:25                                                                           ` Rene Herman
  2008-01-02  0:55                                                                           ` Christer Weinigel
  1 sibling, 0 replies; 243+ messages in thread
From: Rene Herman @ 2008-01-02  0:25 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Alan Cox, David P. Reed, Ingo Molnar, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 02-01-08 00:11, Rene Herman wrote:

> On 01-01-08 23:39, H. Peter Anvin wrote:
> 
>>>> Yes, we do.  It's exactly this side effect which makes this safer 
>>>> than either 0x80 or 0xED -- it's a port that *guaranteed* can't be 
>>>> reclaimed for other purposes without breaking MS-DOS compatibility.
>>>
>>> I see that with CR0.NE set (*) we indeed don't care about IGNNE#...
>>>
>>> However, I'm worried about this comment in arch/x86/kernel/i8259_32.c
>>>
>>> ===
>>> /*
>>>  * New motherboards sometimes make IRQ 13 be a PCI interrupt,
>>>  * so allow interrupt sharing.
>>>  */
>>> ===
>>>
>>> Is it really safe to just blindly negate IRQ13 on everything out 
>>> there, from regular PC through funky embedded thingies?
>>
>> It's not any IRQ 13, it's IRQ 13 from the FPU.
> 
> Well, on the PIIX it is and I guess on anything where it's _not_ fully 
> internal an 0xf0 write wouldn't have any effect on IRQ13...
> 
> When you earlier mentioned this it seemed 0xed switched on DMI would be 
> good enough, but well.
> 
> Alan, do you have an opinion on the port 0xf0 write? It should probably 
> still be combined with a replacement/deletion for new machines due to 
> the bus-locking "bad for real-time" thing you mentioned earlier but in 
> the short run it could be a fairly low-impact replacement on anything 
> except a 386+387
> 
> We should do a another timing measurement survey and it makes for 
> sligtly worse code if we indeed feel it's not safe enough to write 
> anything other than 0, but otherwise it's quite minimal.

Thinking about this, my main worry about 0xf0 as a 0x80 replacement would be 
systems that have elected to _not_ let port 0xf0 writes flow through to ISA 
changing the timing-characteristics. Given that it's a known port, someone 
may have elected to just keep it fully internal.

Upto now the datasheets I've read do put it on ISA...

Rene.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 23:11                                                                         ` Rene Herman
  2008-01-02  0:25                                                                           ` Rene Herman
@ 2008-01-02  0:55                                                                           ` Christer Weinigel
  2008-01-02  1:00                                                                             ` Rene Herman
  2008-01-02  2:27                                                                             ` H. Peter Anvin
  1 sibling, 2 replies; 243+ messages in thread
From: Christer Weinigel @ 2008-01-02  0:55 UTC (permalink / raw)
  To: Rene Herman
  Cc: H. Peter Anvin, Alan Cox, David P. Reed, Rene Herman, Ingo Molnar,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On Wed, 02 Jan 2008 00:11:54 +0100
Rene Herman <rene.herman@keyaccess.nl> wrote:

> Well, on the PIIX it is and I guess on anything where it's _not_
> fully internal an 0xf0 write wouldn't have any effect on IRQ13...
> 
> When you earlier mentioned this it seemed 0xed switched on DMI would
> be good enough, but well.
> 
> Alan, do you have an opinion on the port 0xf0 write? It should
> probably still be combined with a replacement/deletion for new
> machines due to the bus-locking "bad for real-time" thing you
> mentioned earlier but in the short run it could be a fairly
> low-impact replacement on anything except a 386+387

Both 0xed and 0xf0 are mapped to internal functions on the AMD Elan
SC400 processor.  It is an AMD 486 based system on a chip and since AMD
just knew that it would never have a math coprocessor, they reused the
0xf0-0xf2 range for the PCMCIA controller.  I guess the AMD Elan SC500
will have similar problems.

I seem to recall that back when I was working with the Elan SC400
(sometime around 1998?) there were discussions about finding an
alternate delay port because outb to 0x80 messed up the debug port.  I
think the Elan stopped those discussions because just about every port
on the Elan was reused for some alternate purpose.  

  /Christer

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-02  0:55                                                                           ` Christer Weinigel
@ 2008-01-02  1:00                                                                             ` Rene Herman
  2008-01-02  2:27                                                                             ` H. Peter Anvin
  1 sibling, 0 replies; 243+ messages in thread
From: Rene Herman @ 2008-01-02  1:00 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: H. Peter Anvin, Alan Cox, David P. Reed, Rene Herman, Ingo Molnar,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On 02-01-08 01:55, Christer Weinigel wrote:

> On Wed, 02 Jan 2008 00:11:54 +0100
> Rene Herman <rene.herman@keyaccess.nl> wrote:
> 
>> Well, on the PIIX it is and I guess on anything where it's _not_
>> fully internal an 0xf0 write wouldn't have any effect on IRQ13...
>>
>> When you earlier mentioned this it seemed 0xed switched on DMI would
>> be good enough, but well.
>>
>> Alan, do you have an opinion on the port 0xf0 write? It should
>> probably still be combined with a replacement/deletion for new
>> machines due to the bus-locking "bad for real-time" thing you
>> mentioned earlier but in the short run it could be a fairly
>> low-impact replacement on anything except a 386+387
> 
> Both 0xed and 0xf0 are mapped to internal functions on the AMD Elan
> SC400 processor.  It is an AMD 486 based system on a chip and since AMD
> just knew that it would never have a math coprocessor, they reused the
> 0xf0-0xf2 range for the PCMCIA controller.  I guess the AMD Elan SC500
> will have similar problems.
> 
> I seem to recall that back when I was working with the Elan SC400
> (sometime around 1998?) there were discussions about finding an
> alternate delay port because outb to 0x80 messed up the debug port.  I
> think the Elan stopped those discussions because just about every port
> on the Elan was reused for some alternate purpose.  

Okay, thanks much. So 0xf0 would be unuseable on 386+387 and AMD Elan SC400 
and could possibly change timing on an unknown number of systems due to not 
being put on the bus.

0x80 only fails for some recent HP laptops instead so it seems there would 
be not enough cause to go with 0xf0 onstead of 0x80 as the default choice; 
if we're quirking around machines anyway it might as well be the DMI based 
quirking currently suggested.

Rene.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-02  0:55                                                                           ` Christer Weinigel
  2008-01-02  1:00                                                                             ` Rene Herman
@ 2008-01-02  2:27                                                                             ` H. Peter Anvin
  1 sibling, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-02  2:27 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Rene Herman, Alan Cox, David P. Reed, Rene Herman, Ingo Molnar,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

Christer Weinigel wrote:
> 
> Both 0xed and 0xf0 are mapped to internal functions on the AMD Elan
> SC400 processor.  It is an AMD 486 based system on a chip and since AMD
> just knew that it would never have a math coprocessor, they reused the
> 0xf0-0xf2 range for the PCMCIA controller.  I guess the AMD Elan SC500
> will have similar problems.
> 
> I seem to recall that back when I was working with the Elan SC400
> (sometime around 1998?) there were discussions about finding an
> alternate delay port because outb to 0x80 messed up the debug port.  I
> think the Elan stopped those discussions because just about every port
> on the Elan was reused for some alternate purpose.  
> 

Yeah, the Elan is not supportable anyway without a CONFIG option (it's 
broken in so many ways), so it doesn't really apply.  It's a fuckwit design.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:21                                                                       ` H. Peter Anvin
  2008-01-01 23:05                                                                         ` Christer Weinigel
@ 2008-01-02 10:00                                                                         ` Ingo Molnar
  1 sibling, 0 replies; 243+ messages in thread
From: Ingo Molnar @ 2008-01-02 10:00 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Christer Weinigel, Alan Cox, David P. Reed, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol


* H. Peter Anvin <hpa@zytor.com> wrote:

> Christer Weinigel wrote:
>>
>> out 80h, al is only two bytes.  Any alternative that has been suggested
>> in this discussion will use more space.  mov dx, alt_port; out dx, al
>> will be larger, a function call will definitely be a lot larger. People
>> have been making changes to the kernel to save a couple of hundred
>> bytes of text size.
>>
>
> If text size becomes a problem in this case, then we can use an 
> alternatives-like mechanism to fix up the kernel.  However, 
> realistically this probably should be a function call *combined with* 
> the out and in; that reduces the impact somewhat.

and that's exactly what x86.git#mm does now.

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:07                                                                     ` Alan Cox
@ 2008-01-02 10:04                                                                       ` Ingo Molnar
  2008-01-02 13:11                                                                         ` [linux-kernel] " David P. Reed
  2008-01-02 13:47                                                                         ` Alan Cox
  0 siblings, 2 replies; 243+ messages in thread
From: Ingo Molnar @ 2008-01-02 10:04 UTC (permalink / raw)
  To: Alan Cox
  Cc: David P. Reed, H. Peter Anvin, Rene Herman, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:

> > udelay is supposed to be reliable. If someone runs a new kernel and 
> > has no TSC (which might happen even on modern hardware or with 
> > notsc) _and_ finds that udelay is not calibrated well enough then 
> > that's a kernel bug we want to fix.
> 
> You miss the point entirely. The delay is in bus clocks not CPU 
> clocks, not tsc clocks not PIT clocks, and it is permitted to vary by 
> a factor of two. So you'll worst case halve the speed of network 
> packet up/download even if your udelay is accurate.

ok, you are right. How about we go with one of your suggestions: rename 
the API family to isa_*_p() in the affected ISA drivers? That makes it 
perfectly clear that this is an ISA related historic quirk that we just 
cannot properly emulate in an acceptable fashion. It will also make the 
least amount of changes to these truly historic drivers.

The main maintenance thing we are interested in is to have no subsequent 
new uses of this API and to eliminate these accesses from modern 
hardware - and naming it clearly 'ISA' and making it dependent on 
CONFIG_ISA would likely achieve that purpose.

oh, another thing: there are 100+ mails in this thread while there are 
only 3 mails in the thread that lists 61 not-yet-fixed-in-2.6.24 
regressions:

|  Listed regressions statistics:
|
|  Date          Total  Pending  Unresolved
|  ----------------------------------------
|  Today           139       38          23

which is a sad proportion of attention :-/

	Ingo

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-02 10:04                                                                       ` Ingo Molnar
@ 2008-01-02 13:11                                                                         ` David P. Reed
  2008-01-02 13:21                                                                           ` Ingo Molnar
  2008-01-02 13:47                                                                         ` Alan Cox
  1 sibling, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-02 13:11 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Alan Cox, H. Peter Anvin, Rene Herman, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

FYI - another quirky Quanta motherboard from HP, with DMI readings 
reported to me.

-------- Original Message --------
Date: 	Wed, 2 Jan 2008 16:23:27 +1030
From: 	Joel Stanley <joel.stanley@adelaide.edu.au>
To: 	David P. Reed <dpreed@reed.com>
Subject: 	Re: [PATCH] Option to disable AMD C1E (allows dynticks to work)



On Dec 30, 2007 1:13 AM, David P. Reed <dpreed@reed.com> wrote:
> I have also attached a c program that only touches port 80.  Compile it
> for 32-bit mode (see comment), run it as root, and after two or three
> runs, it will hang a system that has the port 80 bug.

Using port80.c, I could hard lock a HP Pavilion tx1000 laptop on the
first go. This was with ubuntu hardy's stock kernel (a 2.6.24-rc)

> dmidecode -s baseboard-manufacturer
> dmidecode -s baseboard-product-name

Quanta
30BF

Tonight, I will try compiling a kernel with these values added to your patch.

Some history, feel free to ignore if it's not relevant: ubuntu
feisty's 2.6.22 based kernel worked fine, irc. We were having issues
with sound, so tried fedora8's .23 based kernel, but this would
sporadically hard lock. Ubuntu hardy's 2.6.24 appeared fine, for the 2
hours or so I used it last night, until using the port80.c program,
obviously.

Cheers,

Joel



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-02 13:11                                                                         ` [linux-kernel] " David P. Reed
@ 2008-01-02 13:21                                                                           ` Ingo Molnar
  0 siblings, 0 replies; 243+ messages in thread
From: Ingo Molnar @ 2008-01-02 13:21 UTC (permalink / raw)
  To: David P. Reed
  Cc: Alan Cox, H. Peter Anvin, Rene Herman, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol


* David P. Reed <dpreed@reed.com> wrote:

> FYI - another quirky Quanta motherboard from HP, with DMI readings reported 
> to me.

> Using port80.c, I could hard lock a HP Pavilion tx1000 laptop on the 
> first go. This was with ubuntu hardy's stock kernel (a 2.6.24-rc)
>
>> dmidecode -s baseboard-manufacturer
>> dmidecode -s baseboard-product-name
>
> Quanta
> 30BF

thanks, i've updated the patches in x86.git with this:

+		.callback	= dmi_io_delay_0xed_port,
+		.ident		= "HP Pavilion tx1000",
+		.matches	= {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME, "30BF")
+		}

Find combo patch below.

	Ingo

--------------->
Index: linux-x86.q/Documentation/kernel-parameters.txt
===================================================================
--- linux-x86.q.orig/Documentation/kernel-parameters.txt
+++ linux-x86.q/Documentation/kernel-parameters.txt
@@ -785,6 +785,16 @@ and is between 256 and 4096 characters. 
 			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
+		0x80
+			Standard port 0x80 based delay
+		0xed
+			Alternate port 0xed based delay (needed on some systems)
+		udelay
+			Simple two microseconds delay
+		none
+			No delay
+
 	io7=		[HW] IO7 for Marvel based alpha systems
 			See comment before marvel_specify_io7 in
 			arch/alpha/kernel/core_marvel.c.
Index: linux-x86.q/arch/x86/Kconfig.debug
===================================================================
--- linux-x86.q.orig/arch/x86/Kconfig.debug
+++ linux-x86.q/arch/x86/Kconfig.debug
@@ -112,4 +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.
 
+#
+# 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_UDELAY
+
+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
+	  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
Index: linux-x86.q/arch/x86/boot/compressed/misc_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_32.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_32.c
@@ -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)
Index: linux-x86.q/arch/x86/boot/compressed/misc_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/boot/compressed/misc_64.c
+++ linux-x86.q/arch/x86/boot/compressed/misc_64.c
@@ -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)
Index: linux-x86.q/arch/x86/kernel/Makefile_32
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/Makefile_32
+++ linux-x86.q/arch/x86/kernel/Makefile_32
@@ -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/
Index: linux-x86.q/arch/x86/kernel/Makefile_64
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/Makefile_64
+++ linux-x86.q/arch/x86/kernel/Makefile_64
@@ -11,7 +11,7 @@ obj-y	:= process_64.o signal_64.o entry_
 		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/
Index: linux-x86.q/arch/x86/kernel/io_delay.c
===================================================================
--- /dev/null
+++ linux-x86.q/arch/x86/kernel/io_delay.c
@@ -0,0 +1,114 @@
+/*
+ * 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		= "Compaq Presario V6000",
+		.matches	= {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME, "30B7")
+		}
+	},
+	{
+		.callback	= dmi_io_delay_0xed_port,
+		.ident		= "HP Pavilion dv9000z",
+		.matches	= {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME, "30B9")
+		}
+	},
+	{
+		.callback	= dmi_io_delay_0xed_port,
+		.ident		= "HP Pavilion tx1000",
+		.matches	= {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME, "30BF")
+		}
+	},
+	{ }
+};
+
+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);
Index: linux-x86.q/arch/x86/kernel/setup_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/setup_32.c
+++ linux-x86.q/arch/x86/kernel/setup_32.c
@@ -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	
Index: linux-x86.q/arch/x86/kernel/setup_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/setup_64.c
+++ linux-x86.q/arch/x86/kernel/setup_64.c
@@ -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;
Index: linux-x86.q/include/asm-x86/io_32.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_32.h
+++ linux-x86.q/include/asm-x86/io_32.h
@@ -250,10 +250,10 @@ static inline void flush_write_buffers(v
 
 #endif /* __KERNEL__ */
 
-static inline void native_io_delay(void)
-{
-	asm volatile("outb %%al,$0x80" : : : "memory");
-}
+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>
Index: linux-x86.q/include/asm-x86/io_64.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/io_64.h
+++ linux-x86.q/include/asm-x86/io_64.h
@@ -35,13 +35,20 @@
   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+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();
 #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..
@@ -50,21 +57,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) \
Index: linux-x86.q/kernel/sysctl.c
===================================================================
--- linux-x86.q.orig/kernel/sysctl.c
+++ linux-x86.q/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);
@@ -683,6 +684,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)
 	{

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-02 10:04                                                                       ` Ingo Molnar
  2008-01-02 13:11                                                                         ` [linux-kernel] " David P. Reed
@ 2008-01-02 13:47                                                                         ` Alan Cox
  2008-01-02 15:35                                                                           ` Rene Herman
  1 sibling, 1 reply; 243+ messages in thread
From: Alan Cox @ 2008-01-02 13:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: David P. Reed, H. Peter Anvin, Rene Herman, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

> ok, you are right. How about we go with one of your suggestions: rename 
> the API family to isa_*_p() in the affected ISA drivers? That makes it 
> perfectly clear that this is an ISA related historic quirk that we just 
> cannot properly emulate in an acceptable fashion. It will also make the 
> least amount of changes to these truly historic drivers.

Works for me. We need to build two versions of 8390.c now but thats no
big deal and sorts PCMCIA out too.

> The main maintenance thing we are interested in is to have no subsequent 
> new uses of this API and to eliminate these accesses from modern 
> hardware - and naming it clearly 'ISA' and making it dependent on 
> CONFIG_ISA would likely achieve that purpose.

Agreed - will see if EISA/VLB cases come up but thats trivial.

> oh, another thing: there are 100+ mails in this thread while there are 
> only 3 mails in the thread that lists 61 not-yet-fixed-in-2.6.24 
> regressions:

That would be because I'm trying to stop 100 new extra regressions ;)

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-02 13:47                                                                         ` Alan Cox
@ 2008-01-02 15:35                                                                           ` Rene Herman
  2008-01-02 15:50                                                                             ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2008-01-02 15:35 UTC (permalink / raw)
  To: Alan Cox
  Cc: Ingo Molnar, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On 02-01-08 14:47, Alan Cox wrote:

>> ok, you are right. How about we go with one of your suggestions: rename 
>> the API family to isa_*_p() in the affected ISA drivers? That makes it 
>> perfectly clear that this is an ISA related historic quirk that we just 
>> cannot properly emulate in an acceptable fashion. It will also make the 
>> least amount of changes to these truly historic drivers.
> 
> Works for me. We need to build two versions of 8390.c now but thats no
> big deal and sorts PCMCIA out too.

For no binary changes at all, and if going through all those outb_p() users 
anyway, might/could as well just manually split them then:

outb_p() --> outb();
              slow_down_io();

and then just leave out the slow_down_io() call in the non-ISA spots. 
slow_down_io() could be renamed isa_io_delay() or anything (paravirt is a 
little annoying there) if someone cares but then it's a complete identity 
transformation for any driver that does care.

Would IMO also make for a somewhat better API than an isa_outb_p() as 
there's nothing particurly ISA about the outb method itself -- many ISA 
drivers use plain outb() as well.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-02 15:35                                                                           ` Rene Herman
@ 2008-01-02 15:50                                                                             ` Rene Herman
  0 siblings, 0 replies; 243+ messages in thread
From: Rene Herman @ 2008-01-02 15:50 UTC (permalink / raw)
  To: Alan Cox
  Cc: Ingo Molnar, David P. Reed, H. Peter Anvin, Rene Herman,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On 02-01-08 16:35, Rene Herman wrote:
 > On 02-01-08 14:47, Alan Cox wrote:
 >
 >>> ok, you are right. How about we go with one of your suggestions:
 >>> rename the API family to isa_*_p() in the affected ISA drivers? That
 >>> makes it perfectly clear that this is an ISA related historic quirk
 >>> that we just cannot properly emulate in an acceptable fashion. It
 >>> will also make the least amount of changes to these truly historic
 >>> drivers.
 >>
 >> Works for me. We need to build two versions of 8390.c now but thats no
 >> big deal and sorts PCMCIA out too.
 >
 > For no binary changes at all, and if going through all those outb_p()
 > users anyway, might/could as well just manually split them then:
 >
 > outb_p() --> outb();
 >              slow_down_io();
 >
 > and then just leave out the slow_down_io() call in the non-ISA spots.
 > slow_down_io() could be renamed isa_io_delay() or anything (paravirt is
 > a little annoying there) if someone cares but then it's a complete
 > identity transformation for any driver that does care.
 >
 > Would IMO also make for a somewhat better API than an isa_outb_p() as
 > there's nothing particurly ISA about the outb method itself -- many ISA
 > drivers use plain outb() as well.

Would just need this bit of io.h arch unification from the orignal patch and 
that's it:

diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index a037b07..97cb8c6 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -35,13 +35,20 @@
    *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
    */

-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+static inline void native_io_delay(void)
+{
+	asm volatile("outb %%al,$0x80" : : : "memory");
+}

+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..
@@ -50,21 +57,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) \


^ permalink raw reply related	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-07 23:24                                   ` H. Peter Anvin
  2008-01-07 23:26                                     ` Rene Herman
@ 2008-01-07 23:57                                     ` David P. Reed
  2008-01-08  1:58                                       ` Alan Cox
  1 sibling, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-07 23:57 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Rene Herman, Bodo Eggert, Christer Weinigel, Ingo Molnar,
	Alan Cox, Rene Herman, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol



H. Peter Anvin wrote:
> Rene Herman wrote:
>>
>> Is this only about the ones then left for things like legacy PIC and 
>> PIT? Does anyone care about just sticking in a udelay(2) (or 1) there 
>> as a replacement and call it a day?
>>
>
> PIT is problematic because the PIT may be necessary for udelay setup.
>
The PIT usage for calibrating the delay loop can be moderated, if need 
by, by using the PC BIOS which by definition uses the PIT correctly it 
its int 15 function 83 call..   Just do it before coming up in a state 
where the PC BIOS int 15h calls no longer work.  I gave code to do this 
in a much earlier message.

This is the MOST reliable way to use the PIT early in boot, on a PC 
compatible.  God knows how one should do it on a Macintosh running a 
386/20  :-).   But the ONLY old bat-PIT machines are, thank god, PC 
compatible, maybe.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-07 23:26                                     ` Rene Herman
@ 2008-01-08  0:10                                       ` David P. Reed
  2008-01-08  0:13                                         ` H. Peter Anvin
  2008-01-08 12:51                                       ` Bodo Eggert
  1 sibling, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-08  0:10 UTC (permalink / raw)
  To: Rene Herman
  Cc: H. Peter Anvin, Bodo Eggert, Christer Weinigel, Ingo Molnar,
	Alan Cox, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

On another topic.  I have indeed determined what device uses port 80 on 
Quanta AMD64 laptops from HP.

I had lunch with Jim Gettys of OLPC a week ago; he's an old friend since 
he worked on the original X windows system.   After telling him my story 
about port 80, he mentioned that the OLPC XO machine had some issues 
with port 80 which was by design handled by the ENE KBC device on its 
motherboard.   He said the ENE was a very desirable chipset for AMD 
designs recommended by Quanta.  Richard Smith of OLPC explained to me 
how the KB3700 they use works, and that they use the KB3700 to send POST 
codes out over a serial link during boot up.

This gave me a reason to take apart my laptop, to discover that it has 
an ENE KB3920 B0 as its EC and KBC.  The port interface for the KB3920 
includes listening to port 80 which is then made available to firmware 
on the EC.  It is recognized and decoded on the LPC bus, only for 
writes, and optionally can generate an interrupt in the 8051.

Dumping both the ENE chip, and looking at the DSDT.dsl for my machine, I 
discovered that port 80 is used as an additional parameter for various 
DSDT methods that communicate to the EC, when it is operating in ACPI mode.

More work is in progress as I play around with this.  But the key thing 
is that ACPI and perhaps SMM both use port 80 as part of the base 
function of the chipset.

And actually, if I had looked at the /sys/bus/pnp definitions, rather 
than /proc/ioports, I would have noticed that port 80 was part of a 
PNP0C02 resource set.   That means exactly one thing:  ACPI says that 
port 80 is NOT free to be used, for delays or anything else.

This should make no difference here: it's just one more reason to stop 
using port 80 for delays on modern machines.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08  0:10                                       ` [linux-kernel] " David P. Reed
@ 2008-01-08  0:13                                         ` H. Peter Anvin
  2008-01-08  1:38                                           ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-08  0:13 UTC (permalink / raw)
  To: David P. Reed
  Cc: Rene Herman, Bodo Eggert, Christer Weinigel, Ingo Molnar,
	Alan Cox, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

David P. Reed wrote:
> 
> And actually, if I had looked at the /sys/bus/pnp definitions, rather 
> than /proc/ioports, I would have noticed that port 80 was part of a 
> PNP0C02 resource set.   That means exactly one thing:  ACPI says that 
> port 80 is NOT free to be used, for delays or anything else.
> 
> This should make no difference here: it's just one more reason to stop 
> using port 80 for delays on modern machines.
> 

And shoot the designer of this particular microcontroller firmware.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08  0:13                                         ` H. Peter Anvin
@ 2008-01-08  1:38                                           ` David P. Reed
  2008-01-08 17:10                                             ` Ondrej Zary
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-08  1:38 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Rene Herman, Bodo Eggert, Christer Weinigel, Ingo Molnar,
	Alan Cox, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

H. Peter Anvin wrote:
>
> And shoot the designer of this particular microcontroller firmware.
>
>  
Well, some days I want to shoot the "designer" of the entire Wintel 
architecture...  it's not exactly "designed" by anybody of course, and 
today it's created largely by a collection of Taiwanese and Chinese ODM 
firms, coupled with Microsoft WinHEC and Intel folks.  At least they 
follow the rules and their ACPI and BIOS code say that they are using 
port 80 very clearly if you use PnP and ACPI properly.  And in the old 
days, you were "supposed" to use the system BIOS to talk to things like 
the PIT that had timing issues, not write your own code.

Or perhaps the ACPI spec should specify a timing loop spec and precisely 
specify the desired timing after accessing an I/O port till that device 
has properly "acted" on that operation.

The idea that Port 80 was "unused" and appropriate for delay purposes 
elicited skepticism by Linus that is recorded for posterity in the 
comments of the relevant Linux include files - especially since it was 
clearly "used" for non-delay purposes, by cards that could be plugged 
into a PCI (fast), not just an 8-bit ISA, bus.

Perhaps we should declare the world of ACPI systems a separate "arch" 
from the world of l'ancien regime where folklore about which ports were 
used for what ruled.   I lived through those old days, and they were not 
wonderful, either.

The world sucks, and Linux is supposed to be able to adapt to that 
world, suckitude and all.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-07 23:57                                     ` David P. Reed
@ 2008-01-08  1:58                                       ` Alan Cox
  0 siblings, 0 replies; 243+ messages in thread
From: Alan Cox @ 2008-01-08  1:58 UTC (permalink / raw)
  To: David P. Reed
  Cc: H. Peter Anvin, Rene Herman, Bodo Eggert, Christer Weinigel,
	Ingo Molnar, Rene Herman, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

> The PIT usage for calibrating the delay loop can be moderated, if need 
> by, by using the PC BIOS which by definition uses the PIT correctly it 
> its int 15 function 83 call..   Just do it before coming up in a state 
> where the PC BIOS int 15h calls no longer work.  I gave code to do this 
> in a much earlier message.

And as I've said before we don't know if we have a PC BIOS. If we are
running from a kexec or on a Macintoy with EFI or an Xbox we may not.

As per previous discussions for the PIT we can simply guess a safe
initial udelay value and then tune the real one.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 12:51                                       ` Bodo Eggert
@ 2008-01-08 13:07                                         ` David P. Reed
  2008-01-08 14:37                                           ` Alan Cox
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-08 13:07 UTC (permalink / raw)
  To: Bodo Eggert
  Cc: Rene Herman, H. Peter Anvin, Christer Weinigel, Ingo Molnar,
	Alan Cox, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

The last time I heard of a 12 MHz bus in a PC system was in the days of 
the PC-AT, when some clone makers sped up their buses (pre PCI!!!) in an 
attempt to allow adapter card *memory* to run at the 12 MHz speed.

This caused so many industry-wide problems with adapter cards that 
couldn't be installed in certain machines and still run reliably that 
the industry learned a lesson.  That doesn't mean that LPCs don't run at 
12 MHz, but if they do, they don't have old 8 bit punky cards plugged 
into them for lots of practical reasons.  (I have whole drawers full of 
such old cards, trying to figure out an environmentally responsible way 
to get rid of them - even third world countries would be fools to make 
machiens with them).

I can't believe that we are not supporting today's machines correctly 
because we are still trying to be compatible with a few (at most a 
hundre thousand were manufactured!  Much less still functioning or 
running Linux) machines.

Now I understand that PC/104 machines and other things are very non PC 
compatible, but are x86 processor architectures.  Do they even run x86 
under 2.6.24?

Perhaps the rational solution here is to declare x86 the architecture 
for "relics" and develop a merged architecture called "modern machines" 
to include only those PCs that have been made to work since, say, the 
release of (cough) WIndows 2000?

Bodo Eggert wrote:
> On Tue, 8 Jan 2008, Rene Herman wrote:
>   
>> On 08-01-08 00:24, H. Peter Anvin wrote:
>>     
>>> Rene Herman wrote:
>>>       
>
>   
>>>> Is this only about the ones then left for things like legacy PIC and PIT?
>>>> Does anyone care about just sticking in a udelay(2) (or 1) there as a
>>>> replacement and call it a day?
>>>>
>>>>         
>>> PIT is problematic because the PIT may be necessary for udelay setup.
>>>       
>> Yes, can initialise loops_per_jiffy conservatively. Just didn't quite get why
>> you guys are talking about an ISA bus speed parameter.
>>     
>
> If the ISA bus is below 8 MHz, we might need a longer delay. If we default
> to the longer delay, the delay will be too long for more than 99,99 % of 
> all systems, not counting i586+. Especially if the driver is fine-tuned to 
> give maximum throughput, this may be bad.
>
> OTOH, the DOS drivers I heared about use delays and would break on 
> underclocked ISA busses if the n * ISA_HZ delay was needed. Maybe
> somebody having a configurable ISA bus speed and some problematic
> chips can test it ...
>
>   

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 13:07                                         ` [linux-kernel] " David P. Reed
@ 2008-01-08 14:37                                           ` Alan Cox
  0 siblings, 0 replies; 243+ messages in thread
From: Alan Cox @ 2008-01-08 14:37 UTC (permalink / raw)
  To: David P. Reed
  Cc: Bodo Eggert, Rene Herman, H. Peter Anvin, Christer Weinigel,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

> The last time I heard of a 12 MHz bus in a PC system was in the days of 
> the PC-AT, when some clone makers sped up their buses (pre PCI!!!) in an 
> attempt to allow adapter card *memory* to run at the 12 MHz speed.

It wasn't about clone makers speeding up their busses. The ISA bus
originally ran at the CPU clock - 4.77/8/6/10 .. etc. Quite a few board
makers assumed 8MHz and while faster isn't a big problem at 8bit trying
to do the 8/16 bit decode with logic chips at 8MHz is quite tight and
above that generally broke. 8bit tends to work fine because you've got a
lot more timing headroom.

> I can't believe that we are not supporting today's machines correctly 
> because we are still trying to be compatible with a few (at most a 
> hundre thousand were manufactured!  Much less still functioning or 
> running Linux) machines.

It is about supporting this properly. Properly for ISA devices means
using I/O delays. Properly for chipset devices is probably using udelay.

> Now I understand that PC/104 machines and other things are very non PC 
> compatible, but are x86 processor architectures.  Do they even run x86 
> under 2.6.24?

Linux runs on x86, it isn't limited to PC type architectures at all. We
don't need a BIOS, we don't need legacy compatible I/O devices.

> for "relics" and develop a merged architecture called "modern machines" 
> to include only those PCs that have been made to work since, say, the 
> release of (cough) WIndows 2000?

No point. We've got the 64bit kernel for that. That is a much saner
boundary to throw out all the nutty stuff.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08  1:38                                           ` David P. Reed
@ 2008-01-08 17:10                                             ` Ondrej Zary
  2008-01-08 17:24                                               ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: Ondrej Zary @ 2008-01-08 17:10 UTC (permalink / raw)
  To: David P. Reed
  Cc: H. Peter Anvin, Rene Herman, Bodo Eggert, Christer Weinigel,
	Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Tuesday 08 January 2008 02:38:15 David P. Reed wrote:
> H. Peter Anvin wrote:
> > And shoot the designer of this particular microcontroller firmware.
>
> Well, some days I want to shoot the "designer" of the entire Wintel
> architecture...  it's not exactly "designed" by anybody of course, and
> today it's created largely by a collection of Taiwanese and Chinese ODM
> firms, coupled with Microsoft WinHEC and Intel folks.  At least they
> follow the rules and their ACPI and BIOS code say that they are using
> port 80 very clearly if you use PnP and ACPI properly.  And in the old
> days, you were "supposed" to use the system BIOS to talk to things like
> the PIT that had timing issues, not write your own code.

Does anyone know what port does Windows use? I'm pretty sure that it isn't 80h 
as I run Windows 98 often with port 80h debug card inserted. The last POST 
code set by BIOS usually remains on the display and only changes when BIOS 
does something like suspend/resume. IIRC, there was a program that was able 
to display temperature from onboard sensors on the port 80h display that's 
integrated on some mainboards.

-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 17:10                                             ` Ondrej Zary
@ 2008-01-08 17:24                                               ` David P. Reed
  2008-01-08 17:38                                                 ` Ondrej Zary
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-08 17:24 UTC (permalink / raw)
  To: Ondrej Zary
  Cc: H. Peter Anvin, Rene Herman, Bodo Eggert, Christer Weinigel,
	Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Windows these days does delays with timing loops or the scheduler.  It 
doesn't use a "port".  Also, Windows XP only supports machines that tend 
not to have timing problems that use delays.  Instead, if a device takes 
a while to respond, it has a "busy bit" in some port or memory slot that 
can be tested.

Almost all of the issues in Linux where _p operations are used are (or 
should be) historical - IMO.

Ondrej Zary wrote:
> On Tuesday 08 January 2008 02:38:15 David P. Reed wrote:
>   
>> H. Peter Anvin wrote:
>>     
>>> And shoot the designer of this particular microcontroller firmware.
>>>       
>> Well, some days I want to shoot the "designer" of the entire Wintel
>> architecture...  it's not exactly "designed" by anybody of course, and
>> today it's created largely by a collection of Taiwanese and Chinese ODM
>> firms, coupled with Microsoft WinHEC and Intel folks.  At least they
>> follow the rules and their ACPI and BIOS code say that they are using
>> port 80 very clearly if you use PnP and ACPI properly.  And in the old
>> days, you were "supposed" to use the system BIOS to talk to things like
>> the PIT that had timing issues, not write your own code.
>>     
>
> Does anyone know what port does Windows use? I'm pretty sure that it isn't 80h 
> as I run Windows 98 often with port 80h debug card inserted. The last POST 
> code set by BIOS usually remains on the display and only changes when BIOS 
> does something like suspend/resume. IIRC, there was a program that was able 
> to display temperature from onboard sensors on the port 80h display that's 
> integrated on some mainboards.
>
>   

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 17:24                                               ` David P. Reed
@ 2008-01-08 17:38                                                 ` Ondrej Zary
  2008-01-08 18:44                                                   ` David P. Reed
  2008-01-08 18:51                                                   ` Bodo Eggert
  0 siblings, 2 replies; 243+ messages in thread
From: Ondrej Zary @ 2008-01-08 17:38 UTC (permalink / raw)
  To: David P. Reed
  Cc: H. Peter Anvin, Rene Herman, Bodo Eggert, Christer Weinigel,
	Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Tuesday 08 January 2008 18:24:02 David P. Reed wrote:
> Windows these days does delays with timing loops or the scheduler.  It
> doesn't use a "port".  Also, Windows XP only supports machines that tend
> not to have timing problems that use delays.  Instead, if a device takes
> a while to respond, it has a "busy bit" in some port or memory slot that
> can be tested.

Windows XP can run on a machine with ISA slot(s) and has built-in drivers for 
some plug&play ISA cards - e.g. the famous 3Com EtherLink III. I think that 
there's a driver for NE2000-compatible cards too and it probably works.

> Almost all of the issues in Linux where _p operations are used are (or
> should be) historical - IMO.
>
> Ondrej Zary wrote:
> > On Tuesday 08 January 2008 02:38:15 David P. Reed wrote:
> >> H. Peter Anvin wrote:
> >>> And shoot the designer of this particular microcontroller firmware.
> >>
> >> Well, some days I want to shoot the "designer" of the entire Wintel
> >> architecture...  it's not exactly "designed" by anybody of course, and
> >> today it's created largely by a collection of Taiwanese and Chinese ODM
> >> firms, coupled with Microsoft WinHEC and Intel folks.  At least they
> >> follow the rules and their ACPI and BIOS code say that they are using
> >> port 80 very clearly if you use PnP and ACPI properly.  And in the old
> >> days, you were "supposed" to use the system BIOS to talk to things like
> >> the PIT that had timing issues, not write your own code.
> >
> > Does anyone know what port does Windows use? I'm pretty sure that it
> > isn't 80h as I run Windows 98 often with port 80h debug card inserted.
> > The last POST code set by BIOS usually remains on the display and only
> > changes when BIOS does something like suspend/resume. IIRC, there was a
> > program that was able to display temperature from onboard sensors on the
> > port 80h display that's integrated on some mainboards.
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 17:38                                                 ` Ondrej Zary
@ 2008-01-08 18:44                                                   ` David P. Reed
  2008-01-08 18:51                                                     ` Alan Cox
  2008-01-08 19:25                                                     ` Christer Weinigel
  2008-01-08 18:51                                                   ` Bodo Eggert
  1 sibling, 2 replies; 243+ messages in thread
From: David P. Reed @ 2008-01-08 18:44 UTC (permalink / raw)
  To: Ondrej Zary
  Cc: H. Peter Anvin, Rene Herman, Bodo Eggert, Christer Weinigel,
	Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol



Ondrej Zary wrote:
> On Tuesday 08 January 2008 18:24:02 David P. Reed wrote:
>   
>> Windows these days does delays with timing loops or the scheduler.  It
>> doesn't use a "port".  Also, Windows XP only supports machines that tend
>> not to have timing problems that use delays.  Instead, if a device takes
>> a while to respond, it has a "busy bit" in some port or memory slot that
>> can be tested.
>>     
>
> Windows XP can run on a machine with ISA slot(s) and has built-in drivers for 
> some plug&play ISA cards - e.g. the famous 3Com EtherLink III. I think that 
> there's a driver for NE2000-compatible cards too and it probably works.
>   
There is no need to use io writes to supposedly/theoretically "unused 
ports" to make drivers work on any bus.
ISA included!  You can, for example, wait for an ISA bus serial adapter 
to put out its next character by looping reading the port that has the 
output buffer full flag in a tight loop, with no delay code at all.  And 
if you need to time things, just call a timing loop subroutine that you 
calibrate at boot time.
I wrote DOS drivers for NE2000's on the ISA bus when they were brand new 
designs from Novell without such kludges as writes to I/O port 80.  I 
don't remember writing a driver for the 3com devices - probably didn't, 
because 3Com's cards were expensive at the time.

In any case, Linux *did* adopt this port 80 strategy - I'm sure all 
concerned thought it was frightfully clever at the time.  Linus 
expressed his skepticism in the comments in io.h.  The problem is to 
safely move away from it toward a proper strategy that doesn't depend on 
"bus aborts" which would trigger machine checks if they were properly 
enabled.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 18:44                                                   ` David P. Reed
@ 2008-01-08 18:51                                                     ` Alan Cox
  2008-01-08 19:15                                                       ` David P. Reed
  2008-01-08 19:25                                                     ` Christer Weinigel
  1 sibling, 1 reply; 243+ messages in thread
From: Alan Cox @ 2008-01-08 18:51 UTC (permalink / raw)
  To: David P. Reed
  Cc: Ondrej Zary, H. Peter Anvin, Rene Herman, Bodo Eggert,
	Christer Weinigel, Ingo Molnar, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

> There is no need to use io writes to supposedly/theoretically "unused 
> ports" to make drivers work on any bus.

The natsemi docs here say otherwise. I trust them not you.

> don't remember writing a driver for the 3com devices - probably didn't, 
> because 3Com's cards were expensive at the time.

3C503 needs delays for some setups according to the docs. I can't tell
you how the 3COM drivers did it as that was a different bit of 3com to
the bit I worked for. From the rest of 3Com I saw probably utterly
vilely ;)

Later 3Com stuff was either sane (3c509 etc) or used whacko intel chips
(3c507/27) which had their own special breed of insanity to replace
address setup delay bugs.

> In any case, Linux *did* adopt this port 80 strategy - I'm sure all 
> concerned thought it was frightfully clever at the time.  Linus 
> expressed his skepticism in the comments in io.h.  The problem is to 
> safely move away from it toward a proper strategy 

No. The problem is that certain people, unfortunately those who know
nothing about ISA related bus systems, keep trying to confuse ISA delay
logic with core chip logic and end up trying to solve both a problem and a
non-problem in one, creating a nasty mess in the process.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 17:38                                                 ` Ondrej Zary
  2008-01-08 18:44                                                   ` David P. Reed
@ 2008-01-08 18:51                                                   ` Bodo Eggert
  2008-01-08 19:13                                                     ` Ondrej Zary
  1 sibling, 1 reply; 243+ messages in thread
From: Bodo Eggert @ 2008-01-08 18:51 UTC (permalink / raw)
  To: Ondrej Zary
  Cc: David P. Reed, H. Peter Anvin, Rene Herman, Bodo Eggert,
	Christer Weinigel, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Tue, 8 Jan 2008, Ondrej Zary wrote:
> On Tuesday 08 January 2008 18:24:02 David P. Reed wrote:

> > Windows these days does delays with timing loops or the scheduler.  It
> > doesn't use a "port".  Also, Windows XP only supports machines that tend
> > not to have timing problems that use delays.  Instead, if a device takes
> > a while to respond, it has a "busy bit" in some port or memory slot that
> > can be tested.
> 
> Windows XP can run on a machine with ISA slot(s) and has built-in drivers for 
> some plug&play ISA cards - e.g. the famous 3Com EtherLink III. I think that 
> there's a driver for NE2000-compatible cards too and it probably works.

The NE2K-driver went missing in W2K. BTDT.
-- 
Anyone can speak Troll. All you have to do is point and grunt.
	-- Fred Weasley

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 18:51                                                   ` Bodo Eggert
@ 2008-01-08 19:13                                                     ` Ondrej Zary
  0 siblings, 0 replies; 243+ messages in thread
From: Ondrej Zary @ 2008-01-08 19:13 UTC (permalink / raw)
  To: Bodo Eggert
  Cc: David P. Reed, H. Peter Anvin, Rene Herman, Christer Weinigel,
	Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Tuesday 08 January 2008 19:51:41 Bodo Eggert wrote:
> On Tue, 8 Jan 2008, Ondrej Zary wrote:
> > On Tuesday 08 January 2008 18:24:02 David P. Reed wrote:
> > > Windows these days does delays with timing loops or the scheduler.  It
> > > doesn't use a "port".  Also, Windows XP only supports machines that
> > > tend not to have timing problems that use delays.  Instead, if a device
> > > takes a while to respond, it has a "busy bit" in some port or memory
> > > slot that can be tested.
> >
> > Windows XP can run on a machine with ISA slot(s) and has built-in drivers
> > for some plug&play ISA cards - e.g. the famous 3Com EtherLink III. I
> > think that there's a driver for NE2000-compatible cards too and it
> > probably works.
>
> The NE2K-driver went missing in W2K. BTDT.

Haven't tried personally but it seems to work accroding to this 
http://www.windowsnetworking.com/articles_tutorials/wxpne2k.html - and it can 
be made to work even with non-PnP cards.

-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 18:51                                                     ` Alan Cox
@ 2008-01-08 19:15                                                       ` David P. Reed
  2008-01-08 19:23                                                         ` Alan Cox
  2008-01-09  2:52                                                         ` Zachary Amsden
  0 siblings, 2 replies; 243+ messages in thread
From: David P. Reed @ 2008-01-08 19:15 UTC (permalink / raw)
  To: Alan Cox
  Cc: Ondrej Zary, H. Peter Anvin, Rene Herman, Bodo Eggert,
	Christer Weinigel, Ingo Molnar, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Alan Cox wrote:
> The natsemi docs here say otherwise. I trust them not you.
>   
As well you should. I am honestly curious (for my own satisfaction) as 
to what the natsemi docs say the delay code should do  (can't imagine 
they say "use io port 80 because it is unused").  I don't have any 
copies anymore. But mere curiosity on my part is not worth spending a 
lot of time on - I know you are super busy.   If there's a copy online 
at a URL ...
>
> The problem is that certain people, unfortunately those who know
> nothing about ISA related bus systems, keep trying to confuse ISA delay
> logic with core chip logic and end up trying to solve both a problem and a
> non-problem in one, creating a nasty mess in the process.
>
>   
I agree that the problems of chip logic and ISA delay are all tangled 
up, probably more than need be.  I hope that the solution turns out to 
simplify matters, and hopefully to document the intention of the 
resulting code sections a bit more clearly for the future.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 19:15                                                       ` David P. Reed
@ 2008-01-08 19:23                                                         ` Alan Cox
  2008-01-08 19:51                                                           ` David P. Reed
  2008-01-09  2:52                                                         ` Zachary Amsden
  1 sibling, 1 reply; 243+ messages in thread
From: Alan Cox @ 2008-01-08 19:23 UTC (permalink / raw)
  To: David P. Reed
  Cc: Ondrej Zary, H. Peter Anvin, Rene Herman, Bodo Eggert,
	Christer Weinigel, Ingo Molnar, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

> As well you should. I am honestly curious (for my own satisfaction) as 
> to what the natsemi docs say the delay code should do  (can't imagine 
> they say "use io port 80 because it is unused").  I don't have any 

They say you must allow 4 bus clocks for the address decode. They don't
deal with the ISA side as the chip itself has no ISA glue.


> copies anymore. But mere curiosity on my part is not worth spending a 
> lot of time on - I know you are super busy.   If there's a copy online 
> at a URL ...

Not that I know of. There may be. A good general source of info is Russ
Nelson's old DOS packet driver collection.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 18:44                                                   ` David P. Reed
  2008-01-08 18:51                                                     ` Alan Cox
@ 2008-01-08 19:25                                                     ` Christer Weinigel
  2008-01-08 20:28                                                       ` David P. Reed
  1 sibling, 1 reply; 243+ messages in thread
From: Christer Weinigel @ 2008-01-08 19:25 UTC (permalink / raw)
  To: David P. Reed
  Cc: Ondrej Zary, H. Peter Anvin, Rene Herman, Bodo Eggert,
	Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Tue, 08 Jan 2008 13:44:54 -0500
"David P. Reed" <dpreed@reed.com> wrote:

> Ondrej Zary wrote:
> > On Tuesday 08 January 2008 18:24:02 David P. Reed wrote:
> >   
> >> Windows these days does delays with timing loops or the
> >> scheduler.  It doesn't use a "port".  Also, Windows XP only
> >> supports machines that tend not to have timing problems that use
> >> delays.  Instead, if a device takes a while to respond, it has a
> >> "busy bit" in some port or memory slot that can be tested.
> >>     
> There is no need to use io writes to supposedly/theoretically "unused 
> ports" to make drivers work on any bus.
> ISA included!  You can, for example, wait for an ISA bus serial
> adapter to put out its next character by looping reading the port
> that has the output buffer full flag in a tight loop, with no delay
> code at all.  And if you need to time things, just call a timing loop
> subroutine that you calibrate at boot time.

Now you're totally confusing things.  You're talking about looking at
bits in a register to see if a transmit register is empty.  
That's easy.

The delays needed for the Intel M8259 and M8253 say that you're not
even allowed to access the registers _at_ _all_ for some time after a
register access.  If you do a write to a register immediately followed
by any access, including a read of the status register, you can corrupt
the state of the chip.

And the Intel chips are not the only ones with that kind of brain
damage.  But what makes the 8259 and 8253 a big problem is that every
modern PC has a descendant of those chips in them.  The discrete Intel
chips or clones got aggregated into Super I/O chips, and the Super I/O
chips were put on a LPC bus (an ISA bus with another name) or
integrated into the southbrige.  And the "if it ain't broken, don't fix
it" mantra probably means that some modern chipsets are still using
exactly the same internal design as the 25 year old chips and will
still be subject to some of those ancient limitations.

  /Christer

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 19:23                                                         ` Alan Cox
@ 2008-01-08 19:51                                                           ` David P. Reed
  0 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2008-01-08 19:51 UTC (permalink / raw)
  To: Alan Cox
  Cc: Ondrej Zary, H. Peter Anvin, Rene Herman, Bodo Eggert,
	Christer Weinigel, Ingo Molnar, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Alan -

I dug up a DP83901A SNIC datasheet in a quick Google search, while that 
wasn't the only such chip, it was one of them.  I can forward the PDF 
(the www.alldatasheet.com site dynamically creates the download URL), if 
anyone wants it.
The relevant passage says, in regard to delaying between checking the 
CRDA addresses to see if a dummy "remote read" has been executed., and 
in regard perhaps to other card IO register loops: 
                                                         

    TIME BETWEEN CHIP SELECTS
                                                                 
    The SNIC requires that successive chip selects be no
    closer                                                     
    than 4 bus clocks (BSCK) together. If the condition is
    violat-                                           
    ed the SNIC may glitch ACK. CPUs that operate from pipe-
    lined instructions (i e 386) or have a cache (i e 486) can
    execute consecutive I O cycles very quickly The solution is
    to delay the execution of consecutive I O cycles by either
    breaking the pipeline or forcing the CPU to access outside
    its cache.

The NE2000 as I recall had no special logic on the board to protect the 
chip from successive chip selects that were too close - which is the 
reason for the problem. Clearly an out to port 80 takes more than 4 ISA 
bus clocks, so that works if the NE2000 is on the ISA bus,   On the 
other hand, there are other ways to delay more than 4 ISA bus clocks.  
And as you say, one needs a delay for this chip that relates to the 
chip's card's bus's clock speed, not absolute time.

Alan Cox wrote:
>> As well you should. I am honestly curious (for my own satisfaction) as 
>> to what the natsemi docs say the delay code should do  (can't imagine 
>> they say "use io port 80 because it is unused").  I don't have any 
>>     
>
> They say you must allow 4 bus clocks for the address decode. They don't
> deal with the ISA side as the chip itself has no ISA glue.
>
>
>   
>> copies anymore. But mere curiosity on my part is not worth spending a 
>> lot of time on - I know you are super busy.   If there's a copy online 
>> at a URL ...
>>     
>
> Not that I know of. There may be. A good general source of info is Russ
> Nelson's old DOS packet driver collection.
>
>
>   

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 19:25                                                     ` Christer Weinigel
@ 2008-01-08 20:28                                                       ` David P. Reed
  2008-01-08 21:43                                                         ` Christer Weinigel
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-08 20:28 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Ondrej Zary, H. Peter Anvin, Rene Herman, Bodo Eggert,
	Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol


Christer Weinigel wrote:
>> There is no need to use io writes to supposedly/theoretically "unused 
>> ports" to make drivers work on any bus.
>> ISA included!  You can, for example, wait for an ISA bus serial
>> adapter to put out its next character by looping reading the port
>> that has the output buffer full flag in a tight loop, with no delay
>> code at all.  And if you need to time things, just call a timing loop
>> subroutine that you calibrate at boot time.
>>     
>
> Now you're totally confusing things.  You're talking about looking at
> bits in a register to see if a transmit register is empty.  
> That's easy.
>
> The delays needed for the Intel M8259 and M8253 say that you're not
> even allowed to access the registers _at_ _all_ for some time after a
> register access.  If you do a write to a register immediately followed
> by any access, including a read of the status register, you can corrupt
> the state of the chip.
>   
Not true.  Even on the original IBM 5150 PC, the 8259 on the motherboard 
accepted back to back  OUT and IN instructions, and it would NOT trash 
the chip state.  You can read the original IBM BIOS code if you like.  I 
don't remember about the 8253's timing.  I doubt the chip's state would 
be corrupted in any way. The data and address lines were the same data 
and address lines that the microprocessor used to access memory - it 
didn't "hold" the lines stable any longer than the OUT instruction.
> And the Intel chips are not the only ones with that kind of brain
> damage.  But what makes the 8259 and 8253 a big problem is that every
> modern PC has a descendant of those chips in them.
Register compatible.  Not  the same chips or even the same  masks or 
timing requirements.
> The discrete Intel
> chips or clones got aggregated into Super I/O chips, and the Super I/O
> chips were put on a LPC bus (an ISA bus with another name) or
> integrated into the southbrige.
Don't try to teach your grandmother to suck eggs: I've been programming 
PC compatibles since probably before you were able to do long division - 
including writing code on the first prototype IBM PCs, the first 
pre-manufacturing PC-ATs, and zillions of clones.  (and I was also 
involved in designing hardware including the so-called "Lotus Intel" 
expanded memory cards and the original PC cards)  The 8259 PIC is an 
*interrupt controller*. It was NEVER present in a Super I/O chip, or an 
LPC chip.  Its functionality was absorbed into the chipsets that control 
interrupt mapping, like the PIIX and the nForce. 

> And the "if it ain't broken, don't fix
> it" mantra probably means that some modern chipsets are still using
> exactly the same internal design as the 25 year old chips and will
> still be subject to some of those ancient limitations.
>   
Oh, come on.  Give the VLSI designers some credit for brains.   The CAD 
tools used to design the 8259 and 8253 were so primitive you couldn't 
even get a chip manufactured with designs from that era today.  When 
people design chips today they do it with simulators that can't even 
work, and testers that run from test suites that were not available at 
the time.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 20:28                                                       ` David P. Reed
@ 2008-01-08 21:43                                                         ` Christer Weinigel
  2008-01-08 22:24                                                           ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: Christer Weinigel @ 2008-01-08 21:43 UTC (permalink / raw)
  To: David P. Reed
  Cc: Ondrej Zary, H. Peter Anvin, Rene Herman, Bodo Eggert,
	Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Tue, 08 Jan 2008 15:28:03 -0500
"David P. Reed" <dpreed@reed.com> wrote:

> Register compatible.  Not  the same chips or even the same  masks or 
> timing requirements.

No, but somehow people keep making similar mistakes.  The DEC HiNote
needed outb_p to function correctly?  That was definitely a much more
modern design than the original PC and most probably did not use any
discrete Intel chips, but the same timing problems were there.  I belive
that problem had to do with the keyboard controller though.

> > The discrete Intel
> > chips or clones got aggregated into Super I/O chips, and the Super
> > I/O chips were put on a LPC bus (an ISA bus with another name) or
> > integrated into the southbrige.
> Don't try to teach your grandmother to suck eggs: I've been
> programming PC compatibles since probably before you were able to do
> long division - including writing code on the first prototype IBM
> PCs, the first pre-manufacturing PC-ATs, and zillions of clones.
> (and I was also involved in designing hardware including the
> so-called "Lotus Intel" expanded memory cards and the original PC
> cards)  

Argument by personal authority.  Thats good.  I guess that's why you
don't seem to understand the difference between reading the serial port
status register and not being allowed to access a register at all
due to such this as the 4 cycle delay you quoted yourself from the 8390
data sheet, and similar issues with the I8253 that I quoted from its
data sheet a few posts ago.

> The 8259 PIC is an *interrupt controller*. It was NEVER
> present in a Super I/O chip, or an LPC chip.  Its functionality was
> absorbed into the chipsets that control interrupt mapping, like the
> PIIX and the nForce. 

Yup, sorry about that, it got integrated into some other chip instead.
I was thinking of another timer, the RTC which is usually a part of the
Super I/O. And which is yet another troublesome area since apparently a
lot of chipsets have problems with it.  But the sequence is the same,
discrete chips get aggregated into larger chips. Sometimes the
sometimes old macrocells are reused, sometimes they are redesigned from
scratch (and new bugs are introduced).

> > And the "if it ain't broken, don't fix
> > it" mantra probably means that some modern chipsets are still using
> > exactly the same internal design as the 25 year old chips and will
> > still be subject to some of those ancient limitations.
> >   
> Oh, come on.  Give the VLSI designers some credit for brains.   The
> CAD tools used to design the 8259 and 8253 were so primitive you
> couldn't even get a chip manufactured with designs from that era
> today.  When people design chips today they do it with simulators
> that can't even work, and testers that run from test suites that were
> not available at the time.

And they still keep making the same mistakes...  Registers that require
wait states before being read again, register that assume that there
are going to be some spare cycles between each access so that some
internal logic has time to update, registers that would have needed a
one byte FIFO to avoid DMA overruns (I'd almost forgotten about that
specific bug on SPI controller of the Samsung 2410, but it bit me last
week and I only managed to chase it down properly yesterday), and so on.

I'm quite impressed with what some VLSI designers manage to do.  I just
saw a company roll out a completely new ARM9 design with lots of fun
stuff and as far as I know they only made one single mistake on that
chip.  On the other hand, on other designs you can see how the same old
macrocell has been reused long past the "best before" date, because
some bugs crop up over and over again.  

  /Christer

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 21:43                                                         ` Christer Weinigel
@ 2008-01-08 22:24                                                           ` David P. Reed
  0 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2008-01-08 22:24 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Ondrej Zary, H. Peter Anvin, Rene Herman, Bodo Eggert,
	Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Christer Weinigel wrote:
> Argument by personal authority.  Thats good.
There is no other kind of argument.  Are you claiming supernatural 
authority drives your typing fingers, or is your argument based on what 
you think you know?  I have piles of code that I wrote, spec sheets (now 
that I'm back in my home office), code that others wrote at the time, 
and documentation from vendors that come from my personal experiences.  
That doesn't mean I'm always right - always happy to learn something 
new.  Just don't condescend to a 55 year old who has been writing 
operating systems, compilers, and designing hardware for almost 40 years 
professionally (yes, I got my first job at 16 writing FORTRAN code to 
simulate hydrodynamic systems).
> I guess that's why you
> don't seem to understand the difference between reading the serial port
> status register and not being allowed to access a register at all
> due to such this as the 4 cycle delay you quoted yourself from the 8390
> data sheet,
If you read what I said carefully, I said that the 8390 was a very 
special case.   The "chip select" problem it experienced was pretty much 
unique among boards of the time.  Those of us who looked at its design 
and had any experience designing hardware for buses like the unibus or 
even the buses on PDP-8's and DG machines thought it had to be a joke.  
Of course it saved money per board, so it beat the 3Com boards on price 
- and you could program it after a fashion.  So it involved "cheaping out".

The normal timing problem was that an out or in operation to a board or 
chip required some time to elapse before the chip performed the side 
effects internally so that the next operation to it would have an 
effect.  This is exactly the reason why most chips and boards are 
designed to either have a polling of a flag indicate operation 
completion.  The serial "buffer empty" flag is the simplest possible 
explanatory example of such handshaking that came to mind (writing a 
character to a serial output device twice often leads to surprises, 
unless you wait for the previous character to clock out).  See my 
comment on RTC below, for a more complex to explain example.
> and similar issues with the I8253 that I quoted from its
> data sheet a few posts ago.
>
>   
The 8253 was a motherboard chip.  I am not sure it had any timing 
problems with its electrical signalling.  I just don't remember.  The 
spec sheet doesn't say it's internal state can get scrambled.
>
> I was thinking of another timer, the RTC which is usually a part of the
> Super I/O.
The RTC has very well documented timing requirements.  But none of the 
spec sheets, nor my experience with it, mention electrical issues that 
prevented back-to-back port operations.  The documented timing 
requirements have to do with the state during the time it ticks over 
internally once per second.  But it is carefully designed to have a flag 
that is "on" during 244 microseconds prior to and covering the time it 
is unsafe to read the registers.   That design is special because it is 
designed to operate when the machine is powered off, so it has two 
internal clock domains, one of which is used in "low power" mode and is 
very slow to minimize power.


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-08 19:15                                                       ` David P. Reed
  2008-01-08 19:23                                                         ` Alan Cox
@ 2008-01-09  2:52                                                         ` Zachary Amsden
  2008-01-09  5:19                                                           ` H. Peter Anvin
  2008-01-09  5:30                                                           ` Christer Weinigel
  1 sibling, 2 replies; 243+ messages in thread
From: Zachary Amsden @ 2008-01-09  2:52 UTC (permalink / raw)
  To: David P. Reed, Avi Kivity
  Cc: Christer Weinigel, Ondrej Zary, H. Peter Anvin, Rene Herman,
	Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Tue, 2008-01-08 at 14:15 -0500, David P. Reed wrote:
> Alan Cox wrote:
> > The natsemi docs here say otherwise. I trust them not you.
> >   
> As well you should. I am honestly curious (for my own satisfaction) as 
> to what the natsemi docs say the delay code should do  (can't imagine 
> they say "use io port 80 because it is unused").  I don't have any 

What is the outcome of this thread?  Are we going to use timing based
port delays, or can we finally drop these things entirely on 64-bit
architectures?

I a have a doubly vested interest in this, both as the owner of an
affected HP dv9210us laptop and as a maintainer of paravirt code - and
would like 64-bit Linux code to stop using I/O to port 0x80 in both
cases (as I suspect would every other person involved with
virtualization).

BTW, it isn't ever safe to pass port 0x80 through to hardware from a
virtual machine; some OSes use port 0x80 as a hardware available scratch
register (I believe Darwin/x86 did/does this during boot).  This means
simultaneous execution of two virtual machines can interleave port 0x80
values or share data with a hardware provided covert channel.  This
means KVM should be trapping port 0x80 access, which is really
expensive, or alternatively, Linux should not be using port 0x80 for
timing bus access on modern (64-bit) hardware.

I've tried to follow this thread, but with all the jabs, 1-ups, and
obscure legacy hardware pageantry going on, it isn't clear what we're
really doing.

Thanks,

Zach


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09  2:52                                                         ` Zachary Amsden
@ 2008-01-09  5:19                                                           ` H. Peter Anvin
  2008-01-09 21:53                                                             ` Zachary Amsden
  2008-01-09  5:30                                                           ` Christer Weinigel
  1 sibling, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-09  5:19 UTC (permalink / raw)
  To: Zachary Amsden
  Cc: David P. Reed, Avi Kivity, Christer Weinigel, Ondrej Zary,
	Rene Herman, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Zachary Amsden wrote:
> 
> BTW, it isn't ever safe to pass port 0x80 through to hardware from a
> virtual machine; some OSes use port 0x80 as a hardware available scratch
> register (I believe Darwin/x86 did/does this during boot).

That's funny, because there is definitely no guarantee that you get back 
what you read (well, perhaps there is on Apple.)

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09  2:52                                                         ` Zachary Amsden
  2008-01-09  5:19                                                           ` H. Peter Anvin
@ 2008-01-09  5:30                                                           ` Christer Weinigel
  2008-01-09 14:42                                                             ` David P. Reed
  2008-01-09 15:27                                                             ` Rene Herman
  1 sibling, 2 replies; 243+ messages in thread
From: Christer Weinigel @ 2008-01-09  5:30 UTC (permalink / raw)
  To: Zachary Amsden
  Cc: David P. Reed, Avi Kivity, Ondrej Zary, H. Peter Anvin,
	Rene Herman, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Tue, 08 Jan 2008 18:52:42 -0800
Zachary Amsden <zach@vmware.com> wrote:

> On Tue, 2008-01-08 at 14:15 -0500, David P. Reed wrote:
> > Alan Cox wrote:
> > > The natsemi docs here say otherwise. I trust them not you.
> > >   
> > As well you should. I am honestly curious (for my own satisfaction)
> > as to what the natsemi docs say the delay code should do  (can't
> > imagine they say "use io port 80 because it is unused").  I don't
> > have any 
> 
> What is the outcome of this thread?  Are we going to use timing based
> port delays, or can we finally drop these things entirely on 64-bit
> architectures?
> 
> I a have a doubly vested interest in this, both as the owner of an
> affected HP dv9210us laptop and as a maintainer of paravirt code - and
> would like 64-bit Linux code to stop using I/O to port 0x80 in both
> cases (as I suspect would every other person involved with
> virtualization).
> 
> I've tried to follow this thread, but with all the jabs, 1-ups, and
> obscure legacy hardware pageantry going on, it isn't clear what we're
> really doing.

I belive Alan Cox is doing a review of some drivers, to see if they
actually need the I/O port delay.  A lot of drivers probably use outb_p
just because it was copy-pasted from some other driver and it can be
removed.  Alan's review has also brought to light a lack of locking in
some drivers, so I think Alan has been adding proper locking to some of
the watchdog drivers.

Most old ISA only device drivers can keep using OUT 80h.  They are not
used on modern machines and it's better to keep them unchanged to avoid
unneccesary incompatibilities.

As far as I know, the 8253 PIT timer code needs outb_p on some older
platform, and this is one of the most troublesome since the same PIT
controller (or a register compatible one) has been used since the
original IBM PC, and it is frequently executed code.  Ingo Molnar has
done an alternate implementation of the PIT clock source which uses
udelay instead of OUT 80h to delay accesses to the ports. The kernel
could make a choice of which variant to use based on the DMI year, if
compiling for x86_64, or something similar.  Maybe have a command line
option too.

The keyboard controller on some platform needs the delay, and the same
driver is used on both ancient and modern systems, I think it can be
changed to udelay since it's not so time critical code.

The 8259 interrupt controller on some platform needs the delay, I think
it can be changed to udelay since it's only some setup code that uses
outb_p.  I guess there are time critical accesses to the interrupt
controller from assembly code somewhere to acknowledge interrupts, and
that code needs a review.

The floppy controller code uses outb_p.  Even though there might be
floppy controllers on modern systems, I'd rather leave the floppy code
alone since it's supposed to be very fragile.  If you still use
floppies you deserve what you get.

Some specific drivers, such as drivers for 8390 or 8390 clone based
network cards are also a bit troublesome, they do need outb_p (and
the delay for the original 8390 chip is specified in bus cycles), and
there can be a big performance loss if pessimistic udelays are used for
the delay.  There are still a bunch of PCMCIA cards based on that chip
which means that those cards can be used with modern machines.  There
are also PCI and memory mapped variants of the 8390, some of them new
designs which are only register compatible, some other designs are
using a real 8390 with a FPGA used as glue logic. I think Alan
suggested compiling two versions of that driver, one with OUT 80h, and
one with udelay.  Old machines can choose the old driver, and new
machines can use the new one.  Other drivers can probably do the same
thing, or if not time critical, always use a pessimistic udelay.

As for the implementation, I like the suggestion to split outb_b into
two calls, one to outb and one to isa_slow_down_io.  It makes it very
obvious that it is really two function calls, and that it needs
locking.  For those uses that are not ISA port accesses,
isa_slow_down_io should be changed to an appropriate udelay instead.

The goal is anyway that a modern machine should not do OUT 80h, and old
machines keep doing it since it has been working well for some 15-odd
years, both in DOS device drivers and on Linux.  Using an alternate
port may be a workaround, but it's probaby not a good idea since
alternate ports have received less testing and there's bound to be some
platform out there that has problems with any alternate port we
might choose.  Allowing an alternate port will also add code bloat
(OUT 80h, AL becomes MOV DX, alternate_port; OUT DX, AL) for a
dubious gain.

Did I miss anyting?

  /Christer

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09  5:30                                                           ` Christer Weinigel
@ 2008-01-09 14:42                                                             ` David P. Reed
  2008-01-09 15:27                                                             ` Rene Herman
  1 sibling, 0 replies; 243+ messages in thread
From: David P. Reed @ 2008-01-09 14:42 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Zachary Amsden, Avi Kivity, Ondrej Zary, H. Peter Anvin,
	Rene Herman, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Christer Weinigel wrote:
>
> Did I miss anyting?
>
>   
Nothing that seems *crucial* going forward for Linux.  The fate of
"legacy machines" is really important to get right.

I have a small suggestion in mind that might be helpful in the future:
the  "motherboard resources" discovered as PNP0C02 devices in their _CRS
settings in ACPI during ACPI PnP startup should be reserved (or
checked), and any drivers that still use port 80 implicitly should
reserve that port.

This may be too late in the boot process to make a decision not to use 
port 80, and it
doesn't help decide a strategy to use an alternate port (0xED happens to
"work" on the dv9000 machines in the sense that it generates a bus
timeout on LPC, but there is no guarantee that 0xED is free on any 
particular motherboard, and "unusedness" is not declared in any 
BIOS/ACPI tables) or to use a udelay-based iodelay (but there is nothing 
in the BIOS tables that suggest the right delays for various I/O ports 
if any modern parts need them...which I question, but can't prove a 
negative in general).

However, doing the reservations on such resources could generate a 
warning that would help diagnose new current and future
designs including devices like the ENE KB3920 that have a port that is
defaulted to port 80 and routed to the EC for functions that the 
firmware and ACPI can agree to do.  Or any other ports used in new ways 
and properly notified to the OS via the now-standard Wintel BIOS functions.

I don't know if /proc/ioports is being maintained, but the fact that it
doesn't contain all of those PNP0C02 resources known on my machine seems 
to be a bug - which I am happy to code a patch or two for as a 
contribution back to Linux, if it isn't on the way out as the /sys 
hierarchy does a better job.
/sys/bus/pnp/... does get built properly and has port 80 described
properly - not as a DMA port, but as a port in use by device 05:00, 
which is the motherboard resource catchall.  Thus the patch would be small.



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09  5:30                                                           ` Christer Weinigel
  2008-01-09 14:42                                                             ` David P. Reed
@ 2008-01-09 15:27                                                             ` Rene Herman
  2008-01-09 18:17                                                               ` Zachary Amsden
  1 sibling, 1 reply; 243+ messages in thread
From: Rene Herman @ 2008-01-09 15:27 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Zachary Amsden, David P. Reed, Avi Kivity, Ondrej Zary,
	H. Peter Anvin, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 09-01-08 06:30, Christer Weinigel wrote:

> On Tue, 08 Jan 2008 18:52:42 -0800
> Zachary Amsden <zach@vmware.com> wrote:

>> What is the outcome of this thread?  Are we going to use timing based
>> port delays, or can we finally drop these things entirely on 64-bit
>> architectures?
>>
>> I a have a doubly vested interest in this, both as the owner of an
>> affected HP dv9210us laptop and as a maintainer of paravirt code - and
>> would like 64-bit Linux code to stop using I/O to port 0x80 in both
>> cases (as I suspect would every other person involved with
>> virtualization).
>>
>> I've tried to follow this thread, but with all the jabs, 1-ups, and
>> obscure legacy hardware pageantry going on, it isn't clear what we're
>> really doing.
> 
> I belive Alan Cox is doing a review of some drivers, to see if they
> actually need the I/O port delay.  A lot of drivers probably use outb_p
> just because it was copy-pasted from some other driver and it can be
> removed.  Alan's review has also brought to light a lack of locking in
> some drivers, so I think Alan has been adding proper locking to some of
> the watchdog drivers.

Yes, Alan should be considered to be in the driver seat here (and current 
x86.git changes should be tossed).

> Most old ISA only device drivers can keep using OUT 80h.  They are not
> used on modern machines and it's better to keep them unchanged to avoid
> unneccesary incompatibilities.
> 
> As far as I know, the 8253 PIT timer code needs outb_p on some older
> platform, and this is one of the most troublesome since the same PIT
> controller (or a register compatible one) has been used since the
> original IBM PC, and it is frequently executed code.  Ingo Molnar has
> done an alternate implementation of the PIT clock source which uses
> udelay instead of OUT 80h to delay accesses to the ports. The kernel
> could make a choice of which variant to use based on the DMI year, if
> compiling for x86_64, or something similar.  Maybe have a command line
> option too.

Just udelay() should be fine after "fixing" udelay() to be somewhat usefully 
defined pre-calibration.

> The keyboard controller on some platform needs the delay, and the same
> driver is used on both ancient and modern systems, I think it can be
> changed to udelay since it's not so time critical code.
> 
> The 8259 interrupt controller on some platform needs the delay, I think
> it can be changed to udelay since it's only some setup code that uses
> outb_p.  I guess there are time critical accesses to the interrupt
> controller from assembly code somewhere to acknowledge interrupts, and
> that code needs a review.

I'd not expect very time crtical. The current outb_p use gives a delay 
somewhere between .5 and 2 microseconds as per earlier survey meaning a 
udelay(1) or 2 would be enough -- again, at the point that udelay() is sensible.

New machines don't use the legacy PIC anymore anyway.

> The floppy controller code uses outb_p.  Even though there might be
> floppy controllers on modern systems, I'd rather leave the floppy code
> alone since it's supposed to be very fragile.  If you still use
> floppies you deserve what you get.

Floppies forever. In practice, leaving it alone isn't going to matter, but 
in that same practice changing it to udelay() probably doesn't either. The 
ones to leave alone are the ones that are clumsy/impossible to test and the 
ones such as in NIC drivers that were specifically tuned.

> Some specific drivers, such as drivers for 8390 or 8390 clone based
> network cards are also a bit troublesome, they do need outb_p (and
> the delay for the original 8390 chip is specified in bus cycles), and
> there can be a big performance loss if pessimistic udelays are used for
> the delay.  There are still a bunch of PCMCIA cards based on that chip
> which means that those cards can be used with modern machines.  There
> are also PCI and memory mapped variants of the 8390, some of them new
> designs which are only register compatible, some other designs are
> using a real 8390 with a FPGA used as glue logic. I think Alan
> suggested compiling two versions of that driver, one with OUT 80h, and
> one with udelay.  Old machines can choose the old driver, and new
> machines can use the new one.  Other drivers can probably do the same
> thing, or if not time critical, always use a pessimistic udelay.

Not sure what the final suggestion for those was either....

> As for the implementation, I like the suggestion to split outb_b into
> two calls, one to outb and one to isa_slow_down_io.  It makes it very
> obvious that it is really two function calls, and that it needs
> locking.  For those uses that are not ISA port accesses,
> isa_slow_down_io should be changed to an appropriate udelay instead.

... or simply deleted. The current outb_p is "outb; slow_down_io" as a macro 
so that with this you also get no binary changes, making it rather easy to 
prove that things do not change timing in cases where you keep the delay.

(they're not so much function calls though -- they're inlined).

> The goal is anyway that a modern machine should not do OUT 80h, and old
> machines keep doing it since it has been working well for some 15-odd
> years, both in DOS device drivers and on Linux.  Using an alternate
> port may be a workaround, but it's probaby not a good idea since
> alternate ports have received less testing and there's bound to be some
> platform out there that has problems with any alternate port we
> might choose.

Based on specific DMI strings this can be limited to tested machines (as in 
current x86.git) but yes, that's not particularly pleasing.

> Allowing an alternate port will also add code bloat (OUT 80h, AL becomes
> MOV DX, alternate_port; OUT DX, AL) for a dubious gain.


... destroying DX while it's at it meaning this might (will) also need DX 
reloads. Not an argument versus a function call, but an argument versus the 
current and proposed manual "outb; slow_down_io" split.

> Did I miss anyting?

Not so much it seems. Only that the only reason for the outb_p slit is an 
API one. Molnar wants the API cleaned up to make sure no new users of outb_p 
creep in, and being explkicit abhout what it that you're doing is going to 
take care of that.

If simple outb_p() deprecation is considered enough instead, no need to 
touch anything in drivers/, only changes to "outb(); udelay()" outside drivers/.

I'd let Alan decide here.

Thanks for the roundup.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-01 21:44                                                                   ` H. Peter Anvin
  2008-01-01 22:35                                                                     ` Rene Herman
@ 2008-01-09 17:27                                                                     ` Maciej W. Rozycki
  2008-01-09 18:18                                                                       ` H. Peter Anvin
  1 sibling, 1 reply; 243+ messages in thread
From: Maciej W. Rozycki @ 2008-01-09 17:27 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Rene Herman, Alan Cox, David P. Reed, Rene Herman, Ingo Molnar,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On Tue, 1 Jan 2008, H. Peter Anvin wrote:

> It's specifically a side effect *we don't care about*, except in the
> by-now-somewhat-exotic case of 386+387 (where we indeed can't use it once user
> code has touched the FPU -- but we can fall back to 0x80 on those, a very
> small number of systems.)  486+ doesn't use this interface under Linux, since
> Linux uses the proper exception path on those processors.  If Compaq had wired
> up the proper signals on the first 386 PC motherboards, we wouldn't have cared
> about it on the 386 either.

 It was actually IBM who broke it with the 80286-based PC/AT because of 
the BIOS compatibility -- the vector #0x10 had already been claimed by the 
original PC for the video software interrupt call (apparently against 
Intel's recommendation not to use low 32 interrupt vectors for such 
purposes), so it could not have been reused as is for FP exception 
handling without breaking existing software.  I suppose a more complicated 
piece of glue logic could have been used along the lines of what 
eventually went into the i486, but presumably the relatively low level of 
integration of the PC/AT made such additional circuits hard to justify 
even if it indeed was considered.

  Maciej

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09 15:27                                                             ` Rene Herman
@ 2008-01-09 18:17                                                               ` Zachary Amsden
  2008-01-09 18:18                                                                 ` H. Peter Anvin
  2008-01-09 18:22                                                                 ` Adrian Bunk
  0 siblings, 2 replies; 243+ messages in thread
From: Zachary Amsden @ 2008-01-09 18:17 UTC (permalink / raw)
  To: Rene Herman
  Cc: Christer Weinigel, David P. Reed, Avi Kivity, Ondrej Zary,
	H. Peter Anvin, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Wed, 2008-01-09 at 16:27 +0100, Rene Herman wrote:
> On 09-01-08 06:30, Christer Weinigel wrote:
> I'd not expect very time crtical. The current outb_p use gives a delay 
> somewhere between .5 and 2 microseconds as per earlier survey meaning a 
> udelay(1) or 2 would be enough -- again, at the point that udelay() is sensible.
> 
> New machines don't use the legacy PIC anymore anyway.
> 
> > The floppy controller code uses outb_p.  Even though there might be
> > floppy controllers on modern systems, I'd rather leave the floppy code
> > alone since it's supposed to be very fragile.  If you still use
> > floppies you deserve what you get.
> 
> Floppies forever. In practice, leaving it alone isn't going to matter, but 
> in that same practice changing it to udelay() probably doesn't either. The 
> ones to leave alone are the ones that are clumsy/impossible to test and the 
> ones such as in NIC drivers that were specifically tuned.

I'm speaking specifically in terms of 64-bit platforms here.  Shouldn't
we unconditionally drop outb_p doing extra port I/O on 64-bit
architectures?  Especially considering they don't even have an ISA bus
where the decode timing could even matter?

> If simple outb_p() deprecation is considered enough instead, no need to 
> touch anything in drivers/, only changes to "outb(); udelay()" outside drivers/.
> 
> I'd let Alan decide here.

Agree.

Zach


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09 18:17                                                               ` Zachary Amsden
@ 2008-01-09 18:18                                                                 ` H. Peter Anvin
  2008-01-09 20:26                                                                   ` Christer Weinigel
  2008-01-09 18:22                                                                 ` Adrian Bunk
  1 sibling, 1 reply; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-09 18:18 UTC (permalink / raw)
  To: Zachary Amsden
  Cc: Rene Herman, Christer Weinigel, David P. Reed, Avi Kivity,
	Ondrej Zary, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Zachary Amsden wrote:
> 
> I'm speaking specifically in terms of 64-bit platforms here.  Shouldn't
> we unconditionally drop outb_p doing extra port I/O on 64-bit
> architectures?  Especially considering they don't even have an ISA bus
> where the decode timing could even matter?
> 

Why should the bitsize of the CPU matter for this?  It seems one of the 
less meaningful keys for this.

Second, as I have mentioned, I don't believe this is really the case, 
especially not for the PIT, which is still present -- the PIT 
*semantics* has explicit timing constraints.

Third, you still have ISA devices, they're just called LPC or PC104 
devices these days.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09 17:27                                                                     ` Maciej W. Rozycki
@ 2008-01-09 18:18                                                                       ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-09 18:18 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Rene Herman, Alan Cox, David P. Reed, Rene Herman, Ingo Molnar,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

Maciej W. Rozycki wrote:
> On Tue, 1 Jan 2008, H. Peter Anvin wrote:
> 
>> It's specifically a side effect *we don't care about*, except in the
>> by-now-somewhat-exotic case of 386+387 (where we indeed can't use it once user
>> code has touched the FPU -- but we can fall back to 0x80 on those, a very
>> small number of systems.)  486+ doesn't use this interface under Linux, since
>> Linux uses the proper exception path on those processors.  If Compaq had wired
>> up the proper signals on the first 386 PC motherboards, we wouldn't have cared
>> about it on the 386 either.
> 
>  It was actually IBM who broke it with the 80286-based PC/AT because of 
> the BIOS compatibility -- the vector #0x10 had already been claimed by the 
> original PC for the video software interrupt call (apparently against 
> Intel's recommendation not to use low 32 interrupt vectors for such 
> purposes), so it could not have been reused as is for FP exception 
> handling without breaking existing software.  I suppose a more complicated 
> piece of glue logic could have been used along the lines of what 
> eventually went into the i486, but presumably the relatively low level of 
> integration of the PC/AT made such additional circuits hard to justify 
> even if it indeed was considered.
> 

Supposedly the reason was that the DOS-less "cassette BASIC" delivered 
by Microsoft used all the INT instructions except the reserved ones as a 
weird bytecode interpreter.  Bill Gates was fond of that kind of hacks.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09 18:17                                                               ` Zachary Amsden
  2008-01-09 18:18                                                                 ` H. Peter Anvin
@ 2008-01-09 18:22                                                                 ` Adrian Bunk
  2008-01-09 18:27                                                                   ` H. Peter Anvin
  1 sibling, 1 reply; 243+ messages in thread
From: Adrian Bunk @ 2008-01-09 18:22 UTC (permalink / raw)
  To: Zachary Amsden
  Cc: Rene Herman, Christer Weinigel, David P. Reed, Avi Kivity,
	Ondrej Zary, H. Peter Anvin, Bodo Eggert, Ingo Molnar, Alan Cox,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On Wed, Jan 09, 2008 at 10:17:24AM -0800, Zachary Amsden wrote:
> On Wed, 2008-01-09 at 16:27 +0100, Rene Herman wrote:
> > On 09-01-08 06:30, Christer Weinigel wrote:
> > I'd not expect very time crtical. The current outb_p use gives a delay 
> > somewhere between .5 and 2 microseconds as per earlier survey meaning a 
> > udelay(1) or 2 would be enough -- again, at the point that udelay() is sensible.
> > 
> > New machines don't use the legacy PIC anymore anyway.
> > 
> > > The floppy controller code uses outb_p.  Even though there might be
> > > floppy controllers on modern systems, I'd rather leave the floppy code
> > > alone since it's supposed to be very fragile.  If you still use
> > > floppies you deserve what you get.
> > 
> > Floppies forever. In practice, leaving it alone isn't going to matter, but 
> > in that same practice changing it to udelay() probably doesn't either. The 
> > ones to leave alone are the ones that are clumsy/impossible to test and the 
> > ones such as in NIC drivers that were specifically tuned.
> 
> I'm speaking specifically in terms of 64-bit platforms here.  Shouldn't
> we unconditionally drop outb_p doing extra port I/O on 64-bit
> architectures?  Especially considering they don't even have an ISA bus
> where the decode timing could even matter?
>...

I don't think the latter statement was true - AFAIR there are Alphas 
with ISA slots.

> Agree.
> 
> Zach

cu
Adrian

-- 

       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09 18:22                                                                 ` Adrian Bunk
@ 2008-01-09 18:27                                                                   ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-09 18:27 UTC (permalink / raw)
  To: Adrian Bunk
  Cc: Zachary Amsden, Rene Herman, Christer Weinigel, David P. Reed,
	Avi Kivity, Ondrej Zary, Bodo Eggert, Ingo Molnar, Alan Cox,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

Adrian Bunk wrote:
> 
> I don't think the latter statement was true - AFAIR there are Alphas 
> with ISA slots.
> 

See subject line.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09 18:18                                                                 ` H. Peter Anvin
@ 2008-01-09 20:26                                                                   ` Christer Weinigel
  2008-01-09 21:59                                                                     ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: Christer Weinigel @ 2008-01-09 20:26 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Zachary Amsden, Rene Herman, David P. Reed, Avi Kivity,
	Ondrej Zary, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Wed, 09 Jan 2008 10:18:11 -0800
"H. Peter Anvin" <hpa@zytor.com> wrote:

> Zachary Amsden wrote:
> > 
> > I'm speaking specifically in terms of 64-bit platforms here.
> > Shouldn't we unconditionally drop outb_p doing extra port I/O on
> > 64-bit architectures?  Especially considering they don't even have
> > an ISA bus where the decode timing could even matter?
> > 
> 
> Why should the bitsize of the CPU matter for this?  It seems one of
> the less meaningful keys for this.

Well, anything that runs x86_64 should be a fairly modern system.
 
> Second, as I have mentioned, I don't believe this is really the case, 
> especially not for the PIT, which is still present -- the PIT 
> *semantics* has explicit timing constraints.
> 
> Third, you still have ISA devices, they're just called LPC or PC104 
> devices these days.

Or PCMCIA.  I'm still a happy user of a Zyxel ZyAIR 100B, it's one of
the most stable cards Wifi I've got running under Linux.   :-)

  /Christer

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09  5:19                                                           ` H. Peter Anvin
@ 2008-01-09 21:53                                                             ` Zachary Amsden
  2008-01-09 22:22                                                               ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: Zachary Amsden @ 2008-01-09 21:53 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: David P. Reed, Avi Kivity, Christer Weinigel, Ondrej Zary,
	Rene Herman, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Tue, 2008-01-08 at 21:19 -0800, H. Peter Anvin wrote:
> Zachary Amsden wrote:
> > 
> > BTW, it isn't ever safe to pass port 0x80 through to hardware from a
> > virtual machine; some OSes use port 0x80 as a hardware available scratch
> > register (I believe Darwin/x86 did/does this during boot).
> 
> That's funny, because there is definitely no guarantee that you get back 
> what you read (well, perhaps there is on Apple.)

According to Phoenix Technologies book "System BIOS for IBM PCs,
Compatibles and EISA Computers, 2nd Edition", the I/O port list gives

port 0080h   R/W  Extra page register (temporary storage)

Despite looking, I've never seen it documented anywhere else, but I
believe it works on just about every PC platform.  Except, apparently,
my laptop.

Zach


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09 20:26                                                                   ` Christer Weinigel
@ 2008-01-09 21:59                                                                     ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-09 21:59 UTC (permalink / raw)
  To: Christer Weinigel
  Cc: Zachary Amsden, Rene Herman, David P. Reed, Avi Kivity,
	Ondrej Zary, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Christer Weinigel wrote:
> On Wed, 09 Jan 2008 10:18:11 -0800
> "H. Peter Anvin" <hpa@zytor.com> wrote:
> 
>> Zachary Amsden wrote:
>>> I'm speaking specifically in terms of 64-bit platforms here.
>>> Shouldn't we unconditionally drop outb_p doing extra port I/O on
>>> 64-bit architectures?  Especially considering they don't even have
>>> an ISA bus where the decode timing could even matter?
>>>
>> Why should the bitsize of the CPU matter for this?  It seems one of
>> the less meaningful keys for this.
> 
> Well, anything that runs x86_64 should be a fairly modern system.
>  

Yes, but you hardly want a situation where the machine works booting a 
32-bit kernel and not a 64-bit kernel, or vice versa.

Furthermore, it's not so much about "modern" versus "old", it is about 
picking a certain set of bugs.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09 21:53                                                             ` Zachary Amsden
@ 2008-01-09 22:22                                                               ` David P. Reed
  2008-01-11  1:36                                                                 ` Zachary Amsden
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-09 22:22 UTC (permalink / raw)
  To: Zachary Amsden
  Cc: H. Peter Anvin, Avi Kivity, Christer Weinigel, Ondrej Zary,
	Rene Herman, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Zachary Amsden wrote:
>
> According to Phoenix Technologies book "System BIOS for IBM PCs,
> Compatibles and EISA Computers, 2nd Edition", the I/O port list gives
>
> port 0080h   R/W  Extra page register (temporary storage)
>
> Despite looking, I've never seen it documented anywhere else, but I
> believe it works on just about every PC platform.  Except, apparently,
> my laptop.
>
>
>   
The port 80 problem was discovered by me, after months of "bisecting" 
the running code around a problem with hanging when using hwclock in 
64-bit mode when ACPI is on.  So it kills my laptop, too, and many 
currentlaptop motherboards designed by Quanta for HP and Compaq (dv6000, 
dv9000, tx1000, apparently)

In the last couple of weeks, I was able with luck to discover that the 
problem is the ENE KB3920 chip, which is the "big brother" of the KB3700 
chip included in the OLPC XO "$100 laptop" made also by Quanta.  I 
verified this by taking my laptop apart - a fun and risky experience.  
Didn't break any connectors, but I don't recommend it for those who are 
not experienced disassembling laptops and cellphones, etc.  The KB3920 
contains an EC, an SMBus, a KBC, some watchdog timers, and a variety of 
other functions that keep the laptop going, coordinating the 
relationships among various peripherals.  The firmware is part standard 
from ENE, part OEM-specific, in this case coded by Quanta or a BIOS 
subcontractor.

You can read the specsheet for the KB3700 online at laptop.org, since 
the specs of the laptop are "open".  The 3920's spec is confidential.  
And the firmware is confidential as well for both the 3700 and 3920.  
Clues as to what it does can be gleaned by reading the disassembler 
output of the DSDT code in the particular laptops - though the SMM BIOS 
probably also talks to it.

Modern machines have many subsystems, and the ACPI and SMBIOS coordinate 
to run them; blade servers also have drawer controllers and backplane 
management buses.  The part that runs Linux is only part of the machine.

Your laptop isn't an aberration.  It's part of the new generation of 
evolved machines that take advantage of the capabilities of ACPI and 
SMBIOS and DMI standards that are becoming core parts of the market.



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
       [not found]         ` <fa.97XrGLIGlvAy4P/TB5vHHrfBrIw@ifi.uio.no>
@ 2008-01-10  0:37           ` Robert Hancock
  2008-01-10  0:44             ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: Robert Hancock @ 2008-01-10  0:37 UTC (permalink / raw)
  To: David P. Reed
  Cc: Christer Weinigel, Zachary Amsden, Avi Kivity, Ondrej Zary,
	H. Peter Anvin, Rene Herman, Bodo Eggert, Ingo Molnar, Alan Cox,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

David P. Reed wrote:
> Christer Weinigel wrote:
>>
>> Did I miss anyting?
>>
>>   
> Nothing that seems *crucial* going forward for Linux.  The fate of
> "legacy machines" is really important to get right.
> 
> I have a small suggestion in mind that might be helpful in the future:
> the  "motherboard resources" discovered as PNP0C02 devices in their _CRS
> settings in ACPI during ACPI PnP startup should be reserved (or
> checked), and any drivers that still use port 80 implicitly should
> reserve that port.

I agree. In this case the BIOS on these laptops is trying to tell us 
"port 80 is used for our purposes, do not touch it". We should be listening.

-- 
Robert Hancock      Saskatoon, SK, Canada
To email, remove "nospam" from hancockr@nospamshaw.ca
Home Page: http://www.roberthancock.com/


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-10  0:37           ` Robert Hancock
@ 2008-01-10  0:44             ` Rene Herman
  2008-01-10 14:41               ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2008-01-10  0:44 UTC (permalink / raw)
  To: Robert Hancock
  Cc: David P. Reed, Christer Weinigel, Zachary Amsden, Avi Kivity,
	Ondrej Zary, H. Peter Anvin, Bodo Eggert, Ingo Molnar, Alan Cox,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol

On 10-01-08 01:37, Robert Hancock wrote:

> David P. Reed wrote:

>> I have a small suggestion in mind that might be helpful in the future:
>> the  "motherboard resources" discovered as PNP0C02 devices in their _CRS
>> settings in ACPI during ACPI PnP startup should be reserved (or
>> checked), and any drivers that still use port 80 implicitly should
>> reserve that port.
> 
> I agree. In this case the BIOS on these laptops is trying to tell us 
> "port 80 is used for our purposes, do not touch it". We should be 
> listening.

Listening is fine but what are you going to do after you have listened? 
Right, not use port 0x80 but since that's the current idea anyway outside of 
legacy drivers, you don't actually need to listen.

If the quirk-to-0xed or similar was to stay, it's a much better switching 
point than DMI strings but if not, it's not actually important.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-10  0:44             ` Rene Herman
@ 2008-01-10 14:41               ` David P. Reed
  0 siblings, 0 replies; 243+ messages in thread
From: David P. Reed @ 2008-01-10 14:41 UTC (permalink / raw)
  To: Rene Herman
  Cc: Robert Hancock, Christer Weinigel, Zachary Amsden, Avi Kivity,
	Ondrej Zary, H. Peter Anvin, Bodo Eggert, Ingo Molnar, Alan Cox,
	Paul Rolland, Pavel Machek, Thomas Gleixner, linux-kernel,
	Ingo Molnar, rol


Rene Herman wrote:
> On 10-01-08 01:37, Robert Hancock wrote:
>>
>> I agree. In this case the BIOS on these laptops is trying to tell us 
>> "port 80 is used for our purposes, do not touch it". We should be 
>> listening.
>
> Listening is fine but what are you going to do after you have 
> listened? Right, not use port 0x80 but since that's the current idea 
> anyway outside of legacy drivers, you don't actually need to listen.
>
> If the quirk-to-0xed or similar was to stay, it's a much better 
> switching point than DMI strings but if not, it's not actually important.
Well, I was just suggesting a warning that would come up when a driver 
that still used port 80 was initialized...
I think that is what Alan Cox and others suggest for legacy drivers that 
have worked - I agree that it may not be the right thing to screw them 
up, especially since my laptop, and probably most machines that might 
start using port 80 or other "legacy ports" won't ever need those drivers.

I thought more about a complete solution last night.   A clean idea that 
really fits the linux design might be the following outline of a patch. 
I suspect it might seem far less ugly, and probably would meet Alan 
Cox's needs, too - I am very sympathetic about not breaking 8390's, etc.

Define a "motherboard resources" driver that claims all the resources 
defined for PNP0C02 devices during the pnp process.   I think Windoze 
actually does something quite similar.   This would claim port 80.

Define an iodelay driver.  This driver exists largely to claim port 80 
for the iodelay operation  (you could even define an option for other 
ports).  Legacy drivers would be modified to require iodelay.  The 
iodelay driver would set up the iodelay mechanism to do something other 
than the "boot time" default - which could be no delay, or udelay.  It 
would also set a flag that says "_b operations are safe".

Put a WARN_ONCE() in the in/out*_b operations that checks the flag that 
is set by the iodelay driver.  This would only trigger in the case that 
80 or whatever was reserved by some other device driver - such as the 
motherboard resources driver above.  Modern machines won't do that.

Finally, anything that happens before the motherboard resources and 
iodelay drivers are initialized cannot use in*_p or out*_p (whether they 
can be loadable modules rather than built in is a question).  This is a 
very small set, and I believe with the exception of the PIT (8253/4) are 
very safe.

Note that this idea is also compatible with rewriting all drivers to use 
"iodelay()" explicitly instead of _p().  But it doesn't require that.

>
> Rene.
>

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-09 22:22                                                               ` David P. Reed
@ 2008-01-11  1:36                                                                 ` Zachary Amsden
  2008-01-11  3:05                                                                   ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: Zachary Amsden @ 2008-01-11  1:36 UTC (permalink / raw)
  To: David P. Reed
  Cc: H. Peter Anvin, Christer Weinigel, Ondrej Zary, Rene Herman,
	Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On Wed, 2008-01-09 at 17:22 -0500, David P. Reed wrote:
> Zachary Amsden wrote:
> >
> > According to Phoenix Technologies book "System BIOS for IBM PCs,
> > Compatibles and EISA Computers, 2nd Edition", the I/O port list gives
> >
> > port 0080h   R/W  Extra page register (temporary storage)
> >
> > Despite looking, I've never seen it documented anywhere else, but I
> > believe it works on just about every PC platform.  Except, apparently,
> > my laptop.
> >
> >
> >   
> The port 80 problem was discovered by me, after months of "bisecting" 
> the running code around a problem with hanging when using hwclock in 
> 64-bit mode when ACPI is on.  So it kills my laptop, too, and many 
> currentlaptop motherboards designed by Quanta for HP and Compaq (dv6000, 
> dv9000, tx1000, apparently)

Thanks very much for that - I was debugging this for a while too, and
eventually just shut off hwclock.

> Your laptop isn't an aberration.  It's part of the new generation of 
> evolved machines that take advantage of the capabilities of ACPI and 
> SMBIOS and DMI standards that are becoming core parts of the market.

I beg to differ.  I managed to turn the thing into a brick by upgrading
the BIOS (with the correct image, no less) in an attempt to fix it.  I
just got it back from repair.  I'm not sure that is positive
evolutionary development, but it certainly does make my laptop an
aberration :)

FWIW, I fixed the problem locally by recompiling, changing port 80 to
port 84 in io.h; works great, and doesn't conflict with any occupied
ports.

Zach


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-11  1:36                                                                 ` Zachary Amsden
@ 2008-01-11  3:05                                                                   ` Rene Herman
  2008-01-11 14:35                                                                     ` David P. Reed
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2008-01-11  3:05 UTC (permalink / raw)
  To: Zachary Amsden
  Cc: David P. Reed, H. Peter Anvin, Christer Weinigel, Ondrej Zary,
	Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 11-01-08 02:36, Zachary Amsden wrote:

> FWIW, I fixed the problem locally by recompiling, changing port 80 to 
> port 84 in io.h; works great, and doesn't conflict with any occupied 
> ports.

Might not give you a "proper" delay though. 0xed should be a better choice...

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-11  3:05                                                                   ` Rene Herman
@ 2008-01-11 14:35                                                                     ` David P. Reed
  2008-01-11 14:37                                                                       ` Alan Cox
                                                                                         ` (2 more replies)
  0 siblings, 3 replies; 243+ messages in thread
From: David P. Reed @ 2008-01-11 14:35 UTC (permalink / raw)
  To: Rene Herman
  Cc: Zachary Amsden, H. Peter Anvin, Christer Weinigel, Ondrej Zary,
	Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol



Rene Herman wrote:
> On 11-01-08 02:36, Zachary Amsden wrote:
>
>> FWIW, I fixed the problem locally by recompiling, changing port 80 to 
>> port 84 in io.h; works great, and doesn't conflict with any occupied 
>> ports.
>
> Might not give you a "proper" delay though. 0xed should be a better 
> choice...
>
I don't think there is any magic here.  I modified the patch to do *no 
delay at all* in the io_delay "quirk" and have been running reliably for 
weeks including the very heavy I/O load that comes from using software 
RAID on this nice laptop that has two separate SATA drives!  This 
particular laptop has no problematic devices - the only problem is 
actually in the CMOS_READ and CMOS_WRITE macros that *use* the _p 
operations in a way that is unnecessary on this machine.  (in fact, it 
would be hard to add a problematic device - there's no PCMCIA slot 
either, and so every option is USB or Firewire).

Using 0xED happens to work, but it's not guaranteed to work either.  
There is not a "standard" for an "unused port that is mapped to cause a 
bus abort on the LPC bus".   More problematic is that I would think some 
people might want to turn on the AMD feature that generates machine 
checks if a bus timeout happens.   The whole point of machine checks is 
to allow the machine to be more reliable.   Using any "unused port" for 
a delay means that the machine check feature is wasted and utterly unusable.



^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-11 14:35                                                                     ` David P. Reed
@ 2008-01-11 14:37                                                                       ` Alan Cox
  2008-01-11 15:07                                                                         ` David P. Reed
  2008-01-11 14:49                                                                       ` Rene Herman
  2008-01-14 21:57                                                                       ` David Woodhouse
  2 siblings, 1 reply; 243+ messages in thread
From: Alan Cox @ 2008-01-11 14:37 UTC (permalink / raw)
  To: David P. Reed
  Cc: Rene Herman, Zachary Amsden, H. Peter Anvin, Christer Weinigel,
	Ondrej Zary, Bodo Eggert, Ingo Molnar, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

> bus abort on the LPC bus".   More problematic is that I would think some 
> people might want to turn on the AMD feature that generates machine 
> checks if a bus timeout happens.   The whole point of machine checks is 

An ISA/LPC bus timeout is fulfilled by the bridge so doesn't cause an MCE.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-11 14:35                                                                     ` David P. Reed
  2008-01-11 14:37                                                                       ` Alan Cox
@ 2008-01-11 14:49                                                                       ` Rene Herman
  2008-01-14 21:57                                                                       ` David Woodhouse
  2 siblings, 0 replies; 243+ messages in thread
From: Rene Herman @ 2008-01-11 14:49 UTC (permalink / raw)
  To: David P. Reed
  Cc: Zachary Amsden, H. Peter Anvin, Christer Weinigel, Ondrej Zary,
	Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

On 11-01-08 15:35, David P. Reed wrote:

> Rene Herman wrote:
>> On 11-01-08 02:36, Zachary Amsden wrote:
>>
>>> FWIW, I fixed the problem locally by recompiling, changing port 80 to 
>>> port 84 in io.h; works great, and doesn't conflict with any occupied 
>>> ports.
>>
>> Might not give you a "proper" delay though. 0xed should be a better 
>> choice...
>>
> I don't think there is any magic here.

Golly, you don't think so? Just commenting on his local hack. Port 0x84 is 
inside the (reserved) DMA page register range and stands a better chance of 
not being echoed onto ISA by various chipsets than 0xed does due to that.

Yes -- on a sane machine it's all useless anyway and with all sane machines 
this discussion would've ended quite some time ago already. It's the insane, 
obsolete legacy junk that's the problem.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-11 14:37                                                                       ` Alan Cox
@ 2008-01-11 15:07                                                                         ` David P. Reed
  2008-01-11 17:54                                                                           ` H. Peter Anvin
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-11 15:07 UTC (permalink / raw)
  To: Alan Cox
  Cc: Rene Herman, Zachary Amsden, H. Peter Anvin, Christer Weinigel,
	Ondrej Zary, Bodo Eggert, Ingo Molnar, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

Alan Cox wrote:
>> bus abort on the LPC bus".   More problematic is that I would think some 
>> people might want to turn on the AMD feature that generates machine 
>> checks if a bus timeout happens.   The whole point of machine checks is 
>>     
>
> An ISA/LPC bus timeout is fulfilled by the bridge so doesn't cause an MCE.
>
>
>   
Good possibility, but the documentation on HyperTransport suggests 
otherwise, even for LPC bridges in this particular modern world of 
AMD64. I might do the experiment someday to see if my LPC bridge is 
implemented in a way that does or doesn't support enabling MCE's. Could 
be different between Intel and AMD - I haven't had reason to pore over 
the Intel chipset specs, since my poking into all this stuff has been 
driven by my personal machine's issues, and it's not got any Intel 
compatible parts.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-11 15:07                                                                         ` David P. Reed
@ 2008-01-11 17:54                                                                           ` H. Peter Anvin
  0 siblings, 0 replies; 243+ messages in thread
From: H. Peter Anvin @ 2008-01-11 17:54 UTC (permalink / raw)
  To: David P. Reed
  Cc: Alan Cox, Rene Herman, Zachary Amsden, Christer Weinigel,
	Ondrej Zary, Bodo Eggert, Ingo Molnar, Paul Rolland, Pavel Machek,
	Thomas Gleixner, linux-kernel, Ingo Molnar, rol

David P. Reed wrote:
> Alan Cox wrote:
>>> bus abort on the LPC bus".   More problematic is that I would think 
>>> some people might want to turn on the AMD feature that generates 
>>> machine checks if a bus timeout happens.   The whole point of machine 
>>> checks is     
>>
>> An ISA/LPC bus timeout is fulfilled by the bridge so doesn't cause an 
>> MCE.

> Good possibility, but the documentation on HyperTransport suggests 
> otherwise, even for LPC bridges in this particular modern world of 
> AMD64. I might do the experiment someday to see if my LPC bridge is 
> implemented in a way that does or doesn't support enabling MCE's. Could 
> be different between Intel and AMD - I haven't had reason to pore over 
> the Intel chipset specs, since my poking into all this stuff has been 
> driven by my personal machine's issues, and it's not got any Intel 
> compatible parts.

If you have a subtractive decoding bridge you will have completion on HT.

	-hpa

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-11 14:35                                                                     ` David P. Reed
  2008-01-11 14:37                                                                       ` Alan Cox
  2008-01-11 14:49                                                                       ` Rene Herman
@ 2008-01-14 21:57                                                                       ` David Woodhouse
  2008-01-14 22:22                                                                         ` David P. Reed
  2 siblings, 1 reply; 243+ messages in thread
From: David Woodhouse @ 2008-01-14 21:57 UTC (permalink / raw)
  To: David P. Reed
  Cc: Rene Herman, Zachary Amsden, H. Peter Anvin, Christer Weinigel,
	Ondrej Zary, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol


On Fri, 2008-01-11 at 09:35 -0500, David P. Reed wrote:
>   Using any "unused port" for a delay means that the machine check
> feature is wasted and utterly unusable.

Not entirely unusable. You can recover silently from the machine check
if it was one of the known accesses to the 'unused port'. It certainly
achieves a delay :)

On ppc32 we recover from the machine check if it was any inb/outb --
mostly to work around crappy drivers developed on i386, I believe.

-- 
dwmw2


^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-14 21:57                                                                       ` David Woodhouse
@ 2008-01-14 22:22                                                                         ` David P. Reed
  2008-01-16 14:36                                                                           ` David Newall
  0 siblings, 1 reply; 243+ messages in thread
From: David P. Reed @ 2008-01-14 22:22 UTC (permalink / raw)
  To: David Woodhouse
  Cc: Rene Herman, Zachary Amsden, H. Peter Anvin, Christer Weinigel,
	Ondrej Zary, Bodo Eggert, Ingo Molnar, Alan Cox, Paul Rolland,
	Pavel Machek, Thomas Gleixner, linux-kernel, Ingo Molnar, rol

David Woodhouse wrote:
> On Fri, 2008-01-11 at 09:35 -0500, David P. Reed wrote:
>   
>>   Using any "unused port" for a delay means that the machine check
>> feature is wasted and utterly unusable.
>>     
>
> Not entirely unusable. You can recover silently from the machine check
> if it was one of the known accesses to the 'unused port'. It certainly
> achieves a delay :)
>   
I'm sure that's what the driver writers had in mind.  ;-)

And I think we probably have a great shot at getting Intel, Microsoft, 
HP, et al.. to add a feature for Linux to one of the ACPI table 
specifications that define an "unused port for delay purposes" field in 
the ACPI 4.0 spec, and retrofit it into PC/104 machine BIOSes.  At least 
Microsoft doesn't have a patent on using port 80 for delay purposes. :-)





^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-14 22:22                                                                         ` David P. Reed
@ 2008-01-16 14:36                                                                           ` David Newall
  2008-01-16 14:55                                                                             ` Alan Cox
  0 siblings, 1 reply; 243+ messages in thread
From: David Newall @ 2008-01-16 14:36 UTC (permalink / raw)
  To: David P. Reed
  Cc: David Woodhouse, Rene Herman, Zachary Amsden, H. Peter Anvin,
	Christer Weinigel, Ondrej Zary, Bodo Eggert, Ingo Molnar,
	Alan Cox, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

David P. Reed wrote:
> I think we probably have a great shot at getting Intel, Microsoft, HP,
> et al.. to add a feature for Linux to one of the ACPI table
> specifications that define an "unused port for delay purposes" field
> in the ACPI 4.0 spec, and retrofit it into PC/104 machine BIOSes.  At
> least Microsoft doesn't have a patent on using port 80 for delay
> purposes. :-) 

This use of port 80 (or insert some other random number) is a croc of
hackery of the most inexperienced kind.  The task to be performed is to
delay for some period, and I think it's a mix of bloody mindedness and
fear of unfamiliar code and specification that explains why a delay is
not being coded.  Lest we forget, someone who should know better said
that an OUT is used because you don't know how long the delay should be
on any specific machine.  What rubbish.

For what it's worth, I would oppose any attempt to ammend ACPI
specifications in the way described above.  It's bad enough to have that
embarrassing and unseemly hack in Linux.  It would be so much worse to
enshrine the practice as industry standard practice.

I won't even mention the many instances of these delays where no delay
is what properly is needed.  Performance?  Who cares about performance?

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-16 14:36                                                                           ` David Newall
@ 2008-01-16 14:55                                                                             ` Alan Cox
  2008-01-16 19:15                                                                               ` David Newall
  0 siblings, 1 reply; 243+ messages in thread
From: Alan Cox @ 2008-01-16 14:55 UTC (permalink / raw)
  To: David Newall
  Cc: David P. Reed, David Woodhouse, Rene Herman, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

On Thu, 17 Jan 2008 01:06:24 +1030
David Newall <davidn@davidnewall.com> wrote:

> This use of port 80 (or insert some other random number) is a croc of
> hackery of the most inexperienced kind. 

Wrong. It's a careful designed solution used by all sorts of code for
over 15 years.

 The task to be performed is to delay for some period

Wrong, it is for some number of bus clocks which is why I/O cycles are
used

> that an OUT is used because you don't know how long the delay should be
> on any specific machine.  What rubbish.

Wrong again.

> I won't even mention the many instances of these delays where no delay
> is what properly is needed.  Performance?  Who cares about performance?

Correctness, who needs correctness ?

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-16 14:55                                                                             ` Alan Cox
@ 2008-01-16 19:15                                                                               ` David Newall
  2008-01-16 20:08                                                                                 ` Alan Cox
  0 siblings, 1 reply; 243+ messages in thread
From: David Newall @ 2008-01-16 19:15 UTC (permalink / raw)
  To: Alan Cox
  Cc: David P. Reed, David Woodhouse, Rene Herman, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

Alan Cox wrote:
> On Thu, 17 Jan 2008 01:06:24 +1030
> David Newall <davidn@davidnewall.com> wrote:
>
>   
>> This use of port 80 (or insert some other random number) is a croc of
>> hackery of the most inexperienced kind. 
>>     
>
> Wrong. It's a careful designed solution used by all sorts of code for
> over 15 years.
>   
It's not careful: it's a croc.  It's an ugly hack, an abuse of process,
and totally unnecessary.  Read my comment about delays (next).

>  The task to be performed is to delay for some period
>
> Wrong, it is for some number of bus clocks which is why I/O cycles are
> used
>   
Wrong.  It's a delay.  It's a delay measured in I/O cycles, but still a
delay.  Doing I/O to get a delay, even if the delay is intended to be
measured in I/O cycles, is hackery of the most inexperienced sort.  It's
the sort of thing junior programmers get boxed in the ear for.  There's
no satisfactory reason to do it that way.

If the hardware required an intermediate junk I/O, that would be a
reason to do one, but it doesn't, does it?  It requires a delay.  It's
written thus in all of the application notes.

>> that an OUT is used because you don't know how long the delay should be
>> on any specific machine.  What rubbish.
>>     
>
> Wrong again.
>   
Wrong again.  Of course one knows how long the delay should be.  The bus
speed is known.  The specifications of the hardware is known.  Do the
math you (the programmer writing the driver, not Alan) lazy sluggard,
and use a delay.  It baffles commonsense to say you don't know how long
it should be.

>> I won't even mention the many instances of these delays where no delay
>> is what properly is needed.  Performance?  Who cares about performance?
>>     
>
> Correctness, who needs correctness ?
Well, frankly, the development process could stand a little more of it.


The sooner we stop denying that this is a hack, the sooner we can fix it.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-16 19:15                                                                               ` David Newall
@ 2008-01-16 20:08                                                                                 ` Alan Cox
  2008-01-17  6:25                                                                                   ` David Newall
  0 siblings, 1 reply; 243+ messages in thread
From: Alan Cox @ 2008-01-16 20:08 UTC (permalink / raw)
  To: David Newall
  Cc: David P. Reed, David Woodhouse, Rene Herman, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

> If the hardware required an intermediate junk I/O, that would be a
> reason to do one, but it doesn't, does it?  It requires a delay.  It's
> written thus in all of the application notes.

And the only instruction that is synchronized to the bus in question is
an I/O instruction. 

> Wrong again.  Of course one knows how long the delay should be.  The bus
> speed is known. 

Wrong again. ISA bus speed is neither defined precisely, nor visible in a
system portable fashion.

I'm so glad you have nothing better to do than troll, if you
actually wrote code I'd be worried it might get into something people
used.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-16 20:08                                                                                 ` Alan Cox
@ 2008-01-17  6:25                                                                                   ` David Newall
  2008-01-17 12:02                                                                                     ` Alan Cox
  0 siblings, 1 reply; 243+ messages in thread
From: David Newall @ 2008-01-17  6:25 UTC (permalink / raw)
  To: Alan Cox
  Cc: David P. Reed, David Woodhouse, Rene Herman, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

Alan Cox wrote:
>> If the hardware required an intermediate junk I/O, that would be a
>> reason to do one, but it doesn't, does it?  It requires a delay.  It's
>> written thus in all of the application notes.
>>     
>
> And the only instruction that is synchronized to the bus in question is
> an I/O instruction.
>   

This is a timing issue, isn't it?  How are we synchronising, other than
by delaying for a (bus-dependant) period?  The characteristics of each
bus are known so a number can be assigned for "one bus cycle", without
having to use the bus.



>> Wrong again.  Of course one knows how long the delay should be.  The bus
>> speed is known. 
>>     
>
> Wrong again. ISA bus speed is neither defined precisely, nor visible in a
> system portable fashion.
>   

You say, "system portable," but I think you mean, "automatically
determined."  We don't have to define this value automatically, if
that's so hard to do.  We can use a tunable kernel-parameter.

> I'm so glad you have nothing better to do than troll

I'm not trolling.  You know this is true because many people perceive
this to be a problem.  I'm working on fixing it.  Not all Linux problems
are solvable by diving into code, and there is anecdotal evidence to
believe this one has big performance considerations.  I don't understand
why you are opposed to even talking about it.


> if you
> actually wrote code I'd be worried it might get into something people
> used.

Speaking of writing code: I remember working on a bluetooth Oops. 
Lacking the hardware, I went to you for advice on how to get it before
someone for testing.  You never replied.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-17  6:25                                                                                   ` David Newall
@ 2008-01-17 12:02                                                                                     ` Alan Cox
  2008-01-17 13:36                                                                                       ` David Newall
  0 siblings, 1 reply; 243+ messages in thread
From: Alan Cox @ 2008-01-17 12:02 UTC (permalink / raw)
  To: David Newall
  Cc: David P. Reed, David Woodhouse, Rene Herman, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

> This is a timing issue, isn't it?  How are we synchronising, other than
> by delaying for a (bus-dependant) period?  The characteristics of each
> bus are known so a number can be assigned for "one bus cycle", without
> having to use the bus.

The characteristics of the bus are not known. It could be anything
between 6 and about 16MHz. The way you read the bus clock is system
dependant.

The underlying problem is really that over time some of the hardware has
moved from the ISA world into the chipsets. That is why I sent Ingo the
patches for inb_pit/inb_pic and to split ISA 8390 and non ISA 8390
support. Someone has to tackle the CMOS but we are then in a position to
relegant port 0x80 timing use to ISA systems where it is fine.

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-17 12:02                                                                                     ` Alan Cox
@ 2008-01-17 13:36                                                                                       ` David Newall
  2008-01-17 13:55                                                                                         ` Rene Herman
  2008-01-17 15:51                                                                                         ` Alan Cox
  0 siblings, 2 replies; 243+ messages in thread
From: David Newall @ 2008-01-17 13:36 UTC (permalink / raw)
  To: Alan Cox
  Cc: David P. Reed, David Woodhouse, Rene Herman, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

Alan Cox wrote:
>> This is a timing issue, isn't it?  How are we synchronising, other than
>> by delaying for a (bus-dependant) period?  The characteristics of each
>> bus are known so a number can be assigned for "one bus cycle", without
>> having to use the bus.
>>     
>
> The characteristics of the bus are not known. It could be anything
> between 6 and about 16MHz.

In the early days of clone PCs, as you know but perhaps many on this
list might not, the bus speed could be changed, but this was
user-selectable.  For such a machine, delay values can be pre-calculated
for each bus speed, and a kernel parameter set accordingly.  Or are you
saying that the characteristics of the bus on a given machine vary for
reasons other than user selection?

The fact that busses run at different speeds on different machines is
not a problem because the delay value can be determined for each given
machine.

The question is, for a given machine, can we determine a delay value
instead of using a junk I/O?

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-17 13:36                                                                                       ` David Newall
@ 2008-01-17 13:55                                                                                         ` Rene Herman
  2008-01-17 21:58                                                                                           ` David Newall
  2008-01-17 15:51                                                                                         ` Alan Cox
  1 sibling, 1 reply; 243+ messages in thread
From: Rene Herman @ 2008-01-17 13:55 UTC (permalink / raw)
  To: David Newall
  Cc: Alan Cox, David P. Reed, David Woodhouse, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

On 17-01-08 14:36, David Newall wrote:

> In the early days of clone PCs, as you know but perhaps many on this
> list might not

I'm so incredibly sick of this fucking thread. We've had enough legacy farts 
coming out of the woodwork advertising their own massive experience and 
cluelessness by now. Both hpa and alan are in this thread and everyone else 
can be ignored on the issue.

Over the course of a 100 messages or so in this thread it's been determined 
that the best course of action is to keep the out for ISA and replace it 
with udelay() for chipset logic. Now go away.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-17 13:36                                                                                       ` David Newall
  2008-01-17 13:55                                                                                         ` Rene Herman
@ 2008-01-17 15:51                                                                                         ` Alan Cox
  1 sibling, 0 replies; 243+ messages in thread
From: Alan Cox @ 2008-01-17 15:51 UTC (permalink / raw)
  To: David Newall
  Cc: David P. Reed, David Woodhouse, Rene Herman, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

> In the early days of clone PCs, as you know but perhaps many on this
> list might not, the bus speed could be changed, but this was
> user-selectable.  For such a machine, delay values can be pre-calculated
> for each bus speed, and a kernel parameter set accordingly.  Or are you
> saying that the characteristics of the bus on a given machine vary for
> reasons other than user selection?

They vary based on the CPU clock, the dividers from PCI to ISA on PCI
based boxes, and on the ISA only ones often on the CPU speed.

Unfortunately the way you control that divider or read it is chipset
specific. Nor would it be reasonable to expect the end user to set it.

For PC/104 systems the same applies today.

> The question is, for a given machine, can we determine a delay value
> instead of using a junk I/O?

The question (for ISA peripherals) is "why bother", and with the 8390
patch there are one or two dubious PCI driver users of _p left but not
much else that isn't ISA or chipset logic. The question for chipset logic
where it has become integrated is "can we get rid of it for some devices,
if not what can we use instead"

Alan

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-17 13:55                                                                                         ` Rene Herman
@ 2008-01-17 21:58                                                                                           ` David Newall
  2008-01-17 22:13                                                                                             ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: David Newall @ 2008-01-17 21:58 UTC (permalink / raw)
  To: Rene Herman
  Cc: Alan Cox, David P. Reed, David Woodhouse, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

Rene Herman wrote:
> Over the course of a 100 messages or so in this thread it's been
> determined that the best course of action is to keep the out for ISA
> and replace it with udelay() for chipset logic. Now go away. 

Rather than this incredible rudeness, why don't you direct your energy
towards convincing Alan of this.  He's the hold-out.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-17 21:58                                                                                           ` David Newall
@ 2008-01-17 22:13                                                                                             ` Rene Herman
  2008-01-18 13:37                                                                                               ` David Newall
  0 siblings, 1 reply; 243+ messages in thread
From: Rene Herman @ 2008-01-17 22:13 UTC (permalink / raw)
  To: David Newall
  Cc: Alan Cox, David P. Reed, David Woodhouse, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

On 17-01-08 22:58, David Newall wrote:

> Rene Herman wrote:

>> Over the course of a 100 messages or so in this thread it's been
>> determined that the best course of action is to keep the out for ISA
>> and replace it with udelay() for chipset logic. Now go away. 
> 
> Rather than this incredible rudeness, why don't you direct your energy
> towards convincing Alan of this.  He's the hold-out.

No he isn't and that's why I'm rude -- everything needs to be repeated over 
and over and over again. Read the thread(s). You didn't limit your reply to 
chipset logic and Alan even already submitted patches to isolate the delay 
for the chipset logic (PIC and PIT that is) where the expectation is that a 
simple udelay() will suffice.

We've already talked about ISA bus speed, and how it's not in a sane sense 
portably determinable, we've already talked about kernel parameters, about 
udelay and it's usefulness in early boot, about how your rude "Junk I/O" is 
exactly what is needed for some ISA devices and so on...

In fact, we're blue in the face from talking about it. So say something 
useful or go away.

Rene

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-17 22:13                                                                                             ` Rene Herman
@ 2008-01-18 13:37                                                                                               ` David Newall
  2008-01-18 14:05                                                                                                 ` Rene Herman
  0 siblings, 1 reply; 243+ messages in thread
From: David Newall @ 2008-01-18 13:37 UTC (permalink / raw)
  To: Rene Herman
  Cc: Alan Cox, David P. Reed, David Woodhouse, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

Rene,

Here is why you shouldn't leap so quickly to rudeness.  Everything is
being repeated over and over and over again (as you put it) because
people like you shout down people like me without making any apparent
effort to understand the truth of the problem.


Rene Herman wrote:
> We've already talked about ISA bus speed, and how it's not in a sane
> sense portably determinable, we've already talked about kernel
> parameters, about udelay and it's usefulness in early boot, about how
> your rude "Junk I/O" is exactly what is needed for some ISA devices
> and so on...

The problem is that _p is widely used for non-ISA devices.  For example,
a quick grep reveals the following (and more) all use outb_p:

    ./i2c/busses/i2c-amd756.c
    ./i2c/busses/i2c-ali1535.c
    ./i2c/busses/i2c-ali15x3.c
    ./i2c/busses/i2c-i801.c
    ./i2c/busses/i2c-piix4.c
    ./i2c/busses/i2c-viapro.c
    ./i2c/busses/i2c-nforce2.c
    ./i2c/busses/i2c-ali1563.c
    ./telephony/ixj.c
    ./char/pc8736x_gpio.c
    ./char/epca.c
    ./char/dtlk.c
    ./char/watchdog/w83697hf_wdt.c
    ./char/watchdog/wafer5823wdt.c
    ./char/watchdog/wdt.c
    ./char/watchdog/sc1200wdt.c
    ./char/watchdog/pc87413_wdt.c
    ./char/watchdog/wdt_pci.c
    ./char/watchdog/w83977f_wdt.c
    ./char/watchdog/pcwd_pci.c
    ./char/watchdog/w83877f_wdt.c
    ./char/watchdog/mixcomwd.c
    ./char/watchdog/w83627hf_wdt.c
    ./char/watchdog/advantechwdt.c
    ./char/watchdog/ib700wdt.c
    ./char/watchdog/pcwd.c
    ./char/watchdog/wdt977.c
    ./char/rocket_int.h
    ./char/sonypi.c


Most of these go nowhere near the ISA bus.  This has been said before,
but perhaps you missed that.  Which is another reason to use good
manners, isn't it?

The argument that you can't know how long to delay is utter rubbish.

> In fact, we're blue in the face from talking about it. So say
> something useful or go away. 

I think I'm saying something useful.  I'll keep an eye out for your
humble apology.  (Are you big enough to give one?)   In the mean time,
perhaps you'll follow your own advice and say something useful or go
away.  :-p

I hope you'll see this in the positive and constructive light that it is
intended.

^ permalink raw reply	[flat|nested] 243+ messages in thread

* Re: [linux-kernel] Re: [PATCH] x86: provide a DMI based port 0x80 I/O delay override.
  2008-01-18 13:37                                                                                               ` David Newall
@ 2008-01-18 14:05                                                                                                 ` Rene Herman
  0 siblings, 0 replies; 243+ messages in thread
From: Rene Herman @ 2008-01-18 14:05 UTC (permalink / raw)
  To: David Newall
  Cc: Alan Cox, David P. Reed, David Woodhouse, Zachary Amsden,
	H. Peter Anvin, Christer Weinigel, Ondrej Zary, Bodo Eggert,
	Ingo Molnar, Paul Rolland, Pavel Machek, Thomas Gleixner,
	linux-kernel, Ingo Molnar, rol

On 18-01-08 14:37, David Newall wrote:

> The problem is that _p is widely used for non-ISA devices.

Yes, we know, it's being fixed. Piss off.

Rene.

^ permalink raw reply	[flat|nested] 243+ messages in thread

end of thread, other threads:[~2008-01-18 14:09 UTC | newest]

Thread overview: 243+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <466F0941.9060201@reed.com>
     [not found] ` <1181682498.8176.224.camel@chaos>
     [not found]   ` <469578CD.3080609@reed.com>
     [not found]     ` <1184216528.12353.203.camel@chaos>
     [not found]       ` <1184218962.12353.209.camel@chaos>
     [not found]         ` <46964352.7040301@reed.com>
     [not found]           ` <1184253339.12353.223.camel@chaos>
     [not found]             ` <469697C6.50903@reed.com>
     [not found]               ` <1184274754.12353.254.camel@chaos>
2007-11-12 16:55                 ` [PATCH] x86: fix locking and sync bugs in x86_64 RTC code in time_64.c David P. Reed
2007-11-14  7:49                   ` Thomas Gleixner
2007-11-14 13:10                     ` David P. Reed
2007-11-14 18:26                       ` Matt Mackall
2007-11-14 21:22                         ` David P. Reed
2007-11-12 17:02                 ` [PATCH] time: fix typo that makes sync_cmos_clock erratic David P. Reed
2007-11-14  7:57                   ` Thomas Gleixner
2007-11-12 19:19                 ` David P. Reed
2007-11-14 22:47                 ` [PATCH] x86: fix freeze in x86_64 RTC update code in time_64.c David P. Reed
2007-11-14 22:49                 ` [PATCH] time: fix typo that makes sync_cmos_clock erratic David P. Reed
2007-11-15  1:14                 ` [PATCH] x86: on x86_64, correct reading of PC RTC when update in progress in time_64.c David P. Reed
2007-11-15 19:33                   ` Thomas Gleixner
2007-11-15 20:31                     ` David P. Reed
2007-11-15 22:17                       ` Thomas Gleixner
2007-12-14  2:59                 ` [PATCH] x86_64: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
2007-12-14  7:49                   ` Yinghai Lu
2007-12-14  9:45                   ` Rene Herman
2007-12-14 14:23                     ` Ingo Molnar
2007-12-14 14:36                       ` Rene Herman
2007-12-14 14:46                         ` Ingo Molnar
2007-12-14 14:56                           ` Rene Herman
2007-12-14 18:36                             ` Alan Cox
2007-12-14 18:48                               ` H. Peter Anvin
2007-12-14 21:05                               ` Pavel Machek
2007-12-15 22:59                       ` Pavel Machek
2007-12-14 10:51                   ` Andi Kleen
2007-12-14 11:11                     ` David P. Reed
2007-12-14 13:15                   ` Ingo Molnar
2007-12-14 13:24                     ` Ingo Molnar
2007-12-14 13:47                       ` Ingo Molnar
2007-12-14 14:41                         ` Ingo Molnar
2007-12-14 13:42                     ` Rene Herman
2007-12-14 14:03                       ` Ingo Molnar
2007-12-14 14:10                         ` Rene Herman
2007-12-14 14:21                           ` Ingo Molnar
2007-12-14 18:02                     ` H. Peter Anvin
2007-12-14 18:23                       ` Rene Herman
2007-12-14 21:06                       ` Pavel Machek
2007-12-14 22:13                         ` H. Peter Anvin
2007-12-14 23:29                           ` Alan Cox
2007-12-15  3:04                             ` David P. Reed
2007-12-15  5:45                               ` H. Peter Anvin
2007-12-15 17:17                                 ` David P. Reed
2007-12-15 17:46                                   ` Alan Cox
2007-12-17 22:50                                     ` Jan Engelhardt
2007-12-17 22:52                                       ` H. Peter Anvin
2007-12-15  8:08                             ` Paul Rolland
2007-12-15  8:13                               ` Rene Herman
2007-12-15 20:27                                 ` H. Peter Anvin
2007-12-15 23:26                                   ` [PATCH] x86: " Rene Herman
2007-12-15 23:51                                     ` H. Peter Anvin
2007-12-16  0:05                                       ` H. Peter Anvin
2007-12-16 13:15                                       ` [PATCH] x86: provide a DMI based port 0x80 I/O delay override Rene Herman
2007-12-16 15:22                                         ` Ingo Molnar
2007-12-17  1:43                                           ` Rene Herman
2007-12-17  2:05                                             ` H. Peter Anvin
2007-12-17  2:19                                               ` Rene Herman
2007-12-17  3:35                                                 ` H. Peter Anvin
2007-12-17 13:02                                                   ` Rene Herman
2007-12-17 17:14                                                     ` H. Peter Anvin
2007-12-17 19:43                                                       ` David P. Reed
2007-12-17 19:55                                                         ` H. Peter Anvin
2007-12-17 21:02                                                           ` David P. Reed
2007-12-17 21:17                                                             ` H. Peter Anvin
2007-12-17 21:25                                                         ` Alan Cox
2008-01-01 15:57                                                           ` David P. Reed
2008-01-01 21:16                                                             ` H. Peter Anvin
2008-01-01 15:59                                                           ` David P. Reed
2008-01-01 16:15                                                             ` Alan Cox
2008-01-01 16:43                                                               ` Ingo Molnar
2008-01-01 17:32                                                                 ` Alan Cox
2008-01-01 18:45                                                                   ` Ingo Molnar
2008-01-01 20:14                                                                     ` Christer Weinigel
2008-01-01 21:13                                                                       ` Alan Cox
2008-01-01 21:07                                                                     ` Alan Cox
2008-01-02 10:04                                                                       ` Ingo Molnar
2008-01-02 13:11                                                                         ` [linux-kernel] " David P. Reed
2008-01-02 13:21                                                                           ` Ingo Molnar
2008-01-02 13:47                                                                         ` Alan Cox
2008-01-02 15:35                                                                           ` Rene Herman
2008-01-02 15:50                                                                             ` Rene Herman
2008-01-01 17:32                                                                 ` Christer Weinigel
2008-01-01 18:46                                                                   ` Ingo Molnar
2008-01-01 19:35                                                                     ` Christer Weinigel
2008-01-01 19:59                                                                       ` Rene Herman
2008-01-01 20:55                                                                         ` Christer Weinigel
2008-01-01 21:24                                                                           ` H. Peter Anvin
2008-01-01 21:01                                                                       ` Ingo Molnar
2008-01-01 21:26                                                                         ` Alan Cox
2008-01-01 21:42                                                                         ` Christer Weinigel
2008-01-01 21:42                                                                           ` Rene Herman
2008-01-01 21:50                                                                           ` H. Peter Anvin
2008-01-01 21:21                                                                       ` H. Peter Anvin
2008-01-01 23:05                                                                         ` Christer Weinigel
2008-01-01 23:12                                                                           ` Alan Cox
2008-01-02  0:23                                                                             ` Christer Weinigel
2008-01-02 10:00                                                                         ` Ingo Molnar
2008-01-01 17:32                                                               ` David P. Reed
2008-01-01 17:38                                                                 ` Alan Cox
2008-01-01 21:15                                                               ` H. Peter Anvin
2008-01-01 21:35                                                                 ` Rene Herman
2008-01-01 21:44                                                                   ` H. Peter Anvin
2008-01-01 22:35                                                                     ` Rene Herman
2008-01-01 22:39                                                                       ` H. Peter Anvin
2008-01-01 23:11                                                                         ` Rene Herman
2008-01-02  0:25                                                                           ` Rene Herman
2008-01-02  0:55                                                                           ` Christer Weinigel
2008-01-02  1:00                                                                             ` Rene Herman
2008-01-02  2:27                                                                             ` H. Peter Anvin
2008-01-09 17:27                                                                     ` Maciej W. Rozycki
2008-01-09 18:18                                                                       ` H. Peter Anvin
2008-01-01 17:31                                                             ` Pavel Machek
2008-01-01 17:33                                                               ` David P. Reed
2007-12-17  4:09                                                 ` H. Peter Anvin
2007-12-17 10:57                                             ` Ingo Molnar
2007-12-17 11:29                                               ` Ingo Molnar
2007-12-17 13:34                                                 ` David P. Reed
2007-12-17 12:15                                               ` Rene Herman
2007-12-17 13:09                                                 ` Ingo Molnar
2007-12-17 13:22                                                   ` Rene Herman
2007-12-17 13:31                                                     ` Pavel Machek
2007-12-17 13:31                                                       ` Rene Herman
2007-12-17 13:32                                                     ` David P. Reed
2007-12-17 13:36                                                       ` Rene Herman
2007-12-17 14:39                                                       ` Ingo Molnar
2007-12-17 16:12                                                         ` Alan Cox
2007-12-17 16:48                                                           ` Ingo Molnar
2007-12-17 20:48                                                           ` Rene Herman
2007-12-17 20:57                                                             ` H. Peter Anvin
2007-12-17 21:33                                                               ` Rene Herman
2007-12-17 21:40                                                                 ` H. Peter Anvin
2007-12-17 21:46                                                                   ` Ingo Molnar
2007-12-17 21:50                                                                   ` Rene Herman
2007-12-17 21:41                                                             ` Ingo Molnar
2007-12-17 21:47                                                               ` Rene Herman
2007-12-17 21:56                                                                 ` Ingo Molnar
2007-12-17 22:01                                                                   ` Rene Herman
2007-12-17 22:18                                                                     ` David P. Reed
2007-12-17 19:38                                                         ` David P. Reed
2007-12-17 19:55                                                           ` H. Peter Anvin
2007-12-17 21:28                                                           ` Ingo Molnar
2007-12-16 21:42                                         ` H. Peter Anvin
2007-12-17  1:48                                           ` Rene Herman
2007-12-17  1:53                                             ` H. Peter Anvin
2007-12-16 23:12                                         ` David P. Reed
2007-12-17  1:56                                           ` Rene Herman
2007-12-17  2:04                                             ` H. Peter Anvin
2007-12-17  2:15                                               ` Rene Herman
2007-12-16  0:23                                     ` [PATCH] x86: fix problems due to use of "outb" to port 80 on some AMD64x2 laptops, etc David P. Reed
2007-12-15 20:26                               ` [PATCH] x86_64: " H. Peter Anvin
2007-12-15 22:55                                 ` Pavel Machek
2007-12-16  9:27                                 ` Ingo Molnar
2007-12-17 21:04                             ` Rene Herman
2007-12-17 23:20                               ` Pavel Machek
2007-12-18  0:06                                 ` Alan Cox
2007-12-18 15:49                                   ` Lennart Sorensen
2007-12-17 22:46                           ` Jan Engelhardt
2007-12-15  7:43                       ` Ingo Molnar
2007-12-15  7:58                         ` Rene Herman
2007-12-15 13:27                           ` Ingo Molnar
2007-12-15 14:01                             ` Rene Herman
2007-12-15 20:25                               ` H. Peter Anvin
2007-12-15 14:29                             ` Alan Cox
2007-12-15 16:19                               ` David P. Reed
2007-12-15 16:48                                 ` Mark Lord
2007-12-15 17:51                                 ` Alan Cox
2007-12-15 23:00                     ` Pavel Machek
2007-12-15 23:04                       ` H. Peter Anvin
2007-12-16  9:40                         ` Ingo Molnar
2007-12-16 21:43                           ` H. Peter Anvin
2007-12-16 23:06                             ` David P. Reed
2007-12-16 23:23                               ` Pavel Machek
2007-12-16 23:34                                 ` H. Peter Anvin
2007-12-26 20:49                                   ` Pavel Machek
2007-12-17  1:51                             ` Rene Herman
2007-12-14 16:08                   ` Avi Kivity
2007-12-15  2:13                     ` David P. Reed
2007-12-15  2:20                       ` H. Peter Anvin
2007-12-15  2:20                         ` H. Peter Anvin
2007-12-17 18:14                       ` linux-os (Dick Johnson)
2007-12-17 18:54                         ` Rene Herman
2007-12-17 18:54                           ` Rene Herman
2007-12-19 15:03                       ` Avi Kivity
2007-12-19 15:03                         ` Avi Kivity
     [not found] <9BdU5-1YW-9@gated-at.bofh.it>
     [not found] ` <9BeZN-3Gf-5@gated-at.bofh.it>
     [not found]   ` <9BnTB-1As-31@gated-at.bofh.it>
     [not found]     ` <9BrX4-8go-1@gated-at.bofh.it>
     [not found]       ` <9BuBG-4eR-51@gated-at.bofh.it>
     [not found]         ` <9BvRd-6aL-71@gated-at.bofh.it>
     [not found]           ` <9GRQW-1DX-13@gated-at.bofh.it>
     [not found]             ` <9GSah-23W-1@gated-at.bofh.it>
     [not found]               ` <9GSDy-2GD-23@gated-at.bofh.it>
     [not found]                 ` <9GTpK-40d-15@gated-at.bofh.it>
     [not found]                   ` <9GUvy-5H2-11@gated-at.bofh.it>
     [not found]                     ` <9GVKU-7SS-25@gated-at.bofh.it>
2008-01-07 19:38                       ` [PATCH] x86: provide a DMI based port 0x80 I/O delay override Bodo Eggert
2008-01-07 19:46                         ` H. Peter Anvin
2008-01-07 22:02                           ` Bodo Eggert
2008-01-07 22:10                             ` H. Peter Anvin
2008-01-07 22:27                               ` Bodo Eggert
2008-01-07 22:59                                 ` Rene Herman
2008-01-07 23:24                                   ` H. Peter Anvin
2008-01-07 23:26                                     ` Rene Herman
2008-01-08  0:10                                       ` [linux-kernel] " David P. Reed
2008-01-08  0:13                                         ` H. Peter Anvin
2008-01-08  1:38                                           ` David P. Reed
2008-01-08 17:10                                             ` Ondrej Zary
2008-01-08 17:24                                               ` David P. Reed
2008-01-08 17:38                                                 ` Ondrej Zary
2008-01-08 18:44                                                   ` David P. Reed
2008-01-08 18:51                                                     ` Alan Cox
2008-01-08 19:15                                                       ` David P. Reed
2008-01-08 19:23                                                         ` Alan Cox
2008-01-08 19:51                                                           ` David P. Reed
2008-01-09  2:52                                                         ` Zachary Amsden
2008-01-09  5:19                                                           ` H. Peter Anvin
2008-01-09 21:53                                                             ` Zachary Amsden
2008-01-09 22:22                                                               ` David P. Reed
2008-01-11  1:36                                                                 ` Zachary Amsden
2008-01-11  3:05                                                                   ` Rene Herman
2008-01-11 14:35                                                                     ` David P. Reed
2008-01-11 14:37                                                                       ` Alan Cox
2008-01-11 15:07                                                                         ` David P. Reed
2008-01-11 17:54                                                                           ` H. Peter Anvin
2008-01-11 14:49                                                                       ` Rene Herman
2008-01-14 21:57                                                                       ` David Woodhouse
2008-01-14 22:22                                                                         ` David P. Reed
2008-01-16 14:36                                                                           ` David Newall
2008-01-16 14:55                                                                             ` Alan Cox
2008-01-16 19:15                                                                               ` David Newall
2008-01-16 20:08                                                                                 ` Alan Cox
2008-01-17  6:25                                                                                   ` David Newall
2008-01-17 12:02                                                                                     ` Alan Cox
2008-01-17 13:36                                                                                       ` David Newall
2008-01-17 13:55                                                                                         ` Rene Herman
2008-01-17 21:58                                                                                           ` David Newall
2008-01-17 22:13                                                                                             ` Rene Herman
2008-01-18 13:37                                                                                               ` David Newall
2008-01-18 14:05                                                                                                 ` Rene Herman
2008-01-17 15:51                                                                                         ` Alan Cox
2008-01-09  5:30                                                           ` Christer Weinigel
2008-01-09 14:42                                                             ` David P. Reed
2008-01-09 15:27                                                             ` Rene Herman
2008-01-09 18:17                                                               ` Zachary Amsden
2008-01-09 18:18                                                                 ` H. Peter Anvin
2008-01-09 20:26                                                                   ` Christer Weinigel
2008-01-09 21:59                                                                     ` H. Peter Anvin
2008-01-09 18:22                                                                 ` Adrian Bunk
2008-01-09 18:27                                                                   ` H. Peter Anvin
2008-01-08 19:25                                                     ` Christer Weinigel
2008-01-08 20:28                                                       ` David P. Reed
2008-01-08 21:43                                                         ` Christer Weinigel
2008-01-08 22:24                                                           ` David P. Reed
2008-01-08 18:51                                                   ` Bodo Eggert
2008-01-08 19:13                                                     ` Ondrej Zary
2008-01-08 12:51                                       ` Bodo Eggert
2008-01-08 13:07                                         ` [linux-kernel] " David P. Reed
2008-01-08 14:37                                           ` Alan Cox
2008-01-07 23:57                                     ` David P. Reed
2008-01-08  1:58                                       ` Alan Cox
     [not found] <fa.u5p8NBl8IjcycTVVtf0K+YtqNQc@ifi.uio.no>
     [not found] ` <fa.NOJkdyuk0c8CAqzZcG+pF1TzhJM@ifi.uio.no>
     [not found]   ` <fa.YLAHN7jSUo9phsICUHnxilN7/lk@ifi.uio.no>
     [not found]     ` <fa.SvgVgdNA9oz4F+tQ9MB2VRwr8ck@ifi.uio.no>
     [not found]       ` <fa.By1MDYK0MY/fwkCWWrAiQCxl5KM@ifi.uio.no>
     [not found]         ` <fa.97XrGLIGlvAy4P/TB5vHHrfBrIw@ifi.uio.no>
2008-01-10  0:37           ` Robert Hancock
2008-01-10  0:44             ` Rene Herman
2008-01-10 14:41               ` David P. Reed

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.