diff options
-rw-r--r-- | arch/i386/kernel/apm.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index b42f2d914af3..2af65858d322 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c | |||
@@ -540,11 +540,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 | 540 | * 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. | 541 | * is no useful data returned in the low order 8 bits of eax. |
542 | */ | 542 | */ |
543 | #define APM_DO_CLI \ | 543 | |
544 | if (apm_info.allow_ints) \ | 544 | static inline unsigned long __apm_irq_save(void) |
545 | local_irq_enable(); \ | 545 | { |
546 | else \ | 546 | unsigned long flags; |
547 | local_save_flags(flags); | ||
548 | if (apm_info.allow_ints) { | ||
549 | if (irqs_disabled_flags(flags)) | ||
550 | local_irq_enable(); | ||
551 | } else | ||
552 | local_irq_disable(); | ||
553 | |||
554 | return flags; | ||
555 | } | ||
556 | |||
557 | #define apm_irq_save(flags) \ | ||
558 | do { flags = __apm_irq_save(); } while (0) | ||
559 | |||
560 | static inline void apm_irq_restore(unsigned long flags) | ||
561 | { | ||
562 | if (irqs_disabled_flags(flags)) | ||
547 | local_irq_disable(); | 563 | local_irq_disable(); |
564 | else if (irqs_disabled()) | ||
565 | local_irq_enable(); | ||
566 | } | ||
548 | 567 | ||
549 | #ifdef APM_ZERO_SEGS | 568 | #ifdef APM_ZERO_SEGS |
550 | # define APM_DECL_SEGS \ | 569 | # define APM_DECL_SEGS \ |
@@ -596,12 +615,11 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in, | |||
596 | save_desc_40 = gdt[0x40 / 8]; | 615 | save_desc_40 = gdt[0x40 / 8]; |
597 | gdt[0x40 / 8] = bad_bios_desc; | 616 | gdt[0x40 / 8] = bad_bios_desc; |
598 | 617 | ||
599 | local_save_flags(flags); | 618 | apm_irq_save(flags); |
600 | APM_DO_CLI; | ||
601 | APM_DO_SAVE_SEGS; | 619 | APM_DO_SAVE_SEGS; |
602 | apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi); | 620 | apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi); |
603 | APM_DO_RESTORE_SEGS; | 621 | APM_DO_RESTORE_SEGS; |
604 | local_irq_restore(flags); | 622 | apm_irq_restore(flags); |
605 | gdt[0x40 / 8] = save_desc_40; | 623 | gdt[0x40 / 8] = save_desc_40; |
606 | put_cpu(); | 624 | put_cpu(); |
607 | apm_restore_cpus(cpus); | 625 | apm_restore_cpus(cpus); |
@@ -640,12 +658,11 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax) | |||
640 | save_desc_40 = gdt[0x40 / 8]; | 658 | save_desc_40 = gdt[0x40 / 8]; |
641 | gdt[0x40 / 8] = bad_bios_desc; | 659 | gdt[0x40 / 8] = bad_bios_desc; |
642 | 660 | ||
643 | local_save_flags(flags); | 661 | apm_irq_save(flags); |
644 | APM_DO_CLI; | ||
645 | APM_DO_SAVE_SEGS; | 662 | APM_DO_SAVE_SEGS; |
646 | error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax); | 663 | error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax); |
647 | APM_DO_RESTORE_SEGS; | 664 | APM_DO_RESTORE_SEGS; |
648 | local_irq_restore(flags); | 665 | apm_irq_restore(flags); |
649 | gdt[0x40 / 8] = save_desc_40; | 666 | gdt[0x40 / 8] = save_desc_40; |
650 | put_cpu(); | 667 | put_cpu(); |
651 | apm_restore_cpus(cpus); | 668 | apm_restore_cpus(cpus); |