Commit 91bfe298 authored by Sergei Shtylyov's avatar Sergei Shtylyov Committed by Wolfram Sang
Browse files

Revert "i2c: rcar: remove spinlock"



This reverts commit 150b8be3.

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: default avatarSergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Cc: stable@vger.kernel.org # 3.16+
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 75b81f33
Loading
Loading
Loading
Loading
+22 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/spinlock.h>


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


	spinlock_t lock;
	wait_queue_head_t wait;
	wait_queue_head_t wait;


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


	/*-------------- spin lock -----------------*/
	spin_lock(&priv->lock);

	msr = rcar_i2c_read(priv, ICMSR);
	msr = rcar_i2c_read(priv, ICMSR);


	/* Only handle interrupts that are currently enabled */
	/* Only handle interrupts that are currently enabled */
@@ -403,6 +408,9 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
		wake_up(&priv->wait);
		wake_up(&priv->wait);
	}
	}


	spin_unlock(&priv->lock);
	/*-------------- spin unlock -----------------*/

	return IRQ_HANDLED;
	return IRQ_HANDLED;
}
}


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


	pm_runtime_get_sync(dev);
	pm_runtime_get_sync(dev);


	/*-------------- spin lock -----------------*/
	spin_lock_irqsave(&priv->lock, flags);

	rcar_i2c_init(priv);
	rcar_i2c_init(priv);
	/* start clock */
	/* start clock */
	rcar_i2c_write(priv, ICCCR, priv->icccr);
	rcar_i2c_write(priv, ICCCR, priv->icccr);


	spin_unlock_irqrestore(&priv->lock, flags);
	/*-------------- spin unlock -----------------*/

	ret = rcar_i2c_bus_barrier(priv);
	ret = rcar_i2c_bus_barrier(priv);
	if (ret < 0)
	if (ret < 0)
		goto out;
		goto out;
@@ -431,6 +446,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
			break;
			break;
		}
		}


		/*-------------- spin lock -----------------*/
		spin_lock_irqsave(&priv->lock, flags);

		/* init each data */
		/* init each data */
		priv->msg	= &msgs[i];
		priv->msg	= &msgs[i];
		priv->pos	= 0;
		priv->pos	= 0;
@@ -440,6 +458,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,


		ret = rcar_i2c_prepare_msg(priv);
		ret = rcar_i2c_prepare_msg(priv);


		spin_unlock_irqrestore(&priv->lock, flags);
		/*-------------- spin unlock -----------------*/

		if (ret < 0)
		if (ret < 0)
			break;
			break;


@@ -543,6 +564,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)


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


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