diff mbox

Enable A20 using KBC for some MSI laptops to fix S3 resume

Message ID 201210240847.52417.linux@rainbow-software.org (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Ondrej Zary Oct. 24, 2012, 6:47 a.m. UTC
Some MSI laptop BIOSes are broken - INT 15h code uses port 92h to enable A20
line but resume code assumes that KBC was used.
The laptop will not resume from S3 otherwise but powers off after a while
and then powers on again stuck with a blank screen.

Fix it by enabling A20 using KBC. Affected laptop list and DMI data are from
bug reports at Ubuntu Launchpad.

Tested with EX600 and PR200.

Fixes https://bugzilla.kernel.org/show_bug.cgi?id=12878

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>

Comments

Rafael Wysocki Oct. 24, 2012, 7:01 p.m. UTC | #1
On Wednesday 24 of October 2012 08:47:52 Ondrej Zary wrote:
> Some MSI laptop BIOSes are broken - INT 15h code uses port 92h to enable A20
> line but resume code assumes that KBC was used.
> The laptop will not resume from S3 otherwise but powers off after a while
> and then powers on again stuck with a blank screen.
> 
> Fix it by enabling A20 using KBC. Affected laptop list and DMI data are from
> bug reports at Ubuntu Launchpad.
> 
> Tested with EX600 and PR200.
> 
> Fixes https://bugzilla.kernel.org/show_bug.cgi?id=12878
> 
> Signed-off-by: Ondrej Zary <linux@rainbow-software.org>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>


> --- a/arch/x86/kernel/acpi/boot.c
> +++ b/arch/x86/kernel/acpi/boot.c
> @@ -1349,6 +1349,20 @@ static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
>  }
>  
>  /*
> + * Enable A20 line using KBC even if it's already enabled using other method.
> + * This is needed for some MSI laptops to resume from S3.
> + */
> +static int __init a20_enable_kbc(const struct dmi_system_id *d)
> +{
> +	printk(KERN_NOTICE "%s detected: enabling A20 using KBC\n", d->ident);
> +	outb(0xd1, 0x64);	/* Command write */
> +	outb(0xdf, 0x60);	/* A20 on */
> +	outb(0xff, 0x64);	/* Null command, but UHCI wants it */
> +
> +	return 0;
> +}
> +
> +/*
>   * If your system is blacklisted here, but you find that acpi=force
>   * works for you, please contact linux-acpi@vger.kernel.org
>   */
> @@ -1423,6 +1437,60 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
>  		     DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
>  		     },
>  	 },
> +	/*
> +	 * Some MSI laptop BIOSes are broken - INT 15h code uses port 92h to
> +	 * enable A20 line but resume code assumes that KBC was used.
> +	 * The laptop will not resume from S3 otherwise but powers off
> +	 * after a while and then powers on again stuck with a blank screen.
> +	 */
> +	{
> +	 .callback = a20_enable_kbc,
> +	 .ident = "MSI EX600 Laptop",
> +	 .matches = {
> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook EX600"),
> +		     },
> +	 },
> +	{
> +	 .callback = a20_enable_kbc,
> +	 .ident = "MSI EX700 Laptop",
> +	 .matches = {
> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> +		     DMI_MATCH(DMI_PRODUCT_NAME, "EX700"),
> +		     },
> +	 },
> +	{
> +	 .callback = a20_enable_kbc,
> +	 .ident = "MSI GX700 Laptop",
> +	 .matches = {
> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> +		     DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
> +		     },
> +	 },
> +	{
> +	 .callback = a20_enable_kbc,
> +	 .ident = "MSI VR201 Laptop",
> +	 .matches = {
> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook VR201"),
> +		     },
> +	 },
> +	{
> +	 .callback = a20_enable_kbc,
> +	 .ident = "MSI VR601 Laptop",
> +	 .matches = {
> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook VR601"),
> +		     },
> +	 },
> +	{
> +	 .callback = a20_enable_kbc,
> +	 .ident = "MSI PR200 Laptop",
> +	 .matches = {
> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook PR200"),
> +		     },
> +	 },
>  	{}
>  };
>  
> 
> 
>
H. Peter Anvin Oct. 24, 2012, 7:36 p.m. UTC | #2
Minor concern: it should do the wait for ready before sending each command.

"Rafael J. Wysocki" <rjw@sisk.pl> wrote:

>On Wednesday 24 of October 2012 08:47:52 Ondrej Zary wrote:
>> Some MSI laptop BIOSes are broken - INT 15h code uses port 92h to
>enable A20
>> line but resume code assumes that KBC was used.
>> The laptop will not resume from S3 otherwise but powers off after a
>while
>> and then powers on again stuck with a blank screen.
>> 
>> Fix it by enabling A20 using KBC. Affected laptop list and DMI data
>are from
>> bug reports at Ubuntu Launchpad.
>> 
>> Tested with EX600 and PR200.
>> 
>> Fixes https://bugzilla.kernel.org/show_bug.cgi?id=12878
>> 
>> Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
>
>Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
>
>> --- a/arch/x86/kernel/acpi/boot.c
>> +++ b/arch/x86/kernel/acpi/boot.c
>> @@ -1349,6 +1349,20 @@ static int __init
>dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
>>  }
>>  
>>  /*
>> + * Enable A20 line using KBC even if it's already enabled using
>other method.
>> + * This is needed for some MSI laptops to resume from S3.
>> + */
>> +static int __init a20_enable_kbc(const struct dmi_system_id *d)
>> +{
>> +	printk(KERN_NOTICE "%s detected: enabling A20 using KBC\n",
>d->ident);
>> +	outb(0xd1, 0x64);	/* Command write */
>> +	outb(0xdf, 0x60);	/* A20 on */
>> +	outb(0xff, 0x64);	/* Null command, but UHCI wants it */
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>>   * If your system is blacklisted here, but you find that acpi=force
>>   * works for you, please contact linux-acpi@vger.kernel.org
>>   */
>> @@ -1423,6 +1437,60 @@ static struct dmi_system_id __initdata
>acpi_dmi_table[] = {
>>  		     DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
>>  		     },
>>  	 },
>> +	/*
>> +	 * Some MSI laptop BIOSes are broken - INT 15h code uses port 92h
>to
>> +	 * enable A20 line but resume code assumes that KBC was used.
>> +	 * The laptop will not resume from S3 otherwise but powers off
>> +	 * after a while and then powers on again stuck with a blank
>screen.
>> +	 */
>> +	{
>> +	 .callback = a20_enable_kbc,
>> +	 .ident = "MSI EX600 Laptop",
>> +	 .matches = {
>> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook EX600"),
>> +		     },
>> +	 },
>> +	{
>> +	 .callback = a20_enable_kbc,
>> +	 .ident = "MSI EX700 Laptop",
>> +	 .matches = {
>> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> +		     DMI_MATCH(DMI_PRODUCT_NAME, "EX700"),
>> +		     },
>> +	 },
>> +	{
>> +	 .callback = a20_enable_kbc,
>> +	 .ident = "MSI GX700 Laptop",
>> +	 .matches = {
>> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> +		     DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
>> +		     },
>> +	 },
>> +	{
>> +	 .callback = a20_enable_kbc,
>> +	 .ident = "MSI VR201 Laptop",
>> +	 .matches = {
>> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook VR201"),
>> +		     },
>> +	 },
>> +	{
>> +	 .callback = a20_enable_kbc,
>> +	 .ident = "MSI VR601 Laptop",
>> +	 .matches = {
>> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook VR601"),
>> +		     },
>> +	 },
>> +	{
>> +	 .callback = a20_enable_kbc,
>> +	 .ident = "MSI PR200 Laptop",
>> +	 .matches = {
>> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook PR200"),
>> +		     },
>> +	 },
>>  	{}
>>  };
>>  
>> 
>> 
>>
Ondrej Zary Oct. 24, 2012, 7:56 p.m. UTC | #3
On Wednesday 24 October 2012 21:36:04 H. Peter Anvin wrote:
> Minor concern: it should do the wait for ready before sending each command.

It was a hack and then I forgot to add the waits... Should I redo the patch? 
I'll not be able to test it as I have to return the machine.

> "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
> >On Wednesday 24 of October 2012 08:47:52 Ondrej Zary wrote:
> >> Some MSI laptop BIOSes are broken - INT 15h code uses port 92h to
> >
> >enable A20
> >
> >> line but resume code assumes that KBC was used.
> >> The laptop will not resume from S3 otherwise but powers off after a
> >
> >while
> >
> >> and then powers on again stuck with a blank screen.
> >>
> >> Fix it by enabling A20 using KBC. Affected laptop list and DMI data
> >
> >are from
> >
> >> bug reports at Ubuntu Launchpad.
> >>
> >> Tested with EX600 and PR200.
> >>
> >> Fixes https://bugzilla.kernel.org/show_bug.cgi?id=12878
> >>
> >> Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
> >
> >Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> >> --- a/arch/x86/kernel/acpi/boot.c
> >> +++ b/arch/x86/kernel/acpi/boot.c
> >> @@ -1349,6 +1349,20 @@ static int __init
> >
> >dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
> >
> >>  }
> >>
> >>  /*
> >> + * Enable A20 line using KBC even if it's already enabled using
> >
> >other method.
> >
> >> + * This is needed for some MSI laptops to resume from S3.
> >> + */
> >> +static int __init a20_enable_kbc(const struct dmi_system_id *d)
> >> +{
> >> +	printk(KERN_NOTICE "%s detected: enabling A20 using KBC\n",
> >
> >d->ident);
> >
> >> +	outb(0xd1, 0x64);	/* Command write */
> >> +	outb(0xdf, 0x60);	/* A20 on */
> >> +	outb(0xff, 0x64);	/* Null command, but UHCI wants it */
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +/*
> >>   * If your system is blacklisted here, but you find that acpi=force
> >>   * works for you, please contact linux-acpi@vger.kernel.org
> >>   */
> >> @@ -1423,6 +1437,60 @@ static struct dmi_system_id __initdata
> >
> >acpi_dmi_table[] = {
> >
> >>  		     DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
> >>  		     },
> >>  	 },
> >> +	/*
> >> +	 * Some MSI laptop BIOSes are broken - INT 15h code uses port 92h
> >
> >to
> >
> >> +	 * enable A20 line but resume code assumes that KBC was used.
> >> +	 * The laptop will not resume from S3 otherwise but powers off
> >> +	 * after a while and then powers on again stuck with a blank
> >
> >screen.
> >
> >> +	 */
> >> +	{
> >> +	 .callback = a20_enable_kbc,
> >> +	 .ident = "MSI EX600 Laptop",
> >> +	 .matches = {
> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook EX600"),
> >> +		     },
> >> +	 },
> >> +	{
> >> +	 .callback = a20_enable_kbc,
> >> +	 .ident = "MSI EX700 Laptop",
> >> +	 .matches = {
> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "EX700"),
> >> +		     },
> >> +	 },
> >> +	{
> >> +	 .callback = a20_enable_kbc,
> >> +	 .ident = "MSI GX700 Laptop",
> >> +	 .matches = {
> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
> >> +		     },
> >> +	 },
> >> +	{
> >> +	 .callback = a20_enable_kbc,
> >> +	 .ident = "MSI VR201 Laptop",
> >> +	 .matches = {
> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook VR201"),
> >> +		     },
> >> +	 },
> >> +	{
> >> +	 .callback = a20_enable_kbc,
> >> +	 .ident = "MSI VR601 Laptop",
> >> +	 .matches = {
> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook VR601"),
> >> +		     },
> >> +	 },
> >> +	{
> >> +	 .callback = a20_enable_kbc,
> >> +	 .ident = "MSI PR200 Laptop",
> >> +	 .matches = {
> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook PR200"),
> >> +		     },
> >> +	 },
> >>  	{}
> >>  };
H. Peter Anvin Oct. 24, 2012, 8:03 p.m. UTC | #4
Probably should.

Ondrej Zary <linux@rainbow-software.org> wrote:

