mmc: msm_sdcc: Fix scatterlist processing in PIO mode
sg_miter_next() does not place byte alignment restrictions on
sgl lengths. However, SDCC FIFO must be accessed in multiples
of 4 bytes, requiring rounding which can cause data corruption.
For example, an sgl of length 481 is decribed below:
struct scatterlist sgl;
sgl.page_link = 0xXXXX_XXXX;
sgl.length = 481;
sgl.offset = 3821;
First call to sg_miter_next():
Sgl length returned = (PAGE_SIZE - 3821) = 275 bytes
Driver rounds this length to multiple of 4 = 276 bytes
Next call to sg_miter_next():
Sgl length returned = (481 - 275) = 206 bytes
Driver rounds this length to 208 bytes
On a write, the extra byte written to the FIFO during the first
276 byte chunk is assumed valid. The next call writes 208 bytes,
but the last 3 bytes (276 + 208 - 481) including 1 valid byte,
are ignored, as the controller uses the MCI_DATA_LENGTH register
to figure out that it only needs to write a total of 481 bytes.
To fix the data corruption in cases as above, a 4 byte bounce
buffer is used realign buffer access to the FIFO, such that 4 byte
multiples are written until the last buffer chunk.
Note that in a simple case where all 481 bytes lie within a page,
the driver rounds the length to 484, but the MCI_DATA_LENGTH
register enusres only 481 bytes are actually written.
Change-Id: I164bae2df4857017b35857e465d753b9dc9edf6a
Signed-off-by:
Oluwafemi Adeyemi <aadeyemi@codeaurora.org>
Loading
Please sign in to comment