From owner-svn-src-head@FreeBSD.ORG Wed Sep 12 07:34:10 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id EE56D1065673; Wed, 12 Sep 2012 07:34:09 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D96B28FC14; Wed, 12 Sep 2012 07:34:09 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8C7Y9df020441; Wed, 12 Sep 2012 07:34:09 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8C7Y9bY020438; Wed, 12 Sep 2012 07:34:09 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201209120734.q8C7Y9bY020438@svn.freebsd.org> From: Hans Petter Selasky Date: Wed, 12 Sep 2012 07:34:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240381 - head/sys/dev/usb/controller X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 12 Sep 2012 07:34:10 -0000 Author: hselasky Date: Wed Sep 12 07:34:09 2012 New Revision: 240381 URL: http://svn.freebsd.org/changeset/base/240381 Log: Reduce DWC OTG polling rate by using the SOF interrupt. Modified: head/sys/dev/usb/controller/dwc_otg.c head/sys/dev/usb/controller/dwc_otg.h Modified: head/sys/dev/usb/controller/dwc_otg.c ============================================================================== --- head/sys/dev/usb/controller/dwc_otg.c Wed Sep 12 04:29:11 2012 (r240380) +++ head/sys/dev/usb/controller/dwc_otg.c Wed Sep 12 07:34:09 2012 (r240381) @@ -160,6 +160,23 @@ dwc_otg_get_hw_ep_profile(struct usb_dev *ppf = NULL; } +static void +dwc_otg_request_sof(struct dwc_otg_softc *sc) +{ + sc->sc_sof_refs++; + sc->sc_irq_mask |= GINTMSK_SOFMSK; + DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask); +} + +static void +dwc_otg_release_sof(struct dwc_otg_softc *sc) +{ + if (--(sc->sc_sof_refs) == 0) { + sc->sc_irq_mask &= ~GINTMSK_SOFMSK; + DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask); + } +} + static int dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode) { @@ -523,6 +540,9 @@ dwc_otg_host_channel_alloc(struct dwc_ot /* set active EP */ sc->sc_active_rx_ep |= (1 << x); + /* request SOF's */ + dwc_otg_request_sof(sc); + return (0); /* allocated */ } } @@ -576,6 +596,10 @@ dwc_otg_host_setup_tx(struct dwc_otg_td td->remainder -= td->tx_bytes; td->toggle = 1; return (0); /* complete */ + } else { + if ((sc->sc_sof_val & 1) != (td->sof_val & 1)) + return (1); /* busy */ + td->sof_val += 1; } } else { return (1); /* busy */ @@ -882,12 +906,19 @@ not_complete: /* DATA 0 */ td->toggle = 0; } else if (ep_type == UE_INTERRUPT) { - if ((sc->sc_interrupt_val & 0xFF) != td->sof_val) + if ((sc->sc_sof_val & 0xFF) != td->sof_val) return (1); /* busy */ td->sof_val += td->sof_res; - } else if (td->set_toggle) { - td->set_toggle = 0; - td->toggle = 1; + } else { + if (td->did_nak) { + if ((sc->sc_sof_val & 1) != (td->sof_val & 1)) + return (1); /* busy */ + td->sof_val += 1; + } + if (td->set_toggle) { + td->set_toggle = 0; + td->toggle = 1; + } } /* receive one packet */ @@ -1078,7 +1109,11 @@ dwc_otg_host_data_tx(struct dwc_otg_td * /* else we need to transmit a short packet */ } - } + } else { + if ((sc->sc_sof_val & 1) != (td->sof_val & 1)) + return (1); /* busy */ + td->sof_val += 1; + } } else { return (1); /* busy */ } @@ -1098,7 +1133,7 @@ dwc_otg_host_data_tx(struct dwc_otg_td * td->toggle = 0; } else if (ep_type == UE_INTERRUPT) { - if ((sc->sc_interrupt_val & 0xFF) != td->sof_val) + if ((sc->sc_sof_val & 0xFF) != td->sof_val) return (1); /* busy */ td->sof_val += td->sof_res; } else if (td->set_toggle) { @@ -1775,21 +1810,8 @@ dwc_otg_interrupt(struct dwc_otg_softc * } /* check for Start Of Frame IRQ */ - if (status & GINTMSK_SOFMSK) { - - uint32_t temp; - - temp = DWC_OTG_READ_4(sc, DOTG_HFNUM); - temp &= HFNUM_FRNUM_MASK; - - if (sc->sc_flags.status_high_speed) { - if ((temp & 7) == (sc->sc_sof_val & 7)) - sc->sc_sof_val++; - } else { - if ((temp & 1) == (sc->sc_sof_val & 1)) - sc->sc_sof_val++; - } - } + if (status & GINTMSK_SOFMSK) + sc->sc_sof_val++; /* poll FIFO(s) */ dwc_otg_interrupt_poll(sc); @@ -2058,6 +2080,16 @@ dwc_otg_setup_standard_chain(struct usb_ } else { td->hcsplt = 0; } + if (xfer_type == UE_INTERRUPT) { + uint32_t ival; + ival = xfer->interval; + if (ival == 0) + ival = 1; + else if (ival > 255) + ival = 255; + td->sof_val = sc->sc_sof_val + ival; + td->sof_res = ival; + } break; case USB_SPEED_HIGH: td->hcsplt = 0; @@ -2066,6 +2098,16 @@ dwc_otg_setup_standard_chain(struct usb_ td->hcchar |= ((xfer->max_packet_count & 3) << HCCHAR_MC_SHIFT); } + if (xfer_type == UE_INTERRUPT) { + uint32_t ival; + ival = xfer->interval * 8; + if (ival == 0) + ival = 1; + else if (ival > 255) + ival = 255; + td->sof_val = sc->sc_sof_val + ival; + td->sof_res = ival; + } break; default: td->hcsplt = 0; @@ -2075,9 +2117,9 @@ dwc_otg_setup_standard_chain(struct usb_ if (xfer_type == UE_ISOCHRONOUS) { td->sof_val = xfer->endpoint->isoc_next & 0xFF; td->sof_res = 1 << usbd_xfer_get_fps_shift(xfer); - } else if (xfer_type == UE_INTERRUPT) { - td->sof_val = sc->sc_interrupt_val; - td->sof_res = 0; /* TODO */ + } else if (xfer_type != UE_INTERRUPT) { + td->sof_val = sc->sc_sof_val + 1; + td->sof_res = 1; } } } @@ -2269,6 +2311,9 @@ dwc_otg_device_done(struct usb_xfer *xfe sc->sc_active_rx_ep &= ~(1 << td->channel); td->channel = DWC_OTG_MAX_CHANNELS; + + /* release SOF's */ + dwc_otg_release_sof(sc); } } /* dequeue transfer and start next transfer */ @@ -2742,32 +2787,22 @@ struct usb_pipe_methods dwc_otg_device_n static void dwc_otg_device_isoc_open(struct usb_xfer *xfer) { - struct dwc_otg_softc *sc = DWC_OTG_BUS2SC(xfer->xroot->bus); - if (xfer->xroot->udev->flags.usb_mode == USB_MODE_HOST) { - xfer->qh_pos = 1; - sc->sc_sof_refs++; - sc->sc_irq_mask |= GINTMSK_SOFMSK; - DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask); + struct dwc_otg_softc *sc = DWC_OTG_BUS2SC(xfer->xroot->bus); - usb_hs_bandwidth_alloc(xfer); + xfer->qh_pos = 1; + dwc_otg_request_sof(sc); } } static void dwc_otg_device_isoc_close(struct usb_xfer *xfer) { - struct dwc_otg_softc *sc = DWC_OTG_BUS2SC(xfer->xroot->bus); - if (xfer->qh_pos != 0) { + struct dwc_otg_softc *sc = DWC_OTG_BUS2SC(xfer->xroot->bus); + xfer->qh_pos = 0; - if (--(sc->sc_sof_refs) == 0) { - sc->sc_irq_mask &= ~GINTMSK_SOFMSK; - DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask); - } - } - if (xfer->xroot->udev->flags.usb_mode == USB_MODE_HOST) { - usb_hs_bandwidth_free(xfer); + dwc_otg_release_sof(sc); } dwc_otg_device_done(xfer, USB_ERR_CANCELLED); } Modified: head/sys/dev/usb/controller/dwc_otg.h ============================================================================== --- head/sys/dev/usb/controller/dwc_otg.h Wed Sep 12 04:29:11 2012 (r240380) +++ head/sys/dev/usb/controller/dwc_otg.h Wed Sep 12 07:34:09 2012 (r240381) @@ -151,8 +151,6 @@ struct dwc_otg_softc { uint32_t sc_hcchar[DWC_OTG_MAX_CHANNELS]; uint32_t sc_sof_refs; uint32_t sc_sof_val; - uint32_t sc_interrupt_refs; - uint32_t sc_interrupt_val; uint32_t sc_hprt_val; uint16_t sc_active_rx_ep;