jcs's openbsd hax
openbsd

Relax DMA restrictions on ehci(4) and xhci(4) controllers that can do 64-bit DMA.

ok mpi@, mlarkin@

kettenis 98dddc57 a006a8cd

+24 -23
+2 -1
sys/dev/usb/ehci.c
··· 1 - /* $OpenBSD: ehci.c,v 1.220 2024/05/23 03:21:08 jsg Exp $ */ 1 + /* $OpenBSD: ehci.c,v 1.221 2024/10/08 19:42:31 kettenis Exp $ */ 2 2 /* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */ 3 3 4 4 /* ··· 317 317 sc->sc_noport = EHCI_HCS_N_PORTS(sparams); 318 318 cparams = EREAD4(sc, EHCI_HCCPARAMS); 319 319 DPRINTF(("ehci_init: cparams=0x%x\n", cparams)); 320 + sc->sc_bus.dmaflags = EHCI_HCC_64BIT(cparams) ? BUS_DMA_64BIT : 0; 320 321 321 322 /* MUST clear segment register if 64 bit capable. */ 322 323 if (EHCI_HCC_64BIT(cparams))
+14 -16
sys/dev/usb/usb_mem.c
··· 1 - /* $OpenBSD: usb_mem.c,v 1.35 2024/05/23 03:21:09 jsg Exp $ */ 1 + /* $OpenBSD: usb_mem.c,v 1.36 2024/10/08 19:42:31 kettenis Exp $ */ 2 2 /* $NetBSD: usb_mem.c,v 1.26 2003/02/01 06:23:40 thorpej Exp $ */ 3 3 4 4 /* ··· 82 82 83 83 usbd_status 84 84 usb_block_allocmem(bus_dma_tag_t tag, size_t size, size_t align, 85 - struct usb_dma_block **dmap, int coherent) 85 + struct usb_dma_block **dmap, int flags) 86 86 { 87 87 int error; 88 88 struct usb_dma_block *p; ··· 95 95 /* First check the free list. */ 96 96 for (p = LIST_FIRST(&usb_blk_freelist); p; p = LIST_NEXT(p, next)) { 97 97 if (p->tag == tag && p->size >= size && p->align >= align && 98 - p->coherent == coherent) { 98 + p->flags == flags) { 99 99 LIST_REMOVE(p, next); 100 100 usb_blk_nfree--; 101 101 splx(s); ··· 115 115 p->tag = tag; 116 116 p->size = size; 117 117 p->align = align; 118 - p->coherent = coherent; 118 + p->flags = flags; 119 119 error = bus_dmamem_alloc(tag, p->size, align, 0, 120 - p->segs, nitems(p->segs), 121 - &p->nsegs, BUS_DMA_NOWAIT); 120 + p->segs, nitems(p->segs), &p->nsegs, 121 + BUS_DMA_NOWAIT | (flags & BUS_DMA_64BIT)); 122 122 if (error) 123 123 goto free0; 124 124 125 125 error = bus_dmamem_map(tag, p->segs, p->nsegs, p->size, 126 - &p->kaddr, BUS_DMA_NOWAIT | (coherent ? 127 - BUS_DMA_COHERENT : 0)); 126 + &p->kaddr, BUS_DMA_NOWAIT | (flags & BUS_DMA_COHERENT)); 128 127 if (error) 129 128 goto free1; 130 129 131 130 error = bus_dmamap_create(tag, p->size, 1, p->size, 132 - 0, BUS_DMA_NOWAIT, &p->map); 131 + 0, BUS_DMA_NOWAIT | (flags & BUS_DMA_64BIT), &p->map); 133 132 if (error) 134 133 goto unmap; 135 134 136 135 error = bus_dmamap_load(tag, p->map, p->kaddr, p->size, NULL, 137 - BUS_DMA_NOWAIT); 136 + BUS_DMA_NOWAIT); 138 137 if (error) 139 138 goto destroy; 140 139 ··· 189 188 usbd_status err; 190 189 struct usb_frag_dma *f; 191 190 struct usb_dma_block *b; 192 - int coherent; 193 191 int i; 194 192 int s; 195 193 196 - coherent = !!(flags & USB_DMA_COHERENT); 194 + flags = (flags & USB_DMA_COHERENT) ? BUS_DMA_COHERENT : 0; 195 + flags |= bus->dmaflags; 197 196 198 197 /* If the request is large then just use a full block. */ 199 198 if (size > USB_MEM_SMALL || align > USB_MEM_SMALL) { 200 199 DPRINTFN(1, ("%s: large alloc %d\n", __func__, (int)size)); 201 200 size = (size + USB_MEM_BLOCK - 1) & ~(USB_MEM_BLOCK - 1); 202 - err = usb_block_allocmem(tag, size, align, &p->block, 203 - coherent); 201 + err = usb_block_allocmem(tag, size, align, &p->block, flags); 204 202 if (!err) { 205 203 p->block->frags = NULL; 206 204 p->offs = 0; ··· 211 209 s = splusb(); 212 210 /* Check for free fragments. */ 213 211 for (f = LIST_FIRST(&usb_frag_freelist); f; f = LIST_NEXT(f, next)) 214 - if (f->block->tag == tag && f->block->coherent == coherent) 212 + if (f->block->tag == tag && f->block->flags == flags) 215 213 break; 216 214 if (f == NULL) { 217 215 DPRINTFN(1, ("usb_allocmem: adding fragments\n")); 218 216 err = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL, &b, 219 - coherent); 217 + flags); 220 218 if (err) { 221 219 splx(s); 222 220 return (err);
+2 -2
sys/dev/usb/usb_mem.h
··· 1 - /* $OpenBSD: usb_mem.h,v 1.17 2020/03/21 12:08:31 patrick Exp $ */ 1 + /* $OpenBSD: usb_mem.h,v 1.18 2024/10/08 19:42:31 kettenis Exp $ */ 2 2 /* $NetBSD: usb_mem.h,v 1.20 2003/05/03 18:11:42 wiz Exp $ */ 3 3 /* $FreeBSD: src/sys/dev/usb/usb_mem.h,v 1.9 1999/11/17 22:33:47 n_hibma Exp $ */ 4 4 ··· 40 40 caddr_t kaddr; 41 41 bus_dma_segment_t segs[1]; 42 42 int nsegs; 43 - int coherent; 43 + int flags; 44 44 size_t size; 45 45 size_t align; 46 46 struct usb_frag_dma *frags;
+2 -1
sys/dev/usb/usbdivar.h
··· 1 - /* $OpenBSD: usbdivar.h,v 1.83 2022/09/04 08:42:39 mglocker Exp $ */ 1 + /* $OpenBSD: usbdivar.h,v 1.84 2024/10/08 19:42:31 kettenis Exp $ */ 2 2 /* $NetBSD: usbdivar.h,v 1.70 2002/07/11 21:14:36 augustss Exp $ */ 3 3 /* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.11 1999/11/17 22:33:51 n_hibma Exp $ */ 4 4 ··· 135 135 #define USBREV_STR { "unknown", "pre 1.0", "1.0", "1.1", "2.0", "3.0" } 136 136 void *soft; /* soft interrupt cookie */ 137 137 bus_dma_tag_t dmatag; /* DMA tag */ 138 + int dmaflags; 138 139 }; 139 140 140 141 struct usbd_device {
+4 -3
sys/dev/usb/xhci.c
··· 1 - /* $OpenBSD: xhci.c,v 1.134 2024/08/17 01:55:03 jsg Exp $ */ 1 + /* $OpenBSD: xhci.c,v 1.135 2024/10/08 19:42:31 kettenis Exp $ */ 2 2 3 3 /* 4 4 * Copyright (c) 2014-2015 Martin Pieuchot ··· 238 238 dma->size = size; 239 239 240 240 error = bus_dmamap_create(dma->tag, size, 1, size, boundary, 241 - BUS_DMA_NOWAIT, &dma->map); 241 + BUS_DMA_NOWAIT | bus->dmaflags, &dma->map); 242 242 if (error != 0) 243 243 return (error); 244 244 245 245 error = bus_dmamem_alloc(dma->tag, size, alignment, boundary, &dma->seg, 246 - 1, &dma->nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO); 246 + 1, &dma->nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO | bus->dmaflags); 247 247 if (error != 0) 248 248 goto destroy; 249 249 ··· 329 329 330 330 hcr = XREAD4(sc, XHCI_HCCPARAMS); 331 331 sc->sc_ctxsize = XHCI_HCC_CSZ(hcr) ? 64 : 32; 332 + sc->sc_bus.dmaflags |= XHCI_HCC_AC64(hcr) ? BUS_DMA_64BIT : 0; 332 333 DPRINTF(("%s: %d bytes context\n", DEVNAME(sc), sc->sc_ctxsize)); 333 334 334 335 #ifdef XHCI_DEBUG