Skip to content
  • Neil Horman's avatar
    3c59x: mask LAST_FRAG bit from length field in ring · a6522c08
    Neil Horman authored
    Recently, I fixed a bug in 3c59x:
    
    commit 6e144419
    
    
    Author: Neil Horman <nhorman@tuxdriver.com>
    Date:   Wed Jan 13 12:43:54 2016 -0500
    
        3c59x: fix another page map/single unmap imbalance
    
    Which correctly rebalanced dma mapping and unmapping types.  Unfortunately it
    introduced a new bug which causes oopses on older systems.
    
    When mapping dma regions, the last entry for a packet in the 3c59x tx ring
    encodes a LAST_FRAG bit, which is encoded as the high order bit of the buffers
    length field.  When it is unmapped the LAST_FRAG bit is cleared prior to being
    passed to the unmap function.  Unfortunately the commit above fails to do that
    masking.  It was missed in testing because the system on which I tested it had
    an intel iommu, the driver for which ignores the size field, using only the DMA
    address as the token to identify the mapping to be released.  However, on older
    systems that rely on swiotlb (or other dma drivers that key off that length
    field), not masking off that LAST_FRAG high order bit results in parsing a huge
    size to be release, leading to all sorts of odd corruptions and the like.
    
    Fix is easy, just mask the length with 0xFFF.  It should really be
    &(LAST_FRAG-1), but 0xFFF is the style of the file, and I'd like to make this
    fix minimal and correct before making it prettier.
    
    Appies to the net tree cleanly.  All testing on both iommu and swiommu based
    systems produce good results
    
    Signed-off-by: default avatarNeil Horman <nhorman@tuxdriver.com>
    CC: Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
    CC: "David S. Miller" <davem@davemloft.net>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    a6522c08