Skip to content

Commit

Permalink
clocksource: sh_cmt: Remove nested spinlock fix
Browse files Browse the repository at this point in the history
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.

[[email protected]: use __sh_cmt_set_next() to simplify code]
[[email protected]: added stable, suitable for v2.6.35 + v2.6.36]
Cc: [email protected]
Signed-off-by: Takashi YOSHII <[email protected]>
Signed-off-by: Magnus Damm <[email protected]>
Signed-off-by: Paul Mundt <[email protected]>
  • Loading branch information
Takashi YOSHII authored and pmundt committed Dec 17, 2010
1 parent b3444d1 commit 65ada54
Showing 1 changed file with 11 additions and 6 deletions.
17 changes: 11 additions & 6 deletions drivers/clocksource/sh_cmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,16 +283,21 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
} 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)
dev_warn(&p->pdev->dev, "delta out of range\n");

spin_lock_irqsave(&p->lock, flags);
p->next_match_value = delta;
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);
}

Expand Down Expand Up @@ -359,7 +364,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)

/* setup timeout if no 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:
spin_unlock_irqrestore(&p->lock, flags);

Expand All @@ -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 */
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);
}
Expand Down

0 comments on commit 65ada54

Please sign in to comment.