Skip to content

Commit f8160d3

Browse files
tq-gregorHerburgerwsakernel
authored andcommitted
i2c: ocores: generate stop condition after timeout in polling mode
In polling mode, no stop condition is generated after a timeout. This causes SCL to remain low and thereby block the bus. If this happens during a transfer it can cause slaves to misinterpret the subsequent transfer and return wrong values. To solve this, pass the ETIMEDOUT error up from ocores_process_polling() instead of setting STATE_ERROR directly. The caller is adjusted to call ocores_process_timeout() on error both in polling and in IRQ mode, which will set STATE_ERROR and generate a stop condition. Fixes: 69c8c0c ("i2c: ocores: add polling interface") Signed-off-by: Gregor Herburger <[email protected]> Signed-off-by: Matthias Schiffer <[email protected]> Acked-by: Peter Korsgaard <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Reviewed-by: Federico Vaga <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent aa874cd commit f8160d3

1 file changed

Lines changed: 19 additions & 16 deletions

File tree

drivers/i2c/busses/i2c-ocores.c

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -342,18 +342,18 @@ static int ocores_poll_wait(struct ocores_i2c *i2c)
342342
* ocores_isr(), we just add our polling code around it.
343343
*
344344
* It can run in atomic context
345+
*
346+
* Return: 0 on success, -ETIMEDOUT on timeout
345347
*/
346-
static void ocores_process_polling(struct ocores_i2c *i2c)
348+
static int ocores_process_polling(struct ocores_i2c *i2c)
347349
{
348-
while (1) {
349-
irqreturn_t ret;
350-
int err;
350+
irqreturn_t ret;
351+
int err = 0;
351352

353+
while (1) {
352354
err = ocores_poll_wait(i2c);
353-
if (err) {
354-
i2c->state = STATE_ERROR;
355+
if (err)
355356
break; /* timeout */
356-
}
357357

358358
ret = ocores_isr(-1, i2c);
359359
if (ret == IRQ_NONE)
@@ -364,13 +364,15 @@ static void ocores_process_polling(struct ocores_i2c *i2c)
364364
break;
365365
}
366366
}
367+
368+
return err;
367369
}
368370

369371
static int ocores_xfer_core(struct ocores_i2c *i2c,
370372
struct i2c_msg *msgs, int num,
371373
bool polling)
372374
{
373-
int ret;
375+
int ret = 0;
374376
u8 ctrl;
375377

376378
ctrl = oc_getreg(i2c, OCI2C_CONTROL);
@@ -388,15 +390,16 @@ static int ocores_xfer_core(struct ocores_i2c *i2c,
388390
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
389391

390392
if (polling) {
391-
ocores_process_polling(i2c);
393+
ret = ocores_process_polling(i2c);
392394
} else {
393-
ret = wait_event_timeout(i2c->wait,
394-
(i2c->state == STATE_ERROR) ||
395-
(i2c->state == STATE_DONE), HZ);
396-
if (ret == 0) {
397-
ocores_process_timeout(i2c);
398-
return -ETIMEDOUT;
399-
}
395+
if (wait_event_timeout(i2c->wait,
396+
(i2c->state == STATE_ERROR) ||
397+
(i2c->state == STATE_DONE), HZ) == 0)
398+
ret = -ETIMEDOUT;
399+
}
400+
if (ret) {
401+
ocores_process_timeout(i2c);
402+
return ret;
400403
}
401404

402405
return (i2c->state == STATE_DONE) ? num : -EIO;

0 commit comments

Comments
 (0)