aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2010-08-11 17:17:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-12 11:43:29 -0400
commit0a7992c90828a65281c3c9cf180be3b432d277b2 (patch)
tree41ecaca813576608b8eed10cabb9d8f3ab312dfa
parentd78a3eda6985e74bc21a23362f27526f73e71649 (diff)
acpi: fix bogus preemption logic
The ACPI_PREEMPTION_POINT() logic was introduced in commit 8bd108d (ACPICA: add preemption point after each opcode parse). The follow up commits abe1dfab6, 138d15692, c084ca70 tried to fix the preemption logic back and forth, but nobody noticed that the usage of in_atomic_preempt_off() in that context is wrong. The check which guards the call of cond_resched() is: if (!in_atomic_preempt_off() && !irqs_disabled()) in_atomic_preempt_off() is not intended for general use as the comment above the macro definition clearly says: * Check whether we were atomic before we did preempt_disable(): * (used by the scheduler, *after* releasing the kernel lock) On a CONFIG_PREEMPT=n kernel the usage of in_atomic_preempt_off() works by accident, but with CONFIG_PREEMPT=y it's just broken. The whole purpose of the ACPI_PREEMPTION_POINT() is to reduce the latency on a CONFIG_PREEMPT=n kernel, so make ACPI_PREEMPTION_POINT() depend on CONFIG_PREEMPT=n and remove the in_atomic_preempt_off() check. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=16210 [akpm@linux-foundation.org: fix build] Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Len Brown <lenb@kernel.org> Cc: Francois Valenduc <francois.valenduc@tvcablenet.be> Cc: Lin Ming <ming.m.lin@intel.com> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/acpi/apei/erst.c1
-rw-r--r--include/acpi/platform/aclinux.h10
2 files changed, 8 insertions, 3 deletions
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 864dd46c346f..18645f4e83cd 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -33,6 +33,7 @@
33#include <linux/uaccess.h> 33#include <linux/uaccess.h>
34#include <linux/cper.h> 34#include <linux/cper.h>
35#include <linux/nmi.h> 35#include <linux/nmi.h>
36#include <linux/hardirq.h>
36#include <acpi/apei.h> 37#include <acpi/apei.h>
37 38
38#include "apei-internal.h" 39#include "apei-internal.h"
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index e5039a2856f8..103f08aca764 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -148,13 +148,17 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache)
148#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a) 148#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a)
149#define ACPI_FREE(a) kfree(a) 149#define ACPI_FREE(a) kfree(a)
150 150
151/* Used within ACPICA to show where it is safe to preempt execution */ 151#ifndef CONFIG_PREEMPT
152#include <linux/hardirq.h> 152/*
153 * Used within ACPICA to show where it is safe to preempt execution
154 * when CONFIG_PREEMPT=n
155 */
153#define ACPI_PREEMPTION_POINT() \ 156#define ACPI_PREEMPTION_POINT() \
154 do { \ 157 do { \
155 if (!in_atomic_preempt_off() && !irqs_disabled()) \ 158 if (!irqs_disabled()) \
156 cond_resched(); \ 159 cond_resched(); \
157 } while (0) 160 } while (0)
161#endif
158 162
159#endif /* __KERNEL__ */ 163#endif /* __KERNEL__ */
160 164