FreeBSD Bugzilla – Attachment 226355 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.15 KB, created by
Hans Petter Selasky
on 2021-07-10 16:49:53 UTC
(
hide
)
Description:
Patch to try
Filename:
MIME Type:
Creator:
Hans Petter Selasky
Created:
2021-07-10 16:49:53 UTC
Size:
30.15 KB
patch
obsolete
>diff --git a/sys/dev/usb/controller/atmegadci.c b/sys/dev/usb/controller/atmegadci.c >index 1f91948c4cc..0e3499de51c 100644 >--- a/sys/dev/usb/controller/atmegadci.c >+++ b/sys/dev/usb/controller/atmegadci.c >@@ -1421,7 +1421,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", >@@ -1433,41 +1432,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, 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 eaf0f8261b9..d42e38ea9ee 100644 >--- a/sys/dev/usb/controller/avr32dci.c >+++ b/sys/dev/usb/controller/avr32dci.c >@@ -1355,7 +1355,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; > >@@ -1366,41 +1365,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, 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); >@@ -1690,6 +1657,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 421b95593b3..a67b3b3d2c7 100644 >--- a/sys/dev/usb/controller/dwc_otg.c >+++ b/sys/dev/usb/controller/dwc_otg.c >@@ -4189,9 +4189,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); >@@ -4214,52 +4212,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, 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 0b7f41b3923..1a74a0ef525 100644 >--- a/sys/dev/usb/controller/ehci.c >+++ b/sys/dev/usb/controller/ehci.c >@@ -2440,6 +2440,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; >@@ -2458,39 +2459,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, 1, EHCI_VIRTUAL_FRAMELIST_COUNT - 1, &startframe)) >+ DPRINTFN(3, "start next=%d\n", startframe); > > /* get the real number of frames */ > >@@ -2507,11 +2478,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) { >@@ -2633,10 +2604,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 >@@ -2743,11 +2710,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; >@@ -2755,47 +2722,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, 1, EHCI_VIRTUAL_FRAMELIST_COUNT - 1, &startframe)) >+ DPRINTFN(3, "start next=%d\n", startframe); > > nframes = xfer->nframes; > >@@ -2811,11 +2747,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) { >@@ -2927,10 +2863,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 24eba2a9a55..4d69a860a0b 100644 >--- a/sys/dev/usb/controller/musb_otg.c >+++ b/sys/dev/usb/controller/musb_otg.c >@@ -3436,9 +3436,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); >@@ -3447,45 +3445,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, 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 39f3bd54f50..17481facf95 100644 >--- a/sys/dev/usb/controller/ohci.c >+++ b/sys/dev/usb/controller/ohci.c >@@ -1824,6 +1824,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]; >@@ -1840,31 +1841,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, 1, 0xFFFF, &startframe)) >+ DPRINTFN(3, "start next=%d\n", startframe); > > /* get the real number of frames */ > >@@ -1905,12 +1884,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 df0162e5174..cab653ac0a5 100644 >--- a/sys/dev/usb/controller/saf1761_otg.c >+++ b/sys/dev/usb/controller/saf1761_otg.c >@@ -2632,7 +2632,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", >@@ -2642,39 +2641,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, 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); >@@ -2714,7 +2683,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", >@@ -2724,39 +2692,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, 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 59453359deb..67d974bd934 100644 >--- a/sys/dev/usb/controller/uhci.c >+++ b/sys/dev/usb/controller/uhci.c >@@ -2111,7 +2111,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 >@@ -2127,34 +2127,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, 1, UHCI_VFRAMELIST_COUNT - 1, &startframe)) >+ DPRINTFN(3, "start next=%d\n", startframe); > > /* get the real number of frames */ > >@@ -2171,11 +2146,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) { >@@ -2252,10 +2227,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 b2e112b07f6..5acffd8cc41 100644 >--- a/sys/dev/usb/controller/uss820dci.c >+++ b/sys/dev/usb/controller/uss820dci.c >@@ -1706,7 +1706,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", >@@ -1716,39 +1715,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, 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 10e37c97c25..faf767bb130 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); > >@@ -2026,7 +2029,6 @@ xhci_setup_generic_chain(struct usb_xfer *xfer) > struct xhci_std_temp temp; > struct xhci_td *td; > uint32_t x; >- uint32_t y; > uint8_t mult; > > temp.do_isoc_sync = 0; >@@ -2075,7 +2077,13 @@ 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, sc->sc_ist); >+ >+ /* add isochronous scheduling threshold */ >+ if (temp.sc->sc_ist & 8) >+ x += (temp.sc->sc_ist & 7) << 3; >+ else >+ x += (temp.sc->sc_ist & 7); > > switch (usbd_get_speed(xfer->xroot->udev)) { > case USB_SPEED_FULL: >@@ -2089,16 +2097,11 @@ xhci_setup_generic_chain(struct usb_xfer *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); >- >- if ((xfer->endpoint->is_synced == 0) || >- (y < (xfer->nframes << shift)) || >- (XHCI_MFINDEX_GET(-y) >= (128 * 8))) { >+ if (usbd_xfer_get_isochronous_start_frame( >+ xfer, x, 8, XHCI_MFINDEX_GET(-1), &temp.isoc_frame)) { > /* > * If there is data underflow or the pipe > * queue is empty we schedule the transfer a >@@ -2106,27 +2109,14 @@ xhci_setup_generic_chain(struct usb_xfer *xfer) > * position. Else two isochronous transfers > * might overlap. > */ >- 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); >+ DPRINTFN(3, "start next=%d\n", temp.isoc_frame); > } > >- /* compute isochronous completion time */ >- >- y = XHCI_MFINDEX_GET(xfer->endpoint->isoc_next - (x & ~7)); >- >- xfer->isoc_time_complete = >- usb_isoc_time_expand(&temp.sc->sc_bus, x / 8) + >- (y / 8) + (((xfer->nframes << shift) + 7) / 8); >- > 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 */ > >@@ -3063,15 +3053,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 >@@ -3080,16 +3062,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 c0427e0cf11..80220720856 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 0b4ad5e71b4..d90ce3b51cb 100644 >--- a/sys/dev/usb/usb_transfer.c >+++ b/sys/dev/usb/usb_transfer.c >@@ -3680,3 +3680,69 @@ 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 isochronous transfer shall 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_ms, uint32_t frame_mask, uint32_t *p_frame_start) >+{ >+ uint32_t duration; >+ uint32_t delta; >+ uint8_t retval; >+ uint8_t shift; >+ >+ delta = (xfer->endpoint->isoc_next - frame_curr) & frame_mask; >+ >+ /* >+ * Check if it is the first transfer, 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 || delta > (frame_mask / 2)) { >+ xfer->endpoint->isoc_next = (frame_curr + frame_ms) & 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 */ >+ 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 c6b97e1ab3c..be070895309 100644 >--- a/sys/dev/usb/usb_transfer.h >+++ b/sys/dev/usb/usb_transfer.h >@@ -250,5 +250,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 *); > > #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