[PATCH 6/7] ARM: dma-mapping: fix for speculative accesses

Russell King - ARM Linux linux at arm.linux.org.uk
Mon Nov 23 07:08:16 EST 2009


On Mon, Nov 23, 2009 at 12:03:02PM +0000, Catalin Marinas wrote:
> Does this mean that the direction information is lost after this point?
> My only issue with this is that in the FROM_DEVICE case we use a clean
> operation before the transfer even though an invalidate would be enough
> and probably faster.

Yes we do.  In the long run, I'd like to change dmac_*_range to be
dmac_map_range and dmac_unmap_range, taking the direction argument.
The problem at the moment is the highmem page stuff gets rather messy
and less efficient to go that far.

> > --- a/arch/arm/mm/dma-mapping.c
> > +++ b/arch/arm/mm/dma-mapping.c
> > @@ -539,58 +539,40 @@ core_initcall(consistent_init);
> >   * platforms with CONFIG_DMABOUNCE.
> >   * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
> >   */
> > -void dma_cache_maint(const void *start, size_t size, int direction)
> > +void __dma_cache_maint(const void *start, size_t size, int map)
> >  {
> >         void (*inner_op)(const void *, const void *);
> >         void (*outer_op)(unsigned long, unsigned long);
> > 
> >         BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(start + size - 1));
> > 
> > -       switch (direction) {
> > -       case DMA_FROM_DEVICE:           /* invalidate only */
> > -               inner_op = dmac_inv_range;
> > -               outer_op = outer_inv_range;
> > -               break;
> > -       case DMA_TO_DEVICE:             /* writeback only */
> > +       if (map) {              /* writeback only */
> >                 inner_op = dmac_clean_range;
> >                 outer_op = outer_clean_range;
> > -               break;
> > -       case DMA_BIDIRECTIONAL:         /* writeback and invalidate */
> > -               inner_op = dmac_flush_range;
> > -               outer_op = outer_flush_range;
> > -               break;
> > -       default:
> > -               BUG();
> > +       } else {                /* invalidate only */
> > +               inner_op = dmac_inv_range;
> > +               outer_op = outer_inv_range;
> >         }
> > 
> >         inner_op(start, start + size);
> >         outer_op(__pa(start), __pa(start) + size);
> >  }
> 
> Since we have real issues with speculative accesses, for the !map case,
> we need to invalidate the outer cache before the inner cache. I think it
> just makes sense to avoid the inner_op and outer_op pointers.

Yes, good catch.



More information about the linux-arm-kernel mailing list