summaryrefslogtreecommitdiff
path: root/drivers/crypto/talitos.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-05-24 12:13:01 +0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-05-24 12:13:01 +0400
commite644dae645e167d154c0526358940986682a72b0 (patch)
tree972993c6568085b8d407fc7e13de10f4b93c651d /drivers/crypto/talitos.c
parent899c612d74d4a242158a4db20367388d6299c028 (diff)
parent86809173ce32ef03bd4d0389dfc72df0c805e9c4 (diff)
downloadlinux-e644dae645e167d154c0526358940986682a72b0.tar.xz
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/crypto/talitos.c')
-rw-r--r--drivers/crypto/talitos.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 2d8c78901686..921039e56f87 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -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; \
@@ -2648,6 +2660,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
alg->cra_priority = TALITOS_CRA_PRIORITY;
alg->cra_alignmask = 0;
alg->cra_ctxsize = sizeof(struct talitos_ctx);
+ alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
t_alg->dev = dev;
@@ -2718,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;