Skip to content

Commit fdc77e0

Browse files
groeckgregkh
authored andcommitted
usb: dwc2: Abort transaction after errors with unknown reason
[ Upstream commit f74b68c ] 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: 151d0cb ("usb: dwc2: make the scheduler handle excessive NAKs better") Cc: Boris ARZUR <boris@konbu.org> Cc: Douglas Anderson <dianders@chromium.org> Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> Link: https://lore.kernel.org/r/20210113112052.17063-3-nsaenzjulienne@suse.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 8eb3e68 commit fdc77e0

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

drivers/usb/dwc2/hcd_intr.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,18 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
19771977
qtd->error_count++;
19781978
dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb,
19791979
qtd, DWC2_HC_XFER_XACT_ERR);
1980+
/*
1981+
* We can get here after a completed transaction
1982+
* (urb->actual_length >= urb->length) which was not reported
1983+
* as completed. If that is the case, and we do not abort
1984+
* the transfer, a transfer of size 0 will be enqueued
1985+
* subsequently. If urb->actual_length is not DMA-aligned,
1986+
* the buffer will then point to an unaligned address, and
1987+
* the resulting behavior is undefined. Bail out in that
1988+
* situation.
1989+
*/
1990+
if (qtd->urb->actual_length >= qtd->urb->length)
1991+
qtd->error_count = 3;
19801992
dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
19811993
dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_XACT_ERR);
19821994
}

0 commit comments

Comments
 (0)