History

i2c: sh_mobile: terminate DMA reads properly

DMA read requests could miss proper termination, so two more bytes would have been read via PIO overwriting the end of the buffer with wrong data. Make DMA stop handling more readable while we are here.

Wolfram Sang committed 11 years ago

Commit 32e22401 parent d5fd1201 file · +11 −1Browse files

Unified · Split

drivers/i2c/busses/i2c-sh_mobile.c+11−1
@@ -139,6 +139,7 @@ struct sh_mobile_i2c_data { · 138 unmodified lines
139139 int pos;
140140 int sr;
141141 bool send_stop;
142+ bool stop_after_dma;
142143
143144 struct resource *res;
144145 struct dma_chan *dma_tx;
@@ -407,7 +408,7 @@ static int sh_mobile_i2c_isr_tx(struct sh_mobile_i2c_data *pd) · 262 unmodified lines
407408
408409 if (pd->pos == pd->msg->len) {
409410 /* Send stop if we haven't yet (DMA case) */
410− if (pd->send_stop && (iic_rd(pd, ICCR) & ICCR_BBSY))
411+ if (pd->send_stop && pd->stop_after_dma)
411412 i2c_op(pd, OP_TX_STOP, 0);
412413 return 1;
413414 }
@@ -449,6 +450,13 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd) · 35 unmodified lines
449450 real_pos = pd->pos - 2;
450451
451452 if (pd->pos == pd->msg->len) {
453+ if (pd->stop_after_dma) {
454+ /* Simulate PIO end condition after DMA transfer */
455+ i2c_op(pd, OP_RX_STOP, 0);
456+ pd->pos++;
457+ break;
458+ }
459+
452460 if (real_pos < 0) {
453461 i2c_op(pd, OP_RX_STOP, 0);
454462 break;
@@ -536,6 +544,7 @@ static void sh_mobile_i2c_dma_callback(void *data) · 81 unmodified lines
536544
537545 sh_mobile_i2c_dma_unmap(pd);
538546 pd->pos = pd->msg->len;
547+ pd->stop_after_dma = true;
539548
540549 iic_set_clr(pd, ICIC, 0, ICIC_TDMAE | ICIC_RDMAE);
541550 }
@@ -726,6 +735,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, · 184 unmodified lines
726735 bool do_start = pd->send_stop || !i;
727736 msg = &msgs[i];
728737 pd->send_stop = i == num - 1 || msg->flags & I2C_M_STOP;
738+ pd->stop_after_dma = false;
729739
730740 err = start_ch(pd, msg, do_start);
731741 if (err)