Skip to content

Commit

Permalink
crypto: talitos - properly lock access to global talitos registers
Browse files Browse the repository at this point in the history
Access to global talitos registers must be protected for the case when
affinities are configured such that primary and secondary talitos irqs
run on different cpus.

Signed-off-by: Horia Geanta <horia.geanta@freescale.com>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Horia Geanta authored and Herbert Xu committed Apr 9, 2012
1 parent 7525872 commit 511d63c
Showing 1 changed file with 17 additions and 3 deletions.
20 changes: 17 additions & 3 deletions drivers/crypto/talitos.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ struct talitos_private {
void __iomem *reg;
int irq[2];

/* SEC global registers lock */
spinlock_t reg_lock ____cacheline_aligned;

/* SEC version geometry (from device tree node) */
unsigned int num_channels;
unsigned int chfifo_len;
Expand Down Expand Up @@ -412,6 +415,7 @@ static void talitos_done_##name(unsigned long data) \
{ \
struct device *dev = (struct device *)data; \
struct talitos_private *priv = dev_get_drvdata(dev); \
unsigned long flags; \
\
if (ch_done_mask & 1) \
flush_channel(dev, 0, 0, 0); \
Expand All @@ -427,8 +431,10 @@ static void talitos_done_##name(unsigned long data) \
out: \
/* At this point, all completed channels have been processed */ \
/* Unmask done interrupts for channels completed later on. */ \
spin_lock_irqsave(&priv->reg_lock, flags); \
setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); \
spin_unlock_irqrestore(&priv->reg_lock, flags); \
}
DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE)
DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE)
Expand Down Expand Up @@ -619,22 +625,28 @@ static irqreturn_t talitos_interrupt_##name(int irq, void *data) \
struct device *dev = data; \
struct talitos_private *priv = dev_get_drvdata(dev); \
u32 isr, isr_lo; \
unsigned long flags; \
\
spin_lock_irqsave(&priv->reg_lock, flags); \
isr = in_be32(priv->reg + TALITOS_ISR); \
isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
/* Acknowledge interrupt */ \
out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
\
if (unlikely((isr & ~TALITOS_ISR_4CHDONE) & ch_err_mask || isr_lo)) \
talitos_error(dev, isr, isr_lo); \
else \
if (unlikely(isr & ch_err_mask || isr_lo)) { \
spin_unlock_irqrestore(&priv->reg_lock, flags); \
talitos_error(dev, isr & ch_err_mask, isr_lo); \
} \
else { \
if (likely(isr & ch_done_mask)) { \
/* mask further done interrupts. */ \
clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
/* done_task will unmask done interrupts at exit */ \
tasklet_schedule(&priv->done_task[tlet]); \
} \
spin_unlock_irqrestore(&priv->reg_lock, flags); \
} \
\
return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
IRQ_NONE; \
Expand Down Expand Up @@ -2719,6 +2731,8 @@ static int talitos_probe(struct platform_device *ofdev)

priv->ofdev = ofdev;

spin_lock_init(&priv->reg_lock);

err = talitos_probe_irq(ofdev);
if (err)
goto err_out;
Expand Down

0 comments on commit 511d63c

Please sign in to comment.