Skip to content

Commit

Permalink
usb: dwc2: host: fix channel halt with unknown reason
Browse files Browse the repository at this point in the history
Channel halt with unknown reason happens in the following case:
DWC2 + USB 2.0 HUB + HS Device + FS Device

The HS Device is an optical fingerprint:
usb 1-1.4: USB disconnect, device number 5
usb 1-1.4: new high-speed USB device number 6 using dwc2
usb 1-1.4: New USB device found, idVendor=28ed, idProduct=7000
usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1.4: Product: Aratek Capture Device
usb 1-1.4: Manufacturer: Aratek

The FS Device is an ID card identification module:
usb 1-1.3: new full-speed USB device number 9 using dwc2
usb 1-1.3: New USB device found, idVendor=0400, idProduct=c35a
usb 1-1.3: New USB device strings: Mfr=0, Product=0, SerialNumber=0

When the issuse occurs, it always dump the error log:

dwc2 ff540000.usb: dwc2_hc_chhltd_intr_dma: Channel 13 - ChHltd set, but reason is unknown
dwc2 ff540000.usb: hcint 0x00000002, intsts 0x04000021
dwc2 ff540000.usb: dwc2_update_urb_state_abn(): trimming xfer length
------------[ cut here ]------------
WARNING: CPU: 0 PID: 0 at drivers/usb/dwc2/hcd.c:2796 dwc2_assign_and_init_hc+0x554/0x8e4()
Modules linked in: bcmdhd
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.4.143 #3
Hardware name: Generic DT based system
[<c010f854>] (unwind_backtrace) from [<c010bb84>] (show_stack+0x10/0x14)
[<c010bb84>] (show_stack) from [<c03ed8b4>] (dump_stack+0x7c/0x9c)
[<c03ed8b4>] (dump_stack) from [<c012737c>] (warn_slowpath_common+0x88/0xb4)
[<c012737c>] (warn_slowpath_common) from [<c0127488>] (warn_slowpath_null+0x18/0x20)
[<c0127488>] (warn_slowpath_null) from [<c05c8314>] (dwc2_assign_and_init_hc+0x554/0x8e4)
[<c05c8314>] (dwc2_assign_and_init_hc) from [<c05c8788>] (dwc2_hcd_select_transactions+0xe4/0x178)
[<c05c8788>] (dwc2_hcd_select_transactions) from [<c05ca0e4>] (dwc2_release_channel+0x1b8/0x1cc)
[<c05ca0e4>] (dwc2_release_channel) from [<c05cbaa8>] (dwc2_hc_n_intr+0x4a0/0x728)
[<c05cbaa8>] (dwc2_hc_n_intr) from [<c05cc1dc>] (dwc2_handle_hcd_intr+0x4ac/0x4d8)
[<c05cc1dc>] (dwc2_handle_hcd_intr) from [<c05b247c>] (usb_hcd_irq+0x24/0x38)
[<c05b247c>] (usb_hcd_irq) from [<c017dea4>] (handle_irq_event_percpu+0xa8/0x28c)
[<c017dea4>] (handle_irq_event_percpu) from [<c017e0c0>] (handle_irq_event+0x38/0x5c)
[<c017e0c0>] (handle_irq_event) from [<c0181560>] (handle_fasteoi_irq+0xa8/0x124)
[<c0181560>] (handle_fasteoi_irq) from [<c017d5cc>] (generic_handle_irq+0x18/0x28)
[<c017d5cc>] (generic_handle_irq) from [<c017d890>] (__handle_domain_irq+0x88/0xb0)
[<c017d890>] (__handle_domain_irq) from [<c010142c>] (gic_handle_irq+0x44/0x74)
[<c010142c>] (gic_handle_irq) from [<c010c554>] (__irq_svc+0x54/0x90)

This patch only clears the unmask interrupts to avoid trigger
unknown Channel Halted interrupt. However, if the Channel Halted
interrupt happens unexpected, we need to check if the urb->length
is 4-byte alignment in dwc2_update_urb_state_abn(), this can help
to avoid the above warning.

Change-Id: I51f829458be032fbc75f745ddfe0c465bf634b3e
  • Loading branch information
tzuwen_chang authored and tzuwen_chang committed Aug 13, 2020
1 parent cd99e30 commit 870a8cc
Showing 1 changed file with 6 additions and 3 deletions.
9 changes: 6 additions & 3 deletions drivers/usb/dwc2/hcd_intr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,10 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg,

if (urb->actual_length + xfer_length > urb->length) {
dev_warn(hsotg->dev, "%s(): trimming xfer length\n", __func__);
xfer_length = urb->length - urb->actual_length;
if (urb->length & 0x3)
xfer_length = 0;
else
xfer_length = urb->length - urb->actual_length;
}

urb->actual_length += xfer_length;
Expand Down Expand Up @@ -2039,8 +2042,6 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
hcint, hcintmsk, hcint & hcintmsk);
}

dwc2_writel(hcint, hsotg->regs + HCINT(chnum));

/*
* If we got an interrupt after someone called
* dwc2_hcd_endpoint_disable() we don't want to crash below
Expand All @@ -2053,6 +2054,8 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
chan->hcint = hcint;
hcint &= hcintmsk;

dwc2_writel(hcint, hsotg->regs + HCINT(chnum));

/*
* If the channel was halted due to a dequeue, the qtd list might
* be empty or at least the first entry will not be the active qtd.
Expand Down

0 comments on commit 870a8cc

Please sign in to comment.