Skip to content

Commit 870a8cc

Browse files
tzuwen_changtzuwen_chang
tzuwen_chang
authored and
tzuwen_chang
committed
usb: dwc2: host: fix channel halt with unknown reason
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
1 parent cd99e30 commit 870a8cc

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

drivers/usb/dwc2/hcd_intr.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -1175,7 +1175,10 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg,
11751175

11761176
if (urb->actual_length + xfer_length > urb->length) {
11771177
dev_warn(hsotg->dev, "%s(): trimming xfer length\n", __func__);
1178-
xfer_length = urb->length - urb->actual_length;
1178+
if (urb->length & 0x3)
1179+
xfer_length = 0;
1180+
else
1181+
xfer_length = urb->length - urb->actual_length;
11791182
}
11801183

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

2042-
dwc2_writel(hcint, hsotg->regs + HCINT(chnum));
2043-
20442045
/*
20452046
* If we got an interrupt after someone called
20462047
* dwc2_hcd_endpoint_disable() we don't want to crash below
@@ -2053,6 +2054,8 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
20532054
chan->hcint = hcint;
20542055
hcint &= hcintmsk;
20552056

2057+
dwc2_writel(hcint, hsotg->regs + HCINT(chnum));
2058+
20562059
/*
20572060
* If the channel was halted due to a dequeue, the qtd list might
20582061
* be empty or at least the first entry will not be the active qtd.

0 commit comments

Comments
 (0)