Hi,
I have one question about SPI dma mode.
If the receiving buffer is NOT multiple of PAGE_SIZE (4KB), can sg_alloc_table get correct pages?
In the configure_dma() function, there is below description.
(driver/spi/spi-pl022.c)
/* Create sglists for the transfers */
pages = DIV_ROUND_UP(pl022->cur_transfer->len, PAGE_SIZE);
This decides the number of pages corresponding to the size of transferred data.
Then sg_alloc_table is called with pages shown above.
(driver/spi/spi-pl022.c)
ret = sg_alloc_table(&pl022->sgt_rx, pages, GfP_ATOMIC);
ret = sg_alloc_table(&pl022->sgt_tx, pages, GfP_ATOMIC);
But, in setup_dma_scatter() which is called after sg_alloc_table(),
the offset between the receiving buffer and PAGE boundary is considered.
(driver/spi/spi-pl022.c)
if (buffer) {
for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
/*
* If there are less bytes left than what fits
* in the current page (plus page alignment offset)
* we just feed in this, else we stuff in as much
* as we can.
*/
if (bytesleft < (PAGE_SIZE - offset_in_page(bufp)))
mapbytes = bytesleft;
else
mapbytes = PAGE_SIZE - offset_in_page(bufp);
sg_set_page(sg, virt_to_page(bufp),
mapbytes, offset_in_page(bufp));
As a result, there is the case that BUG_ON is executed because byteleft is NOT equal to zero.
for example,
PAGE_SIZE: 4096 byte
data size: 4096+2048 byte
offset: 4000 byte (This is calculated by offset_in_page() function.)
in this case,
pages= DIV_ROUND_UP(4096+2048, 4096)=2
mapped bytes at page 1: 4096-4000 = 96
mapped bytes at page 2: 4096
remaining byte: (4096+2048)-(96+4096) = 1952 !!
so byteleft is equal to 1952, BUG_ON is executed, and the hardware is restarted.
Is this true?
My environment is shown below.
-Hikey board(LeMaker)
-SPI0@f7106000
-android 6.0 published in AOSP (android-hikey-linaro-4.1)
(I referred to https://source.android.com/source/devices.html)