• Ira W. Snyder's avatar
    kfifo: fix scatterlist usage · 399f1e30
    Ira W. Snyder authored
    The kfifo_dma family of functions use sg_mark_end() on the last element in
    their scatterlist.  This forces use of a fresh scatterlist for each DMA
    operation, which makes recycling a single scatterlist impossible.
    
    Change the behavior of the kfifo_dma functions to match the usage of the
    dma_map_sg function.  This means that users must respect the returned
    nents value.  The sample code is updated to reflect the change.
    
    This bug is trivial to cause: call kfifo_dma_in_prepare() such that it
    prepares a scatterlist with a single entry comprising the whole fifo.
    This is the case when you map the entirety of a newly created empty fifo.
    This causes the setup_sgl() function to mark the first scatterlist entry
    as the end of the chain, no matter what comes after it.
    
    Afterwards, add and remove some data from the fifo such that another call
    to kfifo_dma_in_prepare() will create two scatterlist entries.  It returns
    nents=2.  However, due to the previous sg_mark_end() call, sg_is_last()
    will now return true for the first scatterlist element.  This causes the
    sample code to print a single scatterlist element when it should print
    two.
    
    By removing the call to sg_mark_end(), we make the API as similar as
    possible to the DMA mapping API.  All users are required to respect the
    returned nents.
    Signed-off-by: default avatarIra W. Snyder <iws@ovro.caltech.edu>
    Cc: Stefani Seibold <stefani@seibold.net>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    399f1e30
kfifo.c 12.7 KB