summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2010-09-29 20:06:38 +0000
committerkettenis <kettenis@openbsd.org>2010-09-29 20:06:38 +0000
commitfdb60670484c99ea2edc6a9611625826bae11136 (patch)
tree66511e26c8604bea17d4976650c427703a20ef24
parentIn the implementation of the SIOCS80211DELNODE ioctl, call (diff)
downloadwireguard-openbsd-fdb60670484c99ea2edc6a9611625826bae11136.tar.xz
wireguard-openbsd-fdb60670484c99ea2edc6a9611625826bae11136.zip
Add DMA sync operations. Fixes problems on macppc with gcc4 because
apparently it reorders stores in a bad way. Mostly from NetBSD. earlier diff tested by landry@ (who noticed the problems on macppc) ok deraadt@
-rw-r--r--sys/dev/usb/ehci.c131
-rw-r--r--sys/dev/usb/ehcivar.h6
-rw-r--r--sys/dev/usb/usb_mem.c9
-rw-r--r--sys/dev/usb/usb_mem.h3
4 files changed, 143 insertions, 6 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c
index 4f7fb9c26c6..7c43fb59a89 100644
--- a/sys/dev/usb/ehci.c
+++ b/sys/dev/usb/ehci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehci.c,v 1.111 2010/09/23 08:39:32 jakemsr Exp $ */
+/* $OpenBSD: ehci.c,v 1.112 2010/09/29 20:06:38 kettenis Exp $ */
/* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */
/*
@@ -450,6 +450,8 @@ ehci_init(ehci_softc_t *sc)
sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
sqh->sqtd = NULL;
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
/* Point the frame list at the last level (128ms). */
for (i = 0; i < (1 << (EHCI_IPOLLRATES - 1)); i++)
@@ -457,6 +459,8 @@ ehci_init(ehci_softc_t *sc)
sc->sc_flist[j] = htole32(EHCI_LINK_QH | sc->sc_islots[
EHCI_IQHIDX(EHCI_IPOLLRATES - 1, ehci_reverse_bits(
i, EHCI_IPOLLRATES - 1))].sqh->physaddr);
+ usb_syncmem(&sc->sc_fldma, 0, sc->sc_flsize * sizeof(ehci_link_t),
+ BUS_DMASYNC_PREWRITE);
/* Allocate dummy QH that starts the async list. */
sqh = ehci_alloc_sqh(sc);
@@ -477,6 +481,8 @@ ehci_init(ehci_softc_t *sc)
sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
sqh->sqtd = NULL;
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#ifdef EHCI_DEBUG
if (ehcidebug)
ehci_dump_sqh(sqh);
@@ -716,10 +722,21 @@ ehci_check_qh_intr(ehci_softc_t *sc, struct ehci_xfer *ex)
* is a an error somewhere in the middle, or whether there was a
* short packet (SPD and not ACTIVE).
*/
+ usb_syncmem(&lsqtd->dma,
+ lsqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(lsqtd->qtd.qtd_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
if (letoh32(lsqtd->qtd.qtd_status) & EHCI_QTD_ACTIVE) {
DPRINTFN(12, ("ehci_check_intr: active ex=%p\n", ex));
for (sqtd = ex->sqtdstart; sqtd != lsqtd; sqtd=sqtd->nextqtd) {
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(sqtd->qtd.qtd_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
status = letoh32(sqtd->qtd.qtd_status);
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(sqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD);
/* If there's an active QTD the xfer isn't done. */
if (status & EHCI_QTD_ACTIVE)
break;
@@ -732,6 +749,9 @@ ehci_check_qh_intr(ehci_softc_t *sc, struct ehci_xfer *ex)
}
DPRINTFN(12, ("ehci_check_intr: ex=%p std=%p still active\n",
ex, ex->sqtdstart));
+ usb_syncmem(&lsqtd->dma,
+ lsqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(lsqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD);
return;
}
done:
@@ -763,9 +783,13 @@ ehci_check_itd_intr(ehci_softc_t *sc, struct ehci_xfer *ex) {
#endif
/*
- * Step 1, check no active transfers in last itd, meaning we're finished
* check no active transfers in last itd, meaning we're finished
*/
+
+ usb_syncmem(&itd->dma, itd->offs + offsetof(ehci_itd_t, itd_ctl),
+ sizeof(itd->itd.itd_ctl), BUS_DMASYNC_POSTWRITE |
+ BUS_DMASYNC_POSTREAD);
+
for (i = 0; i < 8; i++) {
if (letoh32(itd->itd.itd_ctl[i]) & EHCI_ITD_ACTIVE)
break;
@@ -855,6 +879,11 @@ ehci_idone(struct ehci_xfer *ex)
}
for (itd = ex->itdstart; itd != NULL; itd = itd->xfer_next) {
+ usb_syncmem(&itd->dma,
+ itd->offs + offsetof(ehci_itd_t, itd_ctl),
+ sizeof(itd->itd.itd_ctl), BUS_DMASYNC_POSTWRITE |
+ BUS_DMASYNC_POSTREAD);
+
for (i = 0; i < 8; i += uframes) {
/* XXX - driver didn't fill in the frame full
* of uframes. This leads to scheduling
@@ -890,6 +919,8 @@ ehci_idone(struct ehci_xfer *ex)
actlen = 0;
for (sqtd = ex->sqtdstart; sqtd != lsqtd->nextqtd;
sqtd = sqtd->nextqtd) {
+ usb_syncmem(&sqtd->dma, sqtd->offs, sizeof(sqtd->qtd),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
nstatus = letoh32(sqtd->qtd.qtd_status);
if (nstatus & EHCI_QTD_ACTIVE)
break;
@@ -1311,7 +1342,14 @@ ehci_dump_sqtds(ehci_soft_qtd_t *sqtd)
stop = 0;
for (i = 0; sqtd && i < 20 && !stop; sqtd = sqtd->nextqtd, i++) {
ehci_dump_sqtd(sqtd);
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_next),
+ sizeof(sqtd->qtd),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
stop = sqtd->qtd.qtd_next & htole32(EHCI_LINK_TERMINATE);
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_next),
+ sizeof(sqtd->qtd), BUS_DMASYNC_PREREAD);
}
if (!stop)
printf("dump aborted, too many TDs\n");
@@ -1320,8 +1358,12 @@ ehci_dump_sqtds(ehci_soft_qtd_t *sqtd)
void
ehci_dump_sqtd(ehci_soft_qtd_t *sqtd)
{
+ usb_syncmem(&sqtd->dma, sqtd->offs,
+ sizeof(sqtd->qtd), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
printf("QTD(%p) at 0x%08x:\n", sqtd, sqtd->physaddr);
ehci_dump_qtd(&sqtd->qtd);
+ usb_syncmem(&sqtd->dma, sqtd->offs,
+ sizeof(sqtd->qtd), BUS_DMASYNC_PREREAD);
}
void
@@ -1352,6 +1394,8 @@ ehci_dump_sqh(ehci_soft_qh_t *sqh)
ehci_qh_t *qh = &sqh->qh;
u_int32_t endp, endphub;
+ usb_syncmem(&sqh->dma, sqh->offs,
+ sizeof(sqh->qh), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
printf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr);
printf(" link="); ehci_dump_link(qh->qh_link, 1); printf("\n");
endp = letoh32(qh->qh_endp);
@@ -1372,6 +1416,8 @@ ehci_dump_sqh(ehci_soft_qh_t *sqh)
printf(" curqtd="); ehci_dump_link(qh->qh_curqtd, 0); printf("\n");
printf("Overlay qTD:\n");
ehci_dump_qtd(&qh->qh_qtd);
+ usb_syncmem(&sqh->dma, sqh->offs,
+ sizeof(sqh->qh), BUS_DMASYNC_PREREAD);
}
#if notyet
@@ -1523,6 +1569,9 @@ ehci_open(usbd_pipe_handle pipe)
sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
sqh->qh.qh_qtd.qtd_status =
htole32(EHCI_QTD_SET_TOGGLE(pipe->endpoint->savedtoggle));
+
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
epipe->sqh = sqh;
} else {
sqh = NULL;
@@ -1595,13 +1644,19 @@ ehci_add_qh(ehci_soft_qh_t *sqh, ehci_soft_qh_t *head)
{
SPLUSBCHECK;
+ usb_syncmem(&head->dma, head->offs + offsetof(ehci_qh_t, qh_link),
+ sizeof(head->qh.qh_link), BUS_DMASYNC_POSTWRITE);
sqh->next = head->next;
sqh->prev = head;
sqh->qh.qh_link = head->qh.qh_link;
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_link),
+ sizeof(sqh->qh.qh_link), BUS_DMASYNC_PREWRITE);
head->next = sqh;
if (sqh->next)
sqh->next->prev = sqh;
head->qh.qh_link = htole32(sqh->physaddr | EHCI_LINK_QH);
+ usb_syncmem(&head->dma, head->offs + offsetof(ehci_qh_t, qh_link),
+ sizeof(head->qh.qh_link), BUS_DMASYNC_PREWRITE);
#ifdef EHCI_DEBUG
if (ehcidebug > 5) {
@@ -1620,10 +1675,16 @@ ehci_rem_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head)
{
SPLUSBCHECK;
/* XXX */
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_link),
+ sizeof(sqh->qh.qh_link), BUS_DMASYNC_POSTWRITE);
sqh->prev->qh.qh_link = sqh->qh.qh_link;
sqh->prev->next = sqh->next;
if (sqh->next)
sqh->next->prev = sqh->prev;
+ usb_syncmem(&sqh->prev->dma,
+ sqh->prev->offs + offsetof(ehci_qh_t, qh_link),
+ sizeof(sqh->prev->qh.qh_link), BUS_DMASYNC_PREWRITE);
+
ehci_sync_hc(sc);
}
@@ -1634,20 +1695,32 @@ ehci_set_qh_qtd(ehci_soft_qh_t *sqh, ehci_soft_qtd_t *sqtd)
u_int32_t status;
/* Save toggle bit and ping status. */
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
status = sqh->qh.qh_qtd.qtd_status &
htole32(EHCI_QTD_TOGGLE_MASK |
EHCI_QTD_SET_STATUS(EHCI_QTD_PINGSTATE));
/* Set HALTED to make hw leave it alone. */
sqh->qh.qh_qtd.qtd_status =
htole32(EHCI_QTD_SET_STATUS(EHCI_QTD_HALTED));
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+ sizeof(sqh->qh.qh_qtd.qtd_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
sqh->qh.qh_curqtd = 0;
sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr);
sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
for (i = 0; i < EHCI_QTD_NBUFFERS; i++)
sqh->qh.qh_qtd.qtd_buffer[i] = 0;
sqh->sqtd = sqtd;
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/* Set !HALTED && !ACTIVE to start execution, preserve some fields */
sqh->qh.qh_qtd.qtd_status = status;
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+ sizeof(sqh->qh.qh_qtd.qtd_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
/*
@@ -1708,6 +1781,10 @@ ehci_rem_free_itd_chain(ehci_softc_t *sc, struct ehci_xfer *exfer)
if (prev == NULL) { /* We're at the table head */
sc->sc_softitds[itd->slot] = itd->u.frame_list.next;
sc->sc_flist[itd->slot] = itd->itd.itd_next;
+ usb_syncmem(&sc->sc_fldma,
+ sizeof(ehci_link_t) * itd->slot,
+ sizeof(ehci_link_t),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
if (itd->u.frame_list.next != NULL)
itd->u.frame_list.next->u.frame_list.prev =
@@ -1715,6 +1792,10 @@ ehci_rem_free_itd_chain(ehci_softc_t *sc, struct ehci_xfer *exfer)
} else {
/* XXX this part is untested... */
prev->itd.itd_next = itd->itd.itd_next;
+ usb_syncmem(&itd->dma,
+ itd->offs + offsetof(ehci_itd_t, itd_next),
+ sizeof(itd->itd.itd_next), BUS_DMASYNC_PREWRITE);
+
prev->u.frame_list.next = itd->u.frame_list.next;
if (itd->u.frame_list.next != NULL)
itd->u.frame_list.next->u.frame_list.prev =
@@ -2339,6 +2420,8 @@ ehci_alloc_sqh(ehci_softc_t *sc)
offs = i * EHCI_SQH_SIZE;
sqh = KERNADDR(&dma, offs);
sqh->physaddr = DMAADDR(&dma, offs);
+ sqh->dma = dma;
+ sqh->offs = offs;
sqh->next = sc->sc_freeqhs;
sc->sc_freeqhs = sqh;
}
@@ -2382,6 +2465,8 @@ ehci_alloc_sqtd(ehci_softc_t *sc)
offs = i * EHCI_SQTD_SIZE;
sqtd = KERNADDR(&dma, offs);
sqtd->physaddr = DMAADDR(&dma, offs);
+ sqtd->dma = dma;
+ sqtd->offs = offs;
sqtd->nextqtd = sc->sc_freeqtds;
sc->sc_freeqtds = sqtd;
}
@@ -2446,6 +2531,9 @@ ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc, u_int alen,
*sp = cur;
if (cur == NULL)
goto nomem;
+
+ usb_syncmem(dma, 0, alen,
+ rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
for (;;) {
dataphyspage = EHCI_PAGE(dataphys);
/* The EHCI hardware can handle at most 5 pages. */
@@ -2533,11 +2621,15 @@ ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc, u_int alen,
break;
forceshort = 0;
}
+ usb_syncmem(&cur->dma, cur->offs, sizeof(cur->qtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n"));
dataphys += curlen;
cur = next;
}
cur->qtd.qtd_status |= htole32(EHCI_QTD_IOC);
+ usb_syncmem(&cur->dma, cur->offs, sizeof(cur->qtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
*ep = cur;
DPRINTFN(10,("ehci_alloc_sqtd_chain: return sqtd=%p sqtdend=%p\n",
@@ -2618,6 +2710,10 @@ ehci_alloc_itd(ehci_softc_t *sc)
itd = freeitd;
LIST_REMOVE(itd, u.free_list);
memset(&itd->itd, 0, sizeof(ehci_itd_t));
+ usb_syncmem(&itd->dma, itd->offs + offsetof(ehci_itd_t, itd_next),
+ sizeof(itd->itd.itd_next), BUS_DMASYNC_PREWRITE |
+ BUS_DMASYNC_PREREAD);
+
itd->u.frame_list.next = NULL;
itd->u.frame_list.prev = NULL;
itd->xfer_next = NULL;
@@ -2743,7 +2839,15 @@ ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
* behaves correctly when we deactivate them afterwards.
*/
for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(sqtd->qtd.qtd_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sqtd->qtd.qtd_status = htole32(EHCI_QTD_HALTED);
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(sqtd->qtd.qtd_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
if (sqtd == exfer->sqtdend)
break;
}
@@ -2775,6 +2879,10 @@ ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
* the aborting xfer. (If there is something past us).
* Hardware and software.
*/
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(ehci_qh_t, qh_curqtd),
+ sizeof(sqh->qh.qh_curqtd),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
cur = EHCI_LINK_ADDR(letoh32(sqh->qh.qh_curqtd));
hit = 0;
@@ -3137,11 +3245,14 @@ ehci_device_request(usbd_xfer_handle xfer)
end->nextqtd = stat;
end->qtd.qtd_next =
end->qtd.qtd_altnext = htole32(stat->physaddr);
+ usb_syncmem(&end->dma, end->offs, sizeof(end->qtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
} else {
next = stat;
}
memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof(*req));
+ usb_syncmem(&epipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_PREWRITE);
/* Clear toggle */
setup->qtd.qtd_status = htole32(
@@ -3156,6 +3267,8 @@ ehci_device_request(usbd_xfer_handle xfer)
setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr);
setup->xfer = xfer;
setup->len = sizeof(*req);
+ usb_syncmem(&setup->dma, setup->offs, sizeof(setup->qtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
stat->qtd.qtd_status = htole32(
EHCI_QTD_ACTIVE |
@@ -3169,6 +3282,8 @@ ehci_device_request(usbd_xfer_handle xfer)
stat->qtd.qtd_next = stat->qtd.qtd_altnext = EHCI_NULL;
stat->xfer = xfer;
stat->len = 0;
+ usb_syncmem(&stat->dma, stat->offs, sizeof(stat->qtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#ifdef EHCI_DEBUG
if (ehcidebug > 5) {
@@ -3358,7 +3473,9 @@ ehci_device_bulk_done(usbd_xfer_handle xfer)
{
struct ehci_xfer *ex = EXFER(xfer);
ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus;
- /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/
+ struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
+ int endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
+ int rd = UE_GET_DIR(endpt) == UE_DIR_IN;
DPRINTFN(10,("ehci_bulk_done: xfer=%p, actlen=%d\n",
xfer, xfer->actlen));
@@ -3366,6 +3483,8 @@ ehci_device_bulk_done(usbd_xfer_handle xfer)
if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
ehci_del_intr_list(sc, ex); /* remove from active list */
ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+ usb_syncmem(&xfer->dmabuf, 0, xfer->length,
+ rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
}
DPRINTFN(5, ("ehci_bulk_done: length=%d\n", xfer->actlen));
@@ -3555,6 +3674,8 @@ ehci_device_intr_done(usbd_xfer_handle xfer)
xfer->length = len;
endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
isread = UE_GET_DIR(endpt) == UE_DIR_IN;
+ usb_syncmem(&xfer->dmabuf, 0, len,
+ isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
sqh = epipe->sqh;
err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer,
@@ -3589,6 +3710,10 @@ ehci_device_intr_done(usbd_xfer_handle xfer)
} else if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
ehci_del_intr_list(sc, ex); /* remove from active list */
ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+ endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
+ isread = UE_GET_DIR(endpt) == UE_DIR_IN;
+ usb_syncmem(&xfer->dmabuf, 0, xfer->length,
+ isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
}
#undef exfer
}
diff --git a/sys/dev/usb/ehcivar.h b/sys/dev/usb/ehcivar.h
index 9970ac4b516..e93bf1cc18a 100644
--- a/sys/dev/usb/ehcivar.h
+++ b/sys/dev/usb/ehcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehcivar.h,v 1.19 2010/09/07 16:21:46 deraadt Exp $ */
+/* $OpenBSD: ehcivar.h,v 1.20 2010/09/29 20:06:38 kettenis Exp $ */
/* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */
/*
@@ -34,6 +34,8 @@ typedef struct ehci_soft_qtd {
ehci_qtd_t qtd;
struct ehci_soft_qtd *nextqtd; /* mirrors nextqtd in TD */
ehci_physaddr_t physaddr;
+ usb_dma_t dma; /* qTD's DMA infos */
+ int offs; /* qTD's offset in usb_dma_t */
usbd_xfer_handle xfer;
LIST_ENTRY(ehci_soft_qtd) hnext;
u_int16_t len;
@@ -47,6 +49,8 @@ typedef struct ehci_soft_qh {
struct ehci_soft_qh *prev;
struct ehci_soft_qtd *sqtd;
ehci_physaddr_t physaddr;
+ usb_dma_t dma; /* QH's DMA infos */
+ int offs; /* QH's offset in usb_dma_t */
int islot;
} ehci_soft_qh_t;
#define EHCI_SQH_SIZE ((sizeof (struct ehci_soft_qh) + EHCI_QH_ALIGN - 1) / EHCI_QH_ALIGN * EHCI_QH_ALIGN)
diff --git a/sys/dev/usb/usb_mem.c b/sys/dev/usb/usb_mem.c
index e09d15b2667..2302f2b1185 100644
--- a/sys/dev/usb/usb_mem.c
+++ b/sys/dev/usb/usb_mem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_mem.c,v 1.21 2008/06/26 05:42:19 ray Exp $ */
+/* $OpenBSD: usb_mem.c,v 1.22 2010/09/29 20:06:38 kettenis Exp $ */
/* $NetBSD: usb_mem.c,v 1.26 2003/02/01 06:23:40 thorpej Exp $ */
/*
@@ -275,3 +275,10 @@ usb_freemem(usbd_bus_handle bus, usb_dma_t *p)
splx(s);
DPRINTFN(5, ("usb_freemem: frag=%p\n", f));
}
+
+void
+usb_syncmem(usb_dma_t *p, bus_addr_t offset, bus_size_t len, int ops)
+{
+ bus_dmamap_sync(p->block->tag, p->block->map, p->offs + offset,
+ len, ops);
+}
diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h
index 0e803cb07b7..566e95b689c 100644
--- a/sys/dev/usb/usb_mem.h
+++ b/sys/dev/usb/usb_mem.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_mem.h,v 1.12 2008/06/26 05:42:19 ray Exp $ */
+/* $OpenBSD: usb_mem.h,v 1.13 2010/09/29 20:06:38 kettenis Exp $ */
/* $NetBSD: usb_mem.h,v 1.20 2003/05/03 18:11:42 wiz Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_mem.h,v 1.9 1999/11/17 22:33:47 n_hibma Exp $ */
@@ -50,3 +50,4 @@ typedef struct usb_dma_block {
usbd_status usb_allocmem(usbd_bus_handle,size_t,size_t, usb_dma_t *);
void usb_freemem(usbd_bus_handle, usb_dma_t *);
+void usb_syncmem(usb_dma_t *, bus_addr_t, bus_size_t, int);