Skip to content

Commit 86ba8b0

Browse files
committed
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c bugfixes from Wolfram Sang: "I2C driver bugfixes for the 3.17 release. Details can be found in the commit messages, yet I think this is typical driver stuff" * 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: Revert "i2c: rcar: remove spinlock" i2c: at91: add bound checking on SMBus block length bytes i2c: rk3x: fix bug that cause transfer fails in master receive mode i2c: at91: Fix a race condition during signal handling in at91_do_twi_xfer. i2c: mv64xxx: continue probe when clock-frequency is missing i2c: rcar: fix MNR interrupt handling
2 parents fb76234 + 91bfe29 commit 86ba8b0

File tree

4 files changed

+62
-14
lines changed

4 files changed

+62
-14
lines changed

drivers/i2c/busses/i2c-at91.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ struct at91_twi_dev {
101101
unsigned twi_cwgr_reg;
102102
struct at91_twi_pdata *pdata;
103103
bool use_dma;
104+
bool recv_len_abort;
104105
struct at91_twi_dma dma;
105106
};
106107

@@ -267,12 +268,24 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
267268
*dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff;
268269
--dev->buf_len;
269270

271+
/* return if aborting, we only needed to read RHR to clear RXRDY*/
272+
if (dev->recv_len_abort)
273+
return;
274+
270275
/* handle I2C_SMBUS_BLOCK_DATA */
271276
if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) {
272-
dev->msg->flags &= ~I2C_M_RECV_LEN;
273-
dev->buf_len += *dev->buf;
274-
dev->msg->len = dev->buf_len + 1;
275-
dev_dbg(dev->dev, "received block length %d\n", dev->buf_len);
277+
/* ensure length byte is a valid value */
278+
if (*dev->buf <= I2C_SMBUS_BLOCK_MAX && *dev->buf > 0) {
279+
dev->msg->flags &= ~I2C_M_RECV_LEN;
280+
dev->buf_len += *dev->buf;
281+
dev->msg->len = dev->buf_len + 1;
282+
dev_dbg(dev->dev, "received block length %d\n",
283+
dev->buf_len);
284+
} else {
285+
/* abort and send the stop by reading one more byte */
286+
dev->recv_len_abort = true;
287+
dev->buf_len = 1;
288+
}
276289
}
277290

278291
/* send stop if second but last byte has been read */
@@ -421,8 +434,8 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
421434
}
422435
}
423436

424-
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
425-
dev->adapter.timeout);
437+
ret = wait_for_completion_io_timeout(&dev->cmd_complete,
438+
dev->adapter.timeout);
426439
if (ret == 0) {
427440
dev_err(dev->dev, "controller timed out\n");
428441
at91_init_twi_bus(dev);
@@ -444,6 +457,12 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
444457
ret = -EIO;
445458
goto error;
446459
}
460+
if (dev->recv_len_abort) {
461+
dev_err(dev->dev, "invalid smbus block length recvd\n");
462+
ret = -EPROTO;
463+
goto error;
464+
}
465+
447466
dev_dbg(dev->dev, "transfer complete\n");
448467

449468
return 0;
@@ -500,6 +519,7 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
500519
dev->buf_len = m_start->len;
501520
dev->buf = m_start->buf;
502521
dev->msg = m_start;
522+
dev->recv_len_abort = false;
503523

504524
ret = at91_do_twi_transfer(dev);
505525

drivers/i2c/busses/i2c-mv64xxx.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,8 +746,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
746746
}
747747
tclk = clk_get_rate(drv_data->clk);
748748

749-
rc = of_property_read_u32(np, "clock-frequency", &bus_freq);
750-
if (rc)
749+
if (of_property_read_u32(np, "clock-frequency", &bus_freq))
751750
bus_freq = 100000; /* 100kHz by default */
752751

753752
if (!mv64xxx_find_baud_factors(bus_freq, tclk,

drivers/i2c/busses/i2c-rcar.c

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/platform_device.h>
3535
#include <linux/pm_runtime.h>
3636
#include <linux/slab.h>
37+
#include <linux/spinlock.h>
3738

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

99+
spinlock_t lock;
98100
wait_queue_head_t wait;
99101

100102
int pos;
@@ -365,20 +367,20 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
365367
struct rcar_i2c_priv *priv = ptr;
366368
u32 msr;
367369

370+
/*-------------- spin lock -----------------*/
371+
spin_lock(&priv->lock);
372+
368373
msr = rcar_i2c_read(priv, ICMSR);
369374

375+
/* Only handle interrupts that are currently enabled */
376+
msr &= rcar_i2c_read(priv, ICMIER);
377+
370378
/* Arbitration lost */
371379
if (msr & MAL) {
372380
rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
373381
goto out;
374382
}
375383

376-
/* Stop */
377-
if (msr & MST) {
378-
rcar_i2c_flags_set(priv, ID_DONE);
379-
goto out;
380-
}
381-
382384
/* Nack */
383385
if (msr & MNR) {
384386
/* go to stop phase */
@@ -388,6 +390,12 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
388390
goto out;
389391
}
390392

393+
/* Stop */
394+
if (msr & MST) {
395+
rcar_i2c_flags_set(priv, ID_DONE);
396+
goto out;
397+
}
398+
391399
if (rcar_i2c_is_recv(priv))
392400
rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
393401
else
@@ -400,6 +408,9 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
400408
wake_up(&priv->wait);
401409
}
402410

411+
spin_unlock(&priv->lock);
412+
/*-------------- spin unlock -----------------*/
413+
403414
return IRQ_HANDLED;
404415
}
405416

@@ -409,14 +420,21 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
409420
{
410421
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
411422
struct device *dev = rcar_i2c_priv_to_dev(priv);
423+
unsigned long flags;
412424
int i, ret, timeout;
413425

414426
pm_runtime_get_sync(dev);
415427

428+
/*-------------- spin lock -----------------*/
429+
spin_lock_irqsave(&priv->lock, flags);
430+
416431
rcar_i2c_init(priv);
417432
/* start clock */
418433
rcar_i2c_write(priv, ICCCR, priv->icccr);
419434

435+
spin_unlock_irqrestore(&priv->lock, flags);
436+
/*-------------- spin unlock -----------------*/
437+
420438
ret = rcar_i2c_bus_barrier(priv);
421439
if (ret < 0)
422440
goto out;
@@ -428,6 +446,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
428446
break;
429447
}
430448

449+
/*-------------- spin lock -----------------*/
450+
spin_lock_irqsave(&priv->lock, flags);
451+
431452
/* init each data */
432453
priv->msg = &msgs[i];
433454
priv->pos = 0;
@@ -437,6 +458,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
437458

438459
ret = rcar_i2c_prepare_msg(priv);
439460

461+
spin_unlock_irqrestore(&priv->lock, flags);
462+
/*-------------- spin unlock -----------------*/
463+
440464
if (ret < 0)
441465
break;
442466

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

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

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

drivers/i2c/busses/i2c-rk3x.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,10 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd)
323323
/* ack interrupt */
324324
i2c_writel(i2c, REG_INT_MBRF, REG_IPD);
325325

326+
/* Can only handle a maximum of 32 bytes at a time */
327+
if (len > 32)
328+
len = 32;
329+
326330
/* read the data from receive buffer */
327331
for (i = 0; i < len; ++i) {
328332
if (i % 4 == 0)

0 commit comments

Comments
 (0)