diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2009-09-21 03:30:09 -0400 |
---|---|---|
committer | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2010-01-22 11:04:39 -0500 |
commit | 501d70383aa9ffc78b41aa7e74f6b0254c7c731c (patch) | |
tree | b0a9421468f16aabff7ff8e92cf1655d17ef7eef /arch/arm | |
parent | 066000dd856709b6980123eb39b957fe26993f7b (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.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam926x_time.c | 11 |
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) | |||
132 | static int | 138 | static int |
133 | clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) | 139 | clkevt32k_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 = { | |||
62 | static void | 62 | static void |
63 | pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) | 63 | pit_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 | */ |
101 | static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id) | 97 | static 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) |