In order to make this function more clear a new function created that controls channels halt on no DMA mode. Signed-off-by: Georgios Tsotsos <tsotsos@xxxxxxxxx> --- drivers/staging/octeon-usb/octeon-hcd.c | 81 +++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 8a7bdf1a9fe6..3f44ac260eff 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -2593,7 +2593,51 @@ static void cvmx_usb_transfer_isoc(struct octeon_hcd *usb, cvmx_usb_complete(usb, pipe, transaction, CVMX_USB_STATUS_OK); } } +/** + * Handles channels halt in non DMA mode + * @hcchar_chena: + * @hcint_xfercompl: + * @usb: USB device + * @channel: Channel to poll + * + * In non DMA mode the channels don't halt themselves. We need + * to manually disable channels that are left running + * + * Returns: -1 on halt + */ +static int cvmx_usb_dma_halt(u32 hcchar_chena, u32 hcint_xfercompl, + struct octeon_hcd *usb, int channel) +{ + struct usb_hcd *hcd = octeon_to_hcd(usb); + struct device *dev = hcd->self.controller; + if (hcchar_chena) { + union cvmx_usbcx_hcintmskx hcintmsk; + union cvmx_usbcx_hccharx usbc_hcchar; + /* Disable all interrupts except CHHLTD */ + hcintmsk.u32 = 0; + hcintmsk.s.chhltdmsk = 1; + cvmx_usb_write_csr32(usb, + CVMX_USBCX_HCINTMSKX(channel, usb->index), + hcintmsk.u32); + usbc_hcchar.s.chdis = 1; + cvmx_usb_write_csr32(usb, + CVMX_USBCX_HCCHARX(channel, usb->index), + usbc_hcchar.u32); + return -1; + } else if (hcint_xfercompl) { + /* + * Successful IN/OUT with transfer complete. + * Channel halt isn't needed. + */ + } else { + dev_err(dev, "USB%d: Channel %d interrupt without halt\n", + usb->index, channel); + return -1; + } + + return 0; +} /** * Poll a channel for status * @@ -2604,8 +2648,6 @@ static void cvmx_usb_transfer_isoc(struct octeon_hcd *usb, */ static int cvmx_usb_poll_channel(struct octeon_hcd *usb, int channel) { - struct usb_hcd *hcd = octeon_to_hcd(usb); - struct device *dev = hcd->self.controller; union cvmx_usbcx_hcintx usbc_hcint; union cvmx_usbcx_hctsizx usbc_hctsiz; union cvmx_usbcx_hccharx usbc_hcchar; @@ -2637,34 +2679,17 @@ static int cvmx_usb_poll_channel(struct octeon_hcd *usb, int channel) return 0; } - /* - * In non DMA mode the channels don't halt themselves. We need - * to manually disable channels that are left running - */ + /* In case of non DMA mode handle halt */ if (!usbc_hcint.s.chhltd) { - if (usbc_hcchar.s.chena) { - union cvmx_usbcx_hcintmskx hcintmsk; - /* Disable all interrupts except CHHLTD */ - hcintmsk.u32 = 0; - hcintmsk.s.chhltdmsk = 1; - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCINTMSKX(channel, usb->index), - hcintmsk.u32); - usbc_hcchar.s.chdis = 1; - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCCHARX(channel, usb->index), - usbc_hcchar.u32); - return 0; - } else if (usbc_hcint.s.xfercompl) { - /* - * Successful IN/OUT with transfer complete. - * Channel halt isn't needed. - */ - } else { - dev_err(dev, "USB%d: Channel %d interrupt without halt\n", - usb->index, channel); + int dma_halt_status = 0; + u32 xfercompl = usbc_hcint.s.xfercompl; + + dma_halt_status = cvmx_usb_dma_halt(usbc_hcchar.s.chena, + xfercompl, + usb, channel); + + if (dma_halt_status < 0) return 0; - } } } else { /* -- 2.16.4 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel