Patch "usb: dwc2: Abort transaction after errors with unknown reason" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    usb: dwc2: Abort transaction after errors with unknown reason

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     usb-dwc2-abort-transaction-after-errors-with-unknown.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 6a6811f8ab6e2f2895f37432c51fc7c60797c333
Author: Guenter Roeck <linux@xxxxxxxxxxxx>
Date:   Wed Jan 13 12:20:50 2021 +0100

    usb: dwc2: Abort transaction after errors with unknown reason
    
    [ Upstream commit f74b68c61cbc4b2245022fcce038509333d63f6f ]
    
    In some situations, the following error messages are reported.
    
    dwc2 ff540000.usb: dwc2_hc_chhltd_intr_dma: Channel 1 - ChHltd set, but reason is unknown
    dwc2 ff540000.usb: hcint 0x00000002, intsts 0x04000021
    
    This is sometimes followed by:
    
    dwc2 ff540000.usb: dwc2_update_urb_state_abn(): trimming xfer length
    
    and then:
    
    WARNING: CPU: 0 PID: 0 at kernel/v4.19/drivers/usb/dwc2/hcd.c:2913
                            dwc2_assign_and_init_hc+0x98c/0x990
    
    The warning suggests that an odd buffer address is to be used for DMA.
    
    After an error is observed, the receive buffer may be full
    (urb->actual_length >= urb->length). However, the urb is still left in
    the queue unless three errors were observed in a row. When it is queued
    again, the dwc2 hcd code translates this into a 1-block transfer.
    If urb->actual_length (ie the total expected receive length) is not
    DMA-aligned, the buffer pointer programmed into the chip will be
    unaligned. This results in the observed warning.
    
    To solve the problem, abort input transactions after an error with
    unknown cause if the entire packet was already received. This may be
    a bit drastic, but we don't really know why the transfer was aborted
    even though the entire packet was received. Aborting the transfer in
    this situation is less risky than accepting a potentially corrupted
    packet.
    
    With this patch in place, the 'ChHltd set' and 'trimming xfer length'
    messages are still observed, but there are no more transfer attempts
    with odd buffer addresses.
    
    Fixes: 151d0cbdbe860 ("usb: dwc2: make the scheduler handle excessive NAKs better")
    Cc: Boris ARZUR <boris@xxxxxxxxx>
    Cc: Douglas Anderson <dianders@xxxxxxxxxxxx>
    Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@xxxxxxx>
    Reviewed-by: Douglas Anderson <dianders@xxxxxxxxxxxx>
    Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx>
    Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@xxxxxxx>
    Link: https://lore.kernel.org/r/20210113112052.17063-3-nsaenzjulienne@xxxxxxx
    Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index a052d39b4375e..12819e019e13c 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -1977,6 +1977,18 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
 		qtd->error_count++;
 		dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb,
 					  qtd, DWC2_HC_XFER_XACT_ERR);
+		/*
+		 * We can get here after a completed transaction
+		 * (urb->actual_length >= urb->length) which was not reported
+		 * as completed. If that is the case, and we do not abort
+		 * the transfer, a transfer of size 0 will be enqueued
+		 * subsequently. If urb->actual_length is not DMA-aligned,
+		 * the buffer will then point to an unaligned address, and
+		 * the resulting behavior is undefined. Bail out in that
+		 * situation.
+		 */
+		if (qtd->urb->actual_length >= qtd->urb->length)
+			qtd->error_count = 3;
 		dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
 		dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_XACT_ERR);
 	}



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux