• Sarah Sharp's avatar
    xhci: Fix TD size for isochronous URBs. · f18f8ed2
    Sarah Sharp authored
    To calculate the TD size for a particular TRB in an isoc TD, we need
    know the endpoint's max packet size.  Isochronous endpoints also encode
    the number of additional service opportunities in their wMaxPacketSize
    field.  The TD size calculation did not mask off those bits before using
    the field.  This resulted in incorrect TD size information for
    isochronous TRBs when an URB frame buffer crossed a 64KB boundary.
    
    For example:
     - an isoc endpoint has 2 additional service opportunites and
       a max packet size of 1020 bytes
     - a frame transfer buffer contains 3060 bytes
     - one frame buffer crosses a 64KB boundary, and must be split into
       one 1276 byte TRB, and one 1784 byte TRB.
    
    The TD size is is the number of packets that remain to be transferred
    for a TD after processing all the max packet sized packets in the
    current TRB and all previous TRBs.
    
    For this TD, the number of packets to be transferred is (3060 / 1020),
    or 3.  The first TRB contains 1276 bytes, which means it contains one
    full packet, and a 256 byte remainder.  After processing all the max
    packet-sized packets in the first TRB, the host will have 2 packets left
    to transfer.
    
    The old code would calculate the TD size for the first TRB as:
    
    total packet count = DIV_ROUND_UP (TD length / endpoint wMaxPacketSize)
    total packet count - (first TRB length / endpoint wMaxPacketSize)
    
    The math should have been:
    
    total packet count = DIV_ROUND_UP (3060 / 1020) = 3
    3 - (1276 / 1020) = 2
    
    Since the old code didn't mask off the additional service interval bits
    from the wMaxPacketSize field, the math ended up as
    
    total packet count = DIV_ROUND_UP (3060 / 5116) = 1
    1 - (1276 / 5116) = 1
    
    Fix this by masking off the number of additional service opportunities
    in the wMaxPacketSize field.
    
    This patch should be backported to stable kernels as old as 3.0, that
    contain the commit 4da6e6f2 "xhci 1.0:
    Update TD size field format."  It may not apply well to kernels older
    than 3.2 because of commit 29cc8897
    "USB: use usb_endpoint_maxp() instead of le16_to_cpu()".
    Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
    Cc: stable@vger.kernel.org
    f18f8ed2
xhci-ring.c 122 KB