Module Name:    src
Committed By:   jmcneill
Date:           Sun Sep 22 14:05:47 UTC 2024

Modified Files:
        src/sys/dev/usb: ohci.c ohcireg.h ohcivar.h

Log Message:
ohci: Allocate a whole cacheline for all descriptors

Allocate a whole cacheline for all descriptor types such that:

 i) they can be alloc'ed without USBMALLOC_COHERENT which can mean they're
    now mapped cacheable, and
ii) the "soft" versions are cacheable, and mapped as small as possible.

Patch/idea mainly from Nick (skrll@) with a few fixes from me.


To generate a diff of this commit:
cvs rdiff -u -r1.328 -r1.329 src/sys/dev/usb/ohci.c
cvs rdiff -u -r1.28 -r1.29 src/sys/dev/usb/ohcireg.h
cvs rdiff -u -r1.62 -r1.63 src/sys/dev/usb/ohcivar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/ohci.c
diff -u src/sys/dev/usb/ohci.c:1.328 src/sys/dev/usb/ohci.c:1.329
--- src/sys/dev/usb/ohci.c:1.328	Sun Apr 28 08:55:03 2024
+++ src/sys/dev/usb/ohci.c	Sun Sep 22 14:05:47 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: ohci.c,v 1.328 2024/04/28 08:55:03 skrll Exp $	*/
+/*	$NetBSD: ohci.c,v 1.329 2024/09/22 14:05:47 jmcneill Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004, 2005, 2012, 2016, 2020 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.328 2024/04/28 08:55:03 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.329 2024/09/22 14:05:47 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -409,19 +409,29 @@ ohci_alloc_sed(ohci_softc_t *sc)
 		DPRINTFN(2, "allocating chunk", 0, 0, 0, 0);
 		mutex_exit(&sc->sc_lock);
 
-		int err = usb_allocmem(sc->sc_bus.ub_dmatag, OHCI_SED_SIZE * OHCI_SED_CHUNK,
-		    OHCI_ED_ALIGN, 0 /*!USBMALLOC_COHERENT*/, &dma);
+		int err = usb_allocmem(sc->sc_bus.ub_dmatag,
+		    OHCI_ED_SIZE * OHCI_ED_CHUNK,
+		    OHCI_ED_ALIGN, 0, &dma);
 		if (err)
 			return NULL;
 
+		ohci_soft_ed_t *seds =
+		    kmem_alloc(sizeof(*sed) * OHCI_ED_CHUNK, KM_SLEEP);
+		/*
+		 * We can avoid USBMALLOC_COHERENT as the EDs are each on a
+		 * cacheline.
+		 */
 		mutex_enter(&sc->sc_lock);
-		for (i = 0; i < OHCI_SED_CHUNK; i++) {
-			offs = i * OHCI_SED_SIZE;
-			sed = KERNADDR(&dma, offs);
+		for (i = 0; i < OHCI_ED_CHUNK; i++) {
+			offs = i * OHCI_ED_SIZE;
+
+			sed = &seds[i];
+			sed->ed = KERNADDR(&dma, offs);
 			sed->physaddr = DMAADDR(&dma, offs);
 			sed->dma = dma;
 			sed->offs = offs;
 			sed->next = sc->sc_freeeds;
+
 			sc->sc_freeeds = sed;
 		}
 	}
@@ -429,7 +439,7 @@ ohci_alloc_sed(ohci_softc_t *sc)
 	sc->sc_freeeds = sed->next;
 	mutex_exit(&sc->sc_lock);
 
-	memset(&sed->ed, 0, sizeof(ohci_ed_t));
+	memset(sed->ed, 0, sizeof(*sed->ed));
 	sed->next = 0;
 	return sed;
 }
@@ -467,19 +477,29 @@ ohci_alloc_std(ohci_softc_t *sc)
 		DPRINTFN(2, "allocating chunk", 0, 0, 0, 0);
 		mutex_exit(&sc->sc_lock);
 
-		int err = usb_allocmem(sc->sc_bus.ub_dmatag, OHCI_STD_SIZE * OHCI_STD_CHUNK,
-		   OHCI_TD_ALIGN, USBMALLOC_COHERENT, &dma);
+		ohci_soft_td_t *stds =
+		    kmem_alloc(sizeof(*std) * OHCI_TD_CHUNK, KM_SLEEP);
+		/*
+		 * We can avoid USBMALLOC_COHERENT as the TDs are each on a
+		 * cacheline.
+		 */
+		int err = usb_allocmem(sc->sc_bus.ub_dmatag,
+		    OHCI_TD_SIZE * OHCI_TD_CHUNK,
+		    OHCI_TD_ALIGN, 0, &dma);
 		if (err)
 			return NULL;
 
 		mutex_enter(&sc->sc_lock);
-		for (i = 0; i < OHCI_STD_CHUNK; i++) {
-			offs = i * OHCI_STD_SIZE;
-			std = KERNADDR(&dma, offs);
+		for (i = 0; i < OHCI_TD_CHUNK; i++) {
+			offs = i * OHCI_TD_SIZE;
+
+			std = &stds[i];
+			std->td = KERNADDR(&dma, offs);
 			std->physaddr = DMAADDR(&dma, offs);
 			std->dma = dma;
 			std->offs = offs;
 			std->nexttd = sc->sc_freetds;
+
 			sc->sc_freetds = std;
 		}
 	}
@@ -488,7 +508,7 @@ ohci_alloc_std(ohci_softc_t *sc)
 	sc->sc_freetds = std->nexttd;
 	mutex_exit(&sc->sc_lock);
 
-	memset(&std->td, 0, sizeof(ohci_td_t));
+	memset(std->td, 0, sizeof(*std->td));
 	std->nexttd = NULL;
 	std->xfer = NULL;
 	std->held = NULL;
@@ -651,10 +671,10 @@ ohci_reset_std_chain(ohci_softc_t *sc, s
 		DPRINTFN(4, "sdataphys=0x%08jx edataphys=0x%08jx "
 		    "len=%jd curlen=%jd", sdataphys, edataphys, len, curlen);
 
-		cur->td.td_flags = tdflags;
-		cur->td.td_cbp = HTOO32(sdataphys);
-		cur->td.td_be = HTOO32(edataphys);
-		cur->td.td_nexttd = (next != NULL) ? HTOO32(next->physaddr) : 0;
+		cur->td->td_flags = tdflags;
+		cur->td->td_cbp = HTOO32(sdataphys);
+		cur->td->td_be = HTOO32(edataphys);
+		cur->td->td_nexttd = (next != NULL) ? HTOO32(next->physaddr) : 0;
 		cur->nexttd = next;
 		cur->len = curlen;
 		cur->flags = OHCI_ADD_LEN;
@@ -667,20 +687,20 @@ ohci_reset_std_chain(ohci_softc_t *sc, s
 		if (len != 0) {
 			KASSERT(next != NULL);
 			DPRINTFN(10, "extend chain", 0, 0, 0, 0);
-			usb_syncmem(&cur->dma, cur->offs, sizeof(cur->td),
+			usb_syncmem(&cur->dma, cur->offs, sizeof(*cur->td),
 			    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 			cur = next;
 		}
 	}
-	cur->td.td_flags |=
+	cur->td->td_flags |=
 	    HTOO32(xfer->ux_flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0);
 
 	if (!rd &&
 	    (flags & USBD_FORCE_SHORT_XFER) &&
 	    alen % mps == 0) {
 		/* We're adding a ZLP so sync the previous TD */
-		usb_syncmem(&cur->dma, cur->offs, sizeof(cur->td),
+		usb_syncmem(&cur->dma, cur->offs, sizeof(*cur->td),
 		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 		/* Force a 0 length transfer at the end. */
@@ -688,10 +708,10 @@ ohci_reset_std_chain(ohci_softc_t *sc, s
 		KASSERT(next != NULL);
 		cur = next;
 
-		cur->td.td_flags = tdflags;
-		cur->td.td_cbp = 0; /* indicate 0 length packet */
-		cur->td.td_nexttd = 0;
-		cur->td.td_be = ~0;
+		cur->td->td_flags = tdflags;
+		cur->td->td_cbp = 0; /* indicate 0 length packet */
+		cur->td->td_nexttd = 0;
+		cur->td->td_be = ~0;
 		cur->nexttd = NULL;
 		cur->len = 0;
 		cur->flags = 0;
@@ -719,18 +739,26 @@ ohci_alloc_sitd(ohci_softc_t *sc)
 		DPRINTFN(2, "allocating chunk", 0, 0, 0, 0);
 		mutex_exit(&sc->sc_lock);
 
-		int err = usb_allocmem(sc->sc_bus.ub_dmatag, OHCI_SITD_SIZE * OHCI_SITD_CHUNK,
-		    OHCI_ITD_ALIGN, USBMALLOC_COHERENT, &dma);
+		int err = usb_allocmem(sc->sc_bus.ub_dmatag,
+		    OHCI_ITD_SIZE * OHCI_ITD_CHUNK,
+		    OHCI_ITD_ALIGN, 0, &dma);
 		if (err)
 			return NULL;
+
+		ohci_soft_itd_t *sitds =
+		    kmem_alloc(sizeof(*sitd) * OHCI_ITD_CHUNK, KM_SLEEP);
+
 		mutex_enter(&sc->sc_lock);
-		for (i = 0; i < OHCI_SITD_CHUNK; i++) {
-			offs = i * OHCI_SITD_SIZE;
-			sitd = KERNADDR(&dma, offs);
+		for (i = 0; i < OHCI_ITD_CHUNK; i++) {
+			offs = i * OHCI_ITD_SIZE;
+
+			sitd = &sitds[i];
+			sitd->itd = KERNADDR(&dma, offs);
 			sitd->physaddr = DMAADDR(&dma, offs);
 			sitd->dma = dma;
 			sitd->offs = offs;
 			sitd->nextitd = sc->sc_freeitds;
+
 			sc->sc_freeitds = sitd;
 		}
 	}
@@ -739,7 +767,7 @@ ohci_alloc_sitd(ohci_softc_t *sc)
 	sc->sc_freeitds = sitd->nextitd;
 	mutex_exit(&sc->sc_lock);
 
-	memset(&sitd->itd, 0, sizeof(ohci_itd_t));
+	memset(sitd->itd, 0, sizeof(*sitd->itd));
 	sitd->nextitd = NULL;
 	sitd->xfer = NULL;
 
@@ -843,9 +871,9 @@ ohci_init(ohci_softc_t *sc)
 		err = ENOMEM;
 		goto bad1;
 	}
-	sc->sc_ctrl_head->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
+	sc->sc_ctrl_head->ed->ed_flags |= HTOO32(OHCI_ED_SKIP);
 	usb_syncmem(&sc->sc_ctrl_head->dma, sc->sc_ctrl_head->offs,
-	    sizeof(sc->sc_ctrl_head->ed),
+	    sizeof(*sc->sc_ctrl_head->ed),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	/* Allocate dummy ED that starts the bulk list. */
@@ -854,9 +882,9 @@ ohci_init(ohci_softc_t *sc)
 		err = ENOMEM;
 		goto bad2;
 	}
-	sc->sc_bulk_head->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
+	sc->sc_bulk_head->ed->ed_flags |= HTOO32(OHCI_ED_SKIP);
 	usb_syncmem(&sc->sc_bulk_head->dma, sc->sc_bulk_head->offs,
-	    sizeof(sc->sc_bulk_head->ed),
+	    sizeof(*sc->sc_bulk_head->ed),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	/* Allocate dummy ED that starts the isochronous list. */
@@ -865,9 +893,9 @@ ohci_init(ohci_softc_t *sc)
 		err = ENOMEM;
 		goto bad3;
 	}
-	sc->sc_isoc_head->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
+	sc->sc_isoc_head->ed->ed_flags |= HTOO32(OHCI_ED_SKIP);
 	usb_syncmem(&sc->sc_isoc_head->dma, sc->sc_isoc_head->offs,
-	    sizeof(sc->sc_isoc_head->ed),
+	    sizeof(*sc->sc_isoc_head->ed),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	/* Allocate all the dummy EDs that make up the interrupt tree. */
@@ -881,14 +909,14 @@ ohci_init(ohci_softc_t *sc)
 		}
 		/* All ED fields are set to 0. */
 		sc->sc_eds[i] = sed;
-		sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
+		sed->ed->ed_flags |= HTOO32(OHCI_ED_SKIP);
 		if (i != 0)
 			psed = sc->sc_eds[(i-1) / 2];
 		else
 			psed= sc->sc_isoc_head;
 		sed->next = psed;
-		sed->ed.ed_nexted = HTOO32(psed->physaddr);
-		usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+		sed->ed->ed_nexted = HTOO32(psed->physaddr);
+		usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	}
 	/*
@@ -1453,20 +1481,20 @@ ohci_softintr(void *v)
 	for (sdone = NULL, sidone = NULL; done != 0; ) {
 		std = ohci_hash_find_td(sc, done);
 		if (std != NULL) {
-			usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+			usb_syncmem(&std->dma, std->offs, sizeof(*std->td),
 			    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 			std->dnext = sdone;
-			done = O32TOH(std->td.td_nexttd);
+			done = O32TOH(std->td->td_nexttd);
 			sdone = std;
 			DPRINTFN(10, "add TD %#jx", (uintptr_t)std, 0, 0, 0);
 			continue;
 		}
 		sitd = ohci_hash_find_itd(sc, done);
 		if (sitd != NULL) {
-			usb_syncmem(&sitd->dma, sitd->offs, sizeof(sitd->itd),
+			usb_syncmem(&sitd->dma, sitd->offs, sizeof(*sitd->itd),
 			    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 			sitd->dnext = sidone;
-			done = O32TOH(sitd->itd.itd_nextitd);
+			done = O32TOH(sitd->itd->itd_nextitd);
 			sidone = sitd;
 			DPRINTFN(5, "add ITD %#jx", (uintptr_t)sitd, 0, 0, 0);
 			continue;
@@ -1519,14 +1547,14 @@ ohci_softintr(void *v)
 			continue;
 
 		len = std->len;
-		if (std->td.td_cbp != 0)
-			len -= O32TOH(std->td.td_be) -
-			       O32TOH(std->td.td_cbp) + 1;
+		if (std->td->td_cbp != 0)
+			len -= O32TOH(std->td->td_be) -
+			       O32TOH(std->td->td_cbp) + 1;
 		DPRINTFN(10, "len=%jd, flags=%#jx", len, std->flags, 0, 0);
 		if (std->flags & OHCI_ADD_LEN)
 			xfer->ux_actlen += len;
 
-		cc = OHCI_TD_GET_CC(O32TOH(std->td.td_flags));
+		cc = OHCI_TD_GET_CC(O32TOH(std->td->td_flags));
 		if (cc == OHCI_CC_NO_ERROR) {
 			ohci_hash_rem_td(sc, std);
 			if (std->flags & OHCI_CALL_DONE) {
@@ -1553,11 +1581,11 @@ ohci_softintr(void *v)
 			ohci_soft_ed_t *sed = opipe->sed;
 
 			/* clear halt and TD chain, preserving toggle carry */
-			sed->ed.ed_headp = HTOO32(p->physaddr |
-			    (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY));
+			sed->ed->ed_headp = HTOO32(p->physaddr |
+			    (O32TOH(sed->ed->ed_headp) & OHCI_TOGGLECARRY));
 			usb_syncmem(&sed->dma,
 			    sed->offs + offsetof(ohci_ed_t, ed_headp),
-			    sizeof(sed->ed.ed_headp),
+			    sizeof(sed->ed->ed_headp),
 			    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 			OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
@@ -1613,21 +1641,21 @@ ohci_softintr(void *v)
 			    sitd = next) {
 				next = sitd->nextitd;
 
-				usb_syncmem(&sitd->dma, sitd->offs, sizeof(sitd->itd),
+				usb_syncmem(&sitd->dma, sitd->offs, sizeof(*sitd->itd),
 				    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 
 				if (OHCI_ITD_GET_CC(O32TOH(sitd->
-				    itd.itd_flags)) != OHCI_CC_NO_ERROR)
+				    itd->itd_flags)) != OHCI_CC_NO_ERROR)
 					xfer->ux_status = USBD_IOERROR;
 				/* For input, update frlengths with actual */
 				/* XXX anything necessary for output? */
 				if (uedir == UE_DIR_IN &&
 				    xfer->ux_status == USBD_NORMAL_COMPLETION) {
 					iframes = OHCI_ITD_GET_FC(O32TOH(
-					    sitd->itd.itd_flags));
+					    sitd->itd->itd_flags));
 					for (j = 0; j < iframes; i++, j++) {
 						len = O16TOH(sitd->
-						    itd.itd_offset[j]);
+						    itd->itd_offset[j]);
 						if ((OHCI_ITD_PSW_GET_CC(len) &
 						    OHCI_CC_NOT_ACCESSED_MASK)
 						    == OHCI_CC_NOT_ACCESSED)
@@ -1813,17 +1841,17 @@ ohci_add_ed(ohci_softc_t *sc, ohci_soft_
 	KASSERT(mutex_owned(&sc->sc_lock));
 
 	usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted),
-	    sizeof(head->ed.ed_nexted),
+	    sizeof(head->ed->ed_nexted),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 	sed->next = head->next;
-	sed->ed.ed_nexted = head->ed.ed_nexted;
+	sed->ed->ed_nexted = head->ed->ed_nexted;
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted),
-	    sizeof(sed->ed.ed_nexted),
+	    sizeof(sed->ed->ed_nexted),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	head->next = sed;
-	head->ed.ed_nexted = HTOO32(sed->physaddr);
+	head->ed->ed_nexted = HTOO32(sed->physaddr);
 	usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted),
-	    sizeof(head->ed.ed_nexted),
+	    sizeof(head->ed->ed_nexted),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 }
 
@@ -1843,12 +1871,12 @@ ohci_rem_ed(ohci_softc_t *sc, ohci_soft_
 	KASSERT(p != NULL);
 
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted),
-	    sizeof(sed->ed.ed_nexted),
+	    sizeof(sed->ed->ed_nexted),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 	p->next = sed->next;
-	p->ed.ed_nexted = sed->ed.ed_nexted;
+	p->ed->ed_nexted = sed->ed->ed_nexted;
 	usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted),
-	    sizeof(p->ed.ed_nexted),
+	    sizeof(p->ed->ed_nexted),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 }
 
@@ -1959,10 +1987,10 @@ ohci_dump_td(ohci_softc_t *sc, ohci_soft
 {
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
-	usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+	usb_syncmem(&std->dma, std->offs, sizeof(*std->td),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 
-	uint32_t flags = O32TOH(std->td.td_flags);
+	uint32_t flags = O32TOH(std->td->td_flags);
 	DPRINTF("TD(%#jx) at 0x%08jx:", (uintptr_t)std, std->physaddr, 0, 0);
 	DPRINTF("    round=%jd DP=%jx DI=%jx T=%jx",
 	    !!(flags & OHCI_TD_R),
@@ -1972,9 +2000,9 @@ ohci_dump_td(ohci_softc_t *sc, ohci_soft
 	DPRINTF("    EC=%jd CC=%jd", OHCI_TD_GET_EC(flags),
 	    OHCI_TD_GET_CC(flags), 0, 0);
 	DPRINTF("    td_cbp=0x%08jx td_nexttd=0x%08jx td_be=0x%08jx",
-	       (u_long)O32TOH(std->td.td_cbp),
-	       (u_long)O32TOH(std->td.td_nexttd),
-	       (u_long)O32TOH(std->td.td_be), 0);
+	       (u_long)O32TOH(std->td->td_cbp),
+	       (u_long)O32TOH(std->td->td_nexttd),
+	       (u_long)O32TOH(std->td->td_be), 0);
 }
 
 void
@@ -1982,31 +2010,31 @@ ohci_dump_itd(ohci_softc_t *sc, ohci_sof
 {
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
-	usb_syncmem(&sitd->dma, sitd->offs, sizeof(sitd->itd),
+	usb_syncmem(&sitd->dma, sitd->offs, sizeof(*sitd->itd),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 
-	uint32_t flags = O32TOH(sitd->itd.itd_flags);
+	uint32_t flags = O32TOH(sitd->itd->itd_flags);
 	DPRINTF("ITD(%#jx) at 0x%08jx", (uintptr_t)sitd, sitd->physaddr, 0, 0);
 	DPRINTF("    sf=%jd di=%jd fc=%jd cc=%jd",
 	    OHCI_ITD_GET_SF(flags), OHCI_ITD_GET_DI(flags),
 	    OHCI_ITD_GET_FC(flags), OHCI_ITD_GET_CC(flags));
 	DPRINTF("    bp0=0x%08jx next=0x%08jx be=0x%08jx",
-	    O32TOH(sitd->itd.itd_bp0),
-	    O32TOH(sitd->itd.itd_nextitd),
-	    O32TOH(sitd->itd.itd_be), 0);
+	    O32TOH(sitd->itd->itd_bp0),
+	    O32TOH(sitd->itd->itd_nextitd),
+	    O32TOH(sitd->itd->itd_be), 0);
 	CTASSERT(OHCI_ITD_NOFFSET == 8);
 	DPRINTF("    offs[0] = 0x%04jx  offs[1] = 0x%04jx  "
 	    "offs[2] = 0x%04jx  offs[3] = 0x%04jx",
-	    O16TOH(sitd->itd.itd_offset[0]),
-	    O16TOH(sitd->itd.itd_offset[1]),
-	    O16TOH(sitd->itd.itd_offset[2]),
-	    O16TOH(sitd->itd.itd_offset[3]));
+	    O16TOH(sitd->itd->itd_offset[0]),
+	    O16TOH(sitd->itd->itd_offset[1]),
+	    O16TOH(sitd->itd->itd_offset[2]),
+	    O16TOH(sitd->itd->itd_offset[3]));
 	DPRINTF("    offs[4] = 0x%04jx  offs[5] = 0x%04jx  "
 	    "offs[6] = 0x%04jx  offs[7] = 0x%04jx",
-	    O16TOH(sitd->itd.itd_offset[4]),
-	    O16TOH(sitd->itd.itd_offset[5]),
-	    O16TOH(sitd->itd.itd_offset[6]),
-	    O16TOH(sitd->itd.itd_offset[7]));
+	    O16TOH(sitd->itd->itd_offset[4]),
+	    O16TOH(sitd->itd->itd_offset[5]),
+	    O16TOH(sitd->itd->itd_offset[6]),
+	    O16TOH(sitd->itd->itd_offset[7]));
 }
 
 void
@@ -2021,10 +2049,10 @@ ohci_dump_ed(ohci_softc_t *sc, ohci_soft
 {
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
-	usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+	usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 
-	uint32_t flags = O32TOH(sed->ed.ed_flags);
+	uint32_t flags = O32TOH(sed->ed->ed_flags);
 	DPRINTF("ED(%#jx) at 0x%08jx:", (uintptr_t)sed, sed->physaddr, 0, 0);
 	DPRINTF("    addr=%jd endpt=%jd maxp=%jd",
 	    OHCI_ED_GET_FA(flags),
@@ -2036,12 +2064,12 @@ ohci_dump_ed(ohci_softc_t *sc, ohci_soft
 	    __SHIFTOUT(flags, OHCI_ED_SPEED),
 	    __SHIFTOUT(flags, OHCI_ED_SKIP),
 	    OHCI_ED_GET_FORMAT(flags));
-	DPRINTF("    tailp=0x%08jx", (u_long)O32TOH(sed->ed.ed_tailp),
+	DPRINTF("    tailp=0x%08jx", (u_long)O32TOH(sed->ed->ed_tailp),
 	    0, 0, 0);
 	DPRINTF("    headp=0x%08jx nexted=0x%08jx halted=%jd carry=%jd",
-	    O32TOH(sed->ed.ed_headp), O32TOH(sed->ed.ed_nexted),
-	    !!(O32TOH(sed->ed.ed_headp) & OHCI_HALTED),
-	    !!(O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY));
+	    O32TOH(sed->ed->ed_headp), O32TOH(sed->ed->ed_nexted),
+	    !!(O32TOH(sed->ed->ed_headp) & OHCI_HALTED),
+	    !!(O32TOH(sed->ed->ed_headp) & OHCI_TOGGLECARRY));
 }
 #endif
 
@@ -2116,16 +2144,16 @@ ohci_open(struct usbd_pipe *pipe)
 			    OHCI_ED_SET_FORMAT(OHCI_ED_FORMAT_GEN) |
 			    OHCI_ED_SET_DIR(OHCI_ED_DIR_TD);
 		}
-		sed->ed.ed_flags = HTOO32(
+		sed->ed->ed_flags = HTOO32(
 			OHCI_ED_SET_FA(addr) |
 			OHCI_ED_SET_EN(UE_GET_ADDR(ed->bEndpointAddress)) |
 			(dev->ud_speed == USB_SPEED_LOW ? OHCI_ED_SPEED : 0) |
 			fmt |
 			OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize)));
-		sed->ed.ed_headp = HTOO32(tdphys |
+		sed->ed->ed_headp = HTOO32(tdphys |
 		    (pipe->up_endpoint->ue_toggle ? OHCI_TOGGLECARRY : 0));
-		sed->ed.ed_tailp = HTOO32(tdphys);
-		usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+		sed->ed->ed_tailp = HTOO32(tdphys);
+		usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 		switch (xfertype) {
@@ -2188,15 +2216,16 @@ ohci_close_pipe(struct usbd_pipe *pipe, 
 	KASSERT(mutex_owned(&sc->sc_lock));
 
 #ifdef DIAGNOSTIC
-	sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
-	if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
-	    (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) {
+	// XXXNH usb_sync
+	sed->ed->ed_flags |= HTOO32(OHCI_ED_SKIP);
+	if ((O32TOH(sed->ed->ed_tailp) & OHCI_HEADMASK) !=
+	    (O32TOH(sed->ed->ed_headp) & OHCI_HEADMASK)) {
 		ohci_soft_td_t *std;
-		std = ohci_hash_find_td(sc, O32TOH(sed->ed.ed_headp));
+		std = ohci_hash_find_td(sc, O32TOH(sed->ed->ed_headp));
 		printf("ohci_close_pipe: pipe not empty sed=%p hd=%#x "
 		       "tl=%#x pipe=%p, std=%p\n", sed,
-		       (int)O32TOH(sed->ed.ed_headp),
-		       (int)O32TOH(sed->ed.ed_tailp),
+		       (int)O32TOH(sed->ed->ed_headp),
+		       (int)O32TOH(sed->ed->ed_tailp),
 		       pipe, std);
 #ifdef OHCI_DEBUG
 		usbd_dump_pipe(&opipe->pipe);
@@ -2205,8 +2234,8 @@ ohci_close_pipe(struct usbd_pipe *pipe, 
 			ohci_dump_td(sc, std);
 #endif
 		usb_delay_ms(&sc->sc_bus, 2);
-		if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
-		    (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK))
+		if ((O32TOH(sed->ed->ed_tailp) & OHCI_HEADMASK) !=
+		    (O32TOH(sed->ed->ed_headp) & OHCI_HEADMASK))
 			printf("ohci_close_pipe: pipe still not empty\n");
 	}
 #endif
@@ -2214,7 +2243,7 @@ ohci_close_pipe(struct usbd_pipe *pipe, 
 	/* Make sure the host controller is not touching this ED */
 	usb_delay_ms(&sc->sc_bus, 1);
 	pipe->up_endpoint->ue_toggle =
-	    (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0;
+	    (O32TOH(sed->ed->ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0;
 	ohci_free_sed_locked(sc, opipe->sed);
 }
 
@@ -2266,15 +2295,15 @@ ohci_abortx(struct usbd_xfer *xfer)
 	 * waiting for the next start of frame (OHCI_SF)
 	 */
 	DPRINTFN(1, "stop ed=%#jx", (uintptr_t)sed, 0, 0, 0);
-	usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+	usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-	if (!(sed->ed.ed_flags & OHCI_HALTED)) {
+	if (!(sed->ed->ed_flags & OHCI_HALTED)) {
 		/* force hardware skip */
 		DPRINTFN(1, "pausing ed=%#jx", (uintptr_t)sed, 0, 0, 0);
-		sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
+		sed->ed->ed_flags |= HTOO32(OHCI_ED_SKIP);
 		usb_syncmem(&sed->dma,
 		    sed->offs + offsetof(ohci_ed_t, ed_flags),
-		    sizeof(sed->ed.ed_flags),
+		    sizeof(sed->ed->ed_flags),
 		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 		DPRINTFN(10, "SF %#jx xfer %#jx", (uintptr_t)sc,
@@ -2337,16 +2366,16 @@ ohci_abortx(struct usbd_xfer *xfer)
 #define OHCI_CC_ACCESSED_P(x)	\
     (((x) & OHCI_CC_NOT_ACCESSED_MASK) != OHCI_CC_NOT_ACCESSED)
 
-	headp = O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK;
+	headp = O32TOH(sed->ed->ed_headp) & OHCI_HEADMASK;
 	hit = 0;
 	for (; p->xfer == xfer; p = n) {
 		hit |= headp == p->physaddr;
 		n = p->nexttd;
 
 		usb_syncmem(&p->dma, p->offs + offsetof(ohci_td_t, td_flags),
-		    sizeof(p->td.td_flags),
+		    sizeof(p->td->td_flags),
 		    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-		int cc = OHCI_TD_GET_CC(O32TOH(p->td.td_flags));
+		int cc = OHCI_TD_GET_CC(O32TOH(p->td->td_flags));
 		if (!OHCI_CC_ACCESSED_P(cc)) {
 			ohci_hash_rem_td(sc, p);
 			continue;
@@ -2380,13 +2409,13 @@ ohci_abortx(struct usbd_xfer *xfer)
 	/* Zap headp register if hardware pointed inside the xfer. */
 	if (hit) {
 		DPRINTFN(1, "set hd=0x%08jx, tl=0x%08jx",  (int)p->physaddr,
-		    (int)O32TOH(sed->ed.ed_tailp), 0, 0);
+		    (int)O32TOH(sed->ed->ed_tailp), 0, 0);
 		/* unlink TDs, preserving toggle carry */
-		sed->ed.ed_headp = HTOO32(p->physaddr |
-		    (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY));
+		sed->ed->ed_headp = HTOO32(p->physaddr |
+		    (O32TOH(sed->ed->ed_headp) & OHCI_TOGGLECARRY));
 		usb_syncmem(&sed->dma,
 		    sed->offs + offsetof(ohci_ed_t, ed_headp),
-		    sizeof(sed->ed.ed_headp),
+		    sizeof(sed->ed->ed_headp),
 		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	} else {
 		DPRINTFN(1, "no hit", 0, 0, 0, 0);
@@ -2396,11 +2425,11 @@ ohci_abortx(struct usbd_xfer *xfer)
 	 * HC Step 4: Turn on hardware again.
 	 */
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
-	    sizeof(sed->ed.ed_flags),
+	    sizeof(sed->ed->ed_flags),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-	sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */
+	sed->ed->ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
-	    sizeof(sed->ed.ed_flags),
+	    sizeof(sed->ed->ed_flags),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 dying:
 	DPRINTFN(14, "end", 0, 0, 0, 0);
@@ -2808,13 +2837,13 @@ ohci_device_ctrl_start(struct usbd_xfer 
 	DPRINTFN(10, "xfer=%#jx new tail=%#jx held at %#jx", (uintptr_t)ox,
 	    (uintptr_t)tail, (uintptr_t)tail->held, 0);
 
-	KASSERTMSG(OHCI_ED_GET_FA(O32TOH(sed->ed.ed_flags)) == dev->ud_addr,
+	KASSERTMSG(OHCI_ED_GET_FA(O32TOH(sed->ed->ed_flags)) == dev->ud_addr,
 	    "address ED %" __PRIuBITS " pipe %d\n",
-	    OHCI_ED_GET_FA(O32TOH(sed->ed.ed_flags)), dev->ud_addr);
-	KASSERTMSG(OHCI_ED_GET_MAXP(O32TOH(sed->ed.ed_flags)) ==
+	    OHCI_ED_GET_FA(O32TOH(sed->ed->ed_flags)), dev->ud_addr);
+	KASSERTMSG(OHCI_ED_GET_MAXP(O32TOH(sed->ed->ed_flags)) ==
 	    UGETW(opipe->pipe.up_endpoint->ue_edesc->wMaxPacketSize),
 	    "MPL ED %" __PRIuBITS " pipe %d\n",
-	    OHCI_ED_GET_MAXP(O32TOH(sed->ed.ed_flags)),
+	    OHCI_ED_GET_MAXP(O32TOH(sed->ed->ed_flags)),
 	    UGETW(opipe->pipe.up_endpoint->ue_edesc->wMaxPacketSize));
 
 	/* next will point to data if len != 0 */
@@ -2828,21 +2857,21 @@ ohci_device_ctrl_start(struct usbd_xfer 
 		next = ox->ox_stds[0];
 		ohci_reset_std_chain(sc, xfer, len, isread, next, &end);
 
-		end->td.td_nexttd = HTOO32(stat->physaddr);
+		end->td->td_nexttd = HTOO32(stat->physaddr);
 		end->nexttd = stat;
 
-		usb_syncmem(&end->dma, end->offs, sizeof(end->td),
+		usb_syncmem(&end->dma, end->offs, sizeof(*end->td),
 		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 		usb_syncmem(&xfer->ux_dmabuf, 0, len,
 		    isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
 		std = ox->ox_stds[0];
 		/* Start toggle at 1 and then use the carried toggle. */
-		std->td.td_flags &= HTOO32(~OHCI_TD_TOGGLE_MASK);
-		std->td.td_flags |= HTOO32(OHCI_TD_SET_TOGGLE(OHCI_TD_TOGGLE_1));
+		std->td->td_flags &= HTOO32(~OHCI_TD_TOGGLE_MASK);
+		std->td->td_flags |= HTOO32(OHCI_TD_SET_TOGGLE(OHCI_TD_TOGGLE_1));
 		usb_syncmem(&std->dma,
 		    std->offs + offsetof(ohci_td_t, td_flags),
-		    sizeof(std->td.td_flags),
+		    sizeof(std->td->td_flags),
 		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	}
 
@@ -2855,15 +2884,15 @@ ohci_device_ctrl_start(struct usbd_xfer 
 	memcpy(KERNADDR(&opipe->ctrl.reqdma, 0), req, sizeof(*req));
 	usb_syncmem(&opipe->ctrl.reqdma, 0, sizeof(*req), BUS_DMASYNC_PREWRITE);
 
-	setup->td.td_flags = HTOO32(
+	setup->td->td_flags = HTOO32(
 	    OHCI_TD_SET_DP(OHCI_TD_DP_SETUP) |
 	    OHCI_TD_SET_CC(OHCI_TD_NOCC) |
 	    OHCI_TD_SET_TOGGLE(OHCI_TD_TOGGLE_0) |
 	    OHCI_TD_SET_DI(OHCI_TD_NOINTR)
 	    );
-	setup->td.td_cbp = HTOO32(DMAADDR(&opipe->ctrl.reqdma, 0));
-	setup->td.td_nexttd = HTOO32(next->physaddr);
-	setup->td.td_be = HTOO32(O32TOH(setup->td.td_cbp) + sizeof(*req) - 1);
+	setup->td->td_cbp = HTOO32(DMAADDR(&opipe->ctrl.reqdma, 0));
+	setup->td->td_nexttd = HTOO32(next->physaddr);
+	setup->td->td_be = HTOO32(O32TOH(setup->td->td_cbp) + sizeof(*req) - 1);
 	setup->nexttd = next;
 	setup->len = 0;
 	setup->xfer = xfer;
@@ -2871,32 +2900,32 @@ ohci_device_ctrl_start(struct usbd_xfer 
 	ohci_hash_add_td(sc, setup);
 
 	xfer->ux_hcpriv = setup;
-	usb_syncmem(&setup->dma, setup->offs, sizeof(setup->td),
+	usb_syncmem(&setup->dma, setup->offs, sizeof(*setup->td),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
-	stat->td.td_flags = HTOO32(
+	stat->td->td_flags = HTOO32(
 	    OHCI_TD_SET_DP(isread ? OHCI_TD_DP_OUT : OHCI_TD_DP_IN) |
 	    OHCI_TD_SET_CC(OHCI_TD_NOCC) |
 	    OHCI_TD_SET_TOGGLE(OHCI_TD_TOGGLE_1) |
 	    OHCI_TD_SET_DI(1)
 	    );
-	stat->td.td_cbp = 0;
-	stat->td.td_nexttd = HTOO32(tail->physaddr);
-	stat->td.td_be = 0;
+	stat->td->td_cbp = 0;
+	stat->td->td_nexttd = HTOO32(tail->physaddr);
+	stat->td->td_be = 0;
 	stat->nexttd = tail;
 	stat->flags = OHCI_CALL_DONE;
 	stat->len = 0;
 	stat->xfer = xfer;
 	ohci_hash_add_td(sc, stat);
 
-	usb_syncmem(&stat->dma, stat->offs, sizeof(stat->td),
+	usb_syncmem(&stat->dma, stat->offs, sizeof(*stat->td),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
-	memset(&tail->td, 0, sizeof(tail->td));
+	memset(tail->td, 0, sizeof(*tail->td));
 	tail->nexttd = NULL;
 	tail->xfer = NULL;
 
-	usb_syncmem(&tail->dma, tail->offs, sizeof(tail->td),
+	usb_syncmem(&tail->dma, tail->offs, sizeof(*tail->td),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 #ifdef OHCI_DEBUG
@@ -2909,10 +2938,10 @@ ohci_device_ctrl_start(struct usbd_xfer 
 #endif
 
 	/* Insert ED in schedule */
-	sed->ed.ed_tailp = HTOO32(tail->physaddr);
+	sed->ed->ed_tailp = HTOO32(tail->physaddr);
 	usb_syncmem(&sed->dma,
 	    sed->offs + offsetof(ohci_ed_t, ed_tailp),
-	    sizeof(sed->ed.ed_tailp),
+	    sizeof(sed->ed->ed_tailp),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
 	xfer->ux_status = USBD_IN_PROGRESS;
@@ -2963,13 +2992,13 @@ ohci_device_clear_toggle(struct usbd_pip
 	ohci_soft_ed_t *sed = opipe->sed;
 
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_headp),
-	    sizeof(sed->ed.ed_headp),
+	    sizeof(sed->ed->ed_headp),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 
-	opipe->sed->ed.ed_headp &= HTOO32(~OHCI_TOGGLECARRY);
+	opipe->sed->ed->ed_headp &= HTOO32(~OHCI_TOGGLECARRY);
 
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_headp),
-	    sizeof(sed->ed.ed_headp),
+	    sizeof(sed->ed->ed_headp),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 }
 
@@ -3080,13 +3109,13 @@ ohci_device_bulk_start(struct usbd_xfer 
 
 	/* point at sentinel */
 	tail = opipe->tail.td;
-	memset(&tail->td, 0, sizeof(tail->td));
+	memset(tail->td, 0, sizeof(*tail->td));
 	tail->held = &opipe->tail.td;
 	tail->nexttd = NULL;
 	tail->xfer = NULL;
 	DPRINTFN(10, "xfer=%#jx new tail=%#jx held at %#ux",
 	    (uintptr_t)ox, (uintptr_t)tail, (uintptr_t)tail->held, 0);
-	usb_syncmem(&tail->dma, tail->offs, sizeof(tail->td),
+	usb_syncmem(&tail->dma, tail->offs, sizeof(*tail->td),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	xfer->ux_hcpriv = data;
 
@@ -3095,20 +3124,20 @@ ohci_device_bulk_start(struct usbd_xfer 
 	KASSERT(opipe->tail.td == tail);
 
 	/* We want interrupt at the end of the transfer. */
-	last->td.td_flags &= HTOO32(~OHCI_TD_DI_MASK);
-	last->td.td_flags |= HTOO32(OHCI_TD_SET_DI(1));
-	last->td.td_nexttd = HTOO32(tail->physaddr);
+	last->td->td_flags &= HTOO32(~OHCI_TD_DI_MASK);
+	last->td->td_flags |= HTOO32(OHCI_TD_SET_DI(1));
+	last->td->td_nexttd = HTOO32(tail->physaddr);
 	last->nexttd = tail;
 	last->flags |= OHCI_CALL_DONE;
-	usb_syncmem(&last->dma, last->offs, sizeof(last->td),
+	usb_syncmem(&last->dma, last->offs, sizeof(*last->td),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	DPRINTFN(4, "ed_flags=0x%08jx td_flags=0x%08jx "
 		    "td_cbp=0x%08jx td_be=0x%08jx",
-		    (int)O32TOH(sed->ed.ed_flags),
-		    (int)O32TOH(data->td.td_flags),
-		    (int)O32TOH(data->td.td_cbp),
-		    (int)O32TOH(data->td.td_be));
+		    (int)O32TOH(sed->ed->ed_flags),
+		    (int)O32TOH(data->td->td_flags),
+		    (int)O32TOH(data->td->td_cbp),
+		    (int)O32TOH(data->td->td_be));
 
 #ifdef OHCI_DEBUG
 	DPRINTFN(5, "--- dump start ---", 0, 0, 0, 0);
@@ -3123,11 +3152,11 @@ ohci_device_bulk_start(struct usbd_xfer 
 	for (tdp = data; tdp != tail; tdp = tdp->nexttd) {
 		KASSERT(tdp->xfer == xfer);
 	}
-	usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+	usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-	sed->ed.ed_tailp = HTOO32(tail->physaddr);
-	sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP);
-	usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+	sed->ed->ed_tailp = HTOO32(tail->physaddr);
+	sed->ed->ed_flags &= HTOO32(~OHCI_ED_SKIP);
+	usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
 	xfer->ux_status = USBD_IN_PROGRESS;
@@ -3272,13 +3301,13 @@ ohci_device_intr_start(struct usbd_xfer 
 
 	/* point at sentinel */
 	tail = opipe->tail.td;
-	memset(&tail->td, 0, sizeof(tail->td));
+	memset(tail->td, 0, sizeof(*tail->td));
 	tail->held = &opipe->tail.td;
 	tail->nexttd = NULL;
 	tail->xfer = NULL;
 	DPRINTFN(10, "xfer=%#jx new tail=%#jx held at %#jx",
 	    (uintptr_t)ox, (uintptr_t)tail, (uintptr_t)tail->held, 0);
-	usb_syncmem(&tail->dma, tail->offs, sizeof(tail->td),
+	usb_syncmem(&tail->dma, tail->offs, sizeof(*tail->td),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	xfer->ux_hcpriv = data;
 
@@ -3287,13 +3316,13 @@ ohci_device_intr_start(struct usbd_xfer 
 	KASSERT(opipe->tail.td == tail);
 
 	/* We want interrupt at the end of the transfer. */
-	last->td.td_flags &= HTOO32(~OHCI_TD_DI_MASK);
-	last->td.td_flags |= HTOO32(OHCI_TD_SET_DI(1));
+	last->td->td_flags &= HTOO32(~OHCI_TD_DI_MASK);
+	last->td->td_flags |= HTOO32(OHCI_TD_SET_DI(1));
 
-	last->td.td_nexttd = HTOO32(tail->physaddr);
+	last->td->td_nexttd = HTOO32(tail->physaddr);
 	last->nexttd = tail;
 	last->flags |= OHCI_CALL_DONE;
-	usb_syncmem(&last->dma, last->offs, sizeof(last->td),
+	usb_syncmem(&last->dma, last->offs, sizeof(*last->td),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 #ifdef OHCI_DEBUG
@@ -3306,11 +3335,11 @@ ohci_device_intr_start(struct usbd_xfer 
 #endif
 
 	/* Insert ED in schedule */
-	usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+	usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-	sed->ed.ed_tailp = HTOO32(tail->physaddr);
-	sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP);
-	usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+	sed->ed->ed_tailp = HTOO32(tail->physaddr);
+	sed->ed->ed_flags &= HTOO32(~OHCI_ED_SKIP);
+	usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	xfer->ux_status = USBD_IN_PROGRESS;
@@ -3347,22 +3376,22 @@ ohci_device_intr_close(struct usbd_pipe 
 	DPRINTFN(1, "pipe=%#jx nslots=%jd pos=%jd", (uintptr_t)pipe, nslots,
 	    pos, 0);
 	usb_syncmem(&sed->dma, sed->offs,
-	    sizeof(sed->ed), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-	sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
+	    sizeof(*sed->ed), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+	sed->ed->ed_flags |= HTOO32(OHCI_ED_SKIP);
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
-	    sizeof(sed->ed.ed_flags),
+	    sizeof(sed->ed->ed_flags),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
-	if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
-	    (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK))
+	if ((O32TOH(sed->ed->ed_tailp) & OHCI_HEADMASK) !=
+	    (O32TOH(sed->ed->ed_headp) & OHCI_HEADMASK))
 		usb_delay_ms_locked(&sc->sc_bus, 2, &sc->sc_lock);
 
 	for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next)
 		continue;
 	KASSERT(p);
 	p->next = sed->next;
-	p->ed.ed_nexted = sed->ed.ed_nexted;
+	p->ed->ed_nexted = sed->ed->ed_nexted;
 	usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted),
-	    sizeof(p->ed.ed_nexted),
+	    sizeof(p->ed->ed_nexted),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	for (j = 0; j < nslots; j++)
@@ -3422,20 +3451,20 @@ ohci_device_setintr(ohci_softc_t *sc, st
 	hsed = sc->sc_eds[best];
 	sed->next = hsed->next;
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted),
-	    sizeof(sed->ed.ed_nexted),
+	    sizeof(sed->ed->ed_nexted),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-	sed->ed.ed_nexted = hsed->ed.ed_nexted;
+	sed->ed->ed_nexted = hsed->ed->ed_nexted;
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted),
-	    sizeof(sed->ed.ed_nexted),
+	    sizeof(sed->ed->ed_nexted),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	hsed->next = sed;
 	usb_syncmem(&hsed->dma, hsed->offs + offsetof(ohci_ed_t, ed_nexted),
-	    sizeof(hsed->ed.ed_nexted),
+	    sizeof(hsed->ed->ed_nexted),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-	hsed->ed.ed_nexted = HTOO32(sed->physaddr);
+	hsed->ed->ed_nexted = HTOO32(sed->physaddr);
 	usb_syncmem(&hsed->dma, hsed->offs + offsetof(ohci_ed_t, ed_nexted),
-	    sizeof(hsed->ed.ed_nexted),
+	    sizeof(hsed->ed->ed_nexted),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	mutex_exit(&sc->sc_lock);
 
@@ -3624,15 +3653,15 @@ ohci_device_isoc_enter(struct usbd_xfer 
 			KASSERT(j < ox->ox_nsitd);
 
 			/* Fill current ITD */
-			sitd->itd.itd_flags = HTOO32(
+			sitd->itd->itd_flags = HTOO32(
 			    OHCI_ITD_SET_CC(OHCI_ITD_NOCC) |
 			    OHCI_ITD_SET_SF(isoc->next) |
 			    OHCI_ITD_SET_DI(6) | /* delay intr a little */
 			    OHCI_ITD_SET_FC(ncur)
 			    );
-			sitd->itd.itd_bp0 = HTOO32(bp0);
-			sitd->itd.itd_nextitd = HTOO32(nsitd->physaddr);
-			sitd->itd.itd_be = HTOO32(end);
+			sitd->itd->itd_bp0 = HTOO32(bp0);
+			sitd->itd->itd_nextitd = HTOO32(nsitd->physaddr);
+			sitd->itd->itd_be = HTOO32(end);
 			sitd->nextitd = nsitd;
 			sitd->xfer = xfer;
 			sitd->flags = 0;
@@ -3640,7 +3669,7 @@ ohci_device_isoc_enter(struct usbd_xfer 
 			sitd->isdone = false;
 #endif
 			ohci_hash_add_itd(sc, sitd);
-			usb_syncmem(&sitd->dma, sitd->offs, sizeof(sitd->itd),
+			usb_syncmem(&sitd->dma, sitd->offs, sizeof(*sitd->itd),
 			    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 			sitd = nsitd;
@@ -3648,7 +3677,7 @@ ohci_device_isoc_enter(struct usbd_xfer 
 			bp0 = bp1 = OHCI_PAGE(buf);
 			ncur = 0;
 		}
-		sitd->itd.itd_offset[ncur] = HTOO16(OHCI_ITD_MK_OFFS(offs));
+		sitd->itd->itd_offset[ncur] = HTOO16(OHCI_ITD_MK_OFFS(offs));
 		end = nend;
 		offs = noffs;
 	}
@@ -3656,23 +3685,23 @@ ohci_device_isoc_enter(struct usbd_xfer 
 
 	/* point at sentinel */
 	tail = opipe->tail.itd;
-	memset(&tail->itd, 0, sizeof(tail->itd));
+	memset(tail->itd, 0, sizeof(*tail->itd));
 	tail->held = &opipe->tail.itd;
 	tail->nextitd = NULL;
 	tail->xfer = NULL;
-	usb_syncmem(&tail->dma, tail->offs, sizeof(tail->itd),
+	usb_syncmem(&tail->dma, tail->offs, sizeof(*tail->itd),
 	    BUS_DMASYNC_PREWRITE);
 
 	/* Fixup last used ITD */
-	sitd->itd.itd_flags = HTOO32(
+	sitd->itd->itd_flags = HTOO32(
 	    OHCI_ITD_SET_CC(OHCI_ITD_NOCC) |
 	    OHCI_ITD_SET_SF(isoc->next) |
 	    OHCI_ITD_SET_DI(0) |
 	    OHCI_ITD_SET_FC(ncur)
 	    );
-	sitd->itd.itd_bp0 = HTOO32(bp0);
-	sitd->itd.itd_nextitd = HTOO32(tail->physaddr);
-	sitd->itd.itd_be = HTOO32(end);
+	sitd->itd->itd_bp0 = HTOO32(bp0);
+	sitd->itd->itd_nextitd = HTOO32(tail->physaddr);
+	sitd->itd->itd_be = HTOO32(end);
 	sitd->nextitd = tail;
 	sitd->xfer = xfer;
 	sitd->flags = OHCI_CALL_DONE;
@@ -3680,7 +3709,7 @@ ohci_device_isoc_enter(struct usbd_xfer 
 	sitd->isdone = false;
 #endif
 	ohci_hash_add_itd(sc, sitd);
-	usb_syncmem(&sitd->dma, sitd->offs, sizeof(sitd->itd),
+	usb_syncmem(&sitd->dma, sitd->offs, sizeof(*sitd->itd),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	isoc->next = isoc->next + ncur;
@@ -3703,11 +3732,11 @@ ohci_device_isoc_enter(struct usbd_xfer 
 	}
 #endif
 
-	usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+	usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-	sed->ed.ed_tailp = HTOO32(tail->physaddr);
-	sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP);
-	usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+	sed->ed->ed_tailp = HTOO32(tail->physaddr);
+	sed->ed->ed_flags &= HTOO32(~OHCI_ED_SKIP);
+	usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 }
 
@@ -3735,11 +3764,11 @@ ohci_device_isoc_abort(struct usbd_xfer 
 	xfer->ux_status = USBD_CANCELLED;
 
 	sed = opipe->sed;
-	usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+	usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-	sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); /* force hardware skip */
+	sed->ed->ed_flags |= HTOO32(OHCI_ED_SKIP); /* force hardware skip */
 	usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
-	    sizeof(sed->ed.ed_flags),
+	    sizeof(sed->ed->ed_flags),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	sitd = xfer->ux_hcpriv;
@@ -3759,9 +3788,9 @@ ohci_device_isoc_abort(struct usbd_xfer 
 	/* Run callback. */
 	usb_transfer_complete(xfer);
 
-	sed->ed.ed_headp = HTOO32(sitd->physaddr); /* unlink TDs */
-	sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */
-	usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+	sed->ed->ed_headp = HTOO32(sitd->physaddr); /* unlink TDs */
+	sed->ed->ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */
+	usb_syncmem(&sed->dma, sed->offs, sizeof(*sed->ed),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
  done:

Index: src/sys/dev/usb/ohcireg.h
diff -u src/sys/dev/usb/ohcireg.h:1.28 src/sys/dev/usb/ohcireg.h:1.29
--- src/sys/dev/usb/ohcireg.h:1.28	Wed Jun  3 15:38:02 2020
+++ src/sys/dev/usb/ohcireg.h	Sun Sep 22 14:05:47 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: ohcireg.h,v 1.28 2020/06/03 15:38:02 skrll Exp $	*/
+/*	$NetBSD: ohcireg.h,v 1.29 2024/09/22 14:05:47 jmcneill Exp $	*/
 /*	$FreeBSD: src/sys/dev/usb/ohcireg.h,v 1.8 1999/11/17 22:33:40 n_hibma Exp $	*/
 
 /*
@@ -142,7 +142,7 @@ typedef uint32_t ohci_physaddr_t;
 #define OHCI_NO_INTRS 32
 struct ohci_hcca {
 	volatile ohci_physaddr_t	hcca_interrupt_table[OHCI_NO_INTRS];
-	volatile uint32_t	hcca_frame_number;
+	volatile uint32_t		hcca_frame_number;
 	volatile ohci_physaddr_t	hcca_done_head;
 #define OHCI_DONE_INTRS 1
 };
@@ -186,6 +186,10 @@ typedef struct {
 } ohci_ed_t;
 /* #define OHCI_ED_SIZE 16 */
 #define OHCI_ED_ALIGN 16
+#define OHCI_ED_ALLOC_ALIGN	MAX(OHCI_ED_ALIGN, CACHE_LINE_SIZE)
+#define OHCI_ED_SIZE		(roundup(sizeof(ohci_ed_t), OHCI_ED_ALLOC_ALIGN))
+#define OHCI_ED_CHUNK (PAGE_SIZE / OHCI_ED_SIZE)
+
 
 typedef struct {
 	volatile uint32_t	td_flags;
@@ -220,6 +224,10 @@ typedef struct {
 } ohci_td_t;
 /* #define OHCI_TD_SIZE 16 */
 #define OHCI_TD_ALIGN 16
+#define OHCI_TD_ALLOC_ALIGN	MAX(OHCI_TD_ALIGN, CACHE_LINE_SIZE)
+#define OHCI_TD_SIZE		(roundup(sizeof(ohci_td_t), OHCI_TD_ALLOC_ALIGN))
+#define OHCI_TD_CHUNK (PAGE_SIZE / OHCI_TD_SIZE)
+
 
 #define OHCI_ITD_NOFFSET 8
 typedef struct {
@@ -252,6 +260,9 @@ typedef struct {
 } ohci_itd_t;
 /* #define OHCI_ITD_SIZE 32 */
 #define OHCI_ITD_ALIGN 32
+#define OHCI_ITD_ALLOC_ALIGN	MAX(OHCI_ITD_ALIGN, CACHE_LINE_SIZE)
+#define OHCI_ITD_SIZE		(roundup(sizeof(ohci_itd_t), OHCI_ITD_ALLOC_ALIGN))
+#define OHCI_ITD_CHUNK		(PAGE_SIZE / OHCI_ITD_SIZE)
 
 
 #define OHCI_CC_NO_ERROR		0

Index: src/sys/dev/usb/ohcivar.h
diff -u src/sys/dev/usb/ohcivar.h:1.62 src/sys/dev/usb/ohcivar.h:1.63
--- src/sys/dev/usb/ohcivar.h:1.62	Wed Dec  9 07:10:01 2020
+++ src/sys/dev/usb/ohcivar.h	Sun Sep 22 14:05:47 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: ohcivar.h,v 1.62 2020/12/09 07:10:01 skrll Exp $	*/
+/*	$NetBSD: ohcivar.h,v 1.63 2024/09/22 14:05:47 jmcneill Exp $	*/
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -36,18 +36,16 @@
 #include <sys/pool.h>
 
 typedef struct ohci_soft_ed {
-	ohci_ed_t ed;
+	ohci_ed_t *ed;
 	struct ohci_soft_ed *next;
 	ohci_physaddr_t physaddr;
 	usb_dma_t dma;
 	int offs;
 } ohci_soft_ed_t;
-#define OHCI_SED_SIZE (roundup(sizeof(struct ohci_soft_ed), OHCI_ED_ALIGN))
-#define OHCI_SED_CHUNK 128
 
 
 typedef struct ohci_soft_td {
-	ohci_td_t td;
+	ohci_td_t *td;
 	struct ohci_soft_td *nexttd;	/* mirrors nexttd in TD */
 	struct ohci_soft_td *dnext;	/* next in done list */
 	struct ohci_soft_td **held;	/* where the ref to this std is held */
@@ -61,12 +59,12 @@ typedef struct ohci_soft_td {
 #define OHCI_CALL_DONE	0x0001
 #define OHCI_ADD_LEN	0x0002
 } ohci_soft_td_t;
-#define OHCI_STD_SIZE (roundup(sizeof(struct ohci_soft_td), OHCI_TD_ALIGN))
-#define OHCI_STD_CHUNK 128
+// #define OHCI_STD_SIZE (roundup(sizeof(struct ohci_soft_td), OHCI_TD_ALIGN))
+// #define OHCI_STD_CHUNK 128
 
 
 typedef struct ohci_soft_itd {
-	ohci_itd_t itd;
+	ohci_itd_t *itd;
 	struct ohci_soft_itd *nextitd;	/* mirrors nexttd in ITD */
 	struct ohci_soft_itd *dnext;	/* next in done list */
 	struct ohci_soft_itd **held;	/* where the ref to this sitd is held */
@@ -78,8 +76,8 @@ typedef struct ohci_soft_itd {
 	uint16_t flags;
 	bool isdone;	/* used only when DIAGNOSTIC is defined */
 } ohci_soft_itd_t;
-#define OHCI_SITD_SIZE (roundup(sizeof(struct ohci_soft_itd), OHCI_ITD_ALIGN))
-#define OHCI_SITD_CHUNK 64
+// #define OHCI_SITD_SIZE (roundup(sizeof(struct ohci_soft_itd), OHCI_ITD_ALIGN))
+// #define OHCI_SITD_CHUNK 64
 
 
 #define OHCI_NO_EDS (2*OHCI_NO_INTRS-1)

Reply via email to