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 Change-Id: I93ef92007a3d1a91485c764565c8f532ce1ac1aa ------------[ 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: I41f5ea7b6361502019311ed1527137374e93059d Signed-off-by: William Wu <william.wu@rock-chips.com> Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
This commit is contained in:
@@ -1180,7 +1180,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;
|
||||
@@ -2065,8 +2068,6 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
|
||||
hcint, hcintmsk, hcint & hcintmsk);
|
||||
}
|
||||
|
||||
dwc2_writel(hsotg, hcint, HCINT(chnum));
|
||||
|
||||
/*
|
||||
* If we got an interrupt after someone called
|
||||
* dwc2_hcd_endpoint_disable() we don't want to crash below
|
||||
@@ -2079,6 +2080,8 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
|
||||
chan->hcint = hcint;
|
||||
hcint &= hcintmsk;
|
||||
|
||||
dwc2_writel(hsotg, hcint, 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.
|
||||
|
||||
Reference in New Issue
Block a user