aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2009-09-21 03:30:09 -0400
committerUwe Kleine-König <u.kleine-koenig@pengutronix.de>2010-01-22 11:04:39 -0500
commit501d70383aa9ffc78b41aa7e74f6b0254c7c731c (patch)
treeb0a9421468f16aabff7ff8e92cf1655d17ef7eef /arch/arm
parent066000dd856709b6980123eb39b957fe26993f7b (diff)
arm/at91: Don't disable irqs in set_next_event and set_mode callbacks
on AT91 the timer irq is shared, so the handler might be entered without irqs being disabled. Though this should not happen as the timer irq is registered early, there have been some reports on the mailing list. To make debugging that problem easier next time it pops up a WARN_ON_ONCE is added to the handler if irqs are not off. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-at91/at91rm9200_time.c20
-rw-r--r--arch/arm/mach-at91/at91sam926x_time.c11
2 files changed, 12 insertions, 19 deletions
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index 309f3511aa20..2500f41d8d2d 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -58,6 +58,12 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
58{ 58{
59 u32 sr = at91_sys_read(AT91_ST_SR) & irqmask; 59 u32 sr = at91_sys_read(AT91_ST_SR) & irqmask;
60 60
61 /*
62 * irqs should be disabled here, but as the irq is shared they are only
63 * guaranteed to be off if the timer irq is registered first.
64 */
65 WARN_ON_ONCE(!irqs_disabled());
66
61 /* simulate "oneshot" timer with alarm */ 67 /* simulate "oneshot" timer with alarm */
62 if (sr & AT91_ST_ALMS) { 68 if (sr & AT91_ST_ALMS) {
63 clkevt.event_handler(&clkevt); 69 clkevt.event_handler(&clkevt);
@@ -132,24 +138,11 @@ clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
132static int 138static int
133clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) 139clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
134{ 140{
135 unsigned long flags;
136 u32 alm; 141 u32 alm;
137 int status = 0; 142 int status = 0;
138 143
139 BUG_ON(delta < 2); 144 BUG_ON(delta < 2);
140 145
141 /* Use "raw" primitives so we behave correctly on RT kernels. */
142 raw_local_irq_save(flags);
143
144 /*
145 * According to Thomas Gleixner irqs are already disabled here. Simply
146 * removing raw_local_irq_save above (and the matching
147 * raw_local_irq_restore) was not accepted. See
148 * http://thread.gmane.org/gmane.linux.ports.arm.kernel/41174
149 * So for now (2008-11-20) just warn once if irqs were not disabled ...
150 */
151 WARN_ON_ONCE(!raw_irqs_disabled_flags(flags));
152
153 /* The alarm IRQ uses absolute time (now+delta), not the relative 146 /* The alarm IRQ uses absolute time (now+delta), not the relative
154 * time (delta) in our calling convention. Like all clockevents 147 * time (delta) in our calling convention. Like all clockevents
155 * using such "match" hardware, we have a race to defend against. 148 * using such "match" hardware, we have a race to defend against.
@@ -169,7 +162,6 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
169 alm += delta; 162 alm += delta;
170 at91_sys_write(AT91_ST_RTAR, alm); 163 at91_sys_write(AT91_ST_RTAR, alm);
171 164
172 raw_local_irq_restore(flags);
173 return status; 165 return status;
174} 166}
175 167
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 4bd56aee4370..608a63240b64 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -62,16 +62,12 @@ static struct clocksource pit_clk = {
62static void 62static void
63pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) 63pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
64{ 64{
65 unsigned long flags;
66
67 switch (mode) { 65 switch (mode) {
68 case CLOCK_EVT_MODE_PERIODIC: 66 case CLOCK_EVT_MODE_PERIODIC:
69 /* update clocksource counter, then enable the IRQ */ 67 /* update clocksource counter */
70 raw_local_irq_save(flags);
71 pit_cnt += pit_cycle * PIT_PICNT(at91_sys_read(AT91_PIT_PIVR)); 68 pit_cnt += pit_cycle * PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
72 at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN 69 at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN
73 | AT91_PIT_PITIEN); 70 | AT91_PIT_PITIEN);
74 raw_local_irq_restore(flags);
75 break; 71 break;
76 case CLOCK_EVT_MODE_ONESHOT: 72 case CLOCK_EVT_MODE_ONESHOT:
77 BUG(); 73 BUG();
@@ -100,6 +96,11 @@ static struct clock_event_device pit_clkevt = {
100 */ 96 */
101static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id) 97static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
102{ 98{
99 /*
100 * irqs should be disabled here, but as the irq is shared they are only
101 * guaranteed to be off if the timer irq is registered first.
102 */
103 WARN_ON_ONCE(!irqs_disabled());
103 104
104 /* The PIT interrupt may be disabled, and is shared */ 105 /* The PIT interrupt may be disabled, and is shared */
105 if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC) 106 if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC)