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@cogentembedded.com>
Cc: stable@vger.kernel.org # 3.16+
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
(cherry picked from commit
91bfe2989af02e709ca01ccf518c4fbda3efc70f)
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#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 */
/* register offsets */
#define ICSCR 0x00 /* slave ctrl */
struct i2c_msg *msg;
struct clk *clk;
struct i2c_msg *msg;
struct clk *clk;
wait_queue_head_t wait;
int pos;
wait_queue_head_t wait;
int pos;
struct rcar_i2c_priv *priv = ptr;
u32 msr;
struct rcar_i2c_priv *priv = ptr;
u32 msr;
+ /*-------------- spin lock -----------------*/
+ spin_lock(&priv->lock);
+
msr = rcar_i2c_read(priv, ICMSR);
/* Only handle interrupts that are currently enabled */
msr = rcar_i2c_read(priv, ICMSR);
/* Only handle interrupts that are currently enabled */
+ spin_unlock(&priv->lock);
+ /*-------------- spin unlock -----------------*/
+
{
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
struct device *dev = rcar_i2c_priv_to_dev(priv);
{
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
struct device *dev = rcar_i2c_priv_to_dev(priv);
int i, ret, timeout;
pm_runtime_get_sync(dev);
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);
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;
ret = rcar_i2c_bus_barrier(priv);
if (ret < 0)
goto out;
+ /*-------------- spin lock -----------------*/
+ spin_lock_irqsave(&priv->lock, flags);
+
/* init each data */
priv->msg = &msgs[i];
priv->pos = 0;
/* init each data */
priv->msg = &msgs[i];
priv->pos = 0;
ret = rcar_i2c_prepare_msg(priv);
ret = rcar_i2c_prepare_msg(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ /*-------------- spin unlock -----------------*/
+
irq = platform_get_irq(pdev, 0);
init_waitqueue_head(&priv->wait);
irq = platform_get_irq(pdev, 0);
init_waitqueue_head(&priv->wait);
+ spin_lock_init(&priv->lock);
adap = &priv->adap;
adap->nr = pdev->id;
adap = &priv->adap;
adap->nr = pdev->id;