>On Wednesday 24 October 2012 21:36:04 H. Peter Anvin wrote:
>> Minor concern: it should do the wait for ready before sending each
>command.
>
>It was a hack and then I forgot to add the waits... Should I redo the
>patch? 
>I'll not be able to test it as I have to return the machine.
>
>> "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
>> >On Wednesday 24 of October 2012 08:47:52 Ondrej Zary wrote:
>> >> Some MSI laptop BIOSes are broken - INT 15h code uses port 92h to
>> >
>> >enable A20
>> >
>> >> line but resume code assumes that KBC was used.
>> >> The laptop will not resume from S3 otherwise but powers off after
>a
>> >
>> >while
>> >
>> >> and then powers on again stuck with a blank screen.
>> >>
>> >> Fix it by enabling A20 using KBC. Affected laptop list and DMI
>data
>> >
>> >are from
>> >
>> >> bug reports at Ubuntu Launchpad.
>> >>
>> >> Tested with EX600 and PR200.
>> >>
>> >> Fixes https://bugzilla.kernel.org/show_bug.cgi?id=12878
>> >>
>> >> Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
>> >
>> >Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>> >
>> >> --- a/arch/x86/kernel/acpi/boot.c
>> >> +++ b/arch/x86/kernel/acpi/boot.c
>> >> @@ -1349,6 +1349,20 @@ static int __init
>> >
>> >dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
>> >
>> >>  }
>> >>
>> >>  /*
>> >> + * Enable A20 line using KBC even if it's already enabled using
>> >
>> >other method.
>> >
>> >> + * This is needed for some MSI laptops to resume from S3.
>> >> + */
>> >> +static int __init a20_enable_kbc(const struct dmi_system_id *d)
>> >> +{
>> >> +	printk(KERN_NOTICE "%s detected: enabling A20 using KBC\n",
>> >
>> >d->ident);
>> >
>> >> +	outb(0xd1, 0x64);	/* Command write */
>> >> +	outb(0xdf, 0x60);	/* A20 on */
>> >> +	outb(0xff, 0x64);	/* Null command, but UHCI wants it */
>> >> +
>> >> +	return 0;
>> >> +}
>> >> +
>> >> +/*
>> >>   * If your system is blacklisted here, but you find that
>acpi=force
>> >>   * works for you, please contact linux-acpi@vger.kernel.org
>> >>   */
>> >> @@ -1423,6 +1437,60 @@ static struct dmi_system_id __initdata
>> >
>> >acpi_dmi_table[] = {
>> >
>> >>  		     DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
>> >>  		     },
>> >>  	 },
>> >> +	/*
>> >> +	 * Some MSI laptop BIOSes are broken - INT 15h code uses port
>92h
>> >
>> >to
>> >
>> >> +	 * enable A20 line but resume code assumes that KBC was used.
>> >> +	 * The laptop will not resume from S3 otherwise but powers off
>> >> +	 * after a while and then powers on again stuck with a blank
>> >
>> >screen.
>> >
>> >> +	 */
>> >> +	{
>> >> +	 .callback = a20_enable_kbc,
>> >> +	 .ident = "MSI EX600 Laptop",
>> >> +	 .matches = {
>> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook EX600"),
>> >> +		     },
>> >> +	 },
>> >> +	{
>> >> +	 .callback = a20_enable_kbc,
>> >> +	 .ident = "MSI EX700 Laptop",
>> >> +	 .matches = {
>> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "EX700"),
>> >> +		     },
>> >> +	 },
>> >> +	{
>> >> +	 .callback = a20_enable_kbc,
>> >> +	 .ident = "MSI GX700 Laptop",
>> >> +	 .matches = {
>> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
>> >> +		     },
>> >> +	 },
>> >> +	{
>> >> +	 .callback = a20_enable_kbc,
>> >> +	 .ident = "MSI VR201 Laptop",
>> >> +	 .matches = {
>> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook VR201"),
>> >> +		     },
>> >> +	 },
>> >> +	{
>> >> +	 .callback = a20_enable_kbc,
>> >> +	 .ident = "MSI VR601 Laptop",
>> >> +	 .matches = {
>> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook VR601"),
>> >> +		     },
>> >> +	 },
>> >> +	{
>> >> +	 .callback = a20_enable_kbc,
>> >> +	 .ident = "MSI PR200 Laptop",
>> >> +	 .matches = {
>> >> +		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
>> >> +		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook PR200"),
>> >> +		     },
>> >> +	 },
>> >>  	{}
>> >>  };
Alan Cox Oct. 24, 2012, 8:09 p.m. UTC | #5
On Wed, 24 Oct 2012 12:36:04 -0700
"H. Peter Anvin" <hpa@zytor.com> wrote:

> Minor concern: it should do the wait for ready before sending each command.

Can we get a command line to do this quirk too - it strikes me that if
the MSIs rely upon it then it may be something Windows always does so
will be useful to try on other problem machines as an experiment.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Robert Hancock Oct. 26, 2012, 4:31 a.m. UTC | #6
On 10/24/2012 02:09 PM, Alan Cox wrote:
> On Wed, 24 Oct 2012 12:36:04 -0700
> "H. Peter Anvin" <hpa@zytor.com> wrote:
>
>> Minor concern: it should do the wait for ready before sending each command.
>
> Can we get a command line to do this quirk too - it strikes me that if
> the MSIs rely upon it then it may be something Windows always does so
> will be useful to try on other problem machines as an experiment.

I agree, one has to keep in mind the age-old question "how does Windows 
work?" since it surely has no such quirk. I'd say we're sometimes too 
quick to add these DMI quirks when a more general solution would be 
somehow figure out how the Linux behavior differs from what Windows is 
doing.

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
H. Peter Anvin Oct. 26, 2012, 4:44 a.m. UTC | #7
My guess is that Windows explicitly enables A20 on resume.  We should do that too, really... with the current heavily unified realmode code it should be easy - let me hack up a patch in the morning.

