diff options
Diffstat (limited to 'drivers/staging/dwc2/hcd_intr.c')
-rw-r--r-- | drivers/staging/dwc2/hcd_intr.c | 129 |
1 files changed, 61 insertions, 68 deletions
diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c index e75dccb3b80b..e143f69939f5 100644 --- a/drivers/staging/dwc2/hcd_intr.c +++ b/drivers/staging/dwc2/hcd_intr.c @@ -89,15 +89,20 @@ static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg, { struct urb *usb_urb; - if (!chan->qh || !qtd->urb) + if (!chan->qh) + return; + + if (chan->qh->dev_speed == USB_SPEED_HIGH) + return; + + if (!qtd->urb) return; usb_urb = qtd->urb->priv; - if (!usb_urb || !usb_urb->dev) + if (!usb_urb || !usb_urb->dev || !usb_urb->dev->tt) return; - if (chan->qh->dev_speed != USB_SPEED_HIGH && - qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) { + if (qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) { chan->qh->tt_buffer_dirty = 1; if (usb_hub_clear_tt_buffer(usb_urb)) /* Clear failed; let's hope things work anyway */ @@ -160,19 +165,16 @@ static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, "--RxFIFO Level Interrupt--\n"); grxsts = readl(hsotg->regs + GRXSTSP); - chnum = grxsts >> GRXSTS_HCHNUM_SHIFT & - GRXSTS_HCHNUM_MASK >> GRXSTS_HCHNUM_SHIFT; + chnum = (grxsts & GRXSTS_HCHNUM_MASK) >> GRXSTS_HCHNUM_SHIFT; chan = hsotg->hc_ptr_array[chnum]; if (!chan) { dev_err(hsotg->dev, "Unable to get corresponding channel\n"); return; } - bcnt = grxsts >> GRXSTS_BYTECNT_SHIFT & - GRXSTS_BYTECNT_MASK >> GRXSTS_BYTECNT_SHIFT; - dpid = grxsts >> GRXSTS_DPID_SHIFT & - GRXSTS_DPID_MASK >> GRXSTS_DPID_SHIFT; - pktsts = grxsts & GRXSTS_PKTSTS_MASK; + bcnt = (grxsts & GRXSTS_BYTECNT_MASK) >> GRXSTS_BYTECNT_SHIFT; + dpid = (grxsts & GRXSTS_DPID_MASK) >> GRXSTS_DPID_SHIFT; + pktsts = (grxsts & GRXSTS_PKTSTS_MASK) >> GRXSTS_PKTSTS_SHIFT; /* Packet Status */ if (dbg_perio()) { @@ -180,9 +182,7 @@ static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, " Count = %d\n", bcnt); dev_vdbg(hsotg->dev, " DPID = %d, chan.dpid = %d\n", dpid, chan->data_pid_start); - dev_vdbg(hsotg->dev, " PStatus = %d\n", - pktsts >> GRXSTS_PKTSTS_SHIFT & - GRXSTS_PKTSTS_MASK >> GRXSTS_PKTSTS_SHIFT); + dev_vdbg(hsotg->dev, " PStatus = %d\n", pktsts); } switch (pktsts) { @@ -261,7 +261,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, } usbcfg = readl(hsotg->regs + GUSBCFG); - prtspd = hprt0 & HPRT0_SPD_MASK; + prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; if (prtspd == HPRT0_SPD_LOW_SPEED || prtspd == HPRT0_SPD_FULL_SPEED) { /* Low power */ @@ -273,7 +273,8 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, } hcfg = readl(hsotg->regs + HCFG); - fslspclksel = hcfg & HCFG_FSLSPCLKSEL_MASK; + fslspclksel = (hcfg & HCFG_FSLSPCLKSEL_MASK) >> + HCFG_FSLSPCLKSEL_SHIFT; if (prtspd == HPRT0_SPD_LOW_SPEED && params->host_ls_low_power_phy_clk == @@ -282,8 +283,9 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, dev_vdbg(hsotg->dev, "FS_PHY programming HCFG to 6 MHz\n"); if (fslspclksel != HCFG_FSLSPCLKSEL_6_MHZ) { + fslspclksel = HCFG_FSLSPCLKSEL_6_MHZ; hcfg &= ~HCFG_FSLSPCLKSEL_MASK; - hcfg |= HCFG_FSLSPCLKSEL_6_MHZ; + hcfg |= fslspclksel << HCFG_FSLSPCLKSEL_SHIFT; writel(hcfg, hsotg->regs + HCFG); do_reset = 1; } @@ -292,8 +294,9 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, dev_vdbg(hsotg->dev, "FS_PHY programming HCFG to 48 MHz\n"); if (fslspclksel != HCFG_FSLSPCLKSEL_48_MHZ) { + fslspclksel = HCFG_FSLSPCLKSEL_48_MHZ; hcfg &= ~HCFG_FSLSPCLKSEL_MASK; - hcfg |= HCFG_FSLSPCLKSEL_48_MHZ; + hcfg |= fslspclksel << HCFG_FSLSPCLKSEL_SHIFT; writel(hcfg, hsotg->regs + HCFG); do_reset = 1; } @@ -406,8 +409,8 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg, if (halt_status == DWC2_HC_XFER_COMPLETE) { if (chan->ep_is_in) { - count = hctsiz >> TSIZ_XFERSIZE_SHIFT & - TSIZ_XFERSIZE_MASK >> TSIZ_XFERSIZE_SHIFT; + count = (hctsiz & TSIZ_XFERSIZE_MASK) >> + TSIZ_XFERSIZE_SHIFT; length = chan->xfer_len - count; if (short_read != NULL) *short_read = (count != 0); @@ -426,8 +429,7 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg, * hctsiz.xfersize field because that reflects the number of * bytes transferred via the AHB, not the USB). */ - count = hctsiz >> TSIZ_PKTCNT_SHIFT & - TSIZ_PKTCNT_MASK >> TSIZ_PKTCNT_SHIFT; + count = (hctsiz & TSIZ_PKTCNT_MASK) >> TSIZ_PKTCNT_SHIFT; length = (chan->start_pkt_count - count) * chan->max_packet; } @@ -462,7 +464,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && xfer_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, @@ -490,8 +492,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, __func__, (chan->ep_is_in ? "IN" : "OUT"), chnum); dev_vdbg(hsotg->dev, " chan->xfer_len %d\n", chan->xfer_len); dev_vdbg(hsotg->dev, " hctsiz.xfersize %d\n", - hctsiz >> TSIZ_XFERSIZE_SHIFT & - TSIZ_XFERSIZE_MASK >> TSIZ_XFERSIZE_SHIFT); + (hctsiz & TSIZ_XFERSIZE_MASK) >> TSIZ_XFERSIZE_SHIFT); dev_vdbg(hsotg->dev, " urb->transfer_buffer_length %d\n", urb->length); dev_vdbg(hsotg->dev, " urb->actual_length %d\n", urb->actual_length); dev_vdbg(hsotg->dev, " short_read %d, xfer_done %d\n", short_read, @@ -510,7 +511,7 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd) { u32 hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); - u32 pid = hctsiz & TSIZ_SC_MC_PID_MASK; + u32 pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT; if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) { if (pid == TSIZ_SC_MC_PID_DATA0) @@ -557,8 +558,8 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && frame_desc->actual_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", - __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", + __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + frame_desc->offset + @@ -591,8 +592,8 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && frame_desc->actual_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", - __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", + __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + frame_desc->offset + @@ -623,7 +624,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( * urb->status is not used for isoc transfers. The individual * frame_desc statuses are used instead. */ - dwc2_host_complete(hsotg, urb->priv, urb, 0); + dwc2_host_complete(hsotg, qtd, 0); halt_status = DWC2_HC_XFER_URB_COMPLETE; } else { halt_status = DWC2_HC_XFER_COMPLETE; @@ -714,11 +715,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, " Complete URB with transaction error\n"); free_qtd = 1; - if (qtd->urb) { - qtd->urb->status = -EPROTO; - dwc2_host_complete(hsotg, qtd->urb->priv, - qtd->urb, -EPROTO); - } + dwc2_host_complete(hsotg, qtd, -EPROTO); } break; case DWC2_HC_XFER_URB_DEQUEUE: @@ -731,11 +728,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, case DWC2_HC_XFER_PERIODIC_INCOMPLETE: dev_vdbg(hsotg->dev, " Complete URB with I/O error\n"); free_qtd = 1; - if (qtd && qtd->urb) { - qtd->urb->status = -EIO; - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, - -EIO); - } + dwc2_host_complete(hsotg, qtd, -EIO); break; case DWC2_HC_XFER_NO_HALT_STATUS: default: @@ -938,7 +931,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, frame_desc->actual_length += len; if (chan->align_buf && len) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); dma_sync_single_for_cpu(hsotg->dev, qtd->urb->dma, qtd->urb->length, DMA_FROM_DEVICE); memcpy(qtd->urb->buf + frame_desc->offset + @@ -957,7 +950,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, } if (qtd->isoc_frame_index == qtd->urb->packet_count) { - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, 0); + dwc2_host_complete(hsotg, qtd, 0); dwc2_release_channel(hsotg, chan, qtd, DWC2_HC_XFER_URB_COMPLETE); } else { @@ -1040,7 +1033,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, " Control transfer complete\n"); if (urb->status == -EINPROGRESS) urb->status = 0; - dwc2_host_complete(hsotg, urb->priv, urb, urb->status); + dwc2_host_complete(hsotg, qtd, urb->status); halt_status = DWC2_HC_XFER_URB_COMPLETE; break; } @@ -1053,7 +1046,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, urb_xfer_done = dwc2_update_urb_state(hsotg, chan, chnum, urb, qtd); if (urb_xfer_done) { - dwc2_host_complete(hsotg, urb->priv, urb, urb->status); + dwc2_host_complete(hsotg, qtd, urb->status); halt_status = DWC2_HC_XFER_URB_COMPLETE; } else { halt_status = DWC2_HC_XFER_COMPLETE; @@ -1073,11 +1066,10 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, * interrupt */ if (urb_xfer_done) { - dwc2_host_complete(hsotg, urb->priv, urb, - urb->status); - halt_status = DWC2_HC_XFER_URB_COMPLETE; + dwc2_host_complete(hsotg, qtd, urb->status); + halt_status = DWC2_HC_XFER_URB_COMPLETE; } else { - halt_status = DWC2_HC_XFER_COMPLETE; + halt_status = DWC2_HC_XFER_COMPLETE; } dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd); @@ -1123,11 +1115,11 @@ static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg, goto handle_stall_halt; if (pipe_type == USB_ENDPOINT_XFER_CONTROL) - dwc2_host_complete(hsotg, urb->priv, urb, -EPIPE); + dwc2_host_complete(hsotg, qtd, -EPIPE); if (pipe_type == USB_ENDPOINT_XFER_BULK || pipe_type == USB_ENDPOINT_XFER_INT) { - dwc2_host_complete(hsotg, urb->priv, urb, -EPIPE); + dwc2_host_complete(hsotg, qtd, -EPIPE); /* * USB protocol requires resetting the data toggle for bulk * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT) @@ -1168,7 +1160,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && xfer_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, @@ -1185,8 +1177,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, " chan->start_pkt_count %d\n", chan->start_pkt_count); dev_vdbg(hsotg->dev, " hctsiz.pktcnt %d\n", - hctsiz >> TSIZ_PKTCNT_SHIFT & - TSIZ_PKTCNT_MASK >> TSIZ_PKTCNT_SHIFT); + (hctsiz & TSIZ_PKTCNT_MASK) >> TSIZ_PKTCNT_SHIFT); dev_vdbg(hsotg->dev, " chan->max_packet %d\n", chan->max_packet); dev_vdbg(hsotg->dev, " bytes_transferred %d\n", xfer_length); @@ -1372,10 +1363,10 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg, hsotg->core_params->dma_enable > 0) { qtd->complete_split = 0; qtd->isoc_split_offset = 0; + qtd->isoc_frame_index++; if (qtd->urb && - ++qtd->isoc_frame_index == qtd->urb->packet_count) { - dwc2_host_complete(hsotg, qtd->urb->priv, - qtd->urb, 0); + qtd->isoc_frame_index == qtd->urb->packet_count) { + dwc2_host_complete(hsotg, qtd, 0); dwc2_release_channel(hsotg, chan, qtd, DWC2_HC_XFER_URB_COMPLETE); } else { @@ -1445,16 +1436,16 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Babble Error--\n", chnum); + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + if (hsotg->core_params->dma_desc_enable > 0) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, DWC2_HC_XFER_BABBLE_ERR); - goto handle_babble_done; + goto disable_int; } if (chan->ep_type != USB_ENDPOINT_XFER_ISOC) { - if (qtd->urb) - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, - -EOVERFLOW); + dwc2_host_complete(hsotg, qtd, -EOVERFLOW); dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_BABBLE_ERR); } else { enum dwc2_halt_status halt_status; @@ -1464,8 +1455,7 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg, dwc2_halt_channel(hsotg, chan, qtd, halt_status); } -handle_babble_done: - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); +disable_int: disable_hc_int(hsotg, chnum, HCINTMSK_BBLERR); } @@ -1490,6 +1480,8 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, if (!urb) goto handle_ahberr_halt; + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + hcchar = readl(hsotg->regs + HCCHAR(chnum)); hcsplt = readl(hsotg->regs + HCSPLT(chnum)); hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); @@ -1557,7 +1549,7 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, goto handle_ahberr_done; } - dwc2_host_complete(hsotg, urb->priv, urb, -EIO); + dwc2_host_complete(hsotg, qtd, -EIO); handle_ahberr_halt: /* @@ -1567,7 +1559,6 @@ handle_ahberr_halt: dwc2_hc_halt(hsotg, chan, DWC2_HC_XFER_AHB_ERR); handle_ahberr_done: - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); disable_hc_int(hsotg, chnum, HCINTMSK_AHBERR); } @@ -1582,6 +1573,8 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Transaction Error--\n", chnum); + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + if (hsotg->core_params->dma_desc_enable > 0) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, DWC2_HC_XFER_XACT_ERR); @@ -1625,7 +1618,6 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, } handle_xacterr_done: - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); disable_hc_int(hsotg, chnum, HCINTMSK_XACTERR); } @@ -1643,6 +1635,8 @@ static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Frame Overrun--\n", chnum); + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) { case USB_ENDPOINT_XFER_CONTROL: case USB_ENDPOINT_XFER_BULK: @@ -1657,7 +1651,6 @@ static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg, break; } - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); disable_hc_int(hsotg, chnum, HCINTMSK_FRMOVRUN); } @@ -1766,7 +1759,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, * For core with OUT NAK enhancement, the flow for high-speed * CONTROL/BULK OUT is handled a little differently */ - if (hsotg->snpsid >= DWC2_CORE_REV_2_71a) { + if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_71a) { if (chan->speed == USB_SPEED_HIGH && !chan->ep_is_in && (chan->ep_type == USB_ENDPOINT_XFER_CONTROL || chan->ep_type == USB_ENDPOINT_XFER_BULK)) { |