Le 25/11/2016 à 10:46, Paul Burton a écrit : > The DMA API should not be used to map memory which isn't cache-line > aligned. To quote Documentation/DMA-API.txt: > > Warnings: Memory coherency operates at a granularity called the cache > line width. In order for memory mapped by this API to operate > correctly, the mapped region must begin exactly on a cache line > boundary and end exactly on one (to prevent two separately mapped > regions from sharing a single cache line). Since the cache line size > may not be known at compile time, the API will not enforce this > requirement. Therefore, it is recommended that driver writers who > don't take special care to determine the cache line size at run time > only map virtual regions that begin and end on page boundaries (which > are guaranteed also to be cache line boundaries). > > The MIPS L2 cache code has until now attempted to work around unaligned > cache maintenance by writing back the first & last lines of a region to > be invalidated. This is problematic however, because if we access either > line after our initial invalidate call & before the DMA completes we'll > cause the cache line to become valid & thus see stale data unless we go > on to perform a second invalidate on systems where > cpu_needs_post_dma_flush() == 1. In such systems we still have problems > because if we wrote to either cache line causing it to become dirty then > the writeback of it would clobber the data that was written to memory by > the device performing DMA. > > Fix this by removing the bogus writebacks in the L2 cache invalidate > code when the region is aligned. If cache invalidation functions are > invoked on a region which is not cacheline-aligned then produce a > warning and proceed to perform the writebacks despite them being > technically incorrect, in an attempt to both allow broken drivers to > continue to "work" whilst being annoying enough to cause people to fix > them. Ideally at some point we'd remove the writebacks entirely, but at > least leaving them for now will let broken drivers stand a chance of > continuing to work as we find & fix anything that begins emitting > warnings over the next cycle or two. > > In an ideal world we would also check that the size of the memory region > we're performing cache maintenance upon is aligned, however this > generates a great deal of noise from drivers which kmalloc a region of > memory & then map some subset of it using the dma_map_* APIs. These > callers will work fine due to kmalloc providing suitably aligned memory, > but because they don't know that kmalloc may have padded out the region > they requested they don't tell the DMA API the actual size of the region > & we instead see the size that they requested. This leads to all sorts > of noise from many many drivers & subsystems so settle for only checking > the base address of the region. > > A further limitation is that we'd ideally check the alignment for > writeback & invalidate operations, since DMA buffers that we write to & > devices read from ought to be cache-line aligned too in order to satisfy > the documented requirements of the DMA API. However there is a fair > amount of code which violates this alignment requirement, most notably > core networking code which seems to routinely map unaligned regions via > skb_frag_dma_map(). Since this would be rather invasive to change and > the writebacks aren't harmful/lossy, we ignore the writeback case for > now too. > > Although this fixes a bug introduced way back in v2.6.29 by commit > a8ca8b64e3fd ("MIPS: Avoid destructive invalidation on partial > cachelines."), which has since been undone, and commit 96983ffefce4 > ("MIPS: MIPSxx SC: Avoid destructive invalidation on partial L2 > cachelines.") which hasn't, I have not marked this for stable since it > can trigger large numbers of warnings in systems which have not fixed up > their drivers to correctly align buffers, and presumably the bulk of > systems in the wild haven't hit this problem. > > Signed-off-by: Paul Burton <paul.burton@xxxxxxxxxx> > Cc: Ralf Baechle <ralf@xxxxxxxxxxxxxx> > Cc: linux-mips@xxxxxxxxxxxxxx Acked-by: Florian Fainelli <f.fainelli@xxxxxxxxx> -- Florian