diff options
| author | Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> | 2014-08-23 16:44:09 -0400 |
|---|---|---|
| committer | Wolfram Sang <wsa@the-dreams.de> | 2014-09-04 13:59:42 -0400 |
| commit | 91bfe2989af02e709ca01ccf518c4fbda3efc70f (patch) | |
| tree | a4ebc7cde4b09aaea773dba793062cee10fefe80 /drivers/i2c | |
| parent | 75b81f339c6af43f6f4a1b3eabe0603321dade65 (diff) | |
Revert "i2c: rcar: remove spinlock"
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>
Diffstat (limited to 'drivers/i2c')
| -rw-r--r-- | drivers/i2c/busses/i2c-rcar.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index dc32f5fa75d0..1cc146cfc1f3 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
| 35 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
| 36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
| 37 | #include <linux/spinlock.h> | ||
| 37 | 38 | ||
| 38 | /* register offsets */ | 39 | /* register offsets */ |
| 39 | #define ICSCR 0x00 /* slave ctrl */ | 40 | #define ICSCR 0x00 /* slave ctrl */ |
| @@ -95,6 +96,7 @@ struct rcar_i2c_priv { | |||
| 95 | struct i2c_msg *msg; | 96 | struct i2c_msg *msg; |
| 96 | struct clk *clk; | 97 | struct clk *clk; |
| 97 | 98 | ||
| 99 | spinlock_t lock; | ||
| 98 | wait_queue_head_t wait; | 100 | wait_queue_head_t wait; |
| 99 | 101 | ||
| 100 | int pos; | 102 | int pos; |
| @@ -365,6 +367,9 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr) | |||
| 365 | struct rcar_i2c_priv *priv = ptr; | 367 | struct rcar_i2c_priv *priv = ptr; |
| 366 | u32 msr; | 368 | u32 msr; |
| 367 | 369 | ||
| 370 | /*-------------- spin lock -----------------*/ | ||
| 371 | spin_lock(&priv->lock); | ||
| 372 | |||
| 368 | msr = rcar_i2c_read(priv, ICMSR); | 373 | msr = rcar_i2c_read(priv, ICMSR); |
| 369 | 374 | ||
| 370 | /* Only handle interrupts that are currently enabled */ | 375 | /* Only handle interrupts that are currently enabled */ |
| @@ -403,6 +408,9 @@ out: | |||
| 403 | wake_up(&priv->wait); | 408 | wake_up(&priv->wait); |
| 404 | } | 409 | } |
| 405 | 410 | ||
| 411 | spin_unlock(&priv->lock); | ||
| 412 | /*-------------- spin unlock -----------------*/ | ||
| 413 | |||
| 406 | return IRQ_HANDLED; | 414 | return IRQ_HANDLED; |
| 407 | } | 415 | } |
| 408 | 416 | ||
| @@ -412,14 +420,21 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, | |||
| 412 | { | 420 | { |
| 413 | struct rcar_i2c_priv *priv = i2c_get_adapdata(adap); | 421 | struct rcar_i2c_priv *priv = i2c_get_adapdata(adap); |
| 414 | struct device *dev = rcar_i2c_priv_to_dev(priv); | 422 | struct device *dev = rcar_i2c_priv_to_dev(priv); |
| 423 | unsigned long flags; | ||
| 415 | int i, ret, timeout; | 424 | int i, ret, timeout; |
| 416 | 425 | ||
| 417 | pm_runtime_get_sync(dev); | 426 | pm_runtime_get_sync(dev); |
| 418 | 427 | ||
| 428 | /*-------------- spin lock -----------------*/ | ||
| 429 | spin_lock_irqsave(&priv->lock, flags); | ||
| 430 | |||
| 419 | rcar_i2c_init(priv); | 431 | rcar_i2c_init(priv); |
| 420 | /* start clock */ | 432 | /* start clock */ |
| 421 | rcar_i2c_write(priv, ICCCR, priv->icccr); | 433 | rcar_i2c_write(priv, ICCCR, priv->icccr); |
| 422 | 434 | ||
| 435 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 436 | /*-------------- spin unlock -----------------*/ | ||
| 437 | |||
| 423 | ret = rcar_i2c_bus_barrier(priv); | 438 | ret = rcar_i2c_bus_barrier(priv); |
| 424 | if (ret < 0) | 439 | if (ret < 0) |
| 425 | goto out; | 440 | goto out; |
| @@ -431,6 +446,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, | |||
| 431 | break; | 446 | break; |
| 432 | } | 447 | } |
| 433 | 448 | ||
| 449 | /*-------------- spin lock -----------------*/ | ||
| 450 | spin_lock_irqsave(&priv->lock, flags); | ||
| 451 | |||
| 434 | /* init each data */ | 452 | /* init each data */ |
| 435 | priv->msg = &msgs[i]; | 453 | priv->msg = &msgs[i]; |
| 436 | priv->pos = 0; | 454 | priv->pos = 0; |
| @@ -440,6 +458,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, | |||
| 440 | 458 | ||
| 441 | ret = rcar_i2c_prepare_msg(priv); | 459 | ret = rcar_i2c_prepare_msg(priv); |
| 442 | 460 | ||
| 461 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 462 | /*-------------- spin unlock -----------------*/ | ||
| 463 | |||
| 443 | if (ret < 0) | 464 | if (ret < 0) |
| 444 | break; | 465 | break; |
| 445 | 466 | ||
| @@ -543,6 +564,7 @@ static int rcar_i2c_probe(struct platform_device *pdev) | |||
| 543 | 564 | ||
| 544 | irq = platform_get_irq(pdev, 0); | 565 | irq = platform_get_irq(pdev, 0); |
| 545 | init_waitqueue_head(&priv->wait); | 566 | init_waitqueue_head(&priv->wait); |
| 567 | spin_lock_init(&priv->lock); | ||
| 546 | 568 | ||
| 547 | adap = &priv->adap; | 569 | adap = &priv->adap; |
| 548 | adap->nr = pdev->id; | 570 | adap->nr = pdev->id; |
