diff options
Diffstat (limited to 'arch/i386/kernel/apm.c')
-rw-r--r-- | arch/i386/kernel/apm.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index b42f2d914af3..a97847da9ed5 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c | |||
@@ -198,7 +198,7 @@ | |||
198 | * (APM) BIOS Interface Specification, Revision 1.2, February 1996. | 198 | * (APM) BIOS Interface Specification, Revision 1.2, February 1996. |
199 | * | 199 | * |
200 | * [This document is available from Microsoft at: | 200 | * [This document is available from Microsoft at: |
201 | * http://www.microsoft.com/hwdev/busbios/amp_12.htm] | 201 | * http://www.microsoft.com/whdc/archive/amp_12.mspx] |
202 | */ | 202 | */ |
203 | 203 | ||
204 | #include <linux/module.h> | 204 | #include <linux/module.h> |
@@ -231,6 +231,7 @@ | |||
231 | #include <asm/uaccess.h> | 231 | #include <asm/uaccess.h> |
232 | #include <asm/desc.h> | 232 | #include <asm/desc.h> |
233 | #include <asm/i8253.h> | 233 | #include <asm/i8253.h> |
234 | #include <asm/paravirt.h> | ||
234 | 235 | ||
235 | #include "io_ports.h" | 236 | #include "io_ports.h" |
236 | 237 | ||
@@ -540,11 +541,30 @@ static inline void apm_restore_cpus(cpumask_t mask) | |||
540 | * Also, we KNOW that for the non error case of apm_bios_call, there | 541 | * Also, we KNOW that for the non error case of apm_bios_call, there |
541 | * is no useful data returned in the low order 8 bits of eax. | 542 | * is no useful data returned in the low order 8 bits of eax. |
542 | */ | 543 | */ |
543 | #define APM_DO_CLI \ | 544 | |
544 | if (apm_info.allow_ints) \ | 545 | static inline unsigned long __apm_irq_save(void) |
545 | local_irq_enable(); \ | 546 | { |
546 | else \ | 547 | unsigned long flags; |
548 | local_save_flags(flags); | ||
549 | if (apm_info.allow_ints) { | ||
550 | if (irqs_disabled_flags(flags)) | ||
551 | local_irq_enable(); | ||
552 | } else | ||
553 | local_irq_disable(); | ||
554 | |||
555 | return flags; | ||
556 | } | ||
557 | |||
558 | #define apm_irq_save(flags) \ | ||
559 | do { flags = __apm_irq_save(); } while (0) | ||
560 | |||
561 | static inline void apm_irq_restore(unsigned long flags) | ||
562 | { | ||
563 | if (irqs_disabled_flags(flags)) | ||
547 | local_irq_disable(); | 564 | local_irq_disable(); |
565 | else if (irqs_disabled()) | ||
566 | local_irq_enable(); | ||
567 | } | ||
548 | 568 | ||
549 | #ifdef APM_ZERO_SEGS | 569 | #ifdef APM_ZERO_SEGS |
550 | # define APM_DECL_SEGS \ | 570 | # define APM_DECL_SEGS \ |
@@ -596,12 +616,11 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in, | |||
596 | save_desc_40 = gdt[0x40 / 8]; | 616 | save_desc_40 = gdt[0x40 / 8]; |
597 | gdt[0x40 / 8] = bad_bios_desc; | 617 | gdt[0x40 / 8] = bad_bios_desc; |
598 | 618 | ||
599 | local_save_flags(flags); | 619 | apm_irq_save(flags); |
600 | APM_DO_CLI; | ||
601 | APM_DO_SAVE_SEGS; | 620 | APM_DO_SAVE_SEGS; |
602 | apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi); | 621 | apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi); |
603 | APM_DO_RESTORE_SEGS; | 622 | APM_DO_RESTORE_SEGS; |
604 | local_irq_restore(flags); | 623 | apm_irq_restore(flags); |
605 | gdt[0x40 / 8] = save_desc_40; | 624 | gdt[0x40 / 8] = save_desc_40; |
606 | put_cpu(); | 625 | put_cpu(); |
607 | apm_restore_cpus(cpus); | 626 | apm_restore_cpus(cpus); |
@@ -640,12 +659,11 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax) | |||
640 | save_desc_40 = gdt[0x40 / 8]; | 659 | save_desc_40 = gdt[0x40 / 8]; |
641 | gdt[0x40 / 8] = bad_bios_desc; | 660 | gdt[0x40 / 8] = bad_bios_desc; |
642 | 661 | ||
643 | local_save_flags(flags); | 662 | apm_irq_save(flags); |
644 | APM_DO_CLI; | ||
645 | APM_DO_SAVE_SEGS; | 663 | APM_DO_SAVE_SEGS; |
646 | error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax); | 664 | error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax); |
647 | APM_DO_RESTORE_SEGS; | 665 | APM_DO_RESTORE_SEGS; |
648 | local_irq_restore(flags); | 666 | apm_irq_restore(flags); |
649 | gdt[0x40 / 8] = save_desc_40; | 667 | gdt[0x40 / 8] = save_desc_40; |
650 | put_cpu(); | 668 | put_cpu(); |
651 | apm_restore_cpus(cpus); | 669 | apm_restore_cpus(cpus); |
@@ -2218,7 +2236,7 @@ static int __init apm_init(void) | |||
2218 | 2236 | ||
2219 | dmi_check_system(apm_dmi_table); | 2237 | dmi_check_system(apm_dmi_table); |
2220 | 2238 | ||
2221 | if (apm_info.bios.version == 0) { | 2239 | if (apm_info.bios.version == 0 || paravirt_enabled()) { |
2222 | printk(KERN_INFO "apm: BIOS not found.\n"); | 2240 | printk(KERN_INFO "apm: BIOS not found.\n"); |
2223 | return -ENODEV; | 2241 | return -ENODEV; |
2224 | } | 2242 | } |