FreeBSD Bugzilla – Attachment 226357 Details for
Bug 257082
Sound with Scarlett Solo 3rd intermittently cuts off for very short periods of milliseconds.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch to try
a.diff (text/plain), 30.90 KB, created by
Hans Petter Selasky
on 2021-07-10 19:46:39 UTC
(
hide
)
Description:
Patch to try
Filename:
MIME Type:
Creator:
Hans Petter Selasky
Created:
2021-07-10 19:46:39 UTC
Size:
30.90 KB
patch
obsolete
>diff --git a/sys/dev/usb/controller/atmegadci.c b/sys/dev/usb/controller/atmegadci.c >index 8bc27fb51ae5..658f363c67c8 100644 >--- a/sys/dev/usb/controller/atmegadci.c >+++ b/sys/dev/usb/controller/atmegadci.c >@@ -1441,7 +1441,6 @@ static void > atmegadci_device_isoc_fs_enter(struct usb_xfer *xfer) > { > struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus); >- uint32_t temp; > uint32_t nframes; > > DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", >@@ -1453,41 +1452,9 @@ atmegadci_device_isoc_fs_enter(struct usb_xfer *xfer) > (ATMEGA_READ_1(sc, ATMEGA_UDFNUMH) << 8) | > (ATMEGA_READ_1(sc, ATMEGA_UDFNUML)); > >- nframes &= ATMEGA_FRAME_MASK; >- >- /* >- * check if the frame index is within the window where the frames >- * will be inserted >- */ >- temp = (nframes - xfer->endpoint->isoc_next) & ATMEGA_FRAME_MASK; >- >- if ((xfer->endpoint->is_synced == 0) || >- (temp < xfer->nframes)) { >- /* >- * If there is data underflow or the pipe queue is >- * empty we schedule the transfer a few frames ahead >- * of the current frame position. Else two isochronous >- * transfers might overlap. >- */ >- xfer->endpoint->isoc_next = (nframes + 3) & ATMEGA_FRAME_MASK; >- xfer->endpoint->is_synced = 1; >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, nframes, 0, 1, ATMEGA_FRAME_MASK, NULL)) > DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- temp = (xfer->endpoint->isoc_next - nframes) & ATMEGA_FRAME_MASK; >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&sc->sc_bus, nframes) + temp + >- xfer->nframes; >- >- /* compute frame number for next insertion */ >- xfer->endpoint->isoc_next += xfer->nframes; > > /* setup TDs */ > atmegadci_setup_standard_chain(xfer); >diff --git a/sys/dev/usb/controller/avr32dci.c b/sys/dev/usb/controller/avr32dci.c >index b8c22a6ab01f..a8d58fe2a5cc 100644 >--- a/sys/dev/usb/controller/avr32dci.c >+++ b/sys/dev/usb/controller/avr32dci.c >@@ -1371,7 +1371,6 @@ static void > avr32dci_device_isoc_fs_enter(struct usb_xfer *xfer) > { > struct avr32dci_softc *sc = AVR32_BUS2SC(xfer->xroot->bus); >- uint32_t temp; > uint32_t nframes; > uint8_t ep_no; > >@@ -1382,41 +1381,9 @@ avr32dci_device_isoc_fs_enter(struct usb_xfer *xfer) > ep_no = xfer->endpointno & UE_ADDR; > nframes = (AVR32_READ_4(sc, AVR32_FNUM) / 8); > >- nframes &= AVR32_FRAME_MASK; >- >- /* >- * check if the frame index is within the window where the frames >- * will be inserted >- */ >- temp = (nframes - xfer->endpoint->isoc_next) & AVR32_FRAME_MASK; >- >- if ((xfer->endpoint->is_synced == 0) || >- (temp < xfer->nframes)) { >- /* >- * If there is data underflow or the pipe queue is >- * empty we schedule the transfer a few frames ahead >- * of the current frame position. Else two isochronous >- * transfers might overlap. >- */ >- xfer->endpoint->isoc_next = (nframes + 3) & AVR32_FRAME_MASK; >- xfer->endpoint->is_synced = 1; >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, nframes, 0, 1, AVR32_FRAME_MASK, NULL)) > DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- temp = (xfer->endpoint->isoc_next - nframes) & AVR32_FRAME_MASK; >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&sc->sc_bus, nframes) + temp + >- xfer->nframes; >- >- /* compute frame number for next insertion */ >- xfer->endpoint->isoc_next += xfer->nframes; > > /* setup TDs */ > avr32dci_setup_standard_chain(xfer); >@@ -1707,6 +1674,12 @@ avr32dci_roothub_exec(struct usb_device *udev, > len = sizeof(avr32dci_devd); > ptr = (const void *)&avr32dci_devd; > goto tr_valid; >+ case UDESC_DEVICE_QUALIFIER: >+ if (value & 0xff) >+ goto tr_stalled; >+ len = sizeof(avr32dci_odevd); >+ ptr = (const void *)&avr32dci_odevd; >+ goto tr_valid; > case UDESC_CONFIG: > if (value & 0xff) { > goto tr_stalled; >diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c >index 35ce4eee52df..de3420de6c2f 100644 >--- a/sys/dev/usb/controller/dwc_otg.c >+++ b/sys/dev/usb/controller/dwc_otg.c >@@ -4197,9 +4197,7 @@ dwc_otg_device_isoc_start(struct usb_xfer *xfer) > { > struct dwc_otg_softc *sc = DWC_OTG_BUS2SC(xfer->xroot->bus); > uint32_t temp; >- uint32_t msframes; > uint32_t framenum; >- uint8_t shift = usbd_xfer_get_fps_shift(xfer); > > DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", > xfer, xfer->endpoint->isoc_next, xfer->nframes); >@@ -4222,52 +4220,13 @@ dwc_otg_device_isoc_start(struct usb_xfer *xfer) > if (sc->sc_flags.status_high_speed) > framenum /= 8; > >- framenum &= DWC_OTG_FRAME_MASK; >- >- /* >- * Compute number of milliseconds worth of data traffic for >- * this USB transfer: >- */ >- if (xfer->xroot->udev->speed == USB_SPEED_HIGH) >- msframes = ((xfer->nframes << shift) + 7) / 8; >- else >- msframes = xfer->nframes; >- >- /* >- * check if the frame index is within the window where the frames >- * will be inserted >- */ >- temp = (framenum - xfer->endpoint->isoc_next) & DWC_OTG_FRAME_MASK; >- >- if ((xfer->endpoint->is_synced == 0) || (temp < msframes)) { >- /* >- * If there is data underflow or the pipe queue is >- * empty we schedule the transfer a few frames ahead >- * of the current frame position. Else two isochronous >- * transfers might overlap. >- */ >- xfer->endpoint->isoc_next = (framenum + 3) & DWC_OTG_FRAME_MASK; >- xfer->endpoint->is_synced = 1; >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, framenum, 0, 1, DWC_OTG_FRAME_MASK, NULL)) > DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- temp = (xfer->endpoint->isoc_next - framenum) & DWC_OTG_FRAME_MASK; >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&sc->sc_bus, framenum) + temp + msframes; > > /* setup TDs */ > dwc_otg_setup_standard_chain(xfer); > >- /* compute frame number for next insertion */ >- xfer->endpoint->isoc_next += msframes; >- > /* start TD chain */ > dwc_otg_start_standard_chain(xfer); > } >diff --git a/sys/dev/usb/controller/ehci.c b/sys/dev/usb/controller/ehci.c >index aa1f9b31b4d2..5d4772f7bd0a 100644 >--- a/sys/dev/usb/controller/ehci.c >+++ b/sys/dev/usb/controller/ehci.c >@@ -2465,6 +2465,7 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer) > uint32_t *plen; > uint32_t buf_offset; > uint32_t nframes; >+ uint32_t startframe; > uint32_t temp; > uint32_t sitd_mask; > uint16_t tlen; >@@ -2483,39 +2484,9 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer) > > nframes = EOREAD4(sc, EHCI_FRINDEX) / 8; > >- /* >- * check if the frame index is within the window where the frames >- * will be inserted >- */ >- buf_offset = (nframes - xfer->endpoint->isoc_next) & >- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1); >- >- if ((xfer->endpoint->is_synced == 0) || >- (buf_offset < xfer->nframes)) { >- /* >- * If there is data underflow or the pipe queue is empty we >- * schedule the transfer a few frames ahead of the current >- * frame position. Else two isochronous transfers might >- * overlap. >- */ >- xfer->endpoint->isoc_next = (nframes + 3) & >- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1); >- xfer->endpoint->is_synced = 1; >- DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- buf_offset = (xfer->endpoint->isoc_next - nframes) & >- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1); >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&sc->sc_bus, nframes) + >- buf_offset + xfer->nframes; >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, nframes, 0, 1, EHCI_VIRTUAL_FRAMELIST_COUNT - 1, &startframe)) >+ DPRINTFN(3, "start next=%d\n", startframe); > > /* get the real number of frames */ > >@@ -2532,11 +2503,11 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer) > td = xfer->td_start[xfer->flags_int.curr_dma_set]; > xfer->td_transfer_first = td; > >- pp_last = &sc->sc_isoc_fs_p_last[xfer->endpoint->isoc_next]; >+ pp_last = &sc->sc_isoc_fs_p_last[startframe]; > > /* store starting position */ > >- xfer->qh_pos = xfer->endpoint->isoc_next; >+ xfer->qh_pos = startframe; > > while (nframes--) { > if (td == NULL) { >@@ -2658,10 +2629,6 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer) > > xfer->td_transfer_last = td_last; > >- /* update isoc_next */ >- xfer->endpoint->isoc_next = (pp_last - &sc->sc_isoc_fs_p_last[0]) & >- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1); >- > /* > * We don't allow cancelling of the SPLIT transaction USB FULL > * speed transfer, because it disturbs the bandwidth >@@ -2770,11 +2737,11 @@ ehci_device_isoc_hs_enter(struct usb_xfer *xfer) > uint32_t status; > uint32_t buf_offset; > uint32_t nframes; >+ uint32_t startframe; > uint32_t itd_offset[8 + 1]; > uint8_t x; > uint8_t td_no; > uint8_t page_no; >- uint8_t shift = usbd_xfer_get_fps_shift(xfer); > > #ifdef USB_DEBUG > uint8_t once = 1; >@@ -2782,47 +2749,16 @@ ehci_device_isoc_hs_enter(struct usb_xfer *xfer) > #endif > > DPRINTFN(6, "xfer=%p next=%d nframes=%d shift=%d\n", >- xfer, xfer->endpoint->isoc_next, xfer->nframes, (int)shift); >+ xfer, xfer->endpoint->isoc_next, xfer->nframes, >+ usbd_xfer_get_fps_shift(xfer)); > > /* get the current frame index */ > > nframes = EOREAD4(sc, EHCI_FRINDEX) / 8; > >- /* >- * check if the frame index is within the window where the frames >- * will be inserted >- */ >- buf_offset = (nframes - xfer->endpoint->isoc_next) & >- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1); >- >- if ((xfer->endpoint->is_synced == 0) || >- (buf_offset < (((xfer->nframes << shift) + 7) / 8))) { >- /* >- * If there is data underflow or the pipe queue is empty we >- * schedule the transfer a few frames ahead of the current >- * frame position. Else two isochronous transfers might >- * overlap. >- */ >- xfer->endpoint->isoc_next = (nframes + 3) & >- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1); >- xfer->endpoint->is_synced = 1; >- DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- buf_offset = (xfer->endpoint->isoc_next - nframes) & >- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1); >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&sc->sc_bus, nframes) + buf_offset + >- (((xfer->nframes << shift) + 7) / 8); >- >- /* get the real number of frames */ >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, nframes, 0, 1, EHCI_VIRTUAL_FRAMELIST_COUNT - 1, &startframe)) >+ DPRINTFN(3, "start next=%d\n", startframe); > > nframes = xfer->nframes; > >@@ -2838,11 +2774,11 @@ ehci_device_isoc_hs_enter(struct usb_xfer *xfer) > td = xfer->td_start[xfer->flags_int.curr_dma_set]; > xfer->td_transfer_first = td; > >- pp_last = &sc->sc_isoc_hs_p_last[xfer->endpoint->isoc_next]; >+ pp_last = &sc->sc_isoc_hs_p_last[startframe]; > > /* store starting position */ > >- xfer->qh_pos = xfer->endpoint->isoc_next; >+ xfer->qh_pos = startframe; > > while (nframes) { > if (td == NULL) { >@@ -2955,10 +2891,6 @@ ehci_device_isoc_hs_enter(struct usb_xfer *xfer) > } > > xfer->td_transfer_last = td_last; >- >- /* update isoc_next */ >- xfer->endpoint->isoc_next = (pp_last - &sc->sc_isoc_hs_p_last[0]) & >- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1); > } > > static void >diff --git a/sys/dev/usb/controller/musb_otg.c b/sys/dev/usb/controller/musb_otg.c >index 1fca463ee827..a29018d9a448 100644 >--- a/sys/dev/usb/controller/musb_otg.c >+++ b/sys/dev/usb/controller/musb_otg.c >@@ -3474,9 +3474,7 @@ static void > musbotg_device_isoc_enter(struct usb_xfer *xfer) > { > struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus); >- uint32_t temp; > uint32_t nframes; >- uint32_t fs_frames; > > DPRINTFN(5, "xfer=%p next=%d nframes=%d\n", > xfer, xfer->endpoint->isoc_next, xfer->nframes); >@@ -3485,45 +3483,9 @@ musbotg_device_isoc_enter(struct usb_xfer *xfer) > > nframes = MUSB2_READ_2(sc, MUSB2_REG_FRAME); > >- /* >- * check if the frame index is within the window where the frames >- * will be inserted >- */ >- temp = (nframes - xfer->endpoint->isoc_next) & MUSB2_MASK_FRAME; >- >- if (usbd_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH) { >- fs_frames = (xfer->nframes + 7) / 8; >- } else { >- fs_frames = xfer->nframes; >- } >- >- if ((xfer->endpoint->is_synced == 0) || >- (temp < fs_frames)) { >- /* >- * If there is data underflow or the pipe queue is >- * empty we schedule the transfer a few frames ahead >- * of the current frame position. Else two isochronous >- * transfers might overlap. >- */ >- xfer->endpoint->isoc_next = (nframes + 3) & MUSB2_MASK_FRAME; >- xfer->endpoint->is_synced = 1; >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, nframes, 0, 1, MUSB2_MASK_FRAME, NULL)) > DPRINTFN(2, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- temp = (xfer->endpoint->isoc_next - nframes) & MUSB2_MASK_FRAME; >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&sc->sc_bus, nframes) + temp + >- fs_frames; >- >- /* compute frame number for next insertion */ >- xfer->endpoint->isoc_next += fs_frames; > > /* setup TDs */ > musbotg_setup_standard_chain(xfer); >diff --git a/sys/dev/usb/controller/ohci.c b/sys/dev/usb/controller/ohci.c >index dffa3676cb7d..0c91a23db72a 100644 >--- a/sys/dev/usb/controller/ohci.c >+++ b/sys/dev/usb/controller/ohci.c >@@ -1844,6 +1844,7 @@ ohci_device_isoc_enter(struct usb_xfer *xfer) > struct ohci_hcca *hcca; > uint32_t buf_offset; > uint32_t nframes; >+ uint32_t startframe; > uint32_t ed_flags; > uint32_t *plen; > uint16_t itd_offset[OHCI_ITD_NOFFSET]; >@@ -1860,31 +1861,9 @@ ohci_device_isoc_enter(struct usb_xfer *xfer) > DPRINTFN(6, "xfer=%p isoc_next=%u nframes=%u hcca_fn=%u\n", > xfer, xfer->endpoint->isoc_next, xfer->nframes, nframes); > >- if ((xfer->endpoint->is_synced == 0) || >- (((nframes - xfer->endpoint->isoc_next) & 0xFFFF) < xfer->nframes) || >- (((xfer->endpoint->isoc_next - nframes) & 0xFFFF) >= 128)) { >- /* >- * If there is data underflow or the pipe queue is empty we >- * schedule the transfer a few frames ahead of the current >- * frame position. Else two isochronous transfers might >- * overlap. >- */ >- xfer->endpoint->isoc_next = (nframes + 3) & 0xFFFF; >- xfer->endpoint->is_synced = 1; >- DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- buf_offset = ((xfer->endpoint->isoc_next - nframes) & 0xFFFF); >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- (usb_isoc_time_expand(&sc->sc_bus, nframes) + buf_offset + >- xfer->nframes); >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, nframes, 0, 1, 0xFFFF, &startframe)) >+ DPRINTFN(3, "start next=%d\n", startframe); > > /* get the real number of frames */ > >@@ -1926,12 +1905,12 @@ ohci_device_isoc_enter(struct usb_xfer *xfer) > /* fill current ITD */ > td->itd_flags = htole32( > OHCI_ITD_NOCC | >- OHCI_ITD_SET_SF(xfer->endpoint->isoc_next) | >+ OHCI_ITD_SET_SF(startframe) | > OHCI_ITD_NOINTR | > OHCI_ITD_SET_FC(ncur)); > > td->frames = ncur; >- xfer->endpoint->isoc_next += ncur; >+ startframe += ncur; > > if (length == 0) { > /* all zero */ >diff --git a/sys/dev/usb/controller/saf1761_otg.c b/sys/dev/usb/controller/saf1761_otg.c >index b559ac83b229..32bb83a77721 100644 >--- a/sys/dev/usb/controller/saf1761_otg.c >+++ b/sys/dev/usb/controller/saf1761_otg.c >@@ -2645,7 +2645,6 @@ static void > saf1761_otg_device_isoc_enter(struct usb_xfer *xfer) > { > struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(xfer->xroot->bus); >- uint32_t temp; > uint32_t nframes; > > DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", >@@ -2655,39 +2654,9 @@ saf1761_otg_device_isoc_enter(struct usb_xfer *xfer) > > nframes = SAF1761_READ_LE_4(sc, SOTG_FRAME_NUM); > >- /* >- * check if the frame index is within the window where the >- * frames will be inserted >- */ >- temp = (nframes - xfer->endpoint->isoc_next) & SOTG_FRAME_NUM_SOFR_MASK; >- >- if ((xfer->endpoint->is_synced == 0) || >- (temp < xfer->nframes)) { >- /* >- * If there is data underflow or the pipe queue is >- * empty we schedule the transfer a few frames ahead >- * of the current frame position. Else two isochronous >- * transfers might overlap. >- */ >- xfer->endpoint->isoc_next = (nframes + 3) & SOTG_FRAME_NUM_SOFR_MASK; >- xfer->endpoint->is_synced = 1; >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, nframes, 0, 1, SOTG_FRAME_NUM_SOFR_MASK, NULL)) > DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- temp = (xfer->endpoint->isoc_next - nframes) & SOTG_FRAME_NUM_SOFR_MASK; >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&sc->sc_bus, nframes) + temp + >- xfer->nframes; >- >- /* compute frame number for next insertion */ >- xfer->endpoint->isoc_next += xfer->nframes; > > /* setup TDs */ > saf1761_otg_setup_standard_chain(xfer); >@@ -2727,7 +2696,6 @@ static void > saf1761_otg_host_isoc_enter(struct usb_xfer *xfer) > { > struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(xfer->xroot->bus); >- uint32_t temp; > uint32_t nframes; > > DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", >@@ -2737,39 +2705,9 @@ saf1761_otg_host_isoc_enter(struct usb_xfer *xfer) > > nframes = (SAF1761_READ_LE_4(sc, SOTG_FRINDEX) & SOTG_FRINDEX_MASK) >> 3; > >- /* >- * check if the frame index is within the window where the >- * frames will be inserted >- */ >- temp = (nframes - xfer->endpoint->isoc_next) & (SOTG_FRINDEX_MASK >> 3); >- >- if ((xfer->endpoint->is_synced == 0) || >- (temp < xfer->nframes)) { >- /* >- * If there is data underflow or the pipe queue is >- * empty we schedule the transfer a few frames ahead >- * of the current frame position. Else two isochronous >- * transfers might overlap. >- */ >- xfer->endpoint->isoc_next = (nframes + 3) & (SOTG_FRINDEX_MASK >> 3); >- xfer->endpoint->is_synced = 1; >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, nframes, 0, 1, SOTG_FRINDEX_MASK >> 3, NULL)) > DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- temp = (xfer->endpoint->isoc_next - nframes) & (SOTG_FRINDEX_MASK >> 3); >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&sc->sc_bus, nframes) + temp + >- xfer->nframes; >- >- /* compute frame number for next insertion */ >- xfer->endpoint->isoc_next += xfer->nframes; > > /* setup TDs */ > saf1761_otg_setup_standard_chain(xfer); >diff --git a/sys/dev/usb/controller/uhci.c b/sys/dev/usb/controller/uhci.c >index 16ffa7756878..ecb8781b77b2 100644 >--- a/sys/dev/usb/controller/uhci.c >+++ b/sys/dev/usb/controller/uhci.c >@@ -2142,7 +2142,7 @@ uhci_device_isoc_enter(struct usb_xfer *xfer) > struct uhci_mem_layout ml; > uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus); > uint32_t nframes; >- uint32_t temp; >+ uint32_t startframe; > uint32_t *plen; > > #ifdef USB_DEBUG >@@ -2158,34 +2158,9 @@ uhci_device_isoc_enter(struct usb_xfer *xfer) > > nframes = UREAD2(sc, UHCI_FRNUM); > >- temp = (nframes - xfer->endpoint->isoc_next) & >- (UHCI_VFRAMELIST_COUNT - 1); >- >- if ((xfer->endpoint->is_synced == 0) || >- (temp < xfer->nframes)) { >- /* >- * If there is data underflow or the pipe queue is empty we >- * schedule the transfer a few frames ahead of the current >- * frame position. Else two isochronous transfers might >- * overlap. >- */ >- xfer->endpoint->isoc_next = (nframes + 3) & (UHCI_VFRAMELIST_COUNT - 1); >- xfer->endpoint->is_synced = 1; >- DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- temp = (xfer->endpoint->isoc_next - nframes) & >- (UHCI_VFRAMELIST_COUNT - 1); >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&sc->sc_bus, nframes) + temp + >- xfer->nframes; >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, nframes, 0, 1, UHCI_VFRAMELIST_COUNT - 1, &startframe)) >+ DPRINTFN(3, "start next=%d\n", startframe); > > /* get the real number of frames */ > >@@ -2202,11 +2177,11 @@ uhci_device_isoc_enter(struct usb_xfer *xfer) > td = xfer->td_start[xfer->flags_int.curr_dma_set]; > xfer->td_transfer_first = td; > >- pp_last = &sc->sc_isoc_p_last[xfer->endpoint->isoc_next]; >+ pp_last = &sc->sc_isoc_p_last[startframe]; > > /* store starting position */ > >- xfer->qh_pos = xfer->endpoint->isoc_next; >+ xfer->qh_pos = startframe; > > while (nframes--) { > if (td == NULL) { >@@ -2285,10 +2260,6 @@ uhci_device_isoc_enter(struct usb_xfer *xfer) > } > > xfer->td_transfer_last = td_last; >- >- /* update isoc_next */ >- xfer->endpoint->isoc_next = (pp_last - &sc->sc_isoc_p_last[0]) & >- (UHCI_VFRAMELIST_COUNT - 1); > } > > static void >diff --git a/sys/dev/usb/controller/uss820dci.c b/sys/dev/usb/controller/uss820dci.c >index f8e48b9a5a9c..f99c104fdca3 100644 >--- a/sys/dev/usb/controller/uss820dci.c >+++ b/sys/dev/usb/controller/uss820dci.c >@@ -1724,7 +1724,6 @@ static void > uss820dci_device_isoc_fs_enter(struct usb_xfer *xfer) > { > struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus); >- uint32_t temp; > uint32_t nframes; > > DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", >@@ -1734,39 +1733,9 @@ uss820dci_device_isoc_fs_enter(struct usb_xfer *xfer) > > nframes = USS820_READ_1(sc, USS820_SOFL); > >- /* >- * check if the frame index is within the window where the >- * frames will be inserted >- */ >- temp = (nframes - xfer->endpoint->isoc_next) & USS820_SOFL_MASK; >- >- if ((xfer->endpoint->is_synced == 0) || >- (temp < xfer->nframes)) { >- /* >- * If there is data underflow or the pipe queue is >- * empty we schedule the transfer a few frames ahead >- * of the current frame position. Else two isochronous >- * transfers might overlap. >- */ >- xfer->endpoint->isoc_next = (nframes + 3) & USS820_SOFL_MASK; >- xfer->endpoint->is_synced = 1; >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, nframes, 0, 1, USS820_SOFL_MASK, NULL)) > DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >- } >- /* >- * compute how many milliseconds the insertion is ahead of the >- * current frame position: >- */ >- temp = (xfer->endpoint->isoc_next - nframes) & USS820_SOFL_MASK; >- >- /* >- * pre-compute when the isochronous transfer will be finished: >- */ >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&sc->sc_bus, nframes) + temp + >- xfer->nframes; >- >- /* compute frame number for next insertion */ >- xfer->endpoint->isoc_next += xfer->nframes; > > /* setup TDs */ > uss820dci_setup_standard_chain(xfer); >diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c >index 70a73dcc94c4..7cbee6e2104b 100644 >--- a/sys/dev/usb/controller/xhci.c >+++ b/sys/dev/usb/controller/xhci.c >@@ -133,8 +133,8 @@ struct xhci_std_temp { > uint32_t offset; > uint32_t max_packet_size; > uint32_t average; >+ uint32_t isoc_frame; > uint16_t isoc_delta; >- uint16_t isoc_frame; > uint8_t shortpkt; > uint8_t multishort; > uint8_t last_frame; >@@ -644,6 +644,9 @@ xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32) > > DPRINTF("HCS2=0x%08x\n", temp); > >+ /* get isochronous scheduling threshold */ >+ sc->sc_ist = XHCI_HCS2_IST(temp); >+ > /* get number of scratchpads */ > sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp); > >@@ -2089,58 +2092,57 @@ xhci_setup_generic_chain(struct usb_xfer *xfer) > > x = XREAD4(temp.sc, runt, XHCI_MFINDEX); > >- DPRINTF("MFINDEX=0x%08x\n", x); >+ DPRINTF("MFINDEX=0x%08x IST=0x%x\n", x, temp.sc->sc_ist); > > switch (usbd_get_speed(xfer->xroot->udev)) { > case USB_SPEED_FULL: > shift = 3; > temp.isoc_delta = 8; /* 1ms */ >- x += temp.isoc_delta - 1; >- x &= ~(temp.isoc_delta - 1); > break; > default: > shift = usbd_xfer_get_fps_shift(xfer); > temp.isoc_delta = 1U << shift; >- x += temp.isoc_delta - 1; >- x &= ~(temp.isoc_delta - 1); >- /* simple frame load balancing */ >- x += xfer->endpoint->usb_uframe; > break; > } > >- y = XHCI_MFINDEX_GET(x - xfer->endpoint->isoc_next); >+ /* Compute isochronous scheduling threshold. */ >+ if (temp.sc->sc_ist & 8) >+ y = (temp.sc->sc_ist & 7) << 3; >+ else >+ y = (temp.sc->sc_ist & 7); > >- if ((xfer->endpoint->is_synced == 0) || >- (y < (xfer->nframes << shift)) || >- (XHCI_MFINDEX_GET(-y) >= (128 * 8))) { >+ /* Range check the IST. */ >+ if (y < 8) { >+ y = 0; >+ } else if (y > 15) { >+ DPRINTFN(3, "IST(%d) is too big!\n", temp.sc->sc_ist); > /* >- * If there is data underflow or the pipe >- * queue is empty we schedule the transfer a >- * few frames ahead of the current frame >- * position. Else two isochronous transfers >- * might overlap. >+ * The USB stack minimum isochronous transfer >+ * size is typically 2x2 ms of payload. If the >+ * IST makes is above 15 microframes, we have >+ * an effective scheduling delay of more than >+ * or equal to 2 milliseconds, which is too >+ * much. > */ >- xfer->endpoint->isoc_next = XHCI_MFINDEX_GET(x + (3 * 8)); >- xfer->endpoint->is_synced = 1; >- temp.do_isoc_sync = 1; >- >- DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); >+ } else { >+ /* >+ * Subtract one millisecond, because the >+ * generic code adds that to the latency. >+ */ >+ y -= 8; > } > >- /* compute isochronous completion time */ >- >- y = XHCI_MFINDEX_GET(xfer->endpoint->isoc_next - (x & ~7)); >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, x, y, 8, XHCI_MFINDEX_GET(-1), &temp.isoc_frame)) { >+ /* Start isochronous transfer at specified time. */ >+ temp.do_isoc_sync = 1; > >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&temp.sc->sc_bus, x / 8) + >- (y / 8) + (((xfer->nframes << shift) + 7) / 8); >+ DPRINTFN(3, "start next=%d\n", temp.isoc_frame); >+ } > > x = 0; >- temp.isoc_frame = xfer->endpoint->isoc_next; > temp.trb_type = XHCI_TRB_TYPE_ISOCH; > >- xfer->endpoint->isoc_next += xfer->nframes << shift; >- > } else if (xfer->flags_int.control_xfr) { > > /* check if we should prepend a setup message */ >@@ -3087,15 +3089,7 @@ xhci_device_done(struct usb_xfer *xfer, usb_error_t error) > static void > xhci_device_generic_open(struct usb_xfer *xfer) > { >- if (xfer->flags_int.isochronous_xfr) { >- switch (xfer->xroot->udev->speed) { >- case USB_SPEED_FULL: >- break; >- default: >- usb_hs_bandwidth_alloc(xfer); >- break; >- } >- } >+ DPRINTF("\n"); > } > > static void >@@ -3104,16 +3098,6 @@ xhci_device_generic_close(struct usb_xfer *xfer) > DPRINTF("\n"); > > xhci_device_done(xfer, USB_ERR_CANCELLED); >- >- if (xfer->flags_int.isochronous_xfr) { >- switch (xfer->xroot->udev->speed) { >- case USB_SPEED_FULL: >- break; >- default: >- usb_hs_bandwidth_free(xfer); >- break; >- } >- } > } > > static void >diff --git a/sys/dev/usb/controller/xhci.h b/sys/dev/usb/controller/xhci.h >index 6bfd342e0620..dc9156e6e4e4 100644 >--- a/sys/dev/usb/controller/xhci.h >+++ b/sys/dev/usb/controller/xhci.h >@@ -33,7 +33,7 @@ > #define XHCI_MAX_DEVICES MIN(USB_MAX_DEVICES, 128) > #define XHCI_MAX_ENDPOINTS 32 /* hardcoded - do not change */ > #define XHCI_MAX_SCRATCHPADS 256 /* theoretical max is 1023 */ >-#define XHCI_MAX_EVENTS (16 * 13) >+#define XHCI_MAX_EVENTS 232 > #define XHCI_MAX_COMMANDS (16 * 1) > #define XHCI_MAX_RSEG 1 > #define XHCI_MAX_TRANSFERS 4 >@@ -383,6 +383,8 @@ struct xhci_hw_root { > struct xhci_trb hwr_commands[XHCI_MAX_COMMANDS]; > }; > >+CTASSERT(sizeof(struct xhci_hw_root) == XHCI_PAGE_SIZE); >+ > struct xhci_endpoint_ext { > struct xhci_trb *trb; > struct usb_xfer *xfer[XHCI_MAX_TRANSFERS * XHCI_MAX_STREAMS]; >@@ -527,6 +529,9 @@ struct xhci_softc { > /* size of context */ > uint8_t sc_ctx_is_64_byte; > >+ /* Isochronous Scheduling Threshold */ >+ uint8_t sc_ist; >+ > /* vendor string for root HUB */ > char sc_vendor[16]; > }; >diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c >index ab70da8afd4c..b1d8623cea91 100644 >--- a/sys/dev/usb/usb_transfer.c >+++ b/sys/dev/usb/usb_transfer.c >@@ -3662,3 +3662,72 @@ usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer) > { > return (xfer->flags_int.maxp_was_clamped); > } >+ >+/* >+ * The following function computes the next isochronous frame number >+ * where the first isochronous packet should be queued. >+ * >+ * The function returns non-zero if there was a discontinuity. >+ * Else zero is returned for normal operation. >+ */ >+uint8_t >+usbd_xfer_get_isochronous_start_frame(struct usb_xfer *xfer, uint32_t frame_curr, >+ uint32_t frame_min, uint32_t frame_ms, uint32_t frame_mask, uint32_t *p_frame_start) >+{ >+ uint32_t duration; >+ uint32_t delta; >+ uint8_t retval; >+ uint8_t shift; >+ >+ /* Compute time ahead of current schedule. */ >+ delta = (xfer->endpoint->isoc_next - frame_curr) & frame_mask; >+ >+ /* >+ * Check if it is the first transfer or if the future frame >+ * delta is less than one millisecond or if the frame delta is >+ * negative: >+ */ >+ if (xfer->endpoint->is_synced == 0 || >+ delta < (frame_ms + frame_min) || >+ delta > (frame_mask / 2)) { >+ /* Schedule transfer 2 milliseconds into the future. */ >+ xfer->endpoint->isoc_next = (frame_curr + 2 * frame_ms + frame_min) & frame_mask; >+ xfer->endpoint->is_synced = 1; >+ >+ retval = 1; >+ } else { >+ retval = 0; >+ } >+ >+ /* Store start time, if any. */ >+ if (p_frame_start != NULL) >+ *p_frame_start = xfer->endpoint->isoc_next & frame_mask; >+ >+ /* Get relative completion time, in milliseconds. */ >+ delta = xfer->endpoint->isoc_next - frame_curr + (frame_curr % frame_ms); >+ delta &= frame_mask; >+ delta /= frame_ms; >+ >+ switch (usbd_get_speed(xfer->xroot->udev)) { >+ case USB_SPEED_FULL: >+ shift = 3; >+ break; >+ default: >+ shift = usbd_xfer_get_fps_shift(xfer); >+ break; >+ } >+ >+ /* Get duration in milliseconds, rounded up. */ >+ duration = ((xfer->nframes << shift) + 7) / 8; >+ >+ /* Compute full 32-bit completion time, in milliseconds. */ >+ xfer->isoc_time_complete = >+ usb_isoc_time_expand(xfer->xroot->bus, frame_curr / frame_ms) + >+ delta + duration; >+ >+ /* Compute next isochronous frame. */ >+ xfer->endpoint->isoc_next += duration * frame_ms; >+ xfer->endpoint->isoc_next &= frame_mask; >+ >+ return (retval); >+} >diff --git a/sys/dev/usb/usb_transfer.h b/sys/dev/usb/usb_transfer.h >index da632a738262..de4f8bf8c871 100644 >--- a/sys/dev/usb/usb_transfer.h >+++ b/sys/dev/usb/usb_transfer.h >@@ -252,5 +252,6 @@ void usbd_transfer_timeout_ms(struct usb_xfer *xfer, > void (*cb) (void *arg), usb_timeout_t ms); > usb_timeout_t usbd_get_dma_delay(struct usb_device *udev); > void usbd_transfer_power_ref(struct usb_xfer *xfer, int val); >+uint8_t usbd_xfer_get_isochronous_start_frame(struct usb_xfer *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t *); > > #endif /* _USB_TRANSFER_H_ */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 257082
:
226349
|
226355
|
226357
|
226397
|
226420
|
226461
|
226462