Commit 65ada547 authored by Takashi YOSHII's avatar Takashi YOSHII Committed by Paul Mundt

clocksource: sh_cmt: Remove nested spinlock fix

There are control flow that sh_cmt_set_next() does double
spin-lock. The callers sh_cmt_{start,stop}() already have
lock. But another callers sh_cmt_clock_event_{start,next}()
does not.

Now sh_cmt_set_next() does not lock by itself. All the
callers should hold spin-lock before calling it.

[damm@opensource.se: use __sh_cmt_set_next() to simplify code]
[damm@opensource.se: added stable, suitable for v2.6.35 + v2.6.36]
Cc: stable@kernel.org
Signed-off-by: default avatarTakashi YOSHII <takashi.yoshii.zj@renesas.com>
Signed-off-by: default avatarMagnus Damm <damm@opensource.se>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent b3444d16
...@@ -283,16 +283,21 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p, ...@@ -283,16 +283,21 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
} while (delay); } while (delay);
} }
static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) static void __sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
{ {
unsigned long flags;
if (delta > p->max_match_value) if (delta > p->max_match_value)
dev_warn(&p->pdev->dev, "delta out of range\n"); dev_warn(&p->pdev->dev, "delta out of range\n");
spin_lock_irqsave(&p->lock, flags);
p->next_match_value = delta; p->next_match_value = delta;
sh_cmt_clock_event_program_verify(p, 0); sh_cmt_clock_event_program_verify(p, 0);
}
static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
{
unsigned long flags;
spin_lock_irqsave(&p->lock, flags);
__sh_cmt_set_next(p, delta);
spin_unlock_irqrestore(&p->lock, flags); spin_unlock_irqrestore(&p->lock, flags);
} }
...@@ -359,7 +364,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag) ...@@ -359,7 +364,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
/* setup timeout if no clockevent */ /* setup timeout if no clockevent */
if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT))) if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
sh_cmt_set_next(p, p->max_match_value); __sh_cmt_set_next(p, p->max_match_value);
out: out:
spin_unlock_irqrestore(&p->lock, flags); spin_unlock_irqrestore(&p->lock, flags);
...@@ -381,7 +386,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag) ...@@ -381,7 +386,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
/* adjust the timeout to maximum if only clocksource left */ /* adjust the timeout to maximum if only clocksource left */
if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE)) if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
sh_cmt_set_next(p, p->max_match_value); __sh_cmt_set_next(p, p->max_match_value);
spin_unlock_irqrestore(&p->lock, flags); spin_unlock_irqrestore(&p->lock, flags);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment