[PATCH 3.16 048/357] Revert "i2c: rcar: remove spinlock"

From: Greg Kroah-Hartman
Date: Fri Oct 03 2014 - 20:49:25 EST


3.16-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sergei Shtylyov <sergei.shtylyov@xxxxxxxxxxxxxxxxxx>

commit 91bfe2989af02e709ca01ccf518c4fbda3efc70f upstream.

This reverts commit 150b8be3cda54412ad7b54f5392b513b25c0aaa7.

The I2C core's per-adapter locks can't protect from IRQs, so the driver still
needs a spinlock to protect the register accesses.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Wolfram Sang <wsa@xxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
drivers/i2c/busses/i2c-rcar.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -34,6 +34,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
+#include <linux/spinlock.h>

/* register offsets */
#define ICSCR 0x00 /* slave ctrl */
@@ -95,6 +96,7 @@ struct rcar_i2c_priv {
struct i2c_msg *msg;
struct clk *clk;

+ spinlock_t lock;
wait_queue_head_t wait;

int pos;
@@ -365,6 +367,9 @@ static irqreturn_t rcar_i2c_irq(int irq,
struct rcar_i2c_priv *priv = ptr;
u32 msr;

+ /*-------------- spin lock -----------------*/
+ spin_lock(&priv->lock);
+
msr = rcar_i2c_read(priv, ICMSR);

/* Arbitration lost */
@@ -400,6 +405,9 @@ out:
wake_up(&priv->wait);
}

+ spin_unlock(&priv->lock);
+ /*-------------- spin unlock -----------------*/
+
return IRQ_HANDLED;
}

@@ -409,14 +417,21 @@ static int rcar_i2c_master_xfer(struct i
{
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
struct device *dev = rcar_i2c_priv_to_dev(priv);
+ unsigned long flags;
int i, ret, timeout;

pm_runtime_get_sync(dev);

+ /*-------------- spin lock -----------------*/
+ spin_lock_irqsave(&priv->lock, flags);
+
rcar_i2c_init(priv);
/* start clock */
rcar_i2c_write(priv, ICCCR, priv->icccr);

+ spin_unlock_irqrestore(&priv->lock, flags);
+ /*-------------- spin unlock -----------------*/
+
ret = rcar_i2c_bus_barrier(priv);
if (ret < 0)
goto out;
@@ -428,6 +443,9 @@ static int rcar_i2c_master_xfer(struct i
break;
}

+ /*-------------- spin lock -----------------*/
+ spin_lock_irqsave(&priv->lock, flags);
+
/* init each data */
priv->msg = &msgs[i];
priv->pos = 0;
@@ -437,6 +455,9 @@ static int rcar_i2c_master_xfer(struct i

ret = rcar_i2c_prepare_msg(priv);

+ spin_unlock_irqrestore(&priv->lock, flags);
+ /*-------------- spin unlock -----------------*/
+
if (ret < 0)
break;

@@ -540,6 +561,7 @@ static int rcar_i2c_probe(struct platfor

irq = platform_get_irq(pdev, 0);
init_waitqueue_head(&priv->wait);
+ spin_lock_init(&priv->lock);

adap = &priv->adap;
adap->nr = pdev->id;


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/