• Russell King's avatar
    i2c: designware: fix rx fifo depth tracking · 4d6d5f1d
    Russell King authored
    When loading the TX fifo to receive bytes on the I2C bus, we incorrectly
    count the number of bytes:
    
    	rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
    
    	while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
    		if (rx_limit - dev->rx_outstanding <= 0)
    			break;
    		rx_limit--;
    		dev->rx_outstanding++;
    	}
    
    DW_IC_RXFLR indicates how many bytes are available to be read in the
    FIFO, dev->rx_fifo_depth is the FIFO size, and dev->rx_outstanding is
    the number of bytes that we've requested to be read so far, but which
    have not been read.
    
    Firstly, increasing dev->rx_outstanding and decreasing rx_limit and then
    comparing them results in each byte consuming "two" bytes in this
    tracking, so this is obviously wrong.
    
    Secondly, the number of bytes that _could_ be received into the FIFO at
    any time is the number of bytes we have so far requested but not yet
    read from the FIFO - in other words dev->rx_outstanding.
    
    So, in order to request enough bytes to fill the RX FIFO, we need to
    request dev->rx_fifo_depth - dev->rx_outstanding bytes.
    
    Modifying the code thusly results in us reaching the maximum number of
    bytes outstanding each time we queue more "receive" operations, provided
    the transfer allows that to happen.
    Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
    Reviewed-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
    Acked-by: default avatarJarkko Nikula <jarkko.nikula@linux.intel.com>
    Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
    4d6d5f1d
i2c-designware-core.c 26.5 KB