Skip to content

Commit 4bba0fd

Browse files
Jon PoveyBen Dooks
authored andcommitted
i2c-davinci: Fix race when setting up for TX
When setting up to transmit, a race exists between the ISR and i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. This is mostly visible for transmits > 1 byte long. The hardware starts sending immediately that MDR is loaded. IMR trickery doesn't work because if we start sending, finish the first byte and an XRDY event occurs before we load IMR to unmask it, we never get an interrupt, and we timeout. Move the MDR load after DXR,IMR loads to avoid this race without locking. Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 Signed-off-by: Jon Povey <jon.povey@racelogic.co.uk> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
1 parent cc33e54 commit 4bba0fd

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

drivers/i2c/busses/i2c-davinci.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,9 +357,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
357357

358358
dev->terminate = 0;
359359

360-
/* write the data into mode register */
361-
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
362-
363360
/*
364361
* First byte should be set here, not after interrupt,
365362
* because transmit-data-ready interrupt can come before
@@ -371,6 +368,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
371368
dev->buf_len--;
372369
}
373370

371+
/* write the data into mode register; start transmitting */
372+
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
373+
374374
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
375375
dev->adapter.timeout);
376376
if (r == 0) {

0 commit comments

Comments
 (0)