diff options
Diffstat (limited to 'drivers/crypto')
| -rw-r--r-- | drivers/crypto/ixp4xx_crypto.c | 1 | ||||
| -rw-r--r-- | drivers/crypto/talitos.c | 20 | 
2 files changed, 18 insertions, 3 deletions
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 0053d7ebb5c..8f3f74ce8c7 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -18,6 +18,7 @@  #include <linux/interrupt.h>  #include <linux/spinlock.h>  #include <linux/gfp.h> +#include <linux/module.h>  #include <crypto/ctr.h>  #include <crypto/des.h> diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index dc641c79652..921039e56f8 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;      \ @@ -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;  |