Robert Hancock <hancockrwd@gmail.com> wrote:

>On 10/24/2012 02:09 PM, Alan Cox wrote:
>> On Wed, 24 Oct 2012 12:36:04 -0700
>> "H. Peter Anvin" <hpa@zytor.com> wrote:
>>
>>> Minor concern: it should do the wait for ready before sending each
>command.
>>
>> Can we get a command line to do this quirk too - it strikes me that
>if
>> the MSIs rely upon it then it may be something Windows always does so
>> will be useful to try on other problem machines as an experiment.
>
>I agree, one has to keep in mind the age-old question "how does Windows
>
>work?" since it surely has no such quirk. I'd say we're sometimes too 
>quick to add these DMI quirks when a more general solution would be 
>somehow figure out how the Linux behavior differs from what Windows is 
>doing.
Ondrej Zary Oct. 26, 2012, 6:20 a.m. UTC | #8
On Friday 26 October 2012, H. Peter Anvin wrote:
> My guess is that Windows explicitly enables A20 on resume.  We should do
> that too, really... with the current heavily unified realmode code it
> should be easy - let me hack up a patch in the morning.

Neither s3_beep nor s3_leds (this patch: 
https://lists.ubuntu.com/archives/kernel-team/2011-May/015621.html ) worked 
for me so I thing that BIOS breaks on resume before we can do anything.

> Robert Hancock <hancockrwd@gmail.com> wrote:
> >On 10/24/2012 02:09 PM, Alan Cox wrote:
> >> On Wed, 24 Oct 2012 12:36:04 -0700
> >>
> >> "H. Peter Anvin" <hpa@zytor.com> wrote:
> >>> Minor concern: it should do the wait for ready before sending each
> >
> >command.
> >
> >> Can we get a command line to do this quirk too - it strikes me that
> >
> >if
> >
> >> the MSIs rely upon it then it may be something Windows always does so
> >> will be useful to try on other problem machines as an experiment.
> >
> >I agree, one has to keep in mind the age-old question "how does Windows
> >
> >work?" since it surely has no such quirk. I'd say we're sometimes too
> >quick to add these DMI quirks when a more general solution would be
> >somehow figure out how the Linux behavior differs from what Windows is
> >doing.
diff mbox

Patch

--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1349,6 +1349,20 @@  static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
 }
 
 /*
+ * Enable A20 line using KBC even if it's already enabled using other method.
+ * This is needed for some MSI laptops to resume from S3.
+ */
+static int __init a20_enable_kbc(const struct dmi_system_id *d)
+{
+	printk(KERN_NOTICE "%s detected: enabling A20 using KBC\n", d->ident);
+	outb(0xd1, 0x64);	/* Command write */
+	outb(0xdf, 0x60);	/* A20 on */
+	outb(0xff, 0x64);	/* Null command, but UHCI wants it */
+
+	return 0;
+}
+
+/*
  * If your system is blacklisted here, but you find that acpi=force
  * works for you, please contact linux-acpi@vger.kernel.org
  */
@@ -1423,6 +1437,60 @@  static struct dmi_system_id __initdata acpi_dmi_table[] = {
 		     DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
 		     },
 	 },
+	/*
+	 * Some MSI laptop BIOSes are broken - INT 15h code uses port 92h to
+	 * enable A20 line but resume code assumes that KBC was used.
+	 * The laptop will not resume from S3 otherwise but powers off
+	 * after a while and then powers on again stuck with a blank screen.
+	 */
+	{
+	 .callback = a20_enable_kbc,
+	 .ident = "MSI EX600 Laptop",
+	 .matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook EX600"),
+		     },
+	 },
+	{
+	 .callback = a20_enable_kbc,
+	 .ident = "MSI EX700 Laptop",
+	 .matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "EX700"),
+		     },
+	 },
+	{
+	 .callback = a20_enable_kbc,
+	 .ident = "MSI GX700 Laptop",
+	 .matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
+		     },
+	 },
+	{
+	 .callback = a20_enable_kbc,
+	 .ident = "MSI VR201 Laptop",
+	 .matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook VR201"),
+		     },
+	 },
+	{
+	 .callback = a20_enable_kbc,
+	 .ident = "MSI VR601 Laptop",
+	 .matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook VR601"),
+		     },
+	 },
+	{
+	 .callback = a20_enable_kbc,
+	 .ident = "MSI PR200 Laptop",
+	 .matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "MSI Notebook PR200"),
+		     },
+	 },
 	{}
 };