提交 511d63cb 编写于 作者: H Horia Geanta 提交者: Herbert Xu

crypto: talitos - properly lock access to global talitos registers

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: NHoria Geanta <horia.geanta@freescale.com>
Signed-off-by: NKim Phillips <kim.phillips@freescale.com>
Signed-off-by: NHerbert Xu <herbert@gondor.apana.org.au>
上级 75258723
......@@ -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;
......@@ -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); \
......@@ -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)
......@@ -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; \
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册